1 /*   dlgutil2.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:  dlgutil2.c
27 *
28 * Author:  Jonathan Kans
29 *
30 * Version Creation Date:   1/22/95
31 *
32 * $Revision: 6.246 $
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 <utilpub.h>
53 #include <objfeat.h>
54 #include <objseq.h>
55 #include <toasn3.h>
56 #include <explore.h>
57 #include <findrepl.h>
58 #include <valid.h>
59 #include <salparam.h>
60 #ifdef WIN_MOTIF
61 #include <netscape.h>
62 #endif
63 #define NLM_GENERATED_CODE_PROTO
64 #include <objmacro.h>
65 #include <macroapi.h>
66 
67 typedef struct datepage {
68   DIALOG_MESSAGE_BLOCK
69   TexT          year;
70   PopuP         year_popup;
71   Int4          start_year;
72   Int4          num_years;
73   PopuP         month;
74   TexT          day;
75 } DatePage, PNTR DatePagePtr;
76 
SaveStringFromTextAndStripNewlines(TexT t)77 extern CharPtr SaveStringFromTextAndStripNewlines (TexT t)
78 
79 {
80   Char     ch;
81   size_t   len;
82   CharPtr  ptr;
83   CharPtr  str;
84 
85   len = TextLength (t);
86   if (len > 0) {
87     str = MemNew (len + 1);
88     if (str != NULL) {
89       GetTitle (t, str, len + 1);
90       ptr = str;
91       ch = *ptr;
92       while (ch != '\0') {
93         if (ch < ' ') {
94           *ptr = ' ';
95         }
96         ptr++;
97         ch = *ptr;
98       }
99       TrimSpacesAroundString (str);
100       if (StringHasNoText (str)) {
101         str = MemFree (str);
102       }
103       return str;
104     } else {
105       return NULL;
106     }
107   } else {
108     return NULL;
109   }
110 }
111 
112 
StripNewlines(CharPtr str)113 extern CharPtr StripNewlines (CharPtr str)
114 
115 {
116   Char     ch;
117   size_t   len;
118   CharPtr  ptr;
119 
120   if (str == NULL) return str;
121   len = StringLen (str);
122   if (len > 0) {
123     ptr = str;
124     ch = *ptr;
125     while (ch != '\0') {
126       if (ch < ' ') {
127         *ptr = ' ';
128       }
129       ptr++;
130       ch = *ptr;
131     }
132     TrimSpacesAroundString (str);
133     if (StringHasNoText (str)) {
134       str = MemFree (str);
135     }
136   } else {
137     str = MemFree (str);
138   }
139   return str;
140 }
141 
142 
NewlinesToTildes(CharPtr str)143 extern void NewlinesToTildes (CharPtr str)
144 
145 {
146   Uchar    ch;
147   CharPtr  ptr;
148 
149   if (StringHasNoText (str)) return;
150   ptr = str;
151   ch = *ptr;
152   while (ch != '\0') {
153     if (ch < ' ') {
154       *ptr = '~';
155     }
156     ptr++;
157     ch = *ptr;
158   }
159 }
160 
161 
DatePtrToDatePage(DialoG d,Pointer data)162 static void DatePtrToDatePage (DialoG d, Pointer data)
163 
164 {
165   DatePtr      dp;
166   DatePagePtr  dpp;
167   Int2         day;
168   Char         str [32];
169   Int2         year, val;
170 
171 
172   dpp = (DatePagePtr) GetObjectExtra (d);
173   dp = (DatePtr) data;
174   if (dpp != NULL) {
175     if (dp == NULL || dp->data[0] != 1) {
176       SafeSetValue (dpp->month, 1);
177       SafeSetTitle (dpp->day, "");
178       SafeSetTitle (dpp->year, "");
179       SafeSetValue (dpp->year_popup, 1);
180     } else {
181       /* set month */
182       SetEnumPopup (dpp->month, months_alist, (UIEnum) dp->data [2]);
183       /* set day */
184       day = (Int2) dp->data [3];
185       if (day > 0 && day <= 31) {
186         sprintf (str, "%d", (int) day);
187         SafeSetTitle (dpp->day, str);
188       } else {
189         SafeSetTitle (dpp->day, "");
190       }
191       /* set year */
192       year = (Int2) dp->data [1];
193       if (year > 0) {
194         if (dpp->year_popup == NULL) {
195           sprintf (str, "%d", (int) (year + 1900));
196           SafeSetTitle (dpp->year, str);
197         } else {
198           val = year + 1900 - dpp->start_year + 1;
199           if (val < 1 || val >= dpp->num_years) {
200             sprintf (str, "%d", (int) (year + 1900));
201             SafeSetTitle (dpp->year, str);
202             dpp->year_popup = NULL;
203             Show (dpp->year);
204           } else {
205             SetValue (dpp->year_popup, val);
206           }
207         }
208       } else {
209         if (dpp->year_popup == NULL) {
210           SafeSetTitle (dpp->year, "");
211         } else {
212           SetValue (dpp->year_popup, 1);
213         }
214       }
215     }
216   }
217 }
218 
DatePageToDatePtr(DialoG d)219 static Pointer DatePageToDatePtr (DialoG d)
220 
221 {
222   DatePtr      dp;
223   DatePagePtr  dpp;
224   Int2         day;
225   UIEnum       month;
226   Char         str [32];
227   Int2         year = 0;
228 
229   dp = NULL;
230   dpp = (DatePagePtr) GetObjectExtra (d);
231   if (dpp != NULL) {
232     dp = DateNew ();
233     if (dp != NULL) {
234       dp->data [0] = 1;
235       /* get year value */
236       if (dpp->year_popup != NULL) {
237         year = GetValue (dpp->year_popup);
238         if (year > 0) {
239           year += dpp->start_year - 1;
240         } else {
241           dp = DateFree (dp);
242           return NULL;
243         }
244       } else {
245         GetTitle (dpp->year, str, sizeof (str));
246         if (! StringHasNoText (str)) {
247           StrToInt (str, &year);
248         }
249       }
250       if (year >= 1900) {
251         dp->data [1] = (Uint1) (year - 1900);
252       } else {
253         dp = DateFree (dp);
254         return dp;
255       }
256       /* get month value */
257       if (GetEnumPopup (dpp->month, months_alist, &month)) {
258         dp->data [2] = (Uint1) month;
259       } else {
260         dp = DateFree (dp);
261         return dp;
262       }
263       /* get day value */
264       GetTitle (dpp->day, str, sizeof (str));
265       StrToInt (str, &day);
266       dp->data [3] = (Uint1) day;
267     }
268   }
269   return (Pointer) dp;
270 }
271 
CreateDateDialogEx(GrouP prnt,CharPtr title,Int4 start_year,Int4 num_years)272 extern DialoG CreateDateDialogEx (GrouP prnt, CharPtr title, Int4 start_year, Int4 num_years)
273 
274 {
275   DatePagePtr  dpp;
276   GrouP        f;
277   GrouP        m;
278   GrouP        p;
279   GrouP        s;
280   GrouP        year_grp;
281   Char         year_buf[15];
282   Int4         i;
283 
284   p = HiddenGroup (prnt, 1, 0, NULL);
285   SetGroupSpacing (p, 10, 10);
286 
287   dpp = (DatePagePtr) MemNew (sizeof (DatePage));
288   if (dpp) {
289 
290     SetObjectExtra (p, dpp, StdCleanupExtraProc);
291     dpp->dialog = (DialoG) p;
292     dpp->todialog = DatePtrToDatePage;
293     dpp->fromdialog = DatePageToDatePtr;
294     dpp->testdialog = NULL;
295 
296     dpp->start_year = start_year;
297     dpp->num_years = num_years;
298 
299     if (title != NULL && title [0] != '\0') {
300       s = NormalGroup (p, 0, -2, title, systemFont, NULL);
301     } else {
302       s = HiddenGroup (p, 0, -2, NULL);
303     }
304     m = HiddenGroup (s, -1, 0, NULL);
305     /*
306     SetGroupSpacing (m, 10, 10);
307     */
308 
309     f = HiddenGroup (m, -6, 0, NULL);
310     StaticPrompt (f, "Month", 0, popupMenuHeight, programFont, 'l');
311     dpp->month = PopupList (f, TRUE, NULL);
312     InitEnumPopup (dpp->month, months_alist, NULL);
313     SetValue (dpp->month, 1);
314     StaticPrompt (f, "Day", 0, dialogTextHeight, programFont, 'l');
315     dpp->day = DialogText (f, "", 4, NULL);
316     StaticPrompt (f, "Year", 0, dialogTextHeight, programFont, 'l');
317     year_grp = HiddenGroup (f, 0, 0, NULL);
318     if (start_year > 0 && num_years > -1) {
319       dpp->year_popup = PopupList (year_grp, TRUE, NULL);
320       for (i = 0; i < num_years; i++) {
321         sprintf (year_buf, "%d", start_year + i);
322         PopupItem (dpp->year_popup, year_buf);
323       }
324     }
325     dpp->year = DialogText (year_grp, "", 6, NULL);
326     if (dpp->year_popup != NULL) {
327       SafeHide (dpp->year);
328     }
329     AlignObjects (ALIGN_CENTER, (HANDLE)dpp->year, (HANDLE)dpp->year_popup, NULL);
330   }
331 
332   return (DialoG) p;
333 }
334 
335 
CreateDateDialog(GrouP prnt,CharPtr title)336 extern DialoG CreateDateDialog (GrouP prnt, CharPtr title)
337 
338 {
339   return CreateDateDialogEx (prnt, title, -1, 0);
340 }
341 
342 
343 typedef struct featcit {
344   DIALOG_MESSAGE_BLOCK
345   DoC         citdoc;
346   ValNodePtr  pubset;
347 } FeatCitPage, PNTR FeatCitPagePtr;
348 
349 static ParData cofParFmt = {FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0};
350 static ColData cofColFmt = {0, 0, 0, 0, NULL, 'l', TRUE, FALSE, FALSE, FALSE, TRUE};
351 
352 static ParData cofeParFmt = {TRUE, FALSE, FALSE, FALSE, FALSE, 0, 0};
353 static ColData cofeColFmt = {0, 0, 0, 0, NULL, 'l', TRUE, FALSE, FALSE, FALSE, TRUE};
354 
355 static Uint1 diamondSym [] = {
356   0x00, 0x10, 0x38, 0x7C, 0x38, 0x10, 0x00, 0x00
357 };
358 
DrawCitOnFeat(DoC d,RectPtr r,Int2 item,Int2 firstLine)359 static void DrawCitOnFeat (DoC d, RectPtr r, Int2 item, Int2 firstLine)
360 
361 {
362   Int2  lineHeight;
363   RecT  rct;
364 
365   if (d != NULL && r != NULL && item > 0 && firstLine == 0) {
366     if (item == 1) return; /* citonfeattxt or citonfeathdr explanatory text */
367     GetItemParams (d, item, NULL, NULL, NULL, &lineHeight, NULL);
368     rct = *r;
369     rct.left += 1;
370     rct.right = rct.left + 7;
371     rct.top += (lineHeight - 7) / 2;
372     rct.bottom = rct.top + 7;
373     CopyBits (&rct, diamondSym);
374     /*
375     x = r->left + 1;
376     y = r->top + lineHeight / 2;
377     MoveTo (x, y);
378     LineTo (x + 5, y);
379     */
380   }
381 }
382 
CompareStrings(VoidPtr ptr1,VoidPtr ptr2)383 static int LIBCALLBACK CompareStrings (VoidPtr ptr1, VoidPtr ptr2)
384 
385 {
386   CharPtr  str1;
387   CharPtr  str2;
388 
389   if (ptr1 != NULL && ptr2 != NULL) {
390     str1 = *((CharPtr PNTR) ptr1);
391     str2 = *((CharPtr PNTR) ptr2);
392     if (str1 != NULL && str2 != NULL) {
393       return StringICmp (str1, str2);
394     } else {
395       return 0;
396     }
397   } else {
398     return 0;
399   }
400 }
401 
402 static CharPtr citonfeattxt =
403 "Press 'Edit Citations' to attach publications to this feature. \
404 Publications must first be added to the record. For biological \
405 justification, and not to credit the sequencer, create publication \
406 with the 'Cites a feature on the sequence' scope.\n";
407 
408 static CharPtr citonfeathdr =
409 "Press 'Edit Citations' to change publications.\n\n";
410 
PubsetPtrToFeatCitPage(DialoG d,Pointer data)411 static void PubsetPtrToFeatCitPage (DialoG d, Pointer data)
412 
413 {
414   Int2            count;
415   FeatCitPagePtr  fpp;
416   Int2            i;
417   Char            label [128];
418   ObjMgrPtr       omp;
419   ObjMgrTypePtr   omtp;
420   ValNodePtr      ppr;
421   ValNodePtr      psp;
422   RecT            r;
423   CharPtr         PNTR strs;
424 
425   fpp = (FeatCitPagePtr) GetObjectExtra (d);
426   psp = (ValNodePtr) data;
427   if (fpp != NULL) {
428     Reset (fpp->citdoc);
429     fpp->pubset = PubSetFree (fpp->pubset);
430     fpp->pubset = AsnIoMemCopy (data,
431                                 (AsnReadFunc) PubSetAsnRead,
432                                 (AsnWriteFunc) PubSetAsnWrite);
433     SetDocAutoAdjust (fpp->citdoc, FALSE);
434     ObjectRect (fpp->citdoc, &r);
435     InsetRect (&r, 4, 4);
436     cofColFmt.pixWidth = r.right - r.left;
437     cofColFmt.pixInset = 10;
438     omp = ObjMgrGet ();
439     if (omp == NULL) return;
440     omtp = ObjMgrTypeFind (omp, OBJ_SEQFEAT_CIT, NULL, NULL);
441     if (omtp == NULL || omtp->labelfunc == NULL) return;
442     if (psp != NULL && psp->data.ptrvalue != NULL) {
443       count = 0;
444       for (ppr = psp->data.ptrvalue; ppr != NULL; ppr = ppr->next) {
445         count++;
446       }
447       if (count > 0) {
448         strs = MemNew (sizeof (CharPtr) * (size_t) (count + 1));
449         if (strs != NULL) {
450           i = 0;
451           for (ppr = psp->data.ptrvalue; ppr != NULL; ppr = ppr->next) {
452             (*(omtp->labelfunc)) (ppr, label, 127, OM_LABEL_CONTENT);
453             strs [i] = StringSave (label);
454             i++;
455           }
456           HeapSort (strs, count, sizeof (CharPtr), CompareStrings);
457           AppendText (fpp->citdoc, citonfeathdr, &cofParFmt, NULL, programFont);
458           for (i = 0; i < count; i++) {
459             AppendText (fpp->citdoc, strs [i],
460                         &cofParFmt, &cofColFmt, programFont);
461           }
462           for (i = 0; i < count; i++) {
463             strs [i] = MemFree (strs [i]);
464           }
465           MemFree (strs);
466         } else {
467           AppendText (fpp->citdoc, citonfeattxt, &cofParFmt, NULL, programFont);
468         }
469       }
470     } else {
471       AppendText (fpp->citdoc, citonfeattxt, &cofParFmt, NULL, programFont);
472     }
473     SetDocShade (fpp->citdoc, DrawCitOnFeat, NULL, NULL, NULL);
474     UpdateDocument (fpp->citdoc, 0, 0);
475   }
476 }
477 
FeatCitPageToPubsetPtr(DialoG d)478 static Pointer FeatCitPageToPubsetPtr (DialoG d)
479 
480 {
481   FeatCitPagePtr  fpp;
482   ValNodePtr      psp;
483 
484   psp = NULL;
485   fpp = (FeatCitPagePtr) GetObjectExtra (d);
486   if (fpp != NULL) {
487     psp = AsnIoMemCopy (fpp->pubset,
488                         (AsnReadFunc) PubSetAsnRead,
489                         (AsnWriteFunc) PubSetAsnWrite);
490   }
491   return (Pointer) psp;
492 }
493 
CleanupCitOnFeatProc(GraphiC g,VoidPtr data)494 static void CleanupCitOnFeatProc (GraphiC g, VoidPtr data)
495 
496 {
497   FeatCitPagePtr  fpp;
498 
499   fpp = (FeatCitPagePtr) data;
500   if (fpp != NULL) {
501     PubSetFree (fpp->pubset);
502   }
503   MemFree (data);
504 }
505 
CreateCitOnFeatDialog(GrouP h,CharPtr title)506 static DialoG CreateCitOnFeatDialog (GrouP h, CharPtr title)
507 
508 {
509   FeatCitPagePtr  fpp;
510   Int2            lineHeight;
511   GrouP           m;
512   GrouP           p;
513   GrouP           s;
514 
515   p = HiddenGroup (h, 1, 0, NULL);
516   SetGroupSpacing (p, 10, 10);
517 
518   fpp = (FeatCitPagePtr) MemNew (sizeof (FeatCitPage));
519   if (fpp != NULL) {
520 
521     SetObjectExtra (p, fpp, CleanupCitOnFeatProc);
522     fpp->dialog = (DialoG) p;
523     fpp->todialog = PubsetPtrToFeatCitPage;
524     fpp->fromdialog = FeatCitPageToPubsetPtr;
525     fpp->testdialog = NULL;
526 
527     if (title != NULL && title [0] != '\0') {
528       s = NormalGroup (p, 0, -2, title, systemFont, NULL);
529     } else {
530       s = HiddenGroup (p, 0, -2, NULL);
531     }
532     m = HiddenGroup (s, -1, 0, NULL);
533     /*
534     SetGroupSpacing (m, 10, 10);
535     */
536 
537     SelectFont (programFont);
538     lineHeight = LineHeight ();
539     SelectFont (systemFont);
540     cofParFmt.minHeight = lineHeight + 2;
541     StaticPrompt (m, "Citations on Feature", 25 * stdCharWidth, 0, programFont, 'c');
542     fpp->citdoc = DocumentPanel (m, 25 * stdCharWidth, 5 * cofParFmt.minHeight);
543     SetObjectExtra (fpp->citdoc, fpp, NULL);
544     SetDocAutoAdjust (fpp->citdoc, FALSE);
545     fpp->pubset = NULL;
546   }
547 
548   return (DialoG) p;
549 }
550 
551 typedef struct citlist {
552   Uint2    entityID;
553   Uint4    itemID;
554   Uint2    itemtype;
555   CharPtr  label;
556 } CitListData, PNTR CitListDataPtr;
557 
558 typedef struct featcitedit {
559   DIALOG_MESSAGE_BLOCK
560   DoC             allcitdoc;
561   Int2            clickedItem;
562   Int2            clickedRow;
563   Int2            numitems;
564   Int2            lineheight;
565   Int2            index;
566   BoolPtr         chosen;
567   ValNodePtr      citlist;
568   ValNodePtr      psp;
569   ObjMgrPtr       omp;
570   Int2            entityID;
571 } FeatCitEdit, PNTR FeatCitEditPtr;
572 
CleanupFeatCitForm(GraphiC g,VoidPtr data)573 static void CleanupFeatCitForm (GraphiC g, VoidPtr data)
574 
575 {
576   FeatCitEditPtr  fcep;
577 
578   fcep = (FeatCitEditPtr) data;
579   if (fcep != NULL) {
580     MemFree (fcep->chosen);
581   }
582   MemFree (data);
583 }
584 
DrawFeatCit(DoC d,RectPtr r,Int2 item,Int2 firstLine)585 static void DrawFeatCit (DoC d, RectPtr r, Int2 item, Int2 firstLine)
586 
587 {
588   FeatCitEditPtr  fcep;
589   RecT            rct;
590 
591   fcep = (FeatCitEditPtr) GetObjectExtra (d);
592   if (fcep != NULL && r != NULL && item > 0 && firstLine == 0) {
593     rct = *r;
594     rct.left += 1;
595     rct.right = rct.left + fcep->lineheight;
596     rct.bottom = rct.top + (rct.right - rct.left);
597     FrameRect (&rct);
598     if (item > 0 && item <= fcep->numitems) {
599       if (fcep->chosen != NULL && fcep->chosen [item - 1]) {
600         MoveTo (rct.left, rct.top);
601         LineTo (rct.right - 1, rct.bottom - 1);
602         MoveTo (rct.left, rct.bottom - 1);
603         LineTo (rct.right - 1, rct.top);
604       }
605     }
606   }
607 }
608 
ClickFeatCit(DoC d,PoinT pt)609 static void ClickFeatCit (DoC d, PoinT pt)
610 
611 {
612 }
613 
ReleaseFeatCit(DoC d,PoinT pt)614 static void ReleaseFeatCit (DoC d, PoinT pt)
615 
616 {
617   Int2            col;
618   FeatCitEditPtr  fcep;
619   Int2            item;
620   RecT            rct;
621   Int2            row;
622 
623   fcep = (FeatCitEditPtr) GetObjectExtra (d);
624   if (fcep != NULL && fcep->chosen != NULL) {
625     MapDocPoint (d, pt, &item, &row, &col, &rct);
626     rct.left += 1;
627     rct.right = rct.left + fcep->lineheight;
628     rct.bottom = rct.top + (rct.right - rct.left);
629     if (row == 1 && col == 1 && item > 0 && item <= fcep->numitems && PtInRect (pt, &rct)) {
630       if (fcep->chosen [item - 1]) {
631         fcep->chosen [item - 1] = FALSE;
632       } else {
633         fcep->chosen [item - 1] = TRUE;
634       }
635       InsetRect (&rct, -1, -1);
636       InvalRect (&rct);
637       Update ();
638     }
639   }
640 }
641 
GatherAllCits(GatherContextPtr gcp)642 static Boolean GatherAllCits (GatherContextPtr gcp)
643 
644 {
645   CitListDataPtr  cldp;
646   FeatCitEditPtr  fcep;
647   Char            label [128];
648   ObjMgrTypePtr   omtp;
649   PubdescPtr      pdp;
650   ValNodePtr      sdp;
651   SeqFeatPtr      sfp;
652   ValNodePtr      vnp;
653 
654   if (gcp == NULL) return TRUE;
655   fcep = (FeatCitEditPtr) gcp->userdata;
656   if (fcep == NULL) return TRUE;
657   label [0] = '\0';
658   pdp = NULL;
659   if (gcp->thistype == OBJ_SEQDESC) {
660     sdp = (ValNodePtr) gcp->thisitem;
661     if (sdp == NULL || sdp->choice != Seq_descr_pub) return TRUE;
662     pdp = sdp->data.ptrvalue;
663   } else if (gcp->thistype == OBJ_SEQFEAT) {
664     sfp = (SeqFeatPtr) gcp->thisitem;
665     if (sfp == NULL || sfp->data.choice != SEQFEAT_PUB) return TRUE;
666     pdp = sfp->data.value.ptrvalue;
667   } else return TRUE;
668   if (pdp == NULL) return TRUE;
669   omtp = ObjMgrTypeFind (fcep->omp, gcp->thistype, NULL, NULL);
670   if (omtp == NULL || omtp->labelfunc == NULL) return TRUE;
671   (*(omtp->labelfunc)) (gcp->thisitem, label, 127, OM_LABEL_CONTENT);
672   cldp = (CitListDataPtr) MemNew (sizeof (CitListData));
673   if (cldp != NULL) {
674     vnp = ValNodeNew (fcep->citlist);
675     if (fcep->citlist == NULL) {
676       fcep->citlist = vnp;
677     }
678     if (vnp != NULL) {
679       vnp->data.ptrvalue = cldp;
680       cldp->entityID = gcp->entityID;
681       cldp->itemID = gcp->itemID;
682       cldp->itemtype = gcp->thistype;
683       cldp->label = StringSave (label);
684       (fcep->numitems)++;
685     } else {
686       MemFree (cldp);
687       return TRUE;
688     }
689   }
690   return TRUE;
691 }
692 
PrintCitOnFeatItem(GatherContextPtr gcp)693 static Boolean PrintCitOnFeatItem (GatherContextPtr gcp)
694 
695 {
696   CharPtr  PNTR  rsultp;
697   ValNodePtr     sdp;
698   SeqFeatPtr     sfp;
699   Boolean        success;
700 
701   rsultp = (CharPtr PNTR) gcp->userdata;
702   if (rsultp != NULL) {
703     success = FALSE;
704     switch (gcp->thistype) {
705       case OBJ_SEQDESC :
706         sdp = (ValNodePtr) gcp->thisitem;
707         if (sdp->data.ptrvalue != NULL) {
708           success = StdFormatPrint ((Pointer) sdp, (AsnWriteFunc) SeqDescAsnWrite,
709                                     "StdSeqDesc", spop);
710         } else {
711           *rsultp = StringSave ("Empty Descriptor\n");
712           success = TRUE;
713         }
714         break;
715       case OBJ_SEQFEAT :
716         sfp = (SeqFeatPtr) gcp->thisitem;
717         if (sfp != NULL && (sfp->data.choice == 10 || sfp->data.value.ptrvalue != NULL)) {
718           success = StdFormatPrint ((Pointer) sfp, (AsnWriteFunc) SeqFeatAsnWrite,
719                                     "StdSeqFeat", spop);
720         } else {
721           *rsultp = StringSave ("Empty Feature\n");
722           success = TRUE;
723         }
724         break;
725       default :
726         break;
727     }
728     if (success) {
729       if (spop->ptr != NULL && *((CharPtr) (spop->ptr)) != '\0') {
730         *rsultp = spop->ptr;
731         spop->ptr = NULL;
732       } else {
733         *rsultp = StringSave ("Empty Data\n");
734       }
735     } else {
736       *rsultp = StringSave ("Data Failure\n");
737     }
738   }
739   return TRUE;
740 }
741 
CitOnFeatPrintProc(DoC doc,Int2 item,Pointer data)742 static CharPtr CitOnFeatPrintProc (DoC doc, Int2 item, Pointer data)
743 
744 {
745   unsigned int  entityID;
746   unsigned int  itemID;
747   unsigned int  itemtype;
748   CharPtr       rsult;
749   CharPtr       str;
750 
751   rsult = NULL;
752   if (data != NULL) {
753     str = (CharPtr) data;
754     if (sscanf (str, "%u %u %u", &entityID, &itemID, &itemtype) == 3) {
755       GatherItem ((Uint2) entityID, (Uint2) itemID, (Uint2) itemtype,
756                   (Pointer) &rsult, PrintCitOnFeatItem);
757     }
758   } else {
759     rsult = StringSave ("Null Data\n");
760   }
761   return rsult;
762 }
763 
CompareCitList(VoidPtr ptr1,VoidPtr ptr2)764 static int LIBCALLBACK CompareCitList (VoidPtr ptr1, VoidPtr ptr2)
765 
766 {
767   CitListDataPtr  cldp1;
768   CitListDataPtr  cldp2;
769   CharPtr         str1;
770   CharPtr         str2;
771 
772   if (ptr1 != NULL && ptr2 != NULL) {
773     cldp1 = (CitListDataPtr) ptr1;
774     cldp2 = (CitListDataPtr) ptr2;
775     if (cldp1 != NULL && cldp2 != NULL) {
776       str1 = cldp1->label;
777       str2 = cldp2->label;
778       if (str1 != NULL && str2 != NULL) {
779         return StringICmp (str1, str2);
780       } else {
781         return 0;
782       }
783     } else {
784       return 0;
785     }
786   } else {
787     return 0;
788   }
789 }
790 
MakeMinimalCitOnFeatItem(GatherContextPtr gcp)791 static Boolean MakeMinimalCitOnFeatItem (GatherContextPtr gcp)
792 
793 {
794   PubdescPtr  pdp;
795   ValNodePtr  ppr;
796   ValNodePtr  sdp;
797   SeqFeatPtr  sfp;
798   ValNodePtr  vnp;
799   ValNodePtr  PNTR  vnpp;
800 
801   vnpp = (ValNodePtr PNTR) gcp->userdata;
802   if (vnpp != NULL) {
803     pdp = NULL;
804     switch (gcp->thistype) {
805       case OBJ_SEQDESC :
806         sdp = (ValNodePtr) gcp->thisitem;
807         if (sdp->data.ptrvalue != NULL) {
808           pdp = (PubdescPtr) sdp->data.ptrvalue;
809         }
810         break;
811       case OBJ_SEQFEAT :
812         sfp = (SeqFeatPtr) gcp->thisitem;
813         if (sfp != NULL && (sfp->data.choice == 10 || sfp->data.value.ptrvalue != NULL)) {
814           pdp = (PubdescPtr) sfp->data.value.ptrvalue;
815         }
816         break;
817       default :
818         break;
819     }
820     if (pdp != NULL) {
821       ppr = NULL;
822       vnp = ValNodeNew (NULL);
823       if (vnp != NULL) {
824         vnp->choice = PUB_Equiv;
825         vnp->data.ptrvalue = pdp->pub;
826         ppr = MinimizePub (vnp);
827         ValNodeFree (vnp);
828       }
829       vnp = ValNodeNew (*vnpp);
830       if (*vnpp == NULL) {
831         *vnpp = vnp;
832       }
833       if (vnp != NULL) {
834         vnp->choice = PUB_Equiv;
835         vnp->data.ptrvalue = ppr;
836       }
837     }
838   }
839   return TRUE;
840 }
841 
MatchMinimalCits(GatherContextPtr gcp)842 static Boolean MatchMinimalCits (GatherContextPtr gcp)
843 
844 {
845   FeatCitEditPtr  fcep;
846   PubdescPtr      pdp;
847   ValNodePtr      ppr;
848   ValNodePtr      sdp;
849   SeqFeatPtr      sfp;
850   ValNodePtr      vnp;
851 
852   fcep = (FeatCitEditPtr) gcp->userdata;
853   if (fcep != NULL) {
854     pdp = NULL;
855     switch (gcp->thistype) {
856       case OBJ_SEQDESC :
857         sdp = (ValNodePtr) gcp->thisitem;
858         if (sdp->data.ptrvalue != NULL) {
859           pdp = (PubdescPtr) sdp->data.ptrvalue;
860         }
861         break;
862       case OBJ_SEQFEAT :
863         sfp = (SeqFeatPtr) gcp->thisitem;
864         if (sfp != NULL && (sfp->data.choice == 10 || sfp->data.value.ptrvalue != NULL)) {
865           pdp = (PubdescPtr) sfp->data.value.ptrvalue;
866         }
867         break;
868       default :
869         break;
870     }
871     if (pdp != NULL && fcep->psp != NULL) {
872       vnp = ValNodeNew (NULL);
873       if (vnp != NULL) {
874         vnp->choice = PUB_Equiv;
875         vnp->data.ptrvalue = pdp->pub;
876         for (ppr = fcep->psp->data.ptrvalue; ppr != NULL; ppr = ppr->next) {
877           if (PubLabelMatch (vnp, ppr) == 0) {
878             fcep->chosen [fcep->index] = TRUE;
879           }
880         }
881         ValNodeFree (vnp);
882       }
883     }
884   }
885   return TRUE;
886 }
887 
CitListToDialog(DialoG d,Pointer userdata)888 static void CitListToDialog (DialoG d, Pointer userdata)
889 {
890   FeatCitEditPtr  fcep;
891   CitListDataPtr  cldp;
892   CitListDataPtr  cldpp;
893   Int2            count;
894   GatherScope     gs;
895   Int2            i;
896   Int2            j;
897   Char            last [128];
898   CharPtr         ptr;
899   RecT            r;
900   Char            str [34];
901   ValNodePtr      vnp;
902 
903   fcep = (FeatCitEditPtr) GetObjectExtra (d);
904   if (fcep == NULL)
905   {
906     return;
907   }
908   Reset (fcep->allcitdoc);
909 
910   fcep->citlist = ValNodeFree (fcep->citlist);
911   fcep->numitems = 0;
912   fcep->chosen = MemFree (fcep->chosen);
913 
914   MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
915   MemSet ((Pointer) (gs.ignore), (int) (TRUE), (size_t) (OBJ_MAX * sizeof (Boolean)));
916   gs.ignore [OBJ_SEQDESC] = FALSE;
917   gs.ignore [OBJ_SEQANNOT] = FALSE;
918   gs.ignore [OBJ_SEQFEAT] = FALSE;
919   gs.seglevels = 1;
920   GatherEntity (fcep->entityID, (Pointer) fcep, GatherAllCits, &gs);
921   count = fcep->numitems;
922   cldpp = (CitListDataPtr) MemNew (sizeof (CitListData) * (size_t) (count + 1));
923   if (cldpp != NULL) {
924     for (i = 0, vnp = fcep->citlist; i < count && vnp != NULL; i++, vnp = vnp->next) {
925       cldp = vnp->data.ptrvalue;
926       if (cldp != NULL) {
927         cldpp [i] = *cldp;
928         cldp->label = NULL;
929       }
930     }
931     fcep->citlist = ValNodeFreeData (fcep->citlist);
932     HeapSort (cldpp, count, sizeof (CitListData), CompareCitList);
933     last [0] = '\0';
934     ObjectRect (fcep->allcitdoc, &r);
935     InsetRect (&r, 4, 4);
936     cofeColFmt.pixWidth = r.right - r.left;
937     cofeColFmt.pixInset = 20;
938     fcep->numitems = 0;
939     fcep->chosen = MemNew (sizeof (Boolean) * (size_t) (count + 1));
940 
941     fcep->psp = (ValNodePtr) userdata;
942     for (i = 0, j = 0; i < count; i++) {
943       cldp = &(cldpp [i]);
944       if (cldp != NULL) {
945         if (last == NULL || StringCmp (cldp->label, last) != 0) {
946           sprintf (str, "%d %d %d", (int) cldp->entityID,
947                    (int) cldp->itemID, (int) cldp->itemtype);
948           ptr = StringSave (str);
949           (fcep->numitems)++;
950           AppendItem (fcep->allcitdoc, CitOnFeatPrintProc, (Pointer) ptr,
951                       TRUE, 5, &cofeParFmt, &cofeColFmt, programFont);
952           if (fcep->chosen != NULL) {
953             fcep->index = j;
954             GatherItem ((Uint2) cldp->entityID, (Uint2) cldp->itemID,
955                         (Uint2) cldp->itemtype, (Pointer) fcep, MatchMinimalCits);
956           }
957           j++;
958         }
959         StringNCpy_0 (last, cldp->label, sizeof (last));
960         cldpp [i].label = MemFree (cldpp [i].label);
961       }
962     }
963     fcep->psp = NULL;
964   }
965 }
966 
DialogToMinimizedCitList(DialoG d)967 static Pointer DialogToMinimizedCitList (DialoG d)
968 {
969   FeatCitEditPtr  fcep;
970   Pointer         data;
971   unsigned int    entityID;
972   Int2            i;
973   unsigned int    itemID;
974   unsigned int    itemtype;
975   Int2            numItems;
976   ValNodePtr      ppr = NULL, psp = NULL;
977   CharPtr         str;
978 
979   fcep = (FeatCitEditPtr) GetObjectExtra (d);
980   if (fcep == NULL)
981   {
982     return NULL;
983   }
984 
985   if (fcep->chosen != NULL) {
986     GetDocParams (fcep->allcitdoc, &numItems, NULL);
987     for (i = 1; i <= numItems; i++) {
988       if (fcep->chosen [i - 1]) {
989         GetItemParams (fcep->allcitdoc, i, NULL, NULL, NULL, NULL, &data);
990         if (data != NULL) {
991           str = (CharPtr) data;
992           if (sscanf (str, "%u %u %u", &entityID, &itemID, &itemtype) == 3) {
993             GatherItem ((Uint2) entityID, (Uint2) itemID, (Uint2) itemtype,
994                         (Pointer) &ppr, MakeMinimalCitOnFeatItem);
995           }
996         }
997       }
998     }
999   }
1000 
1001   if (ppr != NULL)
1002   {
1003     psp = ValNodeNew (NULL);
1004     if (psp != NULL) {
1005       psp->choice = 1;
1006       psp->data.ptrvalue = ppr;
1007     }
1008   }
1009   return psp;
1010 }
1011 
FeatCitEditDialog(GrouP parent,Uint2 entityID)1012 extern DialoG FeatCitEditDialog (GrouP parent, Uint2 entityID)
1013 {
1014   FeatCitEditPtr  fcep;
1015   GrouP           p;
1016 
1017   fcep = (FeatCitEditPtr) MemNew (sizeof (FeatCitEdit));
1018   if (fcep == NULL)
1019   {
1020     return NULL;
1021   }
1022 
1023   p = HiddenGroup (parent, -1, 0, NULL);
1024   SetObjectExtra (p, fcep, CleanupFeatCitForm);
1025 
1026   fcep->dialog = (DialoG) p;
1027   fcep->todialog = CitListToDialog;
1028   fcep->fromdialog = DialogToMinimizedCitList;
1029   fcep->dialogmessage = NULL;
1030   fcep->testdialog = NULL;
1031 
1032   fcep->entityID = entityID;
1033   fcep->omp = ObjMgrGet ();
1034   fcep->numitems = 0;
1035 
1036   fcep->allcitdoc = DocumentPanel (p, 25 * stdCharWidth, 15 * stdLineHeight);
1037   SetObjectExtra (fcep->allcitdoc, fcep, NULL);
1038   SetDocProcs (fcep->allcitdoc, ClickFeatCit, NULL, ReleaseFeatCit, NULL);
1039   SetDocShade (fcep->allcitdoc, DrawFeatCit, NULL, NULL, NULL);
1040 
1041   SelectFont (programFont);
1042   fcep->lineheight = LineHeight ();
1043   SelectFont (systemFont);
1044 
1045   return (DialoG) p;
1046 }
1047 
1048 typedef struct featcitationform
1049 {
1050   FeatureFormPtr ffp;
1051   DialoG         citation_list;
1052 
1053 } FeatCitationFormData, PNTR FeatCitationFormPtr;
1054 
AcceptFeatCit(ButtoN b)1055 static void AcceptFeatCit (ButtoN b)
1056 
1057 {
1058   FeatCitationFormPtr  fcfp;
1059   FeatureFormPtr       ffp;
1060   ValNodePtr           psp = NULL;
1061 
1062   fcfp = (FeatCitationFormPtr) GetObjectExtra (b);
1063   if (fcfp == NULL)
1064   {
1065     return;
1066   }
1067 
1068   psp = DialogToPointer (fcfp->citation_list);
1069   ffp = (FeatureFormPtr) fcfp->ffp;
1070   if (ffp != NULL) {
1071     PointerToDialog (ffp->featcits, (Pointer) psp);
1072     PubSetFree (psp);
1073   }
1074   Remove (ParentWindow (b));
1075 }
1076 
EditFeatCitsProc(ButtoN b)1077 static void EditFeatCitsProc (ButtoN b)
1078 
1079 {
1080   ButtoN          btn;
1081   GrouP           c;
1082   FeatCitationFormPtr  fcfp;
1083   FeatureFormPtr  ffp;
1084   WindoW          w;
1085   ValNodePtr      psp;
1086 
1087   ffp = (FeatureFormPtr) GetObjectExtra (b);
1088   if (ffp == NULL)
1089   {
1090     return;
1091   }
1092   fcfp = (FeatCitationFormPtr) MemNew (sizeof (FeatCitationFormData));
1093   if (fcfp == NULL)
1094   {
1095     return;
1096   }
1097 
1098   WatchCursor ();
1099   Update ();
1100   w = MovableModalWindow (-50, -33, -10, -10, "Citations", NULL);
1101   SetObjectExtra (w, fcfp, StdCleanupExtraProc);
1102 
1103   fcfp->ffp = ffp;
1104   fcfp->citation_list = FeatCitEditDialog (w, ffp->input_entityID);
1105 
1106   c = HiddenGroup (w, 4, 0, NULL);
1107   SetGroupSpacing (c, 10, 3);
1108   btn = PushButton (c, "Accept", AcceptFeatCit);
1109   SetObjectExtra (btn, fcfp, NULL);
1110   PushButton (c, "Cancel", StdCancelButtonProc);
1111   AlignObjects (ALIGN_CENTER, (HANDLE) fcfp->citation_list, (HANDLE) c, NULL);
1112   RealizeWindow (w);
1113 
1114   psp = DialogToPointer (ffp->featcits);
1115   PointerToDialog (fcfp->citation_list, psp);
1116   PubSetFree (psp);
1117 
1118   Show (w);
1119   Select (w);
1120   ArrowCursor ();
1121   Update ();
1122 }
1123 
ChangeGenePopupOrList(Handle gene)1124 static void ChangeGenePopupOrList (Handle gene)
1125 
1126 {
1127   FeatureFormPtr  ffp;
1128   Int2            val;
1129 
1130   ffp = (FeatureFormPtr) GetObjectExtra (gene);
1131   if (ffp != NULL) {
1132     val = GetValue (ffp->gene);
1133     if (val == 1) {
1134       SafeHide (ffp->newGeneGrp);
1135       SafeHide (ffp->editGeneBtn);
1136     } else if (val == 2) {
1137       SafeHide (ffp->editGeneBtn);
1138       SafeShow (ffp->newGeneGrp);
1139     } else {
1140       SafeHide (ffp->newGeneGrp);
1141       SafeShow (ffp->editGeneBtn);
1142     }
1143   }
1144 }
1145 
ChangeSubGroup(VoidPtr data,Int2 newval,Int2 oldval)1146 static void ChangeSubGroup (VoidPtr data, Int2 newval, Int2 oldval)
1147 
1148 {
1149   FeatureFormPtr  ffp;
1150 
1151   ffp = (FeatureFormPtr) data;
1152   if (ffp != NULL) {
1153     if (ffp->commonPage >= 0 && ffp->commonPage <= 6) {
1154       SafeHide (ffp->commonSubGrp [ffp->commonPage]);
1155     }
1156     ffp->commonPage = newval;
1157     if (ffp->commonPage >= 0 && ffp->commonPage <= 6) {
1158       SafeShow (ffp->commonSubGrp [ffp->commonPage]);
1159     }
1160   }
1161 }
1162 
1163 typedef struct fieldpage {
1164   DIALOG_MESSAGE_BLOCK
1165   Int2               numfields;
1166   CharPtr            PNTR fields;
1167   TexT               PNTR values;
1168   ButtoN             PNTR boxes;
1169 } FieldPage, PNTR FieldPagePtr;
1170 
1171 
1172 
TrimCommasAndAtSignsAroundGBString(CharPtr str)1173 static CharPtr TrimCommasAndAtSignsAroundGBString (CharPtr str)
1174 
1175 {
1176   Uchar    ch;  /* to use 8bit characters in multibyte languages */
1177   CharPtr  dst;
1178   CharPtr  ptr;
1179 
1180   if (str != NULL && str [0] != '\0') {
1181     dst = str;
1182     ptr = str;
1183     ch = *ptr;
1184     while (ch != '\0' && (ch < ' ' || ch == '{' || ch == ',')) {
1185       ptr++;
1186       ch = *ptr;
1187     }
1188     while (ch != '\0') {
1189       *dst = ch;
1190       dst++;
1191       ptr++;
1192       ch = *ptr;
1193     }
1194     *dst = '\0';
1195     dst = NULL;
1196     ptr = str;
1197     ch = *ptr;
1198     while (ch != '\0') {
1199       if (ch != '}' && ch != ',') {
1200         dst = NULL;
1201       } else if (dst == NULL) {
1202         dst = ptr;
1203       }
1204       ptr++;
1205       ch = *ptr;
1206     }
1207     if (dst != NULL) {
1208       *dst = '\0';
1209     }
1210   }
1211   return str;
1212 }
1213 
CombineSplitGBQual(CharPtr origval,CharPtr newval)1214 static CharPtr CombineSplitGBQual (CharPtr origval, CharPtr newval)
1215 
1216 {
1217   size_t   len;
1218   CharPtr  str = NULL;
1219 
1220   if (StringStr (origval, newval) != NULL) return origval;
1221   len = StringLen (origval) + StringLen (newval) + 5;
1222   str = MemNew (sizeof (Char) * len);
1223   if (str == NULL) return origval;
1224   TrimCommasAndAtSignsAroundGBString (origval);
1225   TrimCommasAndAtSignsAroundGBString (newval);
1226   StringCpy (str, "{");
1227   StringCat (str, origval);
1228   StringCat (str, ",");
1229   StringCat (str, newval);
1230   StringCat (str, "}");
1231   /* free original string, knowing return value will replace it */
1232   MemFree (origval);
1233   return str;
1234 }
1235 
CombineTitle(TexT t,CharPtr val)1236 static void CombineTitle (TexT t, CharPtr val)
1237 
1238 {
1239   CharPtr  str;
1240 
1241   if (t == NULL || StringHasNoText (val)) return;
1242   str = SaveStringFromText (t);
1243   if (StringDoesHaveText (str)) {
1244     str = CombineSplitGBQual (str, val);
1245     SetTitle (t, str);
1246   } else {
1247     SetTitle (t, val);
1248   }
1249   MemFree (str);
1250 }
1251 
GBQualPtrToFieldPage(DialoG d,Pointer data)1252 static void GBQualPtrToFieldPage (DialoG d, Pointer data)
1253 
1254 {
1255   Char          empty [4];
1256   FieldPagePtr  fpf;
1257   Int2          i;
1258   GBQualPtr     list;
1259 
1260   fpf = (FieldPagePtr) GetObjectExtra (d);
1261   list = (GBQualPtr) data;
1262   if (fpf != NULL) {
1263     while (list != NULL) {
1264       if (list->qual != NULL && list->val != NULL) {
1265         for (i = 0; i < fpf->numfields; i++) {
1266           if (StringICmp (list->qual, fpf->fields [i]) == 0) {
1267             if (fpf->values [i] != NULL) {
1268               if (*(list->val) == '\0') {
1269                 empty [0] = '"';
1270                 empty [1] = '"';
1271                 empty [2] = '\0';
1272                 SetTitle (fpf->values [i], empty);
1273               } else if (StringICmp (list->qual, "rpt_type") == 0 ||
1274                          StringICmp (list->qual, "rpt_unit") == 0 ||
1275                          StringICmp (list->qual, "rpt_unit_range") == 0 ||
1276                          StringICmp (list->qual, "rpt_unit_seq") == 0 ||
1277                          StringICmp (list->qual, "replace") == 0 ||
1278                          StringICmp (list->qual, "compare") == 0 ||
1279                          StringICmp (list->qual, "old_locus_tag") == 0 ||
1280                          StringICmp (list->qual, "usedin") == 0) {
1281                 CombineTitle (fpf->values [i], list->val);
1282               } else {
1283                 SetTitle (fpf->values [i], list->val);
1284               }
1285             } else if (fpf->boxes [i] != NULL) {
1286               SetStatus (fpf->boxes [i], TRUE);
1287             }
1288           }
1289         }
1290       }
1291       list = list->next;
1292     }
1293   }
1294 }
1295 
1296 extern void SeqFeatPtrToFieldPage (DialoG d, SeqFeatPtr sfp);
SeqFeatPtrToFieldPage(DialoG d,SeqFeatPtr sfp)1297 extern void SeqFeatPtrToFieldPage (DialoG d, SeqFeatPtr sfp)
1298 
1299 {
1300   /*
1301   FieldPagePtr  fpf;
1302   Int2          i;
1303 
1304   fpf = (FieldPagePtr) GetObjectExtra (d);
1305   if (fpf != NULL && sfp != NULL) {
1306         for (i = 0; i < fpf->numfields; i++) {
1307           if (StringICmp ("exception", fpf->fields [i]) == 0) {
1308             if (fpf->values [i] != NULL) {
1309               if (sfp->except_text == NULL || *(sfp->except_text) == '\0') {
1310                 SetTitle (fpf->values [i], "");
1311               } else {
1312                 SetTitle (fpf->values [i], sfp->except_text);
1313               }
1314             }
1315           } else if (StringICmp ("pseudo", fpf->fields [i]) == 0) {
1316             if (fpf->boxes [i] != NULL && (! GetStatus (fpf->boxes [i]))) {
1317               SetStatus (fpf->boxes [i], sfp->pseudo);
1318             }
1319           }
1320         }
1321   }
1322   */
1323 
1324 }
1325 
FieldPageToGBQualPtr(DialoG d)1326 static Pointer FieldPageToGBQualPtr (DialoG d)
1327 
1328 {
1329   FieldPagePtr  fpf;
1330   GBQualPtr     gbq;
1331   GBQualPtr     gbqlast;
1332   GBQualPtr     head;
1333   Int2          i;
1334 
1335   head = NULL;
1336   fpf = (FieldPagePtr) GetObjectExtra (d);
1337   if (fpf != NULL) {
1338     gbq = NULL;
1339     gbqlast = NULL;
1340     for (i = 0; i < fpf->numfields; i++) {
1341       if (fpf->fields [i] == NULL ||
1342           StringHasNoText (fpf->fields [i]) ||
1343           (fpf->values [i] == NULL && fpf->boxes [i] ==NULL) ||
1344           (fpf->values [i] != NULL && TextHasNoText (fpf->values [i]))) {
1345       } else if (fpf->boxes [i] != NULL && (! GetStatus (fpf->boxes [i]))) {
1346       } else {
1347         gbq = GBQualNew ();
1348         if (gbqlast == NULL) {
1349           head = gbq;
1350         } else {
1351           gbqlast->next = gbq;
1352         }
1353         gbqlast = gbq;
1354         if (gbq != NULL) {
1355           gbq->qual = StringSave (fpf->fields [i]);
1356           if (fpf->values [i] != NULL) {
1357             gbq->val = SaveStringFromText (fpf->values [i]);
1358           } else {
1359             gbq->val = StringSave ("");
1360           }
1361         }
1362       }
1363     }
1364   }
1365   return (Pointer) head;
1366 }
1367 
CleanupFieldsPage(GraphiC g,VoidPtr data)1368 static void CleanupFieldsPage (GraphiC g, VoidPtr data)
1369 
1370 {
1371   FieldPagePtr  fpf;
1372   Int2          i;
1373 
1374   fpf = (FieldPagePtr) data;
1375   if (fpf != NULL) {
1376     if (fpf->fields != NULL) {
1377       for (i = 0; i < fpf->numfields; i++) {
1378         MemFree (fpf->fields [i]);
1379       }
1380     }
1381     MemFree (fpf->fields);
1382     MemFree (fpf->values);
1383     MemFree (fpf->boxes);
1384   }
1385   MemFree (data);
1386 }
1387 
1388 #define LEGAL_FEATURE    1
1389 #define ILLEGAL_FEATURE  2
1390 
CreateImportFields(GrouP h,CharPtr name,SeqFeatPtr sfp,Boolean allowProductGBQual)1391 extern DialoG CreateImportFields (GrouP h, CharPtr name, SeqFeatPtr sfp, Boolean allowProductGBQual)
1392 
1393 {
1394   FieldPagePtr    fpf;
1395   GrouP           g;
1396   GBQualPtr       gbq;
1397   Boolean         hasillegal;
1398   Int2            i;
1399   ImpFeatPtr      imp;
1400   Int2            index;
1401   Boolean         is_gap = FALSE;
1402   Int2            j;
1403   Int2            max;
1404   Int2            num;
1405   GrouP           p;
1406   PrompT          ppt;
1407   Int2            qual;
1408   Int2            seen [ParFlat_TOTAL_GBQUAL];
1409   SematicFeatPtr  sefp;
1410   Char            str [64];
1411   Int2            wid;
1412 
1413   p = HiddenGroup (h, 1, 0, NULL);
1414   fpf = (FieldPagePtr) MemNew (sizeof (FieldPage));
1415   if (fpf != NULL) {
1416 
1417     SetObjectExtra (p, fpf, CleanupFieldsPage);
1418     fpf->dialog = (DialoG) p;
1419     fpf->todialog = GBQualPtrToFieldPage;
1420     fpf->fromdialog = FieldPageToGBQualPtr;
1421     fpf->testdialog = NULL;
1422 
1423     if (sfp != NULL && sfp->data.choice == SEQFEAT_IMP) {
1424       imp = (ImpFeatPtr) sfp->data.value.ptrvalue;
1425       if (imp != NULL && StringICmp (imp->key, "gap") == 0) {
1426         is_gap = TRUE;
1427       }
1428     }
1429 
1430     gbq = NULL;
1431     if (sfp != NULL) {
1432       gbq = sfp->qual;
1433     }
1434 
1435     j = 0;
1436     hasillegal = FALSE;
1437     for (i = 0; i < ParFlat_TOTAL_GBQUAL; i++) {
1438       seen [i] = 0;
1439     }
1440     num = 0;
1441 
1442     if (name != NULL) {
1443       index = GBFeatKeyNameValid (&name, FALSE);
1444       if (index >= 0) {
1445 
1446         sefp = &(ParFlat_GBFeat [index]);
1447 
1448         for (i = 0; i < sefp->mand_num; i++) {
1449           qual = sefp->mand_qual [i];
1450           if (qual > -1 && ShouldBeAGBQual (sfp == NULL ? FEATDEF_ANY : sfp->idx.subtype, qual, allowProductGBQual)) {
1451             seen [qual] = LEGAL_FEATURE;
1452           }
1453         }
1454         if (StringCmp (name, "repeat_region") == 0) {
1455           seen [GBQUAL_map] = TRUE;
1456         }
1457         if (StringCmp (name, "operon") == 0) {
1458           seen [GBQUAL_operon] = TRUE;
1459         }
1460         for (i = 0; i < sefp->opt_num; i++) {
1461           qual = sefp->opt_qual [i];
1462           if (qual > -1 && ShouldBeAGBQual (sfp == NULL ? FEATDEF_ANY : sfp->idx.subtype, qual, allowProductGBQual)) {
1463             seen [qual] = LEGAL_FEATURE;
1464           }
1465         }
1466       }
1467     } else if (sfp != NULL && sfp->data.choice == SEQFEAT_CDREGION) {
1468       /*
1469       seen [GBQUAL_exception] = LEGAL_FEATURE;
1470       seen [GBQUAL_pseudo] = LEGAL_FEATURE;
1471       */
1472     }
1473 
1474     while (gbq != NULL) {
1475       qual = GBQualNameValid (gbq->qual);
1476       if (qual > -1) {
1477         if (seen [qual] == 0 && qual != GBQUAL_experiment && qual != GBQUAL_inference && qual != GBQUAL_pseudogene) {
1478           seen [qual] = ILLEGAL_FEATURE;
1479           hasillegal = TRUE;
1480         }
1481       }
1482       gbq = gbq->next;
1483     }
1484 
1485     SelectFont (programFont);
1486     max = 0;
1487     for (i = 0; i < ParFlat_TOTAL_GBQUAL; i++) {
1488       if (seen [i] > 0) {
1489         num++;
1490         if (seen [i] == LEGAL_FEATURE) {
1491           StringNCpy_0 (str, ParFlat_GBQual_names [i].name, sizeof (str));
1492           wid = StringWidth (str) + 2;
1493         } else {
1494           str [0] = '\0';
1495           if (name != NULL) {
1496             StringCpy (str, "*");
1497           }
1498           StringNCat (str, ParFlat_GBQual_names [i].name, sizeof (str) - 2);
1499           wid = StringWidth (str) + 2;
1500         }
1501         if (wid > max) {
1502           max = wid;
1503         }
1504       }
1505     }
1506     SelectFont (systemFont);
1507 
1508     fpf->numfields = num;
1509     fpf->fields = MemNew (sizeof (CharPtr) * (num + 1));
1510     fpf->values = MemNew (sizeof (TexT) * (num + 1));
1511     fpf->boxes = MemNew (sizeof (ButtoN) * (num + 1));
1512 
1513     g = HiddenGroup (p, 2, 0, NULL);
1514     j = 0;
1515     for (i = 0; i < ParFlat_TOTAL_GBQUAL; i++) {
1516       if (seen [i] == LEGAL_FEATURE) {
1517         fpf->fields [j] = StringSave (ParFlat_GBQual_names [i].name);
1518         ppt = StaticPrompt (g, fpf->fields [j], max, dialogTextHeight, programFont, 'l');
1519         if (ParFlat_GBQual_names [i].gbclass != Class_none) {
1520           fpf->values [j] = DialogText (g, "", 20, NULL);
1521           /*
1522           if (i == GBQUAL_estimated_length && is_gap) {
1523             Disable (fpf->values [j]);
1524           }
1525           */
1526         } else {
1527           fpf->boxes [j] = CheckBox (g, "", NULL);
1528           AlignObjects (ALIGN_MIDDLE, (HANDLE) ppt, (HANDLE) fpf->boxes [j], NULL);
1529         }
1530         j++;
1531       }
1532     }
1533     if (hasillegal && name != NULL) {
1534       StaticPrompt (p, "Illegal Qualifiers", 0, 0, programFont, 'c');
1535     }
1536     g = HiddenGroup (p, 2, 0, NULL);
1537     for (i = 0; i < ParFlat_TOTAL_GBQUAL; i++) {
1538       if (seen [i] == ILLEGAL_FEATURE) {
1539         fpf->fields [j] = StringSave (ParFlat_GBQual_names [i].name);
1540         str [0] = '\0';
1541         if (name != NULL) {
1542           StringCpy (str, "*");
1543         }
1544         StringNCat (str, fpf->fields [j], sizeof (str) - 2);
1545         ppt = StaticPrompt (g, str, max, dialogTextHeight, programFont, 'l');
1546         if (ParFlat_GBQual_names [i].gbclass != Class_none) {
1547           fpf->values [j] = DialogText (g, "", 20, NULL);
1548         } else {
1549           fpf->boxes [j] = CheckBox (g, "", NULL);
1550           AlignObjects (ALIGN_MIDDLE, (HANDLE) ppt, (HANDLE) fpf->boxes [j], NULL);
1551         }
1552         j++;
1553       }
1554     }
1555 
1556     if (j == 0) {
1557       StaticPrompt (p, "See Attributes page to set legal qualifiers for this feature.",
1558                     0, 0, programFont, 'c');
1559     }
1560   }
1561   return (DialoG) p;
1562 }
1563 
ChangeCannedMessage(PopuP p)1564 static void ChangeCannedMessage (PopuP p)
1565 
1566 {
1567   FeatureFormPtr  ffp;
1568   Int2            val;
1569 
1570   ffp = (FeatureFormPtr) GetObjectExtra (p);
1571   if (ffp == NULL) return;
1572   val = GetValue (p);
1573   switch (val) {
1574     case 1 :
1575       if (Message (MSG_YN, "Clear the explanation field?") == ANS_YES) {
1576         SetTitle (ffp->exceptText, "");
1577         if (Message (MSG_YN, "Clear the exception flag?") == ANS_YES) {
1578           SetStatus (ffp->exception, FALSE);
1579         }
1580       }
1581       break;
1582     case 2 :
1583       SetTitle (ffp->exceptText, "RNA editing");
1584       SetStatus (ffp->exception, TRUE);
1585       break;
1586     case 3 :
1587       SetTitle (ffp->exceptText, "reasons given in citation");
1588       SetStatus (ffp->exception, TRUE);
1589       break;
1590     case 4 :
1591       SetTitle (ffp->exceptText, "ribosomal slippage");
1592       SetStatus (ffp->exception, TRUE);
1593       break;
1594     case 5 :
1595       SetTitle (ffp->exceptText, "trans-splicing");
1596       SetStatus (ffp->exception, TRUE);
1597       break;
1598     case 6 :
1599       SetTitle (ffp->exceptText, "artificial frameshift");
1600       SetStatus (ffp->exception, TRUE);
1601       break;
1602     case 7 :
1603       SetTitle (ffp->exceptText, "nonconsensus splice site");
1604       SetStatus (ffp->exception, TRUE);
1605       break;
1606     case 8 :
1607       SetTitle (ffp->exceptText, "rearrangement required for product");
1608       SetStatus (ffp->exception, TRUE);
1609       break;
1610     case 9 :
1611       SetTitle (ffp->exceptText, "alternative start codon");
1612       SetStatus (ffp->exception, TRUE);
1613       break;
1614     case 10 :
1615       SetTitle (ffp->exceptText, "annotated by transcript or proteomic data");
1616       SetStatus (ffp->exception, TRUE);
1617       break;
1618     case 11 :
1619       SetTitle (ffp->exceptText, "heterogeneous population sequenced");
1620       SetStatus (ffp->exception, TRUE);
1621       break;
1622     case 12 :
1623       SetTitle (ffp->exceptText, "low-quality sequence region");
1624       SetStatus (ffp->exception, TRUE);
1625       break;
1626     case 13 :
1627       SetTitle (ffp->exceptText, "unextendable partial coding region");
1628       SetStatus (ffp->exception, TRUE);
1629       break;
1630     case 14 :
1631       SetTitle (ffp->exceptText, "translation initiation by tRNA-Leu at CUG codon");
1632       SetStatus (ffp->exception, TRUE);
1633       break;
1634     default :
1635       break;
1636   }
1637 }
1638 
1639 static CharPtr crossRefWarn =
1640 "A gene mapped by cross-reference does not extend the range\n\
1641 of the indicated gene feature.  Overlap is the usual case, and\n\
1642 it does extend the selected gene.";
1643 
1644 static CharPtr suppressWarn =
1645 "This will suppress display of a gene qualifier even though\n\
1646 there is a gene feature that overlaps this one.";
1647 
GeneXrefWarn(GrouP g)1648 static void GeneXrefWarn (GrouP g)
1649 
1650 {
1651   Int2  val;
1652   Boolean indexerVersion;
1653 
1654   indexerVersion = (Boolean) (GetAppProperty ("InternalNcbiSequin") != NULL);
1655   if (indexerVersion) return;
1656 
1657   val = GetValue (g);
1658   if (val == 2) {
1659     Message (MSG_OK, "%s", crossRefWarn);
1660   } else if (val == 3) {
1661     Message (MSG_OK, "%s", suppressWarn);
1662   }
1663 }
1664 
1665 static CharPtr  commonRadioFormTabs [] = {
1666   "General", "Comment", "Citations", "Cross-Refs", "Evidence", "Identifiers", NULL, NULL
1667 };
1668 
1669 static CharPtr  commonNoCitFormTabs [] = {
1670   "General", "Comment", "Cross-Refs", "Evidence", "Identifiers", NULL, NULL
1671 };
1672 
1673 static DialoG NewCreateInferenceDialog (GrouP prnt);
1674 extern void Nlm_LaunchGeneFeatEd (ButtoN b);
1675 
GetNameForFeature(SeqFeatPtr sfp)1676 static CharPtr GetNameForFeature (SeqFeatPtr sfp)
1677 {
1678   FeatDefPtr curr;
1679   Uint1      key;
1680   CharPtr    label = NULL;
1681   CharPtr    featname = NULL;
1682   CharPtr    ptr;
1683   Char       ch;
1684 
1685   if (sfp != NULL) {
1686     curr = FeatDefFindNext (NULL, &key, &label, sfp->idx.subtype, TRUE);
1687     if (curr != NULL) {
1688       featname = StringSave (label);
1689       ptr = featname;
1690       ch = *ptr;
1691       while (ch != '\0') {
1692         if (IS_UPPER (ch)) {
1693           *ptr = TO_LOWER (ch);
1694         }
1695         ptr++;
1696         ch = *ptr;
1697       }
1698     }
1699   }
1700   return featname;
1701 }
1702 
1703 
ClearTextBtn(ButtoN b)1704 NLM_EXTERN void ClearTextBtn (ButtoN b)
1705 {
1706   TexT t;
1707 
1708   t = (TexT) GetObjectExtra (b);
1709   SafeSetTitle (t, "");
1710 }
1711 
1712 
CreateCommonFeatureGroupEx(GrouP h,FeatureFormPtr ffp,SeqFeatPtr sfp,Boolean hasGeneControl,Boolean hasCitationTab,Boolean hasGeneSuppress)1713 extern GrouP CreateCommonFeatureGroupEx (GrouP h, FeatureFormPtr ffp,
1714                                          SeqFeatPtr sfp, Boolean hasGeneControl,
1715                                          Boolean hasCitationTab, Boolean hasGeneSuppress)
1716 
1717 {
1718   ButtoN     b;
1719   GrouP      c;
1720   PopuP      canned;
1721   Boolean    cdsQuals;
1722   GrouP      f;
1723   GrouP      g;
1724   GBQualPtr  gbq;
1725   Boolean    hasQuals;
1726   Boolean    indexerVersion;
1727   Boolean    ispseudo = FALSE;
1728   Char       just;
1729   GrouP      k;
1730   GrouP      m;
1731   GrouP      p;
1732   Int2       page;
1733   PrompT     ppt1, ppt2;
1734   /*
1735   ButtoN     pseudo = NULL;
1736   */
1737   CharPtr    pseudogene = NULL;
1738   GrouP      q;
1739   GrouP      r;
1740   GrouP      t;
1741   GrouP      v;
1742   GrouP      x;
1743   GrouP      y;
1744   CharPtr    featname;
1745 
1746   c = NULL;
1747   if (ffp != NULL) {
1748     hasQuals = FALSE;
1749     cdsQuals = FALSE;
1750     if (sfp != NULL && sfp->pseudo) {
1751       ispseudo = TRUE;
1752     }
1753     if (ffp->gbquals == NULL && sfp != NULL && sfp->qual != NULL) {
1754       for (gbq = sfp->qual; gbq != NULL && !hasQuals; gbq = gbq->next) {
1755         if (StringCmp (gbq->qual, "pseudogene") == 0) {
1756           pseudogene = gbq->val;
1757         }
1758         if (!ShouldSuppressGBQual(sfp->idx.subtype, gbq->qual)) {
1759           hasQuals = TRUE;
1760         }
1761       }
1762       /*
1763       if (GetAppProperty ("InternalNcbiSequin") != NULL) {
1764         if (sfp->data.choice == SEQFEAT_CDREGION) {
1765           cdsQuals = TRUE;
1766         }
1767       }
1768       */
1769     }
1770     m = HiddenGroup (h, -1, 0, NULL);
1771     SetGroupSpacing (m, 10, 10);
1772     ffp->commonPage = 0;
1773     if (cdsQuals) {
1774     } else if (hasQuals) {
1775       commonRadioFormTabs [6] = "Qualifiers";
1776       commonNoCitFormTabs [5] = "Qualifiers";
1777     }
1778     if (hasCitationTab) {
1779       ffp->commonRadio = CreateFolderTabs (m, commonRadioFormTabs, ffp->commonPage,
1780                                            0, 0, PROGRAM_FOLDER_TAB,
1781                                            ChangeSubGroup, (Pointer) ffp);
1782     } else {
1783       ffp->commonRadio = CreateFolderTabs (m, commonNoCitFormTabs, ffp->commonPage,
1784                                            0, 0, PROGRAM_FOLDER_TAB,
1785                                            ChangeSubGroup, (Pointer) ffp);
1786     }
1787     commonRadioFormTabs [6] = NULL;
1788     commonNoCitFormTabs [5] = NULL;
1789 
1790     p = HiddenGroup (m, 0, 0, NULL);
1791 
1792     c = HiddenGroup (p, -1, 0, NULL);
1793     SetGroupSpacing (c, 10, 10);
1794     f = HiddenGroup (c, -1, 0, NULL);
1795     r = HiddenGroup (f, 7, 0, NULL);
1796     StaticPrompt (r, "Flags", 0, popupMenuHeight, programFont, 'l');
1797     ffp->partial = CheckBox (r, "Partial", NULL);
1798     indexerVersion = (Boolean) (GetAppProperty ("InternalNcbiSequin") != NULL);
1799     if (! indexerVersion) {
1800       Disable (ffp->partial);
1801     }
1802 #if 0
1803     if (ffp->pseudo == NULL) {
1804       ffp->pseudo = CheckBox (r, "Pseudo", NULL);
1805       pseudo = ffp->pseudo; /* allows pseudo control on earlier feature-specific page */
1806     }
1807 #endif
1808     StaticPrompt (r, "Pseudogene", 0, popupMenuHeight, programFont, 'l');
1809     ffp->pseudogene = PopupList (r, TRUE, NULL);
1810     SetObjectExtra (ffp->pseudogene, (Pointer) ffp, NULL);
1811     InitPseudogenePopup (ffp, ffp->pseudogene, ispseudo, pseudogene, indexerVersion);
1812     if (indexerVersion) {
1813       StaticPrompt (r, "Evidence", 0, popupMenuHeight, programFont, 'l');
1814       ffp->evidence = PopupList (r, TRUE, NULL);
1815       PopupItem (ffp->evidence, " ");
1816       PopupItem (ffp->evidence, "Experimental");
1817       PopupItem (ffp->evidence, "Non-Experimental");
1818     }
1819     AlignObjects (ALIGN_MIDDLE, (HANDLE) ffp->partial, /* (HANDLE) pseudo, */
1820                   (HANDLE) ffp->pseudogene, (HANDLE) ffp->evidence, NULL);
1821     r = HiddenGroup (f, -3, 0, NULL);
1822     ffp->exception = CheckBox (r, "Exception", NULL);
1823     StaticPrompt (r, "Explanation", 0, dialogTextHeight, programFont, 'l');
1824     ffp->exceptText = DialogText (r, "", 12, NULL);
1825     AlignObjects (ALIGN_MIDDLE, (HANDLE) ffp->exception,
1826                  (HANDLE) ffp->exceptText, NULL);
1827     if (ffp->this_subtype == FEATDEF_CDS) {
1828       StaticPrompt (r, "Standard explanation", 0, popupMenuHeight, programFont, 'l');
1829       canned = PopupList (r, TRUE, ChangeCannedMessage);
1830       SetObjectExtra (canned, (Pointer) ffp, NULL);
1831       PopupItem (canned, " ");
1832       PopupItem (canned, "RNA editing");
1833       PopupItem (canned, "reasons given in citation");
1834       PopupItem (canned, "ribosomal slippage");
1835       PopupItem (canned, "trans-splicing");
1836       PopupItem (canned, "artificial frameshift");
1837       PopupItem (canned, "nonconsensus splice site");
1838       PopupItem (canned, "rearrangement required");
1839       PopupItem (canned, "alternative start codon");
1840       PopupItem (canned, "transcript or proteome data");
1841       PopupItem (canned, "heterogeneous population");
1842       PopupItem (canned, "low-quality sequence region");
1843       PopupItem (canned, "unextendable partial CDS");
1844       if (indexerVersion) {
1845         PopupItem (canned, "Leu-CUG initiation");
1846       }
1847       if (sfp != NULL && sfp->excpt) {
1848         if (StringICmp (sfp->except_text, "RNA editing") == 0) {
1849           SetValue (canned, 2);
1850         } else if (StringICmp (sfp->except_text, "reasons given in citation") == 0 ||
1851                    StringICmp (sfp->except_text, "reasons cited in publication") == 0) {
1852           SetValue (canned, 3);
1853         } else if (StringICmp (sfp->except_text, "ribosomal slippage") == 0 ||
1854                    StringICmp (sfp->except_text, "ribosome slippage") == 0) {
1855           SetValue (canned, 4);
1856         } else if (StringICmp (sfp->except_text, "trans-splicing") == 0 ||
1857                    StringICmp (sfp->except_text, "trans splicing") == 0) {
1858           SetValue (canned, 5);
1859         } else if (StringICmp (sfp->except_text, "artificial frameshift") == 0) {
1860           SetValue (canned, 6);
1861         } else if (StringICmp (sfp->except_text, "non-consensus splice site") == 0 ||
1862                    StringICmp (sfp->except_text, "nonconsensus splice site") == 0) {
1863           SetValue (canned, 7);
1864         } else if (StringICmp (sfp->except_text, "rearrangement required for product") == 0) {
1865           SetValue (canned, 8);
1866         } else if (StringICmp (sfp->except_text, "alternative start codon") == 0) {
1867           SetValue (canned, 9);
1868         } else if (StringICmp (sfp->except_text, "annotated by transcript or proteomic data") == 0) {
1869           SetValue (canned, 10);
1870         } else if (StringICmp (sfp->except_text, "heterogeneous population sequenced") == 0) {
1871           SetValue (canned, 11);
1872         } else if (StringICmp (sfp->except_text, "low-quality sequence region") == 0) {
1873           SetValue (canned, 12);
1874         } else if (StringICmp (sfp->except_text, "unextendable partial coding region") == 0) {
1875           SetValue (canned, 13);
1876         } else if (indexerVersion && StringICmp (sfp->except_text, "translation initiation by tRNA-Leu at CUG codon") == 0) {
1877           SetValue (canned, 14);
1878         }
1879       } else {
1880         SetValue (canned, 1);
1881       }
1882     }
1883 
1884     if (cdsQuals) {
1885       /*
1886       ffp->gbquals = CreateImportFields (c, NULL, sfp, FALSE);
1887       */
1888     }
1889 
1890     g = NULL;
1891     k = NULL;
1892     ffp->gene = NULL;
1893     ffp->genePopup = NULL;
1894     ffp->geneList = NULL;
1895     ffp->geneNames = NULL;
1896     ffp->useGeneXref = NULL;
1897     ffp->newGeneGrp = NULL;
1898     ffp->geneSymbol = NULL;
1899     ffp->geneAllele = NULL;
1900     ffp->geneDesc = NULL;
1901     ffp->locusTag = NULL;
1902     ffp->geneSynonym = NULL;
1903     for (page = 0; page < 8; page++) {
1904       ffp->commonSubGrp [page] = NULL;
1905     }
1906     page = 0;
1907 
1908     if (hasGeneControl) {
1909       g = HiddenGroup (c, -2, 0, NULL);
1910       StaticPrompt (g, "Gene", 0, popupMenuHeight, programFont, 'l');
1911       v = HiddenGroup (g, 0, 0, NULL);
1912       ffp->genePopup = PopupList (v, TRUE, (PupActnProc) ChangeGenePopupOrList);
1913       SetObjectExtra (ffp->genePopup, (Pointer) ffp, NULL);
1914       PopupItem (ffp->genePopup, " ");
1915       PopupItem (ffp->genePopup, "New:");
1916       SetValue (ffp->genePopup, 1);
1917       Hide (ffp->genePopup);
1918       ffp->geneList = SingleList (v, 6, 3, (LstActnProc) ChangeGenePopupOrList);
1919       SetObjectExtra (ffp->geneList, (Pointer) ffp, NULL);
1920       ListItem (ffp->geneList, " ");
1921       ListItem (ffp->geneList, "New:");
1922       SetValue (ffp->geneList, 1);
1923       Hide (ffp->geneList);
1924       k = HiddenGroup (c, 3, 0, NULL);
1925       StaticPrompt (k, "Map by", 0, stdLineHeight, programFont, 'l');
1926       ffp->useGeneXref = HiddenGroup (k, 3, 0, GeneXrefWarn);
1927       SetObjectExtra (ffp->useGeneXref, ffp, NULL);
1928       RadioButton (ffp->useGeneXref, "Overlap");
1929       RadioButton (ffp->useGeneXref, "Cross-reference");
1930       RadioButton (ffp->useGeneXref, "Suppress");
1931       SetValue (ffp->useGeneXref, 1);
1932       y = HiddenGroup (c, 0, 0, NULL);
1933       ffp->newGeneGrp = HiddenGroup (y, 2, 0, NULL);
1934       StaticPrompt (ffp->newGeneGrp, "Gene Symbol", 0, dialogTextHeight, programFont, 'l');
1935       ffp->geneSymbol = DialogText (ffp->newGeneGrp, "", 20, NULL);
1936       StaticPrompt (ffp->newGeneGrp, "Allele", 0, dialogTextHeight, programFont, 'l');
1937       ffp->geneAllele = DialogText (ffp->newGeneGrp, "", 20, NULL);
1938       StaticPrompt (ffp->newGeneGrp, "Description", 0, dialogTextHeight, programFont, 'l');
1939       ffp->geneDesc = DialogText (ffp->newGeneGrp, "", 20, NULL);
1940       StaticPrompt (ffp->newGeneGrp, "Locus Tag", 0, dialogTextHeight, programFont, 'l');
1941       ffp->locusTag = DialogText (ffp->newGeneGrp, "", 20, NULL);
1942       StaticPrompt (ffp->newGeneGrp, "Synonym", 0, dialogTextHeight, programFont, 'l');
1943       ffp->geneSynonym = DialogText (ffp->newGeneGrp, "", 20, NULL);
1944       Hide (ffp->newGeneGrp);
1945       ffp->editGeneBtn = PushButton (y, "Edit Gene Feature", Nlm_LaunchGeneFeatEd);
1946       SetObjectExtra (ffp->editGeneBtn, ffp, NULL);
1947       Hide (ffp->editGeneBtn);
1948     } else if (hasGeneSuppress) {
1949       k = HiddenGroup (c, 3, 0, NULL);
1950       StaticPrompt (k, "Map by", 0, stdLineHeight, programFont, 'l');
1951       ffp->useGeneXref = HiddenGroup (k, 3, 0, GeneXrefWarn);
1952       SetObjectExtra (ffp->useGeneXref, ffp, NULL);
1953       RadioButton (ffp->useGeneXref, "Overlap");
1954       b = RadioButton (ffp->useGeneXref, "Cross-reference");
1955       Disable (b);
1956       RadioButton (ffp->useGeneXref, "Suppress");
1957       SetValue (ffp->useGeneXref, 1);
1958       y = HiddenGroup (c, 0, 0, NULL);
1959     }
1960     ffp->commonSubGrp [page] = c;
1961     page++;
1962     AlignObjects (ALIGN_CENTER, (HANDLE) f, (HANDLE) g,
1963                   (HANDLE) k, (HANDLE) ffp->newGeneGrp,
1964                   (HANDLE) ffp->editGeneBtn, NULL);
1965 
1966     c = HiddenGroup (p, -1, 0, NULL);
1967     SetGroupSpacing (c, 10, 10);
1968     q = HiddenGroup (c, 0, 3, NULL);
1969     StaticPrompt (q, "Comment", 25 * stdCharWidth, 0, programFont, 'c');
1970     if (GetAppProperty ("InternalNcbiSequin") != NULL) {
1971       ffp->comment = ScrollText (q, 25, 10, programFont, TRUE, NULL);
1972     } else {
1973       ffp->comment = ScrollText (q, 25, 5, programFont, TRUE, NULL);
1974     }
1975     b = PushButton (q, "Clear Comment", ClearTextBtn);
1976     SetObjectExtra (b, ffp->comment, NULL);
1977     ffp->commonSubGrp [page] = c;
1978     Hide (ffp->commonSubGrp [page]);
1979     page++;
1980 
1981     if (hasCitationTab) {
1982       c = HiddenGroup (p, -1, 0, NULL);
1983       SetGroupSpacing (c, 10, 10);
1984       ffp->featcits = CreateCitOnFeatDialog (c, NULL);
1985       b = PushButton (c, "Edit Citations", EditFeatCitsProc);
1986       SetObjectExtra (b, ffp, NULL);
1987       ffp->commonSubGrp [page] = c;
1988       AlignObjects (ALIGN_CENTER, (HANDLE) ffp->featcits, (HANDLE) b, NULL);
1989       Hide (ffp->commonSubGrp [page]);
1990       page++;
1991     }
1992 
1993     c = HiddenGroup (p, -1, 0, NULL);
1994     SetGroupSpacing (c, 10, 10);
1995     if (GetAppProperty ("ReadOnlyDbTags") == NULL) {
1996       just = 'c';
1997     } else {
1998       just = 'l';
1999       StaticPrompt (c, "This page is read-only", 15 * stdCharWidth, 0, programFont, 'c');
2000     }
2001     t = HiddenGroup (c, 2, 0, NULL);
2002     StaticPrompt (t, "Database", 7 * stdCharWidth, 0, programFont, just);
2003     StaticPrompt (t, "Object ID", 8 * stdCharWidth, 0, programFont, just);
2004     ffp->dbxrefs = CreateDbtagDialog (c, 3, -1, 7, 8);
2005     ffp->commonSubGrp [page] = c;
2006     Hide (ffp->commonSubGrp [page]);
2007     page++;
2008 
2009     c = HiddenGroup (p, -1, 0, NULL);
2010     SetGroupSpacing (c, 10, 10);
2011     q = HiddenGroup (c, 0, -6, NULL);
2012     ppt1 = StaticPrompt (q, "Experiment", 0, 0, programFont, 'c');
2013     ffp->experiment = CreateExperimentDialog (q);
2014     ppt2 = StaticPrompt (q, "Inference", 0, 0, programFont, 'c');
2015     /*
2016     ffp->inference = CreateInferenceDialog (q, 3, 2, 15);
2017     */
2018     ffp->inference = NewCreateInferenceDialog (q);
2019     AlignObjects (ALIGN_CENTER, (HANDLE) ppt1, (HANDLE) ffp->experiment,
2020                   (HANDLE) ppt2, (HANDLE) ffp->inference, NULL);
2021     ffp->commonSubGrp [page] = c;
2022     Hide (ffp->commonSubGrp [page]);
2023     page++;
2024 
2025     c = HiddenGroup (p, -1, 0, NULL);
2026     SetGroupSpacing (c, 10, 10);
2027     t = HiddenGroup (c, 2, 0, NULL);
2028     SetGroupSpacing (t, 10, 30);
2029     StaticPrompt (t, "Feature ID for this feature", 0, dialogTextHeight, programFont, 'l');
2030     ffp->featid = DialogText (t, "", 8, NULL);
2031     StaticPrompt (t, "ID Xref to associated feature", 0, dialogTextHeight, programFont, 'l');
2032     ffp->fidxref = DialogText (t, "", 8, NULL);
2033     if (! indexerVersion) {
2034       Disable (ffp->featid);
2035       Disable (ffp->fidxref);
2036     }
2037     ffp->commonSubGrp [page] = c;
2038     Hide (ffp->commonSubGrp [page]);
2039     page++;
2040 
2041 
2042     c = HiddenGroup (p, -1, 0, NULL);
2043     SetGroupSpacing (c, 10, 10);
2044     x = NULL;
2045     if (hasQuals && ffp->gbquals == NULL) {
2046       x = HiddenGroup (c, -1, 0, NULL);
2047       featname = GetGBFeatKeyForFeature (sfp);
2048       ffp->gbquals = NewCreateImportFields (x, featname, sfp, FALSE);
2049       featname = MemFree (featname);
2050     }
2051     ffp->commonSubGrp [page] = c;
2052     Hide (ffp->commonSubGrp [page]);
2053     page++;
2054 
2055 
2056     AlignObjects (ALIGN_CENTER, (HANDLE) ffp->commonRadio, (HANDLE) ffp->commonSubGrp [0],
2057                   (HANDLE) ffp->commonSubGrp [1], (HANDLE) ffp->commonSubGrp [2],
2058                   (HANDLE) ffp->commonSubGrp [3], (HANDLE) ffp->commonSubGrp [4],
2059                   (HANDLE) ffp->commonSubGrp [5], (HANDLE) ffp->commonSubGrp [6],
2060                   (HANDLE) ffp->commonSubGrp [7], NULL);
2061   }
2062   return c;
2063 }
2064 
CreateCommonFeatureGroup(GrouP h,FeatureFormPtr ffp,SeqFeatPtr sfp,Boolean hasGeneControl,Boolean hasCitationTab)2065 extern GrouP CreateCommonFeatureGroup (GrouP h, FeatureFormPtr ffp,
2066                                        SeqFeatPtr sfp, Boolean hasGeneControl,
2067                                        Boolean hasCitationTab)
2068 
2069 {
2070   return CreateCommonFeatureGroupEx (h, ffp, sfp, hasGeneControl, hasCitationTab, FALSE);
2071 }
2072 
DlgutilFindBspItem(GatherContextPtr gcp)2073 static Boolean DlgutilFindBspItem (GatherContextPtr gcp)
2074 
2075 {
2076   BioseqPtr  PNTR bspp;
2077 
2078   bspp = (BioseqPtr PNTR) gcp->userdata;
2079   if (bspp != NULL && gcp->thistype == OBJ_BIOSEQ) {
2080     *bspp = (BioseqPtr) gcp->thisitem;
2081   }
2082   return TRUE;
2083 }
2084 
SetNewFeatureDefaultInterval(FeatureFormPtr ffp)2085 extern void SetNewFeatureDefaultInterval (FeatureFormPtr ffp)
2086 
2087 {
2088   BioseqPtr     bsp;
2089   SelStructPtr  sel;
2090   SeqIntPtr     sip;
2091   SeqLocPtr     slp;
2092 
2093   if (ffp == NULL) return;
2094   bsp = NULL;
2095   GatherItem (ffp->input_entityID, ffp->input_itemID, ffp->input_itemtype,
2096               (Pointer) (&bsp), DlgutilFindBspItem);
2097   if (bsp == NULL) return;
2098   slp = NULL;
2099   sel = ObjMgrGetSelected ();
2100   if (sel != NULL && sel->next == NULL && sel->entityID == ffp->input_entityID &&
2101       sel->itemID == ffp->input_itemID && sel->itemtype == ffp->input_itemtype) {
2102     if (sel->regiontype == 1 && sel->region != NULL) {
2103       if (GetBioseqGivenSeqLoc ((SeqLocPtr) sel->region, ffp->input_entityID) == bsp) {
2104         slp = AsnIoMemCopy (sel->region,
2105                             (AsnReadFunc) SeqLocAsnRead,
2106                             (AsnWriteFunc) SeqLocAsnWrite);
2107       }
2108     }
2109   }
2110   if (slp == NULL) {
2111     slp = ValNodeNew (NULL);
2112     if (slp == NULL) return;
2113     sip = SeqIntNew ();
2114     if (sip == NULL) {
2115       slp = SeqLocFree (slp);
2116       return;
2117     }
2118     slp->choice = SEQLOC_INT;
2119     slp->data.ptrvalue = (Pointer) sip;
2120     sip->from = 0;
2121     sip->to = bsp->length - 1;
2122     sip->strand = Seq_strand_plus;
2123     sip->id = SeqIdStripLocus (SeqIdDup (SeqIdFindBest (bsp->id, 0)));
2124   }
2125   if (slp != NULL) {
2126     PointerToDialog (ffp->location, (Pointer) slp);
2127     SeqLocFree (slp);
2128   }
2129 }
2130 
FileToScrollText(TexT t,CharPtr path)2131 extern Boolean FileToScrollText (TexT t, CharPtr path)
2132 
2133 {
2134   FILE     *fp;
2135   Int8     len;
2136   Int4     read_len;
2137   Int4     max;
2138   CharPtr  str;
2139 #ifdef WIN_MAC
2140   CharPtr  p;
2141 #endif
2142 #if (defined(OS_DOS) || defined (OS_NT))
2143   CharPtr  p;
2144   CharPtr  q;
2145 #endif
2146 
2147   if (t != NULL && path != NULL && *path != '\0') {
2148     len = FileLength (path);
2149     max = (Int4) INT2_MAX;
2150 #ifdef WIN_MOTIF
2151     max = INT4_MAX;
2152 #endif
2153 #ifdef WIN_MSWIN
2154     max = INT4_MAX;
2155 #endif
2156 #ifdef WIN_MAC
2157 #ifdef OS_UNIX_DARWIN
2158     max = INT4_MAX;
2159 #endif
2160 #endif
2161     if (len > 0 && len < max - 4) {
2162       str = MemNew (sizeof (char) * ((size_t)len + 3));
2163       if (str != NULL) {
2164         fp = FileOpen (path, "r");
2165         if (fp != NULL) {
2166           read_len = FileRead (str, sizeof (char), (size_t) len, fp);
2167           str [ read_len ] = 0;
2168 #if (defined(OS_DOS) || defined (OS_NT))
2169           p = str;
2170           q = str;
2171           while (*p) {
2172             if (*p == '\r') {
2173               p++;
2174             } else {
2175               *q = *p;
2176               p++;
2177               q++;
2178             }
2179           }
2180           *q = '\0';
2181 #endif
2182 #ifdef WIN_MAC
2183           p = str;
2184           while (*p) {
2185             if (*p == '\r' || *p == '\n') {
2186               *p = '\015';
2187             }
2188             p++;
2189           }
2190 #endif
2191           FileClose (fp);
2192           SetTitle (t, str);
2193         }
2194         MemFree (str);
2195         return TRUE;
2196       }
2197     }
2198   }
2199   return FALSE;
2200 }
2201 
ScrollTextToFile(TexT t,CharPtr path)2202 extern void ScrollTextToFile (TexT t, CharPtr path)
2203 
2204 {
2205   FILE     *fp;
2206   size_t   len;
2207   CharPtr  str;
2208 #ifdef WIN_MAC
2209   CharPtr  p;
2210 #endif
2211 
2212   if (t != NULL && path != NULL && *path != '\0') {
2213     len = TextLength (t);
2214     if (len > 0) {
2215 #ifdef WIN_MAC
2216       fp = FileOpen (path, "r");
2217       if (fp != NULL) {
2218         FileClose (fp);
2219       } else {
2220         FileCreate (path, "TEXT", "ttxt");
2221       }
2222 #endif
2223       fp = FileOpen (path, "w");
2224       if (fp != NULL) {
2225         str = MemNew (sizeof (char) * (len + 3));
2226         if (str != NULL) {
2227           GetTitle (t, str, len + 1);
2228 #ifdef WIN_MAC
2229           p = str;
2230           while (*p) {
2231             if (*p == '\r' || *p == '\n') {
2232               *p = '\n';
2233             }
2234             p++;
2235           }
2236 #endif
2237           FileWrite (str, sizeof (char), len, fp);
2238           MemFree (str);
2239         }
2240         FileClose (fp);
2241       }
2242     }
2243   }
2244 }
2245 
FileToClipboard(CharPtr path)2246 extern void FileToClipboard (CharPtr path)
2247 
2248 {
2249   FILE     *fp;
2250   Int8     len;
2251   Int4     max;
2252   CharPtr  str;
2253 #ifdef WIN_MAC
2254   CharPtr  p;
2255 #endif
2256 #if (defined(OS_DOS) || defined (OS_NT))
2257   CharPtr  p;
2258   CharPtr  q;
2259 #endif
2260 
2261   if (path != NULL && *path != '\0') {
2262     len = FileLength (path);
2263 #ifdef WIN_MOTIF
2264     max = INT4_MAX;
2265 #else
2266     max = (Int4) INT2_MAX;
2267 #endif
2268     if (len > 0 && len < max - 4) {
2269       str = MemNew (sizeof (char) * ((size_t)len + 3));
2270       if (str != NULL) {
2271         fp = FileOpen (path, "r");
2272         if (fp != NULL) {
2273           FileRead (str, sizeof (char), (size_t) len, fp);
2274 #if (defined(OS_DOS) || defined (OS_NT))
2275           p = str;
2276           q = str;
2277           while (*p) {
2278             if (*p == '\r') {
2279               p++;
2280             } else {
2281               *q = *p;
2282               p++;
2283               q++;
2284             }
2285           }
2286           *q = '\0';
2287 #endif
2288 #ifdef WIN_MAC
2289           p = str;
2290           while (*p) {
2291             if (*p == '\r' || *p == '\n') {
2292               *p = '\015';
2293             }
2294             p++;
2295           }
2296 #endif
2297           FileClose (fp);
2298           Nlm_StringToClipboard (str);
2299         }
2300         MemFree (str);
2301       }
2302     }
2303   }
2304 }
2305 
2306 typedef struct textviewform {
2307   FORM_MESSAGE_BLOCK
2308 
2309   DoC              doc;
2310   TexT             text;
2311 
2312   TexT             find;
2313 } TextViewForm, PNTR TextViewFormPtr;
2314 
2315 static ParData txtParFmt = {FALSE, FALSE, FALSE, FALSE, TRUE, 0, 0};
2316 static ColData txtColFmt = {0, 0, 80, 0, NULL, 'l', FALSE, FALSE, FALSE, FALSE, TRUE};
2317 
ResizeTextViewer(WindoW w)2318 static void ResizeTextViewer (WindoW w)
2319 
2320 {
2321   Int2             height;
2322   RecT             r;
2323   RecT             s;
2324   TextViewFormPtr  tfp;
2325   Int2             width;
2326 
2327   tfp = (TextViewFormPtr) GetObjectExtra (w);
2328   if (tfp != NULL) {
2329     WatchCursor ();
2330     ObjectRect (w, &r);
2331     width = r.right - r.left;
2332     height = r.bottom - r.top;
2333     if (tfp->doc != NULL) {
2334       GetPosition (tfp->doc, &s);
2335       s.right = width - s.left;
2336       s.bottom = height - s.left;
2337       SetPosition (tfp->doc, &s);
2338       AdjustPrnt (tfp->doc, &s, FALSE);
2339       txtColFmt.pixWidth = screenRect.right - screenRect.left;
2340       txtColFmt.pixInset = 8;
2341       if (Visible (tfp->doc) && AllParentsVisible (tfp->doc)) {
2342         UpdateDocument (tfp->doc, 0, 0);
2343       }
2344     }
2345     if (tfp->text != NULL) {
2346       GetPosition (tfp->text, &s);
2347       s.right = width - s.left;
2348       s.bottom = height - s.left;
2349       SetPosition (tfp->text, &s);
2350       AdjustPrnt (tfp->text, &s, FALSE);
2351     }
2352     ArrowCursor ();
2353     Update ();
2354   }
2355 }
2356 
ExportTextViewForm(ForM f,CharPtr filename)2357 static Boolean ExportTextViewForm (ForM f, CharPtr filename)
2358 
2359 {
2360   FILE             *fp;
2361   Char             path [PATH_MAX];
2362   TextViewFormPtr  tfp;
2363 
2364   tfp = (TextViewFormPtr) GetObjectExtra (f);
2365   if (tfp != NULL && (tfp->doc != NULL || tfp->text != NULL)) {
2366     path [0] = '\0';
2367     StringNCpy_0 (path, filename, sizeof (path));
2368     if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
2369 #ifdef WIN_MAC
2370       fp = FileOpen (path, "r");
2371       if (fp != NULL) {
2372         FileClose (fp);
2373       } else {
2374         FileCreate (path, "TEXT", "ttxt");
2375       }
2376 #endif
2377       if (tfp->doc != NULL) {
2378         fp = FileOpen (path, "w");
2379         if (fp != NULL) {
2380           SaveDocument (tfp->doc, fp);
2381           FileClose (fp);
2382           return TRUE;
2383         }
2384       } else if (tfp->text != NULL) {
2385         ScrollTextToFile (tfp->text, path);
2386         return TRUE;
2387       }
2388     }
2389   }
2390   return FALSE;
2391 }
2392 
PrintTextViewForm(Pointer formDataPtr)2393 static void LIBCALL PrintTextViewForm (Pointer formDataPtr)
2394 
2395 {
2396   TextViewFormPtr  tfp;
2397 
2398   tfp = (TextViewFormPtr) formDataPtr;
2399   if (tfp != NULL && tfp->doc != NULL) {
2400     PrintDocument (tfp->doc);
2401   }
2402 }
2403 
TextViewFormMessage(ForM f,Int2 mssg)2404 static void TextViewFormMessage (ForM f, Int2 mssg)
2405 
2406 {
2407   TextViewFormPtr  tfp;
2408 
2409   tfp = (TextViewFormPtr) GetObjectExtra (f);
2410   if (tfp != NULL) {
2411     switch (mssg) {
2412       case VIB_MSG_EXPORT :
2413         ExportTextViewForm (f, NULL);
2414         break;
2415       case VIB_MSG_CLOSE :
2416         Remove (f);
2417         break;
2418       case VIB_MSG_PRINT :
2419         PrintTextViewForm (tfp);
2420         break;
2421       case VIB_MSG_CUT :
2422         StdCutTextProc (NULL);
2423         break;
2424       case VIB_MSG_COPY :
2425         StdCopyTextProc (NULL);
2426         break;
2427       case VIB_MSG_PASTE :
2428         StdPasteTextProc (NULL);
2429         break;
2430       case VIB_MSG_DELETE :
2431         StdDeleteTextProc (NULL);
2432         break;
2433       default :
2434         if (tfp->appmessage != NULL) {
2435           tfp->appmessage (f, mssg);
2436         }
2437         break;
2438     }
2439   }
2440 }
2441 
2442 
FindInGeneralText(ButtoN b)2443 static void FindInGeneralText (ButtoN b)
2444 
2445 {
2446   Int2             actual;
2447   Char             buf [1030];
2448   Char             ch;
2449   Int2             cnt;
2450   Int8             cntr;
2451   Int2             first;
2452   FILE             *fp;
2453   Char             lastch;
2454   Int4             line = 0;
2455   ValNodePtr       matches;
2456   Int2             next;
2457   Int2             offset = 0;
2458   Char             path [PATH_MAX];
2459   CharPtr          ptr;
2460   Int4             state;
2461   CharPtr          str;
2462   TextFsaPtr       tbl;
2463   TextViewFormPtr  tfp;
2464   Int4             max;
2465 
2466   tfp = (TextViewFormPtr) GetObjectExtra (b);
2467   if (tfp == NULL) return;
2468   if (tfp->doc != NULL) {
2469     GetOffset (tfp->doc, NULL, &offset);
2470   } else if (tfp->text != NULL) {
2471     GetOffset (tfp->text, NULL, &offset);
2472   }
2473   first = -1;
2474   next = -1;
2475   max = INT2_MAX;
2476 
2477   str = SaveStringFromText (tfp->find);
2478 
2479   if (StringDoesHaveText (str)) {
2480     TmpNam (path);
2481     if (ExportForm (tfp->form, path)) {
2482       tbl = TextFsaNew ();
2483       if (tbl != NULL) {
2484         TextFsaAdd (tbl, str);
2485         fp = FileOpen (path, "r");
2486         if (fp != NULL) {
2487           line = 0;
2488           state = 0;
2489           cntr = FileLength (path);
2490           cnt = (Int2) MIN (cntr, 1024L);
2491           lastch = '\0';
2492           while (cnt > 0 && cntr > 0 && line <= max &&
2493                  ((next == -1 && offset > first) || first == -1)) {
2494             actual = (Int2) FileRead (buf, 1, cnt, fp);
2495             if (actual > 0) {
2496               cnt = actual;
2497               buf [cnt] = '\0';
2498               ptr = buf;
2499               ch = *ptr;
2500               while (ch != '\0') {
2501                 if (ch == '\n' || ch == '\r') {
2502                   if (ch == '\n' && lastch == '\r') {
2503                     /* do not increment line */
2504                   } else if (ch == '\r' && lastch == '\n') {
2505                     /* do not increment line */
2506                   } else {
2507                     line++;
2508                   }
2509                 }
2510                 state = TextFsaNext (tbl, state, ch, &matches);
2511                 if (matches != NULL) {
2512                   if (first == -1) {
2513                     first = line;
2514                   }
2515                   if (next == -1 && line > offset) {
2516                     next = line;
2517                   }
2518                 }
2519                 lastch = ch;
2520                 ptr++;
2521                 ch = *ptr;
2522               }
2523               cntr -= cnt;
2524               cnt = (Int2) MIN (cntr, 1024L);
2525             } else {
2526               cnt = 0;
2527               cntr = 0;
2528             }
2529           }
2530         }
2531         FileClose (fp);
2532       }
2533       TextFsaFree (tbl);
2534     }
2535     FileRemove (path);
2536   }
2537   MemFree (str);
2538   if (line > max) {
2539     Message (MSG_ERROR, "Too many lines for search");
2540   }
2541 
2542   if (next >= 0) {
2543     offset = next;
2544   } else if (first >= 0) {
2545     offset = first;
2546   } else return;
2547   if (tfp->doc != NULL) {
2548     SetOffset (tfp->doc, 0, offset);
2549     Update ();
2550   } else if (tfp->text != NULL) {
2551     SetOffset (tfp->text, 0, offset);
2552     Update ();
2553   }
2554 }
2555 
2556 typedef struct repopulateviewer
2557 {
2558   Nlm_RepopulateViewer   repopulate_func;
2559   Pointer                repopulate_data;
2560   Nlm_RepopulateDataFree free_data_func;
2561   TextViewFormPtr        tfp;
2562   FonT                   fnt;
2563 } RepopulateViewerData, PNTR RepopulateViewerPtr;
2564 
CleanupRepopulateViewer(Nlm_GraphiC g,Nlm_VoidPtr data)2565 static void CleanupRepopulateViewer (Nlm_GraphiC g, Nlm_VoidPtr data)
2566 {
2567   RepopulateViewerPtr rp;
2568 
2569   rp = (RepopulateViewerPtr) data;
2570   if (rp != NULL && rp->free_data_func != NULL)
2571   {
2572     (rp->free_data_func)(rp->repopulate_data);
2573   }
2574 
2575   StdCleanupExtraProc (g, data);
2576 }
2577 
RepopulateViewer(ButtoN b)2578 static void RepopulateViewer (ButtoN b)
2579 {
2580   RepopulateViewerPtr rp;
2581   CharPtr             new_path;
2582 
2583   rp = (RepopulateViewerPtr) GetObjectExtra (b);
2584 
2585   if (rp == NULL || rp->repopulate_func == NULL)
2586   {
2587     return;
2588   }
2589 
2590   new_path = (rp->repopulate_func) (rp->repopulate_data);
2591   if (new_path == NULL)
2592   {
2593     return;
2594   }
2595 
2596   if (rp->tfp->text != NULL)
2597   {
2598     FileToScrollText (rp->tfp->text, new_path);
2599   }
2600   else if (rp->tfp->doc != NULL)
2601   {
2602     txtColFmt.pixWidth = screenRect.right - screenRect.left;
2603     txtColFmt.pixInset = 8;
2604     DisplayFancy (rp->tfp->doc, new_path, &txtParFmt, &txtColFmt, rp->fnt, 0);
2605   }
2606   FileRemove (new_path);
2607   new_path = MemFree (new_path);
2608 }
2609 
2610 static void
LaunchGeneralTextViewerEx(CharPtr path,CharPtr title,Boolean useScrollText,Nlm_RepopulateViewer repopulate_func,Pointer repopulate_data,Nlm_RepopulateDataFree free_data_func)2611 LaunchGeneralTextViewerEx
2612 (CharPtr path,
2613  CharPtr title,
2614  Boolean useScrollText,
2615  Nlm_RepopulateViewer   repopulate_func,
2616  Pointer                repopulate_data,
2617  Nlm_RepopulateDataFree free_data_func)
2618 
2619 {
2620   ButtoN              b;
2621   FonT                fnt;
2622   GrouP               g;
2623   Int2                pixheight;
2624   Int2                pixwidth;
2625   StdEditorProcsPtr   sepp;
2626   TextViewFormPtr     tfp;
2627   TextViewProcsPtr    tvpp;
2628   RepopulateViewerPtr rp;
2629   WindoW              w;
2630 #ifndef WIN_MAC
2631   MenU                m;
2632 #endif
2633 
2634   tfp = (TextViewFormPtr) MemNew (sizeof (TextViewForm));
2635   if (tfp == NULL) return;
2636 
2637   w = DocumentWindow (-50, -33, -10, -10, title, StdCloseWindowProc, ResizeTextViewer);
2638   SetObjectExtra (w, tfp, StdCleanupFormProc);
2639   tfp->form = (ForM) w;
2640   tfp->exportform = ExportTextViewForm;
2641   tfp->formmessage = TextViewFormMessage;
2642 
2643   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
2644   if (sepp != NULL) {
2645     SetActivate (w, sepp->activateForm);
2646     tfp->appmessage = sepp->handleMessages;
2647   }
2648 
2649   fnt = programFont;
2650   pixwidth = 35 * stdCharWidth + 17;
2651   pixheight = 20 * stdLineHeight;
2652 
2653   tvpp = (TextViewProcsPtr) GetAppProperty ("TextDisplayForm");
2654   if (tvpp != NULL) {
2655     pixwidth = MAX (pixwidth, tvpp->minPixelWidth);
2656     pixheight = MAX (pixheight, tvpp->minPixelHeight);
2657     if (tvpp->displayFont != NULL) {
2658       fnt = tvpp->displayFont;
2659     }
2660     if (tvpp->activateForm != NULL) {
2661       SetActivate (w, tvpp->activateForm);
2662     }
2663   }
2664 
2665 #ifndef WIN_MAC
2666   m = PulldownMenu (w, "File");
2667   FormCommandItem (m, "Export...", (BaseFormPtr) tfp, VIB_MSG_EXPORT);
2668   SeparatorItem (m);
2669   FormCommandItem (m, "Close", (BaseFormPtr) tfp, VIB_MSG_CLOSE);
2670   if (tvpp != NULL && tvpp->useScrollText) {
2671     m = PulldownMenu (w, "Edit");
2672     FormCommandItem (m, CUT_MENU_ITEM, (BaseFormPtr) tfp, VIB_MSG_CUT);
2673     FormCommandItem (m, COPY_MENU_ITEM, (BaseFormPtr) tfp, VIB_MSG_COPY);
2674     FormCommandItem (m, PASTE_MENU_ITEM, (BaseFormPtr) tfp, VIB_MSG_PASTE);
2675     FormCommandItem (m, CLEAR_MENU_ITEM, (BaseFormPtr) tfp, VIB_MSG_DELETE);
2676   }
2677 #endif
2678 
2679 #ifdef WIN_MAC
2680   if (useScrollText) {
2681     if (FileLength (path) > 32767) {
2682       /* text edit window has maximum length on Mac */
2683       useScrollText = FALSE;
2684     }
2685   }
2686 #endif
2687 
2688   /* right now Find button is only in indexer Sequin */
2689   if (useScrollText) {
2690     g = HiddenGroup (w, 5, 0, NULL);
2691     b = PushButton (g, "Find", FindInGeneralText);
2692     SetObjectExtra (b, tfp, NULL);
2693     tfp->find = DialogText (g, "", 10, NULL);
2694     if (repopulate_func != NULL)
2695     {
2696       rp = (RepopulateViewerPtr) MemNew (sizeof (RepopulateViewerData));
2697       if (rp != NULL)
2698       {
2699         rp->repopulate_func = repopulate_func;
2700         rp->repopulate_data = repopulate_data;
2701         rp->free_data_func = free_data_func;
2702         rp->tfp = tfp;
2703         rp->fnt = fnt;
2704         b = PushButton (g, "Repopulate", RepopulateViewer);
2705         SetObjectExtra (b, rp, CleanupRepopulateViewer);
2706       }
2707     }
2708   }
2709 
2710   if (useScrollText) {
2711     tfp->text = ScrollText (w, (pixwidth + stdCharWidth - 1) / stdCharWidth,
2712                             (pixheight + stdLineHeight - 1) / stdLineHeight,
2713                             fnt, FALSE, NULL);
2714     SetObjectExtra (tfp->text, tfp, NULL);
2715     RealizeWindow (w);
2716     if (! FileToScrollText (tfp->text, path)) {
2717       /* SetTitle (tfp->text, "(Text is too large to be displayed in this control.)"); */
2718       Remove (w);
2719       LaunchGeneralTextViewerEx (path, title, FALSE,
2720                                  repopulate_func, repopulate_data, free_data_func);
2721       return;
2722     }
2723   } else {
2724     tfp->doc = DocumentPanel (w, pixwidth, pixheight);
2725     SetObjectExtra (tfp->doc, tfp, NULL);
2726     RealizeWindow (w);
2727     txtColFmt.pixWidth = screenRect.right - screenRect.left;
2728     txtColFmt.pixInset = 8;
2729     DisplayFancy (tfp->doc, path, &txtParFmt, &txtColFmt, fnt, 0);
2730     /* document.c: SaveTableItem does not strip preceeding tabs if tabCount is 0 */
2731   }
2732   Show (w);
2733   Select (w);
2734   Update ();
2735 }
2736 
LaunchGeneralTextViewerWithRepopulate(CharPtr path,CharPtr title,Nlm_RepopulateViewer repopulate_func,Pointer repopulate_data,Nlm_RepopulateDataFree free_data_func)2737 extern void LaunchGeneralTextViewerWithRepopulate
2738 (CharPtr                path,
2739  CharPtr                title,
2740  Nlm_RepopulateViewer   repopulate_func,
2741  Pointer                repopulate_data,
2742  Nlm_RepopulateDataFree free_data_func)
2743 {
2744   TextViewProcsPtr tvpp;
2745 
2746   tvpp = (TextViewProcsPtr) GetAppProperty ("TextDisplayForm");
2747   if (tvpp != NULL && tvpp->useScrollText) {
2748     LaunchGeneralTextViewerEx (path, title, TRUE,
2749                                repopulate_func, repopulate_data, free_data_func);
2750   } else {
2751     LaunchGeneralTextViewerEx (path, title, FALSE,
2752                                repopulate_func, repopulate_data, free_data_func);
2753   }
2754 }
2755 
LaunchGeneralTextViewer(CharPtr path,CharPtr title)2756 extern void LaunchGeneralTextViewer (CharPtr path, CharPtr title)
2757 
2758 {
2759   TextViewProcsPtr tvpp;
2760 
2761   tvpp = (TextViewProcsPtr) GetAppProperty ("TextDisplayForm");
2762   if (tvpp != NULL && tvpp->useScrollText) {
2763     LaunchGeneralTextViewerEx (path, title, TRUE, NULL, NULL, NULL);
2764   } else {
2765     LaunchGeneralTextViewerEx (path, title, FALSE, NULL, NULL, NULL);
2766   }
2767 }
2768 
LaunchAsnTextViewer(Pointer from,AsnWriteFunc writefunc,CharPtr title)2769 extern void LaunchAsnTextViewer (Pointer from, AsnWriteFunc writefunc, CharPtr title)
2770 
2771 {
2772   AsnIoPtr  aip;
2773   Char      path [PATH_MAX];
2774 
2775   if (from == NULL || writefunc == NULL) return;
2776   if (StringHasNoText (title)) {
2777     title = "General ASN.1 Text Viewer";
2778   }
2779 
2780   TmpNam (path);
2781   aip = AsnIoOpen (path, "w");
2782   if (aip != NULL) {
2783     (*writefunc) (from, aip, NULL);
2784     AsnIoClose (aip);
2785     LaunchGeneralTextViewer (path, title);
2786   }
2787   FileRemove (path);
2788 }
2789 
2790 #ifndef WIN_MAC
CreateStdEditorFormMenus(WindoW w)2791 extern void CreateStdEditorFormMenus (WindoW w)
2792 
2793 {
2794   BaseFormPtr   bfp;
2795   MenU          m;
2796 
2797   bfp = (BaseFormPtr) GetObjectExtra (w);
2798   if (bfp != NULL) {
2799     m = PulldownMenu (w, "File");
2800     if (bfp->importform != NULL || bfp->exportform != NULL) {
2801       if (bfp->importform != NULL) {
2802         FormCommandItem (m, "Import...", bfp, VIB_MSG_IMPORT);
2803       }
2804       if (bfp->exportform != NULL) {
2805         FormCommandItem (m, "Export...", bfp, VIB_MSG_EXPORT);
2806       }
2807       SeparatorItem (m);
2808     }
2809     FormCommandItem (m, "Close", bfp, VIB_MSG_CLOSE);
2810     m = PulldownMenu (w, "Edit");
2811     FormCommandItem (m, CUT_MENU_ITEM, bfp, VIB_MSG_CUT);
2812     FormCommandItem (m, COPY_MENU_ITEM, bfp, VIB_MSG_COPY);
2813     FormCommandItem (m, PASTE_MENU_ITEM, bfp, VIB_MSG_PASTE);
2814     FormCommandItem (m, CLEAR_MENU_ITEM, bfp, VIB_MSG_DELETE);
2815   }
2816 }
2817 #endif
2818 
DlgutilGetLowestStackSeqEntry(GatherContextPtr gcp)2819 static Boolean DlgutilGetLowestStackSeqEntry (GatherContextPtr gcp)
2820 
2821 {
2822   BaseFormPtr  bfp;
2823   Int2         i;
2824 
2825   if (gcp == NULL) return TRUE;
2826   bfp = (BaseFormPtr) gcp->userdata;
2827   if (bfp == NULL) return TRUE;
2828   if (gcp->gatherstack != NULL && gcp->numstack > 0) {
2829     for (i = 0; i < gcp->numstack; i++) {
2830       if (gcp->gatherstack [i].itemtype == OBJ_BIOSEQ ||
2831           gcp->gatherstack [i].itemtype == OBJ_BIOSEQSET) {
2832         bfp->input_itemID = gcp->gatherstack [i].itemID;
2833         bfp->input_itemtype = gcp->gatherstack [i].itemtype;
2834       }
2835     }
2836   }
2837   return FALSE;
2838 }
2839 
SetClosestParentIfDuplicating(BaseFormPtr bfp)2840 extern Boolean SetClosestParentIfDuplicating (BaseFormPtr bfp)
2841 
2842 {
2843   Uint4              itemID;
2844   Uint2              itemtype;
2845   StdEditorProcsPtr  sepp;
2846 
2847   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
2848   if (bfp == NULL || sepp == NULL || (! sepp->duplicateExisting)) return FALSE;
2849   itemID = bfp->input_itemID;
2850   itemtype = bfp->input_itemtype;
2851   GatherItem (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype,
2852               (Pointer) bfp, DlgutilGetLowestStackSeqEntry);
2853   if (itemID == bfp->input_itemID && itemtype == bfp->input_itemtype) {
2854     return FALSE;
2855   }
2856   return TRUE;
2857 }
2858 
2859 /*****************************************************************************
2860 *
2861 *   Bond and Point SeqLoc dialogs
2862 *
2863 *****************************************************************************/
2864 
2865 typedef struct pointpage {
2866   DIALOG_MESSAGE_BLOCK
2867   TexT               point;
2868   Int2               count;
2869   SeqEntryPtr        PNTR bsptr;
2870   EnumFieldAssoc     PNTR alist;
2871   PopuP              strand;
2872   PopuP              seqIdx;
2873   Boolean            nucsOK;
2874   Boolean            protsOK;
2875   Boolean            showIdTags;
2876 } PointPage, PNTR PointPagePtr;
2877 
2878 typedef struct bondpage {
2879   DIALOG_MESSAGE_BLOCK
2880   DialoG             pointA;
2881   DialoG             pointB;
2882 } BondPage, PNTR BondPagePtr;
2883 
FillInPointProducts(SeqEntryPtr sep,Pointer mydata,Int4 index,Int2 indent)2884 static void FillInPointProducts (SeqEntryPtr sep, Pointer mydata,
2885                                  Int4 index, Int2 indent)
2886 
2887 {
2888   BioseqPtr     bsp;
2889   PointPagePtr  ppp;
2890 
2891   if (sep != NULL && mydata != NULL && sep->choice == 1) {
2892     ppp = (PointPagePtr) mydata;
2893     bsp = (BioseqPtr) sep->data.ptrvalue;
2894     if (bsp != NULL) {
2895       if ((ppp->nucsOK && ISA_na (bsp->mol)) ||
2896           (ppp->protsOK && ISA_aa (bsp->mol))) {
2897         ppp->count++;
2898         ppp->bsptr [ppp->count] = sep;
2899       }
2900     }
2901   }
2902 }
2903 
ENUM_ALIST(strand_alist)2904 static ENUM_ALIST(strand_alist)
2905 {" ",             Seq_strand_unknown},  /* 0 */
2906 {"Plus",          Seq_strand_plus},     /* 1 */
2907 {"Minus",         Seq_strand_minus},    /* 2 */
2908 /*
2909 {"Both",          Seq_strand_both},
2910 {"Reverse",       Seq_strand_both_rev},
2911 */
2912 {"Other",         Seq_strand_other},    /* 255 */
2913 END_ENUM_ALIST
2914 
2915 static void SeqPntPtrToPointPage (DialoG d, Pointer data)
2916 
2917 
2918 {
2919   BioseqPtr     bsp;
2920   Int2          j;
2921   PointPagePtr  ppp;
2922   SeqEntryPtr   sep;
2923   Int2          seq;
2924   SeqPntPtr     spp;
2925   Char          str [16];
2926   Uint1         strand;
2927 
2928   ppp = (PointPagePtr) GetObjectExtra (d);
2929   if (ppp == NULL) return;
2930   spp = (SeqPntPtr) data;
2931   if (spp != NULL) {
2932     sprintf (str, "%ld", (long) (spp->point + 1));
2933     SafeSetTitle (ppp->point, str);
2934     seq = 0;
2935     strand = 0;
2936     bsp = BioseqFind (spp->id);
2937     if (bsp != NULL) {
2938       strand = spp->strand;
2939       if (strand > Seq_strand_both_rev && strand != Seq_strand_other) {
2940         strand = Seq_strand_unknown;
2941       }
2942       if (ppp->bsptr != NULL) {
2943         for (j = 1; j <= ppp->count && seq == 0; j++) {
2944           sep = ppp->bsptr [j];
2945           if (sep != NULL && sep->choice == 1) {
2946             if (bsp == (BioseqPtr) sep->data.ptrvalue) {
2947               seq = j;
2948             }
2949           }
2950         }
2951       }
2952     }
2953     SetEnumPopup (ppp->strand, strand_alist, (UIEnum) strand);
2954     SetEnumPopup (ppp->seqIdx, ppp->alist, (UIEnum) seq);
2955   } else {
2956     SafeSetTitle (ppp->point, "");
2957     SafeSetValue (ppp->strand, 0);
2958     SafeSetValue (ppp->seqIdx, 0);
2959   }
2960 }
2961 
PointPageToSeqPntPtr(DialoG d)2962 static Pointer PointPageToSeqPntPtr (DialoG d)
2963 
2964 {
2965   BioseqPtr     bsp;
2966   PointPagePtr  ppp;
2967   SeqEntryPtr   sep;
2968   UIEnum        seq;
2969   SeqPntPtr     spp;
2970   Char          str [16];
2971   UIEnum        strand;
2972   Int4          val;
2973 
2974   ppp = (PointPagePtr) GetObjectExtra (d);
2975   if (ppp == NULL) return NULL;
2976   spp = NULL;
2977   GetTitle (ppp->point, str, sizeof (str) - 1);
2978   if (StrToLong (str, &val) && val > 0) {
2979     if (GetEnumPopup (ppp->seqIdx, ppp->alist, &seq) &&
2980         seq > 0 && seq <= ppp->count) {
2981       spp = SeqPntNew ();
2982       if (spp != NULL) {
2983         spp->point = val - 1;
2984         if (GetEnumPopup (ppp->strand, strand_alist, &strand)) {
2985           spp->strand = (Uint1) strand;
2986         }
2987         sep = ppp->bsptr [(Int2) seq];
2988         if (sep != NULL && sep->choice == 1) {
2989           bsp = (BioseqPtr) sep->data.ptrvalue;
2990           if (bsp != NULL) {
2991             spp->id = SeqIdStripLocus (SeqIdDup (SeqIdFindBest (bsp->id, 0)));
2992           }
2993         }
2994       }
2995     }
2996   }
2997   return (Pointer) spp;
2998 }
2999 
PointEditorMessage(DialoG d,Int2 mssg)3000 static void PointEditorMessage (DialoG d, Int2 mssg)
3001 
3002 {
3003   PointPagePtr  ppp;
3004 
3005   ppp = (PointPagePtr) GetObjectExtra (d);
3006   if (ppp != NULL) {
3007     if (mssg == VIB_MSG_INIT) {
3008       SeqPntPtrToPointPage (d, NULL);
3009     } else if (mssg == VIB_MSG_ENTER) {
3010       Select (ppp->point);
3011     } else if (mssg == VIB_MSG_RESET) {
3012     }
3013   }
3014 }
3015 
CleanupPointPage(GraphiC g,VoidPtr data)3016 static void CleanupPointPage (GraphiC g, VoidPtr data)
3017 
3018 {
3019   Int2          j;
3020   PointPagePtr  ppp;
3021 
3022   ppp = (PointPagePtr) data;
3023   if (ppp != NULL) {
3024     MemFree (ppp->bsptr);
3025     if (ppp->alist != NULL) {
3026       for (j = 0; j <= ppp->count + 1; j++) {
3027         MemFree (ppp->alist [j].name);
3028       }
3029     }
3030     MemFree (ppp->alist);
3031   }
3032   MemFree (data);
3033 }
3034 
CreatePointEditorDialog(GrouP h,CharPtr title,SeqEntryPtr sep,Boolean nucsOK,Boolean protsOK)3035 static DialoG CreatePointEditorDialog (GrouP h, CharPtr title, SeqEntryPtr sep,
3036                                        Boolean nucsOK, Boolean protsOK)
3037 
3038 {
3039   BioseqPtr     bsp;
3040   Int4          count;
3041   GrouP         f;
3042   Int2          j;
3043   GrouP         m;
3044   GrouP         p;
3045   PointPagePtr  ppp;
3046   CharPtr       ptr;
3047   GrouP         s;
3048   Boolean       showIdTags;
3049   SeqIdPtr      sip;
3050   Char          str [128];
3051 
3052   p = HiddenGroup (h, 1, 0, NULL);
3053   SetGroupSpacing (p, 10, 10);
3054 
3055   ppp = (PointPagePtr) MemNew (sizeof (PointPage));
3056   if (ppp != NULL) {
3057 
3058     SetObjectExtra (p, ppp, CleanupPointPage);
3059     ppp->dialog = (DialoG) p;
3060     ppp->todialog = SeqPntPtrToPointPage;
3061     ppp->fromdialog = PointPageToSeqPntPtr;
3062     ppp->dialogmessage = PointEditorMessage;
3063     ppp->testdialog = NULL;
3064     ppp->importdialog = NULL;
3065     ppp->exportdialog = NULL;
3066 
3067     if (title != NULL && title [0] != '\0') {
3068       s = NormalGroup (p, 0, -2, title, systemFont, NULL);
3069     } else {
3070       s = HiddenGroup (p, 0, -2, NULL);
3071     }
3072     m = HiddenGroup (s, -1, 0, NULL);
3073     /*
3074     SetGroupSpacing (m, 10, 10);
3075     */
3076 
3077     ppp->nucsOK = nucsOK;
3078     ppp->protsOK = protsOK;
3079     ppp->showIdTags = FALSE;
3080     ppp->count = 0;
3081 
3082     if (sep != NULL) {
3083       count = SeqEntryCount (sep);
3084       count += 4;
3085       ppp->bsptr = MemNew (sizeof (BioseqPtr) * (size_t) count);
3086       ppp->alist = MemNew (sizeof (EnumFieldAssoc) * (size_t) count);
3087       ppp->count = 0;
3088 
3089       if (ppp->bsptr != NULL && ppp->alist != NULL) {
3090         SeqEntryExplore (sep, (Pointer) ppp, FillInPointProducts);
3091         j = 0;
3092         ppp->alist [j].name = StringSave ("     ");
3093         ppp->alist [j].value = (UIEnum) 0;
3094         for (j = 1; j <= ppp->count; j++) {
3095           sep = ppp->bsptr [j];
3096           if (sep != NULL && sep->choice == 1 && sep->data.ptrvalue != NULL) {
3097             bsp = (BioseqPtr) sep->data.ptrvalue;
3098             sip = SeqIdFindWorst (bsp->id);
3099             SeqIdWrite (sip, str, PRINTID_REPORT, sizeof (str));
3100             ptr = StringChr (str, '|');
3101             showIdTags = FALSE;
3102             if (ptr == NULL) {
3103               ptr = str;
3104             } else if (showIdTags) {
3105               ptr = str;
3106             } else {
3107               ptr++;
3108             }
3109             ppp->alist [j].name = StringSave (ptr);
3110             ppp->alist [j].value = (UIEnum) j;
3111           }
3112         }
3113         j = ppp->count + 1;
3114         ppp->alist [j].name = NULL;
3115         ppp->alist [j].value = (UIEnum) 0;
3116       }
3117 
3118     } else {
3119       ppp->alist = MemNew (sizeof (EnumFieldAssoc) * (size_t) 4);
3120       if (ppp->alist != NULL) {
3121         j = 0;
3122         ppp->alist [j].name = StringSave ("     ");
3123         ppp->alist [j].value = (UIEnum) 0;
3124         j = 1;
3125         ppp->alist [j].name = NULL;
3126         ppp->alist [j].value = (UIEnum) 0;
3127 
3128       }
3129     }
3130 
3131     f = HiddenGroup (m, 6, 0, NULL);
3132     /*StaticPrompt (f, "Point", 0, dialogTextHeight, programFont, 'l');*/
3133     ppp->point = DialogText (f, "", 5, NULL);
3134     if (nucsOK) {
3135       /*StaticPrompt (f, "Strand", 0, popupMenuHeight, programFont, 'c');*/
3136       ppp->strand = PopupList (f, TRUE, NULL);
3137       InitEnumPopup (ppp->strand, strand_alist, NULL);
3138     }
3139     /*StaticPrompt (f, "SeqID", 0, popupMenuHeight, programFont, 'l');*/
3140     ppp->seqIdx = PopupList (f, TRUE, NULL);
3141     InitEnumPopup (ppp->seqIdx, ppp->alist, NULL);
3142   }
3143 
3144   return (DialoG) p;
3145 }
3146 
SeqLocPtrToBondPage(DialoG d,Pointer data)3147 static void SeqLocPtrToBondPage (DialoG d, Pointer data)
3148 
3149 
3150 {
3151   BondPagePtr  bpp;
3152   SeqBondPtr   sbp;
3153   SeqIdPtr     sip;
3154   SeqLocPtr    slp;
3155   SeqPnt       sqp;
3156 
3157   bpp = (BondPagePtr) GetObjectExtra (d);
3158   if (bpp == NULL) return;
3159   slp = (SeqLocPtr) data;
3160   if (slp != NULL) {
3161     if (slp->choice == SEQLOC_BOND) {
3162       sbp = (SeqBondPtr) slp->data.ptrvalue;
3163       if (sbp != NULL) {
3164         PointerToDialog (bpp->pointA, (Pointer) sbp->a);
3165         PointerToDialog (bpp->pointB, (Pointer) sbp->b);
3166       }
3167     } else {
3168       sip = SeqLocId (slp);
3169       if (sip != NULL) {
3170         sqp.strand = SeqLocStrand (slp);
3171         sqp.id = sip;
3172         sqp.point = SeqLocStart (slp);
3173         PointerToDialog (bpp->pointA, (Pointer) &sqp);
3174         sqp.point = SeqLocStop (slp);
3175         PointerToDialog (bpp->pointB, (Pointer) &sqp);
3176       }
3177     }
3178   }
3179 }
3180 
BondPageToSeqLocPtr(DialoG d)3181 static Pointer BondPageToSeqLocPtr (DialoG d)
3182 
3183 {
3184   BondPagePtr  bpp;
3185   SeqBondPtr   sbp;
3186   SeqLocPtr    slp;
3187 
3188   bpp = (BondPagePtr) GetObjectExtra (d);
3189   if (bpp == NULL) return NULL;
3190   slp = NULL;
3191   sbp = SeqBondNew ();
3192   if (sbp != NULL) {
3193     slp = ValNodeNew (NULL);
3194     if (slp != NULL) {
3195       slp->choice = SEQLOC_BOND;
3196       slp->data.ptrvalue = (Pointer) sbp;
3197       sbp->a = DialogToPointer (bpp->pointA);
3198       sbp->b = DialogToPointer (bpp->pointB);
3199     } else {
3200       SeqBondFree (sbp);
3201     }
3202   }
3203   return (Pointer) slp;
3204 }
3205 
BondEditorMessage(DialoG d,Int2 mssg)3206 static void BondEditorMessage (DialoG d, Int2 mssg)
3207 
3208 {
3209   BondPagePtr  bpp;
3210 
3211   bpp = (BondPagePtr) GetObjectExtra (d);
3212   if (bpp != NULL) {
3213     if (mssg == VIB_MSG_INIT) {
3214       SeqLocPtrToBondPage (d, NULL);
3215     } else if (mssg == VIB_MSG_ENTER) {
3216       SendMessageToDialog (bpp->pointA, VIB_MSG_ENTER);
3217     } else if (mssg == VIB_MSG_RESET) {
3218     }
3219   }
3220 }
3221 
3222 extern DialoG CreateBondEditorDialog (GrouP h, CharPtr title, SeqEntryPtr sep);
3223 
CreateBondEditorDialog(GrouP h,CharPtr title,SeqEntryPtr sep)3224 extern DialoG CreateBondEditorDialog (GrouP h, CharPtr title, SeqEntryPtr sep)
3225 
3226 {
3227   BondPagePtr  bpp;
3228   GrouP        f;
3229   GrouP        m;
3230   GrouP        p;
3231   GrouP        s;
3232 
3233   p = HiddenGroup (h, 1, 0, NULL);
3234   SetGroupSpacing (p, 10, 10);
3235 
3236   bpp = (BondPagePtr) MemNew (sizeof (BondPage));
3237   if (bpp != NULL) {
3238 
3239     SetObjectExtra (p, bpp, StdCleanupExtraProc);
3240     bpp->dialog = (DialoG) p;
3241     bpp->todialog = SeqLocPtrToBondPage;
3242     bpp->fromdialog = BondPageToSeqLocPtr;
3243     bpp->dialogmessage = BondEditorMessage;
3244     bpp->testdialog = NULL;
3245     bpp->importdialog = NULL;
3246     bpp->exportdialog = NULL;
3247 
3248     if (title != NULL && title [0] != '\0') {
3249       s = NormalGroup (p, 0, -2, title, systemFont, NULL);
3250     } else {
3251       s = HiddenGroup (p, 0, -2, NULL);
3252     }
3253     m = HiddenGroup (s, -1, 0, NULL);
3254     /*
3255     SetGroupSpacing (m, 10, 10);
3256     */
3257 
3258     f = HiddenGroup (m, 2, 0, NULL);
3259     StaticPrompt (f, "From", 0, popupMenuHeight, programFont, 'l');
3260     bpp->pointA = CreatePointEditorDialog (f, NULL, sep, FALSE, TRUE);
3261     StaticPrompt (f, "(To)", 0, popupMenuHeight, programFont, 'l');
3262     bpp->pointB = CreatePointEditorDialog (f, NULL, sep, FALSE, TRUE);
3263   }
3264 
3265   return (DialoG) p;
3266 }
3267 
GetRidOfEmptyFeatsDescStrings(Uint2 entityID,SeqEntryPtr sep)3268 void GetRidOfEmptyFeatsDescStrings (Uint2 entityID, SeqEntryPtr sep)
3269 
3270 {
3271   if (entityID < 1 && sep == NULL) return;
3272   if (entityID > 0 && sep == NULL) {
3273     sep = GetTopSeqEntryForEntityID (entityID);
3274   }
3275   if (sep == NULL) return;
3276   SeqEntryExplore (sep, NULL, GetRidOfEmptyFeatsDescCallback);
3277 }
3278 
StdVibrantEditorMsgFunc(OMMsgStructPtr ommsp)3279 extern Int2 LIBCALLBACK StdVibrantEditorMsgFunc (OMMsgStructPtr ommsp)
3280 
3281 {
3282   BaseFormPtr    bfp;
3283   OMUserDataPtr  omudp;
3284 
3285   omudp = (OMUserDataPtr)(ommsp->omuserdata);
3286   if (omudp == NULL) return OM_MSG_RET_ERROR;
3287   bfp = (BaseFormPtr) omudp->userdata.ptrvalue;
3288   if (bfp == NULL) return OM_MSG_RET_ERROR;
3289   switch (ommsp->message) {
3290     case OM_MSG_DEL:
3291       Remove (bfp->form);
3292       Update ();
3293       break;
3294     default :
3295       break;
3296   }
3297   return OM_MSG_RET_OK;
3298 }
3299 
3300 /* launch url section */
3301 
LaunchEntrezURL(CharPtr database,Int4 uid,CharPtr format)3302 NLM_EXTERN void LaunchEntrezURL (CharPtr database, Int4 uid, CharPtr format)
3303 
3304 {
3305 #ifdef WIN_MOTIF
3306   NS_Window  window = NULL;
3307 #endif
3308 
3309   Char  url [256];
3310 
3311   if (uid < 1 || StringHasNoText (database) || StringHasNoText (format)) return;
3312   sprintf (url,
3313            "http://www.ncbi.nlm.nih.gov:80/entrez/query.fcgi?cmd=Retrieve&db=%s&list_uids=%ld&dopt=%s",
3314             database, (long) uid, format);
3315 
3316 #ifdef WIN_MAC
3317   Nlm_SendURLAppleEvent (url, "MOSS", NULL);
3318 #endif
3319 #ifdef WIN_MSWIN
3320   if (! Nlm_MSWin_OpenDocument (url)) {
3321     Message (MSG_POST, "Unable to launch browser");
3322   }
3323 #endif
3324 #ifdef WIN_MOTIF
3325   if (! NS_OpenURL (&window, url, NULL, TRUE)) {
3326     Message (MSG_POST, "Unable to launch browser");
3327   }
3328   NS_WindowFree (window);
3329 #endif
3330 }
3331 
ModalAcceptButton(ButtoN b)3332 extern void ModalAcceptButton (ButtoN b)
3333 {
3334   ModalAcceptCancelPtr acp;
3335 
3336   acp = (ModalAcceptCancelPtr) GetObjectExtra (b);
3337   if (acp != NULL)
3338   {
3339     acp->accepted = TRUE;
3340   }
3341 }
3342 
ModalCancelButton(ButtoN b)3343 extern void ModalCancelButton (ButtoN b)
3344 {
3345   ModalAcceptCancelPtr acp;
3346 
3347   acp = (ModalAcceptCancelPtr) GetObjectExtra (b);
3348   if (acp != NULL)
3349   {
3350     acp->cancelled = TRUE;
3351   }
3352 }
3353 
ModalThirdOptionButton(ButtoN b)3354 extern void ModalThirdOptionButton (ButtoN b)
3355 {
3356   ModalAcceptCancelPtr acp;
3357 
3358   acp = (ModalAcceptCancelPtr) GetObjectExtra (b);
3359   if (acp != NULL)
3360   {
3361     acp->third_option = TRUE;
3362   }
3363 }
3364 
3365 
3366 NLM_EXTERN Int4
ThreeOptionsDlg(CharPtr title_txt,CharPtr explain_txt,CharPtr opt1,CharPtr opt2,CharPtr opt3)3367 ThreeOptionsDlg
3368 (CharPtr title_txt,
3369  CharPtr explain_txt,
3370  CharPtr opt1,
3371  CharPtr opt2,
3372  CharPtr opt3)
3373 {
3374   WindoW w;
3375   GrouP  h, c;
3376   ButtoN b;
3377   GrouP  p;
3378   ModalAcceptCancelData acd;
3379 
3380 
3381   w = MovableModalWindow (-20, -13, -10, -10, title_txt, NULL);
3382   h = HiddenGroup(w, -1, 0, NULL);
3383   SetGroupSpacing (h, 10, 10);
3384 
3385   p = MultiLinePrompt (h, explain_txt, 300, programFont);
3386 
3387   c = HiddenGroup (h, 3, 0, NULL);
3388   b = PushButton (c, opt1, ModalAcceptButton);
3389   SetObjectExtra (b, &acd, NULL);
3390   b = PushButton (c, opt2, ModalCancelButton);
3391   SetObjectExtra (b, &acd, NULL);
3392 
3393   if (!StringHasNoText (opt3)) {
3394     b = PushButton (c, opt3, ModalThirdOptionButton);
3395     SetObjectExtra (b, &acd, NULL);
3396   }
3397 
3398   AlignObjects (ALIGN_CENTER, (HANDLE) p,
3399                               (HANDLE) c,
3400                               NULL);
3401 
3402   Show (w);
3403   Select (w);
3404 
3405   acd.cancelled = FALSE;
3406   acd.third_option = FALSE;
3407   acd.accepted = FALSE;
3408   while (!acd.accepted && ! acd.cancelled && !acd.third_option)
3409   {
3410     ProcessExternalEvent ();
3411     Update ();
3412   }
3413   ProcessAnEvent ();
3414   Remove (w);
3415 
3416   if (acd.accepted)
3417   {
3418     return 1;
3419   }
3420   else if (acd.cancelled)
3421   {
3422     return 2;
3423   }
3424   else
3425   {
3426     return 3;
3427   }
3428 }
3429 
3430 
3431 typedef struct tabledisplay
3432 {
3433   DIALOG_MESSAGE_BLOCK
3434   PaneL panel;
3435   ValNodePtr row_list;
3436   Int4 frozen_header;
3437   Int4 frozen_left;
3438   Int4 table_inset;
3439   Int4 char_width;
3440   Int4 descent;
3441   FonT display_font;
3442   TableDisplayDblClick dbl_click;
3443   Pointer dbl_click_data;
3444   TableDisplayLeftInRed left_in_red;
3445   Pointer left_in_red_data;
3446   Int4 select_x;
3447   Int4 select_y;
3448   Int4 select_cell_offset;
3449   Boolean editable;
3450 } TableDisplayData, PNTR TableDisplayPtr;
3451 
FreeTableDisplayRowList(ValNodePtr row_list)3452 extern ValNodePtr FreeTableDisplayRowList (ValNodePtr row_list)
3453 {
3454   ValNodePtr row_vnp, column_list;
3455 
3456   if (row_list != NULL)
3457   {
3458     /* free table text */
3459     for (row_vnp = row_list; row_vnp != NULL; row_vnp = row_vnp->next)
3460     {
3461       column_list = (ValNodePtr) row_vnp->data.ptrvalue;
3462       row_vnp->data.ptrvalue = ValNodeFreeData (column_list);
3463     }
3464     row_list = ValNodeFree (row_list);
3465   }
3466   return row_list;
3467 }
3468 
PrintTableDisplayRowListToFile(ValNodePtr row_list,FILE * fp)3469 extern void PrintTableDisplayRowListToFile (ValNodePtr row_list, FILE *fp)
3470 {
3471   ValNodePtr row_vnp, col_vnp, column_list;
3472   CharPtr    txt_val;
3473 
3474   if (row_list == NULL || fp == NULL)
3475   {
3476     return;
3477   }
3478 
3479   for (row_vnp = row_list; row_vnp != NULL; row_vnp = row_vnp->next)
3480   {
3481     column_list = (ValNodePtr) row_vnp->data.ptrvalue;
3482     for (col_vnp = column_list; col_vnp != NULL; col_vnp = col_vnp->next)
3483     {
3484       txt_val = (CharPtr) col_vnp->data.ptrvalue;
3485       if (!StringHasNoText (txt_val))
3486       {
3487         fprintf (fp, "%s", txt_val);
3488       }
3489       if (col_vnp->next == NULL)
3490       {
3491         fprintf (fp, "\n");
3492       }
3493       else
3494       {
3495         fprintf (fp, "\t");
3496       }
3497     }
3498   }
3499 }
3500 
ValNodeStringListCopy(ValNodePtr orig_list)3501 static ValNodePtr ValNodeStringListCopy (ValNodePtr orig_list)
3502 {
3503   ValNodePtr new_list = NULL;
3504 
3505   if (orig_list == NULL)
3506   {
3507     return NULL;
3508   }
3509 
3510   new_list = ValNodeNew (NULL);
3511   new_list->choice = orig_list->choice;
3512   new_list->data.ptrvalue = StringSave (orig_list->data.ptrvalue);
3513   new_list->next = ValNodeStringListCopy (orig_list->next);
3514   return new_list;
3515 }
3516 
CopyTableDisplayRowList(ValNodePtr row_list)3517 extern ValNodePtr CopyTableDisplayRowList (ValNodePtr row_list)
3518 {
3519   ValNodePtr new_row_list = NULL;
3520 
3521   if (row_list == NULL)
3522   {
3523     return NULL;
3524   }
3525 
3526   new_row_list = ValNodeNew (NULL);
3527   new_row_list->choice = row_list->choice;
3528   new_row_list->data.ptrvalue = ValNodeStringListCopy (row_list->data.ptrvalue);
3529   new_row_list->next = CopyTableDisplayRowList (row_list->next);
3530   return new_row_list;
3531 }
3532 
CleanupTableDisplayDialog(GraphiC g,VoidPtr data)3533 static void CleanupTableDisplayDialog (GraphiC g, VoidPtr data)
3534 {
3535   TableDisplayPtr dlg;
3536 
3537   dlg = (TableDisplayPtr) data;
3538   if (dlg != NULL) {
3539     dlg->row_list = FreeTableDisplayRowList (dlg->row_list);
3540   }
3541   StdCleanupExtraProc (g, data);
3542 }
3543 
UpdateTableDisplayDialogScrollBars(TableDisplayPtr dlg)3544 static void UpdateTableDisplayDialogScrollBars (TableDisplayPtr dlg)
3545 {
3546   BaR  sb_vert;
3547   BaR  sb_horiz;
3548   Int4 start_row, start_col;
3549   Int4 num_rows, num_columns, visible_rows;
3550   Int4 new_vmax, new_hmax, old_vmax, old_hmax;
3551   RecT r;
3552   Int4 x, y;
3553 
3554   if (dlg == NULL)
3555   {
3556     return;
3557   }
3558 
3559   sb_vert  = GetSlateVScrollBar ((SlatE) dlg->panel);
3560   sb_horiz = GetSlateHScrollBar ((SlatE) dlg->panel);
3561 
3562   start_row = GetBarValue (sb_vert) + dlg->frozen_header;
3563   start_col = GetBarValue (sb_horiz) + dlg->frozen_left;
3564 
3565   if (dlg->row_list == NULL)
3566   {
3567     num_rows = 0;
3568     num_columns = 0;
3569   }
3570   else
3571   {
3572     num_rows = ValNodeLen (dlg->row_list);
3573     num_columns = ValNodeLen (dlg->row_list->data.ptrvalue);
3574   }
3575 
3576   ObjectRect (dlg->panel, &r);
3577   InsetRect (&r, dlg->table_inset, dlg->table_inset);
3578   x = r.left + 1;
3579   y = r.top + stdLineHeight;
3580 
3581   visible_rows = (r.bottom - r.top - 2 * dlg->table_inset) / stdLineHeight - dlg->frozen_header;
3582   new_vmax = num_rows - visible_rows - 1;
3583   new_hmax = num_columns - dlg->frozen_left - 1;
3584   if (new_vmax < 0)
3585   {
3586     new_vmax = 0;
3587   }
3588   if (new_hmax < 0)
3589   {
3590     new_hmax = 0;
3591   }
3592   old_vmax = GetBarMax (sb_vert);
3593   old_hmax = GetBarMax (sb_horiz);
3594 
3595   if (old_vmax != new_vmax)
3596   {
3597     CorrectBarMax (sb_vert, new_vmax);
3598     if (start_row > new_vmax + dlg->frozen_header)
3599     {
3600       start_row = new_vmax + dlg->frozen_header;
3601     }
3602     CorrectBarValue (sb_vert, start_row - dlg->frozen_header);
3603     CorrectBarPage (sb_vert, 1, 1);
3604   }
3605 
3606   if (old_hmax != new_hmax)
3607   {
3608     CorrectBarMax (sb_horiz, new_hmax);
3609     if (start_col > new_hmax + dlg->frozen_left)
3610     {
3611       start_col = new_hmax + dlg->frozen_left;
3612     }
3613     CorrectBarValue (sb_horiz, start_col - dlg->frozen_left);
3614     CorrectBarPage (sb_horiz, 1, 1);
3615   }
3616 }
3617 
RowsToTableDisplayDialog(DialoG d,Pointer userdata)3618 static void RowsToTableDisplayDialog (DialoG d, Pointer userdata)
3619 {
3620   TableDisplayPtr dlg;
3621   RecT            r;
3622     WindoW          temport;
3623 
3624   dlg = (TableDisplayPtr) GetObjectExtra (d);
3625   if (dlg == NULL)
3626   {
3627     return;
3628   }
3629 
3630   dlg->row_list = FreeTableDisplayRowList (dlg->row_list);
3631   dlg->row_list = CopyTableDisplayRowList (userdata);
3632   UpdateTableDisplayDialogScrollBars (dlg);
3633   temport = SavePort (dlg->panel);
3634   Select (dlg->panel);
3635   ObjectRect (dlg->panel, &r);
3636   InvalRect (&r);
3637   Update ();
3638   RestorePort (temport);
3639 }
3640 
TableDisplayDialogToRows(DialoG d)3641 static Pointer TableDisplayDialogToRows (DialoG d)
3642 {
3643   TableDisplayPtr dlg;
3644 
3645   dlg = (TableDisplayPtr) GetObjectExtra (d);
3646   if (dlg == NULL)
3647   {
3648     return NULL;
3649   }
3650 
3651   return CopyTableDisplayRowList (dlg->row_list);
3652 }
3653 
3654 static Int4
PrepareTableDisplayTextBuffer(CharPtr buf,Int4 remaining_chars_in_row,Int4 col_width,CharPtr data)3655 PrepareTableDisplayTextBuffer
3656 (CharPtr buf,
3657  Int4    remaining_chars_in_row,
3658  Int4    col_width,
3659  CharPtr data)
3660 {
3661   Uint4 chars_to_paint = 0;
3662   if (buf == NULL)
3663   {
3664     return 0;
3665   }
3666 
3667   if (remaining_chars_in_row < col_width)
3668   {
3669     chars_to_paint = remaining_chars_in_row;
3670     StringNCpy (buf, data, chars_to_paint);
3671     buf [chars_to_paint] = 0;
3672   }
3673   else
3674   {
3675     chars_to_paint = col_width;
3676     StringNCpy (buf, data, chars_to_paint);
3677     buf [chars_to_paint] = 0;
3678     if (StringLen (data) > chars_to_paint && chars_to_paint > 2)
3679     {
3680       buf [chars_to_paint - 1] = '.';
3681       buf [chars_to_paint - 2] = '.';
3682       buf [chars_to_paint - 3] = '.';
3683     }
3684   }
3685   return chars_to_paint;
3686 }
3687 
DrawTableDisplayLine(Int4 x,Int4 y,ValNodePtr header_row,ValNodePtr data_row,CharPtr buf,Int4 row_length,Int4 frozen_left,Int4 start_col,Int4 char_width,Int4 descent,Boolean left_in_red)3688 static void DrawTableDisplayLine (Int4 x, Int4 y,
3689  ValNodePtr header_row,
3690  ValNodePtr data_row,
3691  CharPtr    buf,
3692  Int4       row_length,
3693  Int4       frozen_left,
3694  Int4       start_col,
3695  Int4       char_width,
3696  Int4       descent,
3697  Boolean    left_in_red)
3698 {
3699   ValNodePtr header_vnp, data_vnp;
3700   Int4       x_offset, chars_to_paint, col_num;
3701   PoinT      pt1, pt2;
3702   RecT       rct;
3703 
3704   /* draw left margin */
3705 
3706   for (header_vnp = header_row, data_vnp = data_row, x_offset = 0, col_num = 0;
3707        header_vnp != NULL && data_vnp != NULL && x_offset < row_length && col_num < frozen_left;
3708        header_vnp = header_vnp->next, data_vnp = data_vnp->next, col_num++)
3709   {
3710     Gray ();
3711     InvertColors ();
3712     if (left_in_red)
3713     {
3714       Red ();
3715     }
3716     else
3717     {
3718       White ();
3719     }
3720     chars_to_paint = PrepareTableDisplayTextBuffer (buf,
3721                                    (row_length - x_offset) / char_width,
3722                                    header_vnp->choice,
3723                                    data_vnp->data.ptrvalue);
3724 
3725     LoadRect (&rct, x + x_offset, y + descent,
3726               x + x_offset + (chars_to_paint + 2) * char_width,
3727               y - stdLineHeight + descent);
3728     EraseRect (&rct);
3729 
3730     PaintStringEx ( (CharPtr)buf, x + x_offset, y);
3731     x_offset += (chars_to_paint + 2) * char_width;
3732     InvertColors ();
3733     Black ();
3734   }
3735 
3736   if (frozen_left > 0)
3737   {
3738     pt1.x = x + x_offset - 1;
3739     pt1.y = y;
3740     pt2.x = x + x_offset - 1;
3741     pt2.y = y - stdLineHeight;
3742     DrawLine (pt1, pt2);
3743   }
3744 
3745 
3746   while (col_num < start_col && header_vnp != NULL && data_vnp != NULL)
3747   {
3748     col_num++;
3749     header_vnp = header_vnp->next;
3750     data_vnp = data_vnp->next;
3751   }
3752 
3753   /* draw unfrozen columns */
3754   while (header_vnp != NULL && data_vnp != NULL && x_offset < row_length)
3755   {
3756     chars_to_paint = MIN (header_vnp->choice, (row_length - x_offset)/char_width);
3757     StringNCpy (buf, data_vnp->data.ptrvalue, chars_to_paint);
3758     buf [chars_to_paint] = 0;
3759     chars_to_paint = PrepareTableDisplayTextBuffer (buf,
3760                                    (row_length - x_offset) / char_width,
3761                                    header_vnp->choice,
3762                                    data_vnp->data.ptrvalue);
3763 
3764     PaintStringEx ( (CharPtr)buf, x + x_offset, y);
3765     x_offset += (chars_to_paint + 2) * char_width;
3766     header_vnp = header_vnp->next;
3767     data_vnp = data_vnp->next;
3768   }
3769 }
3770 
3771 
DrawTableDisplayCaret(Int4 x,Int4 y,ValNodePtr header_row,ValNodePtr data_row,CharPtr buf,Int4 row_length,Int4 frozen_left,Int4 start_col,Int4 char_width,Int4 select_x,Int4 select_cell_offset)3772 static void DrawTableDisplayCaret (Int4 x, Int4 y,
3773  ValNodePtr header_row,
3774  ValNodePtr data_row,
3775  CharPtr    buf,
3776  Int4       row_length,
3777  Int4       frozen_left,
3778  Int4       start_col,
3779  Int4       char_width,
3780  Int4       select_x,
3781  Int4       select_cell_offset)
3782 {
3783 
3784   ValNodePtr header_vnp, data_vnp;
3785   Int4       x_offset, chars_to_paint, col_num;
3786   PoinT      pt1, pt2;
3787   Boolean    found = FALSE;
3788 
3789   /* draw left margin */
3790 
3791   for (header_vnp = header_row, data_vnp = data_row, x_offset = 0, col_num = 0;
3792        header_vnp != NULL && data_vnp != NULL && x_offset < row_length && col_num < frozen_left && !found;
3793        header_vnp = header_vnp->next, data_vnp = data_vnp->next, col_num++)
3794   {
3795     /* no editing in frozen left, so no caret */
3796     chars_to_paint = PrepareTableDisplayTextBuffer (buf,
3797                                    (row_length - x_offset) / char_width,
3798                                    header_vnp->choice,
3799                                    data_vnp->data.ptrvalue);
3800     x_offset += (chars_to_paint + 2) * char_width;
3801   }
3802 
3803   while (col_num < start_col && header_vnp != NULL && data_vnp != NULL)
3804   {
3805     col_num++;
3806     header_vnp = header_vnp->next;
3807     data_vnp = data_vnp->next;
3808   }
3809 
3810   /* draw unfrozen columns */
3811   while (header_vnp != NULL && data_vnp != NULL && x_offset < row_length && !found)
3812   {
3813     if ((col_num - start_col) + frozen_left == select_x) {
3814       Black();
3815       pt1.x = x + x_offset + (select_cell_offset * char_width) - 1;
3816       pt1.y = y;
3817       pt2.x = x + x_offset + (select_cell_offset * char_width);
3818       pt2.y = y - 1;
3819       DrawLine (pt1, pt2);
3820       pt1.x = x + x_offset + (select_cell_offset * char_width) + 1;
3821       DrawLine (pt1, pt2);
3822       found = TRUE;
3823     }
3824 
3825     chars_to_paint = MIN (header_vnp->choice, (row_length - x_offset)/char_width);
3826     x_offset += (chars_to_paint + 2) * char_width;
3827     header_vnp = header_vnp->next;
3828     data_vnp = data_vnp->next;
3829     col_num++;
3830   }
3831 }
3832 
3833 
OnDrawTableDisplay(PaneL p)3834 static void OnDrawTableDisplay (PaneL p)
3835 {
3836   TableDisplayPtr dlg;
3837   BaR             sb_vert, sb_horiz;
3838   Int4            start_row, start_col;
3839   RecT            r;
3840   Int4            x, y, row, row_length;
3841   CharPtr         row_buffer;
3842   ValNodePtr      row_vnp;
3843   PoinT           pt1, pt2;
3844   Boolean         left_in_red;
3845 
3846   dlg = (TableDisplayPtr) GetObjectExtra (p);
3847   if (dlg == NULL)
3848   {
3849     return;
3850   }
3851 
3852   sb_vert  = GetSlateVScrollBar ((SlatE) p);
3853   sb_horiz = GetSlateHScrollBar ((SlatE) p);
3854 
3855   start_row = GetBarValue (sb_vert) + dlg->frozen_header;
3856   start_col = GetBarValue (sb_horiz) + dlg->frozen_left;
3857 
3858   ObjectRect (p, &r);
3859   InsetRect (&r, dlg->table_inset, dlg->table_inset);
3860   x = r.left + 1;
3861   y = r.top + stdLineHeight;
3862 
3863   SelectFont (programFont);
3864 
3865   row_length = r.right - r.left - 2;
3866   row_buffer = (CharPtr) MemNew (((row_length / dlg->char_width) + 1) * sizeof (Char));
3867 
3868   for (row = 0, row_vnp = dlg->row_list;
3869        row < dlg->frozen_header && y <= r.bottom - 2 * dlg->table_inset && row_vnp != NULL;
3870        row++, row_vnp = row_vnp->next)
3871   {
3872     DrawTableDisplayLine (x, y, dlg->row_list->data.ptrvalue, row_vnp->data.ptrvalue,
3873                           row_buffer, row_length, dlg->frozen_left, start_col,
3874                           dlg->char_width, dlg->descent, FALSE);
3875     y += stdLineHeight;
3876   }
3877 
3878   while (row < start_row && row_vnp != NULL)
3879   {
3880     row++;
3881     row_vnp = row_vnp->next;
3882   }
3883 
3884   while (row_vnp != NULL && y <= r.bottom - 2 * dlg->table_inset)
3885   {
3886     left_in_red = FALSE;
3887     if (dlg->left_in_red != NULL)
3888     {
3889       left_in_red = (dlg->left_in_red) (row, dlg->row_list, dlg->left_in_red_data);
3890     }
3891     DrawTableDisplayLine (x, y, dlg->row_list->data.ptrvalue, row_vnp->data.ptrvalue,
3892                           row_buffer, row_length, dlg->frozen_left, start_col,
3893                           dlg->char_width, dlg->descent, left_in_red);
3894     row_vnp = row_vnp->next;
3895     if (row == dlg->select_y) {
3896       DrawTableDisplayCaret (x, y, dlg->row_list->data.ptrvalue,
3897                           row_vnp == NULL ? NULL : row_vnp->data.ptrvalue,
3898                           row_buffer, row_length, dlg->frozen_left, start_col,
3899                           dlg->char_width, dlg->select_x, dlg->select_cell_offset);
3900     }
3901     y += stdLineHeight;
3902     row++;
3903   }
3904 
3905   /* draw line to separate header from remaining lines */
3906   if (dlg->frozen_header > 0)
3907   {
3908     Black ();
3909     pt1.x = x;
3910     pt1.y = r.top + stdLineHeight + dlg->descent;
3911     pt2.x = x + row_length;
3912     pt2.y = r.top + stdLineHeight + dlg->descent;
3913     DrawLine (pt1, pt2);
3914   }
3915 
3916 
3917 }
3918 
OnVScrollTableDisplay(BaR sb,SlatE s,Int4 newval,Int4 oldval)3919 static void OnVScrollTableDisplay (BaR sb, SlatE s, Int4 newval, Int4 oldval)
3920 {
3921   RecT   r;
3922   WindoW temport;
3923 
3924   temport = SavePort (s);
3925   Select (s);
3926   ObjectRect (s, &r);
3927   InvalRect (&r);
3928   RestorePort (temport);
3929   Update ();
3930 }
3931 
OnHScrollTableDisplay(BaR sb,SlatE s,Int4 newval,Int4 oldval)3932 static void OnHScrollTableDisplay (BaR sb, SlatE s, Int4 newval, Int4 oldval)
3933 {
3934   RecT   r;
3935   WindoW temport;
3936 
3937   temport = SavePort (s);
3938   Select (s);
3939   ObjectRect (s, &r);
3940   InvalRect (&r);
3941   RestorePort (temport);
3942   Update ();
3943 }
3944 
3945 static CharPtr TableDisplayGetTextForCell (TableDisplayPtr dlg, PoinT pt);
3946 
GetTableDisplayCell(TableDisplayPtr dlg,PoinT pt,Int4Ptr char_offset)3947 static PoinT GetTableDisplayCell (TableDisplayPtr dlg, PoinT pt, Int4Ptr char_offset)
3948 {
3949   BaR sb_horiz;
3950   BaR sb_vert;
3951   Int4 start_row, start_col;
3952   RecT r;
3953   PoinT cell_coord;
3954   Int4  x, y;
3955   ValNodePtr header_vnp;
3956   Int4  col_width;
3957   CharPtr cell_text;
3958   Int4    chars_skipped, cell_len;
3959   Uint1 chs;
3960 
3961   cell_coord.x = 0;
3962   cell_coord.y = 0;
3963 
3964   if (dlg == NULL || dlg->row_list == NULL)
3965   {
3966     return cell_coord;
3967   }
3968 
3969   sb_vert  = GetSlateVScrollBar ((SlatE) dlg->panel);
3970   sb_horiz = GetSlateHScrollBar ((SlatE) dlg->panel);
3971 
3972   start_row = GetBarValue (sb_vert) + dlg->frozen_header;
3973   start_col = GetBarValue (sb_horiz) + dlg->frozen_left;
3974 
3975   ObjectRect (dlg->panel, &r);
3976   InsetRect (&r, dlg->table_inset, dlg->table_inset);
3977   x = pt.x - r.left;
3978   y = pt.y - r.top;
3979 
3980   cell_coord.y = y / stdLineHeight;
3981 
3982   if (cell_coord.y >= dlg->frozen_header)
3983   {
3984     cell_coord.y += GetBarValue (sb_vert);
3985   }
3986 
3987   header_vnp = dlg->row_list->data.ptrvalue;
3988 
3989   col_width = 0;
3990   while (header_vnp != NULL && col_width + (header_vnp->choice + 2) * dlg->char_width < x
3991          && cell_coord.x < dlg->frozen_left)
3992   {
3993     cell_coord.x++;
3994     col_width += (header_vnp->choice + 2) * dlg->char_width;
3995     header_vnp = header_vnp->next;
3996   }
3997 
3998   if (cell_coord.x >= dlg->frozen_left)
3999   {
4000     /* skip over unfrozen columns not currently displayed */
4001     while (header_vnp != NULL && cell_coord.x < start_col)
4002     {
4003       header_vnp = header_vnp->next;
4004       cell_coord.x++;
4005     }
4006 
4007     while (header_vnp != NULL && col_width + (header_vnp->choice + 2) * dlg->char_width < x)
4008     {
4009       cell_coord.x++;
4010       col_width += (header_vnp->choice + 2) * dlg->char_width;
4011       header_vnp = header_vnp->next;
4012     }
4013     if (char_offset != NULL) {
4014       chs = 0;
4015       if (header_vnp != NULL) {
4016         chs = header_vnp->choice;
4017       }
4018       chars_skipped = ((col_width + (chs + 2) * dlg->char_width) - x) / dlg->char_width;
4019       cell_text = TableDisplayGetTextForCell (dlg, cell_coord);
4020       cell_len = StringLen (cell_text);
4021       cell_text = MemFree (cell_text);
4022       if (chars_skipped > cell_len) {
4023         chars_skipped = cell_len;
4024       }
4025       *char_offset = chars_skipped;
4026     }
4027   }
4028   return cell_coord;
4029 }
4030 
4031 
GetRowListCell(ValNodePtr row_list,Int4 row,Int4 column)4032 static ValNodePtr GetRowListCell (ValNodePtr row_list, Int4 row, Int4 column)
4033 {
4034   ValNodePtr row_vnp, col_vnp;
4035   Int4       row_num, col_num;
4036 
4037   if (row_list == NULL || row < 0 || column < 0)
4038   {
4039     return NULL;
4040   }
4041 
4042   for (row_vnp = row_list, row_num = 0;
4043        row_vnp != NULL && row_num < row;
4044        row_vnp = row_vnp->next, row_num++)
4045   {
4046   }
4047   if (row_num != row || row_vnp == NULL)
4048   {
4049     return NULL;
4050   }
4051   for (col_vnp = row_vnp->data.ptrvalue, col_num = 0;
4052        col_vnp != NULL && col_num < column;
4053        col_vnp = col_vnp->next, col_num++)
4054   {
4055   }
4056   if (col_num != column || col_vnp == NULL)
4057   {
4058     return NULL;
4059   }
4060   else
4061   {
4062     return col_vnp;
4063   }
4064 }
4065 
4066 
GetRowListCellText(ValNodePtr row_list,Int4 row,Int4 column)4067 extern CharPtr GetRowListCellText (ValNodePtr row_list, Int4 row, Int4 column)
4068 {
4069   ValNodePtr col_vnp;
4070 
4071   col_vnp = GetRowListCell (row_list, row, column);
4072   if (col_vnp != NULL)
4073   {
4074     return StringSave (col_vnp->data.ptrvalue);
4075   }
4076   else
4077   {
4078     return NULL;
4079   }
4080 }
4081 
TableDisplayGetTextForCell(TableDisplayPtr dlg,PoinT pt)4082 static CharPtr TableDisplayGetTextForCell (TableDisplayPtr dlg, PoinT pt)
4083 {
4084   if (dlg == NULL || dlg->row_list == NULL || pt.x < 0 || pt.y < 0)
4085   {
4086     return NULL;
4087   }
4088 
4089   return GetRowListCellText (dlg->row_list, pt.y, pt.x);
4090 }
4091 
TableDisplayOnClick(PaneL p,PoinT pt)4092 static void TableDisplayOnClick (PaneL p, PoinT pt)
4093 {
4094   TableDisplayPtr dlg;
4095   Boolean         dbl_click;
4096   PoinT           cell_coord;
4097   PoinT           header_coord;
4098   CharPtr         cell_text;
4099   CharPtr         header_text;
4100 
4101   dlg = (TableDisplayPtr) GetObjectExtra (p);
4102   if (dlg == NULL)
4103   {
4104     return;
4105   }
4106 
4107   cell_coord = GetTableDisplayCell (dlg, pt, &(dlg->select_cell_offset));
4108   if (dlg->editable) {
4109     dlg->select_x = cell_coord.x;
4110     dlg->select_y = cell_coord.y;
4111     if (dlg->select_x == 0) {
4112       dlg->select_x = cell_coord.x;
4113     }
4114   }
4115 
4116   dbl_click = dblClick;
4117 
4118   if (dbl_click && dlg->dbl_click != NULL)
4119   {
4120     cell_text = TableDisplayGetTextForCell (dlg, cell_coord);
4121     header_coord.x = cell_coord.x;
4122     header_coord.y = 0;
4123     header_text = TableDisplayGetTextForCell (dlg, header_coord);
4124     (dlg->dbl_click) (cell_coord, header_text, cell_text, dlg->dbl_click_data);
4125     MemFree (cell_text);
4126     MemFree (header_text);
4127   } else if (dlg->editable) {
4128     inval_panel (p, -1, -1);
4129   }
4130 }
4131 
GetTableDisplayDefaultFont(void)4132 extern FonT GetTableDisplayDefaultFont (void)
4133 {
4134   FonT display_font = NULL;
4135 
4136 #ifdef WIN_MAC
4137   display_font = ParseFont ("Monaco, 9");
4138 #endif
4139 #ifdef WIN_MSWIN
4140   display_font = ParseFont ("Courier, 9");
4141 #endif
4142 #ifdef WIN_MOTIF
4143   display_font = ParseFont ("fixed, 12");
4144 #endif
4145   return display_font;
4146 }
4147 
TableDisplayDialog(GrouP parent,Int4 width,Int4 height,Int4 frozen_header,Int4 frozen_left,TableDisplayDblClick dbl_click,Pointer dbl_click_data,TableDisplayLeftInRed left_in_red,Pointer left_in_red_data)4148 extern DialoG TableDisplayDialog (GrouP parent, Int4 width, Int4 height,
4149                                   Int4 frozen_header, Int4 frozen_left,
4150                                   TableDisplayDblClick dbl_click,
4151                                   Pointer dbl_click_data,
4152                                   TableDisplayLeftInRed left_in_red,
4153                                   Pointer left_in_red_data)
4154 {
4155   TableDisplayPtr dlg;
4156   GrouP           p;
4157 
4158   dlg = (TableDisplayPtr) MemNew (sizeof (TableDisplayData));
4159   if (dlg == NULL)
4160   {
4161     return NULL;
4162   }
4163   p = HiddenGroup (parent, -1, 0, NULL);
4164   SetObjectExtra (p, dlg, CleanupTableDisplayDialog);
4165 
4166   dlg->dialog = (DialoG) p;
4167   dlg->todialog = RowsToTableDisplayDialog;
4168   dlg->fromdialog = TableDisplayDialogToRows;
4169   dlg->dialogmessage = NULL;
4170   dlg->testdialog = NULL;
4171 
4172   dlg->row_list = NULL;
4173   dlg->frozen_header = frozen_header;
4174   dlg->frozen_left = frozen_left;
4175   dlg->table_inset = 4;
4176   dlg->dbl_click = dbl_click;
4177   dlg->dbl_click_data = dbl_click_data;
4178   dlg->left_in_red = left_in_red;
4179   dlg->left_in_red_data = left_in_red_data;
4180 
4181   dlg->display_font = GetTableDisplayDefaultFont ();
4182 
4183   SelectFont (dlg->display_font);
4184   dlg->char_width  = CharWidth ('0');
4185   dlg->descent = Descent ();
4186 
4187   dlg->panel = AutonomousPanel4 (p, width, height, OnDrawTableDisplay,
4188                                OnVScrollTableDisplay, OnHScrollTableDisplay,
4189                                sizeof (TableDisplayData), NULL, NULL);
4190   SetObjectExtra (dlg->panel, dlg, NULL);
4191   SetPanelClick(dlg->panel, TableDisplayOnClick, NULL, NULL, NULL);
4192 
4193   return (DialoG) p;
4194 }
4195 
4196 
EdTableOnKey(SlatE s,Char ch)4197 static void EdTableOnKey (SlatE s, Char ch)
4198 {
4199   PaneL            pnl;
4200   TableDisplayPtr  dlg;
4201   ValNodePtr       col_vnp;
4202   CharPtr          cell_text, new_cell_text;
4203   Int4             orig_len;
4204 
4205   pnl = (PaneL) s;
4206   Select (pnl);
4207   dlg = (TableDisplayPtr) GetObjectExtra (pnl);
4208   if (dlg == NULL) return;
4209 
4210   if ( (int) ch == 0 ) return;
4211 
4212   CaptureSlateFocus ((SlatE) dlg->panel);
4213 
4214   col_vnp = GetRowListCell (dlg->row_list, dlg->select_y, dlg->select_x);
4215   if (col_vnp != NULL) {
4216     cell_text = col_vnp->data.ptrvalue;
4217     orig_len = StringLen (cell_text);
4218     new_cell_text = (CharPtr) MemNew (sizeof (Char) * (orig_len + 2));
4219     new_cell_text[0] = 0;
4220     if (dlg->select_cell_offset > 0) {
4221       StringNCpy (new_cell_text, cell_text, dlg->select_cell_offset);
4222     }
4223     new_cell_text[dlg->select_cell_offset] = ch;
4224     if (dlg->select_cell_offset < orig_len) {
4225       StringCpy (new_cell_text + dlg->select_cell_offset + 1, cell_text + dlg->select_cell_offset);
4226     }
4227     new_cell_text[orig_len + 1] = 0;
4228     cell_text = MemFree (cell_text);
4229     col_vnp->data.ptrvalue = new_cell_text;
4230     /* increment offset to be after what we have just inserted */
4231     dlg->select_cell_offset++;
4232     /* redraw */
4233     inval_panel (pnl, -1, -1);
4234   }
4235 
4236 #if 0
4237   /* later, handle control key combos */
4238 #ifdef WIN_MSWIN
4239   if (ch == 3)
4240   {
4241     SeqEdCopy (sefp);
4242   }
4243   else if (ch == 24)
4244   {
4245     SeqEdCut (sefp);
4246   }
4247   else if (ch == 22)
4248   {
4249     SeqEdPaste (sefp);
4250   }
4251 #else
4252   if (ctrlKey)
4253   {
4254     if (ch == 'c')
4255     {
4256       SeqEdCopy (sefp);
4257     }
4258     else if (ch == 'x')
4259     {
4260       SeqEdCut (sefp);
4261     }
4262     else if (ch == 'v')
4263     {
4264       SeqEdPaste (sefp);
4265     }
4266   	return;
4267   }
4268 #endif
4269   else
4270   {
4271     /* look at key pressed - if it's a good sequence character, insert it */
4272     if ( (str = char_to_insert (&ch, 1, sefp->bfp->bvd.bsp->mol)) != NULL)
4273     {
4274       if (sefp->edit_pos_start != sefp->edit_pos_end)
4275       {
4276         SeqEdDelete (sefp, FALSE);
4277       }
4278       if (AddJournalEntry (eSeqEdInsert, sefp->edit_pos_start,
4279    	                   StringLen (str), str, sefp))
4280       {
4281    	    sefp->edit_pos_start += StringLen (str);
4282    	    sefp->edit_pos_end += StringLen (str);
4283         ResizeSeqEdView (sefp);
4284         Select (sefp->bfp->bvd.seqView);
4285   	    inval_panel (pnl, -1, -1);
4286       }
4287     }
4288     else
4289     {
4290       /* handle movements and deletions */
4291       new_pos = sefp->edit_pos_start;
4292       switch (ch)
4293       {
4294         case NLM_LEFT:
4295           new_pos--;
4296           break;
4297         case NLM_RIGHT:
4298     	    new_pos++;
4299     	    break;
4300     	  case NLM_UP:
4301     	    new_pos -= sefp->bfp->bvd.CharsAtLine;
4302     	    break;
4303     	  case NLM_DOWN:
4304     	    new_pos += sefp->bfp->bvd.CharsAtLine;
4305     	    if (new_pos > sefp->bfp->bvd.bsp->length
4306     	        && new_pos - sefp->bfp->bvd.bsp->length < sefp->bfp->bvd.CharsAtLine)
4307     	    {
4308             new_pos = sefp->bfp->bvd.bsp->length;
4309           }
4310     	    break;
4311         case NLM_DEL:
4312           /* handle deletion */
4313           if (sefp->edit_pos_end == sefp->edit_pos_start)
4314           {
4315             sefp->edit_pos_end = sefp->edit_pos_start + 1;
4316             if (sefp->edit_pos_end > sefp->bfp->bvd.bsp->length)
4317             {
4318               sefp->edit_pos_end = sefp->edit_pos_start;
4319               return;
4320             }
4321           }
4322           RemapSeqEdIntervalForGap (sefp);
4323           SeqEdDelete (sefp, FALSE);
4324           ResizeSeqEdView (sefp);
4325           Select (sefp->bfp->bvd.seqView);
4326 	        inval_panel (pnl, -1, -1);
4327           break;
4328         case NLM_BACK:
4329     	    /* handle backspace */
4330     	    if (sefp->edit_pos_start == sefp->edit_pos_end)
4331     	    {
4332     	      if (sefp->edit_pos_start == 0)
4333     	      {
4334     	        del_start = -1;
4335             }
4336     	      else
4337     	      {
4338               del_start = sefp->edit_pos_start - 1;
4339               del_stop = sefp->edit_pos_start;
4340   	        }
4341           }
4342     	    else
4343     	    {
4344             del_start = sefp->edit_pos_start;
4345             del_stop = sefp->edit_pos_end;
4346   	      }
4347 
4348           if (del_start >= 0)
4349           {
4350             sefp->edit_pos_start = del_start;
4351             sefp->edit_pos_end = del_stop;
4352             RemapSeqEdIntervalForGap (sefp);
4353             new_pos = sefp->edit_pos_start;
4354             SeqEdDelete (sefp, FALSE);
4355             ResizeSeqEdView (sefp);
4356             Select (sefp->bfp->bvd.seqView);
4357             inval_panel (pnl, -1, -1);
4358   	      }
4359   	      break;
4360       }
4361       if (new_pos < 0 || new_pos > sefp->bfp->bvd.bsp->length)
4362       {
4363         Beep ();
4364       }
4365       else
4366       {
4367         sefp->edit_pos_start = new_pos;
4368   	    sefp->edit_pos_end = new_pos;
4369         sb = GetSlateVScrollBar (s);
4370         if (sb != NULL)
4371   	    {
4372   	      scroll_pos = SeqEdGetScrollPosForSequencePos (sefp->edit_pos_start, &(sefp->bfp->bvd));
4373           SetBarValue (sb, scroll_pos);
4374   	    }
4375         Select (sefp->bfp->bvd.seqView);
4376   	    inval_panel (pnl, -1, -1);
4377       }
4378     }
4379     SeqEdUpdateStatus (sefp);
4380   }
4381 #endif
4382 }
4383 
4384 
EditableTableDisplayDialog(GrouP parent,Int4 width,Int4 height,Int4 frozen_header,Int4 frozen_left,TableDisplayDblClick dbl_click,Pointer dbl_click_data,TableDisplayLeftInRed left_in_red,Pointer left_in_red_data)4385 extern DialoG EditableTableDisplayDialog (GrouP parent, Int4 width, Int4 height,
4386                                   Int4 frozen_header, Int4 frozen_left,
4387                                   TableDisplayDblClick dbl_click,
4388                                   Pointer dbl_click_data,
4389                                   TableDisplayLeftInRed left_in_red,
4390                                   Pointer left_in_red_data)
4391 {
4392   TableDisplayPtr dlg;
4393   GrouP           p;
4394 
4395   dlg = (TableDisplayPtr) MemNew (sizeof (TableDisplayData));
4396   if (dlg == NULL)
4397   {
4398     return NULL;
4399   }
4400   p = HiddenGroup (parent, -1, 0, NULL);
4401   SetObjectExtra (p, dlg, CleanupTableDisplayDialog);
4402 
4403   dlg->dialog = (DialoG) p;
4404   dlg->todialog = RowsToTableDisplayDialog;
4405   dlg->fromdialog = TableDisplayDialogToRows;
4406   dlg->dialogmessage = NULL;
4407   dlg->testdialog = NULL;
4408   dlg->editable = TRUE;
4409 
4410   dlg->row_list = NULL;
4411   dlg->frozen_header = frozen_header;
4412   dlg->frozen_left = frozen_left;
4413   dlg->table_inset = 4;
4414   dlg->dbl_click = dbl_click;
4415   dlg->dbl_click_data = dbl_click_data;
4416   dlg->left_in_red = left_in_red;
4417   dlg->left_in_red_data = left_in_red_data;
4418 
4419   dlg->display_font = GetTableDisplayDefaultFont ();
4420 
4421   SelectFont (dlg->display_font);
4422   dlg->char_width  = CharWidth ('0');
4423   dlg->descent = Descent ();
4424 
4425   dlg->panel = AutonomousPanel4 (p, width, height, OnDrawTableDisplay,
4426                                OnVScrollTableDisplay, OnHScrollTableDisplay,
4427                                sizeof (TableDisplayData), NULL, NULL);
4428   SetObjectExtra (dlg->panel, dlg, NULL);
4429   SetPanelClick(dlg->panel, TableDisplayOnClick, NULL, NULL, NULL);
4430   SetSlateChar ((SlatE) dlg->panel, EdTableOnKey);
4431 
4432   return (DialoG) p;
4433 }
4434 
4435 
4436 typedef struct multiselectdialog
4437 {
4438   DIALOG_MESSAGE_BLOCK
4439   DoC                  doc;
4440   ValNodePtr           selected_list;
4441   ParData              listPar;
4442   ColData              listCol;
4443   Int4                 num_choices;
4444   Nlm_ChangeNotifyProc change_notify;
4445   Pointer              change_userdata;
4446 } MultiSelectDialogData, PNTR MultiSelectDialogPtr;
4447 
DataToMultiSelectionDialog(DialoG d,Pointer userdata)4448 static void DataToMultiSelectionDialog (DialoG d, Pointer userdata)
4449 {
4450   MultiSelectDialogPtr dlg;
4451   ValNodePtr           vnp;
4452   Boolean              all_selected = FALSE;
4453 
4454   dlg = (MultiSelectDialogPtr) GetObjectExtra (d);
4455   if (dlg == NULL) return;
4456 
4457   dlg->selected_list = ValNodeFree (dlg->selected_list);
4458   for (vnp = (ValNodePtr) userdata; vnp != NULL && ! all_selected; vnp = vnp->next)
4459   {
4460     if (vnp->data.intvalue == 1)
4461     {
4462       all_selected = TRUE;
4463     }
4464     else
4465     {
4466       ValNodeAddInt (&(dlg->selected_list), vnp->data.intvalue, vnp->data.intvalue);
4467     }
4468   }
4469   if (all_selected)
4470   {
4471     dlg->selected_list = ValNodeFree (dlg->selected_list);
4472     ValNodeAddInt (&(dlg->selected_list), 1, 1);
4473   }
4474   InvalDocRows (dlg->doc, 0, 0, 0);
4475 }
4476 
MultiSelectionDialogToData(DialoG d)4477 static Pointer MultiSelectionDialogToData (DialoG d)
4478 {
4479   MultiSelectDialogPtr dlg;
4480   ValNodePtr           output_list = NULL, vnp;
4481 
4482   dlg = (MultiSelectDialogPtr) GetObjectExtra (d);
4483   if (dlg == NULL) return NULL;
4484 
4485   for (vnp = dlg->selected_list; vnp != NULL; vnp = vnp->next)
4486   {
4487     ValNodeAddInt (&output_list, vnp->choice, vnp->data.intvalue);
4488   }
4489   return output_list;
4490 }
4491 
4492 static void
AddChoiceToSelection(Int2 choice_num,Boolean remove_other_choices,MultiSelectDialogPtr dlg)4493 AddChoiceToSelection
4494 (Int2                 choice_num,
4495  Boolean              remove_other_choices,
4496  MultiSelectDialogPtr dlg)
4497 {
4498   ValNodePtr already_sel, vnp;
4499 
4500   if (dlg == NULL || dlg->doc == NULL || choice_num < 1)
4501   {
4502     return;
4503   }
4504 
4505   if (choice_num == 1)
4506   {
4507     remove_other_choices = TRUE;
4508   }
4509   else
4510   {
4511     /* if we have added a choice other than "All", remove the "All"
4512      * selection if it was present.
4513      */
4514     ValNodeFree (ValNodeExtractList (&(dlg->selected_list), 1));
4515     InvalDocRows (dlg->doc, 1, 1, 1);
4516   }
4517 
4518   already_sel = ValNodeExtractList (&(dlg->selected_list), choice_num);
4519   if (already_sel == NULL)
4520   {
4521     if (remove_other_choices)
4522     {
4523       /* delete old selections */
4524       for (vnp = dlg->selected_list; vnp != NULL; vnp = vnp->next)
4525       {
4526         InvalDocRows (dlg->doc, vnp->choice, 1, 1);
4527       }
4528       dlg->selected_list = ValNodeFree (dlg->selected_list);
4529       ValNodeAddInt (&dlg->selected_list, choice_num, choice_num);
4530       InvalDocRows (dlg->doc, choice_num, 1, 1);
4531     }
4532     else
4533     {
4534       /* add new selection */
4535       ValNodeAddInt (&(dlg->selected_list), choice_num, choice_num);
4536       InvalDocRows (dlg->doc, choice_num, 1, 1);
4537     }
4538   }
4539   else
4540   {
4541     already_sel = ValNodeFree (already_sel);
4542     InvalDocRows (dlg->doc, choice_num, 1, 1);
4543   }
4544   if (dlg->change_notify != NULL)
4545   {
4546     (dlg->change_notify) (dlg->change_userdata);
4547   }
4548 }
4549 
SelectChoice(DoC d,PoinT pt)4550 static void SelectChoice (DoC d, PoinT pt)
4551 {
4552   Int2      item, row;
4553   Boolean   remove_other_choices;
4554   MultiSelectDialogPtr dlg;
4555 
4556   remove_other_choices = ! ctrlKey;
4557 
4558   dlg = (MultiSelectDialogPtr) GetObjectExtra (d);
4559   if (dlg == NULL) return;
4560 
4561   MapDocPoint (d, pt, &item, &row, NULL, NULL);
4562   AddChoiceToSelection (item, remove_other_choices, dlg);
4563 }
4564 
ChoiceHighlight(DoC doc,Int2 item,Int2 row,Int2 col)4565 static Boolean ChoiceHighlight (DoC doc, Int2 item, Int2 row, Int2 col)
4566 {
4567   MultiSelectDialogPtr dlg;
4568   ValNodePtr           vnp;
4569 
4570   dlg = (MultiSelectDialogPtr) GetObjectExtra (doc);
4571   if (dlg == NULL) return FALSE;
4572 
4573   for (vnp = dlg->selected_list; vnp != NULL; vnp = vnp->next)
4574   {
4575     if (vnp->data.intvalue == item)
4576     {
4577       return TRUE;
4578     }
4579   }
4580   return FALSE;
4581 }
4582 
ChoiceOnKey(SlatE s,Char ch)4583 static void ChoiceOnKey (SlatE s, Char ch)
4584 {
4585   MultiSelectDialogPtr dlg;
4586   CharPtr              str;
4587   Int2                 start_pos;
4588   Boolean              found = FALSE;
4589   ValNodePtr           vnp;
4590 
4591   dlg = (MultiSelectDialogPtr) GetObjectExtra (s);
4592   if (dlg == NULL) return;
4593 
4594   if ( (int) ch == 0 ) return;
4595 
4596   if (isalpha (ch))
4597   {
4598     /* find the position of the last choice we added */
4599     for (vnp = dlg->selected_list; vnp != NULL && vnp->next != NULL; vnp = vnp->next)
4600     {}
4601 
4602     if (vnp == NULL)
4603     {
4604       GetOffset (dlg->doc, NULL, &start_pos);
4605       /* start pos is one less than document row */
4606       start_pos ++;
4607       /* want to start at row after top row */
4608       start_pos ++;
4609     }
4610     else
4611     {
4612       /* want to start at row after currently selected row */
4613       start_pos = vnp->choice + 1;
4614     }
4615 
4616     while (!found && start_pos <= dlg->num_choices)
4617     {
4618       str = GetDocText (dlg->doc, start_pos, 1, 1);
4619       if (tolower (str [0]) == tolower (ch))
4620       {
4621         SetOffset (dlg->doc, 0, start_pos - 1);
4622         AddChoiceToSelection (start_pos, TRUE, dlg);
4623         found = TRUE;
4624       }
4625       str = MemFree (str);
4626       start_pos ++;
4627     }
4628     if (!found)
4629     {
4630       /* start searching at the top of the list */
4631       start_pos = 1;
4632       while (!found && start_pos <= dlg->num_choices)
4633       {
4634         str = GetDocText (dlg->doc, start_pos, 1, 1);
4635         if (tolower (str [0]) == tolower (ch))
4636         {
4637           SetOffset (dlg->doc, 0, start_pos - 1);
4638           AddChoiceToSelection (start_pos, TRUE, dlg);
4639           found = TRUE;
4640         }
4641         str = MemFree (str);
4642         start_pos ++;
4643       }
4644     }
4645   }
4646   else if (ch == NLM_DOWN)
4647   {
4648     /* down key */
4649     if (dlg->selected_list == NULL)
4650     {
4651       GetOffset (dlg->doc, NULL, &start_pos);
4652       start_pos ++;
4653     }
4654     else
4655     {
4656       start_pos = dlg->selected_list->choice;
4657     }
4658     start_pos ++;
4659 
4660     if (start_pos <= dlg->num_choices)
4661     {
4662       SetOffset (dlg->doc, 0, start_pos - 1);
4663       AddChoiceToSelection (start_pos, TRUE, dlg);
4664       InvalDocRows (dlg->doc, 0, 0, 0);
4665     }
4666   }
4667   else if (ch == NLM_UP)
4668   {
4669     /* up key */
4670     if (dlg->selected_list == NULL)
4671     {
4672       GetOffset (dlg->doc, NULL, &start_pos);
4673       start_pos ++;
4674     }
4675     else
4676     {
4677       start_pos = dlg->selected_list->choice;
4678     }
4679     start_pos --;
4680     if (start_pos > 0)
4681     {
4682       SetOffset (dlg->doc, 0, start_pos - 1);
4683       AddChoiceToSelection (start_pos, TRUE, dlg);
4684       InvalDocRows (dlg->doc, 0, 0, 0);
4685     }
4686   }
4687 }
4688 
4689 static DialoG
MultiSelectDialog(GrouP parent,ValNodePtr choice_list,Int4 list_height,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)4690 MultiSelectDialog
4691 (GrouP      parent,
4692  ValNodePtr choice_list,
4693  Int4       list_height,
4694  Nlm_ChangeNotifyProc     change_notify,
4695  Pointer                  change_userdata)
4696 {
4697   MultiSelectDialogPtr dlg;
4698   GrouP                p;
4699   Int4                 height;
4700   Int4                 width;
4701   RecT                 r;
4702   ValNodePtr           vnp;
4703 
4704   if (choice_list == NULL)
4705   {
4706     return NULL;
4707   }
4708   dlg = (MultiSelectDialogPtr) MemNew (sizeof (MultiSelectDialogData));
4709   if (dlg == NULL)
4710   {
4711     return NULL;
4712   }
4713 
4714   p = HiddenGroup (parent, -1, 0, NULL);
4715   SetObjectExtra (p, dlg, StdCleanupExtraProc);
4716 
4717   dlg->dialog = (DialoG) p;
4718   dlg->todialog = DataToMultiSelectionDialog;
4719   dlg->fromdialog = MultiSelectionDialogToData;
4720   dlg->dialogmessage = NULL;
4721   dlg->testdialog = NULL;
4722 
4723   dlg->selected_list = NULL;
4724   dlg->change_notify = change_notify;
4725   dlg->change_userdata = change_userdata;
4726 
4727 
4728   SelectFont (systemFont);
4729   width = 0;
4730   for (vnp = choice_list; vnp != NULL; vnp = vnp->next)
4731   {
4732     width = MAX (width, StringWidth (vnp->data.ptrvalue) + 2);
4733   }
4734 
4735   dlg->num_choices = ValNodeLen (choice_list) + 1;
4736 
4737   height = LineHeight ();
4738   dlg->doc = DocumentPanel (p, width, height * list_height);
4739   SetObjectExtra (dlg->doc, dlg, NULL);
4740 
4741   dlg->listPar.openSpace = FALSE;
4742   dlg->listPar.keepWithNext = FALSE;
4743   dlg->listPar.keepTogether = FALSE;
4744   dlg->listPar.newPage = FALSE;
4745   dlg->listPar.tabStops = FALSE;
4746   dlg->listPar.minLines = 0;
4747   dlg->listPar.minHeight = 0;
4748 
4749   ObjectRect (dlg->doc, &r);
4750   InsetRect (&r, 4, 4);
4751   dlg->listCol.pixWidth = r.right - r.left;
4752   dlg->listCol.pixInset = 0;
4753   dlg->listCol.charWidth = 160;
4754   dlg->listCol.charInset = 0;
4755   dlg->listCol.font = systemFont;
4756   dlg->listCol.just = 'l';
4757   dlg->listCol.wrap = FALSE;
4758   dlg->listCol.bar = FALSE;
4759   dlg->listCol.underline = FALSE;
4760   dlg->listCol.left = FALSE;
4761   dlg->listCol.last = TRUE;
4762 
4763   AppendText (dlg->doc, "All", &(dlg->listPar), &(dlg->listCol), programFont);
4764   for (vnp = choice_list; vnp != NULL; vnp = vnp->next)
4765   {
4766       AppendText (dlg->doc, vnp->data.ptrvalue, &(dlg->listPar), &(dlg->listCol), programFont);
4767   }
4768   SetDocAutoAdjust (dlg->doc, FALSE);
4769   SetDocProcs (dlg->doc, SelectChoice, NULL, NULL, NULL);
4770   SetDocShade (dlg->doc, NULL, NULL, ChoiceHighlight, NULL);
4771   SetSlateChar ((SlatE) dlg->doc, ChoiceOnKey);
4772   InvalDocument (dlg->doc);
4773 
4774   return (DialoG) p;
4775 }
4776 
4777 typedef struct selectiondialog
4778 {
4779   DIALOG_MESSAGE_BLOCK
4780   DialoG     multi_select_dlg;
4781   LisT       list_ctrl;
4782   PopuP      popup_ctrl;
4783   Int4       num_choices;
4784   CharPtr    err_msg;
4785   Nlm_ChangeNotifyProc     change_notify;
4786   Pointer                  change_userdata;
4787 } SelectionDialogData, PNTR SelectionDialogPtr;
4788 
ResetSelectionDialog(SelectionDialogPtr dlg)4789 static void ResetSelectionDialog (SelectionDialogPtr dlg)
4790 {
4791   if (dlg != NULL)
4792   {
4793     if (dlg->multi_select_dlg != NULL)
4794     {
4795       PointerToDialog (dlg->multi_select_dlg, NULL);
4796     }
4797     else if (dlg->list_ctrl != NULL)
4798     {
4799       SetValue (dlg->list_ctrl, 0);
4800     }
4801     else if (dlg->popup_ctrl != NULL)
4802     {
4803       SetValue (dlg->popup_ctrl, 0);
4804     }
4805   }
4806 }
4807 
SelectionDialogChanged(LisT l)4808 static void SelectionDialogChanged (LisT l)
4809 {
4810   SelectionDialogPtr dlg;
4811 
4812   dlg = (SelectionDialogPtr) GetObjectExtra (l);
4813   if (dlg == NULL)
4814   {
4815     return;
4816   }
4817 
4818   if (dlg->change_notify != NULL)
4819   {
4820     (dlg->change_notify)(dlg->change_userdata);
4821   }
4822 }
4823 
SelectionDialogPopupChanged(PopuP p)4824 static void SelectionDialogPopupChanged (PopuP p)
4825 {
4826   SelectionDialogPtr dlg;
4827 
4828   dlg = (SelectionDialogPtr) GetObjectExtra (p);
4829   if (dlg == NULL)
4830   {
4831     return;
4832   }
4833 
4834   if (dlg->change_notify != NULL)
4835   {
4836     (dlg->change_notify)(dlg->change_userdata);
4837   }
4838 }
4839 
SelectionListToSelectionDialog(DialoG d,Pointer userdata)4840 static void SelectionListToSelectionDialog (DialoG d, Pointer userdata)
4841 {
4842   SelectionDialogPtr dlg;
4843   ValNodePtr         selected_list;
4844 
4845   dlg = (SelectionDialogPtr) GetObjectExtra (d);
4846   if (dlg == NULL)
4847   {
4848     return;
4849   }
4850 
4851   ResetSelectionDialog (dlg);
4852   selected_list = (ValNodePtr) userdata;
4853   if (dlg->multi_select_dlg != NULL)
4854   {
4855     PointerToDialog (dlg->multi_select_dlg, selected_list);
4856   }
4857   else if (dlg->list_ctrl != NULL)
4858   {
4859     if (selected_list == NULL)
4860     {
4861       SetValue (dlg->list_ctrl, 0);
4862     }
4863     else
4864     {
4865       SetValue (dlg->list_ctrl, selected_list->data.intvalue);
4866     }
4867   }
4868   else if (dlg->popup_ctrl)
4869   {
4870     if (selected_list == NULL)
4871     {
4872       SetValue (dlg->popup_ctrl, 0);
4873     }
4874     else
4875     {
4876       SetValue (dlg->popup_ctrl, selected_list->data.intvalue);
4877     }
4878   }
4879 }
4880 
4881 
SelectionDialogToSelectionList(DialoG d)4882 static Pointer SelectionDialogToSelectionList (DialoG d)
4883 {
4884   SelectionDialogPtr dlg;
4885   ValNodePtr         sel_list = NULL, vnp;
4886   Int4               i = 0;
4887 
4888   dlg = (SelectionDialogPtr) GetObjectExtra (d);
4889   if (dlg == NULL)
4890   {
4891     return NULL;
4892   }
4893 
4894   if (dlg->multi_select_dlg != NULL)
4895   {
4896     sel_list = (ValNodePtr) DialogToPointer (dlg->multi_select_dlg);
4897     if (sel_list != NULL && sel_list->choice == 1)
4898     {
4899       sel_list = ValNodeFree (sel_list);
4900       for (i = 2; i <= dlg->num_choices; i++)
4901       {
4902         ValNodeAddInt (&sel_list, 0, i - 1);
4903       }
4904     }
4905     else
4906     {
4907       for (vnp = sel_list; vnp != NULL; vnp = vnp->next)
4908       {
4909         vnp->choice = 0;
4910         vnp->data.intvalue = vnp->data.intvalue - 1;
4911       }
4912     }
4913   }
4914   else
4915   {
4916     if (dlg->list_ctrl != NULL)
4917     {
4918       i = GetValue (dlg->list_ctrl);
4919     }
4920     else if (dlg->popup_ctrl != NULL)
4921     {
4922       i = GetValue (dlg->popup_ctrl);
4923     }
4924     if (i > 0)
4925     {
4926       ValNodeAddInt (&sel_list, 0, i);
4927     }
4928   }
4929   return (Pointer) sel_list;
4930 }
4931 
SelectionDialogMessage(DialoG d,Int2 mssg)4932 static void SelectionDialogMessage (DialoG d, Int2 mssg)
4933 
4934 {
4935   SelectionDialogPtr dlg;
4936   ValNode            vn;
4937 
4938   dlg = (SelectionDialogPtr) GetObjectExtra (d);
4939   if (dlg != NULL) {
4940     switch (mssg) {
4941       case VIB_MSG_INIT :
4942         /* reset list */
4943         ResetSelectionDialog (dlg);
4944         break;
4945       case VIB_MSG_ENTER :
4946         if (dlg->multi_select_dlg != NULL)
4947         {
4948           Select (dlg->multi_select_dlg);
4949         }
4950         else if (dlg->list_ctrl != NULL)
4951         {
4952           Select (dlg->list_ctrl);
4953         }
4954         else if (dlg->popup_ctrl != NULL)
4955         {
4956           Select (dlg->popup_ctrl);
4957         }
4958         break;
4959       case NUM_VIB_MSG + 1:
4960         if (dlg->multi_select_dlg != NULL)
4961         {
4962           vn.next = NULL;
4963           vn.choice = 1;
4964           vn.data.intvalue = 1;
4965           PointerToDialog (dlg->multi_select_dlg, &vn);
4966         }
4967         else if (dlg->list_ctrl != NULL)
4968         {
4969           SetItemStatus (dlg->list_ctrl, 1, TRUE);
4970         }
4971         else if (dlg->popup_ctrl != NULL)
4972         {
4973           SetValue (dlg->popup_ctrl, 1);
4974         }
4975         SelectionDialogChanged (dlg->list_ctrl);
4976         break;
4977       default :
4978         break;
4979     }
4980   }
4981 }
4982 
TestSelectionDialog(DialoG d)4983 static ValNodePtr TestSelectionDialog (DialoG d)
4984 
4985 {
4986   SelectionDialogPtr dlg;
4987   ValNodePtr         head = NULL, vnp;
4988   Boolean            any_selected = FALSE;
4989 
4990   dlg = (SelectionDialogPtr) GetObjectExtra (d);
4991   if (dlg != NULL) {
4992     if (dlg->multi_select_dlg != NULL)
4993     {
4994       vnp = DialogToPointer (dlg->multi_select_dlg);
4995       if (vnp != NULL)
4996       {
4997         any_selected = TRUE;
4998         vnp = ValNodeFree (vnp);
4999       }
5000     }
5001     else if (dlg->list_ctrl != NULL)
5002     {
5003       if (GetValue (dlg->list_ctrl) > 0)
5004       {
5005         any_selected = TRUE;
5006       }
5007     }
5008     else if (dlg->popup_ctrl != NULL)
5009     {
5010       if (GetValue (dlg->popup_ctrl) > 0)
5011       {
5012         any_selected = TRUE;
5013       }
5014     }
5015     if (!any_selected)
5016     {
5017       head = AddStringToValNodeChain (head, dlg->err_msg, 1);
5018     }
5019   }
5020   return head;
5021 }
5022 
5023 /* err_msg is the message to put in the results from TestDialog if nothing is selected */
5024 /* choice_list should be a valnode list of strings to use for the names of the choices. */
5025 /* All is automatically included as a choice if allow_multi is true. */
5026 /* The ValNodeList returned is a list of integers indicating the position of the item
5027  * in the list - 1 is the first item, 2 is the second item, etc. */
SelectionDialogExEx(GrouP h,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata,Boolean allow_multi,CharPtr err_msg,ValNodePtr choice_list,Int2 list_height,Boolean force_list,Boolean force_popup)5028 extern DialoG SelectionDialogExEx
5029 (GrouP h,
5030  Nlm_ChangeNotifyProc     change_notify,
5031  Pointer                  change_userdata,
5032  Boolean                  allow_multi,
5033  CharPtr                  err_msg,
5034  ValNodePtr               choice_list,
5035  Int2                     list_height,
5036  Boolean                  force_list,
5037  Boolean                  force_popup)
5038 
5039 {
5040   SelectionDialogPtr  dlg;
5041   GrouP               p;
5042   ValNodePtr          vnp;
5043   Int4                num_choices;
5044   Int4                list_width = 8, item_width;
5045 
5046   if (choice_list == NULL)
5047   {
5048     return NULL;
5049   }
5050 
5051   dlg = (SelectionDialogPtr) MemNew (sizeof (SelectionDialogData));
5052   if (dlg == NULL)
5053   {
5054     return NULL;
5055   }
5056 
5057   p = HiddenGroup (h, 0, 2, NULL);
5058   SetObjectExtra (p, dlg, StdCleanupExtraProc);
5059 
5060   dlg->dialog = (DialoG) p;
5061   dlg->todialog = SelectionListToSelectionDialog;
5062   dlg->fromdialog = SelectionDialogToSelectionList;
5063   dlg->dialogmessage = SelectionDialogMessage;
5064   dlg->testdialog = TestSelectionDialog;
5065   dlg->change_notify = change_notify;
5066   dlg->change_userdata = change_userdata;
5067   dlg->err_msg = err_msg;
5068 
5069   num_choices = ValNodeLen (choice_list);
5070 
5071   if (allow_multi)
5072   {
5073     dlg->multi_select_dlg = MultiSelectDialog (p, choice_list, list_height,
5074                                                change_notify, change_userdata);
5075     dlg->num_choices = num_choices + 1;
5076   }
5077   else
5078   {
5079     if (force_popup || (num_choices < 20 && ! force_list) || list_height == 1)
5080     {
5081       dlg->popup_ctrl = PopupList (p, TRUE, SelectionDialogPopupChanged);
5082       SetObjectExtra (dlg->popup_ctrl, dlg, NULL);
5083       for (vnp = choice_list; vnp != NULL; vnp = vnp->next) {
5084         PopupItem (dlg->popup_ctrl, vnp->data.ptrvalue);
5085       }
5086     }
5087     else
5088     {
5089       SelectFont (systemFont);
5090       for (vnp = choice_list; vnp != NULL; vnp = vnp->next) {
5091         item_width = StringWidth (vnp->data.ptrvalue);
5092         list_width = MAX (list_width, item_width);
5093       }
5094       /* add padding */
5095       list_width += StringWidth ("W");
5096       list_width = list_width / Nlm_stdCharWidth;
5097       dlg->list_ctrl = SingleList (p, list_width, list_height, SelectionDialogChanged);
5098       SetObjectExtra (dlg->list_ctrl, dlg, NULL);
5099       for (vnp = choice_list; vnp != NULL; vnp = vnp->next) {
5100         ListItem (dlg->list_ctrl, vnp->data.ptrvalue);
5101       }
5102     }
5103     dlg->num_choices = num_choices;
5104   }
5105 
5106   return (DialoG) p;
5107 }
5108 
5109 
SelectionDialogEx(GrouP h,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata,Boolean allow_multi,CharPtr err_msg,ValNodePtr choice_list,Int2 list_height,Boolean force_list)5110 extern DialoG SelectionDialogEx
5111 (GrouP h,
5112  Nlm_ChangeNotifyProc     change_notify,
5113  Pointer                  change_userdata,
5114  Boolean                  allow_multi,
5115  CharPtr                  err_msg,
5116  ValNodePtr               choice_list,
5117  Int2                     list_height,
5118  Boolean                  force_list)
5119 
5120 {
5121   return SelectionDialogExEx (h, change_notify, change_userdata, allow_multi, err_msg, choice_list, list_height, force_list, FALSE);
5122 }
5123 
5124 
SelectionDialog(GrouP h,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata,Boolean allow_multi,CharPtr err_msg,ValNodePtr choice_list,Int2 list_height)5125 extern DialoG SelectionDialog
5126 (GrouP h,
5127  Nlm_ChangeNotifyProc     change_notify,
5128  Pointer                  change_userdata,
5129  Boolean                  allow_multi,
5130  CharPtr                  err_msg,
5131  ValNodePtr               choice_list,
5132  Int2                     list_height)
5133 {
5134   return SelectionDialogEx (h, change_notify, change_userdata, allow_multi,
5135                           err_msg, choice_list, list_height, FALSE);
5136 }
5137 
5138 typedef struct valnodeselection
5139 {
5140   DIALOG_MESSAGE_BLOCK
5141   DialoG           list_dlg;
5142   ValNodePtr       choice_list;
5143 
5144   Boolean             is_multi;
5145   FreeValNodeProc     free_vn_proc;
5146   CopyValNodeDataProc copy_vn_proc;
5147   MatchValNodeProc    match_vn_proc;
5148   RemapValNodeProc    remap_vn_proc;
5149 
5150 } ValNodeSelectionData, PNTR ValNodeSelectionPtr;
5151 
ValNodeSelectionListToDialog(DialoG d,Pointer userdata)5152 static void ValNodeSelectionListToDialog (DialoG d, Pointer userdata)
5153 {
5154   ValNodeSelectionPtr dlg;
5155   ValNodePtr          item_list, vnp_list, vnp_sel, pos_list = NULL;
5156   Int4                i;
5157   Boolean             found;
5158 
5159   dlg = (ValNodeSelectionPtr) GetObjectExtra (d);
5160   if (dlg == NULL)
5161   {
5162     return;
5163   }
5164 
5165   /* reset list control */
5166   PointerToDialog (dlg->list_dlg, NULL);
5167 
5168   item_list = (ValNodePtr) userdata;
5169   for (vnp_list = item_list; vnp_list != NULL; vnp_list = vnp_list->next)
5170   {
5171     found = FALSE;
5172     i = 1;
5173     if (dlg->is_multi) {
5174       i++;
5175     }
5176     for (vnp_sel = dlg->choice_list;
5177          vnp_sel != NULL && !found;
5178          vnp_sel = vnp_sel->next, i++)
5179     {
5180       if ((dlg->match_vn_proc)(vnp_sel, vnp_list))
5181       {
5182         found = TRUE;
5183         ValNodeAddInt (&pos_list, 0, i);
5184       }
5185     }
5186   }
5187   PointerToDialog (dlg->list_dlg, pos_list);
5188   ValNodeFree (pos_list);
5189 }
5190 
ValNodeSelectionDialogToList(DialoG d)5191 static Pointer ValNodeSelectionDialogToList (DialoG d)
5192 {
5193   ValNodeSelectionPtr dlg;
5194   ValNodePtr          item_list = NULL, vnp_list, pos_list, vnp_pos;
5195   ValNodePtr          vnp_copy, vnp_last = NULL, vnp_test;
5196   Int4                i;
5197   Boolean             found;
5198 
5199   dlg = (ValNodeSelectionPtr) GetObjectExtra (d);
5200   if (dlg == NULL)
5201   {
5202     return NULL;
5203   }
5204 
5205   pos_list = DialogToPointer (dlg->list_dlg);
5206   for (vnp_pos = pos_list; vnp_pos != NULL; vnp_pos = vnp_pos->next)
5207   {
5208     for (i = 1, vnp_list = dlg->choice_list;
5209          i < vnp_pos->data.intvalue && vnp_list != NULL;
5210          i++, vnp_list = vnp_list->next)
5211     {
5212     }
5213     if (i == vnp_pos->data.intvalue && vnp_list != NULL)
5214     {
5215       /* make sure we don't already have this value in the list */
5216       for (vnp_test = item_list, found = FALSE;
5217            vnp_test != NULL && !found;
5218            vnp_test = vnp_test->next)
5219       {
5220         found = (dlg->match_vn_proc) (vnp_list, vnp_test);
5221       }
5222 
5223       if (found)
5224       {
5225         continue;
5226       }
5227       vnp_copy = (dlg->copy_vn_proc) (vnp_list);
5228       if (vnp_last == NULL)
5229       {
5230         item_list = vnp_copy;
5231       }
5232       else
5233       {
5234         vnp_last->next = vnp_copy;
5235       }
5236       vnp_last = vnp_copy;
5237     }
5238   }
5239   if (dlg->remap_vn_proc != NULL)
5240   {
5241     item_list = (dlg->remap_vn_proc) (item_list);
5242   }
5243   return item_list;
5244 }
5245 
CleanupValNodeSelectionDialogForm(GraphiC g,VoidPtr data)5246 static void CleanupValNodeSelectionDialogForm (GraphiC g, VoidPtr data)
5247 
5248 {
5249   ValNodeSelectionPtr dlg;
5250   ValNodePtr          vnp;
5251 
5252   dlg = (ValNodeSelectionPtr) data;
5253   if (dlg != NULL) {
5254     if (dlg->free_vn_proc != NULL)
5255     {
5256       for (vnp = dlg->choice_list; vnp != NULL; vnp = vnp->next)
5257       {
5258         (dlg->free_vn_proc) (vnp);
5259       }
5260     }
5261     dlg->choice_list = ValNodeFree (dlg->choice_list);
5262   }
5263   StdCleanupExtraProc (g, data);
5264 }
5265 
ValNodeSelectionDialogMessage(DialoG d,Int2 mssg)5266 static void ValNodeSelectionDialogMessage (DialoG d, Int2 mssg)
5267 
5268 {
5269   ValNodeSelectionPtr dlg;
5270 
5271   dlg = (ValNodeSelectionPtr) GetObjectExtra (d);
5272   if (dlg != NULL) {
5273     switch (mssg) {
5274       case VIB_MSG_INIT :
5275         /* reset list */
5276         PointerToDialog (dlg->list_dlg, NULL);
5277         break;
5278       case VIB_MSG_SELECT:
5279         SendMessageToDialog (dlg->list_dlg, VIB_MSG_SELECT);
5280         break;
5281       case VIB_MSG_ENTER :
5282         SendMessageToDialog (dlg->list_dlg, VIB_MSG_ENTER);
5283         break;
5284       case NUM_VIB_MSG + 1:
5285         SendMessageToDialog (dlg->list_dlg, NUM_VIB_MSG + 1);
5286         break;
5287       default :
5288         break;
5289     }
5290   }
5291 }
5292 
TestValNodeSelectionDialog(DialoG d)5293 static ValNodePtr TestValNodeSelectionDialog (DialoG d)
5294 
5295 {
5296   ValNodeSelectionPtr  dlg;
5297   ValNodePtr           head = NULL;
5298 
5299   dlg = (ValNodeSelectionPtr) GetObjectExtra (d);
5300   if (dlg != NULL) {
5301     head = TestDialog (dlg->list_dlg);
5302   }
5303   return head;
5304 }
5305 
ValNodeSelectionDialogExEx(GrouP h,ValNodePtr choice_list,Int2 list_height,NameFromValNodeProc name_proc,FreeValNodeProc free_vn_proc,CopyValNodeDataProc copy_vn_proc,MatchValNodeProc match_vn_proc,CharPtr err_name,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata,Boolean allow_multi,Boolean force_list,Boolean force_popup,RemapValNodeProc remap_vn_proc)5306 extern DialoG ValNodeSelectionDialogExEx
5307 (GrouP h,
5308  ValNodePtr               choice_list,
5309  Int2                     list_height,
5310  NameFromValNodeProc      name_proc,
5311  FreeValNodeProc          free_vn_proc,
5312  CopyValNodeDataProc      copy_vn_proc,
5313  MatchValNodeProc         match_vn_proc,
5314  CharPtr                  err_name,
5315  Nlm_ChangeNotifyProc     change_notify,
5316  Pointer                  change_userdata,
5317  Boolean                  allow_multi,
5318  Boolean                  force_list,
5319  Boolean                  force_popup,
5320  RemapValNodeProc         remap_vn_proc)
5321 {
5322   ValNodeSelectionPtr  dlg;
5323   GrouP                p;
5324   ValNodePtr           choice_name_list = NULL, vnp;
5325 
5326   if (choice_list == NULL || name_proc == NULL
5327       || copy_vn_proc == NULL || match_vn_proc == NULL)
5328   {
5329     return NULL;
5330   }
5331 
5332   dlg = (ValNodeSelectionPtr) MemNew (sizeof (ValNodeSelectionData));
5333   if (dlg == NULL)
5334   {
5335     return NULL;
5336   }
5337 
5338   p = HiddenGroup (h, 1, 0, NULL);
5339   SetObjectExtra (p, dlg, CleanupValNodeSelectionDialogForm);
5340 
5341   dlg->dialog = (DialoG) p;
5342   dlg->todialog = ValNodeSelectionListToDialog;
5343   dlg->fromdialog = ValNodeSelectionDialogToList;
5344   dlg->dialogmessage = ValNodeSelectionDialogMessage;
5345   dlg->testdialog = TestValNodeSelectionDialog;
5346 
5347   dlg->choice_list = choice_list;
5348   dlg->free_vn_proc = free_vn_proc;
5349   dlg->copy_vn_proc = copy_vn_proc;
5350   dlg->match_vn_proc = match_vn_proc;
5351   dlg->remap_vn_proc = remap_vn_proc;
5352 
5353   dlg->is_multi = allow_multi;
5354 
5355   for (vnp = choice_list; vnp != NULL; vnp = vnp->next)
5356   {
5357     ValNodeAddPointer (&choice_name_list, 0, (name_proc) (vnp));
5358   }
5359 
5360   dlg->list_dlg = SelectionDialogExEx (p, change_notify, change_userdata,
5361                                    allow_multi, err_name, choice_name_list,
5362                                    list_height, force_list, force_popup);
5363   ValNodeFreeData (choice_name_list);
5364 
5365   return (DialoG) p;
5366 }
5367 
5368 
ValNodeSelectionDialogEx(GrouP h,ValNodePtr choice_list,Int2 list_height,NameFromValNodeProc name_proc,FreeValNodeProc free_vn_proc,CopyValNodeDataProc copy_vn_proc,MatchValNodeProc match_vn_proc,CharPtr err_name,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata,Boolean allow_multi,Boolean force_list,RemapValNodeProc remap_vn_proc)5369 extern DialoG ValNodeSelectionDialogEx
5370 (GrouP h,
5371  ValNodePtr               choice_list,
5372  Int2                     list_height,
5373  NameFromValNodeProc      name_proc,
5374  FreeValNodeProc          free_vn_proc,
5375  CopyValNodeDataProc      copy_vn_proc,
5376  MatchValNodeProc         match_vn_proc,
5377  CharPtr                  err_name,
5378  Nlm_ChangeNotifyProc     change_notify,
5379  Pointer                  change_userdata,
5380  Boolean                  allow_multi,
5381  Boolean                  force_list,
5382  RemapValNodeProc         remap_vn_proc)
5383 {
5384   return ValNodeSelectionDialogExEx (h, choice_list, list_height, name_proc, free_vn_proc, copy_vn_proc,
5385                                      match_vn_proc, err_name, change_notify, change_userdata, allow_multi,
5386                                      force_list, FALSE, remap_vn_proc);
5387 }
5388 
5389 
ValNodeSelectionDialog(GrouP h,ValNodePtr choice_list,Int2 list_height,NameFromValNodeProc name_proc,FreeValNodeProc free_vn_proc,CopyValNodeDataProc copy_vn_proc,MatchValNodeProc match_vn_proc,CharPtr err_name,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata,Boolean allow_multi)5390 extern DialoG ValNodeSelectionDialog
5391 (GrouP h,
5392  ValNodePtr               choice_list,
5393  Int2                     list_height,
5394  NameFromValNodeProc      name_proc,
5395  FreeValNodeProc          free_vn_proc,
5396  CopyValNodeDataProc      copy_vn_proc,
5397  MatchValNodeProc         match_vn_proc,
5398  CharPtr                  err_name,
5399  Nlm_ChangeNotifyProc     change_notify,
5400  Pointer                  change_userdata,
5401  Boolean                  allow_multi)
5402 {
5403   return ValNodeSelectionDialogEx (h, choice_list, list_height,
5404                                    name_proc, free_vn_proc,
5405                                    copy_vn_proc, match_vn_proc, err_name,
5406                                    change_notify, change_userdata,
5407                                    allow_multi, FALSE, NULL);
5408 }
5409 
5410 
5411 typedef struct stringcombodlg {
5412  DIALOG_MESSAGE_BLOCK
5413 
5414  DialoG list;
5415  TexT   text;
5416  Nlm_ChangeNotifyProc     change_notify;
5417  Pointer                  change_userdata;
5418 } StringComboDlgData, PNTR StringComboDlgPtr;
5419 
5420 
ChangeStringComboDialogList(Pointer data)5421 static void ChangeStringComboDialogList (Pointer data)
5422 {
5423   StringComboDlgPtr dlg;
5424   ValNodePtr        vnp;
5425 
5426   dlg = (StringComboDlgPtr) data;
5427   if (dlg == NULL) {
5428     return;
5429   }
5430 
5431   vnp = DialogToPointer (dlg->list);
5432   if (vnp != NULL && vnp->data.ptrvalue != NULL) {
5433     SetTitle (dlg->text, (CharPtr) vnp->data.ptrvalue);
5434   }
5435   vnp = ValNodeFree (vnp);
5436 }
5437 
5438 
ChangeStringComboDialogText(TexT t)5439 static void ChangeStringComboDialogText (TexT t)
5440 {
5441   StringComboDlgPtr dlg;
5442 
5443   dlg = (StringComboDlgPtr) GetObjectExtra (t);
5444   if (dlg == NULL) {
5445     return;
5446   }
5447 
5448   /* to do - change list to match selection? */
5449 
5450   if (dlg->change_notify != NULL) {
5451     (dlg->change_notify)(dlg->change_userdata);
5452   }
5453 }
5454 
5455 
StringToStringComboDialog(DialoG d,Pointer data)5456 static void StringToStringComboDialog (DialoG d, Pointer data)
5457 {
5458   StringComboDlgPtr dlg;
5459   CharPtr           text;
5460 
5461   dlg = (StringComboDlgPtr) GetObjectExtra (d);
5462   if (dlg == NULL) {
5463     return;
5464   }
5465 
5466   text = (CharPtr) data;
5467   if (text == NULL) {
5468     SetTitle (dlg->text, "");
5469   } else {
5470     SetTitle (dlg->text, text);
5471   }
5472 
5473   /* to do - pick from list also? */
5474 
5475 }
5476 
5477 
StringComboDialogToString(DialoG d)5478 static Pointer StringComboDialogToString (DialoG d)
5479 {
5480   StringComboDlgPtr dlg;
5481 
5482   dlg = (StringComboDlgPtr) GetObjectExtra (d);
5483   if (dlg == NULL) {
5484     return NULL;
5485   }
5486 
5487   return JustSaveStringFromText (dlg->text);
5488 }
5489 
StringComboDialog(GrouP h,ValNodePtr choice_list,Int2 list_height,Int2 list_width,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)5490 extern DialoG StringComboDialog
5491 (GrouP h,
5492  ValNodePtr               choice_list,
5493  Int2                     list_height,
5494  Int2                     list_width,
5495  Nlm_ChangeNotifyProc     change_notify,
5496  Pointer                  change_userdata)
5497 {
5498   StringComboDlgPtr dlg;
5499   GrouP             p;
5500 
5501   dlg = (StringComboDlgPtr) MemNew (sizeof (StringComboDlgData));
5502 
5503   p = HiddenGroup (h, 0, 2, NULL);
5504   SetObjectExtra (p, dlg, StdCleanupExtraProc);
5505 
5506   dlg->dialog = (DialoG) p;
5507   dlg->todialog = StringToStringComboDialog;
5508   dlg->fromdialog = StringComboDialogToString;
5509   dlg->change_notify = change_notify;
5510   dlg->change_userdata = change_userdata;
5511 
5512   dlg->text = DialogText (p, "", list_width, ChangeStringComboDialogText);
5513   dlg->list = ValNodeSelectionDialog (p, choice_list, list_height,
5514                                       ValNodeStringName,
5515                                       ValNodeSimpleDataFree,
5516                                       ValNodeStringCopy,
5517                                       ValNodeStringMatch,
5518                                       "combo",
5519                                       ChangeStringComboDialogList, dlg, FALSE);
5520 
5521   return (DialoG) p;
5522 }
5523 
5524 
EnumAssocSelectionDialog(GrouP h,Nlm_EnumFieldAssocPtr eap,CharPtr err_name,Boolean allow_multi,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)5525 extern DialoG EnumAssocSelectionDialog
5526 (GrouP                 h,
5527  Nlm_EnumFieldAssocPtr eap,
5528  CharPtr               err_name,
5529  Boolean               allow_multi,
5530  Nlm_ChangeNotifyProc  change_notify,
5531  Pointer               change_userdata)
5532 
5533 {
5534   DialoG     dlg;
5535   ValNodePtr choice_list = NULL;
5536 
5537   if (eap == NULL)
5538   {
5539     return NULL;
5540   }
5541 
5542   while (eap->name != NULL)
5543   {
5544     if (!StringHasNoText (eap->name))
5545     {
5546       ValNodeAddPointer (&choice_list, eap->value, StringSave (eap->name));
5547     }
5548     eap++;
5549   }
5550 
5551   /* note - the ValNodeSelectionDialog will free the qual_choice_list when done */
5552   dlg = ValNodeSelectionDialog (h, choice_list, TALL_SELECTION_LIST, ValNodeStringName,
5553                                 ValNodeSimpleDataFree, ValNodeStringCopy,
5554                                 ValNodeChoiceMatch, err_name,
5555                                 change_notify, change_userdata, allow_multi);
5556 
5557   return dlg;
5558 }
5559 
ValNodeStringName(ValNodePtr vnp)5560 extern CharPtr ValNodeStringName (ValNodePtr vnp)
5561 {
5562   if (vnp == NULL || vnp->data.ptrvalue == NULL)
5563   {
5564     return NULL;
5565   }
5566   else
5567   {
5568     return StringSave (vnp->data.ptrvalue);
5569   }
5570 }
5571 
ValNodeSimpleDataFree(ValNodePtr vnp)5572 extern void ValNodeSimpleDataFree (ValNodePtr vnp)
5573 {
5574   if (vnp != NULL && vnp->data.ptrvalue != NULL)
5575   {
5576     vnp->data.ptrvalue = MemFree (vnp->data.ptrvalue);
5577   }
5578 }
5579 
ValNodeStringCopy(ValNodePtr vnp)5580 extern ValNodePtr ValNodeStringCopy (ValNodePtr vnp)
5581 {
5582   ValNodePtr vnp_copy = NULL;
5583   if (vnp != NULL)
5584   {
5585     ValNodeAddPointer (&vnp_copy, vnp->choice, StringSave (vnp->data.ptrvalue));
5586   }
5587   return vnp_copy;
5588 }
5589 
ValNodeChoiceMatch(ValNodePtr vnp1,ValNodePtr vnp2)5590 extern Boolean ValNodeChoiceMatch (ValNodePtr vnp1, ValNodePtr vnp2)
5591 {
5592   if (vnp1 == NULL || vnp2 == NULL)
5593   {
5594     return FALSE;
5595   }
5596   if (vnp1->choice == vnp2->choice)
5597   {
5598     return TRUE;
5599   }
5600   else
5601   {
5602     return FALSE;
5603   }
5604 }
5605 
ValNodeStringMatch(ValNodePtr vnp1,ValNodePtr vnp2)5606 extern Boolean ValNodeStringMatch (ValNodePtr vnp1, ValNodePtr vnp2)
5607 {
5608   if (vnp1 == NULL || vnp2 == NULL)
5609   {
5610     return FALSE;
5611   }
5612   if (StringCmp (vnp1->data.ptrvalue, vnp2->data.ptrvalue) == 0)
5613   {
5614     return TRUE;
5615   }
5616   else
5617   {
5618     return FALSE;
5619   }
5620 }
5621 
5622 typedef struct sequenceselection
5623 {
5624   DIALOG_MESSAGE_BLOCK
5625   DialoG     sequence_list_dlg;
5626   ValNodePtr sequence_choice_list;
5627 } SequenceSelectionData, PNTR SequenceSelectionPtr;
5628 
CleanupSequenceSelectionDialogForm(GraphiC g,VoidPtr data)5629 static void CleanupSequenceSelectionDialogForm (GraphiC g, VoidPtr data)
5630 
5631 {
5632   SequenceSelectionPtr dlg;
5633 
5634   dlg = (SequenceSelectionPtr) data;
5635   if (dlg != NULL) {
5636     dlg->sequence_choice_list = ValNodeFree (dlg->sequence_choice_list);
5637   }
5638   StdCleanupExtraProc (g, data);
5639 }
5640 
ResetSequenceSelectionDialog(SequenceSelectionPtr dlg)5641 static void ResetSequenceSelectionDialog (SequenceSelectionPtr dlg)
5642 {
5643   if (dlg != NULL)
5644   {
5645     PointerToDialog (dlg->sequence_list_dlg, NULL);
5646   }
5647 }
5648 
SequenceSelectionListToSequenceSelectionDialog(DialoG d,Pointer userdata)5649 static void SequenceSelectionListToSequenceSelectionDialog (DialoG d, Pointer userdata)
5650 {
5651   SequenceSelectionPtr dlg;
5652   ValNodePtr           sequence_list, vnp_list, vnp_sel, pos_list = NULL;
5653   Int4                 i;
5654   SeqIdPtr             sip;
5655   Boolean              found;
5656 
5657   dlg = (SequenceSelectionPtr) GetObjectExtra (d);
5658   if (dlg == NULL)
5659   {
5660     return;
5661   }
5662 
5663   ResetSequenceSelectionDialog (dlg);
5664   sequence_list = (ValNodePtr) userdata;
5665   for (vnp_list = sequence_list; vnp_list != NULL; vnp_list = vnp_list->next)
5666   {
5667     sip = (SeqIdPtr) vnp_list->data.ptrvalue;
5668     found = FALSE;
5669     while (sip != NULL && ! found)
5670     {
5671       for (vnp_sel = dlg->sequence_choice_list, i = 1;
5672            vnp_sel != NULL && !found;
5673            vnp_sel = vnp_sel->next, i++)
5674       {
5675         found = SeqIdIn (sip, vnp_sel->data.ptrvalue);
5676         if (found)
5677         {
5678           ValNodeAddInt (&pos_list, 0, i);
5679         }
5680       }
5681       sip = sip->next;
5682     }
5683   }
5684   PointerToDialog (dlg->sequence_list_dlg, pos_list);
5685   ValNodeFree (pos_list);
5686 }
5687 
SequenceSelectionDialogToSequenceSelectionList(DialoG d)5688 static Pointer SequenceSelectionDialogToSequenceSelectionList (DialoG d)
5689 {
5690   SequenceSelectionPtr dlg;
5691   ValNodePtr           sequence_list = NULL, vnp_list, pos_list, vnp_pos;
5692   Int4                 i;
5693 
5694   dlg = (SequenceSelectionPtr) GetObjectExtra (d);
5695   if (dlg == NULL)
5696   {
5697     return NULL;
5698   }
5699 
5700   pos_list = DialogToPointer (dlg->sequence_list_dlg);
5701   for (vnp_pos = pos_list; vnp_pos != NULL; vnp_pos = vnp_pos->next)
5702   {
5703     for (i = 1, vnp_list = dlg->sequence_choice_list;
5704          i < vnp_pos->data.intvalue && vnp_list != NULL;
5705          i++, vnp_list = vnp_list->next)
5706     {
5707     }
5708     if (i == vnp_pos->data.intvalue && vnp_list != NULL)
5709     {
5710       ValNodeAddPointer (&sequence_list, 0, vnp_list->data.ptrvalue);
5711     }
5712   }
5713   return sequence_list;
5714 }
5715 
5716 static void
GetSequenceChoiceList(SeqEntryPtr sep,ValNodePtr PNTR list,Boolean show_nucs,Boolean show_prots)5717 GetSequenceChoiceList
5718 (SeqEntryPtr sep,
5719  ValNodePtr PNTR list,
5720  Boolean show_nucs,
5721  Boolean show_prots)
5722 {
5723   BioseqPtr                bsp;
5724   BioseqSetPtr             bssp;
5725 
5726   if (sep == NULL) return;
5727 
5728   if (IS_Bioseq (sep))
5729   {
5730     bsp = (BioseqPtr) sep->data.ptrvalue;
5731     if (bsp == NULL) return;
5732     if (!show_nucs && ISA_na (bsp->mol))
5733     {
5734       return;
5735     }
5736     if (!show_prots && ISA_aa (bsp->mol))
5737     {
5738       return;
5739     }
5740     ValNodeAddPointer (list, 0, bsp->id);
5741   }
5742   else
5743   {
5744       bssp = (BioseqSetPtr) sep->data.ptrvalue;
5745     for (sep = bssp->seq_set; sep != NULL; sep = sep->next)
5746     {
5747       GetSequenceChoiceList (sep, list, show_nucs, show_prots);
5748     }
5749   }
5750 }
5751 
SequenceSelectionDialogMessage(DialoG d,Int2 mssg)5752 static void SequenceSelectionDialogMessage (DialoG d, Int2 mssg)
5753 
5754 {
5755   SequenceSelectionPtr dlg;
5756 
5757   dlg = (SequenceSelectionPtr) GetObjectExtra (d);
5758   if (dlg != NULL) {
5759     switch (mssg) {
5760       case VIB_MSG_INIT :
5761         /* reset list */
5762         ResetSequenceSelectionDialog (dlg);
5763         break;
5764       case VIB_MSG_SELECT:
5765         Select (dlg->sequence_list_dlg);
5766         break;
5767       case VIB_MSG_ENTER :
5768         Select (dlg->sequence_list_dlg);
5769         break;
5770       case NUM_VIB_MSG + 1:
5771         SendMessageToDialog (dlg->sequence_list_dlg, NUM_VIB_MSG + 1);
5772         break;
5773       default :
5774         break;
5775     }
5776   }
5777 }
5778 
TestSequenceSelectionDialog(DialoG d)5779 static ValNodePtr TestSequenceSelectionDialog (DialoG d)
5780 
5781 {
5782   SequenceSelectionPtr dlg;
5783   ValNodePtr           head = NULL;
5784 
5785   dlg = (SequenceSelectionPtr) GetObjectExtra (d);
5786   if (dlg != NULL) {
5787     head = TestDialog (dlg->sequence_list_dlg);
5788   }
5789   return head;
5790 }
5791 
5792 
SequenceSelectionDialogEx(GrouP h,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata,Boolean allow_multi,Boolean allow_none,Boolean show_nucs,Boolean show_prots,Uint2 entityID,Int4 list_height)5793 extern DialoG SequenceSelectionDialogEx
5794 (GrouP h,
5795  Nlm_ChangeNotifyProc     change_notify,
5796  Pointer                  change_userdata,
5797  Boolean                  allow_multi,
5798  Boolean                  allow_none,
5799  Boolean                  show_nucs,
5800  Boolean                  show_prots,
5801  Uint2                    entityID,
5802  Int4                     list_height)
5803 
5804 {
5805   SequenceSelectionPtr  dlg;
5806   GrouP                 p;
5807   ValNodePtr                vnp;
5808   SeqEntryPtr               sep;
5809   SeqIdPtr                  sip;
5810   Char                      tmp[128];
5811   ValNodePtr            choice_name_list = NULL;
5812 
5813   if (!show_nucs && ! show_prots)
5814   {
5815     return NULL;
5816   }
5817 
5818   sep = GetTopSeqEntryForEntityID (entityID);
5819   if (sep == NULL)
5820   {
5821     return NULL;
5822   }
5823 
5824   dlg = (SequenceSelectionPtr) MemNew (sizeof (SequenceSelectionData));
5825   if (dlg == NULL)
5826   {
5827     return NULL;
5828   }
5829 
5830   p = HiddenGroup (h, 1, 0, NULL);
5831   SetObjectExtra (p, dlg, CleanupSequenceSelectionDialogForm);
5832 
5833   dlg->dialog = (DialoG) p;
5834   dlg->todialog = SequenceSelectionListToSequenceSelectionDialog;
5835   dlg->fromdialog = SequenceSelectionDialogToSequenceSelectionList;
5836   dlg->dialogmessage = SequenceSelectionDialogMessage;
5837   dlg->testdialog = TestSequenceSelectionDialog;
5838 
5839   if (allow_none) {
5840     dlg->sequence_choice_list = ValNodeNew (NULL);
5841     dlg->sequence_choice_list->choice = 0;
5842     dlg->sequence_choice_list->data.ptrvalue = NULL;
5843   } else {
5844     dlg->sequence_choice_list = NULL;
5845   }
5846   GetSequenceChoiceList (sep, &dlg->sequence_choice_list, show_nucs, show_prots);
5847 
5848 
5849   for (vnp = dlg->sequence_choice_list; vnp != NULL; vnp = vnp->next) {
5850     sip = SeqIdFindWorst ((SeqIdPtr) vnp->data.ptrvalue);
5851     if (sip == NULL) {
5852       sprintf (tmp, " ");
5853     } else {
5854       SeqIdWrite (sip, tmp, PRINTID_REPORT, sizeof (tmp));
5855     }
5856     ValNodeAddPointer (&choice_name_list, 0, StringSave (tmp));
5857   }
5858 
5859   dlg->sequence_list_dlg = SelectionDialog (p, change_notify, change_userdata,
5860                                             allow_multi, "sequence",
5861                                             choice_name_list, list_height);
5862   ValNodeFreeData (choice_name_list);
5863   return (DialoG) p;
5864 }
5865 
5866 
SequenceSelectionDialog(GrouP h,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata,Boolean allow_multi,Boolean show_nucs,Boolean show_prots,Uint2 entityID)5867 extern DialoG SequenceSelectionDialog
5868 (GrouP h,
5869  Nlm_ChangeNotifyProc     change_notify,
5870  Pointer                  change_userdata,
5871  Boolean                  allow_multi,
5872  Boolean                  show_nucs,
5873  Boolean                  show_prots,
5874  Uint2                    entityID)
5875 {
5876   return SequenceSelectionDialogEx (h, change_notify, change_userdata, allow_multi, FALSE, show_nucs, show_prots, entityID, TALL_SELECTION_LIST);
5877 }
5878 
5879 
SubSourceTypeDialog(GrouP h,Int2 list_height,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata,Boolean allow_multi,Boolean force_list,Boolean include_note)5880 extern DialoG SubSourceTypeDialog
5881 (GrouP                    h,
5882  Int2                     list_height,
5883  Nlm_ChangeNotifyProc     change_notify,
5884  Pointer                  change_userdata,
5885  Boolean                  allow_multi,
5886  Boolean                  force_list,
5887  Boolean                  include_note)
5888 {
5889   ValNodePtr subsource_list = NULL;
5890   Int4       i;
5891 
5892   for (i = 0; current_subsource_subtype_alist[i].name != NULL; i++) {
5893     ValNodeAddPointer (&subsource_list, current_subsource_subtype_alist[i].value, StringSave (current_subsource_subtype_alist[i].name));
5894   }
5895   if (include_note) {
5896     ValNodeAddPointer (&subsource_list, SUBSRC_other, StringSave ("Note"));
5897   }
5898 
5899   return ValNodeSelectionDialogEx (h, subsource_list, list_height,
5900                                    ValNodeStringName,
5901                                    ValNodeSimpleDataFree,
5902                                    ValNodeStringCopy,
5903                                    ValNodeChoiceMatch, "subsource list",
5904                                    change_notify, change_userdata, allow_multi, force_list, NULL);
5905 }
5906 
5907 
OrgModTypeDialog(GrouP h,Int2 list_height,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata,Boolean allow_multi,Boolean force_list,Boolean include_note)5908 extern DialoG OrgModTypeDialog
5909 (GrouP                    h,
5910  Int2                     list_height,
5911  Nlm_ChangeNotifyProc     change_notify,
5912  Pointer                  change_userdata,
5913  Boolean                  allow_multi,
5914  Boolean                  force_list,
5915  Boolean                  include_note)
5916 {
5917   ValNodePtr orgmod_list = NULL;
5918   Int4       i;
5919 
5920   for (i = 0; current_orgmod_subtype_alist[i].name != NULL; i++) {
5921     ValNodeAddPointer (&orgmod_list, current_orgmod_subtype_alist[i].value, StringSave (current_orgmod_subtype_alist[i].name));
5922   }
5923   if (include_note) {
5924     ValNodeAddPointer (&orgmod_list, ORGMOD_other, StringSave ("Note"));
5925   }
5926 
5927   return ValNodeSelectionDialogEx (h, orgmod_list, list_height,
5928                                    ValNodeStringName,
5929                                    ValNodeSimpleDataFree,
5930                                    ValNodeStringCopy,
5931                                    ValNodeChoiceMatch, "orgmod list",
5932                                    change_notify, change_userdata, allow_multi, force_list, NULL);
5933 }
5934 
5935 
5936 /*
5937 static CharPtr inferencePrefix [] = {
5938   "",
5939   "similar to sequence",
5940   "similar to AA sequence",
5941   "similar to DNA sequence",
5942   "similar to RNA sequence",
5943   "similar to RNA sequence, mRNA",
5944   "similar to RNA sequence, EST",
5945   "similar to RNA sequence, other RNA",
5946   "profile",
5947   "nucleotide motif",
5948   "protein motif",
5949   "ab initio prediction",
5950   NULL
5951 };
5952 
5953 ENUM_ALIST(inference_alist)
5954   { " ",                     0 },
5955   { "similar to sequence",   1 },
5956   { "similar to protein",    2 },
5957   { "similar to DNA",        3 },
5958   { "similar to RNA",        4 },
5959   { "similar to mRNA",       5 },
5960   { "similar to EST",        6 },
5961   { "similar to other RNA",  7 },
5962   { "profile",               8 },
5963   { "nucleotide motif",      9 },
5964   { "protein motif",        10 },
5965   { "ab initio prediction", 11 },
5966 END_ENUM_ALIST
5967 
5968 Uint2 inference_types [] = {
5969   TAGLIST_POPUP, TAGLIST_TEXT
5970 };
5971 
5972 Uint2 inference_widths [] = {
5973   0, 0
5974 };
5975 
5976 static EnumFieldAssocPtr inference_popups [] = {
5977   inference_alist, NULL
5978 };
5979 
5980 extern void GBQualsToInferenceDialog (DialoG d, SeqFeatPtr sfp)
5981 
5982 {
5983   Int2               best;
5984   Char               ch;
5985   GBQualPtr          gbq;
5986   ValNodePtr         head = NULL;
5987   Int2               j;
5988   ValNodePtr         last = NULL;
5989   size_t             len;
5990   CharPtr            rest;
5991   CharPtr            str;
5992   TagListPtr         tlp;
5993   Char               tmp [32];
5994   ValNodePtr         vnp;
5995 
5996   tlp = (TagListPtr) GetObjectExtra (d);
5997   if (tlp == NULL) return;
5998 
5999   if (sfp != NULL) {
6000     for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
6001       if (StringICmp (gbq->qual, "inference") != 0) continue;
6002       if (StringHasNoText (gbq->val)) continue;
6003       vnp = ValNodeNew (last);
6004       if (vnp == NULL) continue;
6005       if (head == NULL) {
6006         head = vnp;
6007       }
6008       last = vnp;
6009 
6010       rest = NULL;
6011       best = -1;
6012       for (j = 0; inferencePrefix [j] != NULL; j++) {
6013         len = StringLen (inferencePrefix [j]);
6014         if (StringNICmp (gbq->val, inferencePrefix [j], len) != 0) continue;
6015         rest = gbq->val + len;
6016         best = j;
6017       }
6018       if (best >= 0 && inferencePrefix [best] != NULL) {
6019         if (rest != NULL) {
6020           ch = *rest;
6021           while (IS_WHITESP (ch) || ch == ':') {
6022             rest++;
6023             ch = *rest;
6024           }
6025         }
6026         len = StringLen (rest);
6027         str = MemNew (len + 16);
6028         if (str != NULL) {
6029           sprintf (tmp, "%d", (int) best);
6030           StringCpy (str, tmp);
6031           StringCat (str, "\t");
6032           StringCat (str, rest);
6033           StringCat (str, "\n");
6034         }
6035         vnp->data.ptrvalue = str;
6036       } else {
6037         len + StringLen (gbq->val);
6038         str = MemNew (len + 8);
6039         if (str != NULL) {
6040           StringCpy (str, "0");
6041           StringCat (str, "\t");
6042           StringCat (str, gbq->val);
6043           StringCat (str, "\n");
6044         }
6045         vnp->data.ptrvalue = str;
6046       }
6047     }
6048   }
6049 
6050   SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
6051   tlp->vnp = head;
6052   SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
6053   for (j = 0, vnp = tlp->vnp; vnp != NULL; j++, vnp = vnp->next) continue;
6054   tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows + 1));
6055   CorrectBarMax (tlp->bar, tlp->max);
6056   CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
6057 }
6058 
6059 static void VisStringDialogToGbquals (SeqFeatPtr sfp, DialoG d, CharPtr qual)
6060 
6061 {
6062   GBQualPtr   gbq, gbqlast = NULL;
6063   ValNodePtr  head = NULL, vnp;
6064   CharPtr     str;
6065 
6066   if (sfp == NULL || StringHasNoText (qual)) return;
6067   head = DialogToPointer (d);
6068   for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
6069     gbqlast = gbq;
6070   }
6071   for (vnp = head; vnp != NULL; vnp = vnp->next) {
6072     str = (CharPtr) vnp->data.ptrvalue;
6073     if (StringHasNoText (str)) continue;
6074     gbq = GBQualNew ();
6075     if (gbq == NULL) continue;
6076     gbq->qual = StringSave (qual);
6077     gbq->val = StringSave (str);
6078     if (gbqlast == NULL) {
6079       sfp->qual = gbq;
6080     } else {
6081       gbqlast->next = gbq;
6082     }
6083     gbqlast = gbq;
6084   }
6085   ValNodeFreeData (head);
6086 }
6087 
6088 extern void InferenceDialogToGBQuals (DialoG d, SeqFeatPtr sfp)
6089 
6090 {
6091   GBQualPtr   gbq;
6092   GBQualPtr   gbqlast = NULL;
6093   Int2        j;
6094   size_t      len;
6095   CharPtr     prefix;
6096   CharPtr     ptr;
6097   CharPtr     rest;
6098   CharPtr     str;
6099   TagListPtr  tlp;
6100   Int2        val;
6101   ValNodePtr  vnp;
6102 
6103   tlp = (TagListPtr) GetObjectExtra (d);
6104   if (tlp == NULL || sfp == NULL) return;
6105 
6106   for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
6107     gbqlast = gbq;
6108   }
6109 
6110   for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next) {
6111     if (StringHasNoText ((CharPtr) vnp->data.ptrvalue)) continue;
6112     ptr = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 0);
6113     TrimSpacesAroundString (ptr);
6114     prefix = NULL;
6115     if (StrToInt (ptr, &val)) {
6116       for (j = 0; inferencePrefix [j] != NULL; j++) {
6117         if (j == val) {
6118           prefix = inferencePrefix [j];
6119         }
6120       }
6121     }
6122     MemFree (ptr);
6123     rest = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 1);
6124     TrimSpacesAroundString (rest);
6125     if (StringDoesHaveText (prefix)) {
6126       len = StringLen (prefix) + StringLen (rest);
6127       str = (CharPtr) MemNew (len + 8);
6128       if (str != NULL) {
6129         if (StringDoesHaveText (prefix)) {
6130           StringCpy (str, prefix);
6131           if (StringDoesHaveText (rest)) {
6132             if (StringNICmp (rest, "(same species)", 14) != 0) {
6133               StringCat (str, ":");
6134             } else {
6135               StringCat (str, " ");
6136             }
6137           }
6138         }
6139         if (StringDoesHaveText (rest)) {
6140           StringCat (str, rest);
6141         }
6142         gbq = GBQualNew ();
6143         if (gbq != NULL) {
6144           gbq->qual = StringSave ("inference");
6145           gbq->val = str;
6146           if (gbqlast == NULL) {
6147             sfp->qual = gbq;
6148           } else {
6149             gbqlast->next = gbq;
6150           }
6151           gbqlast = gbq;
6152         }
6153       }
6154     }
6155     MemFree (rest);
6156   }
6157 }
6158 
6159 static DialoG CreateInferenceDialog (GrouP h, Uint2 rows, Int2 spacing, Int2 width)
6160 
6161 {
6162   inference_widths [1] = width;
6163   return CreateTagListDialog (h, rows, 2, spacing,
6164                               inference_types, inference_widths,
6165                               inference_popups, NULL, NULL);
6166 }
6167 */
6168 
6169 /* ************************ */
6170 
6171 /* inference dialog controls, utility functions */
6172 
6173 Uint2 accessionlist_types [] = {
6174   TAGLIST_POPUP, TAGLIST_TEXT
6175 };
6176 
6177 Uint2 accessionlist_widths [] = {
6178   0, 10
6179 };
6180 
ENUM_ALIST(accn_type_alist)6181 ENUM_ALIST(accn_type_alist)
6182   { " ",       0 },
6183   { "GenBank", 1 },
6184   { "EMBL",    2 },
6185   { "DDBJ",    3 },
6186   { "INSD",    4 },
6187   { "RefSeq",  5 },
6188   { "UniProt", 6 },
6189   { "Other",   7 },
6190 END_ENUM_ALIST
6191 
6192 static EnumFieldAssocPtr accessionlist_popups [] = {
6193   accn_type_alist, NULL
6194 };
6195 
6196 static CharPtr accnTypePrefix [] = {
6197   "",
6198   "GenBank",
6199   "EMBL",
6200   "DDBJ",
6201   "INSD",
6202   "RefSeq",
6203   "UniProt",
6204   "?",
6205   NULL
6206 };
6207 
6208 const Int4 numAccnTypePrefixes = sizeof (accnTypePrefix) / sizeof (CharPtr);
6209 
GetAccnTypeNum(CharPtr str)6210 static Int4 GetAccnTypeNum (CharPtr str)
6211 {
6212   Int4 i;
6213 
6214   if (StringHasNoText (str)) return 0;
6215 
6216   for (i = 1; i < numAccnTypePrefixes; i++)
6217   {
6218     if (StringCmp (accnTypePrefix[i], str) == 0)
6219     {
6220       return i;
6221     }
6222   }
6223   return 0;
6224 }
6225 
6226 
ValForOneAccession(CharPtr str)6227 static CharPtr ValForOneAccession (CharPtr str)
6228 {
6229   CharPtr cp, val_buf = NULL;
6230   CharPtr val_fmt = "%d\t%s";
6231   Int4    db;
6232 
6233   if (!StringHasNoText (str))
6234   {
6235     if (StringNCmp (str, ",?|", 3) == 0) {
6236       str += 3;
6237     } else if (StringNCmp (str, "?|", 2) == 0) {
6238       str += 2;
6239     }
6240     cp = StringChr (str, '|');
6241     if (cp == NULL)
6242     {
6243       if ((db = GetAccnTypeNum(str)) > 0)
6244       {
6245         val_buf = MemNew (sizeof (Char) * StringLen (val_fmt));
6246         sprintf (val_buf, val_fmt, db, " ");
6247       }
6248       else
6249       {
6250         val_buf = MemNew (sizeof (Char) * (StringLen (val_fmt) + StringLen (str)));
6251         sprintf (val_buf, val_fmt, 0, str);
6252       }
6253     }
6254     else
6255     {
6256       *cp = 0;
6257       db = GetAccnTypeNum (str);
6258       if (db > 0) {
6259         val_buf = MemNew (sizeof (Char) * (StringLen (val_fmt) + StringLen (cp + 1)));
6260         sprintf (val_buf, val_fmt, db, cp + 1);
6261         *cp = '|';
6262       } else {
6263         *cp = '|';
6264         db = 7;
6265         val_buf = MemNew (sizeof (Char) * (StringLen (val_fmt) + StringLen (str)));
6266         sprintf (val_buf, val_fmt, db, str);
6267       }
6268     }
6269   }
6270   return val_buf;
6271 }
6272 
AccessionListDataToDialog(DialoG d,Pointer data)6273 static void AccessionListDataToDialog (DialoG d, Pointer data)
6274 {
6275   TagListPtr    tlp;
6276   CharPtr       str, cp, val_buf;
6277   ValNodePtr    new_list = NULL, vnp;
6278   Int4          j;
6279   Int2          scroll_pos;
6280 
6281   tlp = (TagListPtr) GetObjectExtra (d);
6282 
6283   if (tlp == NULL) return;
6284   str = (CharPtr) data;
6285 
6286   cp = StringChr (str, ',');
6287   while (cp != NULL)
6288   {
6289     *cp = 0;
6290     val_buf = ValForOneAccession (str);
6291     if (val_buf != NULL)
6292     {
6293       ValNodeAddPointer (&new_list, 0, val_buf);
6294     }
6295     *cp = ',';
6296     str = cp + 1;
6297     cp = StringChr (str, ',');
6298   }
6299   val_buf = ValForOneAccession (str);
6300   if (val_buf != NULL)
6301   {
6302     ValNodeAddPointer (&new_list, 0, val_buf);
6303   }
6304 
6305   scroll_pos = 0;
6306   if (tlp->bar != NULL)
6307   {
6308     scroll_pos = GetBarValue (tlp->bar);
6309   }
6310   else if (tlp->left_bar != NULL)
6311   {
6312     scroll_pos = GetBarValue (tlp->left_bar);
6313   }
6314 
6315   SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
6316   tlp->vnp = new_list;
6317   for (j = 0, vnp = tlp->vnp; vnp != NULL; j++, vnp = vnp->next) {
6318   }
6319   tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows + 1));
6320   CorrectBarMax (tlp->bar, tlp->max);
6321   CorrectBarPage (tlp->bar, (Int2) (tlp->rows-1), (Int2) (tlp->rows-1));
6322 
6323   /* retain scroll position */
6324   if (scroll_pos > tlp->max) {
6325     scroll_pos = tlp->max;
6326   }
6327 
6328   if (tlp->bar != NULL)
6329   {
6330     CorrectBarValue (tlp->bar, scroll_pos);
6331   }
6332   if (tlp->left_bar != NULL)
6333   {
6334     CorrectBarValue (tlp->left_bar, scroll_pos);
6335   }
6336 
6337   SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
6338   Update ();
6339 
6340 }
6341 
6342 
AccessionListDialogToData(DialoG d)6343 static Pointer AccessionListDialogToData (DialoG d)
6344 {
6345   TagListPtr    tlp;
6346   ValNodePtr    vnp;
6347   Int4          result_len = 0, db;
6348   CharPtr       str, acc_str, result_str = NULL;
6349   Boolean       first_item = TRUE;
6350 
6351   tlp = (TagListPtr) GetObjectExtra (d);
6352 
6353   if (tlp == NULL) return NULL;
6354 
6355   for (vnp = tlp->vnp;
6356        vnp != NULL;
6357        vnp = vnp->next)
6358   {
6359     acc_str = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 1);
6360     str = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 0);
6361     if (!StringHasNoText (acc_str) || !StringHasNoText (str))
6362     {
6363       result_len += StringLen (acc_str);
6364       result_len += 1; /* comma */
6365       db = atoi (str);
6366       if (db >= 0 && db < numAccnTypePrefixes)
6367       {
6368         result_len += MAX (StringLen (accnTypePrefix[db]), 1);
6369       }
6370       else
6371       {
6372         result_len ++; /* will represent with ? */
6373       }
6374       result_len ++; /* for db/accession separator */
6375     }
6376     acc_str = MemFree (acc_str);
6377     str = MemFree (str);
6378   }
6379 
6380   if (result_len > 0)
6381   {
6382     result_str = (CharPtr) MemNew (sizeof (Char) * (result_len + 1));
6383     for (vnp = tlp->vnp;
6384         vnp != NULL;
6385         vnp = vnp->next)
6386     {
6387       acc_str = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 1);
6388       str = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 0);
6389       db = (str == NULL ? 0 : atoi (str));
6390       str = MemFree (str);
6391       if (!StringHasNoText (acc_str) || db > 0)
6392       {
6393         if (first_item)
6394         {
6395           first_item = FALSE;
6396         }
6397         else
6398         {
6399           StringCat (result_str, ",");
6400         }
6401 
6402         if (db > 0 && db != 7 && db < numAccnTypePrefixes)
6403         {
6404           StringCat (result_str, accnTypePrefix[db]);
6405           StringCat (result_str, "|");
6406         }
6407         if (!StringHasNoText (acc_str)) {
6408           StringCat (result_str, acc_str);
6409         }
6410       }
6411       acc_str = MemFree (acc_str);
6412     }
6413     result_str[result_len] = 0;
6414   }
6415 
6416   return result_str;
6417 }
6418 
6419 
RemoveEmptyAccessionStrings(CharPtr acc_list)6420 static void RemoveEmptyAccessionStrings (CharPtr acc_list)
6421 {
6422   CharPtr cp_prev_end = NULL, cp_src, cp_dst;
6423 
6424   if (acc_list == NULL) return;
6425 
6426   cp_src = acc_list;
6427   cp_dst = acc_list;
6428   cp_prev_end = acc_list;
6429   while (*cp_src != 0)
6430   {
6431     if (*cp_src == '|' && (*(cp_src + 1) == ',' || *(cp_src + 1) == 0))
6432     {
6433       cp_dst = cp_prev_end;
6434       cp_prev_end = cp_dst;
6435       cp_src++;
6436     }
6437     else
6438     {
6439       *cp_dst = *cp_src;
6440       if (*cp_src == ',')
6441       {
6442         cp_prev_end = cp_dst;
6443       }
6444       cp_dst++;
6445       cp_src++;
6446     }
6447   }
6448   *cp_dst = 0;
6449 }
6450 
6451 
6452 static CharPtr insdmessage =
6453 "GenBank, EMBL, and DDBJ records are part of the International Nucleotide " \
6454 "Sequence Database collaboration.\nThe database prefix for the /inference " \
6455 "qualifier in these cases is INSD by collaboration policy.";
6456 
6457 
ReplaceDatabaseStrings(CharPtr PNTR str)6458 static Boolean ReplaceDatabaseStrings (CharPtr PNTR str)
6459 {
6460   Boolean changed_db = FALSE;
6461 
6462   if (str == NULL || *str == NULL) return FALSE;
6463 
6464   if (StringSearch (*str, "GenBank|") != NULL)
6465   {
6466     changed_db = TRUE;
6467     FindReplaceString (str, "GenBank|", "INSD|", TRUE, FALSE);
6468   }
6469   if (StringSearch (*str, "EMBL|") != NULL)
6470   {
6471     changed_db = TRUE;
6472     FindReplaceString (str, "EMBL|", "INSD|", TRUE, FALSE);
6473   }
6474   if (StringSearch (*str, "DDBJ|") != NULL)
6475   {
6476     changed_db = TRUE;
6477     FindReplaceString (str, "DDBJ|", "INSD|", TRUE, FALSE);
6478   }
6479 
6480   if (changed_db)
6481   {
6482     if (GetAppProperty ("InternalNcbiSequin") == NULL) {
6483       Message (MSG_OK, "%s", insdmessage);
6484     }
6485   }
6486 
6487   return changed_db;
6488 }
6489 
6490 
6491 static void ChangeInferAccessionList (Pointer data);
6492 static TaglistCallback AccessionListCallbacks[] =
6493 { ChangeInferAccessionList, ChangeInferAccessionList };
6494 
6495 typedef struct inferevid {
6496   CharPtr  evcat;      /* from inferencePrefix     */
6497   CharPtr  prefix;     /* from inferencePrefix     */
6498   Boolean  species;    /* optional (same species)  */
6499   CharPtr  database;   /* INSD, RefSeq, etc.       */
6500   CharPtr  db_other;   /* other database           */
6501   CharPtr  accession;  /* accession.version        */
6502   CharPtr  program;    /* common analysis program  */
6503   CharPtr  pr_other;   /* other program            */
6504   CharPtr  version;    /* program version          */
6505   CharPtr  basis1;     /* profile or motif         */
6506   CharPtr  basis2;     /*  evidence_basis texts    */
6507   CharPtr  accession_list; /* accession list for alignment */
6508 } InferEvid, PNTR InferEvidPtr;
6509 
6510 typedef struct inferdialog {
6511   DIALOG_MESSAGE_BLOCK
6512 
6513   DoC           inferdoc;
6514   Int2          currItem;
6515 
6516   PopuP         evcat;
6517   PopuP         prefix;
6518   ButtoN        species;
6519   PopuP         database;
6520   TexT          db_other;
6521   TexT          accession;
6522   PopuP         program;
6523   TexT          pr_other;
6524   TexT          version;
6525   TexT          basis1;
6526   TexT          basis2;
6527   PrompT        inf_free_program_prompt;
6528   PrompT        inf_free_version_prompt;
6529   PrompT        accession_list_program_prompt;
6530   PrompT        accession_list_version_prompt;
6531   PrompT        accession_list_prompt;
6532   DialoG        accession_list;
6533 
6534   GrouP         inf_accn_group;
6535   GrouP         other_db_group;
6536   GrouP         inf_prog_group;
6537   GrouP         other_pr_group;
6538   GrouP         inf_free_group;
6539 
6540   Int2          numInf;
6541   InferEvidPtr  evidence [128];
6542 
6543 } InferDialog, PNTR InferDialogPtr;
6544 
InferEvidNew(void)6545 static InferEvidPtr InferEvidNew (
6546   void
6547 )
6548 
6549 {
6550   InferEvidPtr  iep;
6551 
6552   iep = MemNew (sizeof (InferEvid));
6553   if (iep == NULL) return NULL;
6554 
6555   return iep;
6556 }
6557 
InferEvidFree(InferEvidPtr iep)6558 static InferEvidPtr InferEvidFree (
6559   InferEvidPtr iep
6560 )
6561 
6562 {
6563   if (iep == NULL) return NULL;
6564 
6565   MemFree (iep->evcat);
6566   MemFree (iep->prefix);
6567   MemFree (iep->database);
6568   MemFree (iep->accession);
6569   MemFree (iep->program);
6570   MemFree (iep->version);
6571   MemFree (iep->basis1);
6572   MemFree (iep->basis2);
6573   MemFree (iep->accession_list);
6574 
6575   return MemFree (iep);
6576 }
6577 
GetInferEvid(InferDialogPtr idp,Int2 item)6578 static InferEvidPtr GetInferEvid (
6579   InferDialogPtr idp,
6580   Int2 item
6581 )
6582 
6583 {
6584   InferEvidPtr  iep;
6585 
6586   if (idp == NULL || item < 0 || item > 127) return NULL;
6587   iep = idp->evidence [item];
6588   if (iep != NULL) return iep;
6589 
6590   iep = InferEvidNew ();
6591   if (iep != NULL) {
6592     /*
6593     iep->evcat = StringSave (" ");
6594     iep->prefix = StringSave (" ");
6595     iep->database = StringSave (" ");
6596     iep->db_other = StringSave ("");
6597     iep->accession = StringSave ("");
6598     iep->program = StringSave (" ");
6599     iep->pr_other = StringSave ("");
6600     iep->version = StringSave ("");
6601     iep->basis1 = StringSave ("");
6602     iep->basis2 = StringSave ("");
6603     */
6604   }
6605   idp->evidence [item] = iep;
6606   return iep;
6607 }
6608 
6609 /* inference DoC object tables */
6610 
6611 #define NUM_INFERENCE_LINES 3
6612 
6613 static ParData  inferParFmt = { FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0 };
6614 
6615 static ColData  inferColFmt [] = {
6616   {0, 5, 25, 0, NULL, 'l', FALSE, FALSE, FALSE, FALSE, FALSE}, /* class     */
6617   {0, 5, 25, 2, NULL, 'l', FALSE, TRUE,  FALSE, FALSE, TRUE}   /* specifics */
6618 };
6619 
6620 static CharPtr evcatPrefix [] = {
6621   "",
6622   "COORDINATES: ",
6623   "DESCRIPTION: ",
6624   "EXISTENCE: ",
6625   NULL
6626 };
6627 
ENUM_ALIST(evcat_alist)6628 ENUM_ALIST(evcat_alist)
6629   { " ",             0 },
6630   { "COORDINATES",   1 },
6631   { "DESCRIPTION",   2 },
6632   { "EXISTENCE",     3 },
6633 END_ENUM_ALIST
6634 
6635 static CharPtr inferencePrefix [] = {
6636   "",
6637   "similar to sequence",
6638   "similar to AA sequence",
6639   "similar to DNA sequence",
6640   "similar to RNA sequence",
6641   "similar to RNA sequence, mRNA",
6642   "similar to RNA sequence, EST",
6643   "similar to RNA sequence, other RNA",
6644   "profile",
6645   "nucleotide motif",
6646   "protein motif",
6647   "ab initio prediction",
6648   "alignment",
6649   NULL
6650 };
6651 
ENUM_ALIST(inference_alist)6652 ENUM_ALIST(inference_alist)
6653   { " ",                     0 },
6654   { "similar to sequence",   1 },
6655   { "similar to protein",    2 },
6656   { "similar to DNA",        3 },
6657   { "similar to RNA",        4 },
6658   { "similar to mRNA",       5 },
6659   { "similar to EST",        6 },
6660   { "similar to other RNA",  7 },
6661   { "profile",               8 },
6662   { "nucleotide motif",      9 },
6663   { "protein motif",        10 },
6664   { "ab initio prediction", 11 },
6665   { "alignment",            12 },
6666 END_ENUM_ALIST
6667 
6668 static CharPtr programPrefix [] = {
6669   "",
6670   "tRNAscan",
6671   "Genscan",
6672   "?",
6673   NULL
6674 };
6675 
ENUM_ALIST(program_alist)6676 ENUM_ALIST(program_alist)
6677   { " ",        0 },
6678   { "tRNAscan", 1 },
6679   { "Genscan",  2 },
6680   { "Other",    3 },
6681 END_ENUM_ALIST
6682 
6683 static CharPtr PrintInferTable (
6684   DoC d,
6685   Int2 item,
6686   Pointer data
6687 )
6688 
6689 {
6690   CharPtr         buf;
6691   InferDialogPtr  idp;
6692   InferEvidPtr    iep;
6693   size_t          len;
6694 
6695   idp = (InferDialogPtr) GetObjectExtra (d);
6696   if (idp == NULL || item < 1 || item > 127) return NULL;
6697   iep = GetInferEvid (idp, item);
6698   if (iep == NULL) return NULL;
6699 
6700   len = StringLen (iep->prefix) + StringLen (iep->database) + StringLen (iep->db_other) + StringLen (iep->accession) +
6701         StringLen (iep->program) + StringLen (iep->pr_other) + StringLen (iep->version) + StringLen (iep->basis1) +
6702         StringLen (iep->basis2) + StringLen (iep->accession_list) + StringLen (iep->evcat) + 50;
6703   buf = MemNew (len);
6704   if (buf == NULL) return NULL;
6705 
6706   if (StringHasNoText (iep->prefix)) {
6707     StringCat (buf, " \t \n");
6708     return buf;
6709   }
6710 
6711   StringCat (buf, iep->prefix);
6712 
6713   StringCat (buf, "\t");
6714 
6715   if (StringNICmp (iep->prefix, "similar to ", 11) == 0) {
6716     if (StringDoesHaveText (iep->accession)) {
6717       if (StringCmp (iep->database, "Other") == 0) {
6718         if (StringDoesHaveText (iep->db_other)) {
6719           StringCat (buf, iep->db_other);
6720           StringCat (buf, ":");
6721         }
6722       } else if (StringDoesHaveText (iep->database)) {
6723         StringCat (buf, iep->database);
6724         StringCat (buf, ":");
6725       }
6726       StringCat (buf, iep->accession);
6727     }
6728   } else if (StringNICmp (iep->prefix, "ab initio ", 10) == 0) {
6729     if (StringCmp (iep->program, "Other") == 0) {
6730       if (StringDoesHaveText (iep->pr_other)) {
6731         StringCat (buf, iep->pr_other);
6732         if (StringDoesHaveText (iep->version)) {
6733           StringCat (buf, ":");
6734           StringCat (buf, iep->version);
6735         }
6736       }
6737     } else if (StringDoesHaveText (iep->program)) {
6738       StringCat (buf, iep->program);
6739       if (StringDoesHaveText (iep->version)) {
6740         StringCat (buf, ":");
6741         StringCat (buf, iep->version);
6742       }
6743     }
6744   } else if (StringDoesHaveText (iep->basis1)) {
6745     StringCat (buf, iep->basis1);
6746     if (StringDoesHaveText (iep->basis2)) {
6747       StringCat (buf, ":");
6748       StringCat (buf, iep->basis2);
6749       if (StringCmp (iep->prefix, "alignment") == 0 &&
6750           StringDoesHaveText (iep->accession_list)) {
6751         StringCat (buf, ":");
6752         StringCat (buf, iep->accession_list);
6753       }
6754     }
6755   } else {
6756     StringCat (buf, " ");
6757   }
6758 
6759   StringCat (buf, "\n");
6760   return buf;
6761 }
6762 
ShowInferenceGroup(InferDialogPtr idp)6763 static void ShowInferenceGroup (
6764   InferDialogPtr idp
6765 )
6766 
6767 {
6768   CharPtr  str;
6769   UIEnum   val;
6770 
6771   if (idp == NULL) return;
6772   if (GetEnumPopup (idp->prefix, inference_alist, &val)) {
6773     if (val >= 1 && val <= 7) {
6774       SafeHide (idp->inf_prog_group);
6775       SafeHide (idp->inf_free_group);
6776       SafeShow (idp->inf_accn_group);
6777       SafeShow (idp->species);
6778       str = GetEnumPopupByName (idp->database, accn_type_alist);
6779       if (StringCmp (str, "Other") == 0) {
6780         SafeShow (idp->other_db_group);
6781       } else {
6782         SafeHide (idp->other_db_group);
6783       }
6784       MemFree (str);
6785     } else if (val >= 8 && val <= 10) {
6786       SafeHide (idp->inf_accn_group);
6787       SafeHide (idp->species);
6788       SafeHide (idp->inf_prog_group);
6789       SafeShow (idp->inf_free_group);
6790       SafeHide (idp->accession_list);
6791       SafeShow (idp->inf_free_program_prompt);
6792       SafeShow (idp->inf_free_version_prompt);
6793       SafeHide (idp->accession_list_program_prompt);
6794       SafeHide (idp->accession_list_version_prompt);
6795       SafeHide (idp->accession_list_prompt);
6796     } else if (val == 11) {
6797       SafeHide (idp->inf_accn_group);
6798       SafeHide (idp->species);
6799       SafeHide (idp->inf_free_group);
6800       SafeShow (idp->inf_prog_group);
6801       str = GetEnumPopupByName (idp->program, program_alist);
6802       if (StringCmp (str, "Other") == 0) {
6803         SafeShow (idp->other_pr_group);
6804       } else {
6805         SafeHide (idp->other_pr_group);
6806       }
6807       MemFree (str);
6808     } else if (val == 12) {
6809       SafeHide (idp->inf_accn_group);
6810       SafeHide (idp->species);
6811       SafeHide (idp->inf_prog_group);
6812       SafeShow (idp->inf_free_group);
6813       SafeShow (idp->accession_list);
6814       SafeHide (idp->inf_free_program_prompt);
6815       SafeHide (idp->inf_free_version_prompt);
6816       SafeShow (idp->accession_list_program_prompt);
6817       SafeShow (idp->accession_list_version_prompt);
6818       SafeShow (idp->accession_list_prompt);
6819     } else {
6820       SafeHide (idp->inf_accn_group);
6821       SafeHide (idp->species);
6822       SafeHide (idp->inf_prog_group);
6823       SafeHide (idp->inf_free_group);
6824     }
6825   } else {
6826     SafeHide (idp->inf_accn_group);
6827     SafeHide (idp->species);
6828     SafeHide (idp->inf_prog_group);
6829     SafeHide (idp->inf_free_group);
6830   }
6831   Update ();
6832 }
6833 
SafeSetEnumPopupByName(PopuP lst,EnumFieldAssocPtr al,CharPtr name)6834 static void SafeSetEnumPopupByName (PopuP lst, EnumFieldAssocPtr al, CharPtr name)
6835 
6836 {
6837   if (StringDoesHaveText (name)) {
6838     SetEnumPopupByName (lst, al, name);
6839   } else {
6840     SetEnumPopupByName (lst, al, " ");
6841   }
6842 }
6843 
ChangeInferTableSelect(DoC d,Int2 item,Int2 row,Int2 col,Boolean dblClck)6844 static void ChangeInferTableSelect (
6845   DoC d,
6846   Int2 item,
6847   Int2 row,
6848   Int2 col,
6849   Boolean dblClck
6850 )
6851 
6852 {
6853   InferDialogPtr  idp;
6854   InferEvidPtr    iep;
6855   Int2            itemOld1, itemOld2;
6856 
6857   idp = (InferDialogPtr) GetObjectExtra (d);
6858   if (idp == NULL) return;
6859   if (item == 0 || row == 0 || col == 0) return;
6860 
6861   GetDocHighlight (d, &itemOld1, &itemOld2);
6862   SetDocHighlight (d, item, item);
6863   UpdateDocument (d, itemOld1, itemOld2);
6864   UpdateDocument (d, item, item);
6865   idp->currItem = item;
6866 
6867   iep = GetInferEvid (idp, item);
6868   if (iep != NULL) {
6869     ResetClip ();
6870     SafeSetEnumPopupByName (idp->evcat, evcat_alist, iep->evcat);
6871     SafeSetEnumPopupByName (idp->prefix, inference_alist, iep->prefix);
6872 
6873     SafeSetStatus (idp->species, iep->species);
6874     SafeSetEnumPopupByName (idp->database, accn_type_alist, iep->database);
6875     SafeSetTitle (idp->db_other, iep->db_other);
6876     SafeSetTitle (idp->accession, iep->accession);
6877 
6878     SafeSetEnumPopupByName (idp->program, program_alist, iep->program);
6879     SafeSetTitle (idp->pr_other, iep->pr_other);
6880     SafeSetTitle (idp->version, iep->version);
6881 
6882     SafeSetTitle (idp->basis1, iep->basis1);
6883     SafeSetTitle (idp->basis2, iep->basis2);
6884 
6885     ReplaceDatabaseStrings (&(iep->accession_list));
6886     PointerToDialog (idp->accession_list, iep->accession_list);
6887 
6888     ShowInferenceGroup (idp);
6889   }
6890 
6891   Update ();
6892 }
6893 
CheckExtendInferTable(InferDialogPtr idp)6894 static void CheckExtendInferTable (
6895   InferDialogPtr idp
6896 )
6897 
6898 {
6899   Int2  numItems;
6900 
6901   if (idp == NULL) return;
6902 
6903   GetDocParams (idp->inferdoc, &numItems, NULL);
6904   if (idp->currItem == numItems) {
6905     AppendItem (idp->inferdoc, PrintInferTable, idp, FALSE, 1,
6906                 &inferParFmt, inferColFmt, systemFont);
6907   }
6908 
6909   Update ();
6910 }
6911 
ChangeInferCat(PopuP p)6912 static void ChangeInferCat (
6913   PopuP p
6914 )
6915 
6916 {
6917   AlistDialogPtr  adp;
6918   InferDialogPtr  idp;
6919   InferEvidPtr    iep;
6920   CharPtr         str;
6921 
6922   adp = (AlistDialogPtr) GetObjectExtra (p);
6923   if (adp == NULL) return;
6924   idp = (InferDialogPtr) adp->userdata;
6925   if (idp == NULL) return;
6926   iep = GetInferEvid (idp, idp->currItem);
6927   if (iep == NULL) return;
6928 
6929   str = GetEnumPopupByName (idp->evcat, evcat_alist);
6930   iep->evcat = MemFree (iep->evcat);
6931   iep->evcat = str; /* allocated by GetEnumPopupByName */
6932 
6933   ShowInferenceGroup (idp);
6934 
6935   UpdateDocument (idp->inferdoc, idp->currItem, idp->currItem);
6936   Update ();
6937 
6938   CheckExtendInferTable (idp);
6939 }
6940 
ChangeInferPrefix(PopuP p)6941 static void ChangeInferPrefix (
6942   PopuP p
6943 )
6944 
6945 {
6946   AlistDialogPtr  adp;
6947   InferDialogPtr  idp;
6948   InferEvidPtr    iep;
6949   CharPtr         str;
6950 
6951   adp = (AlistDialogPtr) GetObjectExtra (p);
6952   if (adp == NULL) return;
6953   idp = (InferDialogPtr) adp->userdata;
6954   if (idp == NULL) return;
6955   iep = GetInferEvid (idp, idp->currItem);
6956   if (iep == NULL) return;
6957 
6958   str = GetEnumPopupByName (idp->prefix, inference_alist);
6959   iep->prefix = MemFree (iep->prefix);
6960   iep->prefix = str; /* allocated by GetEnumPopupByName */
6961 
6962   ShowInferenceGroup (idp);
6963 
6964   UpdateDocument (idp->inferdoc, idp->currItem, idp->currItem);
6965   Update ();
6966 
6967   CheckExtendInferTable (idp);
6968 }
6969 
ChangeSameSpecies(ButtoN b)6970 static void ChangeSameSpecies (
6971   ButtoN b
6972 )
6973 
6974 {
6975   InferDialogPtr  idp;
6976   InferEvidPtr    iep;
6977 
6978   idp = (InferDialogPtr) GetObjectExtra (b);
6979   if (idp == NULL) return;
6980   iep = GetInferEvid (idp, idp->currItem);
6981   if (iep == NULL) return;
6982 
6983   iep->species = (Boolean) (GetStatus (b));
6984 
6985   ShowInferenceGroup (idp);
6986 
6987   UpdateDocument (idp->inferdoc, idp->currItem, idp->currItem);
6988   Update ();
6989 
6990   CheckExtendInferTable (idp);
6991 }
6992 
ChangeInferDatabase(PopuP p)6993 static void ChangeInferDatabase (
6994   PopuP p
6995 )
6996 
6997 
6998 {
6999   AlistDialogPtr  adp;
7000   InferDialogPtr  idp;
7001   InferEvidPtr    iep;
7002   CharPtr         str;
7003 
7004   adp = (AlistDialogPtr) GetObjectExtra (p);
7005   if (adp == NULL) return;
7006   idp = (InferDialogPtr) adp->userdata;
7007   if (idp == NULL) return;
7008   iep = GetInferEvid (idp, idp->currItem);
7009   if (iep == NULL) return;
7010 
7011   str = GetEnumPopupByName (idp->database, accn_type_alist);
7012   if (StringCmp (str, "GenBank") == 0 ||
7013       StringCmp (str, "EMBL") == 0 ||
7014       StringCmp (str, "DDBJ") == 0) {
7015     if (GetAppProperty ("InternalNcbiSequin") == NULL) {
7016       Message (MSG_OK, "%s", insdmessage);
7017     }
7018     SetEnumPopupByName (idp->database, accn_type_alist, "INSD");
7019     str = MemFree (str);
7020     str = StringSave ("INSD");
7021   }
7022   iep->database = MemFree (iep->database);
7023   iep->database = str; /* allocated by GetEnumPopupByName */
7024 
7025   ShowInferenceGroup (idp);
7026 
7027   UpdateDocument (idp->inferdoc, idp->currItem, idp->currItem);
7028   Update ();
7029 
7030   CheckExtendInferTable (idp);
7031 }
7032 
ChangeInferDbOther(TexT t)7033 static void ChangeInferDbOther (
7034   TexT t
7035 )
7036 
7037 {
7038   InferDialogPtr  idp;
7039   InferEvidPtr    iep;
7040 
7041   idp = (InferDialogPtr) GetObjectExtra (t);
7042   if (idp == NULL) return;
7043   iep = GetInferEvid (idp, idp->currItem);
7044   if (iep == NULL) return;
7045 
7046   iep->db_other = MemFree (iep->db_other);
7047   iep->db_other = SaveStringFromText (t);
7048 
7049   ShowInferenceGroup (idp);
7050 
7051   UpdateDocument (idp->inferdoc, idp->currItem, idp->currItem);
7052   Update ();
7053 
7054   CheckExtendInferTable (idp);
7055 }
7056 
ChangeInferAccession(TexT t)7057 static void ChangeInferAccession (
7058   TexT t
7059 )
7060 
7061 {
7062   InferDialogPtr  idp;
7063   InferEvidPtr    iep;
7064 
7065   idp = (InferDialogPtr) GetObjectExtra (t);
7066   if (idp == NULL) return;
7067   iep = GetInferEvid (idp, idp->currItem);
7068   if (iep == NULL) return;
7069 
7070   iep->accession = MemFree (iep->accession);
7071   iep->accession = SaveStringFromText (t);
7072 
7073   ShowInferenceGroup (idp);
7074 
7075   UpdateDocument (idp->inferdoc, idp->currItem, idp->currItem);
7076   Update ();
7077 
7078   CheckExtendInferTable (idp);
7079 }
7080 
ChangeInferProgram(PopuP p)7081 static void ChangeInferProgram (
7082   PopuP p
7083 )
7084 
7085 
7086 {
7087   AlistDialogPtr  adp;
7088   InferDialogPtr  idp;
7089   InferEvidPtr    iep;
7090   CharPtr         str;
7091 
7092   adp = (AlistDialogPtr) GetObjectExtra (p);
7093   if (adp == NULL) return;
7094   idp = (InferDialogPtr) adp->userdata;
7095   if (idp == NULL) return;
7096   iep = GetInferEvid (idp, idp->currItem);
7097   if (iep == NULL) return;
7098 
7099   str = GetEnumPopupByName (idp->program, program_alist);
7100   iep->program = MemFree (iep->program);
7101   iep->program = str; /* allocated by GetEnumPopupByName */
7102 
7103   ShowInferenceGroup (idp);
7104 
7105   UpdateDocument (idp->inferdoc, idp->currItem, idp->currItem);
7106   Update ();
7107 
7108   CheckExtendInferTable (idp);
7109 }
7110 
ChangeInferPrOther(TexT t)7111 static void ChangeInferPrOther (
7112   TexT t
7113 )
7114 
7115 {
7116   InferDialogPtr  idp;
7117   InferEvidPtr    iep;
7118 
7119   idp = (InferDialogPtr) GetObjectExtra (t);
7120   if (idp == NULL) return;
7121   iep = GetInferEvid (idp, idp->currItem);
7122   if (iep == NULL) return;
7123 
7124   iep->pr_other = MemFree (iep->pr_other);
7125   iep->pr_other = SaveStringFromText (t);
7126 
7127   ShowInferenceGroup (idp);
7128 
7129   UpdateDocument (idp->inferdoc, idp->currItem, idp->currItem);
7130   Update ();
7131 
7132   CheckExtendInferTable (idp);
7133 }
7134 
ChangeInferVersion(TexT t)7135 static void ChangeInferVersion (
7136   TexT t
7137 )
7138 
7139 {
7140   InferDialogPtr  idp;
7141   InferEvidPtr    iep;
7142 
7143   idp = (InferDialogPtr) GetObjectExtra (t);
7144   if (idp == NULL) return;
7145   iep = GetInferEvid (idp, idp->currItem);
7146   if (iep == NULL) return;
7147 
7148   iep->version = MemFree (iep->version);
7149   iep->version = SaveStringFromText (t);
7150 
7151   ShowInferenceGroup (idp);
7152 
7153   UpdateDocument (idp->inferdoc, idp->currItem, idp->currItem);
7154   Update ();
7155 
7156   CheckExtendInferTable (idp);
7157 }
7158 
ChangeInferBasis1(TexT t)7159 static void ChangeInferBasis1 (
7160   TexT t
7161 )
7162 
7163 {
7164   InferDialogPtr  idp;
7165   InferEvidPtr    iep;
7166 
7167   idp = (InferDialogPtr) GetObjectExtra (t);
7168   if (idp == NULL) return;
7169   iep = GetInferEvid (idp, idp->currItem);
7170   if (iep == NULL) return;
7171 
7172   iep->basis1 = MemFree (iep->basis1);
7173   iep->basis1 = SaveStringFromText (t);
7174 
7175   ShowInferenceGroup (idp);
7176 
7177   UpdateDocument (idp->inferdoc, idp->currItem, idp->currItem);
7178   Update ();
7179 
7180   CheckExtendInferTable (idp);
7181 }
7182 
ChangeInferBasis2(TexT t)7183 static void ChangeInferBasis2 (
7184   TexT t
7185 )
7186 
7187 {
7188   InferDialogPtr  idp;
7189   InferEvidPtr    iep;
7190 
7191   idp = (InferDialogPtr) GetObjectExtra (t);
7192   if (idp == NULL) return;
7193   iep = GetInferEvid (idp, idp->currItem);
7194   if (iep == NULL) return;
7195 
7196   iep->basis2 = MemFree (iep->basis2);
7197   iep->basis2 = SaveStringFromText (t);
7198 
7199   ShowInferenceGroup (idp);
7200 
7201   UpdateDocument (idp->inferdoc, idp->currItem, idp->currItem);
7202   Update ();
7203 
7204   CheckExtendInferTable (idp);
7205 }
7206 
7207 
ChangeInferAccessionList(Pointer data)7208 static void ChangeInferAccessionList (Pointer data)
7209 {
7210   InferDialogPtr  idp;
7211   InferEvidPtr    iep;
7212 
7213   idp = (InferDialogPtr) data;
7214   if (idp == NULL) return;
7215   iep = GetInferEvid (idp, idp->currItem);
7216   if (iep == NULL) return;
7217 
7218   iep->accession_list = MemFree (iep->accession_list);
7219   iep->accession_list = DialogToPointer (idp->accession_list);
7220 
7221   if (ReplaceDatabaseStrings (&(iep->accession_list)))
7222   {
7223     PointerToDialog (idp->accession_list, iep->accession_list);
7224   }
7225 
7226   ShowInferenceGroup (idp);
7227 
7228   UpdateDocument (idp->inferdoc, idp->currItem, idp->currItem);
7229   Update ();
7230 
7231   CheckExtendInferTable (idp);
7232 }
7233 
7234 
StringInList(CharPtr str,CharPtr PNTR list)7235 static Boolean StringInList (CharPtr str, CharPtr PNTR list)
7236 
7237 {
7238   Int2  i;
7239 
7240   if (str == NULL || list == NULL) return FALSE;
7241 
7242   for (i = 0; list [i] != NULL; i++) {
7243     if (StringICmp (str, list[i]) == 0) return TRUE;
7244   }
7245 
7246   return FALSE;
7247 }
7248 
GBQualsToInferenceDialog(DialoG d,SeqFeatPtr sfp)7249 extern void GBQualsToInferenceDialog (DialoG d, SeqFeatPtr sfp)
7250 
7251 {
7252   Int2            best;
7253   Char            ch;
7254   Int2            evc;
7255   GBQualPtr       gbq;
7256   CharPtr         gbval;
7257   Int2            i, j, k;
7258   InferDialogPtr  idp;
7259   InferEvidPtr    iep;
7260   size_t          len;
7261   CharPtr         rest;
7262   CharPtr         str;
7263   CharPtr         tmp, tmp2;
7264 
7265   idp = (InferDialogPtr) GetObjectExtra (d);
7266   if (idp == NULL) return;
7267 
7268   if (sfp == NULL || sfp->qual == NULL) {
7269     Reset (idp->inferdoc);
7270     SetValue (idp->evcat, 0);
7271     SetValue (idp->prefix, 0);
7272     SetStatus (idp->species, FALSE);
7273     SetValue (idp->database, 0);
7274     SetTitle (idp->db_other, "");
7275     SetTitle (idp->accession, "");
7276     SetValue (idp->program, 0);
7277     SetTitle (idp->pr_other, "");
7278     SetTitle (idp->version, "");
7279     SetTitle (idp->basis1, "");
7280     SetTitle (idp->basis2, "");
7281     SafeHide (idp->inf_accn_group);
7282     SafeHide (idp->inf_prog_group);
7283     SafeHide (idp->inf_free_group);
7284     idp->numInf = 0;
7285     idp->currItem = 1;
7286     for (i = 0; i < NUM_INFERENCE_LINES; i++) {
7287       AppendItem (idp->inferdoc, PrintInferTable, idp, FALSE, 1,
7288                   &inferParFmt, inferColFmt, systemFont);
7289     }
7290     SetDocHighlight (idp->inferdoc, 1, 1);
7291     return;
7292   }
7293 
7294   idp->numInf = 0;
7295   idp->currItem = 1;
7296   Reset (idp->inferdoc);
7297 
7298   for (k = 0; k < 128; k++) {
7299     iep = idp->evidence [k];
7300     InferEvidFree (iep);
7301     idp->evidence [k] = NULL;
7302   }
7303 
7304   for (gbq = sfp->qual, k = 0; gbq != NULL; gbq = gbq->next) {
7305     if (StringICmp (gbq->qual, "inference") != 0) continue;
7306     if (StringHasNoText (gbq->val)) continue;
7307 
7308     gbval = gbq->val;
7309     evc = -1;
7310     for (j = 0; evcatPrefix [j] != NULL; j++) {
7311       len = StringLen (evcatPrefix [j]);
7312       if (StringNICmp (gbq->val, evcatPrefix [j], len) != 0) continue;
7313       gbval = gbq->val + len;
7314       evc = j;
7315     }
7316 
7317     rest = NULL;
7318     best = -1;
7319     for (j = 0; inferencePrefix [j] != NULL; j++) {
7320       len = StringLen (inferencePrefix [j]);
7321       if (StringNICmp (gbval, inferencePrefix [j], len) != 0) continue;
7322       rest = gbval + len;
7323       best = j;
7324     }
7325 
7326     k++;
7327     iep = GetInferEvid (idp, k);
7328     if (iep == NULL) continue;
7329 
7330     str = NULL;
7331     if (best > 0 && inferencePrefix [best] != NULL) {
7332       iep->prefix = MemFree (iep->prefix);
7333       iep->prefix = StringSave(GetEnumName ((UIEnum) best, inference_alist));
7334 
7335       if (evc > 0 && evcatPrefix [evc] != NULL) {
7336         iep->evcat = MemFree (iep->evcat);
7337         iep->evcat = StringSave(GetEnumName ((UIEnum) evc, evcat_alist));
7338       }
7339 
7340       if (rest != NULL) {
7341         ch = *rest;
7342         while (IS_WHITESP (ch)) {
7343           rest++;
7344           ch = *rest;
7345         }
7346         if (StringNICmp (rest, "(same species)", 14) == 0) {
7347           iep->species = TRUE;
7348           rest += 14;
7349         } else {
7350           iep->species = FALSE;
7351         }
7352         ch = *rest;
7353         while (IS_WHITESP (ch) || ch == ':') {
7354           rest++;
7355           ch = *rest;
7356         }
7357       }
7358       if (StringDoesHaveText (rest)) {
7359         str = StringSave (rest);
7360       }
7361       tmp = StringChr (str, ':');
7362       if (tmp != NULL) {
7363         *tmp = '\0';
7364         tmp++;
7365         TrimSpacesAroundString (str);
7366         TrimSpacesAroundString (tmp);
7367       } else {
7368         TrimSpacesAroundString (str);
7369       }
7370       if (StringNICmp (iep->prefix, "similar to ", 11) == 0) {
7371         if (StringInList (str, accnTypePrefix)) {
7372           iep->database = MemFree (iep->database);
7373           iep->database = StringSaveNoNull (str);
7374           iep->accession = MemFree (iep->accession);
7375           iep->accession = StringSaveNoNull (tmp);
7376         } else if (tmp != NULL) {
7377           iep->database = MemFree (iep->database);
7378           iep->database = StringSaveNoNull ("Other");
7379           iep->db_other = MemFree (iep->db_other);
7380           iep->db_other = StringSaveNoNull (str);
7381           iep->accession = MemFree (iep->accession);
7382           iep->accession = StringSaveNoNull (tmp);
7383         } else {
7384           iep->database = MemFree (iep->database);
7385           iep->database = StringSaveNoNull (" ");
7386           iep->db_other = MemFree (iep->db_other);
7387           iep->accession = MemFree (iep->accession);
7388           iep->accession = StringSaveNoNull (str);
7389         }
7390       } else if (StringNICmp (iep->prefix, "ab initio ", 10) == 0) {
7391         if (StringInList (str, programPrefix)) {
7392           iep->program = MemFree (iep->program);
7393           iep->program = StringSaveNoNull (str);
7394         } else {
7395           iep->program = MemFree (iep->program);
7396           iep->program = StringSaveNoNull ("Other");
7397           iep->pr_other = MemFree (iep->pr_other);
7398           iep->pr_other = StringSaveNoNull (str);
7399         }
7400         iep->version = MemFree (iep->version);
7401         iep->version = StringSaveNoNull (tmp);
7402       } else {
7403         iep->basis1 = MemFree (iep->basis1);
7404         iep->basis1 = StringSaveNoNull (str);
7405         tmp2 = NULL;
7406         if (StringCmp (iep->prefix, "alignment") == 0)
7407         {
7408           tmp2 = StringChr (tmp, ':');
7409           if (tmp2 != NULL) {
7410             *tmp2 = 0;
7411             tmp2++;
7412           }
7413         }
7414         iep->basis2 = MemFree (iep->basis2);
7415         iep->basis2 = StringSaveNoNull (tmp);
7416         iep->accession_list = MemFree (iep->accession_list);
7417         iep->accession_list = StringSaveNoNull (tmp2);
7418       }
7419 
7420     } else {
7421       iep->evcat = NULL;
7422       iep->prefix = StringSave ("???");
7423       str = StringSave (gbval);
7424       tmp = StringChr (str, ':');
7425       if (tmp != NULL) {
7426         *tmp = '\0';
7427         tmp++;
7428         TrimSpacesAroundString (str);
7429         TrimSpacesAroundString (tmp);
7430       } else {
7431         TrimSpacesAroundString (str);
7432       }
7433       iep->basis1 = MemFree (iep->basis1);
7434       iep->basis1 = StringSaveNoNull (str);
7435       iep->basis2 = MemFree (iep->basis2);
7436       iep->basis2 = StringSaveNoNull (tmp);
7437     }
7438 
7439     MemFree (str);
7440 
7441     AppendItem (idp->inferdoc, PrintInferTable, idp, FALSE, 1,
7442                 &inferParFmt, inferColFmt, systemFont);
7443 
7444     (idp->numInf)++;
7445   }
7446 
7447   AppendItem (idp->inferdoc, PrintInferTable, idp, FALSE, 1,
7448               &inferParFmt, inferColFmt, systemFont);
7449   k++;
7450 
7451   while (k < NUM_INFERENCE_LINES) {
7452     AppendItem (idp->inferdoc, PrintInferTable, idp, FALSE, 1,
7453                 &inferParFmt, inferColFmt, systemFont);
7454     k++;
7455   }
7456 
7457   ShowInferenceGroup (idp);
7458 
7459   UpdateDocument (idp->inferdoc, 0, 0);
7460 
7461   ChangeInferTableSelect (idp->inferdoc, 1, 1, 1, FALSE);
7462 
7463   Update ();
7464 }
7465 
InferenceDialogToGBQuals(DialoG d,SeqFeatPtr sfp,Boolean convertBadToNote)7466 extern void InferenceDialogToGBQuals (DialoG d, SeqFeatPtr sfp, Boolean convertBadToNote)
7467 
7468 {
7469   CharPtr         first = NULL, second = NULL, accession_list = NULL;
7470   CharPtr         evcat = NULL;
7471   GBQualPtr       gbq, lastgbq;
7472   InferDialogPtr  idp;
7473   InferEvidPtr    iep;
7474   Int2            k, numItems;
7475   size_t          len;
7476   CharPtr         prefix = NULL;
7477   CharPtr         speciesies = NULL;
7478   CharPtr         str;
7479   UIEnum          val;
7480 
7481   idp = (InferDialogPtr) GetObjectExtra (d);
7482   if (idp == NULL || sfp == NULL) return;
7483 
7484   lastgbq = NULL;
7485   for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
7486     lastgbq = gbq;
7487   }
7488 
7489   GetDocParams (idp->inferdoc, &numItems, NULL);
7490   for (k = 1; k <= numItems; k++) {
7491     iep = GetInferEvid (idp, k);
7492     if (iep == NULL) continue;
7493 
7494     if (StringHasNoText (iep->prefix)) continue;
7495     gbq = GBQualNew ();
7496     if (gbq == NULL) continue;
7497 
7498     gbq->qual = StringSave ("inference");
7499 
7500     evcat = NULL;
7501     if (WhereInEnumPopup (evcat_alist, iep->evcat, &val)) {
7502       if (val > 0 && val <= 3) {
7503         evcat = evcatPrefix [(int) val];
7504       }
7505     }
7506     prefix = NULL;
7507     if (WhereInEnumPopup (inference_alist, iep->prefix, &val)) {
7508       if (val > 0 && val <= 12) {
7509         prefix = inferencePrefix [(int) val];
7510       }
7511     }
7512     speciesies = NULL;
7513     if (StringNICmp (iep->prefix, "similar to ", 11) == 0) {
7514       if (iep->species) {
7515         speciesies = " (same species)";
7516       }
7517       if (StringDoesHaveText (iep->accession)) {
7518         if (StringCmp (iep->database, "Other") == 0) {
7519           if (StringDoesHaveText (iep->db_other)) {
7520             first = iep->db_other;
7521           }
7522         } else if (StringDoesHaveText (iep->database)) {
7523           first = iep->database;
7524         }
7525         second = iep->accession;
7526       }
7527     } else if (StringNICmp (iep->prefix, "ab initio ", 10) == 0) {
7528       if (StringCmp (iep->program, "Other") == 0) {
7529         if (StringDoesHaveText (iep->pr_other)) {
7530           first = iep->pr_other;
7531         }
7532       } else if (StringDoesHaveText (iep->program)) {
7533         first = iep->program;
7534       }
7535       second = iep->version;
7536     } else {
7537       if (StringDoesHaveText (iep->basis1)) {
7538         first = iep->basis1;
7539         second = iep->basis2;
7540         if (StringCmp (iep->prefix, "alignment") == 0) {
7541           accession_list = iep->accession_list;
7542           RemoveEmptyAccessionStrings (accession_list);
7543           ReplaceDatabaseStrings (&accession_list);
7544         }
7545       }
7546     }
7547 
7548     len = StringLen (evcat) + StringLen (prefix) + StringLen (speciesies) +
7549           StringLen (first) + StringLen (second) + StringLen (accession_list);
7550     str = MemNew (len + 6);
7551     if (str != NULL) {
7552       str [0] = '\0';
7553       if (evcat != NULL) {
7554         StringCat (str, evcat);
7555       }
7556       StringCat (str, prefix);
7557       StringCat (str, speciesies);
7558       StringCat (str, ":");
7559       StringCat (str, first);
7560       StringCat (str, ":");
7561       StringCat (str, second);
7562       if (StringCmp (prefix, "alignment") == 0 && StringDoesHaveText (accession_list)) {
7563         StringCat (str, ":");
7564         StringCat (str, accession_list);
7565       }
7566       gbq->val = StringSave (str);
7567       MemFree (str);
7568     } else {
7569       gbq->val = StringSave ("?");
7570     }
7571 
7572     /* do not allow saving of bad qualifier */
7573     if (convertBadToNote &&
7574         ValidateInferenceQualifier (gbq->val, FALSE) != VALID_INFERENCE) {
7575       if (StringNICmp (gbq->val, "similar to ", 11) == 0) {
7576         len = StringLen ("similar to ") + StringLen (first) + StringLen (second);
7577         str = MemNew (len + 5);
7578         if (str != NULL) {
7579           StringCpy (str, "similar to ");
7580           if (StringDoesHaveText (first)) {
7581             StringCat (str, first);
7582             if (StringDoesHaveText (second)) {
7583               StringCat (str, ":");
7584               StringCat (str, second);
7585             }
7586           } else if (StringDoesHaveText (second)) {
7587             StringCat (str, second);
7588           }
7589           gbq->val = MemFree (gbq->val);
7590           gbq->val = StringSave (str);
7591           MemFree (str);
7592         }
7593       }
7594       gbq->qual = MemFree (gbq->qual);
7595       gbq->qual = StringSave ("note");
7596     }
7597 
7598     if (sfp->qual == NULL) {
7599       sfp->qual = gbq;
7600     }
7601     if (lastgbq != NULL) {
7602       lastgbq->next = gbq;
7603     }
7604     lastgbq = gbq;
7605     accession_list = NULL;
7606   }
7607 }
7608 
CleanupInferProc(GraphiC g,VoidPtr data)7609 static void CleanupInferProc (GraphiC g, VoidPtr data)
7610 
7611 {
7612   InferDialogPtr  idp;
7613   InferEvidPtr    iep;
7614   Int2            k;
7615 
7616   idp = (InferDialogPtr) data;
7617   if (idp != NULL) {
7618     for (k = 0; k < 128; k++) {
7619       iep = idp->evidence [k];
7620       InferEvidFree (iep);
7621       idp->evidence [k] = NULL;
7622     }
7623   }
7624   StdCleanupExtraProc (g, data);
7625 }
7626 
NewCreateInferenceDialog(GrouP prnt)7627 static DialoG NewCreateInferenceDialog (
7628   GrouP prnt
7629 )
7630 
7631 {
7632   GrouP           cts, tbl, g0, g1, g2, g3, g4, g5, p, prompt_grp;
7633   FonT            fnt;
7634   Int2            i, hgt, wid;
7635   InferDialogPtr  idp;
7636 
7637   idp = (InferDialogPtr) MemNew (sizeof (InferDialog));
7638   if (idp == NULL) return NULL;
7639 
7640   p = HiddenGroup (prnt, -1, 0, NULL);
7641   SetGroupSpacing (p, 10, 10);
7642 
7643   SetObjectExtra (p, idp, CleanupInferProc);
7644   idp->dialog = (DialoG) p;
7645   /*
7646   idp->todialog = GBQualToInferTable;
7647   idp->fromdialog = InferTableToGBQual;
7648   */
7649 
7650   SelectFont (systemFont);
7651   hgt = LineHeight ();
7652   inferColFmt [0].pixWidth = MaxAlistWidths (inference_alist) + 5;
7653   inferColFmt [1].pixWidth = 25 * StringWidth ("X") + 5;
7654   SelectFont (systemFont);
7655 
7656   wid = 0;
7657   for (i = 0; i < 2; i++) {
7658     wid += inferColFmt [i].pixWidth;
7659   }
7660 
7661   tbl = HiddenGroup (p, -1, 0, NULL);
7662   SetGroupSpacing (tbl, 10, 5);
7663   SetGroupMargins (tbl, 5, 5);
7664 
7665   g0 = HiddenGroup (tbl, 15, 0, NULL);
7666   SetGroupSpacing (g0, 0, 3);
7667 #ifdef WIN_MSWIN
7668   fnt = systemFont;
7669 #else
7670   fnt = programFont;
7671 #endif
7672   /*
7673   StaticPrompt (g0, "Category", inferColFmt [0].pixWidth, 0, fnt, 'c');
7674   StaticPrompt (g0, "Explanation", inferColFmt [1].pixWidth, 0, fnt, 'c');
7675   */
7676 
7677   idp->inferdoc = DocumentPanel (tbl, wid + 2, NUM_INFERENCE_LINES * hgt + 2);
7678   SetObjectExtra (idp->inferdoc, idp, NULL);
7679   SetDocCache (idp->inferdoc, NULL, NULL, NULL);
7680   SetDocNotify (idp->inferdoc, ChangeInferTableSelect);
7681   idp->numInf = 0;
7682 
7683   for (i = 0; i < NUM_INFERENCE_LINES; i++) {
7684     AppendItem (idp->inferdoc, PrintInferTable, idp, FALSE, 1,
7685                 &inferParFmt, inferColFmt, systemFont);
7686   }
7687 
7688   cts = HiddenGroup (p, -1, 0, NULL);
7689   SetGroupSpacing (cts, 10, 10);
7690   SetGroupMargins (cts, 5, 5);
7691 
7692   g1 = HiddenGroup (cts, -10, 0, NULL);
7693   SetGroupSpacing (g1, 5, 5);
7694 
7695   StaticPrompt (g1, "Category", 0, popupMenuHeight, programFont, 'l');
7696   idp->evcat = CreateEnumPopupDialog (g1, TRUE, ChangeInferCat, evcat_alist, (UIEnum) 0, idp);
7697 
7698   StaticPrompt (g1, "Type", 0, popupMenuHeight, programFont, 'l');
7699   idp->prefix = CreateEnumPopupDialog (g1, TRUE, ChangeInferPrefix, inference_alist, (UIEnum) 0, idp);
7700 
7701   idp->species = CheckBox (g1, "(same species)", ChangeSameSpecies);
7702   SetObjectExtra (idp->species, idp, NULL);
7703   Hide (idp->species);
7704 
7705   g2 = HiddenGroup (cts, 0, 0, NULL);
7706   SetGroupSpacing (g2, 5, 5);
7707 
7708   g3 = HiddenGroup (g2, -3, 0, NULL);
7709   SetGroupSpacing (g3, 5, 5);
7710 
7711   StaticPrompt (g3, "Database", 0, dialogTextHeight, programFont, 'l');
7712   idp->database = CreateEnumPopupDialog (g3, TRUE, ChangeInferDatabase, accn_type_alist, (UIEnum) 0, idp);
7713   idp->other_db_group = HiddenGroup (g3, -4, 0, NULL);
7714   StaticPrompt (idp->other_db_group, ":", 0, dialogTextHeight, programFont, 'l');
7715   idp->db_other = DialogText (idp->other_db_group, "", 8, ChangeInferDbOther);
7716   SetObjectExtra (idp->db_other, idp, NULL);
7717   Hide (idp->other_db_group);
7718 
7719   StaticPrompt (g3, "Accession", 0, dialogTextHeight, programFont, 'l');
7720   idp->accession = DialogText (g3, "", 10, ChangeInferAccession);
7721   SetObjectExtra (idp->accession, idp, NULL);
7722 
7723   idp->inf_accn_group = g3;
7724   Hide (idp->inf_accn_group);
7725 
7726   g4 = HiddenGroup (g2, -3, 0, NULL);
7727   SetGroupSpacing (g4, 5, 5);
7728 
7729   StaticPrompt (g4, "Program", 0, dialogTextHeight, programFont, 'l');
7730   idp->program = CreateEnumPopupDialog (g4, TRUE, ChangeInferProgram, program_alist, (UIEnum) 0, idp);
7731   idp->other_pr_group = HiddenGroup (g4, -4, 0, NULL);
7732   StaticPrompt (idp->other_pr_group, ":", 0, dialogTextHeight, programFont, 'l');
7733   idp->pr_other = DialogText (idp->other_pr_group, "", 8, ChangeInferPrOther);
7734   SetObjectExtra (idp->pr_other, idp, NULL);
7735   Hide (idp->other_pr_group);
7736 
7737   StaticPrompt (g4, "Program Version", 0, dialogTextHeight, programFont, 'l');
7738   idp->version = DialogText (g4, "", 3, ChangeInferVersion);
7739   SetObjectExtra (idp->version, idp, NULL);
7740 
7741   idp->inf_prog_group = g4;
7742   Hide (idp->inf_prog_group);
7743 
7744   g5 = HiddenGroup (g2, 2, 0, NULL);
7745   SetGroupSpacing (g5, 5, 5);
7746 
7747   prompt_grp = HiddenGroup (g5, 0, 0, NULL);
7748   idp->inf_free_program_prompt = StaticPrompt (prompt_grp, "Program or Database", 0, dialogTextHeight, programFont, 'l');
7749   idp->accession_list_program_prompt = StaticPrompt (prompt_grp, "Program", 0, dialogTextHeight, programFont, 'l');
7750   idp->basis1 = DialogText (g5, "", 10, ChangeInferBasis1);
7751   SetObjectExtra (idp->basis1, idp, NULL);
7752 
7753   prompt_grp = HiddenGroup (g5, 0, 0, NULL);
7754   idp->inf_free_version_prompt = StaticPrompt (prompt_grp, "Version or Accession", 0, dialogTextHeight, programFont, 'l');
7755   idp->accession_list_version_prompt = StaticPrompt (prompt_grp, "Version", 0, dialogTextHeight, programFont, 'l');
7756 
7757   idp->basis2 = DialogText (g5, "", 10, ChangeInferBasis2);
7758   SetObjectExtra (idp->basis2, idp, NULL);
7759 
7760   idp->accession_list_prompt = StaticPrompt (g5, "Accessions", 0, dialogTextHeight, programFont, 'l');
7761   idp->accession_list = CreateTagListDialogEx3 (g5, 3, 2, 2,
7762                               accessionlist_types, accessionlist_widths,
7763                               accessionlist_popups, TRUE, FALSE, AccessionListDataToDialog, AccessionListDialogToData,
7764                               AccessionListCallbacks, idp,
7765                               FALSE, FALSE);
7766 
7767   idp->inf_free_group = g5;
7768   Hide (idp->inf_free_group);
7769 
7770   AlignObjects (ALIGN_CENTER, (HANDLE) tbl, (HANDLE) cts, NULL);
7771 
7772   idp->numInf = 0;
7773   idp->currItem = 1;
7774   SetDocHighlight (idp->inferdoc, 1, 1);
7775 
7776   return (DialoG) p;
7777 }
7778 
7779 
7780 typedef struct experimentdlg {
7781   DIALOG_MESSAGE_BLOCK
7782   DialoG     dlg;
7783 } ExperimentDlgData, PNTR ExperimentDlgPtr;
7784 
7785 
7786 Uint2 experiment_types [] = {
7787   TAGLIST_POPUP, TAGLIST_TEXT, TAGLIST_TEXT
7788 };
7789 
7790 Uint2 experiment_widths [] = {
7791   10, 10, 10
7792 };
7793 
ENUM_ALIST(experiment_category_alist)7794 ENUM_ALIST(experiment_category_alist)
7795   { " ",       0 },
7796   { "COORDINATES", 1 },
7797   { "DESCRIPTION", 2 },
7798   { "EXISTENCE",   3 },
7799 END_ENUM_ALIST
7800 
7801 static EnumFieldAssocPtr experiment_popups [] = {
7802   experiment_category_alist, NULL
7803 };
7804 
7805 
StartsWithStringFollowedBySpaceAndColon(CharPtr text,CharPtr str)7806 static Boolean StartsWithStringFollowedBySpaceAndColon (CharPtr text, CharPtr str)
7807 {
7808   Int4 len;
7809 
7810   if (StringHasNoText (text) || StringHasNoText (str)) {
7811     return FALSE;
7812   }
7813   len = StringLen (str);
7814   if (StringNICmp (text, str, len) != 0) {
7815     return FALSE;
7816   }
7817   len += StringSpn (text + len, " ");
7818   if (text[len] == ':') {
7819     return TRUE;
7820   } else {
7821     return FALSE;
7822   }
7823 }
7824 
7825 
ExperimentToDialog(DialoG d,Pointer data)7826 static void ExperimentToDialog (DialoG d, Pointer data)
7827 {
7828   ExperimentDlgPtr dlg;
7829   TagListPtr       tlp;
7830   ValNodePtr       vals, vnp;
7831   CharPtr          exp, fmt, doi;
7832   Int2             num_rows = 0;
7833   Int4             i, match_num;
7834   Int4             len;
7835 
7836   dlg = (ExperimentDlgPtr) GetObjectExtra (d);
7837   if (dlg == NULL) {
7838     return;
7839   }
7840   tlp = (TagListPtr) GetObjectExtra (dlg->dlg);
7841   if (tlp == NULL) {
7842     return;
7843   }
7844   tlp->vnp = ValNodeFreeData (tlp->vnp);
7845   vals = (ValNodePtr) data;
7846   for (vnp = vals; vnp != NULL; vnp = vnp->next) {
7847     exp = (CharPtr) vnp->data.ptrvalue;
7848     if (!StringHasNoText (exp)) {
7849       len = 19;
7850       match_num = 0;
7851       for (i = 1; experiment_category_alist[i].name != NULL && match_num == 0; i++) {
7852         if (StartsWithStringFollowedBySpaceAndColon(exp, experiment_category_alist[i].name)) {
7853           match_num = i;
7854           exp = StringChr(exp, ':') + 1;
7855         }
7856       }
7857       len += StringLen (exp);
7858       doi = StringRChr (exp, '[');
7859       if (doi != NULL && exp[StringLen (exp) - 1] != ']') {
7860         doi = NULL;
7861       }
7862 
7863       fmt = (CharPtr) MemNew (sizeof (Char) + len);
7864       sprintf (fmt, "%d\t", match_num);
7865       if (doi == NULL) {
7866         StringCat (fmt, exp);
7867         StringCat (fmt, "\t");
7868       } else {
7869         StringNCat (fmt, exp, doi - exp);
7870         StringCat (fmt, "\t");
7871         StringCat (fmt, doi + 1);
7872         len = StringLen (fmt);
7873         if (fmt[len - 1] == ']') {
7874           fmt[len - 1] = 0;
7875         }
7876       }
7877       ValNodeAddPointer (&(tlp->vnp), 0, fmt);
7878       num_rows++;
7879     }
7880   }
7881 
7882   tlp->max = MAX ((Int2) 0, (Int2) (num_rows - tlp->rows + 1));
7883   CorrectBarMax (tlp->bar, tlp->max);
7884   CorrectBarPage (tlp->bar, (Int2) (tlp->rows-1), (Int2) (tlp->rows-1));
7885 
7886   SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
7887 }
7888 
7889 
ExperimentFromDialog(DialoG d)7890 static Pointer ExperimentFromDialog(DialoG d)
7891 {
7892   ExperimentDlgPtr dlg;
7893   TagListPtr       tlp;
7894   ValNodePtr       vals = NULL, vnp;
7895   CharPtr          cat_name, exp, doi, num_str, fmt;
7896   Int4             len, cat_num;
7897 
7898   dlg = (ExperimentDlgPtr) GetObjectExtra (d);
7899   if (dlg == NULL) {
7900     return NULL;
7901   }
7902   tlp = (TagListPtr) GetObjectExtra (dlg->dlg);
7903   if (tlp == NULL) {
7904     return NULL;
7905   }
7906 
7907   for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next) {
7908     num_str = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 0);
7909     exp = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 1);
7910     doi = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 2);
7911     cat_name = NULL;
7912     if (!StringHasNoText (num_str) && (cat_num = atoi(num_str)) > 0) {
7913       cat_name = experiment_category_alist[cat_num].name;
7914     }
7915     num_str = MemFree (num_str);
7916     len = StringLen (exp) + 1;
7917     if (cat_name != NULL) {
7918       len += StringLen (cat_name) + 1;
7919     }
7920     if (StringHasNoText (doi)) {
7921       doi = MemFree (doi);
7922     }
7923     if (doi != NULL) {
7924       len += StringLen (doi) + 2;
7925     }
7926     fmt = (CharPtr) MemNew (sizeof (Char) * len);
7927     sprintf (fmt, "%s%s%s%s%s%s",
7928              cat_name == NULL ? "" : cat_name,
7929              cat_name == NULL ? "" : ":",
7930              exp == NULL ? "" : exp,
7931              doi == NULL ? "" : "[",
7932              doi == NULL ? "" : doi,
7933              doi == NULL ? "" : "]");
7934     ValNodeAddPointer (&vals, 0, fmt);
7935     exp = MemFree (exp);
7936     doi = MemFree (doi);
7937   }
7938   return (Pointer) vals;
7939 }
7940 
7941 
CreateExperimentDialog(GrouP prnt)7942 extern DialoG CreateExperimentDialog (GrouP prnt)
7943 {
7944   GrouP            p, g;
7945   ExperimentDlgPtr dlg;
7946   TagListPtr       tlp;
7947   PrompT           p1, p2, p3;
7948 
7949   dlg = (ExperimentDlgPtr) MemNew (sizeof (ExperimentDlgData));
7950   if (dlg == NULL) return NULL;
7951 
7952   p = HiddenGroup (prnt, -1, 0, NULL);
7953   SetGroupSpacing (p, 10, 10);
7954 
7955   SetObjectExtra (p, dlg, StdCleanupExtraProc);
7956   dlg->dialog = (DialoG) p;
7957   dlg->todialog = ExperimentToDialog;
7958   dlg->fromdialog = ExperimentFromDialog;
7959 
7960   g = HiddenGroup (p, 3, 0, NULL);
7961   SetGroupSpacing (g, 10, 10);
7962   SelectFont(systemFont);
7963   p1 = StaticPrompt (g, "Category (optional)", 0, 0, systemFont, 'c');
7964   p2 = StaticPrompt (g, "Experiment", 0, 0, systemFont, 'c');
7965   p3 = StaticPrompt (g, "PMID or doi (optional)", 0, 0, systemFont, 'c');
7966   dlg->dlg = CreateTagListDialogEx3 (p, 3, 3, 2,
7967                               experiment_types, experiment_widths,
7968                               experiment_popups, TRUE, FALSE, NULL, NULL,
7969                               NULL, NULL,
7970                               FALSE, FALSE);
7971   tlp = GetObjectExtra (dlg->dlg);
7972   AlignObjects (ALIGN_JUSTIFY, (HANDLE) p1, (HANDLE) tlp->control[0], NULL);
7973   AlignObjects (ALIGN_JUSTIFY, (HANDLE) p2, (HANDLE) tlp->control[1], NULL);
7974   AlignObjects (ALIGN_JUSTIFY, (HANDLE) p3, (HANDLE) tlp->control[2], NULL);
7975 
7976   return (DialoG) p;
7977 }
7978 
7979 
ExperimentDialogToGbquals(SeqFeatPtr sfp,DialoG d)7980 extern void ExperimentDialogToGbquals (SeqFeatPtr sfp, DialoG d)
7981 
7982 {
7983   GBQualPtr   gbq, gbqlast = NULL;
7984   ValNodePtr  head = NULL, vnp;
7985   CharPtr     str;
7986 
7987   if (sfp == NULL) return;
7988   head = DialogToPointer (d);
7989   for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
7990     gbqlast = gbq;
7991   }
7992   for (vnp = head; vnp != NULL; vnp = vnp->next) {
7993     str = (CharPtr) vnp->data.ptrvalue;
7994     if (StringHasNoText (str)) continue;
7995     gbq = GBQualNew ();
7996     if (gbq == NULL) continue;
7997     gbq->qual = StringSave ("experiment");
7998     gbq->val = StringSave (str);
7999     if (gbqlast == NULL) {
8000       sfp->qual = gbq;
8001     } else {
8002       gbqlast->next = gbq;
8003     }
8004     gbqlast = gbq;
8005   }
8006   ValNodeFreeData (head);
8007 }
8008 
8009 
GBQualsToExperimentDialog(SeqFeatPtr sfp,DialoG d)8010 extern void GBQualsToExperimentDialog (SeqFeatPtr sfp, DialoG d)
8011 {
8012   ValNodePtr list = NULL;
8013   GBQualPtr   gbq;
8014 
8015   if (sfp != NULL) {
8016     for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
8017       if (StringICmp (gbq->qual, "experiment") == 0) {
8018         ValNodeAddPointer (&list, 0, gbq->val);
8019       }
8020     }
8021   }
8022   PointerToDialog (d, list);
8023   list = ValNodeFree (list);
8024 }
8025 
8026 
8027 /* ExistingText handling dialog and structures */
8028 typedef struct existingtextdlg
8029 {
8030   GrouP pre_app_grp;
8031   GrouP delim_grp;
8032 } ExistingTextDlgData, PNTR ExistingTextDlgPtr;
8033 
ChangePreAppIgnoreChoice(GrouP g)8034 static void ChangePreAppIgnoreChoice (GrouP g)
8035 {
8036   ExistingTextDlgPtr etdp;
8037   Int4               handle_choice;
8038 
8039   etdp = (ExistingTextDlgPtr) GetObjectExtra (g);
8040   if (etdp == NULL)
8041   {
8042     return;
8043   }
8044 
8045   handle_choice = GetValue (etdp->pre_app_grp);
8046   if (handle_choice == 1 || handle_choice == 2)
8047   {
8048     Enable (etdp->delim_grp);
8049   }
8050   else
8051   {
8052     Disable (etdp->delim_grp);
8053   }
8054 }
8055 
GetExistingTextHandlerInfo(Int4 num_found,Boolean non_text)8056 extern ExistingTextPtr GetExistingTextHandlerInfo (Int4 num_found, Boolean non_text)
8057 {
8058   WindoW                w;
8059   GrouP                 h, c;
8060   ExistingTextDlgData   etdd;
8061   ButtoN                b;
8062   ModalAcceptCancelData acd;
8063   ExistingTextPtr       etp;
8064   MsgAnswer             ans;
8065   PrompT                ppt;
8066   Int4                  handle_choice;
8067 
8068   if (num_found <= 0)
8069   {
8070     return NULL;
8071   }
8072 
8073   ans = Message (MSG_YNC, "%d affected fields already contain a value.  Do you wish to overwrite existing text?", num_found);
8074   if (ans == ANS_CANCEL)
8075   {
8076     etp = (ExistingTextPtr) MemNew (sizeof (ExistingTextData));
8077     etp->existing_text_choice = eExistingTextChoiceCancel;
8078     return etp;
8079   }
8080   else if (ans == ANS_YES)
8081   {
8082     etp = (ExistingTextPtr) MemNew (sizeof (ExistingTextData));
8083     etp->existing_text_choice = eExistingTextChoiceReplaceOld;
8084     return etp;
8085   }
8086 
8087   w = MovableModalWindow(-20, -13, -10, -10, "How to Add New Text", NULL);
8088   h = HiddenGroup (w, -1, 0, NULL);
8089   SetGroupSpacing (h, 10, 10);
8090   etdd.pre_app_grp = HiddenGroup (h, 0, 3, ChangePreAppIgnoreChoice);
8091   SetGroupSpacing (etdd.pre_app_grp, 10, 10);
8092   RadioButton (etdd.pre_app_grp, "Append");
8093   RadioButton (etdd.pre_app_grp, "Prefix");
8094   RadioButton (etdd.pre_app_grp, "Ignore new text");
8095   SetValue (etdd.pre_app_grp, 1);
8096   SetObjectExtra (etdd.pre_app_grp, &etdd, NULL);
8097 
8098   ppt = StaticPrompt (h, "Separate new text and old text with",
8099                       0, dialogTextHeight, programFont, 'c');
8100   etdd.delim_grp = HiddenGroup (h, 0, 4, NULL);
8101   SetGroupSpacing (etdd.delim_grp, 10, 10);
8102   RadioButton (etdd.delim_grp, "Semicolon");
8103   RadioButton (etdd.delim_grp, "Space");
8104   RadioButton (etdd.delim_grp, "Colon");
8105   RadioButton (etdd.delim_grp, "Do not separate");
8106   SetValue (etdd.delim_grp, 1);
8107 
8108   c = HiddenGroup (h, 2, 0, NULL);
8109   SetGroupSpacing (c, 10, 10);
8110   b = PushButton (c, "Accept", ModalAcceptButton);
8111   SetObjectExtra (b, &acd, NULL);
8112   b = PushButton (c, "Cancel", ModalCancelButton);
8113   SetObjectExtra (b, &acd, NULL);
8114   AlignObjects (ALIGN_CENTER, (HANDLE) etdd.pre_app_grp,
8115                               (HANDLE) ppt,
8116                               (HANDLE) etdd.delim_grp,
8117                               (HANDLE) c,
8118                               NULL);
8119   Show (w);
8120   Select (w);
8121   acd.accepted = FALSE;
8122   acd.cancelled = FALSE;
8123   while (!acd.accepted && ! acd.cancelled)
8124   {
8125     ProcessExternalEvent ();
8126     Update ();
8127   }
8128   ProcessAnEvent ();
8129   etp = (ExistingTextPtr) MemNew (sizeof (ExistingTextData));
8130   if (acd.cancelled)
8131   {
8132     etp->existing_text_choice = eExistingTextChoiceCancel;
8133   }
8134   else
8135   {
8136     handle_choice = GetValue (etdd.pre_app_grp);
8137     if (handle_choice == 1)
8138     {
8139       switch (GetValue (etdd.delim_grp))
8140       {
8141         case 1:
8142           etp->existing_text_choice = eExistingTextChoiceAppendSemi;
8143           break;
8144         case 2:
8145           etp->existing_text_choice = eExistingTextChoiceAppendSpace;
8146           break;
8147         case 3:
8148           etp->existing_text_choice = eExistingTextChoiceAppendColon;
8149           break;
8150         case 4:
8151           etp->existing_text_choice = eExistingTextChoiceAppendNone;
8152           break;
8153       }
8154     }
8155     else if (handle_choice == 2)
8156     {
8157       switch (GetValue (etdd.delim_grp))
8158       {
8159         case 1:
8160           etp->existing_text_choice = eExistingTextChoicePrefixSemi;
8161           break;
8162         case 2:
8163           etp->existing_text_choice = eExistingTextChoicePrefixSpace;
8164           break;
8165         case 3:
8166           etp->existing_text_choice = eExistingTextChoicePrefixColon;
8167           break;
8168         case 4:
8169           etp->existing_text_choice = eExistingTextChoicePrefixNone;
8170           break;
8171       }
8172     }
8173     else
8174     {
8175       etp->existing_text_choice = eExistingTextChoiceLeaveOld;
8176     }
8177   }
8178   Remove (w);
8179   return etp;
8180 }
8181 
HandleExistingText(CharPtr existing_text,CharPtr new_text,ExistingTextPtr etp)8182 extern CharPtr HandleExistingText (CharPtr existing_text, CharPtr new_text, ExistingTextPtr etp)
8183 {
8184   CharPtr rstring = NULL;
8185   Int4    len;
8186 
8187   if (StringHasNoText (existing_text) || etp == NULL)
8188   {
8189     MemFree (existing_text);
8190     return new_text;
8191   }
8192   switch (etp->existing_text_choice)
8193   {
8194     case eExistingTextChoiceReplaceOld:
8195       /* replace current text with new text */
8196       MemFree (existing_text);
8197       rstring = new_text;
8198       break;
8199     case eExistingTextChoiceLeaveOld:
8200       /* do not change current text */
8201       MemFree (new_text);
8202       rstring = existing_text;
8203       break;
8204     case eExistingTextChoiceAppendSemi:
8205       /* Append new text to current text, separated by semicolon */
8206       len = StringLen (new_text) + StringLen (existing_text) + 4;
8207       rstring = MemNew (len);
8208       if (rstring != NULL) {
8209         StringCpy (rstring, existing_text);
8210         StringCat (rstring, "; ");
8211         StringCat (rstring, new_text);
8212         MemFree (new_text);
8213         MemFree (existing_text);
8214       }
8215       break;
8216     case eExistingTextChoiceAppendSpace:
8217       /* Append new text to current text, separated by space */
8218       len = StringLen (new_text) + StringLen (existing_text) + 3;
8219       rstring = MemNew (len);
8220       if (rstring != NULL) {
8221         StringCpy (rstring, existing_text);
8222         StringCat (rstring, " ");
8223         StringCat (rstring, new_text);
8224         MemFree (new_text);
8225         MemFree (existing_text);
8226       }
8227       break;
8228     case eExistingTextChoiceAppendColon:
8229       /* Append new text to current text, separated by colon */
8230       len = StringLen (new_text) + StringLen (existing_text) + 4;
8231       rstring = MemNew (len);
8232       if (rstring != NULL) {
8233         StringCpy (rstring, existing_text);
8234         StringCat (rstring, ": ");
8235         StringCat (rstring, new_text);
8236         MemFree (new_text);
8237         MemFree (existing_text);
8238       }
8239       break;
8240     case eExistingTextChoiceAppendNone:
8241       /* Append new text to current text, no delimiter */
8242       len = StringLen (new_text) + StringLen (existing_text) + 1;
8243       rstring = MemNew (len);
8244       if (rstring != NULL) {
8245         StringCpy (rstring, existing_text);
8246         StringCat (rstring, new_text);
8247         MemFree (new_text);
8248         MemFree (existing_text);
8249       }
8250       break;
8251     case eExistingTextChoicePrefixSemi:
8252       /* Prepend new text to current text, separated by semicolon */
8253       len = StringLen (new_text) + StringLen (existing_text) + 4;
8254       rstring = MemNew (len);
8255       if (rstring != NULL) {
8256         StringCpy (rstring, new_text);
8257         StringCat (rstring, "; ");
8258         StringCat (rstring, existing_text);
8259         MemFree (new_text);
8260         MemFree (existing_text);
8261       }
8262       break;
8263     case eExistingTextChoicePrefixSpace:
8264       /* Prepend new text to current text, separated by space */
8265       len = StringLen (new_text) + StringLen (existing_text) + 3;
8266       rstring = MemNew (len);
8267       if (rstring != NULL) {
8268         StringCpy (rstring, new_text);
8269         StringCat (rstring, " ");
8270         StringCat (rstring, existing_text);
8271         MemFree (new_text);
8272         MemFree (existing_text);
8273       }
8274       break;
8275     case eExistingTextChoicePrefixColon:
8276       /* Prepend new text to current text, separated by colon */
8277       len = StringLen (new_text) + StringLen (existing_text) + 4;
8278       rstring = MemNew (len);
8279       if (rstring != NULL) {
8280         StringCpy (rstring, new_text);
8281         StringCat (rstring, ": ");
8282         StringCat (rstring, existing_text);
8283         MemFree (new_text);
8284         MemFree (existing_text);
8285       }
8286       break;
8287     case eExistingTextChoicePrefixNone:
8288       /* prefix current text with new text */
8289       len = StringLen (new_text) + StringLen (existing_text) + 1;
8290       rstring = MemNew (len);
8291       if (rstring != NULL) {
8292         StringCpy (rstring, new_text);
8293         StringCat (rstring, existing_text);
8294         MemFree (new_text);
8295         MemFree (existing_text);
8296       }
8297       break;
8298   }
8299   return rstring;
8300 }
8301 
8302 
8303 /* Move EditApply data and dialog here */
EditApplyFree(EditApplyPtr eap)8304 extern EditApplyPtr EditApplyFree (EditApplyPtr eap)
8305 {
8306   if (eap != NULL)
8307   {
8308     eap->find_txt = MemFree (eap->find_txt);
8309     eap->repl_txt = MemFree (eap->repl_txt);
8310     eap->apply_txt = MemFree (eap->apply_txt);
8311     eap = MemFree (eap);
8312   }
8313   return eap;
8314 }
8315 
8316 
EditApplyNew(void)8317 extern EditApplyPtr EditApplyNew (void)
8318 {
8319   EditApplyPtr eap;
8320 
8321   eap = (EditApplyPtr) MemNew (sizeof (EditApplyData));
8322   eap->find_location = EditApplyFindLocation_anywhere;
8323   return eap;
8324 }
8325 
8326 
8327 typedef struct EditApplydlg
8328 {
8329   DIALOG_MESSAGE_BLOCK
8330   TexT           find_txt;
8331   TexT           repl_txt;
8332   TexT           apply_txt;
8333 
8334   DialoG         find_dlg;
8335   DialoG         repl_dlg;
8336   DialoG         apply_dlg;
8337 
8338   Int4           action_choice;
8339   GrouP          location_choice;
8340   Nlm_ChangeNotifyProc     change_notify;
8341   Pointer                  change_userdata;
8342 } EditApplyDlgData, PNTR EditApplyDlgPtr;
8343 
ResetEditApplyDlg(EditApplyDlgPtr dlg)8344 static void ResetEditApplyDlg (EditApplyDlgPtr dlg)
8345 {
8346   if (dlg != NULL)
8347   {
8348     if (dlg->find_txt != NULL)
8349     {
8350       SetTitle (dlg->find_txt, "");
8351     }
8352     if (dlg->repl_txt != NULL)
8353     {
8354       SetTitle (dlg->repl_txt, "");
8355     }
8356     if (dlg->apply_txt != NULL)
8357     {
8358       SetTitle (dlg->apply_txt, "");
8359     }
8360     if (dlg->location_choice != NULL) {
8361       SetValue (dlg->location_choice, EditApplyFindLocation_anywhere);
8362     }
8363 
8364     PointerToDialog (dlg->find_dlg, NULL);
8365     PointerToDialog (dlg->repl_dlg, NULL);
8366     PointerToDialog (dlg->apply_dlg, NULL);
8367 
8368   }
8369 }
8370 
EditApplyDialogChangeText(TexT t)8371 static void EditApplyDialogChangeText (TexT t)
8372 {
8373   EditApplyDlgPtr dlg;
8374 
8375   dlg = (EditApplyDlgPtr) GetObjectExtra (t);
8376   if (dlg != NULL && dlg->change_notify != NULL)
8377   {
8378     (dlg->change_notify)(dlg->change_userdata);
8379   }
8380 }
8381 
EditApplyToDialog(DialoG d,Pointer userdata)8382 static void EditApplyToDialog (DialoG d, Pointer userdata)
8383 {
8384   EditApplyDlgPtr dlg;
8385   EditApplyPtr    data;
8386   ValNode         vn;
8387 
8388   dlg = (EditApplyDlgPtr) GetObjectExtra (d);
8389   if (dlg == NULL)
8390   {
8391     return;
8392   }
8393 
8394   ResetEditApplyDlg (dlg);
8395   data = (EditApplyPtr) userdata;
8396 
8397   vn.next = NULL;
8398   vn.choice = 0;
8399 
8400   if (data != NULL)
8401   {
8402     if (!StringHasNoText (data->find_txt))
8403     {
8404       if (dlg->find_txt != NULL)
8405       {
8406         SetTitle (dlg->find_txt, data->find_txt);
8407       }
8408       else if (dlg->find_dlg != NULL)
8409       {
8410         vn.data.ptrvalue = data->find_txt;
8411         PointerToDialog (dlg->find_dlg, &vn);
8412       }
8413     }
8414 
8415     if (!StringHasNoText (data->repl_txt))
8416     {
8417       if (dlg->repl_txt != NULL)
8418       {
8419         SetTitle (dlg->repl_txt, data->repl_txt);
8420       }
8421       else if (dlg->repl_dlg != NULL)
8422       {
8423         vn.data.ptrvalue = data->repl_txt;
8424         PointerToDialog (dlg->repl_dlg, &vn);
8425       }
8426     }
8427 
8428     if (!StringHasNoText (data->apply_txt))
8429     {
8430       if (dlg->apply_txt != NULL)
8431       {
8432         SetTitle (dlg->apply_txt, data->apply_txt);
8433       }
8434       else if (dlg->apply_dlg != NULL)
8435       {
8436         vn.data.ptrvalue = data->apply_txt;
8437         PointerToDialog (dlg->apply_dlg, &vn);
8438       }
8439     }
8440 
8441     if (dlg->location_choice != NULL) {
8442       SetValue (dlg->location_choice, data->find_location);
8443     }
8444   }
8445 }
8446 
DialogToEditApply(DialoG d)8447 static Pointer DialogToEditApply (DialoG d)
8448 {
8449   EditApplyDlgPtr dlg;
8450   EditApplyPtr    data;
8451   ValNodePtr      vnp;
8452 
8453   dlg = (EditApplyDlgPtr) GetObjectExtra (d);
8454   if (dlg == NULL)
8455   {
8456     return NULL;
8457   }
8458 
8459   data = (EditApplyPtr) MemNew (sizeof (EditApplyData));
8460   if (data != NULL)
8461   {
8462     if (dlg->find_txt != NULL)
8463     {
8464       data->find_txt = JustSaveStringFromText (dlg->find_txt);
8465     }
8466     else if (dlg->find_dlg != NULL)
8467     {
8468       vnp = (ValNodePtr) DialogToPointer (dlg->find_dlg);
8469       if (vnp != NULL)
8470       {
8471         data->find_txt = StringSave (vnp->data.ptrvalue);
8472       }
8473       vnp = ValNodeFreeData (vnp);
8474     }
8475 
8476     if (dlg->repl_txt != NULL)
8477     {
8478       data->repl_txt = JustSaveStringFromText (dlg->repl_txt);
8479     }
8480     else if (dlg->repl_dlg != NULL)
8481     {
8482       vnp = (ValNodePtr) DialogToPointer (dlg->repl_dlg);
8483       if (vnp != NULL)
8484       {
8485         data->repl_txt = StringSave (vnp->data.ptrvalue);
8486       }
8487       vnp = ValNodeFreeData (vnp);
8488     }
8489 
8490     if (dlg->apply_txt != NULL)
8491     {
8492       data->apply_txt = JustSaveStringFromText (dlg->apply_txt);
8493     }
8494     else if (dlg->apply_dlg != NULL)
8495     {
8496       vnp = (ValNodePtr) DialogToPointer (dlg->apply_dlg);
8497       if (vnp != NULL)
8498       {
8499         data->apply_txt = StringSave (vnp->data.ptrvalue);
8500       }
8501       vnp = ValNodeFreeData (vnp);
8502     }
8503 
8504     if (dlg->location_choice != NULL) {
8505       data->find_location = (EditApplyFindLocation) GetValue (dlg->location_choice);
8506     } else {
8507       data->find_location = EditApplyFindLocation_anywhere;
8508     }
8509   }
8510   return data;
8511 }
8512 
8513 
EditApplyMessage(DialoG d,Int2 mssg)8514 static void EditApplyMessage (DialoG d, Int2 mssg)
8515 
8516 {
8517   EditApplyDlgPtr  dlg;
8518 
8519   dlg = (EditApplyDlgPtr) GetObjectExtra (d);
8520   if (dlg != NULL) {
8521     switch (mssg)
8522     {
8523       case VIB_MSG_INIT :
8524         /* reset list */
8525         ResetEditApplyDlg (dlg);
8526         break;
8527       case VIB_MSG_ENTER :
8528         if (dlg->find_txt != NULL)
8529         {
8530           Select (dlg->find_txt);
8531         }
8532         else if (dlg->apply_txt != NULL)
8533         {
8534           Select (dlg->apply_txt);
8535         }
8536         else if (dlg->find_dlg != NULL)
8537         {
8538           Select (dlg->find_dlg);
8539         }
8540         else if (dlg->apply_dlg != NULL)
8541         {
8542           Select (dlg->apply_dlg);
8543         }
8544         break;
8545       case NUM_VIB_MSG + 1 :
8546         SafeSetTitle (dlg->apply_txt, "");
8547         SafeSetTitle (dlg->find_txt, "");
8548         SafeSetTitle (dlg->repl_txt, "");
8549         break;
8550       default :
8551         break;
8552     }
8553   }
8554 }
8555 
TestEditApply(DialoG d)8556 static ValNodePtr TestEditApply (DialoG d)
8557 {
8558   EditApplyDlgPtr dlg;
8559   ValNodePtr      total_err_list = NULL, err_list;
8560 
8561   dlg = (EditApplyDlgPtr) GetObjectExtra (d);
8562   if (dlg == NULL)
8563   {
8564     return FALSE;
8565   }
8566 
8567   if (dlg->action_choice == eEditApplyChoice_Apply)
8568   {
8569     if (dlg->apply_dlg == NULL)
8570     {
8571       if (TextHasNoText (dlg->apply_txt))
8572       {
8573         ValNodeAddPointer (&total_err_list, 0, StringSave ("apply text"));
8574       }
8575     }
8576     else
8577     {
8578       total_err_list = TestDialog (dlg->apply_dlg);
8579     }
8580   }
8581   else if (dlg->action_choice == eEditApplyChoice_Edit)
8582   {
8583     if (dlg->find_dlg == NULL)
8584     {
8585       if (TextHasNoText (dlg->find_txt))
8586       {
8587         ValNodeAddPointer (&total_err_list, 0, StringSave ("find text"));
8588       }
8589     }
8590     else
8591     {
8592       total_err_list = TestDialog (dlg->find_dlg);
8593       err_list = TestDialog (dlg->repl_dlg);
8594       ValNodeLink (&total_err_list, err_list);
8595     }
8596   }
8597   return total_err_list;
8598 }
8599 
8600 
EditApplyDialogCopy(ButtoN b)8601 static void EditApplyDialogCopy (ButtoN b)
8602 {
8603   EditApplyDlgPtr dlg;
8604   CharPtr         str = NULL;
8605 
8606   dlg = (EditApplyDlgPtr) GetObjectExtra (b);
8607   if (dlg == NULL)
8608   {
8609     return;
8610   }
8611   str = JustSaveStringFromText (dlg->find_txt);
8612   SetTitle (dlg->repl_txt, str);
8613   str = MemFree (str);
8614 }
8615 
EditApplyDialog(GrouP h,Int4 action_choice,CharPtr apply_label,ValNodePtr choice_list,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)8616 extern DialoG EditApplyDialog
8617 (GrouP                    h,
8618  Int4                     action_choice,
8619  CharPtr                  apply_label,
8620  ValNodePtr               choice_list,
8621  Nlm_ChangeNotifyProc     change_notify,
8622  Pointer                  change_userdata)
8623 {
8624   EditApplyDlgPtr dlg;
8625   GrouP           p, p1 = NULL;
8626   ButtoN          b;
8627   ValNodePtr      cpy;
8628 
8629   dlg = (EditApplyDlgPtr) MemNew (sizeof (EditApplyDlgData));
8630   if (dlg == NULL)
8631   {
8632     return NULL;
8633   }
8634 
8635   p = HiddenGroup (h, -1, 0, NULL);
8636   SetObjectExtra (p, dlg, StdCleanupExtraProc);
8637   SetGroupSpacing (p, 10, 10);
8638 
8639   dlg->dialog = (DialoG) p;
8640   dlg->todialog = EditApplyToDialog;
8641   dlg->fromdialog = DialogToEditApply;
8642   dlg->dialogmessage = EditApplyMessage;
8643   dlg->testdialog = TestEditApply;
8644   dlg->action_choice = action_choice;
8645   dlg->change_notify = change_notify;
8646   dlg->change_userdata = change_userdata;
8647 
8648   if (choice_list == NULL)
8649   {
8650     p1 = HiddenGroup (p, 3, 0, NULL);
8651     SetGroupSpacing (p1, 10, 10);
8652 
8653     if (action_choice == eEditApplyChoice_Apply)
8654     {
8655       StaticPrompt (p1, apply_label, 0, dialogTextHeight, systemFont, 'r');
8656       dlg->apply_txt = DialogText (p1, "", 20, EditApplyDialogChangeText);
8657       SetObjectExtra (dlg->apply_txt, dlg, NULL);
8658       dlg->location_choice = NULL;
8659     }
8660     else if (action_choice == eEditApplyChoice_Edit)
8661     {
8662       StaticPrompt (p1, "Find", 0, dialogTextHeight, systemFont, 'r');
8663       dlg->find_txt = DialogText (p1, "", 18, EditApplyDialogChangeText);
8664       SetObjectExtra (dlg->find_txt, dlg, NULL);
8665       b = PushButton (p1, "Copy", EditApplyDialogCopy);
8666       SetObjectExtra (b, dlg, NULL);
8667       Hide (b);
8668       StaticPrompt (p1, "Replace", 0, dialogTextHeight, systemFont, 'r');
8669       dlg->repl_txt = DialogText (p1, "", 18, EditApplyDialogChangeText);
8670       SetObjectExtra (dlg->repl_txt, dlg, NULL);
8671       b = PushButton (p1, "Copy", EditApplyDialogCopy);
8672       SetObjectExtra (b, dlg, NULL);
8673 
8674       dlg->location_choice = HiddenGroup (p, 3, 0, NULL);
8675       RadioButton (dlg->location_choice, "Anywhere in field");
8676       RadioButton (dlg->location_choice, "At the beginning of the field");
8677       RadioButton (dlg->location_choice, "At the end of the field");
8678       SetValue (dlg->location_choice, EditApplyFindLocation_anywhere);
8679     }
8680   }
8681   else
8682   {
8683     if (action_choice == eEditApplyChoice_Apply)
8684     {
8685       p1 = HiddenGroup (p, 1, 0, NULL);
8686       SetGroupSpacing (p1, 10, 10);
8687       if (!StringHasNoText (apply_label))
8688       {
8689         StaticPrompt (p1, apply_label, 0, dialogTextHeight, systemFont, 'r');
8690       }
8691       cpy = ValNodeDupStringList (choice_list);
8692       dlg->apply_dlg = ValNodeSelectionDialog (p1, cpy, 6,
8693                                                ValNodeStringName,
8694                                                ValNodeSimpleDataFree,
8695                                                ValNodeStringCopy,
8696                                                ValNodeStringMatch,
8697                                                apply_label,
8698                                                dlg->change_notify, dlg->change_userdata, FALSE);
8699     }
8700     else if (action_choice == eEditApplyChoice_Edit)
8701     {
8702       p1 = HiddenGroup (p, 2, 0, NULL);
8703       SetGroupSpacing (p1, 10, 10);
8704       StaticPrompt (p1, "From", 0, dialogTextHeight, systemFont, 'r');
8705       StaticPrompt (p1, "To", 0, dialogTextHeight, systemFont, 'r');
8706 
8707       cpy = ValNodeDupStringList (choice_list);
8708       dlg->find_dlg = ValNodeSelectionDialog (p1, cpy, 6,
8709                                                ValNodeStringName,
8710                                                ValNodeSimpleDataFree,
8711                                                ValNodeStringCopy,
8712                                                ValNodeStringMatch,
8713                                                "Original",
8714                                                dlg->change_notify, dlg->change_userdata, FALSE);
8715       cpy = ValNodeDupStringList (choice_list);
8716       dlg->repl_dlg = ValNodeSelectionDialog (p1, cpy, 6,
8717                                                ValNodeStringName,
8718                                                ValNodeSimpleDataFree,
8719                                                ValNodeStringCopy,
8720                                                ValNodeStringMatch,
8721                                                "New",
8722                                                dlg->change_notify, dlg->change_userdata, FALSE);
8723 
8724     }
8725     dlg->location_choice = NULL;
8726   }
8727   AlignObjects (ALIGN_CENTER, (HANDLE) p1, (HANDLE) dlg->location_choice, NULL);
8728 
8729   return (DialoG) p;
8730 }
8731 
8732 
8733 /* Global Inference Editor Dialog */
8734 
ParseInferenceText(CharPtr inference)8735 extern InferenceParsePtr ParseInferenceText (CharPtr inference)
8736 {
8737   CharPtr cp1, cp2, cp3;
8738   Int4    len;
8739   InferenceParsePtr ipp;
8740 
8741   if (StringHasNoText (inference))
8742   {
8743     return NULL;
8744   }
8745 
8746   cp1 = StringChr (inference, ':');
8747   if (cp1 == NULL)
8748   {
8749     return NULL;
8750   }
8751   cp2 = StringChr (cp1 + 1, ':');
8752   if (cp2 == NULL)
8753   {
8754     return NULL;
8755   }
8756   cp3 = StringChr (cp2 + 1, ':');
8757   if (cp3 == NULL)
8758   {
8759     return NULL;
8760   }
8761 
8762   ipp = (InferenceParsePtr) MemNew (sizeof (InferenceParseData));
8763   ipp->second_field = StringSave (cp3 + 1);
8764 
8765   len = cp3 - cp2;
8766   ipp->first_field = (CharPtr) MemNew (sizeof (Char) * len);
8767   StringNCpy (ipp->first_field, cp2 + 1, len - 1);
8768   ipp->first_field[len - 1] = 0;
8769 
8770   /* look for same species */
8771   cp3 = StringISearch (inference, "(same species)");
8772   if (cp3 != NULL && cp3 < cp2)
8773   {
8774     ipp->same_species = TRUE;
8775     cp2 = cp3;
8776   }
8777   else
8778   {
8779     ipp->same_species = FALSE;
8780   }
8781 
8782   /* type */
8783   len = cp2 - cp1;
8784   ipp->type = (CharPtr) MemNew (sizeof (Char) * len);
8785   StringNCpy (ipp->type, cp1 + 1, len - 1);
8786   ipp->type[len - 1] = 0;
8787 
8788   len = cp1 - inference + 1;
8789   ipp->category = (CharPtr) MemNew (sizeof (Char) * len);
8790   StringNCpy (ipp->category, inference, len - 1);
8791   ipp->category[len - 1] = 0;
8792   TrimSpacesAroundString (ipp->category);
8793   TrimSpacesAroundString (ipp->type);
8794   TrimSpacesAroundString (ipp->first_field);
8795   TrimSpacesAroundString (ipp->second_field);
8796 
8797   return ipp;
8798 }
8799 
8800 
InferenceTextFromStruct(InferenceParsePtr ipp)8801 extern CharPtr InferenceTextFromStruct (InferenceParsePtr ipp)
8802 {
8803   Int4 len;
8804   CharPtr inference = NULL;
8805   CharPtr same_sp = " (same species)";
8806 
8807   if (ipp == NULL) return NULL;
8808 
8809   len = StringLen (ipp->category) + + StringLen (ipp->type) + StringLen (ipp->first_field) + StringLen (ipp->second_field)
8810         + 4;
8811   if (ipp->same_species)
8812   {
8813     len += StringLen (same_sp);
8814   }
8815 
8816   inference = (CharPtr) MemNew (sizeof (Char) * len);
8817   sprintf (inference, "%s:%s%s:%s:%s", ipp->category == NULL ? "" : ipp->category,
8818                                     ipp->type == NULL ? "" : ipp->type,
8819                                     ipp->same_species ? same_sp : "",
8820                                     ipp->first_field == NULL ? "" : ipp->first_field,
8821                                     ipp->second_field == NULL ? "" : ipp->second_field);
8822   return inference;
8823 }
8824 
8825 
8826 typedef enum {
8827   eInferenceCategorySimilarTo = 0,
8828   eInferenceCategoryProgram,
8829   eInferenceCategoryAbInitio,
8830   eNumInferenceCategories } EInferenceCategoryType;
8831 
8832 
GetCategoryTypeFromNum(Int4 num)8833 static Int4 GetCategoryTypeFromNum (Int4 num)
8834 {
8835   if (num > 0 && num < 8)
8836   {
8837     return eInferenceCategorySimilarTo;
8838   }
8839   else if (num > 7 && num < 11)
8840   {
8841     return eInferenceCategoryProgram;
8842   }
8843   else if (num == 11)
8844   {
8845     return eInferenceCategoryAbInitio;
8846   }
8847   else
8848   {
8849     return -1;
8850   }
8851 }
8852 
8853 
GetCategoryNumFromName(CharPtr category)8854 static Int4 GetCategoryNumFromName (CharPtr category)
8855 {
8856   Int4 i;
8857 
8858   if (StringHasNoText (category))
8859   {
8860     return -1;
8861   }
8862 
8863   for (i = 0; inference_alist[i].name != NULL; i++)
8864   {
8865     if (StringICmp (inference_alist[i].name, category) == 0)
8866     {
8867       return i;
8868     }
8869   }
8870   return -1;
8871 }
8872 
8873 
InferenceFieldEditFree(InferenceFieldEditPtr ifep)8874 extern InferenceFieldEditPtr InferenceFieldEditFree (InferenceFieldEditPtr ifep)
8875 {
8876   if (ifep != NULL)
8877   {
8878     ifep->edit_apply = EditApplyFree (ifep->edit_apply);
8879     ifep = MemFree (ifep);
8880   }
8881   return ifep;
8882 }
8883 
InferenceEditFree(InferenceEditPtr iep)8884 extern InferenceEditPtr InferenceEditFree (InferenceEditPtr iep)
8885 {
8886   if (iep != NULL)
8887   {
8888     iep->field_edit = InferenceFieldEditFree (iep->field_edit);
8889     iep = MemFree (iep);
8890   }
8891   return iep;
8892 }
8893 
8894 typedef struct inferencefieldeditdialog
8895 {
8896   DIALOG_MESSAGE_BLOCK
8897 
8898   PopuP  field_type;
8899   PopuP  field_list[eNumInferenceCategories];
8900   DialoG field_editors[eNumInferenceCategories * 2];
8901   Nlm_ChangeNotifyProc     change_notify;
8902   Pointer                  change_userdata;
8903 
8904 } InferenceFieldEditDialogData, PNTR InferenceFieldEditDialogPtr;
8905 
8906 
InferenceFieldEditDataFromDialog(DialoG d)8907 static Pointer InferenceFieldEditDataFromDialog (DialoG d)
8908 {
8909   InferenceFieldEditDialogPtr dlg;
8910   UIEnum                      val;
8911   Int4                        i, j;
8912   InferenceFieldEditPtr       data = NULL;
8913 
8914   dlg = (InferenceFieldEditDialogPtr) GetObjectExtra (d);
8915   if (dlg == NULL) return NULL;
8916 
8917   if (GetEnumPopup (dlg->field_type, inference_alist, &val)
8918       && val > 0
8919       && (i = GetCategoryTypeFromNum (val)) > -1
8920       && (j = GetValue (dlg->field_list[i])) > 0
8921       && j < 3)
8922   {
8923     data = (InferenceFieldEditPtr) MemNew (sizeof (InferenceFieldEditData));
8924     data->field_type = inferencePrefix[val];
8925     data->field_choice = j - 1;
8926     data->edit_apply = DialogToPointer (dlg->field_editors[2 * i + j - 1]);
8927   }
8928   return data;
8929 }
8930 
8931 
ChangeInferenceFieldChoice(PopuP p)8932 static void ChangeInferenceFieldChoice (PopuP p)
8933 {
8934   InferenceFieldEditDialogPtr dlg;
8935   UIEnum                      val;
8936   Int4                        i, j;
8937 
8938   dlg = (InferenceFieldEditDialogPtr) GetObjectExtra (p);
8939   if (dlg == NULL) return;
8940 
8941   for (i = eInferenceCategorySimilarTo;
8942        i <= eInferenceCategoryAbInitio;
8943        i++)
8944   {
8945     Hide (dlg->field_list[i]);
8946     Hide (dlg->field_editors[2 * i]);
8947     Hide (dlg->field_editors[2 * i + 1]);
8948   }
8949 
8950   if (GetEnumPopup (dlg->field_type, inference_alist, &val)
8951       && val > 0
8952       && (i = GetCategoryTypeFromNum (val)) > -1)
8953   {
8954     Show (dlg->field_list[i]);
8955     j = GetValue (dlg->field_list[i]);
8956     if (j > 0 && j < 3)
8957     {
8958       Show (dlg->field_editors[2 * i + j - 1]);
8959     }
8960   }
8961 
8962   if (dlg->change_notify != NULL)
8963   {
8964     (dlg->change_notify)(dlg->change_userdata);
8965   }
8966 }
8967 
MakeValNodeListFromEnum(EnumFieldAssocPtr al)8968 static ValNodePtr MakeValNodeListFromEnum ( EnumFieldAssocPtr al)
8969 {
8970   EnumFieldAssocPtr efap;
8971   ValNodePtr        list;
8972 
8973   efap = al;
8974   list = NULL;
8975   while (efap->name != NULL)
8976   {
8977     ValNodeAddStr (&list, efap->value, StringSave (efap->name));
8978     efap ++;
8979   }
8980   return list;
8981 }
8982 
8983 
8984 static DialoG
CreateInferenceFieldEditApplyDialog(GrouP h,Int4 action_choice,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)8985 CreateInferenceFieldEditApplyDialog
8986 (GrouP                h,
8987  Int4                 action_choice,
8988  Nlm_ChangeNotifyProc change_notify,
8989  Pointer              change_userdata)
8990 {
8991   InferenceFieldEditDialogPtr dlg;
8992   GrouP                       p, k;
8993   Int4                        i;
8994   ValNodePtr                  choice_list;
8995 
8996   dlg = (InferenceFieldEditDialogPtr) MemNew (sizeof (InferenceFieldEditDialogData));
8997   if (dlg == NULL)
8998   {
8999     return NULL;
9000   }
9001   p = HiddenGroup (h, 3, 0, NULL);
9002   SetObjectExtra (p, dlg, StdCleanupExtraProc);
9003   SetGroupSpacing (p, 10, 10);
9004 
9005   dlg->dialog = (DialoG) p;
9006   dlg->todialog = NULL;
9007   dlg->fromdialog = InferenceFieldEditDataFromDialog;
9008   dlg->dialogmessage = NULL;
9009   dlg->testdialog = NULL;
9010 
9011   dlg->change_notify = change_notify;
9012   dlg->change_userdata = change_userdata;
9013 
9014   StaticPrompt (p, "Type", 0, popupMenuHeight, programFont, 'c');
9015   StaticPrompt (p, "Field", 0, popupMenuHeight, programFont, 'c');
9016   if (action_choice == eEditApplyChoice_Apply)
9017   {
9018     StaticPrompt (p, "New Value", 0, popupMenuHeight, programFont, 'c');
9019   }
9020   else
9021   {
9022     StaticPrompt (p, "Convert", 0, popupMenuHeight, programFont, 'c');
9023   }
9024 
9025   dlg->field_type = PopupList (p, TRUE, ChangeInferenceFieldChoice);
9026   SetObjectExtra (dlg->field_type, dlg, NULL);
9027   InitEnumPopup (dlg->field_type, inference_alist, NULL);
9028 
9029 
9030   k = HiddenGroup (p, 0, 0, NULL);
9031   dlg->field_list[eInferenceCategorySimilarTo] = PopupList (k, TRUE, ChangeInferenceFieldChoice);
9032   SetObjectExtra (dlg->field_list[eInferenceCategorySimilarTo], dlg, NULL);
9033   PopupItem (dlg->field_list[eInferenceCategorySimilarTo], "Database");
9034   PopupItem (dlg->field_list[eInferenceCategorySimilarTo], "Accession");
9035 
9036   dlg->field_list[eInferenceCategoryProgram] = PopupList (k, TRUE, ChangeInferenceFieldChoice);
9037   SetObjectExtra (dlg->field_list[eInferenceCategoryProgram], dlg, NULL);
9038   PopupItem (dlg->field_list[eInferenceCategoryProgram], "Program or Database");
9039   PopupItem (dlg->field_list[eInferenceCategoryProgram], "Version or Accession");
9040 
9041   dlg->field_list[eInferenceCategoryAbInitio] = PopupList (k, TRUE, ChangeInferenceFieldChoice);
9042   SetObjectExtra (dlg->field_list[eInferenceCategoryAbInitio], dlg, NULL);
9043   PopupItem (dlg->field_list[eInferenceCategoryAbInitio], "Program");
9044   PopupItem (dlg->field_list[eInferenceCategoryAbInitio], "Program Version");
9045 
9046   k = HiddenGroup (p, 0, 0, NULL);
9047   i = 0;
9048   choice_list = MakeValNodeListFromEnum (accn_type_alist);
9049   dlg->field_editors[i++] = EditApplyDialog (k, action_choice, "", choice_list, change_notify, change_userdata);
9050   dlg->field_editors[i++] = EditApplyDialog (k, action_choice, "", NULL, change_notify, change_userdata);
9051   dlg->field_editors[i++] = EditApplyDialog (k, action_choice, "", NULL, change_notify, change_userdata);
9052   dlg->field_editors[i++] = EditApplyDialog (k, action_choice, "", NULL, change_notify, change_userdata);
9053   choice_list = MakeValNodeListFromEnum (program_alist);
9054   dlg->field_editors[i++] = EditApplyDialog (k, action_choice, "", choice_list, change_notify, change_userdata);
9055   dlg->field_editors[i++] = EditApplyDialog (k, action_choice, "", NULL, change_notify, change_userdata);
9056 
9057   ChangeInferenceFieldChoice (dlg->field_type);
9058   return (DialoG) p;
9059 }
9060 
9061 
9062 typedef struct inferenceeditdialog {
9063   DIALOG_MESSAGE_BLOCK
9064   PopuP action;
9065   GrouP action_pages[eNumInferenceEditActions];
9066   PopuP category_from;
9067   PopuP category_to;
9068   PopuP type_from;
9069   PopuP type_to;
9070 
9071   DialoG apply_field;
9072   DialoG edit_field;
9073 
9074   Nlm_ChangeNotifyProc change_notify;
9075   Pointer              change_userdata;
9076 
9077 } InferenceEditDialogData, PNTR InferenceEditDialogPtr;
9078 
9079 
InferenceEditDataFromDialog(DialoG d)9080 static Pointer InferenceEditDataFromDialog (DialoG d)
9081 {
9082   InferenceEditDialogPtr dlg;
9083   InferenceEditPtr       data;
9084   Int4                   i;
9085 
9086   dlg = (InferenceEditDialogPtr) GetObjectExtra (d);
9087   if (dlg == NULL) return NULL;
9088 
9089   data = (InferenceEditPtr) MemNew (sizeof (InferenceEditData));
9090   if (data == NULL) return NULL;
9091 
9092   data->action = (EInferenceEditAction) (GetValue (dlg->action) - 1);
9093 
9094   switch (data->action)
9095   {
9096     case eInferenceRemove:
9097       /* no other data needed */
9098       break;
9099     case eInferenceEditCategory:
9100       i = GetValue (dlg->category_from);
9101       if (i <= 1)
9102       {
9103         data->category_from = NULL;
9104       }
9105       else
9106       {
9107         data->category_from = evcat_alist[i - 2].name;
9108       }
9109       i = GetValue (dlg->category_to);
9110       if (i < 1)
9111       {
9112         data->category_to = NULL;
9113       }
9114       else
9115       {
9116         data->category_to = evcat_alist[i - 1].name;
9117       }
9118       break;
9119     case eInferenceEditType:
9120       i = GetValue (dlg->type_from);
9121       if (i <= 1)
9122       {
9123         data->type_from = NULL;
9124       }
9125       else
9126       {
9127         data->type_from = inference_alist[i - 2].name;
9128       }
9129       i = GetValue (dlg->type_to);
9130       if (i < 1)
9131       {
9132         data->type_to = NULL;
9133       }
9134       else
9135       {
9136         data->type_to = inference_alist[i - 1].name;
9137       }
9138       break;
9139     case eInferenceApplyTypeFields:
9140      data->field_edit = DialogToPointer (dlg->apply_field);
9141      break;
9142     case eInferenceEditTypeFields:
9143      data->field_edit = DialogToPointer (dlg->edit_field);
9144       break;
9145     default:
9146       break;
9147   }
9148 
9149   return data;
9150 }
9151 
9152 
ChangeInferenceEditAction(PopuP p)9153 static void ChangeInferenceEditAction (PopuP p)
9154 {
9155   InferenceEditDialogPtr dlg;
9156   Int4                   i;
9157 
9158   dlg = (InferenceEditDialogPtr) GetObjectExtra (p);
9159   if (dlg == NULL) return;
9160 
9161   ResetClip();
9162   for (i = 0; i < eNumInferenceEditActions; i++)
9163   {
9164     Hide (dlg->action_pages[i]);
9165   }
9166 
9167   i = GetValue (dlg->action);
9168   if (i > 0 && i <= eNumInferenceEditActions)
9169   {
9170     Show (dlg->action_pages[i - 1]);
9171   }
9172 
9173   if (dlg->change_notify != NULL)
9174   {
9175     (dlg->change_notify) (dlg->change_userdata);
9176   }
9177 }
9178 
9179 
ChangeInferenceCategoryChoice(PopuP p)9180 static void ChangeInferenceCategoryChoice (PopuP p)
9181 {
9182   InferenceEditDialogPtr dlg;
9183 
9184   dlg = (InferenceEditDialogPtr) GetObjectExtra (p);
9185   if (dlg == NULL) return;
9186 
9187   if (dlg->change_notify != NULL)
9188   {
9189     (dlg->change_notify) (dlg->change_userdata);
9190   }
9191 }
9192 
9193 
TestInferenceEditDialog(DialoG d)9194 static ValNodePtr TestInferenceEditDialog (DialoG d)
9195 {
9196   ValNodePtr             err_list = NULL;
9197   InferenceEditPtr       iep;
9198 
9199   iep = DialogToPointer (d);
9200   if (iep == NULL)
9201   {
9202     ValNodeAddPointer (&err_list, 0, "no values");
9203   }
9204   else
9205   {
9206     switch (iep->action)
9207     {
9208       case eInferenceRemove:
9209         /* nothing to check */
9210         break;
9211       case eInferenceEditCategory:
9212         if (StringHasNoText (iep->category_from))
9213         {
9214           ValNodeAddPointer (&err_list, 0, "missing category from");
9215         }
9216         if (StringHasNoText (iep->category_to))
9217         {
9218           ValNodeAddPointer (&err_list, 0, "missing category to");
9219         }
9220         break;
9221       case eInferenceEditType:
9222         if (StringHasNoText (iep->type_from))
9223         {
9224           ValNodeAddPointer (&err_list, 0, "missing type from");
9225         }
9226         if (StringHasNoText (iep->type_to))
9227         {
9228           ValNodeAddPointer (&err_list, 0, "missing type to");
9229         }
9230         break;
9231       case eInferenceApplyTypeFields:
9232       case eInferenceEditTypeFields:
9233         if (iep->field_edit == NULL)
9234         {
9235           ValNodeAddPointer (&err_list, 0, "missing edit data");
9236         }
9237         break;
9238       default:
9239         break;
9240     }
9241   }
9242   iep = InferenceEditFree (iep);
9243 
9244   return err_list;
9245 }
9246 
9247 
CreateInferenceEditDialog(GrouP h,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)9248 extern DialoG CreateInferenceEditDialog
9249 (GrouP                    h,
9250  Nlm_ChangeNotifyProc     change_notify,
9251  Pointer                  change_userdata)
9252 {
9253   InferenceEditDialogPtr dlg;
9254   GrouP                  p, g;
9255   Int4                   i;
9256   Nlm_EnumFieldAssocPtr  eap;
9257 
9258   dlg = (InferenceEditDialogPtr) MemNew (sizeof (InferenceEditDialogData));
9259   if (dlg == NULL)
9260   {
9261     return NULL;
9262   }
9263   p = HiddenGroup (h, -1, 0, NULL);
9264   SetObjectExtra (p, dlg, StdCleanupExtraProc);
9265   SetGroupSpacing (p, 10, 10);
9266 
9267   dlg->dialog = (DialoG) p;
9268   dlg->todialog = NULL;
9269   dlg->fromdialog = InferenceEditDataFromDialog;
9270   dlg->dialogmessage = NULL;
9271   dlg->testdialog = TestInferenceEditDialog;
9272 
9273   dlg->change_notify = change_notify;
9274   dlg->change_userdata = change_userdata;
9275 
9276   dlg->action = PopupList (p, TRUE, ChangeInferenceEditAction);
9277   SetObjectExtra (dlg->action, dlg, NULL);
9278   PopupItem (dlg->action, "Remove");
9279   PopupItem (dlg->action, "Change Category");
9280   PopupItem (dlg->action, "Change Type");
9281   PopupItem (dlg->action, "Apply Type Fields");
9282   PopupItem (dlg->action, "Edit Type Fields");
9283   SetValue (dlg->action, eInferenceRemove + 1);
9284 
9285   g = HiddenGroup (p, 0, 0, NULL);
9286   i = 0;
9287 
9288   /* remove group */
9289   dlg->action_pages[i] = HiddenGroup (g, -1, 0, NULL);
9290   StaticPrompt (dlg->action_pages[i], "Hit Accept to Remove Inferences", 0, popupMenuHeight, programFont, 'c');
9291   i++;
9292 
9293   /* edit category group */
9294   dlg->action_pages[i] = HiddenGroup (g, 2, 0, NULL);
9295   StaticPrompt (dlg->action_pages[i], "Original Category", 0, popupMenuHeight, programFont, 'c');
9296   dlg->category_from = PopupList (dlg->action_pages[i], TRUE, ChangeInferenceCategoryChoice);
9297   SetObjectExtra (dlg->category_from, dlg, NULL);
9298   PopupItem (dlg->category_from, "Any");
9299   eap = evcat_alist;
9300   while (eap->name != NULL) {
9301     PopupItem (dlg->category_from, eap->name);
9302     eap++;
9303   }
9304 
9305   StaticPrompt (dlg->action_pages[i], "New Category", 0, popupMenuHeight, programFont, 'c');
9306   dlg->category_to = PopupList (dlg->action_pages[i], TRUE, ChangeInferenceCategoryChoice);
9307   SetObjectExtra (dlg->category_to, dlg, NULL);
9308   InitEnumPopup (dlg->category_to, evcat_alist, NULL);
9309   i++;
9310 
9311   /* edit type group */
9312   dlg->action_pages[i] = HiddenGroup (g, 2, 0, NULL);
9313   StaticPrompt (dlg->action_pages[i], "Original Type", 0, popupMenuHeight, programFont, 'c');
9314   dlg->type_from = PopupList (dlg->action_pages[i], TRUE, ChangeInferenceCategoryChoice);
9315   SetObjectExtra (dlg->type_from, dlg, NULL);
9316   PopupItem (dlg->type_from, "Any");
9317   eap = inference_alist;
9318   while (eap->name != NULL) {
9319     PopupItem (dlg->type_from, eap->name);
9320     eap++;
9321   }
9322 
9323   StaticPrompt (dlg->action_pages[i], "New Type", 0, popupMenuHeight, programFont, 'c');
9324   dlg->type_to = PopupList (dlg->action_pages[i], TRUE, ChangeInferenceCategoryChoice);
9325   SetObjectExtra (dlg->type_to, dlg, NULL);
9326   InitEnumPopup (dlg->type_to, inference_alist, NULL);
9327   i++;
9328 
9329   dlg->action_pages[i] = HiddenGroup (g, 0, 0, NULL);
9330   dlg->apply_field = CreateInferenceFieldEditApplyDialog (dlg->action_pages[i], eEditApplyChoice_Apply, change_notify, change_userdata);
9331   i++;
9332 
9333   dlg->action_pages[i] = HiddenGroup (g, 0, 0, NULL);
9334   dlg->edit_field = CreateInferenceFieldEditApplyDialog (dlg->action_pages[i], eEditApplyChoice_Edit, change_notify, change_userdata);
9335   i++;
9336 
9337   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->action_pages[0],
9338                               (HANDLE) dlg->action_pages[1],
9339                               (HANDLE) dlg->action_pages[2],
9340                               (HANDLE) dlg->action_pages[3],
9341                               NULL);
9342 
9343   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->action, (HANDLE) g, NULL);
9344 
9345   ChangeInferenceEditAction (dlg->action);
9346 
9347   return (DialoG) p;
9348 }
9349 
9350 
9351 /* This section of code is for handling ClickableLists */
9352 
9353 typedef struct clickableitemlist
9354 {
9355   DIALOG_MESSAGE_BLOCK
9356   DoC doc;
9357 
9358   Nlm_ParData par_fmt;
9359   Nlm_ColPtr col_fmt;
9360 
9361   ClickableCallback single_click_callback;
9362   ClickableCallback double_click_callback;
9363   Pointer           click_callback_data;
9364   GetClickableItemText get_item_text;
9365   ValNodePtr           item_list;
9366   Int2                 selected;
9367 } ClickableItemListDlgData, PNTR ClickableItemListDlgPtr;
9368 
PointerToClickableItemListDlg(DialoG d,Pointer data)9369 static void PointerToClickableItemListDlg (DialoG d, Pointer data)
9370 {
9371   ClickableItemListDlgPtr dlg;
9372   ValNodePtr              vnp;
9373   CharPtr                 row_text;
9374   Int2                    numItems;
9375   RecT                    r;
9376   Int4                    i, count;
9377 
9378   dlg = (ClickableItemListDlgPtr) GetObjectExtra (d);
9379   if (dlg == NULL) return;
9380 
9381   Reset (dlg->doc);
9382 
9383   if (dlg->get_item_text == NULL)
9384   {
9385     return;
9386   }
9387 
9388   ObjectRect (dlg->doc, &r);
9389   InsetRect (&r, 4, 4);
9390 
9391   count = 1;
9392   i = 0;
9393   while (!dlg->col_fmt[i].last) {
9394     i++;
9395     count++;
9396   }
9397 
9398   if (count > 1) {
9399     dlg->col_fmt[0].pixWidth = 5 * stdCharWidth;
9400     i = 0;
9401     while (!dlg->col_fmt[i].last) {
9402       i++;
9403       dlg->col_fmt[i].pixWidth = (r.right - r.left - dlg->col_fmt[0].pixWidth) / (count - 1);
9404     }
9405   } else {
9406     dlg->col_fmt[0].pixWidth = r.right - r.left;
9407   }
9408 
9409   dlg->item_list = ClickableItemObjectListFree (dlg->item_list);
9410   dlg->item_list = (ValNodePtr) data;
9411 
9412   if (dlg->item_list == NULL)
9413   {
9414     AppendText (dlg->doc, "No items listed", NULL, NULL, programFont);
9415   } else {
9416     for (vnp = dlg->item_list; vnp != NULL; vnp = vnp->next) {
9417       row_text = dlg->get_item_text (vnp);
9418       if (row_text != NULL)
9419       {
9420         if (vnp->choice == OBJ_SEQFEAT)
9421         {
9422           AppendText (dlg->doc, row_text, &(dlg->par_fmt), dlg->col_fmt, programFont);
9423         }
9424         else
9425         {
9426           AppendText (dlg->doc, row_text, &(dlg->par_fmt), NULL, programFont);
9427         }
9428         row_text = MemFree (row_text);
9429       }
9430     }
9431   }
9432 
9433   GetDocParams (dlg->doc, &numItems, NULL);
9434   UpdateDocument (dlg->doc, 0, numItems);
9435 }
9436 
9437 
ClickClickableItemList(DoC d,PoinT pt)9438 static void ClickClickableItemList (DoC d, PoinT pt)
9439 
9440 {
9441   Int2             item, last_selected, numItems;
9442   Int2             row, i;
9443   ClickableItemListDlgPtr dlg;
9444   ValNodePtr       vnp;
9445 
9446   dlg = GetObjectExtra (d);
9447   if (dlg != NULL) {
9448     MapDocPoint (d, pt, &item, &row, NULL, NULL);
9449     if (item > 0 && row > 0) {
9450       i = 1;
9451       vnp = dlg->item_list;
9452       while (i < item && vnp != NULL) {
9453         i++;
9454         vnp = vnp->next;
9455       }
9456       if (vnp != NULL) {
9457         last_selected = dlg->selected;
9458         dlg->selected = item;
9459 
9460         if (item != last_selected)
9461         {
9462           GetDocParams (d, &numItems, NULL);
9463           UpdateDocument (d, 0, numItems);
9464         }
9465 
9466         if (dblClick)
9467         {
9468           if (dlg->double_click_callback != NULL) {
9469             (dlg->double_click_callback) (vnp, dlg->click_callback_data);
9470           }
9471         } else {
9472           if (dlg->single_click_callback != NULL) {
9473             (dlg->single_click_callback) (vnp, dlg->click_callback_data);
9474           }
9475         }
9476       }
9477     }
9478   }
9479 }
9480 
9481 
DrawClickableItemList(DoC d,RectPtr r,Int2 item,Int2 firstLine)9482 static void DrawClickableItemList (DoC d, RectPtr r, Int2 item, Int2 firstLine)
9483 
9484 {
9485   ClickableItemListDlgPtr dlg;
9486   RecT             rct;
9487 
9488   dlg = (ClickableItemListDlgPtr) GetObjectExtra (d);
9489   if (dlg != NULL && r != NULL && item > 0 && firstLine == 0) {
9490     rct = *r;
9491 
9492     /* draw selection */
9493     if (item == dlg->selected) {
9494       rct = *r;
9495       rct.right = rct.left + 4;
9496       PaintRect (&rct);
9497     }
9498   }
9499 }
9500 
9501 
CleanupClickableItemListDlg(GraphiC g,VoidPtr data)9502 static void CleanupClickableItemListDlg (GraphiC g, VoidPtr data)
9503 {
9504   ClickableItemListDlgPtr dlg;
9505 
9506   dlg = (ClickableItemListDlgPtr) data;
9507   if (dlg != NULL) {
9508     dlg->item_list = ClickableItemObjectListFree (dlg->item_list);
9509     dlg->col_fmt = MemFree (dlg->col_fmt);
9510   }
9511   StdCleanupExtraProc (g, data);
9512 }
9513 
9514 static DialoG
ClickableItemListDialog(GrouP h,Int4 width,GetClickableItemText get_item_text,Int4 num_item_text_columns,ClickableCallback single_click_callback,ClickableCallback double_click_callback,Pointer click_callback_data)9515 ClickableItemListDialog
9516 (GrouP h,
9517  Int4 width,
9518  GetClickableItemText get_item_text,
9519  Int4 num_item_text_columns,
9520  ClickableCallback single_click_callback,
9521  ClickableCallback double_click_callback,
9522  Pointer click_callback_data)
9523 {
9524   ClickableItemListDlgPtr dlg;
9525   GrouP                p;
9526   Int4 i;
9527 
9528   dlg = (ClickableItemListDlgPtr) MemNew (sizeof (ClickableItemListDlgData));
9529   p = HiddenGroup (h, -1, 0, NULL);
9530   SetObjectExtra (p, dlg, CleanupClickableItemListDlg);
9531   dlg->dialog = (DialoG) p;
9532   dlg->todialog = PointerToClickableItemListDlg;
9533 
9534   dlg->get_item_text = get_item_text;
9535   dlg->single_click_callback = single_click_callback;
9536   dlg->double_click_callback = double_click_callback;
9537   dlg->click_callback_data = click_callback_data;
9538   /* initialize paragraph format */
9539   dlg->par_fmt.openSpace = FALSE;
9540   dlg->par_fmt.keepWithNext = FALSE;
9541   dlg->par_fmt.keepTogether = FALSE;
9542   dlg->par_fmt.newPage = FALSE;
9543   dlg->par_fmt.tabStops = FALSE;
9544   dlg->par_fmt.minLines = 0;
9545   dlg->par_fmt.minHeight = 0;
9546 
9547   dlg->col_fmt = (Nlm_ColPtr) MemNew (sizeof (Nlm_ColData) * num_item_text_columns);
9548   /* initialize column format */
9549   for (i = 0; i < num_item_text_columns; i++) {
9550     dlg->col_fmt[i].pixWidth = 0;
9551     dlg->col_fmt[i].pixInset = 0;
9552     dlg->col_fmt[i].charWidth = 10;
9553     dlg->col_fmt[i].charInset = 0;
9554     dlg->col_fmt[i].font = NULL;
9555     dlg->col_fmt[i].just = 'l';
9556     dlg->col_fmt[i].wrap = 1;
9557     dlg->col_fmt[i].bar = 0;
9558     dlg->col_fmt[i].underline = 0;
9559     dlg->col_fmt[i].left = 0;
9560     dlg->col_fmt[i].last = FALSE;
9561   }
9562   dlg->col_fmt[0].pixInset = 5;
9563   dlg->col_fmt[num_item_text_columns - 1].last = TRUE;
9564 
9565   dlg->doc = DocumentPanel (p, width, stdLineHeight * 20);
9566   SetObjectExtra (dlg->doc, dlg, NULL);
9567   SetDocAutoAdjust (dlg->doc, FALSE);
9568   SetDocProcs (dlg->doc, ClickClickableItemList, NULL, NULL, NULL);
9569   SetDocShade (dlg->doc, DrawClickableItemList, NULL, NULL, NULL);
9570 
9571   return (DialoG) p;
9572 }
9573 
9574 typedef struct clickablelist
9575 {
9576   DIALOG_MESSAGE_BLOCK
9577   DoC  doc;
9578   DialoG clickable_item_list;
9579   PrompT title1;
9580   PrompT title2;
9581   PrompT help1;
9582   PrompT help2;
9583   TexT find_txt;
9584 
9585   ClickableCallback item_single_click_callback;
9586   ClickableCallback item_double_click_callback;
9587   Pointer         item_click_callback_data;
9588   GetClickableItemText get_item_text;
9589   Boolean         dblClick;
9590   Int2            clicked;
9591   Int2            selected;
9592   Int2            item_selected;
9593   Int4            num_levels;
9594   ValNodePtr      list_list;
9595   Nlm_ColPtr PNTR col_fmt_array_array;
9596   PrompT          chosen_count;
9597 
9598   Int2            text_select_item_start;
9599   Int2            text_select_row_start;
9600   Int2            text_select_char_start;
9601   Int2            text_select_item_stop;
9602   Int2            text_select_row_stop;
9603   Int2            text_select_char_stop;
9604   Int2            text_select_item_anchor;
9605   Int2            text_select_row_anchor;
9606   Int2            text_select_char_anchor;
9607 
9608   Boolean         display_chosen;
9609 } ClickableListData, PNTR ClickableListPtr;
9610 
9611 
9612 static Nlm_ParData clickableParFmt = {FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0};
9613 static Nlm_ColData clickableColFmt[2] = {{16, 0, 0, 0, NULL, 'l', 0,0,0,0, FALSE},
9614                                     {1000, 0, 0, 0, NULL, 'l', 1,0,0,0, TRUE}};
9615 
9616 
FreeColumnFormatArrays(Nlm_ColPtr PNTR col_fmt_array_array,Int4 num_levels)9617 static Nlm_ColPtr PNTR FreeColumnFormatArrays (Nlm_ColPtr PNTR col_fmt_array_array, Int4 num_levels)
9618 {
9619   Int4 n;
9620 
9621   if (col_fmt_array_array == NULL || num_levels < 1)
9622   {
9623     return NULL;
9624   }
9625   for (n = 0; n < num_levels; n++)
9626   {
9627     col_fmt_array_array [n] = MemFree (col_fmt_array_array [n]);
9628   }
9629   col_fmt_array_array = MemFree (col_fmt_array_array);
9630   return col_fmt_array_array;
9631 }
9632 
CleanupClickableListDialog(GraphiC g,VoidPtr data)9633 static void CleanupClickableListDialog (GraphiC g, VoidPtr data)
9634 
9635 {
9636   ClickableListPtr dlg;
9637 
9638   dlg = (ClickableListPtr) data;
9639   if (dlg != NULL) {
9640      dlg->col_fmt_array_array = FreeColumnFormatArrays (dlg->col_fmt_array_array, dlg->num_levels);
9641   }
9642   StdCleanupExtraProc (g, data);
9643 }
9644 
9645 
GetSubItem(ValNodePtr item_list,Int2Ptr pitem)9646 static ClickableItemPtr GetSubItem (ValNodePtr item_list, Int2Ptr pitem)
9647 {
9648   ClickableItemPtr cip = NULL;
9649 
9650   if (item_list == NULL || pitem == NULL)
9651   {
9652     return NULL;
9653   }
9654   while (*pitem > 0 && item_list != NULL)
9655   {
9656     (*pitem)--;
9657     cip = (ClickableItemPtr) item_list->data.ptrvalue;
9658     if (*pitem > 0)
9659     {
9660       if (cip != NULL && cip->expanded)
9661       {
9662         cip = GetSubItem (cip->subcategories, pitem);
9663       }
9664     }
9665     item_list = item_list->next;
9666   }
9667   if (*pitem > 0)
9668   {
9669     cip = NULL;
9670   }
9671   return cip;
9672 }
9673 
CountLevels(ValNodePtr item_list)9674 static Int4 CountLevels (ValNodePtr item_list)
9675 {
9676   Int4       num, num_sublevels = 0;
9677   ValNodePtr vnp;
9678   ClickableItemPtr cip;
9679 
9680   if (item_list == NULL)
9681   {
9682     return 0;
9683   }
9684 
9685   for (vnp = item_list; vnp != NULL; vnp = vnp->next)
9686   {
9687     cip = (ClickableItemPtr) vnp->data.ptrvalue;
9688     if (cip == NULL || cip->subcategories == NULL || !cip->expanded)
9689     {
9690       continue;
9691     }
9692     num = CountLevels (cip->subcategories);
9693     if (num > num_sublevels) num_sublevels = num;
9694   }
9695 
9696   /* one level for the top plus levels for the subcategories */
9697 
9698   return 1 + num_sublevels;
9699 }
9700 
9701 
GetSelectedClickableList(ValNodePtr item_list,Int2 item)9702 static ClickableItemPtr GetSelectedClickableList (ValNodePtr item_list, Int2 item)
9703 {
9704   ClickableItemPtr cip = NULL;
9705 
9706   cip = GetSubItem (item_list, &item);
9707 
9708   return cip;
9709 }
9710 
9711 
GetColumnFormatArrays(Int4 num_levels,DoC doc)9712 static Nlm_ColPtr PNTR GetColumnFormatArrays (Int4 num_levels, DoC doc)
9713 {
9714   Int4               n, k;
9715   Nlm_ColPtr PNTR    col_fmt_array_array = NULL;
9716   RecT               r;
9717   Int4               doc_width;
9718 
9719   if (num_levels == 0)
9720   {
9721     return NULL;
9722   }
9723 
9724   ObjectRect (doc, &r);
9725   InsetRect (&r, 4, 4);
9726   doc_width = r.right - r.left;
9727 
9728   col_fmt_array_array = (Nlm_ColPtr PNTR) MemNew (sizeof (Nlm_ColPtr) * num_levels);
9729   for (n = 0; n < num_levels; n++)
9730   {
9731     col_fmt_array_array[n] = (Nlm_ColPtr) MemNew (sizeof (Nlm_ColData) * (n + 3));
9732     for (k = 0; k < n + 2; k++)
9733     {
9734       col_fmt_array_array[n][k].pixWidth = 16;
9735       col_fmt_array_array[n][k].pixInset = 0;
9736       col_fmt_array_array[n][k].charWidth = 0;
9737       col_fmt_array_array[n][k].charInset = 0;
9738       col_fmt_array_array[n][k].font = programFont;
9739       col_fmt_array_array[n][k].just = 'l';
9740       col_fmt_array_array[n][k].wrap = 0;
9741       col_fmt_array_array[n][k].bar = 0;
9742       col_fmt_array_array[n][k].underline = 0;
9743       col_fmt_array_array[n][k].left = 0;
9744       col_fmt_array_array[n][k].last = 0;
9745     }
9746     col_fmt_array_array[n][k].pixWidth = doc_width - ((n + 2) * 16);
9747     col_fmt_array_array[n][k].pixInset = 0;
9748     col_fmt_array_array[n][k].charWidth = 0;
9749     col_fmt_array_array[n][k].charInset = 0;
9750     col_fmt_array_array[n][k].font = programFont;
9751     col_fmt_array_array[n][k].just = 'l';
9752     col_fmt_array_array[n][k].wrap = 1;
9753     col_fmt_array_array[n][k].bar = 0;
9754     col_fmt_array_array[n][k].underline = 0;
9755     col_fmt_array_array[n][k].left = 0;
9756     col_fmt_array_array[n][k].last = 1;
9757   }
9758   return col_fmt_array_array;
9759 }
9760 
9761 
AddClickableItem(ClickableListPtr dlg,ClickableItemPtr cip,Int4 level)9762 static void AddClickableItem (ClickableListPtr dlg, ClickableItemPtr cip, Int4 level)
9763 {
9764   CharPtr            item_text;
9765   ValNodePtr         vnp;
9766   Int4               n;
9767 
9768   if (cip == NULL)
9769   {
9770     return;
9771   }
9772   item_text = (CharPtr) MemNew (sizeof (Char) * (StringLen (cip->description) + 6 + level));
9773   for (n = 0; n < level; n++)
9774   {
9775     StringCat (item_text, "\t");
9776   }
9777   StringCat (item_text, " \t \t");
9778   StringCat (item_text, cip->description);
9779   StringCat (item_text, "\n");
9780   AppendText (dlg->doc, item_text, &clickableParFmt, dlg->col_fmt_array_array [level], programFont);
9781   if (cip->expanded)
9782   {
9783     for (vnp = cip->subcategories; vnp != NULL; vnp = vnp->next)
9784     {
9785       AddClickableItem (dlg, vnp->data.ptrvalue, level + 1);
9786     }
9787   }
9788 }
9789 
PopulateClickableList(ClickableListPtr dlg,ValNodePtr list_list)9790 static void PopulateClickableList (ClickableListPtr dlg, ValNodePtr list_list)
9791 {
9792   Int2               numItems;
9793   Int4               num_levels;
9794 
9795   if (dlg == NULL || dlg->doc == NULL)
9796   {
9797     return;
9798   }
9799 
9800   Reset (dlg->doc);
9801 
9802   num_levels = CountLevels (dlg->list_list);
9803   if (num_levels != dlg->num_levels)
9804   {
9805     dlg->col_fmt_array_array = FreeColumnFormatArrays (dlg->col_fmt_array_array, dlg->num_levels);
9806     dlg->num_levels = num_levels;
9807     dlg->col_fmt_array_array = GetColumnFormatArrays (dlg->num_levels, dlg->doc);
9808   }
9809 
9810   while (list_list != NULL)
9811   {
9812     AddClickableItem (dlg, list_list->data.ptrvalue, 0);
9813     list_list = list_list->next;
9814   }
9815   GetDocParams (dlg->doc, &numItems, NULL);
9816   UpdateDocument (dlg->doc, 0, numItems);
9817 
9818 }
9819 
9820 
PanelOffsetFromCharOffsetEx(DoC doc,FonT font,Int2 item,Int2 col,Int2 char_offset)9821 NLM_EXTERN Int2 PanelOffsetFromCharOffsetEx (DoC doc, FonT font, Int2 item, Int2 col, Int2 char_offset)
9822 {
9823   Int2 numRows, numCols, lineHeight;
9824   Int2 left_start, width, inset, char_width;
9825 
9826   if (doc == NULL) return 0;
9827   GetItemParams4 (doc, item, NULL, &numRows, &numCols, &lineHeight, NULL);
9828   GetColParams (doc, item, col, &left_start, &width, &inset, NULL);
9829 
9830   /* need to set font so that Nlm_CharWidth works properly */
9831   SelectFont (font);
9832   char_width = Nlm_CharWidth ('A');
9833   return left_start + inset + char_offset * char_width;
9834 }
9835 
9836 
PanelOffsetFromCharOffset(ClickableListPtr dlg,Int2 item,Int2 char_offset)9837 static Int2 PanelOffsetFromCharOffset (ClickableListPtr dlg, Int2 item, Int2 char_offset)
9838 {
9839   Int2 numCols;
9840   if (dlg == NULL) return 0;
9841   GetItemParams4 (dlg->doc, item, NULL, NULL, &numCols, NULL, NULL);
9842 
9843   return PanelOffsetFromCharOffsetEx (dlg->doc, dlg->col_fmt_array_array[0][0].font, item, numCols, char_offset);
9844 }
9845 
9846 
GetTextSelectCharOffsetEx(PoinT pt,DoC doc,FonT font,Int2 item,Int2 row,Int2 col)9847 NLM_EXTERN Int2 GetTextSelectCharOffsetEx (PoinT pt, DoC doc, FonT font, Int2 item, Int2 row, Int2 col)
9848 {
9849   Int2 pixPos, pixInset;
9850   Int2 one_char_width;
9851   CharPtr txt;
9852   Int4    len;
9853   Int2    char_offset;
9854 
9855   if (doc == NULL) return 0;
9856 
9857   GetColParams (doc, item, col, &pixPos,
9858                 NULL, &pixInset, NULL);
9859 
9860   SelectFont (font);
9861   one_char_width = Nlm_CharWidth ('A');
9862   if (one_char_width == 0) return 0;
9863 
9864   char_offset = (pt.x - pixPos - pixInset) / one_char_width;
9865   if (char_offset > 0) {
9866     txt = GetDocText (doc, item, row, col);
9867     len = StringLen (txt);
9868     if (char_offset >= len) {
9869       char_offset = - 1;
9870     }
9871   }
9872 
9873   return char_offset;
9874 }
9875 
9876 
GetTextSelectCharOffset(PoinT pt,ClickableListPtr dlg,Int2 item,Int2 row,Int2 col)9877 static Int2 GetTextSelectCharOffset (PoinT pt, ClickableListPtr dlg, Int2 item, Int2 row, Int2 col)
9878 {
9879   if (dlg == NULL) return 0;
9880 
9881   return GetTextSelectCharOffsetEx (pt, dlg->doc, dlg->col_fmt_array_array[0][0].font, item, row, col);
9882 }
9883 
9884 
ValNodeLinkCopy(ValNodePtr PNTR list1,ValNodePtr list2)9885 static void ValNodeLinkCopy (ValNodePtr PNTR list1, ValNodePtr list2)
9886 {
9887   if (list1 == NULL) return;
9888   while (list2 != NULL)
9889   {
9890     ValNodeAddPointer (list1, list2->choice, list2->data.ptrvalue);
9891     list2 = list2->next;
9892   }
9893 }
9894 
9895 
GetChosenItemsList(ValNodePtr clickable_list)9896 static ValNodePtr GetChosenItemsList (ValNodePtr clickable_list)
9897 {
9898   ValNodePtr item_list = NULL;
9899   ClickableItemPtr cip;
9900 
9901   while (clickable_list != NULL) {
9902     cip = (ClickableItemPtr) clickable_list->data.ptrvalue;
9903     if (cip != NULL) {
9904       if (cip->chosen) {
9905         ValNodeLinkCopy (&item_list, cip->item_list);
9906       } else {
9907         ValNodeLink (&item_list, GetChosenItemsList (cip->subcategories));
9908       }
9909     }
9910     clickable_list = clickable_list->next;
9911   }
9912   return item_list;
9913 }
9914 
9915 
UpdateChosenCount(DialoG d)9916 static void UpdateChosenCount (DialoG d)
9917 {
9918   ClickableListPtr dlg;
9919   ValNodePtr list;
9920   Int4       num;
9921   CharPtr    fmt = "%d items selected";
9922   Char       val[255];
9923 
9924   dlg = (ClickableListPtr) GetObjectExtra (d);
9925   if (dlg == NULL) {
9926     return;
9927   }
9928 
9929   list = GetChosenItemsList (dlg->list_list);
9930   num = ValNodeLen (list);
9931   list = ClickableItemObjectListFree (list);
9932   sprintf (val, fmt, num);
9933   SetTitle (dlg->chosen_count, val);
9934 }
9935 
9936 
ClickList(DoC d,PoinT pt)9937 static void ClickList (DoC d, PoinT pt)
9938 
9939 {
9940   Int2             item, numItems;
9941   Int2             row;
9942   Int2             col;
9943   ClickableListPtr dlg;
9944   ClickableItemPtr cip;
9945   Int4             offset;
9946   Int2             first_shown;
9947   Boolean          rsult;
9948   RecT             r;
9949 
9950   dlg = GetObjectExtra (d);
9951   if (dlg != NULL) {
9952     MapDocPoint (d, pt, &item, &row, &col, NULL);
9953     if (item > 0 && row > 0 && dlg->clicked == item) {
9954       dlg->dblClick = dblClick;
9955     } else {
9956       dlg->dblClick = FALSE;
9957     }
9958     dlg->clicked = 0;
9959     if (item > 0 && row > 0) {
9960       dlg->clicked = item;
9961     }
9962     if (item > 0 && row > 0 && !dblClick)
9963     {
9964       cip = GetSelectedClickableList (dlg->list_list, item);
9965       if (cip != NULL)
9966       {
9967         if (col == cip->level + 1)
9968         {
9969           cip->chosen = !cip->chosen;
9970           GetDocParams (d, &numItems, NULL);
9971           UpdateDocument (d, 0, numItems);
9972           if (dlg->display_chosen)
9973           {
9974             PointerToDialog (dlg->clickable_item_list, GetChosenItemsList (dlg->list_list));
9975             UpdateChosenCount (dlg->dialog);
9976           }
9977         }
9978         else if (col == cip->level + 2)
9979         {
9980           if (cip->subcategories != NULL) {
9981             cip->expanded = !cip->expanded;
9982             rsult = GetScrlParams4 (dlg->doc, &offset, &first_shown, NULL);
9983             PopulateClickableList (dlg, dlg->list_list);
9984             if (rsult) {
9985               GetItemParams4 (dlg->doc, first_shown, &offset, NULL, NULL, NULL, NULL);
9986               SetScrlParams4 (dlg->doc, offset);
9987             }
9988             ObjectRect (dlg->doc, &r);
9989             InsetRect (&r, -1, -1);
9990             InvalRect (&r);
9991           }
9992         } else {
9993           dlg->text_select_item_anchor = item;
9994           dlg->text_select_row_anchor = row;
9995           dlg->text_select_char_anchor = GetTextSelectCharOffset (pt, dlg, item, row, col);
9996 
9997           dlg->text_select_char_start = dlg->text_select_char_anchor;
9998           dlg->text_select_char_stop = dlg->text_select_char_start;
9999           if (dlg->text_select_char_start < 0) {
10000             dlg->text_select_item_start = -1;
10001             dlg->text_select_row_start = -1;
10002             dlg->text_select_item_stop = -1;
10003             dlg->text_select_row_stop = -1;
10004           } else {
10005             dlg->text_select_item_start = item;
10006             dlg->text_select_row_start = row;
10007             dlg->text_select_item_stop = item;
10008             dlg->text_select_row_stop = row;
10009           }
10010           GetDocParams (dlg->doc, &numItems, NULL);
10011           UpdateDocument (dlg->doc, 0, numItems);
10012         }
10013       }
10014     }
10015   }
10016 }
10017 
UpdateClickableListTextSelection(ClickableListPtr dlg,Int2 item,Int2 row,Int2 col,PoinT pt)10018 static void UpdateClickableListTextSelection (ClickableListPtr dlg, Int2 item, Int2 row, Int2 col, PoinT pt)
10019 {
10020   Int2 char_start, numCols;
10021 
10022   if (dlg == NULL || item < 1 || row < 1) return;
10023 
10024   /* only update for positions in the text area */
10025   GetItemParams4 (dlg->doc, item, NULL, NULL, &numCols, NULL, NULL);
10026   if (col != numCols) {
10027     return;
10028   }
10029 
10030   char_start = GetTextSelectCharOffset (pt, dlg, item, row, col);
10031   if (char_start < 0) {
10032     /* no updates unless mouse is in text area */
10033     return;
10034   }
10035 
10036   if (item < dlg->text_select_item_anchor) {
10037     /* mouse is before anchor */
10038     dlg->text_select_item_start = item;
10039     dlg->text_select_row_start = row;
10040     dlg->text_select_char_start = char_start;
10041     dlg->text_select_item_stop = dlg->text_select_item_anchor;
10042     dlg->text_select_row_stop = dlg->text_select_row_anchor;
10043     dlg->text_select_char_stop = dlg->text_select_char_anchor;
10044   } else if (item == dlg->text_select_item_anchor) {
10045     /* start and stop in the anchor item */
10046     dlg->text_select_item_start = item;
10047     dlg->text_select_item_stop = item;
10048     if (row < dlg->text_select_row_anchor) {
10049       /* mouse is before anchor */
10050       dlg->text_select_row_start = row;
10051       dlg->text_select_char_start = char_start;
10052       dlg->text_select_row_stop = dlg->text_select_row_anchor;
10053       dlg->text_select_char_stop = dlg->text_select_char_anchor;
10054     } else if (row == dlg->text_select_row_anchor) {
10055       /* start and stop in the anchor row */
10056       dlg->text_select_row_start = row;
10057       dlg->text_select_row_stop = row;
10058       if (char_start <= dlg->text_select_char_anchor) {
10059         /* mouse is before anchor */
10060         dlg->text_select_char_start = char_start;
10061         dlg->text_select_char_stop = dlg->text_select_char_anchor;
10062       } else {
10063         dlg->text_select_char_start = dlg->text_select_char_anchor;
10064         dlg->text_select_char_stop = char_start;
10065       }
10066     }
10067   } else {
10068     /* mouse is after anchor */
10069     dlg->text_select_item_start = dlg->text_select_item_anchor;
10070     dlg->text_select_row_start = dlg->text_select_row_anchor;
10071     dlg->text_select_char_start = dlg->text_select_char_anchor;
10072     dlg->text_select_item_stop = item;
10073     dlg->text_select_row_stop = row;
10074     dlg->text_select_char_stop = char_start;
10075   }
10076   InvalDocRows (dlg->doc, 0, 0, 0);
10077 }
10078 
DragClickableList(DoC d,PoinT pt)10079 static void DragClickableList (DoC d, PoinT pt)
10080 {
10081   Int2            item, row, col, numCols;
10082 
10083   ClickableListPtr dlg;
10084 
10085   dlg = GetObjectExtra (d);
10086   if (dlg != NULL) {
10087     MapDocPoint (d, pt, &item, &row, &col, NULL);
10088     GetItemParams4 (d, item, NULL, NULL, &numCols, NULL, NULL);
10089     if (col == numCols) {
10090       UpdateClickableListTextSelection (dlg, item, row, col, pt);
10091     }
10092   }
10093 }
10094 
10095 
InvalBorder(DoC d,Int2 item)10096 static void InvalBorder (DoC d, Int2 item)
10097 
10098 {
10099   Int2  bottom;
10100   RecT  r;
10101   Int2  top;
10102 
10103   ObjectRect (d, &r);
10104   InsetRect (&r, 4, 4);
10105   if (ItemIsVisible (d, item, &top, &bottom, NULL)) {
10106     r.top = top;
10107     r.bottom = bottom;
10108     r.right = r.left + 4;
10109     InsetRect (&r, -1, -1);
10110     InvalRect (&r);
10111   }
10112 }
10113 
ActOnClickableList(ValNodePtr list_list,Int2 item)10114 static void ActOnClickableList (ValNodePtr list_list, Int2 item)
10115 {
10116   ClickableItemPtr cip;
10117 
10118   cip = GetSelectedClickableList (list_list, item);
10119   if (cip != NULL && cip->callback_func != NULL)
10120   {
10121     (cip->callback_func) (cip->item_list, cip->callback_data);
10122   }
10123 }
10124 
10125 
PopulateClickableItemList(DialoG d,ClickableItemPtr cip)10126 static void PopulateClickableItemList (DialoG d, ClickableItemPtr cip)
10127 {
10128   ValNodePtr        list = NULL;
10129 
10130   if (d == NULL) return;
10131   if (cip != NULL)
10132   {
10133     ValNodeLink (&list, ClickableItemObjectListCopy (cip->item_list));
10134   }
10135   PointerToDialog (d, list);
10136 
10137 }
10138 
10139 
ReleaseClickableList(DoC d,PoinT pt)10140 static void ReleaseClickableList (DoC d, PoinT pt)
10141 
10142 {
10143   Int2           item;
10144   Int2           old;
10145   Int2           row, col;
10146   ClickableListPtr dlg;
10147 
10148   dlg = GetObjectExtra (d);
10149   if (dlg != NULL) {
10150     ResetClip ();
10151     MapDocPoint (d, pt, &item, &row, &col, NULL);
10152     /* update text selection */
10153     UpdateClickableListTextSelection (dlg, item, row, col, pt);
10154 
10155     if (item > 0 && row > 0) {
10156 
10157       if (item == dlg->clicked) {
10158         old = dlg->selected;
10159         dlg->selected = item;
10160         if (old != item) {
10161           if (old == 0) {
10162             UpdateDocument (d, item, item);
10163           } else {
10164             UpdateDocument (d, old, old);
10165             UpdateDocument (d, item, item);
10166           }
10167           Update ();
10168         }
10169       }
10170     } else if (dlg->clicked == 0) {
10171       if (dlg->selected != 0) {
10172         old = dlg->selected;
10173         dlg->selected = 0;
10174         InvalBorder (d, old);
10175       }
10176       Update ();
10177     }
10178     if (dlg->selected > 0 && dlg->dblClick)
10179     {
10180       ActOnClickableList (dlg->list_list, dlg->selected);
10181     }
10182     else if (dlg->selected > 0)
10183     {
10184       dlg->item_selected = 0;
10185       if (!dlg->display_chosen) {
10186         PopulateClickableItemList (dlg->clickable_item_list,
10187                                   GetSelectedClickableList (dlg->list_list,
10188                                                             dlg->selected));
10189         UpdateChosenCount (dlg->dialog);
10190       }
10191     }
10192   }
10193 }
10194 
10195 
DrawTextSelection(ClickableListPtr dlg,Int2 item,RectPtr r)10196 static void DrawTextSelection (ClickableListPtr dlg, Int2 item, RectPtr r)
10197 {
10198   Int2 lineHeight, numRows, numCols;
10199   Int2 last_right;
10200   Int2 left_start;
10201   Int4 top, line_y;
10202   CharPtr txt;
10203 
10204   if (dlg == NULL || r == NULL
10205       || item < dlg->text_select_item_start
10206       || item > dlg->text_select_item_stop) {
10207     return;
10208   }
10209 
10210   if (dlg->text_select_item_start == dlg->text_select_item_stop
10211       && dlg->text_select_row_start == dlg->text_select_row_stop
10212       && dlg->text_select_char_start == dlg->text_select_char_stop) {
10213     /* if we've only selected one char, and it's blank, don't draw it. */
10214     txt = GetSelectedClickableListText (dlg->dialog);
10215     if (StringHasNoText (txt)) {
10216       MemFree (txt);
10217       return;
10218     }
10219     MemFree (txt);
10220   }
10221 
10222   GetItemParams4 (dlg->doc, item, &top, &numRows, &numCols, &lineHeight, NULL);
10223 
10224   /* calculate missing rows from end first */
10225   if (dlg->text_select_item_stop == item) {
10226     numRows = dlg->text_select_row_stop;
10227     last_right = PanelOffsetFromCharOffset (dlg, item, dlg->text_select_char_stop + 1);
10228   } else {
10229     last_right = r->right;
10230   }
10231 
10232   if (dlg->text_select_item_start == item) {
10233     left_start = PanelOffsetFromCharOffset (dlg, item, dlg->text_select_char_start);
10234     line_y = r->top + (dlg->text_select_row_start) * lineHeight - 1;
10235     numRows -= dlg->text_select_row_start - 1;
10236   } else {
10237     left_start = PanelOffsetFromCharOffset (dlg, item, 0);
10238     line_y = r->top + lineHeight - 1;
10239   }
10240 
10241   while (numRows > 1) {
10242     MoveTo (left_start, line_y);
10243     left_start = PanelOffsetFromCharOffset (dlg, item, 0);
10244     LineTo (r->right, line_y);
10245     line_y += lineHeight;
10246     numRows--;
10247   }
10248   MoveTo (left_start, line_y);
10249   LineTo (last_right, line_y);
10250 
10251 }
10252 
DrawClickableList(DoC d,RectPtr r,Int2 item,Int2 firstLine)10253 static void DrawClickableList (DoC d, RectPtr r, Int2 item, Int2 firstLine)
10254 
10255 {
10256   ClickableListPtr dlg;
10257   RecT             rct;
10258   ClickableItemPtr cip;
10259   Int4             level_offset;
10260 
10261   dlg = (ClickableListPtr) GetObjectExtra (d);
10262   if (dlg != NULL && r != NULL && item > 0 && firstLine == 0) {
10263     rct = *r;
10264 
10265     cip = GetSelectedClickableList (dlg->list_list, item);
10266     if (cip != NULL)
10267     {
10268       level_offset = cip->level * 16;
10269       rct.left += level_offset;
10270       rct.right += level_offset;
10271     }
10272 
10273     /* draw text selection */
10274     DrawTextSelection (dlg, item, &rct);
10275 
10276     /* draw selection */
10277     if (item == dlg->selected) {
10278       rct.right = rct.left + 4;
10279       PaintRect (&rct);
10280     }
10281 
10282     /* draw chosen checkboxes */
10283     rct.left += 5;
10284     rct.right = rct.left + 10;
10285     rct.bottom = rct.top + (rct.right - rct.left);
10286     FrameRect (&rct);
10287 
10288     if (cip != NULL && cip->chosen) {
10289       MoveTo (rct.left, rct.top);
10290       LineTo (rct.right - 1, rct.bottom - 1);
10291       MoveTo (rct.left, rct.bottom - 1);
10292       LineTo (rct.right - 1, rct.top);
10293     }
10294 
10295     /* draw open/closed checkboxes */
10296     if (cip!= NULL && cip->subcategories != NULL)
10297     {
10298       rct.left += 10;
10299       rct.right = rct.left + 10;
10300       rct.bottom = rct.top + (rct.right - rct.left);
10301       FrameRect (&rct);
10302       MoveTo (rct.left, (rct.top + rct.bottom) / 2);
10303       LineTo (rct.right - 1, (rct.top + rct.bottom) / 2);
10304       if (!cip->expanded)
10305       {
10306         MoveTo ((rct.left + rct.right) / 2, rct.top);
10307         LineTo ((rct.left + rct.right) / 2, rct.bottom - 1);
10308       }
10309     }
10310 
10311   }
10312 }
10313 
10314 
10315 
DrawClickableListItem(DoC d,RectPtr r,Int2 item,Int2 firstLine)10316 static void DrawClickableListItem (DoC d, RectPtr r, Int2 item, Int2 firstLine)
10317 
10318 {
10319   ClickableListPtr dlg;
10320   RecT             rct;
10321 
10322   dlg = (ClickableListPtr) GetObjectExtra (d);
10323   if (dlg != NULL && r != NULL && item > 0 && firstLine == 0) {
10324     rct = *r;
10325 
10326     /* draw selection */
10327     if (item == dlg->item_selected) {
10328       rct = *r;
10329       rct.right = rct.left + 4;
10330       PaintRect (&rct);
10331     }
10332   }
10333 }
10334 
10335 
ClickClickableListItem(DoC d,PoinT pt)10336 static void ClickClickableListItem (DoC d, PoinT pt)
10337 
10338 {
10339   Int2             item, last_selected, numItems;
10340   Int2             row;
10341   ClickableListPtr dlg;
10342   ClickableItemPtr cip;
10343   ValNodePtr       vnp;
10344 
10345   dlg = GetObjectExtra (d);
10346   if (dlg != NULL) {
10347     MapDocPoint (d, pt, &item, &row, NULL, NULL);
10348     if (item > 0 && row > 0) {
10349       cip = GetSelectedClickableList (dlg->list_list, dlg->selected);
10350       if (cip != NULL && cip->item_list != NULL)
10351       {
10352         vnp = cip->item_list;
10353 
10354         last_selected = dlg->item_selected;
10355         dlg->item_selected = item;
10356 
10357         if (item != last_selected)
10358         {
10359           GetDocParams (d, &numItems, NULL);
10360           UpdateDocument (d, 0, numItems);
10361         }
10362 
10363         /* find item in list */
10364         while (item > 1 && vnp != NULL)
10365         {
10366           vnp = vnp->next;
10367           item--;
10368         }
10369 
10370         if (dblClick)
10371         {
10372           if (dlg->item_double_click_callback != NULL) {
10373             (dlg->item_double_click_callback) (vnp, dlg->item_click_callback_data);
10374           }
10375         } else {
10376           if (dlg->item_single_click_callback != NULL) {
10377             (dlg->item_single_click_callback) (vnp, dlg->item_click_callback_data);
10378           }
10379         }
10380       }
10381     }
10382   }
10383 }
10384 
10385 
ClickableListToDialog(DialoG d,Pointer userdata)10386 static void ClickableListToDialog (DialoG d, Pointer userdata)
10387 {
10388   ClickableListPtr dlg;
10389 
10390   dlg = (ClickableListPtr) GetObjectExtra (d);
10391   if (dlg == NULL)
10392   {
10393     return;
10394   }
10395 
10396   dlg->list_list = (ValNodePtr) userdata;
10397 
10398   PopulateClickableList (dlg, dlg->list_list);
10399   if (dlg->list_list != NULL) {
10400     dlg->selected = 1;
10401     dlg->item_selected = 0;
10402     if (dlg->display_chosen)  {
10403       PointerToDialog (dlg->clickable_item_list, GetChosenItemsList (dlg->list_list));
10404       UpdateChosenCount (dlg->dialog);
10405     } else {
10406       PopulateClickableItemList (dlg->clickable_item_list,
10407                                 GetSelectedClickableList (dlg->list_list,
10408                                                           dlg->selected));
10409     }
10410   } else {
10411     PointerToDialog (dlg->clickable_item_list, NULL);
10412   }
10413 }
10414 
FindClickableText(ButtoN b)10415 static void FindClickableText (ButtoN b)
10416 {
10417   ClickableListPtr dlg;
10418   CharPtr          find_txt;
10419 
10420   dlg = (ClickableListPtr) GetObjectExtra (b);
10421   if (dlg == NULL)
10422   {
10423     return;
10424   }
10425 
10426   find_txt = SaveStringFromText (dlg->find_txt);
10427   ScrollToNextClickableTextDescription (find_txt, dlg->dialog);
10428   find_txt = MemFree (find_txt);
10429 }
10430 
10431 
FindPreviousClickableText(ButtoN b)10432 static void FindPreviousClickableText (ButtoN b)
10433 {
10434   ClickableListPtr dlg;
10435   CharPtr          find_txt;
10436 
10437   dlg = (ClickableListPtr) GetObjectExtra (b);
10438   if (dlg == NULL)
10439   {
10440     return;
10441   }
10442 
10443   find_txt = SaveStringFromText (dlg->find_txt);
10444   ScrollToPreviousClickableTextDescription (find_txt, dlg->dialog);
10445   find_txt = MemFree (find_txt);
10446 }
10447 
10448 
ClickableListCopyToClipboard(DialoG d)10449 static void ClickableListCopyToClipboard (DialoG d)
10450 {
10451   ClickableListPtr dlg;
10452   CharPtr          txt;
10453 
10454   dlg = (ClickableListPtr) GetObjectExtra (d);
10455 
10456   if (dlg == NULL) return;
10457 
10458   txt = GetSelectedClickableListText (d);
10459   Nlm_StringToClipboard (txt);
10460   txt = MemFree (txt);
10461 }
10462 
ClickableListMessage(DialoG d,Int2 mssg)10463 static void ClickableListMessage (DialoG d, Int2 mssg)
10464 
10465 {
10466   ClickableListPtr dlg;
10467 
10468   dlg = (ClickableListPtr) GetObjectExtra (d);
10469   if (dlg != NULL) {
10470     if (mssg == VIB_MSG_COPY) {
10471       ClickableListCopyToClipboard(d);
10472     }
10473   }
10474 }
10475 
ClickableListOnKey(SlatE s,Char ch)10476 static void ClickableListOnKey (SlatE s, Char ch)
10477 {
10478   DoC              d;
10479   ClickableListPtr clp;
10480 #ifdef WIN_MSWIN
10481   Int2             first_shown;
10482   Int4             offset;
10483   BaR              sb;
10484 #endif
10485 
10486   if ( (int) ch == 0 ) return;
10487 
10488   d = (DoC) s;
10489   clp = (ClickableListPtr) GetObjectExtra (d);
10490 
10491   CaptureSlateFocus (s);
10492   /* later, handle control key combos */
10493 #ifdef WIN_MSWIN
10494   if (ch == 3)
10495   {
10496     ClickableListCopyToClipboard (clp->dialog);
10497   }
10498   else if (ch == 11)
10499   {
10500     /* PageUp key pressed */
10501     if (GetScrlParams4 (d, &offset, &first_shown, NULL) && first_shown > 0)
10502     {
10503       sb = GetSlateVScrollBar (s);
10504       Nlm_Scroll (sb, SCROLL_PAGEUP);
10505     }
10506   }
10507   else if (ch == 12)
10508   {
10509     /* PageDown key pressed */
10510     if (GetScrlParams4 (d, &offset, &first_shown, NULL))
10511     {
10512       sb = GetSlateVScrollBar (s);
10513       Nlm_Scroll (sb, SCROLL_PAGEDN);
10514     }
10515   }
10516   else if (ch == 30)
10517   {
10518     /* Up Arrow key pressed */
10519     if (GetScrlParams4 (d, &offset, &first_shown, NULL) && first_shown > 0)
10520     {
10521       GetItemParams4 (d, first_shown - 1, &offset, NULL, NULL, NULL, NULL);
10522       SetScrlParams4 (d, offset);
10523     }
10524   }
10525   else if (ch == 31)
10526   {
10527     /* Down Arrow key pressed */
10528     if (GetScrlParams4 (d, &offset, &first_shown, NULL)) {
10529       sb = GetSlateVScrollBar (s);
10530       if (offset < GetBarMax (sb))
10531       {
10532         GetItemParams4 (d, first_shown + 1, &offset, NULL, NULL, NULL, NULL);
10533         SetScrlParams4 (d, offset);
10534       }
10535     }
10536   }
10537 #endif
10538 }
10539 
10540 
10541 extern DialoG
CreateClickableListDialogExExEx(GrouP h,CharPtr label1,CharPtr label2,CharPtr help1,CharPtr help2,ClickableCallback item_single_click_callback,ClickableCallback item_double_click_callback,Pointer item_click_callback_data,GetClickableItemText get_item_text,Int4 num_item_text_columns,Int4 left_width,Int4 right_width,Boolean horizontal,Boolean show_find,Boolean display_chosen)10542 CreateClickableListDialogExExEx
10543 (GrouP h,
10544  CharPtr label1,
10545  CharPtr label2,
10546  CharPtr help1,
10547  CharPtr help2,
10548  ClickableCallback item_single_click_callback,
10549  ClickableCallback item_double_click_callback,
10550  Pointer         item_click_callback_data,
10551  GetClickableItemText get_item_text,
10552  Int4            num_item_text_columns,
10553  Int4            left_width,
10554  Int4            right_width,
10555  Boolean         horizontal,
10556  Boolean         show_find,
10557  Boolean         display_chosen)
10558 {
10559   GrouP p, pnl_grp, find_grp = NULL;
10560   ClickableListPtr dlg;
10561   RecT             r;
10562   ButtoN           b;
10563 
10564   dlg = (ClickableListPtr) MemNew (sizeof (ClickableListData));
10565   if (dlg == NULL)
10566   {
10567     return NULL;
10568   }
10569   p = HiddenGroup (h, -1, 0, NULL);
10570   SetObjectExtra (p, dlg, CleanupClickableListDialog);
10571   SetGroupSpacing (p, 10, 10);
10572 
10573   dlg->dialog = (DialoG) p;
10574   dlg->todialog = ClickableListToDialog;
10575   dlg->fromdialog = NULL;
10576   dlg->dialogmessage = ClickableListMessage;
10577   dlg->testdialog = NULL;
10578 
10579   dlg->item_single_click_callback = item_single_click_callback;
10580   dlg->item_double_click_callback = item_double_click_callback;
10581   dlg->item_click_callback_data = item_click_callback_data;
10582 
10583   dlg->get_item_text = get_item_text;
10584 
10585   dlg->display_chosen = display_chosen;
10586 
10587   if (horizontal) {
10588     pnl_grp = HiddenGroup (p, 2, 0, NULL);
10589 
10590     if (label1 || label2) {
10591       dlg->title1 = StaticPrompt (pnl_grp, label1, left_width, popupMenuHeight, programFont, 'c');
10592       dlg->title2 = StaticPrompt (pnl_grp, label2, right_width, popupMenuHeight, programFont, 'c');
10593     }
10594     dlg->doc = DocumentPanel (pnl_grp, left_width, stdLineHeight * 20);
10595     dlg->clickable_item_list = ClickableItemListDialog (pnl_grp, right_width,
10596                                                         get_item_text, num_item_text_columns,
10597                                                         item_single_click_callback,
10598                                                         item_double_click_callback,
10599                                                         item_click_callback_data);
10600     if (help1 || help2) {
10601       dlg->help1 = StaticPrompt (pnl_grp, help1, left_width, popupMenuHeight, programFont, 'c');
10602       dlg->help2 = StaticPrompt (pnl_grp, help2, right_width, popupMenuHeight, programFont, 'c');
10603     }
10604   } else {
10605     pnl_grp = HiddenGroup (p, -1, 0, NULL);
10606     dlg->title1 = StaticPrompt (pnl_grp, label1, left_width, popupMenuHeight, programFont, 'c');
10607     dlg->doc = DocumentPanel (pnl_grp, left_width, stdLineHeight * 20);
10608     if (help1 || help2) {
10609       dlg->help1 = StaticPrompt (pnl_grp, help1, left_width, popupMenuHeight, programFont, 'c');
10610     }
10611     dlg->title2 = StaticPrompt (pnl_grp, label2, right_width, popupMenuHeight, programFont, 'c');
10612     dlg->clickable_item_list = ClickableItemListDialog (pnl_grp, right_width,
10613                                                         get_item_text, num_item_text_columns,
10614                                                         item_single_click_callback,
10615                                                         item_double_click_callback,
10616                                                         item_click_callback_data);
10617     if (help1 || help2) {
10618       dlg->help2 = StaticPrompt (pnl_grp, help2, right_width, popupMenuHeight, programFont, 'c');
10619     }
10620     AlignObjects (ALIGN_CENTER, (HANDLE) dlg->title1, (HANDLE) dlg->doc, (HANDLE) dlg->title2, (HANDLE) dlg->clickable_item_list,
10621                                 (HANDLE) (dlg->help1 == NULL ? dlg->help2 : dlg->help1), (HANDLE) (dlg->help1 == NULL ? NULL : dlg->help2), NULL);
10622   }
10623 
10624   SetObjectExtra (dlg->doc, dlg, NULL);
10625   SetDocAutoAdjust (dlg->doc, FALSE);
10626   SetDocProcs (dlg->doc, ClickList, DragClickableList, ReleaseClickableList, NULL);
10627   SetDocShade (dlg->doc, DrawClickableList, NULL, NULL, NULL);
10628 
10629   SetSlateChar ((SlatE) dlg->doc, ClickableListOnKey);
10630 
10631   /* adjust column width for discrepancy list */
10632   ObjectRect (dlg->doc, &r);
10633   InsetRect (&r, 4, 4);
10634   clickableColFmt[1].pixWidth = r.right - r.left - clickableColFmt[0].pixWidth;
10635 
10636   dlg->chosen_count = StaticPrompt (p, "0 items checked", 20 * stdCharWidth, dialogTextHeight, programFont, 'l');
10637   if (!dlg->display_chosen) {
10638     Hide (dlg->chosen_count);
10639   }
10640   if (show_find) {
10641     find_grp = HiddenGroup (p, 4, 0, NULL);
10642     SetGroupSpacing (find_grp, 10, 10);
10643     StaticPrompt (find_grp, "Find Text", 0, popupMenuHeight, programFont, 'l');
10644     dlg->find_txt = DialogText (find_grp, "", 20, NULL);
10645     b = PushButton (find_grp, "<<", FindPreviousClickableText);
10646     SetObjectExtra (b, dlg, NULL);
10647     b = PushButton (find_grp, ">>", FindClickableText);
10648     SetObjectExtra (b, dlg, NULL);
10649   }
10650 
10651   AlignObjects (ALIGN_CENTER, (HANDLE) pnl_grp, (HANDLE) dlg->chosen_count, (HANDLE) find_grp, NULL);
10652   return (DialoG) p;
10653 }
10654 
10655 
10656 extern DialoG
CreateClickableListDialogExEx(GrouP h,CharPtr label1,CharPtr label2,CharPtr help1,CharPtr help2,ClickableCallback item_single_click_callback,ClickableCallback item_double_click_callback,Pointer item_click_callback_data,GetClickableItemText get_item_text,Int4 left_width,Int4 right_width,Boolean horizontal,Boolean show_find,Boolean display_chosen)10657 CreateClickableListDialogExEx
10658 (GrouP h,
10659  CharPtr label1,
10660  CharPtr label2,
10661  CharPtr help1,
10662  CharPtr help2,
10663  ClickableCallback item_single_click_callback,
10664  ClickableCallback item_double_click_callback,
10665  Pointer         item_click_callback_data,
10666  GetClickableItemText get_item_text,
10667  Int4            left_width,
10668  Int4            right_width,
10669  Boolean         horizontal,
10670  Boolean         show_find,
10671  Boolean         display_chosen)
10672 {
10673   return CreateClickableListDialogExExEx (h, label1, label2, help1, help2,
10674                                           item_single_click_callback,
10675                                           item_double_click_callback,
10676                                           item_click_callback_data,
10677                                           get_item_text, 4,
10678                                           left_width,
10679                                           right_width,
10680                                           horizontal,
10681                                           show_find,
10682                                           display_chosen);
10683 }
10684 
10685 
10686 extern DialoG
CreateClickableListDialogEx(GrouP h,CharPtr label1,CharPtr label2,CharPtr help1,CharPtr help2,ClickableCallback item_single_click_callback,ClickableCallback item_double_click_callback,Pointer item_click_callback_data,GetClickableItemText get_item_text,Int4 left_width,Int4 right_width,Boolean horizontal,Boolean show_find)10687 CreateClickableListDialogEx
10688 (GrouP h,
10689  CharPtr label1,
10690  CharPtr label2,
10691  CharPtr help1,
10692  CharPtr help2,
10693  ClickableCallback item_single_click_callback,
10694  ClickableCallback item_double_click_callback,
10695  Pointer         item_click_callback_data,
10696  GetClickableItemText get_item_text,
10697  Int4            left_width,
10698  Int4            right_width,
10699  Boolean         horizontal,
10700  Boolean         show_find)
10701 {
10702   return CreateClickableListDialogExEx (h, label1, label2, help1, help2,
10703                                         item_single_click_callback, item_double_click_callback,
10704                                         item_click_callback_data,
10705                                         get_item_text,
10706                                         left_width,
10707                                         right_width,
10708                                         horizontal,
10709                                         show_find,
10710                                         FALSE);
10711 }
10712 
10713 
SetClickableListDialogTitles(DialoG d,CharPtr title1,CharPtr title2,CharPtr help1,CharPtr help2)10714 extern void SetClickableListDialogTitles (DialoG d, CharPtr title1, CharPtr title2, CharPtr help1, CharPtr help2)
10715 {
10716   ClickableListPtr dlg;
10717 
10718   dlg = (ClickableListPtr) GetObjectExtra (d);
10719   if (dlg == NULL)
10720   {
10721     return;
10722   }
10723   SafeSetTitle (dlg->title1, title1);
10724   SafeSetTitle (dlg->title2, title2);
10725   SafeSetTitle (dlg->help1, help1);
10726   SafeSetTitle (dlg->help2, help2);
10727 }
10728 
10729 
SetClickableListDisplayChosen(DialoG d,Boolean set)10730 extern void SetClickableListDisplayChosen (DialoG d, Boolean set)
10731 {
10732   ClickableListPtr dlg;
10733 
10734   dlg = (ClickableListPtr) GetObjectExtra (d);
10735   if (dlg == NULL)
10736   {
10737     return;
10738   }
10739   dlg->display_chosen = set;
10740   if (dlg->display_chosen)  {
10741     PointerToDialog (dlg->clickable_item_list, GetChosenItemsList (dlg->list_list));
10742     UpdateChosenCount (d);
10743     Show (dlg->chosen_count);
10744   } else {
10745     PopulateClickableItemList (dlg->clickable_item_list,
10746                               GetSelectedClickableList (dlg->list_list,
10747                                                         dlg->selected));
10748     Hide (dlg->chosen_count);
10749   }
10750 }
10751 
10752 
10753 extern DialoG
CreateClickableListDialog(GrouP h,CharPtr label1,CharPtr label2,ClickableCallback item_single_click_callback,ClickableCallback item_double_click_callback,Pointer item_click_callback_data,GetClickableItemText get_item_text)10754 CreateClickableListDialog
10755 (GrouP h,
10756  CharPtr label1,
10757  CharPtr label2,
10758  ClickableCallback item_single_click_callback,
10759  ClickableCallback item_double_click_callback,
10760  Pointer         item_click_callback_data,
10761  GetClickableItemText get_item_text)
10762 {
10763   return CreateClickableListDialogEx (h, label1, label2, NULL, NULL,
10764                                       item_single_click_callback,
10765                                       item_double_click_callback,
10766                                       item_click_callback_data,
10767                                       get_item_text,
10768                                       stdCharWidth * 30,
10769                                       stdCharWidth * 30 + 5,
10770                                       TRUE, TRUE);
10771 }
10772 
10773 
CountExpandedSublevels(ValNodePtr subcategories)10774 static Int4 CountExpandedSublevels (ValNodePtr subcategories)
10775 {
10776   ValNodePtr vnp;
10777   Int4       num = 0;
10778   ClickableItemPtr cip;
10779 
10780   for (vnp = subcategories; vnp != NULL; vnp = vnp->next) {
10781     cip = (ClickableItemPtr) vnp->data.ptrvalue;
10782     if (cip != NULL) {
10783       num++;
10784       if (cip->expanded && cip->subcategories != NULL) {
10785         num += CountExpandedSublevels(cip->subcategories);
10786       }
10787     }
10788   }
10789   return num;
10790 }
10791 
10792 
10793 /* First, need to locate items that have description that contains txt.
10794  * Then need to make sure that they are visible.
10795  * Then need to figure out how to scroll to them.
10796  */
FindInClickableItemDescriptions(CharPtr txt,ValNodePtr clickable_item_list,ValNodePtr PNTR row_list,Int4Ptr row_offset)10797 static Boolean FindInClickableItemDescriptions (CharPtr txt, ValNodePtr clickable_item_list, ValNodePtr PNTR row_list, Int4Ptr row_offset)
10798 {
10799   ValNodePtr       vnp;
10800   ClickableItemPtr cip;
10801   Boolean          found = FALSE;
10802   Int4             lower_levels;
10803 
10804   if (StringHasNoText (txt) || clickable_item_list == NULL || row_list == NULL || row_offset == NULL) return FALSE;
10805 
10806   vnp = clickable_item_list;
10807   while (vnp != NULL) {
10808     (*row_offset)++;
10809     cip = (ClickableItemPtr) vnp->data.ptrvalue;
10810     if (StringStr (cip->description, txt) != NULL) {
10811       ValNodeAddInt (row_list, 0, *row_offset);
10812       found = TRUE;
10813     }
10814     lower_levels = *row_offset;
10815     if (cip->subcategories != NULL) {
10816       if (FindInClickableItemDescriptions (txt, cip->subcategories, row_list, &lower_levels)) {
10817         cip->expanded = TRUE;
10818         found = TRUE;
10819       }
10820       if (cip->expanded) {
10821         (*row_offset) += CountExpandedSublevels (cip->subcategories);
10822       }
10823     }
10824     vnp = vnp->next;
10825   }
10826 
10827   return found;
10828 }
10829 
10830 
ScrollToNextClickableTextDescription(CharPtr txt,DialoG d)10831 extern void ScrollToNextClickableTextDescription (CharPtr txt, DialoG d)
10832 {
10833   ClickableListPtr dlg;
10834   ValNodePtr       found_list = NULL, vnp;
10835   Int4             row_offset = 0, startsAt;
10836   Int2             numRows, numCols, lineHeight;
10837 
10838   dlg = (ClickableListPtr) GetObjectExtra (d);
10839   if (dlg == NULL)
10840   {
10841     return;
10842   }
10843 
10844   if (!FindInClickableItemDescriptions (txt, dlg->list_list, &found_list, &row_offset)
10845       || found_list == NULL) {
10846     Message (MSG_OK, "Text not found!");
10847     return;
10848   }
10849 
10850   /* find first found txt after current selection */
10851   vnp = found_list;
10852   while (vnp != NULL && vnp->data.intvalue <= dlg->selected) {
10853     vnp = vnp->next;
10854   }
10855   if (vnp == NULL) {
10856    row_offset = found_list->data.intvalue;
10857   } else {
10858     row_offset = vnp->data.intvalue;
10859   }
10860 
10861   dlg->selected = row_offset;
10862   PopulateClickableList (dlg, dlg->list_list);
10863   SetDocAutoAdjust (dlg->doc, TRUE);
10864   UpdateDocument (dlg->doc, 0, 0);
10865   SetDocAutoAdjust (dlg->doc, FALSE);
10866   dlg->item_selected = 0;
10867   PopulateClickableItemList (dlg->clickable_item_list,
10868                              GetSelectedClickableList (dlg->list_list,
10869                                                        dlg->selected));
10870 
10871   GetItemParams4 (dlg->doc, row_offset, &startsAt, &numRows,
10872                   &numCols, &lineHeight, NULL);
10873   SetScrlParams4 (dlg->doc, startsAt);
10874 }
10875 
10876 
ScrollToPreviousClickableTextDescription(CharPtr txt,DialoG d)10877 extern void ScrollToPreviousClickableTextDescription (CharPtr txt, DialoG d)
10878 {
10879   ClickableListPtr dlg;
10880   ValNodePtr       found_list = NULL, vnp, vnp_prev = NULL;
10881   Int4             row_offset = 0, startsAt;
10882   Int2             numRows, numCols, lineHeight;
10883 
10884   dlg = (ClickableListPtr) GetObjectExtra (d);
10885   if (dlg == NULL)
10886   {
10887     return;
10888   }
10889 
10890   if (!FindInClickableItemDescriptions (txt, dlg->list_list, &found_list, &row_offset)
10891       || found_list == NULL) {
10892     Message (MSG_OK, "Text not found!");
10893     return;
10894   }
10895 
10896   /* find first found txt before current selection */
10897   vnp = found_list;
10898   while (vnp != NULL && vnp->data.intvalue < dlg->selected) {
10899     vnp_prev = vnp;
10900     vnp = vnp->next;
10901   }
10902   if (vnp_prev == NULL) {
10903     /* use last item in list */
10904     vnp = found_list;
10905     while (vnp != NULL && vnp->next != NULL) {
10906       vnp = vnp->next;
10907     }
10908     if (vnp != NULL) {
10909       row_offset = vnp->data.intvalue;
10910     }
10911   } else {
10912     row_offset = vnp_prev->data.intvalue;
10913   }
10914 
10915   dlg->selected = row_offset;
10916   PopulateClickableList (dlg, dlg->list_list);
10917   SetDocAutoAdjust (dlg->doc, TRUE);
10918   UpdateDocument (dlg->doc, 0, 0);
10919   SetDocAutoAdjust (dlg->doc, FALSE);
10920   dlg->item_selected = 0;
10921   PopulateClickableItemList (dlg->clickable_item_list,
10922                              GetSelectedClickableList (dlg->list_list,
10923                                                        dlg->selected));
10924 
10925   GetItemParams4 (dlg->doc, row_offset, &startsAt, &numRows,
10926                   &numCols, &lineHeight, NULL);
10927   SetScrlParams4 (dlg->doc, startsAt);
10928 }
10929 
10930 
GetClickableTextFromItemList(ValNodePtr item_list,CharPtr separator)10931 static CharPtr GetClickableTextFromItemList (ValNodePtr item_list, CharPtr separator)
10932 {
10933   Int4 text_len = 1;
10934   ValNodePtr vnp;
10935   CharPtr    txt;
10936 
10937   for (vnp = item_list; vnp != NULL; vnp = vnp->next) {
10938     text_len += StringLen (vnp->data.ptrvalue) + StringLen (separator);
10939   }
10940 
10941   txt = (CharPtr) MemNew (sizeof(Char) * text_len);
10942   for (vnp = item_list; vnp != NULL; vnp = vnp->next) {
10943     StringCat (txt, vnp->data.ptrvalue);
10944     if (vnp->next != NULL) {
10945       StringCat (txt, separator);
10946     }
10947   }
10948   return txt;
10949 }
10950 
10951 
10952 static CharPtr
GetFragmentFromDocRow(DoC doc,Int2 item,Int2 col,Int2 row,Int2 char_start,Int2 char_stop)10953 GetFragmentFromDocRow
10954 (DoC  doc,
10955  Int2 item,
10956  Int2 col,
10957  Int2 row,
10958  Int2 char_start, Int2 char_stop)
10959 {
10960   CharPtr txt = NULL, cp_txt;
10961   Int4    len;
10962 
10963   txt = GetDocText (doc, item, row, col);
10964 
10965   if (char_start == 0 && char_stop < 0) {
10966     /* take all of row */
10967     return txt;
10968   } else {
10969     len = StringLen (txt);
10970     if (char_stop >= len) {
10971       /* selection was drawn beyond length of text */
10972       char_stop = len - 1;
10973     } else if (char_stop < 0) {
10974       /* take all of row */
10975       char_stop = len - 1;
10976     }
10977     if (char_start >= len) {
10978       /* do nothing - selection is not within text */
10979       txt = MemFree (txt);
10980     } else {
10981       cp_txt = (CharPtr) MemNew (sizeof (Char) * (2 + char_stop - char_start));
10982       StringNCpy (cp_txt, txt + char_start, 1 + char_stop - char_start);
10983       cp_txt[1 + char_stop - char_start] = 0;
10984       txt = MemFree (txt);
10985       txt = cp_txt;
10986     }
10987   }
10988   return txt;
10989 }
10990 
10991 
10992 static CharPtr
GetFragmentsFromDocCol(DoC doc,Int2 item,Int2 col,Int2 row_start,Int2 row_stop,Int2 char_start,Int2 char_stop)10993 GetFragmentsFromDocCol
10994 (DoC  doc,
10995  Int2 item,
10996  Int2 col,
10997  Int2 row_start, Int2 row_stop,
10998  Int2 char_start, Int2 char_stop)
10999 {
11000   Int2       row;
11001   CharPtr    txt;
11002   ValNodePtr fragments = NULL;
11003 
11004   if (row_start == row_stop) {
11005     txt = GetFragmentFromDocRow (doc, item, col, row_start, char_start, char_stop);
11006     if (StringHasNoText (txt)) {
11007       txt = MemFree (txt);
11008     } else {
11009       ValNodeAddPointer (&fragments, 0, txt);
11010     }
11011   } else {
11012     txt = GetFragmentFromDocRow (doc, item, col, row_start, char_start, -1);
11013     if (StringHasNoText (txt)) {
11014       txt = MemFree (txt);
11015     } else {
11016       ValNodeAddPointer (&fragments, 0, txt);
11017     }
11018     row = row_start + 1;
11019     while (row < row_stop) {
11020       txt = GetFragmentFromDocRow (doc, item, col, row, 0, -1);
11021       if (StringHasNoText (txt)) {
11022         txt = MemFree (txt);
11023       } else {
11024         ValNodeAddPointer (&fragments, 0, txt);
11025       }
11026       row++;
11027     }
11028     txt = GetFragmentFromDocRow (doc, item, col, row_stop, 0, char_stop);
11029     if (StringHasNoText (txt)) {
11030       txt = MemFree (txt);
11031     } else {
11032       ValNodeAddPointer (&fragments, 0, txt);
11033     }
11034   }
11035   txt = GetClickableTextFromItemList (fragments, " ");
11036   fragments = ValNodeFreeData (fragments);
11037   return txt;
11038 }
11039 
11040 
CollectFromThisColumn(Int2 col,Int2Ptr only_these_columns,Int2 num_col)11041 static Boolean CollectFromThisColumn (Int2 col, Int2Ptr only_these_columns, Int2 num_col)
11042 {
11043   Int2 i;
11044   Boolean rval = FALSE;
11045 
11046   if (only_these_columns == NULL) {
11047     rval = TRUE;
11048   } else {
11049     for (i = 0; i < num_col; i++) {
11050       if (only_these_columns[i] == col) {
11051         rval = TRUE;
11052       }
11053     }
11054   }
11055   return rval;
11056 }
11057 
11058 
11059 static CharPtr
GetFragmentsFromDocItem(DoC doc,Int2 item,Int2 col_start,Int2 col_stop,Int2 row_start,Int2 row_stop,Int2 char_start,Int2 char_stop,Int2Ptr only_these_columns,Int2 num_col)11060 GetFragmentsFromDocItem
11061 (DoC  doc,
11062  Int2 item,
11063  Int2 col_start, Int2 col_stop,
11064  Int2 row_start, Int2 row_stop,
11065  Int2 char_start, Int2 char_stop,
11066  Int2Ptr only_these_columns, Int2 num_col)
11067 {
11068   Int2       col;
11069   CharPtr    txt;
11070   Int2       num_rows, num_cols;
11071   ValNodePtr fragments = NULL;
11072 
11073   GetItemParams4 (doc, item, NULL, &num_rows, &num_cols, NULL, NULL);
11074   if (col_stop < 0) {
11075     col_stop = num_cols;
11076   }
11077   if (row_stop < 0) {
11078     row_stop = num_rows;
11079   }
11080 
11081   if (col_start == col_stop) {
11082     if (CollectFromThisColumn (col_start, only_these_columns, num_col)) {
11083       txt = GetFragmentsFromDocCol (doc, item, col_start, row_start, row_stop, char_start, char_stop);
11084       ValNodeAddPointer (&fragments, 0, txt);
11085     }
11086   } else {
11087     if (CollectFromThisColumn (col_start, only_these_columns, num_col)) {
11088       txt = GetFragmentsFromDocCol (doc, item, col_start, row_start, num_rows, char_start, -1);
11089       ValNodeAddPointer (&fragments, 0, txt);
11090     }
11091     col = col_start + 1;
11092     while (col < col_stop) {
11093       if (CollectFromThisColumn (col, only_these_columns, num_col)) {
11094         txt = GetFragmentsFromDocCol (doc, item, col, 1, num_rows, 0, -1);
11095         ValNodeAddPointer (&fragments, 0, txt);
11096       }
11097       col++;
11098     }
11099     if (CollectFromThisColumn (col_stop, only_these_columns, num_col)) {
11100       txt = GetFragmentsFromDocCol (doc, item, col_stop, 1, row_stop, 0, char_stop);
11101       ValNodeAddPointer (&fragments, 0, txt);
11102     }
11103   }
11104   txt = GetClickableTextFromItemList (fragments, "\t");
11105   fragments = ValNodeFreeData (fragments);
11106 
11107   return txt;
11108 }
11109 
11110 
GetSelectedDocText(DoC doc,Int2 item_start,Int2 row_start,Int2 col_start,Int2 char_start,Int2 item_stop,Int2 row_stop,Int2 col_stop,Int2 char_stop,Int2Ptr only_these_columns,Int2 num_col)11111 NLM_EXTERN CharPtr GetSelectedDocText (DoC doc, Int2 item_start, Int2 row_start, Int2 col_start, Int2 char_start,
11112                                        Int2 item_stop, Int2 row_stop, Int2 col_stop, Int2 char_stop,
11113                                        Int2Ptr only_these_columns, Int2 num_col)
11114 {
11115   Int2             item;
11116   CharPtr          txt;
11117   ValNodePtr       fragment_list = NULL;
11118 
11119   if (doc == NULL || item_start < 1)
11120   {
11121     return NULL;
11122   }
11123 
11124   if (char_start < 0) char_start = 0;
11125 
11126   if (item_start == item_stop) {
11127     txt = GetFragmentsFromDocItem (doc, item_start, col_start, col_stop, row_start, row_stop, char_start, char_stop, only_these_columns, num_col);
11128     ValNodeAddPointer (&fragment_list, 0, txt);
11129   } else {
11130     txt = GetFragmentsFromDocItem (doc, item_start, col_start, -1, row_start, -1, char_start, -1, only_these_columns, num_col);
11131     ValNodeAddPointer (&fragment_list, 0, txt);
11132     item = item_start + 1;
11133     while (item < item_stop) {
11134       txt = GetFragmentsFromDocItem (doc, item, 1, -1, 1, -1, 0, -1, only_these_columns, num_col);
11135       ValNodeAddPointer (&fragment_list, 0, txt);
11136       item++;
11137     }
11138     txt = GetFragmentsFromDocItem (doc, item, 1, col_stop, 1, row_stop, 0, char_stop, only_these_columns, num_col);
11139     ValNodeAddPointer (&fragment_list, 0, txt);
11140   }
11141 
11142   txt = GetClickableTextFromItemList (fragment_list, "\r\n");
11143   fragment_list = ValNodeFreeData (fragment_list);
11144   return txt;
11145 }
11146 
GetSelectedClickableListText(DialoG d)11147 extern CharPtr GetSelectedClickableListText (DialoG d)
11148 {
11149   ClickableListPtr dlg;
11150   Int2             numRows;
11151   Int2             item, row, col, char_offset;
11152   Int4             text_len = 0, len = 0;
11153   CharPtr          txt, cp_txt;
11154   ValNodePtr       fragment_list = NULL, item_list = NULL;
11155 
11156   dlg = (ClickableListPtr) GetObjectExtra (d);
11157   if (dlg == NULL || dlg->text_select_item_start < 1)
11158   {
11159     return NULL;
11160   }
11161 
11162   item = dlg->text_select_item_start;
11163   row = dlg->text_select_row_start;
11164   char_offset = dlg->text_select_char_start;
11165 
11166   while (item <= dlg->text_select_item_stop) {
11167     if (item == dlg->text_select_item_start) {
11168       if (item == dlg->text_select_item_stop) {
11169         /* all text from one item */
11170         /* all text will be from last column in item */
11171         GetItemParams4 (dlg->doc, item, NULL, NULL, &col, NULL, NULL);
11172         if (row == dlg->text_select_row_stop) {
11173           /* all text from one row */
11174           txt = GetDocText (dlg->doc, item, row, col);
11175           len = StringLen (txt);
11176           if (dlg->text_select_char_stop >= len) {
11177             /* selection was drawn beyond length of text */
11178             dlg->text_select_char_stop = len - 1;
11179           }
11180           if (dlg->text_select_char_start >= len) {
11181             /* do nothing - selection is not within text */
11182           } else {
11183             cp_txt = (CharPtr) MemNew (sizeof (Char) * (2 + dlg->text_select_char_stop - dlg->text_select_char_start));
11184             StringNCpy (cp_txt, txt + dlg->text_select_char_start, 1 + dlg->text_select_char_stop - dlg->text_select_char_start);
11185             cp_txt[1 + dlg->text_select_char_stop - dlg->text_select_char_start] = 0;
11186             ValNodeAddPointer (&fragment_list, 0, cp_txt);
11187           }
11188           /* free txt read from Doc */
11189           txt = MemFree (txt);
11190         } else {
11191           /* take text from several rows */
11192           item_list = NULL;
11193           while (row < dlg->text_select_row_stop) {
11194             txt = GetDocText (dlg->doc, item, row, col);
11195             len = StringLen (txt);
11196             if (row == dlg->text_select_row_start && dlg->text_select_char_start >= len) {
11197               /* do nothing - selection is not within text */
11198               txt = MemFree (txt);
11199             } else {
11200               if (row == dlg->text_select_row_start && dlg->text_select_char_start > 0) {
11201                 cp_txt = (CharPtr) MemNew (sizeof (Char) * (1 + StringLen (txt) - dlg->text_select_char_start));
11202                 StringCpy (cp_txt, txt + dlg->text_select_char_start);
11203                 txt = MemFree (txt);
11204                 txt = cp_txt;
11205               }
11206               ValNodeAddPointer (&item_list, 0, txt);
11207             }
11208             row++;
11209           }
11210           txt = GetDocText (dlg->doc, item, row, col);
11211           if (dlg->text_select_char_stop < len) {
11212             txt[dlg->text_select_char_stop] = 0;
11213           }
11214           ValNodeAddPointer (&item_list, 0, txt);
11215           txt = GetClickableTextFromItemList (item_list, " ");
11216           ValNodeAddPointer (&fragment_list, 0, txt);
11217           item_list = ValNodeFreeData (item_list);
11218         }
11219       } else {
11220         /* take all text after first row and char offset */
11221         item_list = NULL;
11222         GetItemParams4 (dlg->doc, item, NULL, &numRows, &col, NULL, NULL);
11223         while (row <= numRows) {
11224           txt = GetDocText (dlg->doc, item, row, col);
11225           len = StringLen (txt);
11226           if (row == dlg->text_select_row_start && dlg->text_select_char_start >= len) {
11227             /* do nothing = selection is outside text */
11228             txt = MemFree (txt);
11229           } else {
11230             if (row == dlg->text_select_row_start && dlg->text_select_char_start > 0) {
11231               cp_txt = (CharPtr) MemNew (sizeof (Char) * (1 + StringLen (txt) - dlg->text_select_char_start));
11232               StringCpy (cp_txt, txt + dlg->text_select_char_start);
11233               txt = MemFree (txt);
11234               txt = cp_txt;
11235             }
11236             ValNodeAddPointer (&item_list, 0, txt);
11237           }
11238           row++;
11239         }
11240         txt = GetClickableTextFromItemList (item_list, " ");
11241         ValNodeAddPointer (&fragment_list, 0, txt);
11242         item_list = ValNodeFreeData (item_list);
11243       }
11244     } else if (item == dlg->text_select_item_stop) {
11245       /* take all text until last row and char offset */
11246       row = 1;
11247       item_list = NULL;
11248       GetItemParams4 (dlg->doc, item, NULL, NULL, &col, NULL, NULL);
11249       while (row < dlg->text_select_row_stop) {
11250         txt = GetDocText (dlg->doc, item, row, col);
11251         ValNodeAddPointer (&item_list, 0, txt);
11252       }
11253       txt = GetDocText (dlg->doc, item, row, col);
11254       if (dlg->text_select_char_stop + 1 < StringLen (txt)) {
11255         txt[dlg->text_select_char_stop + 1] = 0;
11256       }
11257       ValNodeAddPointer (&item_list, 0, txt);
11258       txt = GetClickableTextFromItemList (item_list, " ");
11259       ValNodeAddPointer (&fragment_list, 0, txt);
11260       item_list = ValNodeFreeData (item_list);
11261     } else {
11262       GetItemParams4 (dlg->doc, item, NULL, NULL, &col, NULL, NULL);
11263       txt = GetDocText (dlg->doc, item, 0, col);
11264       if (txt != NULL && txt[StringLen(txt) - 1] == '\n') {
11265         /* remove terminal carriage return */
11266         txt[StringLen(txt) - 1] = 0;
11267       }
11268       ValNodeAddPointer (&fragment_list, 0, txt);
11269       text_len += StringLen (txt) + 1;
11270     }
11271     item++;
11272   }
11273   txt = GetClickableTextFromItemList (fragment_list, "\r\n");
11274   fragment_list = ValNodeFreeData (fragment_list);
11275   return txt;
11276 }
11277 
11278 typedef struct basegbqualeditor {
11279   DIALOG_MESSAGE_BLOCK
11280   TaglistCallback tlp_callback;
11281   Pointer         callback_data;
11282 } BaseGBQualEditor, PNTR BaseGBQualEditorPtr;
11283 
ChangeGBQualEditorPopup(PopuP p)11284 static void ChangeGBQualEditorPopup (PopuP p)
11285 {
11286   BaseGBQualEditorPtr dlg;
11287 
11288   dlg = (BaseGBQualEditorPtr) GetObjectExtra (p);
11289   if (dlg != NULL && dlg->tlp_callback != NULL) {
11290     (dlg->tlp_callback)(dlg->callback_data);
11291   }
11292 }
11293 
ChangeGBQualEditorButton(ButtoN b)11294 static void ChangeGBQualEditorButton (ButtoN b)
11295 {
11296   BaseGBQualEditorPtr dlg;
11297 
11298   dlg = (BaseGBQualEditorPtr) GetObjectExtra (b);
11299   if (dlg != NULL && dlg->tlp_callback != NULL) {
11300     (dlg->tlp_callback)(dlg->callback_data);
11301   }
11302 }
11303 
ChangeGBQualEditorText(TexT t)11304 static void ChangeGBQualEditorText (TexT t)
11305 {
11306   BaseGBQualEditorPtr dlg;
11307 
11308   dlg = (BaseGBQualEditorPtr) GetObjectExtra (t);
11309   if (dlg != NULL && dlg->tlp_callback != NULL) {
11310     (dlg->tlp_callback)(dlg->callback_data);
11311   }
11312 }
11313 
11314 
11315 typedef struct collectiondatedlg {
11316   DIALOG_MESSAGE_BLOCK
11317   TaglistCallback tlp_callback;
11318   Pointer callback_data;
11319   PopuP month;
11320   PopuP day;
11321   PopuP year;
11322   Int4  start_year;
11323 } CollectionDateDlgData, PNTR CollectionDateDlgPtr;
11324 
11325 static void PopulateDayPopup (PopuP p, Int4 month);
11326 
PointerToCollectionDateDialog(DialoG d,Pointer data)11327 static void PointerToCollectionDateDialog (DialoG d, Pointer data)
11328 {
11329   CollectionDateDlgPtr dlg;
11330   CharPtr              val, reformatted;
11331   Boolean              ambiguous = FALSE;
11332   CharPtr              cp, cp2, month_abbrev;
11333   Int4                 year = 1, month = 1, day = 1;
11334 
11335   dlg = (CollectionDateDlgPtr) GetObjectExtra (d);
11336   if (dlg == NULL) return;
11337 
11338   SetValue (dlg->year, 1);
11339   SetValue (dlg->month, 1);
11340   SetValue (dlg->day, 1);
11341   Disable (dlg->month);
11342   Disable (dlg->day);
11343 
11344   val = (CharPtr) data;
11345 
11346   reformatted = ReformatDateStringEx (val, TRUE, &ambiguous);
11347   if (StringHasNoText (reformatted) || ambiguous) {
11348     /* do nothing */
11349   } else {
11350     cp = StringChr (reformatted, '-');
11351     if (cp == NULL) {
11352       year = GetYearFromToken (reformatted, StringLen (reformatted));
11353       year = year - dlg->start_year + 2;
11354     } else {
11355       if (isdigit (*reformatted)) {
11356         day = ReadNumberFromToken (reformatted, cp - reformatted);
11357         day += 1;
11358         cp++;
11359         cp2 = StringChr (cp, '-');
11360         month_abbrev = GetMonthFromToken (cp, cp2 - cp);
11361         month = GetMonthNumFromAbbrev (month_abbrev);
11362         if (month > -1) {
11363           month += 2;
11364         } else {
11365           month = 1;
11366         }
11367         year = GetYearFromToken (cp2 + 1, StringLen (cp2 + 1));
11368         year = year - dlg->start_year + 2;
11369       }
11370       else
11371       {
11372         month_abbrev = GetMonthFromToken (reformatted, cp - reformatted);
11373         month = GetMonthNumFromAbbrev (month_abbrev);
11374         if (month > -1) {
11375           month += 2;
11376         } else {
11377           month = 1;
11378         }
11379         year = GetYearFromToken (cp + 1, StringLen (cp + 1));
11380         year = year - dlg->start_year + 2;
11381       }
11382     }
11383     SetValue (dlg->year, year);
11384     Enable (dlg->month);
11385     SetValue (dlg->month, month);
11386     if (month > 1) {
11387       PopulateDayPopup (dlg->day, month);
11388       Enable (dlg->day);
11389     }
11390     SetValue (dlg->day, day);
11391   }
11392 }
11393 
CollectionDateDialogToPointer(DialoG d)11394 static Pointer CollectionDateDialogToPointer (DialoG d)
11395 {
11396   CollectionDateDlgPtr dlg;
11397   Int4                 year, month = -1, day = 0;
11398   CharPtr              year_fmt = "%d";
11399   CharPtr              mon_year_fmt = "%s-%d";
11400   CharPtr              day_mon_year_fmt = "%d-%s-%d";
11401   Char                 date_str[100];
11402 
11403   dlg = (CollectionDateDlgPtr) GetObjectExtra (d);
11404   date_str[0] = 0;
11405   if (dlg != NULL) {
11406     year = GetValue (dlg->year);
11407     if (year < 2) {
11408       return NULL;
11409     } else {
11410       year = year + dlg->start_year - 2;
11411       month = GetValue (dlg->month);
11412       if (month < 2) {
11413         sprintf (date_str, year_fmt, year);
11414       } else {
11415         day = GetValue (dlg->day);
11416         if (day < 2) {
11417           sprintf (date_str, mon_year_fmt, GetMonthAbbrev (month - 1), year);
11418         } else {
11419           sprintf (date_str, day_mon_year_fmt, day - 1, GetMonthAbbrev (month - 1), year);
11420         }
11421       }
11422     }
11423   }
11424 
11425   return StringSave (date_str);
11426 }
11427 
PopulateDayPopup(PopuP p,Int4 month)11428 static void PopulateDayPopup (PopuP p, Int4 month)
11429 {
11430   Int4 i;
11431   Char day[10];
11432 
11433   Reset (p);
11434   PopupItem (p, "");
11435 
11436   if (month > 1) {
11437     for (i = 1; i <= GetDaysInMonth(month - 1); i++) {
11438       sprintf (day, "%d", i);
11439       PopupItem (p, day);
11440     }
11441   }
11442 }
11443 
PopulateMonthPopup(PopuP p)11444 static void PopulateMonthPopup (PopuP p)
11445 {
11446   Int4 i;
11447 
11448   PopupItem (p, "");
11449   for (i = 0; i < 12; i++) {
11450     PopupItem (p, GetMonthAbbrev(i + 1));
11451   }
11452 }
11453 
ChangeCollectionDateMonth(PopuP p)11454 static void ChangeCollectionDateMonth (PopuP p)
11455 {
11456   CollectionDateDlgPtr dlg;
11457   Int4                 month;
11458 
11459   dlg = (CollectionDateDlgPtr) GetObjectExtra (p);
11460   if (dlg == NULL) return;
11461 
11462   month = GetValue (p);
11463   if (month < 2) {
11464     Disable (dlg->day);
11465   } else {
11466     PopulateDayPopup (dlg->day, month);
11467     Enable (dlg->day);
11468   }
11469   if (dlg->tlp_callback != NULL) {
11470     (dlg->tlp_callback) (dlg->callback_data);
11471   }
11472 }
11473 
PopulateYearPopup(PopuP p)11474 static Int4 PopulateYearPopup (PopuP p)
11475 {
11476     Nlm_DayTime dt;
11477   Char        year_str[20];
11478   Int4        start_year, i, end_year;
11479 
11480   GetDayTime (&dt);
11481   start_year = dt.tm_year + 1901 - 10;
11482   end_year = start_year + 20;
11483   PopupItem (p, " ");
11484   for (i=start_year; i <= end_year; i++) {
11485     sprintf (year_str, "%d", i);
11486     PopupItem (p, year_str);
11487   }
11488   return start_year;
11489 }
11490 
ChangeCollectionDateYear(PopuP p)11491 static void ChangeCollectionDateYear (PopuP p)
11492 {
11493   CollectionDateDlgPtr dlg;
11494 
11495   dlg = (CollectionDateDlgPtr) GetObjectExtra (p);
11496   if (dlg == NULL) return;
11497 
11498   if (GetValue (p) < 2) {
11499     Disable (dlg->month);
11500     Disable (dlg->day);
11501   } else {
11502     Enable (dlg->month);
11503     ChangeCollectionDateMonth (dlg->month);
11504   }
11505   if (dlg->tlp_callback != NULL) {
11506     (dlg->tlp_callback) (dlg->callback_data);
11507   }
11508 }
11509 
CollectionDateDialog(GrouP h,SeqEntryPtr sep,CharPtr name,TaglistCallback tlp_callback,Pointer callback_data)11510 extern DialoG CollectionDateDialog (GrouP h, SeqEntryPtr sep, CharPtr name,
11511                                TaglistCallback tlp_callback,
11512                                Pointer callback_data)
11513 {
11514   CollectionDateDlgPtr dlg;
11515   GrouP           p;
11516 
11517   p = HiddenGroup (h, 4, 0, NULL);
11518   dlg = (CollectionDateDlgPtr) MemNew (sizeof(CollectionDateDlgData));
11519 
11520   SetObjectExtra (p, dlg, StdCleanupExtraProc);
11521   dlg->dialog = (DialoG) p;
11522   dlg->todialog = PointerToCollectionDateDialog;
11523   dlg->fromdialog = CollectionDateDialogToPointer;
11524   dlg->testdialog = NULL;
11525   dlg->tlp_callback = tlp_callback;
11526   dlg->callback_data = callback_data;
11527 
11528   dlg->year = PopupList (p, TRUE, ChangeCollectionDateYear);
11529   SetObjectExtra (dlg->year, dlg, NULL);
11530   dlg->start_year = PopulateYearPopup (dlg->year);
11531   SetValue (dlg->year, 1);
11532 
11533   dlg->month = PopupList (p, TRUE, ChangeCollectionDateMonth);
11534   SetObjectExtra (dlg->month, dlg, NULL);
11535   PopulateMonthPopup (dlg->month);
11536   SetValue (dlg->month, 1);
11537 
11538   dlg->day = PopupList (p, TRUE, ChangeGBQualEditorPopup);
11539   SetObjectExtra (dlg->day, dlg, NULL);
11540 
11541   return (DialoG) p;
11542 }
11543 
ParseCollectionDateOk(CharPtr txt)11544 extern Boolean ParseCollectionDateOk (CharPtr txt)
11545 {
11546   CharPtr date_str;
11547   Boolean ambiguous = FALSE;
11548   Boolean rval = FALSE;
11549 
11550   if (StringHasNoText (txt)) {
11551     rval = TRUE;
11552   } else {
11553     date_str = ReformatDateStringEx (txt, TRUE, &ambiguous);
11554     if (date_str != NULL && !ambiguous) {
11555       rval = TRUE;
11556     }
11557     date_str = MemFree (date_str);
11558   }
11559   return rval;
11560 }
11561 
11562 typedef struct rptunitrangedlg {
11563   DIALOG_MESSAGE_BLOCK
11564   TaglistCallback tlp_callback;
11565   Pointer callback_data;
11566   TexT  range_start;
11567   TexT  range_stop;
11568 } RptUnitRangeDlgData, PNTR RptUnitRangeDlgPtr;
11569 
ParseRptUnitRangeOkEx(CharPtr txt,Int4Ptr pstart,Int4Ptr pstop)11570 static Boolean ParseRptUnitRangeOkEx (CharPtr txt, Int4Ptr pstart, Int4Ptr pstop)
11571 {
11572   CharPtr cp;
11573   Int4    start = -1, stop = -1;
11574   Char    ch;
11575   Boolean rval = FALSE;
11576 
11577   if (StringHasNoText (txt)) {
11578     return TRUE;
11579   }
11580 
11581   cp = txt;
11582   while (*cp != 0 && isdigit (*cp)) {
11583     cp++;
11584   }
11585   if (cp != txt) {
11586     ch = *cp;
11587     *cp = 0;
11588     start = atoi (txt);
11589     *cp = ch;
11590     cp++;
11591     while (*cp == ch) {
11592       cp++;
11593     }
11594     txt = cp;
11595     while (isdigit (*cp)) {
11596       cp++;
11597     }
11598     if (cp != txt) {
11599       stop = atoi (txt);
11600     }
11601   }
11602 
11603   if (start > -1 && stop > -1) {
11604     if (pstart != NULL) {
11605       *pstart = start;
11606     }
11607     if (pstop != NULL) {
11608       *pstop = stop;
11609     }
11610     rval = TRUE;
11611   }
11612   return rval;
11613 }
11614 
StringToRptUnitRangeDialog(DialoG d,Pointer data)11615 static void StringToRptUnitRangeDialog (DialoG d, Pointer data)
11616 {
11617   RptUnitRangeDlgPtr dlg;
11618   CharPtr            val;
11619   Int4               start = -1, stop = -1;
11620   Char               num_str[100];
11621 
11622   dlg = (RptUnitRangeDlgPtr) GetObjectExtra (d);
11623   if (dlg == NULL) return;
11624 
11625   val = (CharPtr) data;
11626 
11627   ParseRptUnitRangeOkEx (val, &start, &stop);
11628   if (start > -1 && stop > -1) {
11629     sprintf (num_str, "%d", start);
11630     SetTitle (dlg->range_start, num_str);
11631     sprintf (num_str, "%d", stop);
11632     SetTitle (dlg->range_stop, num_str);
11633   } else {
11634     SetTitle (dlg->range_start, "");
11635     SetTitle (dlg->range_stop, "");
11636   }
11637 }
11638 
RptUnitRangeDialogToString(DialoG d)11639 static Pointer RptUnitRangeDialogToString (DialoG d)
11640 {
11641   RptUnitRangeDlgPtr dlg;
11642   CharPtr            val = NULL;
11643   CharPtr            start, stop;
11644 
11645   dlg = (RptUnitRangeDlgPtr) GetObjectExtra (d);
11646   if (dlg == NULL) return NULL;
11647 
11648   start = SaveStringFromText (dlg->range_start);
11649   stop = SaveStringFromText (dlg->range_stop);
11650 
11651   if (StringHasNoText (start) && StringHasNoText (stop)) {
11652     return StringSave ("");
11653   } else {
11654     val = (CharPtr) MemNew (sizeof (Char) * (StringLen (start) + StringLen (stop) + 3));
11655     sprintf (val, "%s..%s", start == NULL ? "" : start, stop == NULL ? "" : stop);
11656   }
11657   start = MemFree (start);
11658   stop = MemFree (stop);
11659   return val;
11660 }
11661 
11662 
CreateRptUnitRangeDialog(GrouP h,SeqEntryPtr sep,CharPtr name,TaglistCallback tlp_callback,Pointer callback_data)11663 extern DialoG CreateRptUnitRangeDialog (GrouP h, SeqEntryPtr sep, CharPtr name,
11664                                          TaglistCallback tlp_callback,
11665                                          Pointer callback_data)
11666 {
11667   RptUnitRangeDlgPtr dlg;
11668   GrouP           p;
11669 
11670   p = HiddenGroup (h, 6, 0, NULL);
11671   dlg = (RptUnitRangeDlgPtr) MemNew (sizeof(RptUnitRangeDlgData));
11672 
11673   SetObjectExtra (p, dlg, StdCleanupExtraProc);
11674   dlg->dialog = (DialoG) p;
11675   dlg->todialog = StringToRptUnitRangeDialog;
11676   dlg->fromdialog = RptUnitRangeDialogToString;
11677   dlg->testdialog = NULL;
11678 
11679   dlg->tlp_callback = tlp_callback;
11680   dlg->callback_data = callback_data;
11681 
11682   StaticPrompt (p, "Start", 0, dialogTextHeight, programFont, 'l');
11683   dlg->range_start = DialogText (p, "", 5, ChangeGBQualEditorText);
11684   SetObjectExtra (dlg->range_start, dlg, NULL);
11685   StaticPrompt (p, "Stop", 0, dialogTextHeight, programFont, 'l');
11686   dlg->range_stop = DialogText (p, "", 5, ChangeGBQualEditorText);
11687   SetObjectExtra (dlg->range_stop, dlg, NULL);
11688 
11689 
11690   return (DialoG) p;
11691 }
11692 
ParseRptUnitRangeOk(CharPtr txt)11693 static Boolean ParseRptUnitRangeOk (CharPtr txt)
11694 {
11695   return ParseRptUnitRangeOkEx (txt, NULL, NULL);
11696 }
11697 
11698 
11699 typedef struct controlplusfreedlg {
11700   DIALOG_MESSAGE_BLOCK
11701   TaglistCallback tlp_callback;
11702   Pointer callback_data;
11703   PopuP element_type;
11704   TexT  description;
11705 
11706   CharPtr PNTR control_words;
11707 } ControlPlusFreeDlgData, PNTR ControlPlusFreeDlgPtr;
11708 
11709 
GetControlNum(CharPtr txt,CharPtr PNTR control_words,CharPtr PNTR desc_start)11710 static Int2 GetControlNum (CharPtr txt, CharPtr PNTR control_words, CharPtr PNTR desc_start)
11711 {
11712   CharPtr cp;
11713   Int2    i;
11714   Int4    keyword_len;
11715 
11716   if (desc_start != NULL) {
11717     *desc_start = NULL;
11718   }
11719   if (StringHasNoText (txt) || control_words == NULL) {
11720     return 0;
11721   }
11722   /* skip over any leading spaces */
11723   while (isspace (*txt)) {
11724     txt++;
11725   }
11726   cp = StringChr (txt, ':');
11727   if (cp == NULL) {
11728     for (i = 1; control_words[i] != NULL; i++) {
11729       if (StringICmp (txt, control_words[i]) == 0) {
11730         return i;
11731       }
11732     }
11733     return -1;
11734   } else {
11735     keyword_len = cp - txt;
11736     while (keyword_len > 0 && isspace (txt[keyword_len - 1])) {
11737       keyword_len--;
11738     }
11739     if (keyword_len == 0) {
11740       return 0;
11741     }
11742     for (i = 1; control_words[i] != NULL; i++) {
11743       if (StringNICmp (txt, control_words[i], keyword_len) == 0) {
11744         if (desc_start != NULL && !StringHasNoText (cp + 1)) {
11745           *desc_start = cp + 1;
11746           while (isspace(**desc_start)) {
11747             (*desc_start)++;
11748           }
11749         }
11750         return i;
11751       }
11752     }
11753   }
11754   return -1;
11755 }
11756 
ChangeControlPlusFreeType(PopuP p)11757 static void ChangeControlPlusFreeType (PopuP p)
11758 {
11759   ControlPlusFreeDlgPtr dlg;
11760 
11761   dlg = (ControlPlusFreeDlgPtr) GetObjectExtra (p);
11762   if (dlg == NULL) return;
11763 
11764   if (GetValue (dlg->element_type) <= 1) {
11765     Disable (dlg->description);
11766   } else {
11767     Enable (dlg->description);
11768   }
11769   ChangeGBQualEditorPopup (p);
11770 }
11771 
StringToControlPlusFreeDialog(DialoG d,Pointer data)11772 static void StringToControlPlusFreeDialog (DialoG d, Pointer data)
11773 {
11774   ControlPlusFreeDlgPtr dlg;
11775   CharPtr             val;
11776   CharPtr             desc_start = NULL;
11777   Int2                num;
11778 
11779   dlg = (ControlPlusFreeDlgPtr) GetObjectExtra (d);
11780   if (dlg == NULL) return;
11781 
11782   val = (CharPtr) data;
11783 
11784   num = GetControlNum (val, dlg->control_words, &desc_start);
11785 
11786   if (num >= 0) {
11787     SetValue (dlg->element_type, num + 1);
11788     SetTitle (dlg->description, desc_start == NULL ? "" : desc_start);
11789   }
11790 }
11791 
ControlPlusFreeDialogToString(DialoG d)11792 static Pointer ControlPlusFreeDialogToString (DialoG d)
11793 {
11794   ControlPlusFreeDlgPtr dlg;
11795   CharPtr             val = NULL;
11796   CharPtr             desc_start = NULL;
11797   Int2                num;
11798 
11799   dlg = (ControlPlusFreeDlgPtr) GetObjectExtra (d);
11800   if (dlg == NULL) return NULL;
11801 
11802   num = GetValue (dlg->element_type);
11803 
11804   if (num >= 1) {
11805     desc_start = SaveStringFromText (dlg->description);
11806     if (StringHasNoText (desc_start)) {
11807       val = StringSave (dlg->control_words[num - 1]);
11808     } else {
11809       val = (CharPtr) MemNew (sizeof (Char) * (StringLen (dlg->control_words[num - 1]) + StringLen (desc_start) + 2));
11810       sprintf (val, "%s:%s", dlg->control_words[num - 1], desc_start);
11811     }
11812   }
11813   return (Pointer) val;
11814 }
11815 
11816 
CreateControlPlusFreeDialog(GrouP h,SeqEntryPtr sep,CharPtr name,TaglistCallback tlp_callback,Pointer callback_data,CharPtr PNTR control_words)11817 static DialoG CreateControlPlusFreeDialog (GrouP h, SeqEntryPtr sep, CharPtr name,
11818                                            TaglistCallback tlp_callback,
11819                                            Pointer callback_data,
11820                                            CharPtr PNTR control_words)
11821 {
11822   ControlPlusFreeDlgPtr dlg;
11823   GrouP           p;
11824   Int2            i;
11825 
11826   p = HiddenGroup (h, 3, 0, NULL);
11827   dlg = (ControlPlusFreeDlgPtr) MemNew (sizeof(ControlPlusFreeDlgData));
11828 
11829   SetObjectExtra (p, dlg, StdCleanupExtraProc);
11830   dlg->dialog = (DialoG) p;
11831   dlg->todialog = StringToControlPlusFreeDialog;
11832   dlg->fromdialog = ControlPlusFreeDialogToString;
11833   dlg->testdialog = NULL;
11834 
11835   dlg->tlp_callback = tlp_callback;
11836   dlg->callback_data = callback_data;
11837 
11838   dlg->control_words = control_words;
11839   dlg->element_type = PopupList (p, TRUE, ChangeControlPlusFreeType);
11840   for (i = 0; dlg->control_words[i] != NULL; i++) {
11841     PopupItem (dlg->element_type, dlg->control_words[i]);
11842   }
11843   SetValue (dlg->element_type, 1);
11844   SetObjectExtra (dlg->element_type, dlg, NULL);
11845 
11846   dlg->description = DialogText (p, "", 15, ChangeGBQualEditorText);
11847   SetObjectExtra (dlg->description, dlg, NULL);
11848 
11849   return (DialoG) p;
11850 }
11851 
CopyTextToControlPlusFreeDialog(DialoG d,CharPtr txt)11852 static void CopyTextToControlPlusFreeDialog (DialoG d, CharPtr txt)
11853 {
11854   ControlPlusFreeDlgPtr dlg;
11855 
11856   dlg = (ControlPlusFreeDlgPtr) GetObjectExtra (d);
11857 
11858   if (dlg == NULL || StringHasNoText (txt)) return;
11859 
11860   SetTitle (dlg->description, txt);
11861 }
11862 
11863 
11864 CharPtr mobile_element_keywords[] =
11865 { " ",
11866   "transposon",
11867   "retrotransposon",
11868   "integron",
11869   "insertion sequence",
11870   "non-LTR retrotransposon",
11871   "SINE",
11872   "MITE",
11873   "LINE",
11874   "other",
11875   NULL};
11876 
11877 
CreateMobileElementDialog(GrouP h,SeqEntryPtr sep,CharPtr name,TaglistCallback tlp_callback,Pointer callback_data)11878 static DialoG CreateMobileElementDialog (GrouP h, SeqEntryPtr sep, CharPtr name,
11879                                          TaglistCallback tlp_callback,
11880                                          Pointer callback_data)
11881 {
11882   return CreateControlPlusFreeDialog (h, sep, name, tlp_callback, callback_data, mobile_element_keywords);
11883 }
11884 
ParseMobileElementOk(CharPtr txt)11885 static Boolean ParseMobileElementOk (CharPtr txt)
11886 {
11887 
11888   if (GetControlNum (txt, mobile_element_keywords, NULL) > -1) {
11889     return TRUE;
11890   } else {
11891     return FALSE;
11892   }
11893 }
11894 
11895 
11896 CharPtr regulatory_class_keywords[] =
11897 { " ",
11898   "attenuator",
11899   "CAAT_signal",
11900   "DNase_I_hypersensitive_site",
11901   "enhancer_blocking_element",
11902   "enhancer",
11903   "GC_signal",
11904   "imprinting_control_region",
11905   "insulator",
11906   "locus_control_region",
11907   "matrix_attachment_region",
11908   "minus_10_signal",
11909   "minus_35_signal",
11910   "polyA_signal_sequence",
11911   "promoter",
11912   "recoding_stimulatory_region",
11913   "replication_regulatory_region",
11914   "response_element",
11915   "ribosome_binding_site",
11916   "riboswitch",
11917   "silencer",
11918   "TATA_box",
11919   "terminator",
11920   "transcriptional_cis_regulatory_region",
11921   "other",
11922   NULL};
11923 
11924 
CreateRegulatoryClassDialog(GrouP h,SeqEntryPtr sep,CharPtr name,TaglistCallback tlp_callback,Pointer callback_data)11925 static DialoG CreateRegulatoryClassDialog (GrouP h, SeqEntryPtr sep, CharPtr name,
11926                                            TaglistCallback tlp_callback,
11927                                            Pointer callback_data)
11928 {
11929   return CreateControlPlusFreeDialog (h, sep, name, tlp_callback, callback_data, regulatory_class_keywords);
11930 }
11931 
ParseRegulatoryClassOk(CharPtr txt)11932 static Boolean ParseRegulatoryClassOk (CharPtr txt)
11933 {
11934 
11935   if (GetControlNum (txt, regulatory_class_keywords, NULL) > -1) {
11936     return TRUE;
11937   } else {
11938     return FALSE;
11939   }
11940 }
11941 
11942 CharPtr satellite_keywords[] =
11943 { " ",
11944   "satellite",
11945   "microsatellite",
11946   "minisatellite",
11947   NULL};
11948 
11949 
CreateSatelliteDialog(GrouP h,SeqEntryPtr sep,CharPtr name,TaglistCallback tlp_callback,Pointer callback_data)11950 static DialoG CreateSatelliteDialog (GrouP h, SeqEntryPtr sep, CharPtr name,
11951                                          TaglistCallback tlp_callback,
11952                                          Pointer callback_data)
11953 {
11954   return CreateControlPlusFreeDialog (h, sep, name, tlp_callback, callback_data, satellite_keywords);
11955 }
11956 
ParseSatelliteOk(CharPtr txt)11957 static Boolean ParseSatelliteOk (CharPtr txt)
11958 {
11959 
11960   if (GetControlNum (txt, satellite_keywords, NULL) > -1) {
11961     return TRUE;
11962   } else {
11963     return FALSE;
11964   }
11965 }
11966 
11967 CharPtr recombination_class_keywords[] =
11968 { " ",
11969   "meiotic_recombination",
11970   "mitotic_recombination",
11971   "non_allelic_homologous_recombination",
11972   "chromosome_breakpoint",
11973   "other",
11974   NULL};
11975 
11976 
CreateRecombClassDialog(GrouP h,SeqEntryPtr sep,CharPtr name,TaglistCallback tlp_callback,Pointer callback_data)11977 static DialoG CreateRecombClassDialog (GrouP h, SeqEntryPtr sep, CharPtr name,
11978                                        TaglistCallback tlp_callback,
11979                                        Pointer callback_data)
11980 {
11981   return CreateControlPlusFreeDialog (h, sep, name, tlp_callback, callback_data, recombination_class_keywords);
11982 }
11983 
ParseRecombClassOk(CharPtr txt)11984 static Boolean ParseRecombClassOk (CharPtr txt)
11985 {
11986 
11987   if (GetControlNum (txt, recombination_class_keywords, NULL) > -1) {
11988     return TRUE;
11989   } else {
11990     return FALSE;
11991   }
11992 }
11993 
11994 typedef struct truefalsedlg {
11995   DIALOG_MESSAGE_BLOCK
11996   TaglistCallback tlp_callback;
11997   Pointer callback_data;
11998   ButtoN is_true;
11999 } TrueFalseDlgData, PNTR TrueFalseDlgPtr;
12000 
PointerToTrueFalseDialog(DialoG d,Pointer data)12001 static void PointerToTrueFalseDialog (DialoG d, Pointer data)
12002 {
12003   TrueFalseDlgPtr dlg;
12004   CharPtr         val;
12005 
12006   dlg = (TrueFalseDlgPtr) GetObjectExtra (d);
12007   if (dlg == NULL) return;
12008 
12009   val = (CharPtr) data;
12010 
12011   if (StringICmp (val, "TRUE") == 0) {
12012     SetStatus (dlg->is_true, TRUE);
12013   } else {
12014     SetStatus (dlg->is_true, FALSE);
12015   }
12016 }
12017 
TrueFalseDialogToPointer(DialoG d)12018 static Pointer TrueFalseDialogToPointer (DialoG d)
12019 {
12020   TrueFalseDlgPtr dlg;
12021 
12022   dlg = (TrueFalseDlgPtr) GetObjectExtra (d);
12023   if (dlg == NULL) return StringSave ("FALSE");
12024 
12025   if (GetStatus (dlg->is_true)) {
12026     return StringSave ("TRUE");
12027   } else {
12028     return StringSave ("FALSE");
12029   }
12030 }
12031 
TrueFalseDialog(GrouP h,SeqEntryPtr sep,CharPtr name,TaglistCallback tlp_callback,Pointer callback_data)12032 static DialoG TrueFalseDialog (GrouP h, SeqEntryPtr sep, CharPtr name,
12033                                TaglistCallback tlp_callback,
12034                                Pointer callback_data)
12035 {
12036   TrueFalseDlgPtr dlg;
12037   GrouP           p;
12038 
12039   p = HiddenGroup (h, 2, 0, NULL);
12040   dlg = (TrueFalseDlgPtr) MemNew (sizeof(TrueFalseDlgData));
12041 
12042   SetObjectExtra (p, dlg, StdCleanupExtraProc);
12043   dlg->dialog = (DialoG) p;
12044   dlg->todialog = PointerToTrueFalseDialog;
12045   dlg->fromdialog = TrueFalseDialogToPointer;
12046   dlg->testdialog = NULL;
12047   dlg->tlp_callback = tlp_callback;
12048   dlg->callback_data = callback_data;
12049 
12050   dlg->is_true = CheckBox (p, "", ChangeGBQualEditorButton);
12051   SetObjectExtra (dlg->is_true, dlg, NULL);
12052 
12053   return (DialoG) p;
12054 }
12055 
ParseTrueFalseOk(CharPtr txt)12056 static Boolean ParseTrueFalseOk (CharPtr txt)
12057 {
12058   if (StringHasNoText (txt) || StringICmp (txt, "TRUE") == 0 || StringICmp (txt, "FALSE") == 0) {
12059     return TRUE;
12060   } else {
12061     return FALSE;
12062   }
12063 }
12064 
12065 typedef struct simplelistqualdlg {
12066   DIALOG_MESSAGE_BLOCK
12067   TaglistCallback tlp_callback;
12068   Pointer callback_data;
12069   PopuP list;
12070   CharPtr PNTR val_list;
12071 } SimpleListQualDlgData, PNTR SimpleListQualDlgPtr;
12072 
GetListNum(CharPtr val,CharPtr PNTR val_list)12073 static Int2 GetListNum (CharPtr val, CharPtr PNTR val_list)
12074 {
12075   Int2 i;
12076   if (StringHasNoText (val)) return 0;
12077   for (i = 1; val_list[i] != NULL; i++) {
12078     if (StringICmp (val, val_list[i]) == 0) {
12079       return i;
12080     }
12081   }
12082   return -1;
12083 }
12084 
StringToSimpleListQualDialog(DialoG d,Pointer data)12085 static void StringToSimpleListQualDialog (DialoG d, Pointer data)
12086 {
12087   SimpleListQualDlgPtr dlg;
12088   CharPtr              val;
12089   Int2                 num;
12090 
12091   dlg = (SimpleListQualDlgPtr) GetObjectExtra (d);
12092   if (dlg == NULL) return;
12093   val = (CharPtr) data;
12094   num = GetListNum (val, dlg->val_list);
12095   if (num > -1) {
12096     SetValue (dlg->list, num + 1);
12097   } else {
12098     SetValue (dlg->list, 1);
12099   }
12100 }
12101 
SimpleListQualDialogToString(DialoG d)12102 static Pointer SimpleListQualDialogToString (DialoG d)
12103 {
12104   SimpleListQualDlgPtr dlg;
12105   CharPtr              val = NULL;
12106   Int2                 num;
12107 
12108   dlg = (SimpleListQualDlgPtr) GetObjectExtra (d);
12109   if (dlg == NULL) return NULL;
12110 
12111   num = GetValue (dlg->list);
12112   if (num > 1) {
12113     val = StringSave (dlg->val_list[num - 1]);
12114   }
12115   return (Pointer) val;
12116 }
12117 
SimpleListQualDialog(GrouP h,SeqEntryPtr sep,CharPtr name,CharPtr PNTR list,TaglistCallback tlp_callback,Pointer callback_data)12118 static DialoG SimpleListQualDialog (GrouP h, SeqEntryPtr sep, CharPtr name, CharPtr PNTR list,
12119                                     TaglistCallback tlp_callback,
12120                                     Pointer callback_data)
12121 {
12122   SimpleListQualDlgPtr dlg;
12123   GrouP           p;
12124   Int2            i;
12125 
12126   p = HiddenGroup (h, 2, 0, NULL);
12127   dlg = (SimpleListQualDlgPtr) MemNew (sizeof(SimpleListQualDlgData));
12128 
12129   SetObjectExtra (p, dlg, StdCleanupExtraProc);
12130   dlg->dialog = (DialoG) p;
12131   dlg->todialog = StringToSimpleListQualDialog;
12132   dlg->fromdialog = SimpleListQualDialogToString;
12133   dlg->testdialog = NULL;
12134   dlg->tlp_callback = tlp_callback;
12135   dlg->callback_data = callback_data;
12136 
12137   dlg->list = PopupList (p, TRUE, ChangeGBQualEditorPopup);
12138   SetObjectExtra (dlg->list, dlg, NULL);
12139   dlg->val_list = list;
12140   if (dlg->val_list != NULL) {
12141     for (i = 0; dlg->val_list[i] != NULL; i++) {
12142       PopupItem (dlg->list, dlg->val_list[i]);
12143     }
12144     SetValue (dlg->list, 1);
12145   }
12146   return (DialoG) p;
12147 }
12148 
12149 typedef struct multilistqualdlg {
12150   DIALOG_MESSAGE_BLOCK
12151   TaglistCallback tlp_callback;
12152   Pointer callback_data;
12153   ButtoN  *button_list;
12154   TexT    last_txt;
12155 
12156   CharPtr PNTR val_list;
12157 } MultiListQualDlgData, PNTR MultiListQualDlgPtr;
12158 
CleanupMultiListQualDlg(GraphiC g,VoidPtr data)12159 static void CleanupMultiListQualDlg (GraphiC g, VoidPtr data)
12160 
12161 {
12162   MultiListQualDlgPtr  dlg;
12163 
12164   dlg = (MultiListQualDlgPtr) data;
12165   if (dlg != NULL) {
12166     dlg->button_list = MemFree (dlg->button_list);
12167   }
12168   StdCleanupExtraProc (g, data);
12169 }
12170 
CheckMultiListLast(ButtoN b)12171 static void CheckMultiListLast (ButtoN b)
12172 {
12173   MultiListQualDlgPtr dlg;
12174 
12175   dlg = (MultiListQualDlgPtr) GetObjectExtra (b);
12176   if (dlg == NULL) return;
12177 
12178   if (GetStatus (b)) {
12179     Enable (dlg->last_txt);
12180   } else {
12181     Disable (dlg->last_txt);
12182   }
12183   if (dlg->tlp_callback) {
12184     (dlg->tlp_callback) (dlg->callback_data);
12185   }
12186 }
12187 
ApplyOneValToMultiListQualDialog(MultiListQualDlgPtr dlg,CharPtr val,CharPtr PNTR other_text)12188 static void ApplyOneValToMultiListQualDialog (MultiListQualDlgPtr dlg, CharPtr val, CharPtr PNTR other_text)
12189 {
12190   Int2    i;
12191   CharPtr tmp;
12192 
12193   if (dlg == NULL || StringHasNoText (val) || other_text == NULL) return;
12194 
12195   i = GetListNum (val, dlg->val_list);
12196   if (i > 0) {
12197     SetStatus (dlg->button_list[i - 1], TRUE);
12198   } else {
12199     if (*other_text == NULL) {
12200       *other_text = StringSave (val);
12201     } else {
12202       tmp = (CharPtr) MemNew (sizeof (Char) * (StringLen (*other_text) + StringLen (val) + 2));
12203       sprintf (tmp, "%s,%s", *other_text, val);
12204       *other_text = MemFree (*other_text);
12205       *other_text = tmp;
12206     }
12207   }
12208 }
12209 
StringToMultiListQualDialog(DialoG d,Pointer data)12210 static void StringToMultiListQualDialog (DialoG d, Pointer data)
12211 {
12212   MultiListQualDlgPtr dlg;
12213   CharPtr             val, cp, other_text = NULL;
12214   Int2                i;
12215 
12216   dlg = (MultiListQualDlgPtr) GetObjectExtra (d);
12217   if (dlg == NULL) return;
12218   for (i = 1; dlg->val_list[i] != NULL; i++) {
12219     SetStatus (dlg->button_list[i - 1], FALSE);
12220   }
12221   SetStatus (dlg->button_list[i - 1], FALSE);
12222   SetTitle (dlg->last_txt, "");
12223 
12224   val = (CharPtr) data;
12225   if (StringHasNoText (val)) {
12226     return;
12227   }
12228 
12229   if (*val == '(' && val[StringLen(val) - 1] == ')') {
12230     /* parentheses list */
12231     val++;
12232     cp = StringChr (val, ',');
12233     while (cp != NULL) {
12234       *cp = 0;
12235       ApplyOneValToMultiListQualDialog (dlg, val, &other_text);
12236       *cp = ',';
12237       val = cp + 1;
12238       while (isspace(*val)) {
12239         val++;
12240       }
12241       cp = StringChr (val, ',');
12242     }
12243     val[StringLen(val) - 1] = 0;
12244     ApplyOneValToMultiListQualDialog (dlg, val, &other_text);
12245     val[StringLen(val) - 1] = ')';
12246   } else {
12247     ApplyOneValToMultiListQualDialog (dlg, val, &other_text);
12248   }
12249   if (dlg->last_txt != NULL)
12250   {
12251     if (!StringHasNoText (other_text)) {
12252       SetTitle (dlg->last_txt, other_text);
12253       SetStatus (dlg->button_list[i - 1], TRUE);
12254       Enable (dlg->last_txt);
12255     } else {
12256       Disable (dlg->last_txt);
12257     }
12258   }
12259   other_text = MemFree (other_text);
12260 }
12261 
MultiListQualDialogToString(DialoG d)12262 static Pointer MultiListQualDialogToString (DialoG d)
12263 {
12264   MultiListQualDlgPtr dlg;
12265   CharPtr             val = NULL, tmp;
12266   Int2                i;
12267 
12268   dlg = (MultiListQualDlgPtr) GetObjectExtra (d);
12269   if (dlg == NULL) return NULL;
12270   for (i = 1; dlg->val_list[i] != NULL; i++) {
12271     if (GetStatus (dlg->button_list[i - 1])) {
12272       if (val == NULL) {
12273         val = StringSave (dlg->val_list[i]);
12274       } else {
12275         tmp = StringSave (dlg->val_list[i]);
12276         val = CombineSplitGBQual (val, tmp);
12277       }
12278     }
12279   }
12280   if (dlg->last_txt != NULL
12281       && GetStatus (dlg->button_list[i - 1])
12282       && !TextHasNoText (dlg->last_txt)) {
12283     if (val == NULL) {
12284       val = SaveStringFromText (dlg->last_txt);
12285     } else {
12286       tmp = SaveStringFromText (dlg->last_txt);
12287       val = CombineSplitGBQual (val, tmp);
12288       tmp = MemFree (tmp);
12289     }
12290   }
12291   return val;
12292 }
12293 
MultiListQualDialog(GrouP h,SeqEntryPtr sep,CharPtr name,CharPtr PNTR list,Boolean allow_not_in_list,TaglistCallback tlp_callback,Pointer callback_data)12294 static DialoG MultiListQualDialog (GrouP h, SeqEntryPtr sep, CharPtr name, CharPtr PNTR list,
12295                                    Boolean allow_not_in_list,
12296                                    TaglistCallback tlp_callback,
12297                                    Pointer callback_data)
12298 {
12299   MultiListQualDlgPtr dlg;
12300   GrouP           p, g, last_button = NULL;
12301   Int2            i, num_buttons = 1; /* start with one, for the type-in wildcard value */
12302 
12303   p = HiddenGroup (h, -1, 0, NULL);
12304   dlg = (MultiListQualDlgPtr) MemNew (sizeof(MultiListQualDlgData));
12305 
12306   SetObjectExtra (p, dlg, CleanupMultiListQualDlg);
12307   dlg->dialog = (DialoG) p;
12308   dlg->todialog = StringToMultiListQualDialog;
12309   dlg->fromdialog = MultiListQualDialogToString;
12310   dlg->testdialog = NULL;
12311   dlg->tlp_callback = tlp_callback;
12312   dlg->callback_data = callback_data;
12313   dlg->val_list = list;
12314 
12315   /* start with 1, skip blank at start of list */
12316   for (i = 1; dlg->val_list[i] != NULL; i++) {
12317     num_buttons ++;
12318   }
12319 
12320   dlg->button_list = (ButtoN *) MemNew (num_buttons * sizeof (ButtoN));
12321 
12322   g = HiddenGroup (p, 4, 0, NULL);
12323   for (i = 1; dlg->val_list [i] != NULL; i++) {
12324     dlg->button_list[i - 1] = CheckBox (g, dlg->val_list[i], ChangeGBQualEditorButton);
12325     SetObjectExtra (dlg->button_list[i - 1], dlg, NULL);
12326   }
12327   if (allow_not_in_list)
12328   {
12329     last_button = HiddenGroup (p, 2, 0, NULL);
12330     dlg->button_list[i - 1] = CheckBox (last_button, "", CheckMultiListLast);
12331     SetObjectExtra (dlg->button_list[i - 1], dlg, NULL);
12332     dlg->last_txt = DialogText (last_button, "", 20, ChangeGBQualEditorText);
12333     SetObjectExtra (dlg->last_txt, dlg, NULL);
12334     Disable (dlg->last_txt);
12335   }
12336 
12337   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) last_button, NULL);
12338 
12339   return (DialoG) p;
12340 }
12341 
ParseMultiListQualOk(CharPtr val)12342 static Boolean ParseMultiListQualOk (CharPtr val)
12343 {
12344   return TRUE;
12345 }
12346 
12347 CharPtr codon_start_values[] = {" ", "1", "2", "3", NULL};
CodonStartQualDialog(GrouP h,SeqEntryPtr sep,CharPtr name,TaglistCallback tlp_callback,Pointer callback_data)12348 static DialoG CodonStartQualDialog (GrouP h, SeqEntryPtr sep, CharPtr name,
12349                                     TaglistCallback tlp_callback,
12350                                     Pointer callback_data)
12351 
12352 {
12353   return SimpleListQualDialog (h, sep, name, codon_start_values, tlp_callback, callback_data);
12354 }
ParseCodonStartOk(CharPtr val)12355 static Boolean ParseCodonStartOk (CharPtr val)
12356 {
12357   if (GetListNum (val, codon_start_values) > -1) {
12358     return TRUE;
12359   } else {
12360     return FALSE;
12361   }
12362 }
12363 
12364 CharPtr mol_type_values[] = {" ", "genomic DNA", "genomic RNA", "mRNA", "tRNA", "rRNA",
12365                 "snoRNA", "snRNA", "scRNA", "pre-RNA", "other RNA",
12366                 "other DNA", "viral cRNA", "unassigned DNA", "unassigned RNA", NULL};
MolTypeQualDialog(GrouP h,SeqEntryPtr sep,CharPtr name,TaglistCallback tlp_callback,Pointer callback_data)12367 static DialoG MolTypeQualDialog (GrouP h, SeqEntryPtr sep, CharPtr name,
12368                                  TaglistCallback tlp_callback,
12369                                  Pointer callback_data)
12370 {
12371   return SimpleListQualDialog (h, sep, name, mol_type_values, tlp_callback, callback_data);
12372 }
ParseMolTypeOk(CharPtr val)12373 static Boolean ParseMolTypeOk (CharPtr val)
12374 {
12375   if (GetListNum (val, mol_type_values) > -1) {
12376     return TRUE;
12377   } else {
12378     return FALSE;
12379   }
12380 }
12381 
12382 CharPtr organelle_values[] = {" ", "mitochondrion", "nucleomorph", "plastid",
12383                               "mitochondrion:kinetoplast",
12384                               "plastid:chloroplast", "plastid:apicoplast",
12385                               "plastid:chromoplast", "plastid:cyanelle",
12386                               "plastid:leucoplast", "plastid:proplastid", NULL};
OrganelleQualDialog(GrouP h,SeqEntryPtr sep,CharPtr name,TaglistCallback tlp_callback,Pointer callback_data)12387 static DialoG OrganelleQualDialog (GrouP h, SeqEntryPtr sep, CharPtr name,
12388                                    TaglistCallback tlp_callback,
12389                                    Pointer callback_data)
12390 {
12391   return SimpleListQualDialog (h, sep, name, organelle_values, tlp_callback, callback_data);
12392 }
ParseOrganelleOk(CharPtr val)12393 static Boolean ParseOrganelleOk (CharPtr val)
12394 {
12395   if (GetListNum (val, organelle_values) > -1) {
12396     return TRUE;
12397   } else {
12398     return FALSE;
12399   }
12400 }
12401 
12402 CharPtr rpt_type_values[] = {
12403   " ",
12404   "tandem",
12405   "inverted",
12406   "flanking",
12407   "nested",
12408   "terminal",
12409   "direct",
12410   "dispersed",
12411   "long_terminal_repeat",
12412   "non_LTR_retrotransposon_polymeric_tract",
12413   "X_element_combinatorial_repeat",
12414   "Y_prime_element",
12415   "telomeric_repeat",
12416   "centromeric_repeat",
12417   "engineered_foreign_repetitive_element",
12418   "other",
12419   NULL
12420 };
RptTypeQualDialog(GrouP h,SeqEntryPtr sep,CharPtr name,TaglistCallback tlp_callback,Pointer callback_data)12421 static DialoG RptTypeQualDialog (GrouP h, SeqEntryPtr sep, CharPtr name,
12422                                  TaglistCallback tlp_callback,
12423                                  Pointer callback_data)
12424 {
12425 
12426 
12427   return MultiListQualDialog (h, sep, name, rpt_type_values, FALSE, tlp_callback, callback_data);
12428 }
12429 
ParseRptTypeOk(CharPtr val)12430 static Boolean ParseRptTypeOk (CharPtr val)
12431 {
12432   CharPtr cpy, cp, check;
12433   Boolean rval = TRUE;
12434 
12435   if (StringHasNoText (val))
12436   {
12437     return TRUE;
12438   }
12439   else if (val[0] == '(' && val[StringLen(val) - 1] == ')')
12440   {
12441     cpy = StringSave (val + 1);
12442     cpy [StringLen (cpy) - 1] = 0;
12443     check = cpy;
12444     cp = StringChr (cpy, ',');
12445     while (cp != NULL && rval)
12446     {
12447       *cp = 0;
12448       TrimSpacesAroundString (check);
12449       if (GetListNum (check, rpt_type_values) < 0)
12450       {
12451         rval = FALSE;
12452       }
12453       check = cp + 1;
12454       cp = StringChr (check, ',');
12455     }
12456     if (rval)
12457     {
12458       TrimSpacesAroundString (check);
12459       if (GetListNum (check, rpt_type_values) < 0)
12460       {
12461         rval = FALSE;
12462       }
12463     }
12464     cpy = MemFree (cpy);
12465   }
12466   else if (GetListNum (val, rpt_type_values) < 0)
12467   {
12468     rval = FALSE;
12469   }
12470   return rval;
12471 }
12472 
12473 CharPtr direction_values[] = {" ", "LEFT", "RIGHT", "BOTH", NULL};
DirectionQualDialog(GrouP h,SeqEntryPtr sep,CharPtr name,TaglistCallback tlp_callback,Pointer callback_data)12474 static DialoG DirectionQualDialog (GrouP h, SeqEntryPtr sep, CharPtr name,
12475                                  TaglistCallback tlp_callback,
12476                                  Pointer callback_data)
12477 {
12478   return SimpleListQualDialog (h, sep, name, direction_values, tlp_callback, callback_data);
12479 }
ParseDirectionOk(CharPtr val)12480 static Boolean ParseDirectionOk (CharPtr val)
12481 {
12482   if (GetListNum (val, direction_values) > -1) {
12483     return TRUE;
12484   } else {
12485     return FALSE;
12486   }
12487 }
12488 
12489 typedef DialoG (*BuildQualEditorDialog) PROTO ((GrouP, SeqEntryPtr, CharPtr,
12490                                                 TaglistCallback, Pointer));
12491 typedef void (*CopyTextToEditor) PROTO ((DialoG, CharPtr));
12492 
12493 typedef struct gbqualeditlist {
12494   CharPtr               name;
12495   BuildQualEditorDialog build_dlg;
12496   ParseOK               parse_ok;
12497   CopyTextToEditor      copy_txt;
12498 } GBQualEditListData, PNTR GBQualEditListPtr;
12499 
12500 GBQualEditListData gbqual_edit_list[] = {
12501   {"chloroplast",              TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12502   {"chromoplast",              TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12503   {"codon_start",              CodonStartQualDialog,        ParseCodonStartOk,       NULL },
12504   {"collection_date",          CollectionDateDialog,        ParseCollectionDateOk,   NULL },
12505   {"cyanelle",                 TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12506   {"direction",                DirectionQualDialog,         ParseDirectionOk,        NULL },
12507   {"germline",                 TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12508   {"kinetoplast",              TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12509   {"macronuclear",             TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12510   {"mitochondrion",            TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12511   {"mobile_element",           CreateMobileElementDialog,   ParseMobileElementOk,    CopyTextToControlPlusFreeDialog },
12512   {"mobile_element_type",      CreateMobileElementDialog,   ParseMobileElementOk,    CopyTextToControlPlusFreeDialog },
12513   {"mol_type",                 MolTypeQualDialog,           ParseMolTypeOk,          NULL },
12514   {"organelle",                OrganelleQualDialog,         ParseOrganelleOk,        NULL },
12515   {"partial",                  TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12516   {"proviral",                 TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12517   {"pseudo",                   TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12518   {"rearranged",               TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12519   {"rpt_type",                 RptTypeQualDialog,           ParseRptTypeOk,          NULL },
12520   {"rpt_unit_range",           CreateRptUnitRangeDialog,    ParseRptUnitRangeOk,     NULL } ,
12521   {"satellite",                CreateSatelliteDialog,       ParseSatelliteOk,        CopyTextToControlPlusFreeDialog },
12522   {"virion",                   TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12523   {"focus",                    TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12524   {"transgenic",               TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12525   {"environmental_sample",     TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12526   {"ribosomal_slippage",       TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12527   {"trans_splicing",           TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12528   {"metagenomic",              TrueFalseDialog,             ParseTrueFalseOk,        NULL },
12529   {"regulatory_class",         CreateRegulatoryClassDialog, ParseRegulatoryClassOk,  CopyTextToControlPlusFreeDialog },
12530   {"regulatory_class_type",    CreateRegulatoryClassDialog, ParseRegulatoryClassOk,  CopyTextToControlPlusFreeDialog },
12531   {"recombination_class",      CreateRecombClassDialog,     ParseRecombClassOk,      CopyTextToControlPlusFreeDialog },
12532   {"recombination_class_type", CreateRecombClassDialog,     ParseRecombClassOk,      CopyTextToControlPlusFreeDialog },
12533   {NULL, NULL, NULL}};
12534 
12535 
12536 typedef struct singlegbqualedit {
12537   DIALOG_MESSAGE_BLOCK
12538   TaglistCallback tlp_callback;
12539   Pointer callback_data;
12540   DialoG editor;
12541   TexT   txt;
12542   GrouP  choice_grp;
12543   ButtoN            use_editor;
12544   ButtoN            use_text;
12545   ButtoN            copy_text;
12546   GBQualEditListPtr edit_list;
12547   CharPtr           name;
12548   Boolean           force_string;
12549 } SingleGBQualEditData, PNTR SingleGBQualEditPtr;
12550 
ChangeSingleQualEdit(GrouP g)12551 static void ChangeSingleQualEdit (GrouP g)
12552 {
12553   SingleGBQualEditPtr dlg;
12554 
12555   dlg = (SingleGBQualEditPtr) GetObjectExtra (g);
12556   if (dlg != NULL) {
12557     if (GetValue (dlg->choice_grp) == 1) {
12558       SafeEnable (dlg->editor);
12559       Disable (dlg->txt);
12560     } else {
12561       SetValue (dlg->choice_grp, 2);
12562       SafeDisable (dlg->editor);
12563       Enable (dlg->txt);
12564     }
12565     if (dlg->tlp_callback != NULL) {
12566       (dlg->tlp_callback) (dlg->callback_data);
12567     }
12568   }
12569 }
12570 
StringToSingleGBQualEditDialog(DialoG d,Pointer data)12571 static void StringToSingleGBQualEditDialog (DialoG d, Pointer data)
12572 {
12573   SingleGBQualEditPtr dlg;
12574   CharPtr             val;
12575 
12576   dlg = (SingleGBQualEditPtr) GetObjectExtra (d);
12577   if (dlg == NULL) return;
12578 
12579   val = (CharPtr) data;
12580 
12581   if (StringHasNoText (val) || (!dlg->force_string && dlg->edit_list != NULL && (dlg->edit_list->parse_ok(val)))) {
12582     SetTitle (dlg->txt, "");
12583     if (dlg->choice_grp != NULL) {
12584       SetValue (dlg->choice_grp, 1);
12585       Hide (dlg->use_editor);
12586       Hide (dlg->use_text);
12587       Hide (dlg->txt);
12588       Hide (dlg->copy_text);
12589       PointerToDialog (dlg->editor, val);
12590       Enable (dlg->editor);
12591       Disable (dlg->txt);
12592     }
12593   } else {
12594     SetTitle (dlg->txt, val);
12595     if (dlg->choice_grp != NULL) {
12596       SetValue (dlg->choice_grp, 2);
12597       Show (dlg->use_editor);
12598       Show (dlg->use_text);
12599       Show (dlg->txt);
12600       Show (dlg->copy_text);
12601       PointerToDialog (dlg->editor, NULL);
12602       Enable (dlg->txt);
12603       Disable (dlg->editor);
12604     }
12605   }
12606   if (dlg->tlp_callback != NULL) {
12607     (dlg->tlp_callback)(dlg->callback_data);
12608   }
12609 }
12610 
SingleGBQualEditDialogToString(DialoG d)12611 static Pointer SingleGBQualEditDialogToString (DialoG d)
12612 {
12613   SingleGBQualEditPtr dlg;
12614   CharPtr             val;
12615 
12616   dlg = (SingleGBQualEditPtr) GetObjectExtra (d);
12617   if (dlg == NULL) return NULL;
12618   if (dlg->choice_grp == NULL || GetValue (dlg->choice_grp) == 2) {
12619     val = SaveStringFromText (dlg->txt);
12620   } else {
12621     val = DialogToPointer (dlg->editor);
12622   }
12623 
12624   return val;
12625 }
12626 
GBQualEditDialogMessage(DialoG d,Int2 mssg)12627 static void GBQualEditDialogMessage (DialoG d, Int2 mssg)
12628 
12629 {
12630   SingleGBQualEditPtr dlg;
12631 
12632   dlg = (SingleGBQualEditPtr) GetObjectExtra (d);
12633   if (dlg != NULL) {
12634     if (mssg == VIB_MSG_INIT
12635         || mssg == VIB_MSG_ENTER) {
12636       if (dlg->choice_grp == NULL || GetValue (dlg->choice_grp) == 2) {
12637         Select (dlg->txt);
12638       } else {
12639         Select (dlg->editor);
12640       }
12641     }
12642   }
12643 }
12644 
GBQualEditDialogCopyText(ButtoN b)12645 static void GBQualEditDialogCopyText (ButtoN b)
12646 {
12647   SingleGBQualEditPtr dlg;
12648   CharPtr             txt;
12649 
12650   dlg = (SingleGBQualEditPtr) GetObjectExtra (b);
12651   if (dlg != NULL && dlg->edit_list != NULL && dlg->edit_list->copy_txt != NULL) {
12652     txt = SaveStringFromText (dlg->txt);
12653     (dlg->edit_list->copy_txt)(dlg->editor, txt);
12654     txt = MemFree (txt);
12655   }
12656 }
12657 
CreateSingleGBQualEditDialog(GrouP h,SeqEntryPtr sep,CharPtr name,Boolean force_string,TaglistCallback tlp_callback,Pointer callback_data)12658 static DialoG CreateSingleGBQualEditDialog (GrouP h, SeqEntryPtr sep, CharPtr name,
12659                                             Boolean force_string,
12660                                             TaglistCallback tlp_callback,
12661                                             Pointer callback_data)
12662 {
12663   SingleGBQualEditPtr dlg;
12664   GrouP           p;
12665   Int4            i;
12666 
12667   p = HiddenGroup (h, 2, 0, NULL);
12668   SetGroupSpacing (p, 10, 10);
12669   dlg = (SingleGBQualEditPtr) MemNew (sizeof(SingleGBQualEditData));
12670 
12671   SetObjectExtra (p, dlg, StdCleanupExtraProc);
12672   dlg->dialog = (DialoG) p;
12673   dlg->todialog = StringToSingleGBQualEditDialog;
12674   dlg->fromdialog = SingleGBQualEditDialogToString;
12675   dlg->testdialog = NULL;
12676   dlg->dialogmessage = GBQualEditDialogMessage;
12677   dlg->tlp_callback = tlp_callback;
12678   dlg->callback_data = callback_data;
12679   dlg->force_string = force_string;
12680 
12681   dlg->name = name;
12682   dlg->edit_list = NULL;
12683   for (i = 0; gbqual_edit_list[i].name != NULL && dlg->edit_list == NULL; i++) {
12684     if (StringICmp (gbqual_edit_list[i].name, name) == 0) {
12685       dlg->edit_list = gbqual_edit_list + i;
12686     }
12687   }
12688 
12689   dlg->copy_text = NULL;
12690 
12691   if (dlg->edit_list == NULL || dlg->edit_list->build_dlg == NULL || force_string) {
12692     dlg->txt = DialogText (p, "", 20, ChangeGBQualEditorText);
12693     SetObjectExtra (dlg->txt, dlg, NULL);
12694     dlg->editor = NULL;
12695     dlg->choice_grp = NULL;
12696   } else {
12697     dlg->choice_grp = HiddenGroup (p, 0, 2, ChangeSingleQualEdit);
12698     SetObjectExtra (dlg->choice_grp, dlg, NULL);
12699     dlg->use_editor = RadioButton (dlg->choice_grp, "");
12700     dlg->use_text = RadioButton (dlg->choice_grp, "");
12701     dlg->editor = (dlg->edit_list->build_dlg) (dlg->choice_grp, sep, name, tlp_callback, callback_data);
12702     dlg->txt = DialogText (dlg->choice_grp, "", 20, ChangeGBQualEditorText);
12703     SetObjectExtra (dlg->txt, dlg, NULL);
12704     SetValue (dlg->choice_grp, 1);
12705     if (dlg->edit_list->copy_txt != NULL) {
12706       dlg->copy_text = PushButton (dlg->choice_grp, "Copy Text", GBQualEditDialogCopyText);
12707       SetObjectExtra (dlg->copy_text, dlg, NULL);
12708     }
12709 //    AlignObjects (ALIGN_LOWER, (HANDLE) dlg->use_text, (HANDLE) dlg->txt, NULL);
12710     AlignObjects (ALIGN_LOWER, (HANDLE) dlg->txt, (HANDLE) dlg->use_text, NULL);
12711     ChangeSingleQualEdit (dlg->choice_grp);
12712   }
12713 
12714   return (DialoG) p;
12715 }
12716 
12717 typedef struct newfieldpage {
12718   DIALOG_MESSAGE_BLOCK
12719   Int2               numfields;
12720   DialoG             PNTR editors;
12721 
12722   GBQualPtr          new_gbq;
12723   Uint1              subtype;
12724   Boolean            allowProductGBQual;
12725   Int2               last_viewed;
12726 } NewFieldPage, PNTR NewFieldPagePtr;
12727 
CleanupNewFieldsPage(GraphiC g,VoidPtr data)12728 static void CleanupNewFieldsPage (GraphiC g, VoidPtr data)
12729 
12730 {
12731   NewFieldPagePtr  fpf;
12732 
12733   fpf = (NewFieldPagePtr) data;
12734   if (fpf != NULL) {
12735     MemFree (fpf->editors);
12736     fpf->new_gbq = GBQualFree (fpf->new_gbq);
12737   }
12738   MemFree (data);
12739 }
12740 
GetDisplayQualName(CharPtr qual_name,Boolean is_legal)12741 static CharPtr GetDisplayQualName (CharPtr qual_name, Boolean is_legal)
12742 {
12743   CharPtr display_name;
12744 
12745   if (is_legal) {
12746     display_name = StringSave (qual_name);
12747   } else {
12748     display_name = (CharPtr) MemNew (sizeof (Char) * (StringLen (qual_name) + 2));
12749     sprintf (display_name, "*%s", qual_name);
12750   }
12751   return display_name;
12752 }
12753 
QualNamesMatch(CharPtr qual_name1,CharPtr qual_name2)12754 static Boolean QualNamesMatch (CharPtr qual_name1, CharPtr qual_name2)
12755 {
12756   if (StringICmp (qual_name1, qual_name2) == 0) {
12757     return TRUE;
12758   } else if (qual_name1 != NULL
12759              && *(qual_name1) == '*'
12760              && StringICmp (qual_name1 + 1, qual_name2) == 0) {
12761     return TRUE;
12762   } else if (qual_name2 != NULL
12763              && *qual_name2 == '*'
12764              && StringICmp (qual_name1, qual_name2 + 1) == 0) {
12765     return TRUE;
12766   } else {
12767     return FALSE;
12768   }
12769 }
12770 
IsCombinableQual(Int2 qual)12771 static Boolean IsCombinableQual (Int2 qual)
12772 {
12773   Boolean   combine_qual = FALSE;
12774 
12775   if (qual == GBQUAL_rpt_type
12776       || qual == GBQUAL_rpt_unit
12777       || qual == GBQUAL_rpt_unit_range
12778       || qual == GBQUAL_rpt_unit_seq
12779       || qual == GBQUAL_replace
12780       || qual == GBQUAL_compare
12781       || qual == GBQUAL_old_locus_tag
12782       || qual == GBQUAL_usedin) {
12783     combine_qual = TRUE;
12784   }
12785   return combine_qual;
12786 }
12787 
AddTemporaryGBQual(GBQualPtr PNTR gbq_list,CharPtr qual_name,GBQualPtr gbq_feat,Boolean is_legal)12788 static void AddTemporaryGBQual (GBQualPtr PNTR gbq_list, CharPtr qual_name, GBQualPtr gbq_feat, Boolean is_legal)
12789 {
12790   Int2 qual;
12791   GBQualPtr gbq_last = NULL;
12792   GBQualPtr gbq_new = NULL;
12793   Boolean   found = FALSE;
12794   Boolean   combine_qual = FALSE;
12795   CharPtr   blank_val = "\"\"";
12796 
12797   if (gbq_list == NULL) return;
12798 
12799   gbq_last = *gbq_list;
12800   while (gbq_last != NULL && gbq_last->next != NULL) {
12801     if (QualNamesMatch (gbq_last->qual, qual_name)) {
12802       /* already added */
12803       return;
12804     }
12805     gbq_last = gbq_last->next;
12806   }
12807   if (gbq_last != NULL && QualNamesMatch (gbq_last->qual, qual_name)) {
12808     /* already added */
12809     return;
12810   }
12811 
12812   /* add value.  If none in feature, if true/false, add TRUE or FALSE, else use blank. */
12813   qual = GBQualNameValid (qual_name);
12814 
12815   combine_qual = IsCombinableQual (qual);
12816 
12817   while (gbq_feat != NULL) {
12818     if (StringICmp (qual_name, gbq_feat->qual) == 0) {
12819       if (StringHasNoText (gbq_feat->val)) {
12820         if (qual > -1 && ParFlat_GBQual_names [qual].gbclass == Class_none && !found) {
12821           /* if this is a true-false, only add one qualifier */
12822           gbq_new = GBQualNew ();
12823           gbq_new->qual = GetDisplayQualName (qual_name, is_legal);
12824           gbq_new->val = StringSave ("TRUE");
12825           if (gbq_last == NULL) {
12826             *gbq_list = gbq_new;
12827           } else {
12828             gbq_last->next = gbq_new;
12829           }
12830           gbq_last = gbq_new;
12831           found = TRUE;
12832         } else if (qual == GBQUAL_replace) {
12833           /* save blank values */
12834           gbq_new = NULL;
12835           if (found && combine_qual) {
12836             gbq_new = *gbq_list;
12837             while (gbq_new != NULL && !QualNamesMatch (gbq_feat->qual, gbq_new->qual)) {
12838               gbq_new = gbq_new->next;
12839             }
12840           }
12841           if (gbq_new == NULL) {
12842             /* make new qualifier */
12843             gbq_new = GBQualNew ();
12844             gbq_new->qual = GetDisplayQualName (qual_name, is_legal);
12845             gbq_new->val = StringSave (blank_val);
12846             /* add to list */
12847             if (gbq_last == NULL) {
12848               *gbq_list = gbq_new;
12849             } else {
12850               gbq_last->next = gbq_new;
12851             }
12852             gbq_last = gbq_new;
12853           } else {
12854             /* combine with previous value */
12855             gbq_new->val = CombineSplitGBQual (gbq_new->val, blank_val);
12856           }
12857           found = TRUE;
12858         } else {
12859           /* if not true-false or already have true-false, we'll just be adding a blank value later */
12860           /* so do nothing here */
12861         }
12862       } else {
12863         gbq_new = NULL;
12864         if (found && combine_qual) {
12865           gbq_new = *gbq_list;
12866           while (gbq_new != NULL && !QualNamesMatch (gbq_feat->qual, gbq_new->qual)) {
12867             gbq_new = gbq_new->next;
12868           }
12869         }
12870         if (gbq_new == NULL) {
12871           /* make new qualifier */
12872           gbq_new = GBQualNew ();
12873           gbq_new->qual = GetDisplayQualName (qual_name, is_legal);
12874           gbq_new->val = StringSave (gbq_feat->val);
12875           /* add to list */
12876           if (gbq_last == NULL) {
12877             *gbq_list = gbq_new;
12878           } else {
12879             gbq_last->next = gbq_new;
12880           }
12881           gbq_last = gbq_new;
12882         } else {
12883           /* combine with previous value */
12884           gbq_new->val = CombineSplitGBQual (gbq_new->val, gbq_feat->val);
12885         }
12886         found = TRUE;
12887       }
12888     }
12889     gbq_feat = gbq_feat->next;
12890   }
12891 
12892   if (!found) {
12893     gbq_new = GBQualNew ();
12894     gbq_new->qual = GetDisplayQualName (qual_name, is_legal);
12895     if (qual > -1 && ParFlat_GBQual_names [qual].gbclass == Class_none) {
12896       gbq_new->val = StringSave ("FALSE");
12897     } else {
12898       gbq_new->val = StringSave ("");
12899     }
12900     if (gbq_last == NULL) {
12901       *gbq_list = gbq_new;
12902     } else {
12903       gbq_last->next = gbq_new;
12904     }
12905   }
12906 }
12907 
IsRarelyUsed(Int2 qual)12908 static Boolean IsRarelyUsed (Int2 qual)
12909 {
12910   if (qual == GBQUAL_allele
12911       || qual == GBQUAL_function
12912       || qual == GBQUAL_map
12913       || qual == GBQUAL_standard_name
12914       || qual == GBQUAL_old_locus_tag) {
12915     return TRUE;
12916   } else {
12917     return FALSE;
12918   }
12919 }
12920 
NewDialogToImportFields(DialoG d)12921 static Pointer NewDialogToImportFields (DialoG d)
12922 {
12923   NewFieldPagePtr fpf;
12924   GBQualPtr       gbq_list = NULL, gbq_last = NULL, gbq_new, gbq_it;
12925   Int2            qual, i;
12926   CharPtr         val, qual_name;
12927 
12928   fpf = (NewFieldPagePtr) GetObjectExtra (d);
12929   if (fpf == NULL) return NULL;
12930 
12931   for (gbq_it = fpf->new_gbq, i = 0; gbq_it != NULL; gbq_it = gbq_it->next, i++) {
12932     gbq_it->val = MemFree (gbq_it->val);
12933     gbq_it->val = DialogToPointer (fpf->editors[i]);
12934   }
12935 
12936   for (gbq_it = fpf->new_gbq; gbq_it != NULL; gbq_it = gbq_it->next) {
12937     if (StringHasNoText (gbq_it->val)) {
12938       continue;
12939     }
12940     qual_name = gbq_it->qual;
12941     if (qual_name != NULL && *qual_name == '*') {
12942       qual_name++;
12943     }
12944     qual = GBQualNameValid (qual_name);
12945 
12946     val = gbq_it->val;
12947     if (qual > -1 && ParFlat_GBQual_names [qual].gbclass == Class_none) {
12948       if (StringICmp (val, "TRUE") == 0) {
12949         /* don't put "true" in qual, just use empty string */
12950         val = "";
12951       } else if (StringICmp (val, "FALSE") == 0) {
12952         /* don't add FALSE qual */
12953         continue;
12954       }
12955       /* any other values, add as they are */
12956     }
12957 
12958     gbq_new = GBQualNew();
12959     gbq_new->qual = StringSave (qual_name);
12960     gbq_new->val = StringSave (val);
12961     if (gbq_last == NULL) {
12962       gbq_list = gbq_new;
12963     } else {
12964       gbq_last->next = gbq_new;
12965     }
12966     gbq_last = gbq_new;
12967   }
12968   return (Pointer) gbq_list;
12969 }
12970 
12971 static void
AddMandatoryAndOptionalQuals(CharPtr name,NewFieldPagePtr fpf,GBQualPtr gbq,Boolean use_rarely_used)12972 AddMandatoryAndOptionalQuals
12973 (CharPtr         name,
12974  NewFieldPagePtr fpf,
12975  GBQualPtr       gbq,
12976  Boolean         use_rarely_used)
12977 {
12978   Int2 index, i, qual;
12979   SematicFeatPtr  sefp;
12980 
12981   if (name == NULL) return;
12982 
12983   index = GBFeatKeyNameValid (&name, FALSE);
12984   if (index < 0) return;
12985 
12986   sefp = &(ParFlat_GBFeat [index]);
12987   /* add mandatory quals first */
12988   for (i = 0; i < sefp->mand_num; i++) {
12989     qual = sefp->mand_qual [i];
12990     if (qual > -1
12991         && ShouldBeAGBQual (fpf->subtype, qual, fpf->allowProductGBQual)
12992         && ((use_rarely_used && IsRarelyUsed (qual))
12993             || (!use_rarely_used && ! IsRarelyUsed (qual)))) {
12994       AddTemporaryGBQual (&(fpf->new_gbq), ParFlat_GBQual_names [qual].name, gbq, TRUE);
12995     }
12996   }
12997   /* add optional quals next */
12998   for (i = 0; i < sefp->opt_num; i++) {
12999     qual = sefp->opt_qual [i];
13000     if (qual > -1
13001         && ShouldBeAGBQual (fpf->subtype, qual, fpf->allowProductGBQual)
13002         && ((use_rarely_used && IsRarelyUsed (qual))
13003             || (!use_rarely_used && ! IsRarelyUsed (qual)))) {
13004       AddTemporaryGBQual (&(fpf->new_gbq), ParFlat_GBQual_names [qual].name, gbq, TRUE);
13005     }
13006   }
13007 }
13008 
CopyGBQualList(GBQualPtr origgbq)13009 static GBQualPtr CopyGBQualList (GBQualPtr origgbq)
13010 
13011 {
13012   GBQualPtr  gbq, gbq_new, head = NULL, last = NULL;
13013 
13014   for (gbq = origgbq; gbq != NULL; gbq = gbq->next) {
13015     gbq_new = GBQualNew ();
13016     gbq_new->qual = StringSave (gbq->qual);
13017     gbq_new->val = StringSave (gbq->val);
13018     if (head == NULL) {
13019       head = gbq_new;
13020     }
13021     if (last != NULL) {
13022       last->next = gbq_new;
13023     }
13024     last = gbq_new;
13025   }
13026 
13027   return head;
13028 }
13029 
13030 
ChangeRptTypeForSatellite(Pointer data)13031 static void ChangeRptTypeForSatellite (Pointer data)
13032 {
13033   NewFieldPagePtr fpf;
13034   GBQualPtr       gbq_it;
13035   Int4            i;
13036   Int4            rpt_type_num = -1;
13037   Boolean         tandem = FALSE, found_satellite = FALSE;
13038   CharPtr         val, new_val, src;
13039   CharPtr         fmt = "(tandem,%s)";
13040 
13041   fpf = (NewFieldPagePtr) data;
13042 
13043   if (fpf == NULL) {
13044     return;
13045   }
13046 
13047   /* find satellite qualifier, get type */
13048   for (gbq_it = fpf->new_gbq, i = 0; gbq_it != NULL; gbq_it = gbq_it->next, i++) {
13049     if (StringICmp (gbq_it->qual, "satellite") == 0) {
13050       val = DialogToPointer (fpf->editors[i]);
13051       if (StringCmp (val, "microsatellite") == 0
13052           || StringCmp (val, "minisatellite") == 0
13053           || StringNICmp (val, "microsatellite:", 15) == 0
13054           || StringNICmp (val, "minisatellite:", 14) == 0) {
13055         tandem = TRUE;
13056       }
13057       val = MemFree (val);
13058       found_satellite = TRUE;
13059     } else if (StringICmp (gbq_it->qual, "rpt_type") == 0) {
13060       rpt_type_num = i;
13061     }
13062   }
13063 
13064   /* now set rpt_type */
13065   if (found_satellite && rpt_type_num > -1) {
13066     val = DialogToPointer (fpf->editors[rpt_type_num]);
13067 
13068     if (tandem) {
13069       if (StringISearch (val, "tandem") == NULL) {
13070         /* add tandem */
13071         if (StringHasNoText (val)) {
13072           PointerToDialog (fpf->editors[rpt_type_num], "tandem");
13073         } else {
13074           src = StringChr (val, '}');
13075           if (src != NULL) {
13076             *src = 0;
13077           }
13078           src = val;
13079           if (*src == '{') {
13080             src++;
13081           }
13082           new_val = (CharPtr) MemNew (sizeof (Char) * (StringLen (src) + StringLen (fmt)));
13083           sprintf (new_val, fmt, src);
13084           PointerToDialog (fpf->editors[rpt_type_num], new_val);
13085           new_val = MemFree (new_val);
13086         }
13087       }
13088     }
13089 
13090     /* set */
13091 
13092     val = MemFree (val);
13093   }
13094 }
13095 
13096 
NewCreateImportFields(GrouP h,CharPtr name,SeqFeatPtr sfp,Boolean allowProductGBQual)13097 extern DialoG NewCreateImportFields (GrouP h, CharPtr name, SeqFeatPtr sfp, Boolean allowProductGBQual)
13098 {
13099   NewFieldPagePtr fpf;
13100   GrouP           g, g1, g2 = NULL;
13101   GBQualPtr       gbq = NULL, gbq_it;
13102   Int2            j;
13103   Int2            max;
13104   Int2            num = 0, num_legal = 0;
13105   GrouP           p;
13106   Int2            qual;
13107   Int2            wid;
13108   PrompT          ill_q = NULL;
13109   size_t          len;
13110   CharPtr         ptr;
13111 
13112   p = HiddenGroup (h, -1, 0, NULL);
13113   fpf = (NewFieldPagePtr) MemNew (sizeof (NewFieldPage));
13114   if (fpf != NULL) {
13115 
13116     SetObjectExtra (p, fpf, CleanupNewFieldsPage);
13117     fpf->dialog = (DialoG) p;
13118     fpf->todialog = NULL;
13119     fpf->fromdialog = NewDialogToImportFields;
13120     fpf->testdialog = NULL;
13121 
13122     fpf->allowProductGBQual = allowProductGBQual;
13123     if (sfp == NULL) {
13124       fpf->subtype = FEATDEF_ANY;
13125     } else {
13126       fpf->subtype = sfp->idx.subtype;
13127       gbq = CopyGBQualList (sfp->qual); /* make copy so it is not corrupted */
13128     }
13129 
13130     fpf->last_viewed = -1;
13131 
13132     /* create list of temporary GBQuals */
13133     /* list mandatory/optional quals that are not rarely used first */
13134     AddMandatoryAndOptionalQuals (name, fpf, gbq, FALSE);
13135 
13136     /* add rarely used quals here */
13137     AddMandatoryAndOptionalQuals (name, fpf, gbq, TRUE);
13138 
13139     /* count legal values - all others to be listed as simple strings */
13140     for (gbq_it = fpf->new_gbq; gbq_it != NULL; gbq_it = gbq_it->next) {
13141       num_legal++;
13142     }
13143 
13144     /* add legal added qualifiers next */
13145     gbq_it = gbq;
13146     while (gbq_it != NULL) {
13147       qual = GBQualNameValid (gbq_it->qual);
13148       if (qual > -1 && ShouldBeAGBQual (fpf->subtype, qual, fpf->allowProductGBQual)) {
13149         AddTemporaryGBQual (&(fpf->new_gbq), ParFlat_GBQual_names [qual].name, gbq, FALSE);
13150       }
13151       gbq_it = gbq_it->next;
13152     }
13153 
13154     /* add remaining qualifiers last */
13155     gbq_it = gbq;
13156     while (gbq_it != NULL) {
13157       if (!ShouldSuppressGBQual(fpf->subtype, gbq_it->qual)) {
13158         AddTemporaryGBQual (&(fpf->new_gbq), gbq_it->qual, gbq, FALSE);
13159       }
13160       gbq_it = gbq_it->next;
13161     }
13162 
13163     /* replace {} combined qual bookends with () */
13164     for (gbq_it = fpf->new_gbq; gbq_it != NULL; gbq_it = gbq_it->next) {
13165       ptr = gbq_it->val;
13166       if (StringHasNoText (ptr)) continue;
13167       len = StringLen (ptr);
13168       if (len > 2 && ptr [0] == '{' && ptr [len - 1] == '}') {
13169         ptr [0] = '(';
13170         ptr [len - 1] = ')';
13171       }
13172     }
13173 
13174     /* calculate maximum name width */
13175     SelectFont (systemFont);
13176     max = 0;
13177     for (gbq_it = fpf->new_gbq; gbq_it != NULL; gbq_it = gbq_it->next) {
13178       num++;
13179       wid = StringWidth (gbq_it->qual) + 2;
13180       if (wid > max) {
13181         max = wid;
13182       }
13183     }
13184     SelectFont (systemFont);
13185 
13186     fpf->numfields = num;
13187 
13188     if (num > 0) {
13189       g1 = HiddenGroup (p, 2, 0, NULL);
13190       g = g1;
13191       fpf->editors = MemNew (sizeof (DialoG) * (num + 1));
13192       for (gbq_it = fpf->new_gbq, j = 0; gbq_it != NULL; gbq_it = gbq_it->next) {
13193         if (j == num_legal) {
13194           ill_q = StaticPrompt (p, "*** Illegal Qualifiers ***", 0, dialogTextHeight, programFont, 'l');
13195           g2 = HiddenGroup (p, 2, 0, NULL);
13196           g = g2;
13197         }
13198         StaticPrompt (g, gbq_it->qual, 0, dialogTextHeight, programFont, 'l');
13199         fpf->editors[j] = CreateSingleGBQualEditDialog (g, NULL, gbq_it->qual,
13200                                                         j < num_legal ? FALSE : TRUE,
13201                                                         StringCmp (gbq_it->qual, "satellite") == 0 ? ChangeRptTypeForSatellite : NULL,
13202                                                         StringCmp (gbq_it->qual, "satellite") == 0 ? fpf : NULL);
13203         PointerToDialog (fpf->editors[j], gbq_it->val);
13204         j++;
13205       }
13206       AlignObjects (ALIGN_CENTER, (HANDLE) g1, (HANDLE) ill_q, (HANDLE) g2, NULL);
13207     } else {
13208       fpf->editors = NULL;
13209       StaticPrompt (p, "See Attributes page to set legal qualifiers for this feature.",
13210                     0, 0, programFont, 'c');
13211     }
13212   }
13213   GBQualFree (gbq); /* free copy */
13214   return (DialoG) p;
13215 }
13216 
13217 
13218 typedef struct specialcharacterdialog
13219 {
13220   TexT PNTR       text_list;
13221   ButtoN          accept_btn;
13222   Int4            num_chars;
13223   ValNodePtr      find_list;
13224 } SpecialCharacterDialogData, PNTR SpecialCharacterDialogPtr;
13225 
13226 
EnableSpecialCharacterAccept(TexT t)13227 static void EnableSpecialCharacterAccept (TexT t)
13228 {
13229   SpecialCharacterDialogPtr sd;
13230   Int4                      pos;
13231   CharPtr                   str;
13232   Boolean                   has_bad = FALSE;
13233 
13234   sd = (SpecialCharacterDialogPtr) GetObjectExtra (t);
13235   if (sd == NULL) return;
13236 
13237   for (pos = 0; pos < sd->num_chars && !has_bad; pos++)
13238   {
13239     str = SaveStringFromText (sd->text_list[pos]);
13240     SpecialCharFind (&str, NULL, &has_bad, NULL);
13241     str = MemFree (str);
13242   }
13243   if (has_bad)
13244   {
13245     Disable (sd->accept_btn);
13246   }
13247   else
13248   {
13249     Enable (sd->accept_btn);
13250   }
13251 }
13252 
13253 
SetWindowsSpecialCharacterDefaults(ButtoN b)13254 static void SetWindowsSpecialCharacterDefaults (ButtoN b)
13255 {
13256   SpecialCharacterDialogPtr sd;
13257   Int4                      pos;
13258   CharPtr                   str;
13259   ValNodePtr                vnp;
13260 
13261   sd = (SpecialCharacterDialogPtr) GetObjectExtra (b);
13262   if (sd == NULL) return;
13263 
13264   for (vnp = sd->find_list, pos = 0; vnp != NULL; vnp = vnp->next, pos++)
13265   {
13266     str = GetSpecialWinCharacterReplacement ((unsigned char) vnp->choice);
13267     SetTitle (sd->text_list[pos], str);
13268   }
13269 }
13270 
13271 
SetMacSpecialCharacterDefaults(ButtoN b)13272 static void SetMacSpecialCharacterDefaults (ButtoN b)
13273 {
13274   SpecialCharacterDialogPtr sd;
13275   Int4                      pos;
13276   CharPtr                   str;
13277   ValNodePtr                vnp;
13278 
13279   sd = (SpecialCharacterDialogPtr) GetObjectExtra (b);
13280   if (sd == NULL) return;
13281 
13282   for (vnp = sd->find_list, pos = 0; vnp != NULL; vnp = vnp->next, pos++)
13283   {
13284     str = GetSpecialMacCharacterReplacement ((unsigned char) vnp->choice);
13285     SetTitle (sd->text_list[pos], str);
13286   }
13287 
13288 }
13289 
13290 
FixSpecialCharactersForStringsInList(ValNodePtr find_list,CharPtr exp_text,Boolean force_fix)13291 extern Boolean FixSpecialCharactersForStringsInList (ValNodePtr find_list, CharPtr exp_text, Boolean force_fix)
13292 {
13293   ValNodePtr      vnp, context_list, vnp_c;
13294   Int4            pos;
13295   CharPtr         repl;
13296   WindoW          w;
13297   GrouP           h, c, g, p1, g2;
13298   PrompT          p2;
13299   LisT            contexts;
13300   ButtoN          b;
13301   SpecialCharacterDialogData sd;
13302   ModalAcceptCancelData      acd;
13303   Char                  label[2];
13304   Int4                  num_contexts;
13305   Boolean               rval = FALSE;
13306 
13307   if (find_list == NULL) {
13308     return TRUE;
13309   }
13310 
13311   ArrowCursor();
13312   Update();
13313 
13314   sd.find_list = find_list;
13315   sd.num_chars = ValNodeLen (find_list);
13316 
13317   acd.accepted = FALSE;
13318   acd.cancelled = FALSE;
13319 
13320   w = ModalWindow(-20, -13, -10, -10, NULL);
13321   h = HiddenGroup (w, -1, 0, NULL);
13322   SetGroupSpacing (h, 10, 10);
13323 
13324   p1 = MultiLinePrompt (h, exp_text, 27 * stdCharWidth, programFont);
13325   p2 = StaticPrompt (h, "Choose replacement characters.", 0, 0, programFont, 'l');
13326 
13327   g = HiddenGroup (h, 3, 0, NULL);
13328   StaticPrompt (g, "Character", 0, 0, programFont, 'l');
13329   StaticPrompt (g, "Replacement", 0, 0, programFont, 'l');
13330   StaticPrompt (g, "Contexts", 0, 0, programFont, 'l');
13331 
13332   sd.text_list = MemNew (sizeof (TexT) * sd.num_chars);
13333   label[1] = 0;
13334   for (vnp = find_list, pos = 0; vnp != NULL; vnp = vnp->next, pos++)
13335   {
13336     label[0] = vnp->choice;
13337     StaticPrompt (g, label, 0, 0, programFont, 'l');
13338     repl = GetSpecialCharacterReplacement (vnp->choice);
13339     sd.text_list[pos] = DialogText (g, repl, 5, EnableSpecialCharacterAccept);
13340     SetObjectExtra (sd.text_list[pos], &sd, NULL);
13341     context_list = vnp->data.ptrvalue;
13342     num_contexts = ValNodeLen (context_list);
13343     if (num_contexts == 0)
13344     {
13345       StaticPrompt (g, "", 0, 0, programFont, 'l');
13346     }
13347     else if (num_contexts == 1)
13348     {
13349       StaticPrompt (g, *((CharPtr PNTR)context_list->data.ptrvalue), 0, 0, programFont, 'l');
13350     }
13351     else
13352     {
13353       contexts = SingleList (g, 16, MIN (num_contexts, 5), NULL);
13354       for (vnp_c = context_list; vnp_c != NULL; vnp_c = vnp_c->next)
13355       {
13356         ListItem (contexts, *((CharPtr PNTR)vnp_c->data.ptrvalue));
13357       }
13358       SetValue (contexts, 1);
13359     }
13360   }
13361 
13362   g2 = HiddenGroup (h, 2, 0, NULL);
13363   SetGroupSpacing (g2, 10, 10);
13364   b = PushButton (g2, "Suggest Windows Replacements", SetWindowsSpecialCharacterDefaults);
13365   SetObjectExtra (b, &sd, NULL);
13366   b = PushButton (g2, "Suggest Mac Replacements", SetMacSpecialCharacterDefaults);
13367   SetObjectExtra (b, &sd, NULL);
13368 
13369   c = HiddenGroup (h, 3, 0, NULL);
13370   SetGroupSpacing (c, 10, 10);
13371   sd.accept_btn = PushButton (c, "Replace Characters", ModalAcceptButton);
13372   SetObjectExtra (sd.accept_btn, &acd, NULL);
13373   if (!force_fix) {
13374     b = PushButton (c, "Cancel", ModalCancelButton);
13375     SetObjectExtra (b, &acd, NULL);
13376   }
13377   AlignObjects (ALIGN_CENTER, (HANDLE) p1, (HANDLE) p2, (HANDLE) g, (HANDLE) g2, (HANDLE) c, NULL);
13378 
13379   Show(w);
13380   Select (w);
13381   while (!acd.accepted && ! acd.cancelled)
13382   {
13383     ProcessExternalEvent ();
13384     Update ();
13385   }
13386   ProcessAnEvent ();
13387   if (acd.accepted)
13388   {
13389     for (vnp = find_list, pos = 0; vnp != NULL; vnp = vnp->next, pos++)
13390     {
13391       repl = JustSaveStringFromText (sd.text_list[pos]);
13392       label[0] = vnp->choice;
13393       for (vnp_c = vnp->data.ptrvalue; vnp_c != NULL; vnp_c = vnp_c->next)
13394       {
13395         FindReplaceString (vnp_c->data.ptrvalue, label, repl, TRUE, FALSE);
13396       }
13397       repl = MemFree (repl);
13398     }
13399 
13400     rval = TRUE;
13401   }
13402   else if (force_fix)
13403   {
13404     for (vnp = find_list; vnp != NULL; vnp = vnp->next)
13405     {
13406       label[0] = vnp->choice;
13407       for (vnp_c = vnp->data.ptrvalue; vnp_c != NULL; vnp_c = vnp_c->next)
13408       {
13409         FindReplaceString (vnp_c->data.ptrvalue, label, "#", TRUE, FALSE);
13410       }
13411     }
13412     rval = TRUE;
13413   }
13414 
13415   Remove (w);
13416   return rval;
13417 
13418 }
13419 
13420 
FixSpecialCharacters(Uint2 entityID)13421 NLM_EXTERN Boolean FixSpecialCharacters (Uint2 entityID)
13422 {
13423   ValNodePtr      find_list = NULL;
13424   Boolean         rval;
13425 
13426   StringActionInEntity (entityID, FALSE, UPDATE_NEVER, NULL, NULL, NULL, TRUE,
13427                         SpecialCharFindWithContext, NULL, &find_list);
13428 
13429   rval = FixSpecialCharactersForStringsInList (find_list,
13430               "The ASN.1 contains special characters.\nIf you save it without stripping them,\nyou will be unable to load the file in Sequin.",
13431               FALSE);
13432 
13433   find_list = FreeContextList (find_list);
13434   if (rval)
13435   {
13436     ObjMgrSetDirtyFlag (entityID, TRUE);
13437     ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
13438   }
13439   return rval;
13440 }
13441 
13442 
FixSpecialCharactersForObject(Uint2 datatype,Pointer objdata,CharPtr msg,Boolean force_fix,BoolPtr changed)13443 NLM_EXTERN Boolean FixSpecialCharactersForObject (Uint2 datatype, Pointer objdata, CharPtr msg, Boolean force_fix, BoolPtr changed)
13444 {
13445   ValNodePtr      find_list = NULL;
13446   Boolean         rval;
13447 
13448   StringActionForObject (datatype, objdata, 0, FALSE, UPDATE_NEVER,
13449                         SpecialCharFindWithContext, NULL, &find_list);
13450 
13451   rval = FixSpecialCharactersForStringsInList (find_list,
13452               msg == NULL ?
13453                      "The ASN.1 contains special characters.\nIf you save it without stripping them,\nyou will be unable to load the file in Sequin."
13454                      : msg,
13455               force_fix);
13456 
13457   if (changed != NULL)
13458   {
13459     if (find_list == NULL)
13460     {
13461       *changed = FALSE;
13462     }
13463     else
13464     {
13465       *changed = rval;
13466     }
13467   }
13468 
13469   find_list = FreeContextList (find_list);
13470   return rval;
13471 }
13472 
13473 
13474 
13475 
13476 typedef struct featurereplace {
13477   SeqFeatPtr sfp;
13478   Boolean    chosen;
13479   ValNodePtr replace_list;
13480 } FeatureReplaceData, PNTR FeatureReplacePtr;
13481 
13482 
FeatureReplaceNew(SeqFeatPtr sfp)13483 static FeatureReplacePtr FeatureReplaceNew (SeqFeatPtr sfp)
13484 {
13485   FeatureReplacePtr f;
13486 
13487   f = (FeatureReplacePtr) MemNew (sizeof (FeatureReplaceData));
13488   f->sfp = AsnIoMemCopy (sfp, (AsnReadFunc) SeqFeatAsnRead, (AsnWriteFunc) SeqFeatAsnWrite);
13489   f->chosen = TRUE;
13490   f->replace_list = NULL;
13491   return f;
13492 }
13493 
13494 
FeatureReplaceCopy(FeatureReplacePtr orig)13495 static FeatureReplacePtr FeatureReplaceCopy (FeatureReplacePtr orig)
13496 {
13497   FeatureReplacePtr f = NULL;
13498 
13499 
13500   if (orig != NULL) {
13501     f = FeatureReplaceNew (orig->sfp);
13502     f->chosen = orig->chosen;
13503     f->replace_list = ValNodeCopyPtr (orig->replace_list);
13504   }
13505   return f;
13506 }
13507 
13508 
FeatureReplaceFree(FeatureReplacePtr f)13509 static FeatureReplacePtr FeatureReplaceFree (FeatureReplacePtr f)
13510 {
13511   if (f != NULL) {
13512     f->sfp = SeqFeatFree (f->sfp);
13513     f->replace_list = ValNodeFree (f->replace_list);
13514     f = MemFree (f);
13515   }
13516   return f;
13517 }
13518 
13519 
FeatureReplaceListFree(ValNodePtr vnp)13520 NLM_EXTERN ValNodePtr FeatureReplaceListFree (ValNodePtr vnp)
13521 {
13522   ValNodePtr vnp_next;
13523 
13524   while (vnp != NULL) {
13525     vnp_next = vnp->next;
13526     vnp->next = NULL;
13527     vnp->data.ptrvalue = FeatureReplaceFree (vnp->data.ptrvalue);
13528     vnp = ValNodeFree (vnp);
13529     vnp = vnp_next;
13530   }
13531   return vnp;
13532 }
13533 
13534 
FeatureReplaceListCopy(ValNodePtr orig)13535 static ValNodePtr FeatureReplaceListCopy (ValNodePtr orig)
13536 {
13537   ValNodePtr list = NULL;
13538 
13539   while (orig != NULL) {
13540     ValNodeAddPointer (&list, orig->choice, FeatureReplaceCopy (orig->data.ptrvalue));
13541     orig = orig->next;
13542   }
13543   return list;
13544 }
13545 
13546 
FeatureReplaceListFromSeqAnnot(SeqAnnotPtr sap)13547 NLM_EXTERN ValNodePtr FeatureReplaceListFromSeqAnnot (SeqAnnotPtr sap)
13548 {
13549   SeqFeatPtr sfp;
13550   ValNodePtr list = NULL;
13551 
13552   if (sap == NULL || sap->type != 1) {
13553     return NULL;
13554   }
13555 
13556   sfp = sap->data;
13557   while (sfp != NULL) {
13558     ValNodeAddPointer (&list, 0, FeatureReplaceNew (sfp));
13559     sfp = sfp->next;
13560   }
13561   return list;
13562 }
13563 
13564 
DoFeaturesAutomatchForUpdate(SeqFeatPtr sfp1,SeqFeatPtr sfp2)13565 static Boolean DoFeaturesAutomatchForUpdate (SeqFeatPtr sfp1, SeqFeatPtr sfp2)
13566 {
13567   GeneRefPtr grp1, grp2;
13568   Boolean    rval = FALSE;
13569   GBQualPtr  gbq;
13570   SeqIdPtr   sip;
13571   BioseqPtr  pbsp;
13572 
13573   if (sfp1 == NULL || sfp2 == NULL) {
13574     rval = FALSE;
13575   } else if (sfp1->data.choice != sfp2->data.choice) {
13576     rval = FALSE;
13577   } else if (sfp1->data.choice == SEQFEAT_GENE) {
13578     grp1 = sfp1->data.value.ptrvalue;
13579     grp2 = sfp2->data.value.ptrvalue;
13580     if (StringCmp (grp1->locus_tag, grp2->locus_tag) == 0) {
13581       rval = TRUE;
13582     }
13583   } else if (sfp1->data.choice == SEQFEAT_CDREGION) {
13584     /* match protein IDs */
13585     gbq = sfp1->qual;
13586     while (gbq != NULL && StringCmp (gbq->qual, "protein_id") != 0) {
13587       gbq = gbq->next;
13588     }
13589     if (gbq != NULL) {
13590       sip = MakeSeqID (gbq->val);
13591       /* look for protein ID on comparison feature */
13592       pbsp = BioseqFindFromSeqLoc (sfp2->product);
13593       if (pbsp != NULL && sip != NULL && SeqIdIn (sip, pbsp->id)) {
13594         rval = TRUE;
13595       }
13596       sip = SeqIdFree (sip);
13597     }
13598   }
13599   return rval;
13600 }
13601 
13602 
EntityIDAlreadyInList(Uint2 entityID,ValNodePtr entityIDList)13603 static Boolean EntityIDAlreadyInList (Uint2 entityID, ValNodePtr entityIDList)
13604 {
13605   while (entityIDList != NULL) {
13606     if ((Uint2)(entityIDList->data.intvalue) == entityID) {
13607       return TRUE;
13608     }
13609   }
13610   return FALSE;
13611 }
13612 
13613 
ActOnFeatureReplaceList(ValNodePtr list)13614 NLM_EXTERN void ActOnFeatureReplaceList (ValNodePtr list)
13615 {
13616   ValNodePtr vnp, vnp2;
13617   FeatureReplacePtr fr;
13618   BioseqPtr         bsp, product_bsp;
13619   SeqAnnotPtr       sap;
13620   SeqFeatPtr        sfp;
13621   ValNodePtr        entityIDList = NULL;
13622   SeqEntryPtr       sep;
13623   Int2              genCode;
13624   OMProcControl     ompc;
13625 
13626   for (vnp = list; vnp != NULL; vnp = vnp->next) {
13627     fr = (FeatureReplacePtr) vnp->data.ptrvalue;
13628     if (fr != NULL && fr->chosen && fr->sfp != NULL) {
13629       bsp = BioseqFindFromSeqLoc (fr->sfp->location);
13630       if (bsp != NULL) {
13631         sap = SeqAnnotNew ();
13632         sap->type = 1;
13633         sap->data = AsnIoMemCopy (fr->sfp, (AsnReadFunc) SeqFeatAsnRead, (AsnWriteFunc) SeqFeatAsnWrite);
13634         MemSet ((Pointer) &ompc, 0, sizeof (OMProcControl));
13635         ompc.input_entityID = bsp->idx.entityID;
13636         ompc.input_itemID = GetItemIDGivenPointer (bsp->idx.entityID, OBJ_BIOSEQ, (Pointer) bsp);
13637         ompc.input_itemtype = OBJ_BIOSEQ;
13638         ompc.output_itemtype = OBJ_SEQANNOT;
13639         ompc.output_data = (Pointer) sap;
13640         if (! AttachDataForProc (&ompc, FALSE)) {
13641           Message (MSG_POSTERR, "Error attaching SeqAnnot");
13642         } else {
13643           for (vnp2 = fr->replace_list; vnp2 != NULL; vnp2 = vnp2->next) {
13644             sfp = vnp2->data.ptrvalue;
13645             if (sfp != NULL) {
13646               sfp->idx.deleteme = TRUE;
13647               if (sfp->product != NULL) {
13648                 product_bsp = BioseqFindFromSeqLoc (sfp->product);
13649                 if (product_bsp != NULL) {
13650                   product_bsp->idx.deleteme = TRUE;
13651                 }
13652               }
13653             }
13654           }
13655           if (!EntityIDAlreadyInList (bsp->idx.entityID, entityIDList)) {
13656             ValNodeAddInt (&entityIDList, 0, bsp->idx.entityID);
13657           }
13658           sep = GetBestTopParentForData (bsp->idx.entityID, bsp);
13659           genCode = SeqEntryToGeneticCode (sep, NULL, NULL, 0);
13660           SetEmptyGeneticCodes (sap, genCode);
13661           PromoteXrefs (sap->data, bsp, bsp->idx.entityID);
13662         }
13663       }
13664     }
13665   }
13666   for (vnp = entityIDList; vnp != NULL; vnp = vnp->next) {
13667     DeleteMarkedObjects (vnp->data.intvalue, 0, NULL);
13668   }
13669 }
13670 
13671 
13672 typedef struct featurereplacelistdlg {
13673   DIALOG_MESSAGE_BLOCK
13674   DoC doc;
13675   ValNodePtr list;
13676   Int2       selected;
13677   Int2       clicked;
13678   Boolean    dblClick;
13679 
13680   Nlm_ParData ParFmt;
13681   Nlm_ColData NewFeatColFmt[2];
13682   Nlm_ColData OldFeatColFmt[2];
13683 
13684   Nlm_ChangeNotifyProc change_notify;
13685   Pointer              change_userdata;
13686 } FeatureReplaceListDlgData, PNTR FeatureReplaceListDlgPtr;
13687 
13688 
InitColAndParForFeatureReplaceList(DialoG d)13689 static void InitColAndParForFeatureReplaceList (DialoG d)
13690 {
13691   FeatureReplaceListDlgPtr dlg;
13692   RecT r;
13693   Int4 doc_width;
13694 
13695   dlg = (FeatureReplaceListDlgPtr) GetObjectExtra (d);
13696   if (dlg == NULL) {
13697     return;
13698   }
13699 
13700   dlg->ParFmt.openSpace = FALSE;
13701   dlg->ParFmt.keepWithNext = FALSE;
13702   dlg->ParFmt.keepTogether = FALSE;
13703   dlg->ParFmt.newPage = FALSE;
13704   dlg->ParFmt.tabStops = FALSE;
13705   dlg->ParFmt.minLines = 0;
13706   dlg->ParFmt.minHeight = 0;
13707 
13708   ObjectRect (dlg->doc, &r);
13709   InsetRect (&r, 4, 4);
13710   doc_width = r.right - r.left;
13711 
13712   dlg->NewFeatColFmt[0].pixWidth = 16;
13713   dlg->NewFeatColFmt[0].pixInset = 0;
13714   dlg->NewFeatColFmt[0].charWidth = 0;
13715   dlg->NewFeatColFmt[0].charInset = 0;
13716   dlg->NewFeatColFmt[0].font = programFont;
13717   dlg->NewFeatColFmt[0].just = 'l';
13718   dlg->NewFeatColFmt[0].wrap = 0;
13719   dlg->NewFeatColFmt[0].bar = 0;
13720   dlg->NewFeatColFmt[0].underline = 0;
13721   dlg->NewFeatColFmt[0].left = 0;
13722   dlg->NewFeatColFmt[0].last = 0;
13723 
13724   dlg->NewFeatColFmt[1].pixWidth = doc_width - 16;
13725   dlg->NewFeatColFmt[1].pixInset = 0;
13726   dlg->NewFeatColFmt[1].charWidth = 0;
13727   dlg->NewFeatColFmt[1].charInset = 0;
13728   dlg->NewFeatColFmt[1].font = programFont;
13729   dlg->NewFeatColFmt[1].just = 'l';
13730   dlg->NewFeatColFmt[1].wrap = 1;
13731   dlg->NewFeatColFmt[1].bar = 0;
13732   dlg->NewFeatColFmt[1].underline = 0;
13733   dlg->NewFeatColFmt[1].left = 0;
13734   dlg->NewFeatColFmt[1].last = 1;
13735 
13736 
13737   dlg->OldFeatColFmt[0].pixWidth = 32;
13738   dlg->OldFeatColFmt[0].pixInset = 0;
13739   dlg->OldFeatColFmt[0].charWidth = 0;
13740   dlg->OldFeatColFmt[0].charInset = 0;
13741   dlg->OldFeatColFmt[0].font = programFont;
13742   dlg->OldFeatColFmt[0].just = 'l';
13743   dlg->OldFeatColFmt[0].wrap = 0;
13744   dlg->OldFeatColFmt[0].bar = 0;
13745   dlg->OldFeatColFmt[0].underline = 0;
13746   dlg->OldFeatColFmt[0].left = 0;
13747   dlg->OldFeatColFmt[0].last = 0;
13748 
13749   dlg->OldFeatColFmt[1].pixWidth = doc_width - 32;
13750   dlg->OldFeatColFmt[1].pixInset = 0;
13751   dlg->OldFeatColFmt[1].charWidth = 0;
13752   dlg->OldFeatColFmt[1].charInset = 0;
13753   dlg->OldFeatColFmt[1].font = programFont;
13754   dlg->OldFeatColFmt[1].just = 'l';
13755   dlg->OldFeatColFmt[1].wrap = 1;
13756   dlg->OldFeatColFmt[1].bar = 0;
13757   dlg->OldFeatColFmt[1].underline = 0;
13758   dlg->OldFeatColFmt[1].left = 0;
13759   dlg->OldFeatColFmt[1].last = 1;
13760 }
13761 
13762 
13763 /* calculates position of feature replace item and feature within replace item */
GetListPosFromItem(ValNodePtr list,Int2 item,Int2Ptr feature_pos)13764 static Int2 GetListPosFromItem (ValNodePtr list, Int2 item, Int2Ptr feature_pos)
13765 {
13766   Int2 num = 1, pos = 1, nextval;
13767   FeatureReplacePtr fr;
13768   ValNodePtr vnp;
13769 
13770   if (feature_pos != NULL) {
13771     *feature_pos = 0;
13772   }
13773   if (list == NULL || item < 1) {
13774     return -1;
13775   }
13776 
13777   vnp = list;
13778 
13779   while (num < item && vnp != NULL) {
13780     fr = (FeatureReplacePtr) vnp->data.ptrvalue;
13781     nextval = num + ValNodeLen (fr->replace_list) + 1;
13782     if (nextval < item ) {
13783       pos++;
13784       num = nextval;
13785     } else if (nextval == item) {
13786       pos++;
13787       if (feature_pos != NULL) {
13788         *feature_pos = 0;
13789       }
13790       return pos;
13791     } else {
13792       if (feature_pos != NULL) {
13793         *feature_pos = nextval - item;
13794       }
13795       return pos;
13796     }
13797     vnp = vnp->next;
13798   }
13799   return pos;
13800 }
13801 
13802 
DrawFeatureReplaceList(DoC d,RectPtr r,Int2 item,Int2 firstLine)13803 static void DrawFeatureReplaceList (DoC d, RectPtr r, Int2 item, Int2 firstLine)
13804 
13805 {
13806   FeatureReplaceListDlgPtr dlg;
13807   RecT                     rct;
13808   FeatureReplacePtr        fr;
13809   ValNodePtr               vnp;
13810   Int2                     pos, num, feature_pos = 0;
13811 
13812   dlg = (FeatureReplaceListDlgPtr) GetObjectExtra (d);
13813   if (dlg != NULL && r != NULL && item > 0 && firstLine == 0) {
13814     rct = *r;
13815 
13816     vnp = dlg->list;
13817     pos = GetListPosFromItem (dlg->list, item, &feature_pos);
13818     if (pos < 1) {
13819       /* do nothing */
13820     } else if (feature_pos > 0) {
13821       /* do nothing */
13822     } else {
13823       /* draw box for selecting feature to be imported */
13824       num = 1;
13825       while (num < pos) {
13826         vnp = vnp->next;
13827         num++;
13828       }
13829       if (vnp != NULL && vnp->data.ptrvalue != NULL) {
13830         fr = (FeatureReplacePtr) vnp->data.ptrvalue;
13831 
13832         /* draw selection */
13833         if (item == dlg->selected) {
13834           rct.right = rct.left + 4;
13835           PaintRect (&rct);
13836         }
13837 
13838         /* draw chosen checkboxes */
13839         rct.left += 5;
13840         rct.right = rct.left + 10;
13841         rct.bottom = rct.top + (rct.right - rct.left);
13842         FrameRect (&rct);
13843 
13844         if (fr->chosen) {
13845           MoveTo (rct.left, rct.top);
13846           LineTo (rct.right - 1, rct.bottom - 1);
13847           MoveTo (rct.left, rct.bottom - 1);
13848           LineTo (rct.right - 1, rct.top);
13849         }
13850       }
13851     }
13852   }
13853 }
13854 
13855 
HighlightFeatureReplaceTarget(DoC doc,Int2 item,Int2 row,Int2 col)13856 static Boolean HighlightFeatureReplaceTarget (DoC doc, Int2 item, Int2 row, Int2 col)
13857 {
13858   FeatureReplaceListDlgPtr dlg;
13859 
13860   dlg = (FeatureReplaceListDlgPtr) GetObjectExtra (doc);
13861   if (dlg == NULL) return FALSE;
13862 
13863   if (dlg->selected == item)
13864   {
13865     return TRUE;
13866   }
13867   else
13868   {
13869     return FALSE;
13870   }
13871 }
13872 
GetNewItemDescription(SeqFeatPtr sfp)13873 static CharPtr GetNewItemDescription (SeqFeatPtr sfp)
13874 {
13875   CharPtr location, label, row_text;
13876   Char buf[129];
13877 
13878   if (sfp == NULL) {
13879     return StringSave ("Misc Features to Delete");
13880   }
13881   location = SeqLocPrintUseBestID (sfp->location);
13882   label = (CharPtr) FeatDefTypeLabel(sfp);
13883 
13884   FeatDefLabel (sfp, buf, sizeof (buf) - 1, OM_LABEL_CONTENT);
13885 
13886   row_text = (CharPtr) MemNew (sizeof (Char) *
13887                               (StringLen (label)
13888                               + StringLen (buf)
13889                               + StringLen (location)
13890                               + 6));
13891   sprintf (row_text, "%s:%s:%s\n", label, buf, location);
13892   location = MemFree (location);
13893   return row_text;
13894 }
13895 
13896 
AddFeatureReplace(FeatureReplaceListDlgPtr dlg,FeatureReplacePtr fr)13897 static void AddFeatureReplace (FeatureReplaceListDlgPtr dlg, FeatureReplacePtr fr)
13898 {
13899   CharPtr            desc, item_text, desc_fmt = "\t%s", repl_fmt = "\tReplaces %s";
13900   ValNodePtr         vnp;
13901 
13902   if (dlg == NULL || fr == NULL)
13903   {
13904     return;
13905   }
13906   desc = GetNewItemDescription (fr->sfp);
13907   item_text = (CharPtr) MemNew (sizeof (Char) * (StringLen (desc_fmt) + StringLen (desc)));
13908   sprintf (item_text, desc_fmt, desc);
13909   desc = MemFree (desc);
13910   AppendText (dlg->doc, item_text, &dlg->ParFmt, dlg->NewFeatColFmt, programFont);
13911   MemFree (item_text);
13912   for (vnp = fr->replace_list; vnp != NULL; vnp = vnp->next) {
13913     desc = GetNewItemDescription (vnp->data.ptrvalue);
13914     item_text = (CharPtr) MemNew (sizeof (Char) * (StringLen (repl_fmt) + StringLen (desc)));
13915     sprintf (item_text, repl_fmt, desc);
13916     desc = MemFree (desc);
13917     AppendText (dlg->doc, item_text, &dlg->ParFmt, dlg->OldFeatColFmt, programFont);
13918     MemFree (item_text);
13919   }
13920 }
13921 
13922 
ClickFeatureReplaceList(DoC d,PoinT pt)13923 static void ClickFeatureReplaceList (DoC d, PoinT pt)
13924 
13925 {
13926   Int2             item, numItems, pos, feature_pos;
13927   Int2             row;
13928   Int2             col;
13929   FeatureReplaceListDlgPtr dlg;
13930   Int4             offset;
13931   Int2             first_shown = 0;
13932   RecT             r;
13933   BaR              vbar;
13934   Int4             scroll_pos;
13935 
13936   dlg = GetObjectExtra (d);
13937   if (dlg != NULL) {
13938     MapDocPoint (d, pt, &item, &row, &col, NULL);
13939     if (item > 0 && row > 0 && dlg->clicked == item) {
13940       dlg->dblClick = dblClick;
13941     } else {
13942       dlg->dblClick = FALSE;
13943     }
13944     dlg->clicked = 0;
13945     if (item > 0 && row > 0) {
13946       dlg->clicked = item;
13947     }
13948     if (item > 0 && row > 0 && !dblClick)
13949     {
13950       vbar = GetSlateVScrollBar ((SlatE) dlg->doc);
13951       scroll_pos = GetBarValue (vbar);
13952 
13953       pos = GetListPosFromItem (dlg->list, item, &feature_pos);
13954       if (pos >= 1 && col == 2 && feature_pos == 0) {
13955         dlg->selected = item;
13956       }
13957       GetDocParams (d, &numItems, NULL);
13958       UpdateDocument (d, 0, numItems);
13959       GetItemParams4 (dlg->doc, first_shown, &offset, NULL, NULL, NULL, NULL);
13960       SetScrlParams4 (dlg->doc, offset);
13961       ObjectRect (dlg->doc, &r);
13962       InsetRect (&r, -1, -1);
13963       InvalRect (&r);
13964       SetBarValue (vbar, scroll_pos);
13965       if (dlg->change_notify != NULL) {
13966         (dlg->change_notify) (dlg->change_userdata);
13967       }
13968     }
13969   }
13970 }
13971 
13972 
PopulateFeatureReplaceList(FeatureReplaceListDlgPtr dlg,ValNodePtr list)13973 static void PopulateFeatureReplaceList (FeatureReplaceListDlgPtr dlg, ValNodePtr list)
13974 {
13975   Int2               numItems;
13976 
13977   if (dlg == NULL || dlg->doc == NULL)
13978   {
13979     return;
13980   }
13981 
13982   Reset (dlg->doc);
13983 
13984 
13985   while (list != NULL)
13986   {
13987     AddFeatureReplace (dlg, list->data.ptrvalue);
13988     list = list->next;
13989   }
13990   GetDocParams (dlg->doc, &numItems, NULL);
13991   UpdateDocument (dlg->doc, 0, numItems);
13992 
13993 }
13994 
13995 
FeatureReplaceListToDialog(DialoG d,Pointer data)13996 static void FeatureReplaceListToDialog (DialoG d, Pointer data)
13997 {
13998   FeatureReplaceListDlgPtr dlg;
13999 
14000   dlg = (FeatureReplaceListDlgPtr) GetObjectExtra (d);
14001   if (dlg == NULL) {
14002     return;
14003   }
14004   dlg->list = FeatureReplaceListFree (dlg->list);
14005   dlg->list = FeatureReplaceListCopy((ValNodePtr) data);
14006   PopulateFeatureReplaceList (dlg, dlg->list);
14007 }
14008 
14009 
FeatureReplaceListFromDialog(DialoG d)14010 static Pointer FeatureReplaceListFromDialog (DialoG d)
14011 {
14012   FeatureReplaceListDlgPtr dlg;
14013 
14014   dlg = (FeatureReplaceListDlgPtr) GetObjectExtra (d);
14015   if (dlg == NULL) {
14016     return NULL;
14017   }
14018   return FeatureReplaceListCopy(dlg->list);
14019 }
14020 
14021 
CleanupFeatureReplaceListDialog(GraphiC g,VoidPtr data)14022 static void CleanupFeatureReplaceListDialog (GraphiC g, VoidPtr data)
14023 
14024 {
14025   FeatureReplaceListDlgPtr dlg;
14026 
14027   dlg = (FeatureReplaceListDlgPtr) data;
14028   if (dlg != NULL) {
14029     dlg->list = FeatureReplaceListFree (dlg->list);
14030   }
14031   StdCleanupExtraProc (g, data);
14032 }
14033 
14034 
14035 NLM_EXTERN DialoG
FeatureReplaceListDialog(GrouP h,Int4 width,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)14036 FeatureReplaceListDialog
14037 (GrouP h,
14038  Int4 width,
14039  Nlm_ChangeNotifyProc change_notify,
14040  Pointer change_userdata)
14041 {
14042   FeatureReplaceListDlgPtr dlg;
14043   GrouP                    p;
14044 
14045   dlg = (FeatureReplaceListDlgPtr) MemNew (sizeof (FeatureReplaceListDlgData));
14046 
14047   p = HiddenGroup (h, -1, 0, NULL);
14048   SetObjectExtra (p, dlg, CleanupFeatureReplaceListDialog);
14049 
14050   dlg->dialog = (DialoG) p;
14051   dlg->fromdialog = FeatureReplaceListFromDialog;
14052   dlg->todialog = FeatureReplaceListToDialog;
14053   dlg->change_notify = change_notify;
14054   dlg->change_userdata = change_userdata;
14055 
14056   dlg->doc = DocumentPanel (p, width, stdLineHeight * 20);
14057   SetObjectExtra (dlg->doc, dlg, NULL);
14058   SetDocAutoAdjust (dlg->doc, FALSE);
14059   SetDocProcs (dlg->doc, ClickFeatureReplaceList, NULL, NULL, NULL);
14060   SetDocShade (dlg->doc, DrawFeatureReplaceList, NULL, HighlightFeatureReplaceTarget, NULL);
14061 
14062   InitColAndParForFeatureReplaceList (dlg->dialog);
14063 
14064   return (DialoG) p;
14065 }
14066 
14067 
AddFeaturesToReplaceList(DialoG d,ValNodePtr feature_list)14068 NLM_EXTERN Boolean AddFeaturesToReplaceList (DialoG d, ValNodePtr feature_list)
14069 {
14070   FeatureReplaceListDlgPtr dlg;
14071   Int2                     num, pos;
14072   ValNodePtr               vnp = NULL;
14073   FeatureReplacePtr        fr;
14074   Boolean                  rval = FALSE;
14075   BaR                      vbar;
14076   Int4                     scroll_pos;
14077 
14078   dlg = (FeatureReplaceListDlgPtr) GetObjectExtra (d);
14079   if (dlg == NULL || feature_list == NULL) {
14080     return FALSE;
14081   }
14082 
14083   vbar = GetSlateVScrollBar ((SlatE) dlg->doc);
14084   scroll_pos = GetBarValue (vbar);
14085 
14086   if (dlg->selected >= 1) {
14087     pos = GetListPosFromItem (dlg->list, dlg->selected, NULL);
14088     num = 1;
14089     vnp = dlg->list;
14090     while (num < pos && vnp != NULL) {
14091       num++;
14092       vnp = vnp->next;
14093     }
14094   }
14095   if (vnp != NULL) {
14096     fr = (FeatureReplacePtr) vnp->data.ptrvalue;
14097     if (fr != NULL) {
14098       ValNodeLink (&fr->replace_list, feature_list);
14099       PopulateFeatureReplaceList (dlg, dlg->list);
14100       rval = TRUE;
14101     }
14102   }
14103   if (!rval) {
14104     /* find misc item */
14105     vnp = dlg->list;
14106     while (vnp != NULL && ((fr = (FeatureReplacePtr) vnp->data.ptrvalue) == NULL
14107                            || fr->sfp != NULL)) {
14108       vnp = vnp->next;
14109     }
14110     if (vnp == NULL) {
14111       fr = FeatureReplaceNew (NULL);
14112       ValNodeAddPointer (&dlg->list, 0, fr);
14113     }
14114     ValNodeLink (&(fr->replace_list), feature_list);
14115     PopulateFeatureReplaceList (dlg, dlg->list);
14116     rval = TRUE;
14117   }
14118 
14119   SetBarValue (vbar, scroll_pos);
14120 
14121   return rval;
14122 }
14123 
14124 
GetSelectedNewFeature(DialoG d)14125 NLM_EXTERN SeqFeatPtr GetSelectedNewFeature (DialoG d)
14126 {
14127   FeatureReplaceListDlgPtr dlg;
14128   FeatureReplacePtr fr;
14129   SeqFeatPtr sfp = NULL;
14130   ValNodePtr vnp;
14131   Int2       num, pos;
14132 
14133   dlg = (FeatureReplaceListDlgPtr) GetObjectExtra (d);
14134   if (dlg == NULL) {
14135     return NULL;
14136   }
14137 
14138   if (dlg->selected >= 1) {
14139     pos = GetListPosFromItem (dlg->list, dlg->selected, NULL);
14140     num = 1;
14141     vnp = dlg->list;
14142     while (num < pos && vnp != NULL) {
14143       num++;
14144       vnp = vnp->next;
14145     }
14146     if (vnp != NULL) {
14147       fr = (FeatureReplacePtr) vnp->data.ptrvalue;
14148       if (fr != NULL) {
14149         sfp = fr->sfp;
14150       }
14151     }
14152   }
14153   return sfp;
14154 }
14155 
14156 
RemoveFeaturesFromReplaceList(DialoG d)14157 NLM_EXTERN ValNodePtr RemoveFeaturesFromReplaceList (DialoG d)
14158 {
14159   FeatureReplaceListDlgPtr dlg;
14160   Int2                     num;
14161   ValNodePtr               vnp, list = NULL, prev = NULL;
14162   FeatureReplacePtr        fr;
14163   BaR                      vbar;
14164   Int4                     scroll_pos;
14165 
14166   dlg = (FeatureReplaceListDlgPtr) GetObjectExtra (d);
14167   if (dlg == NULL || dlg->list == NULL || dlg->selected < 1) {
14168     return NULL;
14169   }
14170 
14171   num = 1;
14172   vnp = dlg->list;
14173   while (num < dlg->selected && vnp != NULL) {
14174     num++;
14175     prev = vnp;
14176     vnp = vnp->next;
14177   }
14178   if (vnp != NULL) {
14179     fr = (FeatureReplacePtr) vnp->data.ptrvalue;
14180     if (fr != NULL) {
14181       list = fr->replace_list;
14182       fr->replace_list = NULL;
14183       /* if we have removed features from a placeholder empty category, remove the category */
14184       if (fr->sfp == NULL) {
14185         if (prev == NULL) {
14186           dlg->list->next = vnp->next;
14187         } else {
14188           prev->next = vnp->next;
14189         }
14190         vnp->next = NULL;
14191         vnp = FeatureReplaceListFree (vnp);
14192       }
14193       vbar = GetSlateVScrollBar ((SlatE) dlg->doc);
14194       scroll_pos = GetBarValue (vbar);
14195 
14196       PopulateFeatureReplaceList (dlg, dlg->list);
14197       SetBarValue (vbar, scroll_pos);
14198     }
14199   }
14200   return list;
14201 }
14202 
14203 
AutomatchFeatures(DialoG d,ValNodePtr PNTR existing_features)14204 NLM_EXTERN Boolean AutomatchFeatures (DialoG d, ValNodePtr PNTR existing_features)
14205 {
14206   FeatureReplaceListDlgPtr dlg;
14207   ValNodePtr               vnp, vnp_f, vnp_next, prev = NULL;
14208   FeatureReplacePtr        fr;
14209   Boolean                  found = FALSE;
14210   SeqIntPtr                s1, s2, s3;
14211 
14212   dlg = (FeatureReplaceListDlgPtr) GetObjectExtra (d);
14213   if (dlg == NULL || dlg->list == NULL || existing_features == NULL || *existing_features == NULL) {
14214     return FALSE;
14215   }
14216 
14217   for (vnp = dlg->list; vnp != NULL; vnp = vnp->next) {
14218     fr = (FeatureReplacePtr) vnp->data.ptrvalue;
14219     prev = NULL;
14220     s1 = (SeqIntPtr)(fr->sfp->location->data.ptrvalue);
14221     if (s1->from == 86391) {
14222       s2 = NULL;
14223     }
14224     for (vnp_f = *existing_features; vnp_f != NULL; vnp_f = vnp_next) {
14225       vnp_next = vnp_f->next;
14226       s2 = (SeqIntPtr)((SeqFeatPtr)vnp_f->data.ptrvalue)->location->data.ptrvalue;
14227       if (s2->from == 86391) {
14228         s3 = NULL;
14229       }
14230       if (DoFeaturesAutomatchForUpdate (fr->sfp, vnp_f->data.ptrvalue)) {
14231         if (prev == NULL) {
14232           *existing_features = vnp_f->next;
14233         } else {
14234           prev->next = vnp_f->next;
14235         }
14236         vnp_f->next = NULL;
14237         ValNodeLink (&(fr->replace_list), vnp_f);
14238         found = TRUE;
14239       } else {
14240         prev = vnp_f;
14241       }
14242     }
14243   }
14244 
14245   PopulateFeatureReplaceList (dlg, dlg->list);
14246 
14247   return found;
14248 }
14249 
14250 
14251 
14252 typedef struct featureselectlistdlg {
14253   DIALOG_MESSAGE_BLOCK
14254   DoC doc;
14255   ValNodePtr list;
14256   Int2       selected;
14257   Int2       clicked;
14258   Boolean    dblClick;
14259 
14260   Nlm_ParData ParFmt;
14261   Nlm_ColData ColFmt[2];
14262 } FeatureSelectListDlgData, PNTR FeatureSelectListDlgPtr;
14263 
14264 
ClickFeatureSelectList(DoC d,PoinT pt)14265 static void ClickFeatureSelectList (DoC d, PoinT pt)
14266 
14267 {
14268   Int2             item, numItems;
14269   Int2             first_shown = 0;
14270   Int2             row;
14271   Int2             col;
14272   Int4             offset;
14273   FeatureSelectListDlgPtr dlg;
14274   RecT             r;
14275   BaR                     vbar;
14276   Int4                    scroll_pos;
14277 
14278 
14279   dlg = GetObjectExtra (d);
14280   if (dlg != NULL) {
14281     MapDocPoint (d, pt, &item, &row, &col, NULL);
14282     if (item > 0 && row > 0 && dlg->clicked == item) {
14283       dlg->dblClick = dblClick;
14284     } else {
14285       dlg->dblClick = FALSE;
14286     }
14287     dlg->clicked = 0;
14288     if (item > 0 && row > 0) {
14289       dlg->clicked = item;
14290       dlg->selected = item;
14291     }
14292     vbar = GetSlateVScrollBar ((SlatE) dlg->doc);
14293     scroll_pos = GetBarValue (vbar);
14294 
14295     GetDocParams (d, &numItems, NULL);
14296     UpdateDocument (d, 0, numItems);
14297     GetItemParams4 (dlg->doc, first_shown, &offset, NULL, NULL, NULL, NULL);
14298     SetScrlParams4 (dlg->doc, offset);
14299     ObjectRect (dlg->doc, &r);
14300     InsetRect (&r, -1, -1);
14301     InvalRect (&r);
14302     SetBarValue (vbar, scroll_pos);
14303   }
14304 }
14305 
14306 
HighlightFeatureSelectTarget(DoC doc,Int2 item,Int2 row,Int2 col)14307 static Boolean HighlightFeatureSelectTarget (DoC doc, Int2 item, Int2 row, Int2 col)
14308 {
14309   FeatureSelectListDlgPtr dlg;
14310 
14311   dlg = (FeatureSelectListDlgPtr) GetObjectExtra (doc);
14312   if (dlg == NULL) return FALSE;
14313 
14314   if (dlg->selected == item)
14315   {
14316     return TRUE;
14317   }
14318   else
14319   {
14320     return FALSE;
14321   }
14322 }
14323 
14324 
14325 
PopulateFeatureSelectList(FeatureSelectListDlgPtr dlg,ValNodePtr list)14326 static void PopulateFeatureSelectList (FeatureSelectListDlgPtr dlg, ValNodePtr list)
14327 {
14328   ValNodePtr              vnp;
14329   CharPtr                 desc;
14330   Int2                    numItems;
14331 
14332   Reset (dlg->doc);
14333   for (vnp = list; vnp != NULL; vnp = vnp->next) {
14334     desc = GetNewItemDescription (vnp->data.ptrvalue);
14335     AppendText (dlg->doc, desc, &dlg->ParFmt, dlg->ColFmt, programFont);
14336     desc = MemFree (desc);
14337   }
14338 
14339   GetDocParams (dlg->doc, &numItems, NULL);
14340   UpdateDocument (dlg->doc, 0, numItems);
14341 }
14342 
14343 
FeatureSelectListToDialog(DialoG d,Pointer data)14344 static void FeatureSelectListToDialog (DialoG d, Pointer data)
14345 {
14346   FeatureSelectListDlgPtr dlg;
14347 
14348   dlg = (FeatureSelectListDlgPtr) GetObjectExtra (d);
14349   if (dlg == NULL) {
14350     return;
14351   }
14352 
14353   dlg->list = (ValNodePtr) data;
14354   PopulateFeatureSelectList (dlg, dlg->list);
14355 }
14356 
14357 
FeatureSelectListFromDialog(DialoG d)14358 static Pointer FeatureSelectListFromDialog (DialoG d)
14359 {
14360   FeatureSelectListDlgPtr dlg;
14361 
14362   dlg = (FeatureSelectListDlgPtr) GetObjectExtra (d);
14363   if (dlg == NULL) {
14364     return NULL;
14365   }
14366 
14367   return (Pointer) dlg->list;
14368 }
14369 
14370 
FeatureSelectListDialog(GrouP h,Int4 width)14371 NLM_EXTERN DialoG FeatureSelectListDialog (GrouP h, Int4 width)
14372 {
14373   FeatureSelectListDlgPtr dlg;
14374   GrouP                   p;
14375   RecT                    r;
14376   Int4                    doc_width;
14377 
14378   dlg = (FeatureSelectListDlgPtr) MemNew (sizeof (FeatureSelectListDlgData));
14379 
14380   p = HiddenGroup (h, -1, 0, NULL);
14381   SetObjectExtra (p, dlg, StdCleanupExtraProc);
14382 
14383   dlg->dialog = (DialoG) p;
14384   dlg->todialog = FeatureSelectListToDialog;
14385   dlg->fromdialog = FeatureSelectListFromDialog;
14386 
14387   dlg->doc = DocumentPanel (p, width, stdLineHeight * 20);
14388   SetObjectExtra (dlg->doc, dlg, NULL);
14389   SetDocAutoAdjust (dlg->doc, FALSE);
14390   SetDocShade (dlg->doc, NULL, NULL, HighlightFeatureSelectTarget, NULL);
14391   SetDocProcs (dlg->doc, ClickFeatureSelectList, NULL, NULL, NULL);
14392 
14393   dlg->ParFmt.openSpace = FALSE;
14394   dlg->ParFmt.keepWithNext = FALSE;
14395   dlg->ParFmt.keepTogether = FALSE;
14396   dlg->ParFmt.newPage = FALSE;
14397   dlg->ParFmt.tabStops = FALSE;
14398   dlg->ParFmt.minLines = 0;
14399   dlg->ParFmt.minHeight = 0;
14400 
14401   ObjectRect (dlg->doc, &r);
14402   InsetRect (&r, 4, 4);
14403   doc_width = r.right - r.left;
14404 
14405   dlg->ColFmt[0].pixWidth = doc_width;
14406   dlg->ColFmt[0].pixInset = 0;
14407   dlg->ColFmt[0].charWidth = 0;
14408   dlg->ColFmt[0].charInset = 0;
14409   dlg->ColFmt[0].font = programFont;
14410   dlg->ColFmt[0].just = 'l';
14411   dlg->ColFmt[0].wrap = 0;
14412   dlg->ColFmt[0].bar = 0;
14413   dlg->ColFmt[0].underline = 0;
14414   dlg->ColFmt[0].left = 0;
14415   dlg->ColFmt[0].last = 1;
14416 
14417 
14418   return (DialoG) p;
14419 }
14420 
14421 
RemoveSelectedFeaturesFromList(DialoG d)14422 NLM_EXTERN ValNodePtr RemoveSelectedFeaturesFromList (DialoG d)
14423 {
14424   FeatureSelectListDlgPtr dlg;
14425   ValNodePtr              vnp, prev = NULL;
14426   Int2                    num;
14427   BaR                     vbar;
14428   Int4                    scroll_pos;
14429 
14430   dlg = (FeatureSelectListDlgPtr) GetObjectExtra (d);
14431   if (dlg == NULL || dlg->selected == 0) {
14432     return NULL;
14433   }
14434 
14435   vbar = GetSlateVScrollBar ((SlatE) dlg->doc);
14436   scroll_pos = GetBarValue (vbar);
14437 
14438   num = 1;
14439   vnp = dlg->list;
14440   while (num < dlg->selected && vnp != NULL) {
14441     prev = vnp;
14442     vnp = vnp->next;
14443     num++;
14444   }
14445 
14446   if (vnp != NULL) {
14447     if (prev == NULL) {
14448       dlg->list = vnp->next;
14449     } else {
14450       prev->next = vnp->next;
14451     }
14452     vnp->next = NULL;
14453   }
14454   PopulateFeatureSelectList (dlg, dlg->list);
14455   SetBarValue (vbar, scroll_pos);
14456   return vnp;
14457 }
14458 
14459 
ScrollToMatchingFeatures(DialoG d,SeqFeatPtr sfp)14460 NLM_EXTERN void ScrollToMatchingFeatures (DialoG d, SeqFeatPtr sfp)
14461 {
14462   FeatureSelectListDlgPtr dlg;
14463   ValNodePtr              vnp;
14464   BaR                     vbar;
14465   Int4                    scroll_pos;
14466   Int4                    start, stop, startitem;
14467   Int4                    range_start = -1, pos;
14468   RecT                    r;
14469 
14470   dlg = (FeatureSelectListDlgPtr) GetObjectExtra (d);
14471   if (dlg == NULL || sfp == NULL) {
14472     return;
14473   }
14474 
14475   dlg->selected = 0;
14476   start = SeqLocStart (sfp->location);
14477   stop = SeqLocStop (sfp->location);
14478 
14479   for (vnp = dlg->list, pos = 0; vnp != NULL; vnp = vnp->next, pos++) {
14480     startitem = SeqLocStart (((SeqFeatPtr)vnp->data.ptrvalue)->location);
14481     if (startitem >= start && range_start == -1) {
14482       range_start = pos;
14483     }
14484     if (DoFeaturesAutomatchForUpdate (sfp, vnp->data.ptrvalue)) {
14485       range_start = pos;
14486       dlg->selected = pos + 1;
14487       break;
14488     }
14489     if (startitem > stop) {
14490       break;
14491     }
14492   }
14493 
14494   /* scroll to position */
14495   if (range_start > -1) {
14496     vbar = GetSlateVScrollBar ((SlatE) dlg->doc);
14497     scroll_pos = GetBarMax (vbar);
14498     if (scroll_pos > range_start) {
14499       scroll_pos = range_start;
14500     }
14501     SetBarValue (vbar, scroll_pos);
14502   }
14503   ObjectRect (dlg->doc, &r);
14504   InsetRect (&r, -1, -1);
14505   InvalRect (&r);
14506   Update ();
14507 
14508 }
14509 
14510 
14511 typedef struct featsort {
14512   SeqFeatPtr sfp;
14513   Int4       start;
14514   Int4       stop;
14515 } FeatSortData, PNTR FeatSortPtr;
14516 
14517 
FeatSortNew(SeqFeatPtr sfp)14518 static FeatSortPtr FeatSortNew (SeqFeatPtr sfp)
14519 {
14520   FeatSortPtr f;
14521 
14522   if (sfp == NULL) {
14523     return NULL;
14524   }
14525 
14526   f = (FeatSortPtr) MemNew (sizeof (FeatSortData));
14527   f->sfp = sfp;
14528   f->start = SeqLocStart (sfp->location);
14529   f->stop = SeqLocStop (sfp->location);
14530   return f;
14531 }
14532 
14533 
FeatSortFree(FeatSortPtr f)14534 static FeatSortPtr FeatSortFree (FeatSortPtr f)
14535 {
14536   if (f != NULL) {
14537     f = MemFree (f);
14538   }
14539   return f;
14540 }
14541 
14542 
FeatSortListFree(ValNodePtr vnp)14543 static ValNodePtr FeatSortListFree (ValNodePtr vnp)
14544 {
14545   ValNodePtr vnp_next;
14546 
14547   while (vnp != NULL) {
14548     vnp_next = vnp->next;
14549     vnp->next = NULL;
14550     vnp->data.ptrvalue = FeatSortFree (vnp->data.ptrvalue);
14551     vnp = ValNodeFree (vnp);
14552     vnp = vnp_next;
14553   }
14554   return vnp;
14555 }
14556 
14557 
FeatSortListFromSeqAnnot(SeqAnnotPtr sap)14558 static ValNodePtr FeatSortListFromSeqAnnot (SeqAnnotPtr sap)
14559 {
14560   ValNodePtr list = NULL, prev = NULL, vnp;
14561   SeqFeatPtr sfp;
14562   FeatSortPtr f;
14563 
14564   if (sap == NULL || sap->type != 1) {
14565     return NULL;
14566   }
14567 
14568   for (sfp = sap->data; sfp != NULL; sfp = sfp->next) {
14569     f = FeatSortNew (sfp);
14570     vnp = ValNodeNew (NULL);
14571     vnp->data.ptrvalue = f;
14572     if (prev == NULL) {
14573       list = vnp;
14574     } else {
14575       prev->next = vnp;
14576     }
14577     prev = vnp;
14578   }
14579   return list;
14580 }
14581 
14582 
SeqFeatListFromFeatSortList(ValNodePtr list)14583 static SeqFeatPtr SeqFeatListFromFeatSortList (ValNodePtr list)
14584 {
14585   SeqFeatPtr first = NULL, last = NULL;
14586   FeatSortPtr f;
14587 
14588   while (list != NULL) {
14589     f = (FeatSortPtr) list->data.ptrvalue;
14590     if (f != NULL) {
14591       if (first == NULL) {
14592         first = f->sfp;
14593       } else {
14594         last->next = f->sfp;
14595       }
14596       last = f->sfp;
14597       last->next = NULL;
14598     }
14599     list = list->next;
14600   }
14601   return first;
14602 }
14603 
14604 
FeatSortListFromFeatValNodeList(ValNodePtr orig)14605 static ValNodePtr FeatSortListFromFeatValNodeList (ValNodePtr orig)
14606 {
14607   ValNodePtr list = NULL, prev = NULL, vnp, vnp_orig;
14608   FeatSortPtr f;
14609 
14610   for (vnp_orig = orig; vnp_orig != NULL; vnp_orig = vnp_orig->next) {
14611     f = FeatSortNew ((SeqFeatPtr) vnp_orig->data.ptrvalue);
14612     vnp = ValNodeNew (NULL);
14613     vnp->data.ptrvalue = f;
14614     if (prev == NULL) {
14615       list = vnp;
14616     } else {
14617       prev->next = vnp;
14618     }
14619     prev = vnp;
14620   }
14621   return list;
14622 }
14623 
14624 
FeatValNodeListFromFeatSortList(ValNodePtr orig)14625 static ValNodePtr FeatValNodeListFromFeatSortList (ValNodePtr orig)
14626 {
14627   ValNodePtr list = NULL, prev = NULL, vnp, vnp_orig;
14628   FeatSortPtr f;
14629 
14630   for (vnp_orig = orig; vnp_orig != NULL; vnp_orig = vnp_orig->next) {
14631     f = (FeatSortPtr) vnp_orig->data.ptrvalue;
14632     vnp = ValNodeNew (NULL);
14633     vnp->data.ptrvalue = f->sfp;
14634     if (prev == NULL) {
14635       list = vnp;
14636     } else {
14637       prev->next = vnp;
14638     }
14639     prev = vnp;
14640   }
14641   return list;
14642 }
14643 
SortVnpByFeatSort(VoidPtr ptr1,VoidPtr ptr2)14644 static int LIBCALLBACK SortVnpByFeatSort (VoidPtr ptr1, VoidPtr ptr2)
14645 
14646 {
14647   ValNodePtr  vnp1;
14648   ValNodePtr  vnp2;
14649   FeatSortPtr f1, f2;
14650 
14651   if (ptr1 != NULL && ptr2 != NULL) {
14652     vnp1 = *((ValNodePtr PNTR) ptr1);
14653     vnp2 = *((ValNodePtr PNTR) ptr2);
14654     if (vnp1 != NULL && vnp2 != NULL) {
14655       f1 = (FeatSortPtr) vnp1->data.ptrvalue;
14656       f2 = (FeatSortPtr) vnp2->data.ptrvalue;
14657       if (f1 != NULL && f2 != NULL) {
14658         if (f1->start < f2->start) {
14659           return -1;
14660         } else if (f1->start > f2->start) {
14661           return 1;
14662         } else if (f1->stop > f2->stop) {
14663           return -1;
14664         } else if (f1->stop < f2->stop) {
14665           return 1;
14666         } else if (f1->sfp->data.choice < f2->sfp->data.choice) {
14667           return -1;
14668         } else if (f1->sfp->data.choice > f2->sfp->data.choice) {
14669           return 1;
14670         } else {
14671           return 0;
14672         }
14673       }
14674     }
14675   }
14676   return 0;
14677 }
14678 
14679 
14680 
SortSeqFeatInAnnot(SeqAnnotPtr sap)14681 NLM_EXTERN void SortSeqFeatInAnnot (SeqAnnotPtr sap)
14682 {
14683   ValNodePtr list;
14684 
14685   list = FeatSortListFromSeqAnnot (sap);
14686   list = ValNodeSort (list, SortVnpByFeatSort);
14687   if (list != NULL) {
14688     sap->data = SeqFeatListFromFeatSortList (list);
14689     list = FeatSortListFree (list);
14690   }
14691 }
14692 
14693 
14694 
14695 
AddFeaturesToList(DialoG d,ValNodePtr features)14696 NLM_EXTERN void AddFeaturesToList (DialoG d, ValNodePtr features)
14697 {
14698   FeatureSelectListDlgPtr dlg;
14699   BaR                     vbar;
14700   Int4                    scroll_pos;
14701   ValNodePtr              tmp;
14702 
14703   dlg = (FeatureSelectListDlgPtr) GetObjectExtra (d);
14704   if (dlg == NULL || features == NULL) {
14705     return;
14706   }
14707 
14708   ValNodeLink (&dlg->list, features);
14709   tmp = FeatSortListFromFeatValNodeList (dlg->list);
14710   tmp = ValNodeSort (tmp, SortVnpByFeatSort);
14711   dlg->list = ValNodeFree (dlg->list);
14712   dlg->list = FeatValNodeListFromFeatSortList (tmp);
14713   tmp = FeatSortListFree (tmp);
14714 
14715   vbar = GetSlateVScrollBar ((SlatE) dlg->doc);
14716   scroll_pos = GetBarValue (vbar);
14717   PopulateFeatureSelectList (dlg, dlg->list);
14718   SetBarValue (vbar, scroll_pos);
14719 }
14720 
14721 
14722 
14723 
14724 
14725 
14726