1 /*   e2trmlst.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:  e2trmlst.c
27 *
28 * Author:  Jonathan Kans, Greg Schuler, Jonathan Epstein, Tim Ford
29 *
30 * Version Creation Date:   10/30/01
31 *
32 * $Revision: 6.48 $
33 *
34 * File Description:
35 *
36 * Modifications:
37 * --------------------------------------------------------------------------
38 *
39 * ==========================================================================
40 */
41 
42 #include <vibrant.h>
43 #include <document.h>
44 #include <asn.h>
45 #include <ent2api.h>
46 #include <urlquery.h>
47 #include <dlogutil.h>
48 #include <medview.h>
49 #include <bspview.h>
50 #include <accutils.h>
51 
52 #include <entrez2.h>
53 
54 /*-------------------*/
55 /* Defined constants */
56 /*-------------------*/
57 
58 #define MAX_TAXONOMY_TREE_DEPTH  1024
59 #define TL_TERM_DELIMITER        ':'
60 #define E2_STR_BUFF_SIZE         256
61 #define E2_EXPLODE               FALSE
62 #define E2_DO_NOT_EXPLODE        TRUE
63 #define E2_TRANSLATE             FALSE
64 #define E2_DO_NOT_TRANSLATE      TRUE
65 #define E2_TERM_COL              1
66 #define E2_COUNT_COL             2
67 #define E2_LIST_MODIFIED         TRUE
68 #define E2_LIST_NOT_MODIFIED     FALSE
69 
70 #define MAX_MODES         11
71 
72 #define STATE_OFF         0
73 #define STATE_ON          1
74 
75 #define E2_RANGE_FROM     1
76 #define E2_RANGE_TO       2
77 
78 #define GROUP_NONE        0
79 #define GROUP_SINGLE      1
80 #define GROUP_FIRST       2
81 #define GROUP_MIDDLE      3
82 #define GROUP_LAST        4
83 
84 #define TERMLIST_OPERATOR             2
85 #define TERMLIST_TERM                 3
86 
87 #define ADV_QUERY_INVALID_STATE       0
88 #define ADV_QUERY_EVALUATE_STATE      1
89 #define ADV_QUERY_RETRIEVE_STATE      2
90 
91 #define AVAIL_WINDOW_ROWS             7
92 #define ADV_TEXT_MAX_LENGTH           8192
93 #define ADV_TEXT_WIDTH                20
94 #define ADV_TEXT_HEIGHT               7
95 
96 #define LEXCHAR_LPAREN                1
97 #define LEXCHAR_RPAREN                2
98 #define LEXCHAR_LBRACKET              3
99 #define LEXCHAR_RBRACKET              4
100 #define LEXCHAR_QUOTE                 5
101 #define LEXCHAR_AND                   6
102 #define LEXCHAR_OR                    7
103 #define LEXCHAR_NOT                   8
104 #define LEXCHAR_COMMA                 9
105 #define LEXCHAR_ATSIGN               10
106 #define LEXCHAR_BACKSLASH            11
107 #define LEXCHAR_WHITESPACE           12
108 #define LEXCHAR_SEMICOLON            13
109 #define LEXCHAR_COLON                14
110 #define LEXCHAR_EOL                  15
111 #define LEXCHAR_NULL                 16
112 #define LEXCHAR_OTHER                17
113 
114 #define LEXSTATE_IDLE                 0
115 #define LEXSTATE_BACKSLASHED          1
116 #define LEXSTATE_INQUOTE              2
117 #define LEXSTATE_INQUOTE_AFTERBSLASH  3
118 #define LEXSTATE_INSTRING             4
119 #define LEXSTATE_ERROR                5
120 
121 #define LEXTOK_LPAREN                 1
122 #define LEXTOK_RPAREN                 2
123 #define LEXTOK_LBRACKET               3
124 #define LEXTOK_RBRACKET               4
125 #define LEXTOK_AND                    5
126 #define LEXTOK_OR                     6
127 #define LEXTOK_NOT                    7
128 #define LEXTOK_COMMA                  8
129 #define LEXTOK_ATSIGN                 9
130 #define LEXTOK_STRING                10
131 #define LEXTOK_RANGE                 11
132 
133 #define ERR_CD_LEX                   17
134 
135 /*------------------------------*/
136 /* Defines for enumerated lists */
137 /*------------------------------*/
138 
139 typedef enum {
140   SELECTION_MODE = 1,
141   AUTOMATIC_MODE,
142   WILD_CARD_MODE,
143   MESH_TREE_MODE,
144   TAXONOMY_MODE,
145   RANGE_MODE,
146   LOOKUP_ACCN_MODE,
147   VIEW_ACCN_MODE,
148   LOOKUP_UID_MODE,
149   VIEW_UID_MODE,
150   TRANSLATE_MODE
151 } ModeChoice;
152 
ENUM_ALIST(mult_alist)153 static ENUM_ALIST(mult_alist)
154   {"Multiple",            AUTOMATIC_MODE},
155   {"Selection",           SELECTION_MODE},
156   {"Wild Card",           WILD_CARD_MODE},
157 END_ENUM_ALIST
158 
159 static ENUM_ALIST(auto_alist)
160   {"Automatic",           TRANSLATE_MODE},
161   {"Multiple",            AUTOMATIC_MODE},
162   {"Selection",           SELECTION_MODE},
163   {"Wild Card",           WILD_CARD_MODE},
164 END_ENUM_ALIST
165 
166 static ENUM_ALIST(accn_alist)
167   {"Lookup",              LOOKUP_ACCN_MODE},
168   {"Range",               RANGE_MODE},
169   {"Selection",           SELECTION_MODE},
170   {"Wild Card",           WILD_CARD_MODE},
171   {"View",                VIEW_ACCN_MODE},
172 END_ENUM_ALIST
173 
174 static ENUM_ALIST(mesh_alist)
175   {"MeSH Tree",           MESH_TREE_MODE},
176   {"Selection",           SELECTION_MODE},
177   {"Wild Card",           WILD_CARD_MODE},
178 END_ENUM_ALIST
179 
180 static ENUM_ALIST(tax_alist)
181   {"Selection",           SELECTION_MODE},
182   {"Taxonomy",            TAXONOMY_MODE},
183   {"Wild Card",           WILD_CARD_MODE},
184 END_ENUM_ALIST
185 
186 static ENUM_ALIST(default_alist)
187   {"Range",               RANGE_MODE},
188   {"Selection",           SELECTION_MODE},
189   {"Wild Card",           WILD_CARD_MODE},
190 END_ENUM_ALIST
191 
192 static ENUM_ALIST(range_alist)
193   {"Range",               RANGE_MODE},
194   {"Selection",           SELECTION_MODE},
195 END_ENUM_ALIST
196 
197 static ENUM_ALIST(trunc_alist)
198   {"Selection",           SELECTION_MODE},
199   {"Wild Card",           WILD_CARD_MODE},
200 END_ENUM_ALIST
201 
202 static ENUM_ALIST(uid_alist)
203   {"Lookup",              LOOKUP_UID_MODE},
204   {"View",                VIEW_UID_MODE},
205 END_ENUM_ALIST
206 
207 static EnumFieldAssocPtr mode_alists [] = {
208   mult_alist,
209   auto_alist,
210   accn_alist,
211   mesh_alist,
212   tax_alist,
213   default_alist,
214   range_alist,
215   trunc_alist,
216   uid_alist,
217   NULL
218 };
219 
220 typedef enum {
221   POPUP_MULT = 0,
222   POPUP_AUTO,
223   POPUP_ACCN,
224   POPUP_MESH,
225   POPUP_TAX,
226   POPUP_DEFAULT,
227   POPUP_RANGE,
228   POPUP_TRUNC,
229   POPUP_UID
230 } ModeIndex;
231 
232 /*-----------------------*/
233 /* Structure definitions */
234 /*-----------------------*/
235 
236 typedef struct trmstatedata {
237   CharPtr                   term;
238   CharPtr                   field;
239   Int4                      count;
240   Int2                      db;
241   Int2                      fld;
242   Int2                      group;
243   Int2                      above;
244   Int2                      below;
245   Int2                      state;
246   Int4Ptr                   uids;
247   CharPtr                   key;
248   struct trmstatedata PNTR  prev;
249   struct trmstatedata PNTR  next;
250 } StateData, PNTR StateDataPtr;
251 
252 typedef struct {
253   FORM_MESSAGE_BLOCK
254   E2RetrieveDocsProc  retrieveDocsProc;
255   E2RetrieveUidProc   retrieveUidProc;
256   GrouP               stdQueryGroup;
257   GrouP               advQueryGroup;
258   ButtoN              advEvaluateButton;
259   ButtoN              advRetrieveButton;
260   Int2                advQueryState;
261   ButtoN              advResetButton;
262   TexT                advQueryText;
263   Int2                advQueryLexPos;
264   CharPtr             advQueryLexStr;
265   Int2                advQueryLexState;
266   ValNodePtr          advQueryNextToken;
267   ValNode             advQueryNextRealNode;
268   Boolean             advQueryNewGroup;
269   PopuP PNTR          fieldsPopup;
270   PopuP               modesPopup [MAX_MODES];
271   GrouP               termGroup;
272   GrouP               rangeGroup;
273   IteM                advancedQueryItem;
274   IteM                explodeItem;
275   ModeChoice          currMode;
276   Int2                currField;
277   Int2                currDb;
278   DoC                 availDoc;
279   Int2                availItem;
280   Int2                availRow;
281   Int2                availClickItem;
282   Int2                availClickRow;
283   Int4                availNumTerms;
284   Int4                availPageSize;
285   Int2                availNumPages;
286   Int2                availCurrentPage;
287   Boolean             textChanged;
288   Int2                okayToAccept;
289   TexT                termText;
290   TexT                fromText;
291   TexT                toText;
292   Boolean             isValidFrom;
293   Boolean             isValidTo;
294   Boolean             isFromTextChanged;
295   Boolean             isToTextChanged;
296   Int2                currRangeField;
297   ButtoN              acceptButton;
298   PopuP               taxLineagePopup;
299   ValNodePtr          taxStrings;
300   PopuP               databasePopup;
301   ButtoN              retrieveButton;
302   ButtoN              resetButton;
303   Boolean             wasDoubleClick;
304   DoC                 chosenDoc;
305   Int2                chosenItem;
306   Int2                chosenClickItem;
307   Int2                chosenClickRow;
308   Int2                chosenClickCol;
309   Boolean             chosenInAboveBox;
310   Boolean             chosenInBelowBox;
311   Int2                chosenNumLines;
312   RecT                trackRect;
313   PoinT               trackPt;
314   StateDataPtr        termList;
315 } FormInfo, PNTR FormInfoPtr;
316 
317 /*----------------------------*/
318 /* File-wide static variables */
319 /*----------------------------*/
320 
321 static ChoicE         s_showASNItem;
322 static Entrez2InfoPtr s_masterE2ip = NULL;
323 
324 static ParData  availParFmt = { FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0 };
325 static ColData  availColFmt [] = {
326   {0, 5, 70, 0, NULL, 'l', FALSE, FALSE, FALSE, FALSE, FALSE},  /* term  */
327   {0, 5, 10, 0, NULL, 'r', FALSE, TRUE, FALSE, FALSE, FALSE},   /* count */
328   {0, 5, 10, 0, NULL, 'r', FALSE, FALSE, FALSE, FALSE, TRUE}    /* leaf  */
329 };
330 
331 static ParData  chosenParFmt = { FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0 };
332 static ColData  chosenColFmt [] = {
333   {0, 23, 70, 0, NULL, 'l', FALSE, FALSE, FALSE, FALSE, FALSE}, /* term  */
334   {0, 5, 10, 0, NULL, 'l', FALSE, FALSE, FALSE, FALSE, FALSE},  /* field */
335   {0, 5, 10, 0, NULL, 'r', FALSE, TRUE, FALSE, FALSE, TRUE}     /* count */
336 };
337 
338 /*---------------------*/
339 /* Function prototpyes */
340 /*---------------------*/
341 
342 static Boolean RemoveTermFromList (
343   FormInfoPtr pFormInfo,
344   StateDataPtr sdp,
345   Boolean goingDown,
346   Boolean lastDraggedDown
347 );
348 static Boolean Query_TranslateAndAddBoolTerm (
349   ForM f,
350   Int2 currDb,
351   Int2 currFld,
352   CharPtr strs,
353   Int2 state,
354   Int4 num
355 );
356 
357 static Boolean LoadAvailList (FormInfoPtr pFormInfo, CharPtr str);
358 
359 /*==================================================================*/
360 /*                                                                  */
361 /*  ShowASN () -  Returns the current setting of the s_showASN      */
362 /*               static variable.                                   */
363 /*                                                                  */
364 /*==================================================================*/
365 
ShowASN(void)366 NLM_EXTERN Boolean ShowASN (void)
367 
368 {
369   Int2  val;
370 
371   /*
372   return GetStatus (s_showASNItem);
373   */
374   val = GetValue (s_showASNItem);
375   if (val >= 11) return TRUE;
376   if (val < 2) return FALSE;
377   SetValue (s_showASNItem, val - 1);
378   if (val < 2) return FALSE;
379   return TRUE;
380 }
381 
LogOrLaunch(CharPtr path,CharPtr title)382 static void LogOrLaunch (CharPtr path, CharPtr title)
383 
384 {
385   Char    buf [257];
386   size_t  ct;
387   FILE    *ifp;
388   FILE    *ofp;
389   Int2    val;
390 
391   val = GetValue (s_showASNItem);
392   if (val == 12) {
393     ifp = FileOpen (path, "r");
394     ofp = FileOpen ("entrez2.log", "a");
395     if (ifp != NULL && ofp != NULL) {
396       while ((ct = FileRead (buf, 1, sizeof (buf) - 1, ifp)) > 0) {
397         FileWrite (buf, 1, ct, ofp);
398       }
399       fprintf (ofp, "\n");
400     }
401     FileClose (ofp);
402     FileClose (ifp);
403   } else {
404     LaunchGeneralTextViewer (path, title);
405   }
406 }
407 
408 /*==================================================================*/
409 /*                                                                  */
410 /*  DisplayEntrezRequest () - Displays an Entrez2 request in a      */
411 /*                           pop-up window.                         */
412 /*                                                                  */
413 /*==================================================================*/
414 
DisplayEntrezRequest(Entrez2RequestPtr e2rq)415 NLM_EXTERN void DisplayEntrezRequest (Entrez2RequestPtr e2rq)
416 
417 {
418   AsnIoPtr  aip;
419   Char      path [PATH_MAX];
420 
421   if (e2rq == NULL) return;
422   TmpNam (path);
423   aip = AsnIoOpen (path, "w");
424   if (aip == NULL) return;
425   Entrez2RequestAsnWrite (e2rq, aip, NULL);
426   AsnIoClose (aip);
427   LogOrLaunch (path, "Entrez2RequestAsnWrite");
428   FileRemove (path);
429 }
430 
431 /*==================================================================*/
432 /*                                                                  */
433 /*  DisplayEntrezReply () - Displays an Entrez2 reply in a pop-up   */
434 /*                         window.                                  */
435 /*                                                                  */
436 /*==================================================================*/
437 
DisplayEntrezReply(Entrez2ReplyPtr e2ry)438 NLM_EXTERN void DisplayEntrezReply (Entrez2ReplyPtr e2ry)
439 
440 {
441   AsnIoPtr  aip;
442   Char      path [PATH_MAX];
443 
444   if (e2ry == NULL) return;
445   TmpNam (path);
446   aip = AsnIoOpen (path, "w");
447   if (aip == NULL) return;
448   Entrez2ReplyAsnWrite (e2ry, aip, NULL);
449   AsnIoClose (aip);
450   LogOrLaunch (path, "Entrez2ReplyAsnWrite");
451   FileRemove (path);
452 }
453 
454 /* text version of entrez2 query for debugging purposes */
455 
EntrezTextWaitForReply(CONN conn)456 static Entrez2ReplyPtr EntrezTextWaitForReply (
457   CONN conn
458 )
459 
460 {
461   AsnIoConnPtr     aicp;
462   AsnIoPtr         aip;
463   Char             buffer [1025];
464   time_t           currtime, starttime;
465   Entrez2ReplyPtr  e2ry = NULL;
466   Boolean          first;
467   FILE *           fp;
468   time_t           max = 0;
469   size_t           n_read;
470   Boolean          special_read = FALSE;
471   EIO_Status       status;
472   STimeout         timeout;
473   Char             tmp [PATH_MAX];
474 
475   if (conn == NULL) return NULL;
476 
477   timeout.sec = 100;
478   timeout.usec = 0;
479 
480   starttime = GetSecs ();
481   while ((status = CONN_Wait (conn, eIO_Read, &timeout)) == eIO_Timeout && max < 300) {
482     currtime = GetSecs ();
483     max = currtime - starttime;
484   }
485   if (status == eIO_Success) {
486 #ifdef OS_UNIX
487     if (getenv ("ENTREZ2_RECORD_QUERY") != 0) {
488       special_read = TRUE;
489     }
490 #endif
491     if (special_read) {
492       TmpNam (tmp);
493 #ifdef OS_UNIX
494 printf ("TmpNam '%s'\n", tmp);
495 #endif
496       fp = FileOpen (tmp, "w");
497       if (fp != NULL) {
498 
499         first = TRUE;
500         do {
501           status = CONN_Read (conn, buffer, sizeof (buffer) -1, &n_read,
502                               first ? eIO_ReadPersist : eIO_ReadPlain);
503           buffer [n_read] = '\0';
504           if (first) {
505             if (StringStr (buffer, "Entrez2-reply") == NULL) {
506               ErrPostEx (SEV_ERROR, 0, 0, "EntrezReadReply failed on '%s'", buffer);
507               FileClose (fp);
508               /*
509               FileRemove (tmp);
510               */
511               return NULL;
512             }
513             first = FALSE;
514           }
515           fprintf (fp, "%s", buffer);
516         } while (status == eIO_Success);
517         FileClose (fp);
518 
519         aip = AsnIoOpen (tmp, "r");
520         e2ry = Entrez2ReplyAsnRead (aip, NULL);
521         AsnIoClose (aip);
522         /*
523         FileRemove (tmp);
524         */
525       }
526     } else {
527       aicp = QUERY_AsnIoConnOpen ("r", conn);
528       e2ry = Entrez2ReplyAsnRead (aicp->aip, NULL);
529       QUERY_AsnIoConnClose (aicp);
530     }
531   }
532   CONN_Close (conn);
533 
534   return e2ry;
535 }
536 
EntrezSpecialSynchronousQuery(Entrez2RequestPtr e2rq,Boolean textmode)537 static Entrez2ReplyPtr EntrezSpecialSynchronousQuery (
538   Entrez2RequestPtr e2rq,
539   Boolean textmode
540 )
541 
542 {
543   AsnIoConnPtr     aicp;
544   CONN             conn;
545   Entrez2ReplyPtr  e2ry;
546   CharPtr          tempcookie = NULL;
547   CharPtr          host_machine = NULL;
548   Uint2            host_port = 0;
549   CharPtr          host_path = NULL;
550   CharPtr          env_machine = NULL;
551   CharPtr          env_path = NULL;
552   CharPtr          env_port = NULL;
553   int              val = 0;
554 
555   if (e2rq == NULL) return NULL;
556 
557 #ifdef OS_UNIX
558   env_machine = (CharPtr) getenv ("NCBI_ENTREZ2_HOST_MACHINE");
559   if (! StringHasNoText (env_machine)) {
560     host_machine = env_machine;
561   }
562 #endif
563   if (StringHasNoText (host_machine)) {
564     host_machine = "www.ncbi.nlm.nih.gov";
565   }
566 
567 #ifdef OS_UNIX
568   env_port = (CharPtr) getenv ("NCBI_ENTREZ2_HOST_PORT");
569   if (! StringHasNoText (env_port)) {
570     if (sscanf (env_port, "%d", &val) == 1) {
571       host_port = (Uint2) val;
572     }
573   }
574 #endif
575   if (host_port == 0) {
576     host_port = 80;
577   }
578 
579 #ifdef OS_UNIX
580   env_path = (CharPtr) getenv ("NCBI_ENTREZ2_HOST_PATH");
581   if (! StringHasNoText (env_path)) {
582     host_path = env_path;
583   }
584 #endif
585   if (StringHasNoText (host_path)) {
586     host_path = "/entrez/eutils/entrez2server.fcgi";
587   }
588 
589   if (textmode) {
590     conn = QUERY_OpenUrlQuery (host_machine, host_port, host_path, NULL,
591                                "Entrez2Text", 30, eMIME_T_NcbiData,
592                                eMIME_AsnText, eENCOD_None, 0);
593 
594     aicp = QUERY_AsnIoConnOpen ("w", conn);
595   } else {
596     conn = QUERY_OpenUrlQuery (host_machine, host_port, host_path, NULL,
597                                "Entrez2Text", 30, eMIME_T_NcbiData,
598                                eMIME_AsnBinary, eENCOD_None, 0);
599 
600     aicp = QUERY_AsnIoConnOpen ("wb", conn);
601   }
602 
603   tempcookie = e2rq->cookie;
604 
605   Entrez2RequestAsnWrite (e2rq, aicp->aip, NULL);
606 
607   e2rq->cookie = tempcookie;
608 
609   AsnIoFlush (aicp->aip);
610   QUERY_AsnIoConnClose (aicp);
611 
612   QUERY_SendQuery (conn);
613 
614   if (textmode) {
615     e2ry = EntrezTextWaitForReply (conn);
616   } else {
617     e2ry = EntrezWaitForReply (conn);
618   }
619 
620   return e2ry;
621 }
622 
623 extern Entrez2ReplyPtr SpecialEntrezSynchronousQuery (
624   Entrez2RequestPtr e2rq
625 );
626 
SpecialEntrezSynchronousQuery(Entrez2RequestPtr e2rq)627 extern Entrez2ReplyPtr SpecialEntrezSynchronousQuery (
628   Entrez2RequestPtr e2rq
629 )
630 
631 {
632 #ifdef OS_UNIX
633   if (getenv ("ENTREZ2_TEXT_QUERY") != 0) {
634     return EntrezSpecialSynchronousQuery (e2rq, TRUE);
635   }
636   if (getenv ("ENTREZ2_BINARY_QUERY") != 0) {
637     return EntrezSpecialSynchronousQuery (e2rq, FALSE);
638   }
639 #endif
640   return EntrezSynchronousQuery (e2rq);
641 }
642 
643 /*==================================================================*/
644 /*                                                                  */
645 /*  DBGetInfo () - Given a database ID, return the DB pointer.      */
646 /*                                                                  */
647 /*==================================================================*/
648 
DBGetInfo(Int2 dbId)649 static Entrez2DbInfoPtr DBGetInfo (Int2 dbId)
650 
651 {
652   Int2              count;
653   Entrez2InfoPtr    e2ip;
654   Entrez2DbInfoPtr  e2db;
655 
656   /*------------------*/
657   /* Check parameters */
658   /*------------------*/
659 
660   if (dbId < 0) return NULL;
661 
662   /*----------------------------------*/
663   /* Get information on the databases */
664   /*----------------------------------*/
665 
666   e2ip = Query_GetInfo ();
667 
668   /*-----------------------*/
669   /* Find the requested DB */
670   /*-----------------------*/
671 
672   for (e2db = e2ip->db_info, count = 0; e2db != NULL; e2db = e2db->next, count++) {
673     if (count == dbId) return e2db;
674   }
675 
676   return NULL;
677 }
678 
679 /*==================================================================*/
680 /*                                                                  */
681 /*  DBGetNameFromID () - Given a DB ID, returns its name.           */
682 /*                                                                  */
683 /*==================================================================*/
684 
DBGetNameFromID(Int2 dbId)685 NLM_EXTERN CharPtr DBGetNameFromID (Int2 dbId)
686 
687 {
688   Int2              count;
689   Entrez2InfoPtr    e2ip;
690   Entrez2DbInfoPtr  e2db;
691 
692   /*-----------------*/
693   /* Check parameter */
694   /*-----------------*/
695 
696   if (dbId < 0) return NULL;
697 
698   /*----------------------------------*/
699   /* Get information on the databases */
700   /*----------------------------------*/
701 
702   e2ip = Query_GetInfo ();
703 
704   /*--------------------------*/
705   /* Find to the requested DB */
706   /*--------------------------*/
707 
708   for (e2db = e2ip->db_info, count = 0; e2db != NULL; e2db = e2db->next, count++) {
709     if (count != dbId) continue;
710     if (StringHasNoText (e2db->db_name)) continue;
711     return e2db->db_name;
712   }
713 
714   return NULL;
715 }
716 
717 /*==================================================================*/
718 /*                                                                  */
719 /*  DBGetIDFromName () - Given a DB name, returns its unique ID.    */
720 /*                                                                  */
721 /*==================================================================*/
722 
DBGetIDFromName(CharPtr dbName)723 NLM_EXTERN Int2 DBGetIDFromName (CharPtr dbName)
724 
725 {
726   Int2              count;
727   Entrez2InfoPtr    e2ip;
728   Entrez2DbInfoPtr  e2db;
729 
730   /*-----------------*/
731   /* Check parameter */
732   /*-----------------*/
733 
734   if (dbName == NULL) return -1;
735 
736   /*----------------------------------*/
737   /* Get information on the databases */
738   /*----------------------------------*/
739 
740   e2ip = Query_GetInfo ();
741 
742   /*---------------------------*/
743   /* Look for the requested DB */
744   /*---------------------------*/
745 
746   for (e2db = e2ip->db_info, count = 0; e2db != NULL; e2db = e2db->next, count++) {
747     if (StrICmp (e2db->db_name, dbName) == 0) return count;
748   }
749 
750   return -1;
751 }
752 
753 /*==================================================================*/
754 /*                                                                  */
755 /*  FieldGetInfo () - Given a database ID and a field ID, return    */
756 /*                    the field name.                               */
757 /*                                                                  */
758 /*==================================================================*/
759 
FieldGetInfo(Int2 dbId,Int2 fieldId)760 static Entrez2FieldInfoPtr FieldGetInfo (Int2 dbId, Int2 fieldId)
761 
762 {
763   Int2                 count;
764   Entrez2DbInfoPtr     e2db;
765   Entrez2FieldInfoPtr  e2fd;
766 
767   /*------------------*/
768   /* Check parameters */
769   /*------------------*/
770 
771   if (dbId < 0 || fieldId < 0) return NULL;
772 
773   /*----------------------------------*/
774   /* Find the requested DB            */
775   /*----------------------------------*/
776 
777   e2db = DBGetInfo (dbId);
778   if (e2db == NULL) return NULL;
779 
780   /*----------------*/
781   /* Get field info */
782   /*----------------*/
783 
784   for (e2fd = e2db->fields, count = 0; e2fd != NULL; e2fd = e2fd->next, count++) {
785     if (count == fieldId) return e2fd;
786   }
787 
788   return NULL;
789 }
790 
791 /*==================================================================*/
792 /*                                                                  */
793 /*  IsValidFieldName () - Given a database ID and a field name,     */
794 /*                        check to see if it is as valid name.      */
795 /*                                                                  */
796 /*==================================================================*/
797 
IsValidFieldName(Int2 dbId,CharPtr fieldName)798 static Boolean IsValidFieldName (Int2 dbId, CharPtr fieldName)
799 
800 {
801   Entrez2DbInfoPtr     e2db;
802   Entrez2FieldInfoPtr  e2fd;
803 
804   /*------------------*/
805   /* Check parameters */
806   /*------------------*/
807 
808   if (dbId < 0 || fieldName == NULL) return FALSE;
809 
810   /*-----------------------*/
811   /* Find the requested DB */
812   /*-----------------------*/
813 
814   e2db = DBGetInfo (dbId);
815   if (e2db == NULL) return FALSE;
816 
817   /*----------------*/
818   /* Get field info */
819   /*----------------*/
820 
821   for (e2fd = e2db->fields; e2fd != NULL; e2fd = e2fd->next) {
822     if (StrICmp (e2fd->field_name, fieldName) == 0)
823       return TRUE;
824   }
825 
826   return FALSE;
827 }
828 
829 /*===================================================================*/
830 /*                                                                   */
831 /*  FieldGetNameFromMenuName () - Given a field menu name and a      */
832 /*                               database ID, return the field name. */
833 /*                                                                   */
834 /*===================================================================*/
835 
FieldGetNameFromMenuName(Int2 dbId,CharPtr menuName)836 static CharPtr FieldGetNameFromMenuName (Int2 dbId, CharPtr menuName)
837 
838 {
839   Entrez2DbInfoPtr     e2db;
840   Entrez2FieldInfoPtr  e2fd;
841 
842   /*------------------*/
843   /* Check parameters */
844   /*------------------*/
845 
846   if (menuName == NULL || dbId < 0) return NULL;
847 
848   /*-----------------------*/
849   /* Find the requested DB */
850   /*-----------------------*/
851 
852   e2db = DBGetInfo (dbId);
853   if (e2db == NULL) return NULL;
854 
855   /*--------------------------*/
856   /* Find the requested field */
857   /*--------------------------*/
858 
859   for (e2fd = e2db->fields; e2fd != NULL; e2fd = e2fd->next) {
860     if (StrICmp (e2fd->field_menu, menuName) == 0) return e2fd->field_name;
861   }
862 
863   return NULL;
864 }
865 
866 /*==================================================================*/
867 /*                                                                  */
868 /*  FieldGetIDFromName () - Given a field name and a database ID,   */
869 /*                         return the field ID.                     */
870 /*                                                                  */
871 /*==================================================================*/
872 
FieldGetIDFromName(Int2 dbId,CharPtr fieldName)873 static Int2 FieldGetIDFromName (Int2 dbId, CharPtr fieldName)
874 
875 {
876   Int2                 count;
877   Entrez2DbInfoPtr     e2db;
878   Entrez2FieldInfoPtr  e2fd;
879 
880   /*------------------*/
881   /* Check parameters */
882   /*------------------*/
883 
884   if (fieldName == NULL || dbId < 0) return -1;
885 
886   /*-----------------------*/
887   /* Find the requested DB */
888   /*-----------------------*/
889 
890   e2db = DBGetInfo (dbId);
891   if (e2db == NULL) return -1;
892 
893   /*--------------------------*/
894   /* Find the requested field */
895   /*--------------------------*/
896 
897   for (e2fd = e2db->fields, count = 0; e2fd != NULL; e2fd = e2fd->next, count++) {
898     if (StrICmp (e2fd->field_name, fieldName) == 0) return count;
899   }
900 
901   return -1;
902 }
903 
904 /*==================================================================*/
905 /*                                                                  */
906 /*  FieldGetInfoFromName () - This is desigend to get field info    */
907 /*                           given only a field name. It is useful  */
908 /*                           for a getting information on a field   */
909 /*                           in a sorted alist of fields.           */
910 /*                                                                  */
911 /*==================================================================*/
912 
FieldGetInfoFromName(CharPtr fieldName)913 static Entrez2FieldInfoPtr FieldGetInfoFromName (CharPtr fieldName)
914 
915 {
916   Int2                 count;
917   Entrez2InfoPtr       e2ip;
918   Entrez2DbInfoPtr     e2db;
919   Entrez2FieldInfoPtr  e2fd;
920 
921   /*------------------*/
922   /* Check parameters */
923   /*------------------*/
924 
925   if (fieldName == NULL) return NULL;
926 
927   /*----------------------------------*/
928   /* Get information on the databases */
929   /*----------------------------------*/
930 
931   e2ip = Query_GetInfo ();
932 
933   /*-------------------------------*/
934   /* Find the requested field info */
935   /*-------------------------------*/
936 
937   for (e2db = e2ip->db_info, count = 0; e2db != NULL; e2db = e2db->next, count++) {
938     for (e2fd = e2db->fields; e2fd != NULL; e2fd = e2fd->next) {
939       if (StrICmp (e2fd->field_name, fieldName) == 0) return e2fd;
940     }
941   }
942 
943   return NULL;
944 }
945 
946 /*==================================================================*/
947 /*                                                                  */
948 /* FieldGetModePopup () -                                           */
949 /*                                                                  */
950 /*==================================================================*/
951 
FieldGetModePopup(Int2 dbId,Int2 fieldId,EnumFieldAssocPtr fieldAList,FormInfoPtr pFormInfo)952 static Int2 FieldGetModePopup (Int2 dbId, Int2 fieldId, EnumFieldAssocPtr fieldAList, FormInfoPtr pFormInfo)
953 
954 {
955   Entrez2DbInfoPtr     dbInfo;
956   Entrez2FieldInfoPtr  fieldInfo;
957   Boolean              is_rangable;
958   Boolean              is_truncatable;
959   ModeIndex            modeId = POPUP_DEFAULT;
960 
961   /*-----------------------------------------*/
962   /* Find the requested field, and determine */
963   /* its corresponding mode list popup.      */
964   /*-----------------------------------------*/
965 
966   dbInfo = DBGetInfo (dbId);
967   if (dbInfo == NULL) return -1;
968 
969   fieldInfo = FieldGetInfo (dbId, fieldId);
970   if (fieldInfo == NULL) return -1;
971 
972   /* is_rangable = fieldInfo->is_rangable; */
973   is_rangable = (Boolean) (fieldInfo->is_date || fieldInfo->is_numerical);
974   /* is_truncatable = fieldInfo->is_truncatable; */
975   is_truncatable = (Boolean) (! is_rangable);
976 
977   if (StringICmp (dbInfo->db_name, "PubMed") == 0 &&
978       StringICmp (fieldInfo->field_name, "ALL") == 0) {
979     modeId = POPUP_AUTO;
980   } else if (StringICmp (fieldInfo->field_name, "ALL") == 0) {
981     modeId = POPUP_MULT;
982   } else if ((StringICmp (fieldInfo->field_name, "TITL") == 0) ||
983              (StringICmp (fieldInfo->field_name, "WORD") == 0) ||
984              (StringICmp (fieldInfo->field_name, "TIAB") == 0)) {
985     modeId = POPUP_MULT;
986   } else if (StringICmp (fieldInfo->field_name, "ACCN") == 0 ||
987              StringICmp (fieldInfo->field_name, "PACC") == 0) {
988     modeId = POPUP_ACCN;
989   } else if (StringICmp (fieldInfo->field_name, "ORGN") == 0) {
990     modeId = POPUP_TAX;
991   } else if (StringICmp (fieldInfo->field_name, "MESH") == 0 ||
992              StringICmp (fieldInfo->field_name, "MAJR") == 0) {
993     modeId = POPUP_MESH;
994   } else if (StringICmp (fieldInfo->field_name, "UID") == 0) {
995     modeId = POPUP_UID;
996   } else if (is_rangable && is_truncatable) {
997     modeId = POPUP_DEFAULT;
998   } else if (is_rangable) {
999     modeId = POPUP_RANGE;
1000   } else if (is_truncatable) {
1001     modeId = POPUP_TRUNC;
1002   } else {
1003     modeId = POPUP_DEFAULT;
1004   }
1005 
1006   pFormInfo->currField = FieldGetIDFromName (dbId, fieldInfo->field_name);
1007   return modeId;
1008 }
1009 
1010 /*==================================================================*/
1011 /*                                                                  */
1012 /*  CreateDatabaseAlist () - Returns alist of database names        */
1013 /*                                                                  */
1014 /*==================================================================*/
1015 
CreateDatabaseAlist(Entrez2InfoPtr e2ip)1016 EnumFieldAssocPtr CreateDatabaseAlist (Entrez2InfoPtr e2ip)
1017 
1018 {
1019   EnumFieldAssocPtr  alist;
1020   Uint1              choice;
1021   Entrez2DbInfoPtr   e2db;
1022   ValNodePtr         head = NULL;
1023 
1024   if (e2ip == NULL || e2ip->db_count < 1) return NULL;
1025 
1026   for (e2db = e2ip->db_info; e2db != NULL; e2db = e2db->next) {
1027     if (StringHasNoText (e2db->db_menu)) continue;
1028     choice = (Uint1) DBGetIDFromName (e2db->db_name);
1029     ValNodeCopyStr (&head, choice, e2db->db_menu);
1030   }
1031 
1032   alist = MakeEnumFieldAlistFromValNodeList (head);
1033   ValNodeFreeData (head);
1034 
1035   return alist;
1036 }
1037 
1038 /*==================================================================*/
1039 /*                                                                  */
1040 /*  CreateFieldAlist () - Returns sorted alist of field names for   */
1041 /*                       the given database.                        */
1042 /*                                                                  */
1043 /*==================================================================*/
1044 
CreateFieldAlist(Entrez2DbInfoPtr e2db)1045 EnumFieldAssocPtr CreateFieldAlist (Entrez2DbInfoPtr e2db)
1046 
1047 {
1048   EnumFieldAssocPtr    alist;
1049   Uint1                choice;
1050   Entrez2FieldInfoPtr  fieldInfo;
1051   Int2                 dbId;
1052   ValNodePtr           head = NULL;
1053 
1054   if (e2db == NULL || e2db->field_count < 1) return NULL;
1055 
1056   dbId = DBGetIDFromName (e2db->db_name);
1057   for (fieldInfo = e2db->fields; fieldInfo != NULL; fieldInfo = fieldInfo->next) {
1058     if (StringHasNoText (fieldInfo->field_name)) continue;
1059     choice = (Uint1) FieldGetIDFromName (dbId, fieldInfo->field_name);
1060     ValNodeCopyStr (&head, choice, fieldInfo->field_menu);
1061   }
1062 
1063   head = ValNodeSort (head, SortVnpByString);
1064 
1065   alist = MakeEnumFieldAlistFromValNodeList (head);
1066   ValNodeFreeData (head);
1067 
1068   return alist;
1069 }
1070 
1071 /*==================================================================*/
1072 /*                                                                  */
1073 /*  CreateAllFieldsAlist () - Returns sorted uniqued alist of all   */
1074 /*                           field names.                           */
1075 /*                                                                  */
1076 /*==================================================================*/
1077 
CreateAllFieldsAlist(Entrez2InfoPtr e2ip)1078 static EnumFieldAssocPtr CreateAllFieldsAlist (Entrez2InfoPtr e2ip)
1079 
1080 {
1081   EnumFieldAssocPtr    alist;
1082   Uint1                choice;
1083   Entrez2DbInfoPtr     e2db;
1084   Entrez2FieldInfoPtr  fieldInfo;
1085   Int2                 dbId;
1086   ValNodePtr           head = NULL;
1087 
1088   for (e2db = e2ip->db_info; e2db != NULL; e2db = e2db->next) {
1089     dbId = DBGetIDFromName (e2db->db_name);
1090     for (fieldInfo = e2db->fields; fieldInfo != NULL; fieldInfo = fieldInfo->next) {
1091       if (StringHasNoText (fieldInfo->field_name)) continue;
1092       choice = (Uint1) FieldGetIDFromName (dbId, fieldInfo->field_name);
1093       ValNodeCopyStr (&head, choice, fieldInfo->field_name);
1094     }
1095   }
1096 
1097   head = ValNodeSort (head, SortVnpByString);
1098   head = UniqueValNode (head);
1099 
1100   alist = MakeEnumFieldAlistFromValNodeList (head);
1101   ValNodeFreeData (head);
1102 
1103   return alist;
1104 }
1105 
1106 /*==================================================================*/
1107 /*                                                                  */
1108 /*  GetUidFromAccn () -                                             */
1109 /*                                                                  */
1110 /*==================================================================*/
1111 
GetUidFromAccn(CharPtr dbName,CharPtr accn)1112 static Uint4 GetUidFromAccn (CharPtr dbName, CharPtr accn)
1113 
1114 {
1115   Entrez2BooleanReplyPtr  e2br;
1116   Entrez2IdListPtr        e2id;
1117   Entrez2RequestPtr       e2rq;
1118   Entrez2ReplyPtr         e2ry;
1119   Char                    ch;
1120   CharPtr                 ptr;
1121   Char                    str [61];
1122   Uint4                   uid = 0;
1123 
1124   if (StringHasNoText (dbName) || StringHasNoText (accn)) return 0;
1125 
1126   StringNCpy_0 (str, accn, sizeof (str));
1127   ptr = str;
1128   ch = *ptr;
1129   while (ch != '\0') {
1130     if (ch == '|' || ch == '.') {
1131       *ptr = ' ';
1132     }
1133     ptr++;
1134     ch = *ptr;
1135   }
1136   TrimSpacesAroundString (str);
1137   if (StringStr (str, "[ACCN]") == NULL) {
1138     StringCat (str, "[ACCN]");
1139   }
1140   e2rq = EntrezCreateBooleanRequest (TRUE, FALSE, dbName, str, 0, 0, NULL, 1, 0);
1141 
1142   if (e2rq == NULL) return 0;
1143   e2ry = SpecialEntrezSynchronousQuery (e2rq);
1144   e2rq = Entrez2RequestFree (e2rq);
1145   if (e2ry == NULL) return 0;
1146   e2br = EntrezExtractBooleanReply (e2ry);
1147   if (e2br == NULL) return 0;
1148 
1149   if (e2br->count > 0) {
1150     e2id = e2br->uids;
1151     if (e2id != NULL && e2id->num > 0 && e2id->uids != NULL) {
1152       BSSeek (e2id->uids, 0, SEEK_SET);
1153       uid = Nlm_BSGetUint4 (e2id->uids);
1154     }
1155   }
1156 
1157   Entrez2BooleanReplyFree (e2br);
1158 
1159   return uid;
1160 }
1161 
1162 /*==================================================================*/
1163 /*                                                                  */
1164 /*  ProcessDirectLookup () -                                        */
1165 /*                                                                  */
1166 /*==================================================================*/
1167 
ProcessDirectLookup(FormInfoPtr pFormInfo,CharPtr str)1168 static void ProcessDirectLookup (FormInfoPtr pFormInfo, CharPtr str)
1169 
1170 {
1171   CharPtr  dbName;
1172   Int4     uid;
1173 
1174   uid = 0;
1175 
1176   /*----------------------------------------*/
1177   /* Convert the given string to a UID and */
1178   /* check to see if it is a valid one.    */
1179   /*---------------------------------------*/
1180 
1181   if ((pFormInfo->currMode == LOOKUP_ACCN_MODE) || (pFormInfo->currMode == VIEW_ACCN_MODE)) {
1182     if (StringLen (str) > 0) {
1183       dbName = DBGetNameFromID (pFormInfo->currDb);
1184       uid = GetUidFromAccn (dbName, str);
1185     }
1186   } else if ((pFormInfo->currMode == LOOKUP_UID_MODE) || (pFormInfo->currMode == VIEW_UID_MODE)) {
1187     if (! StrToLong (str, &uid)) {
1188       Message (MSG_OK, "You must enter an integer");
1189       return;
1190     }
1191   } else
1192     return;
1193 
1194   if (uid <= 0) {
1195     if (pFormInfo->currMode == LOOKUP_ACCN_MODE || pFormInfo->currMode == VIEW_ACCN_MODE) {
1196       Message (MSG_OK, "This accession is not present in the database");
1197     } else {
1198       Message (MSG_OK, "This UID is not present in the database");
1199     }
1200     return;
1201   }
1202 
1203   /*-------------------------------------*/
1204   /* Lookup the record for the given UID */
1205   /* and display it in a DocSum window.  */
1206   /*-------------------------------------*/
1207 
1208   if (pFormInfo->currMode == LOOKUP_ACCN_MODE || pFormInfo->currMode == LOOKUP_UID_MODE) {
1209     dbName = DBGetNameFromID (pFormInfo->currDb);
1210     pFormInfo->retrieveUidProc (pFormInfo->form, uid, dbName);
1211   } else {
1212     LaunchRecViewer (pFormInfo->form, uid, 1, &uid, pFormInfo->currDb, 1);
1213   }
1214 }
1215 
1216 /*==================================================================*/
1217 /*                                                                  */
1218 /*  DoResetAvail () - Clears out the Term List object.              */
1219 /*                                                                  */
1220 /*==================================================================*/
1221 
DoResetAvail(FormInfoPtr pFormInfo,Boolean clearTerm)1222 static void DoResetAvail (FormInfoPtr pFormInfo, Boolean clearTerm)
1223 
1224 {
1225   Int2  i;
1226 
1227   if (clearTerm) {
1228     SafeSetTitle (pFormInfo->termText, "");
1229     SafeSetTitle (pFormInfo->toText, "");
1230     SafeSetTitle (pFormInfo->fromText, "");
1231     SafeDisable (pFormInfo->acceptButton);
1232   } else if (pFormInfo->currMode == RANGE_MODE) {
1233     if (TextHasNoText (pFormInfo->fromText) && TextHasNoText (pFormInfo->toText))
1234       SafeDisable (pFormInfo->acceptButton);
1235     else
1236       SafeEnable (pFormInfo->acceptButton);
1237   } else {
1238     if (TextHasNoText (pFormInfo->termText))
1239       SafeDisable (pFormInfo->acceptButton);
1240     else
1241       SafeEnable (pFormInfo->acceptButton);
1242   }
1243 
1244   pFormInfo->availItem = 0;
1245   pFormInfo->availRow = 0;
1246   Reset (pFormInfo->availDoc);
1247   SetDocCache (pFormInfo->availDoc, NULL, NULL, NULL);
1248 
1249   for (i = 0; i < 7; i++)
1250     AppendText (pFormInfo->availDoc, " \n", &availParFmt, availColFmt, systemFont);
1251 
1252   InvalDocument (pFormInfo->availDoc);
1253   SafeHide (pFormInfo->taxLineagePopup);
1254   Reset (pFormInfo->taxLineagePopup);
1255   pFormInfo->taxStrings = ValNodeFreeData (pFormInfo->taxStrings);
1256   pFormInfo->availNumTerms = 0;
1257   pFormInfo->availPageSize = 0;
1258   pFormInfo->availNumPages = 0;
1259 }
1260 
1261 /*==================================================================*/
1262 /*                                                                  */
1263 /* FreeTerm () - Frees a given term from the term list.             */
1264 /*                                                                  */
1265 /*==================================================================*/
1266 
FreeTerm(StateDataPtr termPtr)1267 static void FreeTerm (StateDataPtr termPtr)
1268 
1269 {
1270   MemFree (termPtr->term);
1271   MemFree (termPtr->field);
1272   MemFree (termPtr);
1273 }
1274 
1275 /*==================================================================*/
1276 /*                                                                  */
1277 /* FreeTermList () - Frees all the terms in the current query       */
1278 /*                    term list.                                    */
1279 /*                                                                  */
1280 /*==================================================================*/
1281 
FreeTermList(FormInfoPtr pFormInfo)1282 static StateDataPtr FreeTermList (FormInfoPtr pFormInfo)
1283 
1284 {
1285   StateDataPtr  next;
1286 
1287   while (pFormInfo->termList != NULL) {
1288     next = pFormInfo->termList->next;
1289     FreeTerm (pFormInfo->termList);
1290     pFormInfo->termList = next;
1291   }
1292 
1293   return NULL;
1294 }
1295 
1296 /*==================================================================*/
1297 /*                                                                  */
1298 /*  ResetChosen () - Clears out the Query Refinement object.        */
1299 /*                                                                  */
1300 /*==================================================================*/
1301 
ResetChosen(FormInfoPtr pFormInfo)1302 static void ResetChosen (FormInfoPtr pFormInfo)
1303 
1304 {
1305   /*--------------*/
1306   /* Clear it out */
1307   /*--------------*/
1308 
1309   Reset (pFormInfo->chosenDoc);
1310   FreeTermList (pFormInfo);
1311   SetDocCache (pFormInfo->chosenDoc, NULL, NULL, NULL);
1312 
1313   InvalDocument (pFormInfo->chosenDoc);
1314   pFormInfo->chosenNumLines = 0;
1315 
1316   SafeSetTitle (pFormInfo->retrieveButton, "Retrieve 0 Documents");
1317   SafeDisable (pFormInfo->retrieveButton);
1318 }
1319 
1320 /*==================================================================*/
1321 /*                                                                  */
1322 /*  Reset_Callback () - Called when reset button is pushed. Clears  */
1323 /*                     the Term List and Query Refinement windows.  */
1324 /*                                                                  */
1325 /*==================================================================*/
1326 
Reset_Callback(ButtoN b)1327 static void Reset_Callback (ButtoN b)
1328 
1329 {
1330   FormInfoPtr  pFormInfo;
1331 
1332   pFormInfo = (FormInfoPtr) GetObjectExtra (b);
1333   DoResetAvail (pFormInfo, TRUE);
1334   ResetChosen (pFormInfo);
1335   Reset (pFormInfo->advQueryText);
1336   pFormInfo->isValidFrom = FALSE;
1337   pFormInfo->isValidTo = FALSE;
1338 }
1339 
1340 /*==================================================================*/
1341 /*                                                                  */
1342 /*  StateDataNew() - Creates a new Query term structure and adds    */
1343 /*                     it to the query term list.                   */
1344 /*                                                                  */
1345 /*==================================================================*/
1346 
StateDataNew(FormInfoPtr pFormInfo)1347 static StateDataPtr StateDataNew (FormInfoPtr pFormInfo)
1348 
1349 {
1350   StateDataPtr  newNode;
1351   StateDataPtr  tempNode;
1352 
1353   /*-------------------*/
1354   /* Create a new node */
1355   /*-------------------*/
1356 
1357   newNode = (StateDataPtr) MemNew (sizeof (StateData));
1358   if (newNode == NULL) return NULL;
1359 
1360   /*-------------------------------*/
1361   /* Add it to the end of the list */
1362   /*-------------------------------*/
1363 
1364   tempNode = pFormInfo->termList;
1365   if (tempNode != NULL) {
1366     while (tempNode->next != NULL)
1367       tempNode = tempNode->next;
1368     tempNode->next = newNode;
1369     newNode->prev = tempNode;
1370   } else {                      /* Empty list -- this is first term */
1371 
1372     newNode->prev = NULL;
1373     newNode->next = NULL;
1374     pFormInfo->termList = newNode;
1375   }
1376 
1377   /*---------------------*/
1378   /* Return successfully */
1379   /*---------------------*/
1380 
1381   return newNode;
1382 }
1383 
1384 /*===================================================================*/
1385 /*                                                                   */
1386 /*  CreateTerm () - Creates a new boolean term using the given       */
1387 /*                       data and adds it to the linked list of      */
1388 /*                       terms.                                      */
1389 /*                                                                   */
1390 /*===================================================================*/
1391 
CreateTerm(ForM f,Int2 currDb,Int2 currFld,CharPtr strs,Int2 state,Int4 num,Boolean allowDuplicates)1392 static StateDataPtr CreateTerm (
1393   ForM    f,
1394   Int2    currDb,
1395   Int2    currFld,
1396   CharPtr strs,
1397   Int2    state,
1398   Int4    num,
1399   Boolean allowDuplicates
1400 )
1401 
1402 {
1403   StateDataPtr         prev;
1404   StateDataPtr         sdp;
1405   Entrez2FieldInfoPtr  fieldInfo;
1406   FormInfoPtr          pFormInfo;
1407 
1408   pFormInfo = (FormInfoPtr) GetObjectExtra (f);
1409 
1410   /*----------------------------------*/
1411   /* Make sure we're don't try to add */
1412   /* the same string twice.           */
1413   /*----------------------------------*/
1414 
1415   if (! allowDuplicates) {
1416     for (sdp = pFormInfo->termList; sdp != NULL; sdp = sdp->next) {
1417       if (MeshStringICmp (sdp->term, strs) == 0 &&
1418           sdp->db == currDb && sdp->fld == currFld) return NULL;
1419     }
1420   }
1421 
1422   /*------------------------------*/
1423   /* Create a term for the string */
1424   /* on the end of the list.      */
1425   /*------------------------------*/
1426 
1427   sdp = StateDataNew (pFormInfo);
1428   if (pFormInfo->termList == NULL)
1429     pFormInfo->termList = sdp;
1430 
1431   if (sdp == NULL) return NULL;
1432 
1433   (pFormInfo->chosenNumLines)++;
1434 
1435   sdp->term = StringSave (strs);
1436   sdp->count = num;
1437   sdp->db = currDb;
1438   sdp->fld = currFld;
1439   sdp->uids = NULL;
1440   sdp->key = NULL;
1441   fieldInfo = FieldGetInfo (currDb, currFld);
1442   if (fieldInfo == NULL) return NULL;
1443   sdp->field = StringSave (fieldInfo->field_name);
1444   if (sdp->field == NULL)
1445     sdp->field = StringSave ("----");
1446   sdp->group = GROUP_SINGLE;
1447   sdp->above = ENTREZ_OP_NONE;
1448 
1449   /*-------------------------------------*/
1450   /* Add the term to the current Query's */
1451   /* linked list of terms.               */
1452   /*-------------------------------------*/
1453 
1454   prev = sdp->prev;
1455   if (prev != NULL) {
1456     sdp->above = ENTREZ_OP_AND;
1457     prev->below = ENTREZ_OP_AND;
1458   }
1459   sdp->below = ENTREZ_OP_NONE;
1460   sdp->state = state;
1461 
1462   /*------------------------------*/
1463   /* Return a ptr to the new term */
1464   /*------------------------------*/
1465 
1466   return sdp;
1467 }
1468 
1469 /*==================================================================*/
1470 /*                                                                  */
1471 /*  DisplayTerm () -                                                */
1472 /*                                                                  */
1473 /*==================================================================*/
1474 
DisplayTerm(FormInfoPtr pFormInfo,CharPtr term,CharPtr fieldName,Int4 total)1475 static void DisplayTerm (FormInfoPtr pFormInfo, CharPtr term, CharPtr fieldName, Int4 total)
1476 
1477 {
1478   RecT  r;
1479   BaR   sb;
1480   Char  strn [256];
1481 
1482   /*------------------------------------------*/
1483   /* Create a display string for the term and */
1484   /* add it to the 'chosen' window.           */
1485   /*------------------------------------------*/
1486 
1487   sprintf (strn, "%s\t [%s]\t%ld\n", term, fieldName, (long) total);
1488   AppendText (pFormInfo->chosenDoc, strn, &chosenParFmt, chosenColFmt, systemFont);
1489 
1490   /*---------------------------------*/
1491   /* Display our new query string in */
1492   /* Query Refinement window.        */
1493   /*---------------------------------*/
1494 
1495   InvalDocRows (pFormInfo->chosenDoc, pFormInfo->chosenNumLines, 1, 1);
1496   AdjustDocScroll (pFormInfo->chosenDoc);
1497   sb = GetSlateVScrollBar ((SlatE) pFormInfo->chosenDoc);
1498   ResetClip ();
1499   SetBarValue (sb, MAX (pFormInfo->chosenNumLines - 7, 0));
1500   ObjectRect (pFormInfo->chosenDoc, &r);
1501   InsetRect (&r, 4, 4);
1502   r.right = r.left + 16;
1503   InsetRect (&r, -1, -1);
1504   Select (pFormInfo->chosenDoc);
1505   InvalRect (&r);
1506 
1507   Update ();
1508 }
1509 
1510 /*==================================================================*/
1511 /*                                                                  */
1512 /*  Query_AddBoolTerm () - Adds a boolean term to the linked list   */
1513 /*                        of terms that form the query.             */
1514 /*                                                                  */
1515 /*==================================================================*/
1516 
Query_AddBoolTerm(ForM f,Int2 currDb,Int2 currFld,CharPtr strs,Int2 state,Int4 num)1517 static StateDataPtr Query_AddBoolTerm (ForM f, Int2 currDb, Int2 currFld, CharPtr strs, Int2 state, Int4 num)
1518 
1519 {
1520   StateDataPtr  sdp;
1521   FormInfoPtr   pFormInfo;
1522 
1523   pFormInfo = (FormInfoPtr) GetObjectExtra (f);
1524 
1525   /*-----------------------------*/
1526   /* Add the term and display it */
1527   /*-----------------------------*/
1528 
1529   sdp = CreateTerm (f, currDb, currFld, strs, state, num, FALSE);
1530   if (sdp != NULL) {
1531     DisplayTerm (pFormInfo, strs, sdp->field, num);
1532   }
1533 
1534   /*------------------------------*/
1535   /* Return a ptr to the new term */
1536   /*------------------------------*/
1537 
1538   return sdp;
1539 }
1540 
1541 /*==================================================================*/
1542 /*                                                                  */
1543 /*  ProcessMeshTerm () -                                            */
1544 /*                                                                  */
1545 /*==================================================================*/
1546 
ProcessMeshTerm(FormInfoPtr pFormInfo,CharPtr str)1547 static void ProcessMeshTerm (FormInfoPtr pFormInfo, CharPtr str)
1548 
1549 {
1550   Int4     iTermCount;
1551   CharPtr  ptr;
1552   CharPtr  text;
1553 
1554   /*---------------------------*/
1555   /* Trim off extra spaces and */
1556   /* curly-bracketed info      */
1557   /*---------------------------*/
1558 
1559   ptr = str;
1560   while (*ptr != '\0' && *ptr != '{') {
1561     ptr++;
1562   }
1563   *ptr = '\0';
1564 
1565   /*-----------------------------*/
1566   /* Get the term count from the */
1567   /* term selection window.      */
1568   /*-----------------------------*/
1569 
1570   text = GetDocText (pFormInfo->availDoc, pFormInfo->availItem, pFormInfo->availRow, E2_COUNT_COL);
1571   TrimSpacesAroundString (text);
1572   StrToLong (text, &iTermCount);
1573   MemFree (text);
1574 
1575   /*-------------------------------*/
1576   /* Load the chosen term into the */
1577   /* query refinement window.      */
1578   /*-------------------------------*/
1579 
1580   Query_AddBoolTerm (pFormInfo->form, pFormInfo->currDb, pFormInfo->currField, str, STATE_ON, iTermCount);
1581 }
1582 
1583 /*==================================================================*/
1584 /*                                                                  */
1585 /*  ValNodeMerge () -                                               */
1586 /*                                                                  */
1587 /*==================================================================*/
1588 
ValNodeMerge(ValNodePtr head)1589 static CharPtr ValNodeMerge (ValNodePtr head)
1590 
1591 {
1592   size_t      len;
1593   CharPtr     str;
1594   CharPtr     to;
1595   ValNodePtr  vnp;
1596 
1597   if (head == NULL) return NULL;
1598 
1599   for (vnp = head, len = 0; vnp != NULL; vnp = vnp->next)
1600     len += StringLen ((CharPtr) vnp->data.ptrvalue);
1601 
1602   str = (CharPtr) MemNew (len + 4);
1603   if (str == NULL) return NULL;
1604 
1605   for (vnp = head, to = str; vnp != NULL; vnp = vnp->next)
1606     to = StringMove (to, (CharPtr) vnp->data.ptrvalue);
1607 
1608   return str;
1609 }
1610 
1611 /*==================================================================*/
1612 /*                                                                  */
1613 /*  FetchFromTermList () -                                          */
1614 /*                                                                  */
1615 /*==================================================================*/
1616 
FetchFromTermList(DoC d,Int2 item,Pointer ptr)1617 static CharPtr FetchFromTermList (DoC d, Int2 item, Pointer ptr)
1618 
1619 {
1620   FormInfoPtr          pFormInfo;
1621   CharPtr              db, field;
1622   Entrez2RequestPtr    e2rq;
1623   Entrez2ReplyPtr      e2ry;
1624   Entrez2TermListPtr   e2tl;
1625   Entrez2TermPtr       e2tp;
1626   Entrez2FieldInfoPtr  fieldInfo;
1627   Int4                 firstPos, numTerms, page;
1628   ValNodePtr           head = NULL;
1629   CharPtr              rsult = NULL;
1630   Char                 str [256], tmp [16];
1631 
1632   pFormInfo = (FormInfoPtr) GetObjectExtra (d);
1633 
1634   if (item < 1) return NULL;
1635 
1636   page = item - 1;
1637 
1638   db = DBGetNameFromID (pFormInfo->currDb);
1639   fieldInfo = FieldGetInfo (pFormInfo->currDb, pFormInfo->currField);
1640   field = fieldInfo->field_name;
1641   if (StringHasNoText (db) || StringHasNoText (field)) return NULL;
1642 
1643   firstPos = pFormInfo->availPageSize * page;
1644   numTerms = pFormInfo->availPageSize;
1645   if (firstPos + numTerms > pFormInfo->availNumTerms)
1646     numTerms = pFormInfo->availNumTerms - firstPos;
1647 
1648   e2rq = EntrezCreateGetTermListRequest (db, field, firstPos, numTerms);
1649   if (e2rq == NULL) return NULL;
1650 
1651   if (ShowASN () == TRUE)
1652     DisplayEntrezRequest (e2rq);
1653 
1654   e2ry = SpecialEntrezSynchronousQuery (e2rq);
1655   if (e2ry != NULL) {
1656     if (ShowASN () == TRUE)
1657       DisplayEntrezReply (e2ry);
1658 
1659     e2tl = EntrezExtractTermListReply (e2ry);
1660     if (e2tl != NULL)
1661       for (e2tp = e2tl->list; e2tp != NULL; e2tp = e2tp->next) {
1662         StringNCpy_0 (str, e2tp->term, sizeof (str) - 16);
1663         sprintf (tmp, "\t%ld\n", (long) e2tp->count);
1664         StringCat (str, tmp);
1665         ValNodeCopyStr (&head, 0, str);
1666       }
1667   }
1668   Entrez2RequestFree (e2rq);
1669 
1670   rsult = ValNodeMerge (head);
1671   ValNodeFreeData (head);
1672 
1673   return rsult;
1674 }
1675 
1676 /*==================================================================*/
1677 /*                                                                  */
1678 /*  GetTermPage () -                                                */
1679 /*                                                                  */
1680 /*==================================================================*/
1681 
GetTermPage(FormInfoPtr pFormInfo,CharPtr str)1682 static Int4 GetTermPage (FormInfoPtr pFormInfo, CharPtr str)
1683 
1684 {
1685   CharPtr              db;
1686   CharPtr              field;
1687   Entrez2RequestPtr    e2rq;
1688   Entrez2ReplyPtr      e2ry;
1689   Int4                 pagesize = -1;
1690   Int4                 pos = -1;
1691   Int4                 rsult = -1;
1692   Entrez2FieldInfoPtr  fieldInfo;
1693 
1694   db = DBGetNameFromID (pFormInfo->currDb);
1695   fieldInfo = FieldGetInfo (pFormInfo->currDb, pFormInfo->currField);
1696   field = fieldInfo->field_name;
1697 
1698   if (StringHasNoText (db) || StringHasNoText (field)) return rsult;
1699 
1700   e2rq = EntrezCreateGetTermPositionRequest (db, field, str);
1701   if (e2rq == NULL) return rsult;
1702 
1703   if (ShowASN () == TRUE)
1704     DisplayEntrezRequest (e2rq);
1705 
1706   e2ry = SpecialEntrezSynchronousQuery (e2rq);
1707   if (e2ry != NULL) {
1708     if (ShowASN () == TRUE)
1709       DisplayEntrezReply (e2ry);
1710 
1711     pos = EntrezExtractTermPosReply (e2ry);
1712     pagesize = pFormInfo->availPageSize;
1713     if (pagesize > 0)
1714       rsult = (pos - 1) / pagesize;
1715   }
1716   Entrez2RequestFree (e2rq);
1717 
1718   if (pos == -1) return -1;
1719 
1720   return rsult;
1721 }
1722 
1723 /*==================================================================*/
1724 /*                                                                  */
1725 /*  ChangeUnderscoreToSpace () -                                    */
1726 /*                                                                  */
1727 /*==================================================================*/
1728 
ChangeUnderscoreToSpace(CharPtr str)1729 static void ChangeUnderscoreToSpace (CharPtr str)
1730 
1731 {
1732   Char     ch;
1733   CharPtr  ptr;
1734 
1735   if (str == NULL) return;
1736   ptr = str;
1737   ch = *ptr;
1738   while (ch != '\0') {
1739     if (ch == '_')
1740       *ptr = ' ';
1741     ptr++;
1742     ch = *ptr;
1743   }
1744 }
1745 
1746 /*==================================================================*/
1747 /*                                                                  */
1748 /*  ChangePeriodToSpace () -                                    */
1749 /*                                                                  */
1750 /*==================================================================*/
1751 
ChangePeriodToSpace(CharPtr str)1752 static void ChangePeriodToSpace (CharPtr str)
1753 
1754 {
1755   Char     ch;
1756   CharPtr  ptr;
1757 
1758   if (str == NULL) return;
1759   ptr = str;
1760   ch = *ptr;
1761   while (ch != '\0') {
1762     if (ch == '.')
1763       *ptr = ' ';
1764     ptr++;
1765     ch = *ptr;
1766   }
1767 }
1768 
1769 /*==================================================================*/
1770 /*                                                                  */
1771 /*  ChangeMeshSlashSymbol () -                                      */
1772 /*                                                                  */
1773 /*==================================================================*/
1774 
ChangeMeshSlashSymbol(CharPtr str)1775 static void ChangeMeshSlashSymbol (CharPtr str)
1776 
1777 {
1778   Char     ch;
1779   CharPtr  ptr;
1780 
1781   if (str == NULL) return;
1782 
1783   ptr = str;
1784   ch = *ptr;
1785   while (ch != '\0') {
1786     if (ch == '/')
1787       *ptr = '\31';
1788     ptr++;
1789     ch = *ptr;
1790   }
1791 }
1792 
1793 /*==================================================================*/
1794 /*                                                                  */
1795 /*  FindLineOfText () - Assumes a string of text separated by       */
1796 /*                     newline, characters, and terminated by a     */
1797 /*                     newline                                      */
1798 /*                                                                  */
1799 /*==================================================================*/
1800 
FindLineOfText(CharPtr text,CharPtr str)1801 static Int2 FindLineOfText (CharPtr text, CharPtr str)
1802 
1803 {
1804   Char          ch;
1805   Int2          compare, idx, left, mid, numLines, right;
1806   CharPtr PNTR  index;
1807   CharPtr       lookfor, ptr;
1808   size_t        len;
1809 
1810   /* Check parameters */
1811 
1812   if (StringLen (text) == 0 || StringLen (str) == 0) return 0;
1813 
1814   /* Count the number of lines to be searched */
1815 
1816   mid = 0;
1817   lookfor = StringSave (str);
1818   ChangeMeshSlashSymbol (lookfor);
1819   numLines = 0;
1820   ptr = text;
1821   ch = *ptr;
1822   while (ch != '\0') {
1823     if (ch == '\n')
1824       numLines++;
1825     ptr++;
1826     ch = *ptr;
1827   }
1828 
1829   if (numLines <= 0) {
1830     MemFree (lookfor);
1831     return 0;
1832   }
1833 
1834   /* Create an array of pointers to the lines */
1835 
1836   index = MemNew (sizeof (CharPtr) * (size_t) (numLines + 3));
1837   if (index != NULL) {
1838     idx = 0;
1839     ptr = text;
1840     ch = *ptr;
1841     index [idx] = ptr;
1842     while (ch != '\0') {
1843       if (ch == '\n') {
1844         idx++;
1845         *ptr = '\0';
1846         ptr++;
1847         ch = *ptr;
1848         index [idx] = ptr;
1849       } else {
1850         ptr++;
1851         ch = *ptr;
1852       }
1853     }
1854   }
1855 
1856   /* Do a binary search for the search string */
1857 
1858   if (index != NULL) {
1859     left = 1;
1860     right = numLines;
1861     while (left <= right) {
1862       mid = (left + right) / 2;
1863       compare = StringICmp (lookfor, index [mid - 1]);
1864       if (compare <= 0)
1865         right = mid - 1;
1866       if (compare >= 0)
1867         left = mid + 1;
1868     }
1869 
1870     if (left <= right + 1) {
1871       len = StringLen (lookfor);
1872       compare = StringNICmp (lookfor, index [mid - 1], len);
1873       if (compare > 0) {
1874         mid++;
1875         /*
1876         if (mid <= numLines) {
1877       compare = StringNICmp (lookfor, index [mid - 1], len);
1878       if (compare > 0)
1879         mid = 0;
1880         } else
1881       mid = 0;
1882         */
1883       }
1884       /*
1885       else
1886         mid = 0;
1887       */
1888     }
1889   }
1890 
1891   /* Clean up and return */
1892 
1893   MemFree (index);
1894   MemFree (lookfor);
1895   return mid;
1896 }
1897 
1898 /*==================================================================*/
1899 /*                                                                  */
1900 /*  ScrollToText () -                                               */
1901 /*                                                                  */
1902 /*==================================================================*/
1903 
ScrollToText(FormInfoPtr pFormInfo,CharPtr str,Int2 page,Boolean hard,Boolean exact)1904 static void ScrollToText (FormInfoPtr pFormInfo,
1905               CharPtr     str,
1906               Int2        page,
1907               Boolean     hard,
1908               Boolean     exact)
1909 
1910 {
1911   Int2     compare, oldItem, oldRow, perfect, row;
1912   size_t   len;
1913   Int4     numLines, startsAt;
1914   BaR      sb;
1915   Char     temp [256];
1916   CharPtr  text;
1917 
1918   /* Check parameters */
1919 
1920   if (StringHasNoText (str) || page == 0) return;
1921 
1922   /* Clean up the text string */
1923 
1924   StringNCpy_0 (temp, str, sizeof (temp));
1925   ChangeUnderscoreToSpace (temp);
1926   ChangePeriodToSpace (temp);
1927   ChangeMeshSlashSymbol (temp);
1928 
1929   /* Get the information on the current page of data */
1930 
1931   text = GetDocText (pFormInfo->availDoc, page, 0, 1);
1932   GetItemParams4 (pFormInfo->availDoc, page, &startsAt, NULL, NULL, NULL, NULL);
1933   GetDocParams4 (pFormInfo->availDoc, NULL, &numLines);
1934   ChangeMeshSlashSymbol (text);
1935 
1936   /* Search for the text string in the current page of data */
1937 
1938   row = FindLineOfText (text, temp);
1939   MemFree (text);
1940 
1941   /* If the text string is not on the page */
1942   /* then go to the top of the page.       */
1943 
1944   if (row < 1 || row > numLines)
1945     /*
1946     return;
1947     */
1948     row = 1;
1949 
1950   /* If the term is not on the current page then */
1951   /* we have to load and search the new page.    */
1952 
1953   /*
1954   if (row <= 1 || row >= numLines) {
1955     LoadAvailList (pFormInfo, str);
1956     return;
1957   }
1958   */
1959 
1960   /* Redisplay the page with the text string highlighted */
1961 
1962   startsAt += row - 1;
1963   sb = GetSlateVScrollBar ((SlatE) pFormInfo->availDoc);
1964   CorrectBarMax (sb, numLines - 7);
1965   if (!RowIsVisible (pFormInfo->availDoc, page, row, NULL, NULL)) {
1966     ForceFormat (pFormInfo->availDoc, page);    /* forces UpdateLineStarts */
1967     GetItemParams4 (pFormInfo->availDoc, page, &startsAt, NULL, NULL,
1968             NULL, NULL);
1969     GetDocParams4 (pFormInfo->availDoc, NULL, &numLines);
1970     startsAt += row - 1;
1971     sb = GetSlateVScrollBar ((SlatE) pFormInfo->availDoc);
1972     CorrectBarMax (sb, numLines - 7);
1973     if (hard)
1974       SetBarValue (sb, startsAt);
1975     else
1976       CorrectBarValue (sb, startsAt);
1977   }
1978   text = GetDocText (pFormInfo->availDoc, page, row, 1);
1979   ChangeMeshSlashSymbol (text);
1980   perfect = StringICmp (text, temp);
1981   len = StringLen (temp);
1982   compare = StringNICmp (text, temp, len);
1983   MemFree (text);
1984   if (compare == 0) {
1985     oldItem = pFormInfo->availItem;
1986     oldRow = pFormInfo->availRow;
1987     if (oldItem != page || oldRow != row) {
1988       pFormInfo->availItem = page;
1989       pFormInfo->availRow = row;
1990       InvalDocRows (pFormInfo->availDoc, oldItem, oldRow, oldRow);
1991       InvalDocRows (pFormInfo->availDoc, pFormInfo->availItem,
1992             pFormInfo->availRow, pFormInfo->availRow);
1993     }
1994     if (exact) {
1995       if (perfect == 0)
1996         pFormInfo->textChanged = FALSE;
1997     } else
1998       pFormInfo->textChanged = FALSE;
1999   } else {
2000     pFormInfo->availItem = 0;
2001     pFormInfo->availRow = 0;
2002   }
2003 }
2004 
2005 /*==================================================================*/
2006 /*                                                                  */
2007 /*  LoadAvailList () -                                              */
2008 /*                                                                  */
2009 /*==================================================================*/
2010 
LoadAvailList(FormInfoPtr pFormInfo,CharPtr str)2011 static Boolean LoadAvailList (FormInfoPtr pFormInfo, CharPtr str)
2012 
2013 {
2014   Int4                 count;
2015   Entrez2FieldInfoPtr  fieldInfo;
2016   Int4                 pagesize;
2017   Int2                 numpages = 0;
2018   Int2                 page = 0;
2019 
2020   pFormInfo->availItem = 0;
2021   pFormInfo->availRow = 0;
2022   Reset (pFormInfo->availDoc);
2023   SetDocCache (pFormInfo->availDoc, NULL, NULL, NULL);
2024   Update ();
2025   if (str [0] == '\0') return FALSE;
2026 
2027   fieldInfo = FieldGetInfo (pFormInfo->currDb, pFormInfo->currField);
2028   count = fieldInfo->term_count;
2029   if (count == 0) return FALSE;
2030 
2031   pFormInfo->availNumTerms = count;
2032   pagesize = 1;
2033   while (count > pagesize) {
2034     count /= 2;
2035     pagesize *= 2;
2036   }
2037 
2038   while (count < 16000 && pagesize > 128) {
2039     count *= 2;
2040     pagesize /= 2;
2041   }
2042   pFormInfo->availPageSize = pagesize;
2043   numpages = (Int2) ((pFormInfo->availNumTerms + pagesize - 1) / pagesize);
2044   pFormInfo->availNumPages = numpages;
2045 
2046   BulkAppendItem (pFormInfo->availDoc, numpages, FetchFromTermList, pagesize, &availParFmt, availColFmt, systemFont);
2047   AppendText (pFormInfo->availDoc, "\n\n\n\n\n\n\n\n\n\n\n\n \n", &availParFmt, availColFmt, systemFont);
2048 
2049   SetDocCache (pFormInfo->availDoc, StdPutDocCache, StdGetDocCache, StdResetDocCache);
2050 
2051   page = GetTermPage (pFormInfo, str);
2052   pFormInfo->availCurrentPage = page + 1;
2053   if (page != -1) {
2054     ScrollToText (pFormInfo, str, pFormInfo->availCurrentPage, FALSE, FALSE);
2055   }
2056 
2057   InvalDocument (pFormInfo->availDoc);
2058   Update ();
2059   AdjustDocScroll (pFormInfo->availDoc);
2060 
2061   return TRUE;
2062 }
2063 
2064 /*==================================================================*/
2065 /*                                                                  */
2066 /*  ProcessSelectionTerm () -                                       */
2067 /*                                                                  */
2068 /*==================================================================*/
2069 
ProcessSelectionTerm(FormInfoPtr pFormInfo,CharPtr str)2070 static void ProcessSelectionTerm (FormInfoPtr pFormInfo, CharPtr str)
2071 
2072 {
2073   Int4     iTermCount;
2074   Char     termText [E2_STR_BUFF_SIZE];
2075   CharPtr  text;
2076 
2077   /* If a new term has been typed into the */
2078   /* term text entry box, then do a lookup */
2079   /* of that term.                         */
2080 
2081   if (pFormInfo->textChanged) {
2082     LoadAvailList (pFormInfo, str);
2083     pFormInfo->textChanged = FALSE;
2084     pFormInfo->okayToAccept = FALSE;
2085   }
2086 
2087   /* Process the highlighted term from */
2088   /* the term selection box            */
2089 
2090   else if (pFormInfo->okayToAccept &&
2091        pFormInfo->availItem > 0 &&
2092        pFormInfo->availRow > 0) {
2093 
2094     text = GetDocText (pFormInfo->availDoc, pFormInfo->availItem,
2095                pFormInfo->availRow, E2_TERM_COL);
2096     if (NULL == text)
2097       return;
2098 
2099     GetTitle (pFormInfo->termText, termText, E2_STR_BUFF_SIZE);
2100 
2101     /* If the higlighted term is the same as */
2102     /* in the text entry box, then add the   */
2103     /* term to the Query Refinement list.    */
2104 
2105     if (StringICmp (termText, text) == 0) {
2106       if (StringICmp (str, text) == 0) {
2107     MemFree (text);
2108     text = GetDocText (pFormInfo->availDoc, pFormInfo->availItem,
2109                pFormInfo->availRow, E2_COUNT_COL);
2110     TrimSpacesAroundString (text);
2111     StrToLong (text, &iTermCount);
2112     MemFree (text);
2113     Query_AddBoolTerm (pFormInfo->form, pFormInfo->currDb,
2114                pFormInfo->currField, str, STATE_ON,
2115                iTermCount);
2116     Select (pFormInfo->termText);
2117     pFormInfo->okayToAccept = FALSE;
2118       }
2119     }
2120 
2121     /* Otherwise, just move the higlighted */
2122     /* term to the text box.               */
2123 
2124     else {
2125       TrimSpacesAroundString (text);
2126       SafeSetTitle (pFormInfo->termText, text);
2127       Select (pFormInfo->termText);
2128       Update ();
2129       StringNCpy_0 (str, text, E2_STR_BUFF_SIZE);
2130     }
2131 
2132   }
2133 }
2134 
2135 /*==================================================================*/
2136 /*                                                                  */
2137 /*  ProcessTaxonomyTerm () -                                        */
2138 /*                                                                  */
2139 /*==================================================================*/
2140 
ProcessTaxonomyTerm(FormInfoPtr pFormInfo,CharPtr str)2141 static void ProcessTaxonomyTerm (FormInfoPtr pFormInfo, CharPtr str)
2142 
2143 {
2144   Int4     iTermCount;
2145   CharPtr  text;
2146 
2147   /*----------------------*/
2148   /* Get the term's count */
2149   /*----------------------*/
2150 
2151   text = GetDocText (pFormInfo->availDoc, pFormInfo->availItem, pFormInfo->availRow, E2_COUNT_COL);
2152   TrimSpacesAroundString (text);
2153   StrToLong (text, &iTermCount);
2154   MemFree (text);
2155 
2156   /*-----------------------------------*/
2157   /* Add the term to the current query */
2158   /*-----------------------------------*/
2159 
2160   Query_AddBoolTerm (pFormInfo->form, pFormInfo->currDb, pFormInfo->currField, str, STATE_ON, iTermCount);
2161   Select (pFormInfo->termText);
2162   pFormInfo->okayToAccept = FALSE;
2163 }
2164 
2165 /*===================================================================*/
2166 /*                                                                   */
2167 /*  ReadAFew () - Fetches the count for a given term and for several */
2168 /*               following terms and displays them in the term list  */
2169 /*               panel.                                              */
2170 /*                                                                   */
2171 /*===================================================================*/
2172 
ReadAFew(FormInfoPtr pFormInfo,CharPtr str,CharPtr actual,size_t maxsize,Int4Ptr count)2173 static Boolean ReadAFew (FormInfoPtr pFormInfo, CharPtr str, CharPtr actual, size_t maxsize, Int4Ptr count)
2174 
2175 {
2176   Char                 displayStr [256];
2177   Boolean              found;
2178   Entrez2TermListPtr   e2TermListPtr;
2179   Entrez2FieldInfoPtr  fieldInfo;
2180   CharPtr              dbName;
2181   CharPtr              fieldName;
2182   Int2                 row;
2183   Entrez2TermPtr       termPtr;
2184 
2185   /*------------------------------*/
2186   /* Get the names of the current */
2187   /* db and the current field.    */
2188   /*------------------------------*/
2189 
2190   found = FALSE;
2191   dbName = DBGetNameFromID (pFormInfo->currDb);
2192   fieldInfo = FieldGetInfo (pFormInfo->currDb, pFormInfo->currField);
2193   fieldName = fieldInfo->field_name;
2194   if (StringHasNoText (dbName) || StringHasNoText (fieldName)) return FALSE;
2195 
2196   /*----------------------------------------*/
2197   /* Fetch a count for the requested string */
2198   /* and for several strings after it.      */
2199   /*----------------------------------------*/
2200 
2201   e2TermListPtr = Query_FetchSeveralCounts (dbName, fieldName, str, AVAIL_WINDOW_ROWS);
2202 
2203   if (e2TermListPtr == NULL) return FALSE;
2204 
2205   /*-------------------------------*/
2206   /* Did we find the desired term? */
2207   /*-------------------------------*/
2208 
2209   if (StringICmp (e2TermListPtr->list->term, str) == 0) {
2210     found = TRUE;
2211   } else {
2212     found = FALSE;
2213     StringCpy (actual, e2TermListPtr->list->term);
2214   }
2215 
2216   /*----------------------------*/
2217   /* Send the count back to the */
2218   /* calling function.          */
2219   /*----------------------------*/
2220 
2221   *count = e2TermListPtr->list->count;
2222 
2223   /*-------------------------------------*/
2224   /* Display the term and it's neighbors */
2225   /* in the term list window.            */
2226   /*-------------------------------------*/
2227 
2228   termPtr = e2TermListPtr->list;
2229 
2230   for (row = 1, termPtr = e2TermListPtr->list; row <= *count, termPtr != NULL; row++, termPtr = termPtr->next) {
2231     sprintf (displayStr, "%s\t%ld\t%d\n", termPtr->term, (long) (termPtr->count), (int) (termPtr->is_leaf_node ? 1 : 0));
2232     AppendText (pFormInfo->availDoc, displayStr, &availParFmt, availColFmt, systemFont);
2233   }
2234 
2235   if (found) {
2236     pFormInfo->availItem = 1;
2237     pFormInfo->availRow = 1;
2238   }
2239   InvalDocument (pFormInfo->availDoc);
2240 
2241   /*---------------------*/
2242   /* Return successfully */
2243   /*---------------------*/
2244 
2245   return found;
2246 }
2247 
2248 /*==================================================================*/
2249 /*                                                                  */
2250 /*  ProcessMultipleTerms () -                                       */
2251 /*                                                                  */
2252 /*==================================================================*/
2253 
ProcessMultipleTerms(FormInfoPtr pFormInfo,CharPtr strs)2254 static void ProcessMultipleTerms (FormInfoPtr pFormInfo, CharPtr strs)
2255 
2256 {
2257   Char     actual [256];
2258   Char     ch;
2259   Int4     count = 0;
2260   Boolean  found;
2261   Int2     i;
2262   Int2     j;
2263   Int2     k;
2264   Char     str [256];
2265 
2266   i = 0;
2267   while (StringLen (strs + i) > 0) {
2268 
2269     /*--------------------------------*/
2270     /* Parse a term out of the string */
2271     /*--------------------------------*/
2272 
2273     StringNCpy_0 (str, strs + i, sizeof (str));
2274     k = 0;
2275     ch = str [k];
2276     while (ch == ' ') {
2277       k++;
2278       ch = str [k];
2279     }
2280     j = 0;
2281     if (ch == '"') {
2282       k++;
2283       ch = str [j + k];
2284       while (ch != '\0' && ch != '"') {
2285         j++;
2286         ch = str [j + k];
2287       }
2288       if (ch == '"') {
2289         str [j + k] = '\0';
2290         i += j + k + 1;
2291       } else
2292         i += j + k;
2293     } else {
2294       while (ch != '\0' && ch != ' ') {
2295         j++;
2296         ch = str [j + k];
2297       }
2298       if (ch == ' ') {
2299         str [j + k] = '\0';
2300         i += j + k + 1;
2301       } else
2302         i += j + k;
2303     }
2304 
2305     /*-----------------------------------*/
2306     /* If we successfully parsed a term, */
2307     /* look it up and then add it to the */
2308     /* boolean query if found.           */
2309     /*-----------------------------------*/
2310 
2311     if (StringLen (str + k) > 0) {
2312       pFormInfo->availItem = 0;
2313       pFormInfo->availRow = 0;
2314       Reset (pFormInfo->availDoc);
2315       actual [0] = '\0';
2316       found = ReadAFew (pFormInfo, str + k, actual, sizeof (actual), &count);
2317       Update ();
2318       if (found) {
2319         Query_AddBoolTerm (pFormInfo->form, pFormInfo->currDb, pFormInfo->currField, str + k, STATE_ON, count);
2320       } else {
2321         Query_AddBoolTerm (pFormInfo->form, pFormInfo->currDb, pFormInfo->currField, actual, STATE_OFF, count);
2322       }
2323     }
2324   }
2325 
2326   /*-------------------------------------*/
2327   /* Clear out the term selection window */
2328   /* and the term entry fields.          */
2329   /*-------------------------------------*/
2330 
2331   pFormInfo->availItem = 0;
2332   pFormInfo->availRow = 0;
2333   Reset (pFormInfo->availDoc);
2334 
2335   InvalDocument (pFormInfo->availDoc);
2336   SafeSetTitle (pFormInfo->termText, "");
2337   SafeSetTitle (pFormInfo->fromText, "");
2338   SafeSetTitle (pFormInfo->toText, "");
2339   SafeDisable (pFormInfo->acceptButton);
2340   if (Visible (pFormInfo->termText)) {
2341     Select (pFormInfo->termText);
2342   }
2343 }
2344 
2345 /*==================================================================*/
2346 /*                                                                  */
2347 /*  RecalculateChosen () -                                          */
2348 /*                                                                  */
2349 /*==================================================================*/
2350 
RecalculateChosen(FormInfoPtr pFormInfo)2351 static void RecalculateChosen (FormInfoPtr pFormInfo)
2352 
2353 {
2354   Int4  count;
2355   Char  tmp [32];
2356 
2357   /*-------------------------------*/
2358   /* Get a count of documents that */
2359   /* satisfy the current query.    */
2360   /*-------------------------------*/
2361 
2362   count = Query_FetchCount (pFormInfo->form);
2363 
2364   /*-----------------------------------*/
2365   /* Update the retrieve message count */
2366   /*-----------------------------------*/
2367 
2368   if (count < 1)
2369     sprintf (tmp, "Retrieve 0 Documents");
2370   else if (count > 1)
2371     sprintf (tmp, "Retrieve %ld Documents", (long) count);
2372   else
2373     sprintf (tmp, "Retrieve %ld Document", (long) count);
2374 
2375   SafeSetTitle (pFormInfo->retrieveButton, tmp);
2376   SafeSetTitle (pFormInfo->advRetrieveButton, tmp);
2377 
2378   if (count < 1 || count > 32000) {
2379     SafeDisable (pFormInfo->retrieveButton);
2380     SafeDisable (pFormInfo->advRetrieveButton);
2381   } else {
2382     SafeEnable (pFormInfo->retrieveButton);
2383     SafeEnable (pFormInfo->advRetrieveButton);
2384   }
2385 }
2386 
2387 /*==================================================================*/
2388 /*                                                                  */
2389 /*  Query_TruncateCount () -                                        */
2390 /*                                                                  */
2391 /*==================================================================*/
2392 
Query_TruncateCount(FormInfoPtr pFormInfo,CharPtr str)2393 static Int4 Query_TruncateCount (FormInfoPtr pFormInfo, CharPtr str)
2394 
2395 {
2396   CharPtr                 dbName;
2397   Boolean                 doNotExplode;
2398   Boolean                 doNotTranslate;
2399   Int4                    count;
2400   Entrez2RequestPtr       e2RequestPtr;
2401   Entrez2ReplyPtr         e2ReplyPtr;
2402   Entrez2BooleanReplyPtr  e2BooleanPtr;
2403   Entrez2FieldInfoPtr     fieldInfo;
2404 
2405   if (pFormInfo == NULL || StringHasNoText (str)) return 0;
2406 
2407   /*--------------------------------*/
2408   /* Get the name of the current DB */
2409   /*--------------------------------*/
2410 
2411   dbName = DBGetNameFromID (pFormInfo->currDb);
2412   if (StringHasNoText (dbName)) return 0;
2413 
2414   fieldInfo = FieldGetInfo (pFormInfo->currDb, pFormInfo->currField);
2415   if (fieldInfo == NULL) return 0;
2416 
2417   /*---------------------------------*/
2418   /* Create an empty Boolean request */
2419   /*---------------------------------*/
2420 
2421   e2RequestPtr = EntrezCreateBooleanRequest (FALSE, FALSE, dbName, NULL, 0, 0, NULL, 0, 0);
2422   if (e2RequestPtr == NULL) return 0;
2423 
2424   /*--------------------------------------------------*/
2425   /* Send truncated term count request to the server. */
2426   /*--------------------------------------------------*/
2427 
2428   doNotTranslate = FALSE;
2429   doNotExplode = !GetStatus (pFormInfo->explodeItem);
2430   EntrezAddToBooleanRequest (e2RequestPtr, NULL, 0, fieldInfo->field_name,
2431                              str, NULL, 0, 0, NULL, NULL,
2432                              doNotExplode, doNotTranslate);
2433 
2434   if (ShowASN () == TRUE)
2435     DisplayEntrezRequest (e2RequestPtr);
2436 
2437   e2ReplyPtr = SpecialEntrezSynchronousQuery (e2RequestPtr);
2438 
2439   if (ShowASN () == TRUE)
2440     DisplayEntrezReply (e2ReplyPtr);
2441 
2442   if (e2ReplyPtr == NULL) return 0;
2443 
2444   /*----------------------------------*/
2445   /* Parse the count out of the reply */
2446   /*----------------------------------*/
2447 
2448   e2BooleanPtr = EntrezExtractBooleanReply (e2ReplyPtr);
2449   count = e2BooleanPtr->count;
2450 
2451   /*----------------------------------*/
2452   /* Clean up and return successfully */
2453   /*----------------------------------*/
2454 
2455   Entrez2BooleanReplyFree (e2BooleanPtr);
2456   Entrez2RequestFree (e2RequestPtr);
2457 
2458   return count;
2459 }
2460 
2461 /*==================================================================*/
2462 /*                                                                  */
2463 /*  Query_FetchRangeCount () -                                      */
2464 /*                                                                  */
2465 /*==================================================================*/
2466 
Query_FetchRangeCount(FormInfoPtr pFormInfo,CharPtr str)2467 static Int4 Query_FetchRangeCount (FormInfoPtr pFormInfo, CharPtr str)
2468 
2469 {
2470   CharPtr                 dbName;
2471   Int4                    count;
2472   Entrez2RequestPtr       e2RequestPtr;
2473   Entrez2ReplyPtr         e2ReplyPtr;
2474   Entrez2BooleanReplyPtr  e2BooleanPtr;
2475   Entrez2FieldInfoPtr     fieldInfo;
2476   Boolean                 doNotTranslate;
2477 
2478   if (pFormInfo == NULL || StringHasNoText (str)) return 0;
2479 
2480   /*--------------------------------*/
2481   /* Get the name of the current DB */
2482   /*--------------------------------*/
2483 
2484   dbName = DBGetNameFromID (pFormInfo->currDb);
2485   if (StringHasNoText (dbName)) return 0;
2486 
2487   fieldInfo = FieldGetInfo (pFormInfo->currDb, pFormInfo->currField);
2488   if (fieldInfo == NULL) return 0;
2489 
2490   /*---------------------------------*/
2491   /* Create an empty Boolean request */
2492   /*---------------------------------*/
2493 
2494   e2RequestPtr = EntrezCreateBooleanRequest (FALSE, FALSE, dbName, NULL, 0, 0, NULL, 0, 0);
2495   if (e2RequestPtr == NULL) return 0;
2496 
2497   /*--------------------------------------------------*/
2498   /* Send truncated term count request to the server. */
2499   /*--------------------------------------------------*/
2500 
2501   doNotTranslate = FALSE;
2502   EntrezAddToBooleanRequest (e2RequestPtr, NULL, 0, fieldInfo->field_name, str, NULL, 0, 0, NULL, NULL, FALSE, doNotTranslate);
2503 
2504   if (ShowASN () == TRUE)
2505     DisplayEntrezRequest (e2RequestPtr);
2506 
2507   e2ReplyPtr = SpecialEntrezSynchronousQuery (e2RequestPtr);
2508 
2509   if (ShowASN () == TRUE)
2510     DisplayEntrezReply (e2ReplyPtr);
2511 
2512   if (e2ReplyPtr == NULL) return 0;
2513 
2514   /*----------------------------------*/
2515   /* Parse the count out of the reply */
2516   /*----------------------------------*/
2517 
2518   e2BooleanPtr = EntrezExtractBooleanReply (e2ReplyPtr);
2519   if (e2BooleanPtr != NULL)
2520     count = e2BooleanPtr->count;
2521   else {
2522     Entrez2RequestFree (e2RequestPtr);
2523     return 0;
2524   }
2525 
2526 
2527   /*----------------------------------*/
2528   /* Clean up and return successfully */
2529   /*----------------------------------*/
2530 
2531   Entrez2BooleanReplyFree (e2BooleanPtr);
2532   Entrez2RequestFree (e2RequestPtr);
2533 
2534   return count;
2535 }
2536 
2537 /*===================================================================*/
2538 /*                                                                   */
2539 /* ProcessRangeTerms ()                                              */
2540 /*                                                                   */
2541 /*===================================================================*/
2542 
ProcessRangeTerms(FormInfoPtr pFormInfo)2543 static void ProcessRangeTerms (FormInfoPtr pFormInfo)
2544 {
2545   Char          fromStr [E2_STR_BUFF_SIZE];
2546   Char          toStr [E2_STR_BUFF_SIZE];
2547   Char          rangeStr [2 * E2_STR_BUFF_SIZE + 1];
2548   StateDataPtr  sdp;
2549   Int4          count;
2550   CharPtr       text;
2551 
2552   /* If a new term has been typed into the */
2553   /* 'To' text box, then do a lookup of    */
2554   /* that term.                            */
2555 
2556   if (pFormInfo->isToTextChanged) {
2557     GetTitle (pFormInfo->toText, toStr, E2_STR_BUFF_SIZE);
2558     pFormInfo->isValidTo = LoadAvailList (pFormInfo, toStr);
2559     pFormInfo->isToTextChanged = FALSE;
2560   }
2561   /* If we have valid 'From' and 'To' terms then */
2562   /* create a range term in the query window.    */
2563 
2564   else if ((pFormInfo->isValidFrom) && (pFormInfo->isValidTo)) {
2565 
2566     /* Get the 'from' and 'to' strings */
2567 
2568     GetTitle (pFormInfo->toText, toStr, E2_STR_BUFF_SIZE);
2569     GetTitle (pFormInfo->fromText, fromStr, E2_STR_BUFF_SIZE);
2570     sprintf(rangeStr, "%s:%s", fromStr, toStr);
2571 
2572     /* Get a count for the range */
2573 
2574     count = Query_FetchRangeCount (pFormInfo, rangeStr);
2575 
2576     /*  Add a term to the linked list */
2577 
2578     sdp = CreateTerm (pFormInfo->form, pFormInfo->currDb,
2579                       pFormInfo->currField, rangeStr, STATE_ON, count,
2580                       FALSE);
2581     if (NULL == sdp)
2582       return;
2583 
2584     /* Display the range as one term */
2585 
2586     DisplayTerm (pFormInfo, rangeStr, sdp->field, sdp->count);
2587 
2588     Select (pFormInfo->fromText);
2589     Reset (pFormInfo->availDoc);
2590     pFormInfo->okayToAccept = FALSE;
2591   }
2592 
2593   /* If a new term has been typed into the */
2594   /* 'From' text box, then do a lookup of  */
2595   /* that term.                            */
2596 
2597   else if (pFormInfo->isFromTextChanged) {
2598     GetTitle (pFormInfo->fromText, fromStr, E2_STR_BUFF_SIZE);
2599     pFormInfo->isValidFrom = LoadAvailList (pFormInfo, fromStr);
2600     pFormInfo->isFromTextChanged = FALSE;
2601   }
2602 
2603   else if (pFormInfo->okayToAccept &&
2604            pFormInfo->availItem > 0 &&
2605            pFormInfo->availRow > 0) {
2606     text = GetDocText (pFormInfo->availDoc, pFormInfo->availItem,
2607                        pFormInfo->availRow, E2_TERM_COL);
2608     if (text != NULL) {
2609       TrimSpacesAroundString (text);
2610       if (pFormInfo->currRangeField == E2_RANGE_FROM) {
2611         SafeSetTitle (pFormInfo->fromText, text);
2612         Select (pFormInfo->fromText);
2613         pFormInfo->isValidFrom = TRUE;
2614         pFormInfo->isFromTextChanged = FALSE;
2615       }
2616       else {
2617         SafeSetTitle (pFormInfo->toText, text);
2618         Select (pFormInfo->toText);
2619         pFormInfo->isValidTo = TRUE;
2620         pFormInfo->isToTextChanged = FALSE;
2621       }
2622       Update ();
2623     }
2624     MemFree (text);
2625   }
2626 
2627   /* Return successfully */
2628 
2629   return;
2630 }
2631 
2632 /*===================================================================*/
2633 /*                                                                   */
2634 /*  Accept_Callback () - Called when the accept button is pressed,   */
2635 /*                      if fetches a term list or adds term to query */
2636 /*                      list.                                        */
2637 /*                                                                   */
2638 /*===================================================================*/
2639 
Accept_Callback(ButtoN b)2640 static void Accept_Callback (ButtoN b)
2641 
2642 {
2643   Int4          count;
2644   FormInfoPtr   pFormInfo;
2645   StateDataPtr  sdp;
2646   Char          str [E2_STR_BUFF_SIZE];
2647 
2648   pFormInfo = (FormInfoPtr) GetObjectExtra (b);
2649 
2650   str [0] = '\0';
2651   if (pFormInfo->currMode == RANGE_MODE)
2652     GetTitle (CurrentText (), str, E2_STR_BUFF_SIZE);
2653   else
2654     GetTitle (pFormInfo->termText, str, E2_STR_BUFF_SIZE);
2655   if (str [0] == '\0') return;
2656 
2657   WatchCursor ();
2658   switch (pFormInfo->currMode) {
2659     case TRANSLATE_MODE:
2660       Query_TranslateAndAddBoolTerm (pFormInfo->form, pFormInfo->currDb,
2661                      pFormInfo->currField, str, STATE_ON, 0);
2662       SafeSetTitle (pFormInfo->termText, "");
2663       if (Visible (pFormInfo->termText))
2664         Select (pFormInfo->termText);
2665       pFormInfo->availItem = 0;
2666       pFormInfo->availRow = 0;
2667       Reset (pFormInfo->availDoc);
2668       break;
2669     case SELECTION_MODE:
2670       ProcessSelectionTerm (pFormInfo, str);
2671       /*
2672       pFormInfo->availCurrentPage = 0;
2673       */
2674       break;
2675     case AUTOMATIC_MODE:
2676       ProcessMultipleTerms (pFormInfo, str);
2677       break;
2678     case WILD_CARD_MODE:
2679       StringCat (str, "*");
2680       count = Query_TruncateCount (pFormInfo, str);
2681       sdp = CreateTerm (pFormInfo->form, pFormInfo->currDb,
2682                         pFormInfo->currField, str, STATE_ON, count, FALSE);
2683       if (sdp != NULL) {
2684         DisplayTerm (pFormInfo, str, sdp->field, count);
2685       }
2686       SafeSetTitle (pFormInfo->termText, "");
2687       if (Visible (pFormInfo->termText))
2688         Select (pFormInfo->termText);
2689       pFormInfo->availItem = 0;
2690       pFormInfo->availRow = 0;
2691       Reset (pFormInfo->availDoc);
2692       break;
2693     case MESH_TREE_MODE:
2694       ProcessMeshTerm (pFormInfo, str);
2695       break;
2696     case TAXONOMY_MODE:
2697       ProcessTaxonomyTerm (pFormInfo, str);
2698       break;
2699     case RANGE_MODE:
2700       ProcessRangeTerms (pFormInfo);
2701       break;
2702     case LOOKUP_ACCN_MODE:
2703     case LOOKUP_UID_MODE:
2704     case VIEW_ACCN_MODE:
2705     case VIEW_UID_MODE:
2706       ProcessDirectLookup (pFormInfo, str);
2707       ArrowCursor ();
2708       Update ();
2709       return;
2710     default:
2711       break;
2712   }
2713   Update ();
2714 
2715   RecalculateChosen (pFormInfo);
2716 
2717   ArrowCursor ();
2718   Update ();
2719 }
2720 
2721 /*===================================================================*/
2722 /*                                                                   */
2723 /*  EvaluateRetrieve_Callback () - This is the callback for the      */
2724 /*                                Evaluate/Retrieve button in        */
2725 /*                                advanced query mode.               */
2726 /*                                                                   */
2727 /*===================================================================*/
2728 
EvaluateRetrieve_Callback(ButtoN evaluateRetrieveButton)2729 static void EvaluateRetrieve_Callback (ButtoN evaluateRetrieveButton)
2730 
2731 {
2732   FormInfoPtr  pFormInfo;
2733 
2734   pFormInfo = (FormInfoPtr) GetObjectExtra (evaluateRetrieveButton);
2735 
2736   if (pFormInfo->advQueryState == ADV_QUERY_EVALUATE_STATE) {
2737     WatchCursor ();
2738     Update ();
2739     RecalculateChosen (pFormInfo);
2740     pFormInfo->advQueryState = ADV_QUERY_RETRIEVE_STATE;
2741     ArrowCursor ();
2742   } else if (pFormInfo->advQueryState == ADV_QUERY_RETRIEVE_STATE) {
2743     pFormInfo->retrieveDocsProc (evaluateRetrieveButton);
2744     pFormInfo->advQueryState = ADV_QUERY_INVALID_STATE;
2745   }
2746 }
2747 
2748 /*===================================================================*/
2749 /*                                                                   */
2750 /*  DatabaseView_Callback () and FieldView_Callback () -             */
2751 /*     Callback functions for items in Help menu.                    */
2752 /*                                                                   */
2753 /*===================================================================*/
2754 
DatabaseView_Callback(IteM i)2755 static void DatabaseView_Callback (IteM i)
2756 
2757 {
2758   Entrez2DbInfoPtr  e2db;
2759   Entrez2InfoPtr    e2ip;
2760   FILE              *fp;
2761   Int2              len;
2762   Int2              max_menu = 0;
2763   Int2              max_name = 0;
2764   Char              path [PATH_MAX];
2765 
2766   e2ip = Query_GetInfo ();
2767   if (e2ip == NULL) return;
2768   TmpNam (path);
2769   fp = FileOpen (path, "w");
2770   if (fp == NULL) return;
2771   for (e2db = e2ip->db_info; e2db != NULL; e2db = e2db->next) {
2772     len = (Int2) StringLen (e2db->db_name);
2773     max_name = MAX (len, max_name);
2774     len = (Int2) StringLen (e2db->db_menu);
2775     max_menu = MAX (len, max_menu);
2776   }
2777   max_name += 2;
2778   max_menu += 2;
2779   for (e2db = e2ip->db_info; e2db != NULL; e2db = e2db->next) {
2780     len = (Int2) StringLen (e2db->db_name);
2781     max_name = MAX (len, max_name);
2782     len = (Int2) StringLen (e2db->db_menu);
2783     max_menu = MAX (len, max_menu);
2784   }
2785   for (e2db = e2ip->db_info; e2db != NULL; e2db = e2db->next) {
2786     len = (Int2) StringLen (e2db->db_name);
2787     fprintf (fp, "%s", e2db->db_name);
2788     while (len < max_name) {
2789       fprintf (fp, " ");
2790       len++;
2791     }
2792     len = (Int2) StringLen (e2db->db_menu);
2793     fprintf (fp, "%s", e2db->db_menu);
2794     while (len < max_menu) {
2795       fprintf (fp, " ");
2796       len++;
2797     }
2798     fprintf (fp, "%s", e2db->db_descr);
2799     fprintf (fp, "\n");
2800   }
2801   FileClose (fp);
2802   LaunchGeneralTextViewer (path, "Database Summary");
2803   FileRemove (path);
2804 }
2805 
FieldView_Callback(IteM i)2806 static void FieldView_Callback (IteM i)
2807 
2808 {
2809   Entrez2InfoPtr       e2ip;
2810   EnumFieldAssocPtr    fieldAlist;
2811   Entrez2FieldInfoPtr  fieldInfo;
2812   FILE                 *fp;
2813   Int2                 j;
2814   Int2                 len;
2815   Int2                 max_menu = 0;
2816   Int2                 max_name = 0;
2817   Char                 path [PATH_MAX];
2818 
2819   e2ip = Query_GetInfo ();
2820   if (e2ip == NULL) return;
2821   fieldAlist = CreateAllFieldsAlist (e2ip);
2822   if (fieldAlist == NULL) return;
2823   TmpNam (path);
2824   fp = FileOpen (path, "w");
2825   if (fp == NULL) return;
2826   for (j = 0; fieldAlist [j].name != NULL; j++) {
2827     fieldInfo = FieldGetInfoFromName (fieldAlist [j].name);
2828     len = (Int2) StringLen (fieldInfo->field_name);
2829     max_name = MAX (len, max_name);
2830     len = (Int2) StringLen (fieldInfo->field_menu);
2831     max_menu = MAX (len, max_menu);
2832   }
2833   max_name += 2;
2834   max_menu += 2;
2835   for (j = 0; fieldAlist [j].name != NULL; j++) {
2836     fieldInfo = FieldGetInfoFromName (fieldAlist [j].name);
2837     len = (Int2) StringLen (fieldInfo->field_name);
2838     fprintf (fp, "%s", fieldInfo->field_name);
2839     while (len < max_name) {
2840       fprintf (fp, " ");
2841       len++;
2842     }
2843     len = (Int2) StringLen (fieldInfo->field_menu);
2844     fprintf (fp, "%s", fieldInfo->field_menu);
2845     while (len < max_menu) {
2846       fprintf (fp, " ");
2847       len++;
2848     }
2849     fprintf (fp, "%s", fieldInfo->field_descr);
2850     fprintf (fp, "\n");
2851   }
2852   FileClose (fp);
2853   LaunchGeneralTextViewer (path, "Field Summary");
2854   FileRemove (path);
2855   FreeEnumFieldAlist (fieldAlist);
2856 }
2857 
2858 static CharPtr modeSummary [] = {
2859   "Automatic  Terms are processed through PubMed query engine",
2860   "Lookup     Accession looked up directly into Document window",
2861   "MeSH Tree  MeSH hierarchy above current level displayed in popup",
2862   "Multiple   Terms extracted and processed one at a time",
2863   "Range      From and To values entered as a composite term",
2864   "Selection  Available terms are displayed in Term Selection box",
2865   "Taxonomy   Organism hierarchy above current level displayed in popup",
2866   "View       Accession looked up directly into Viewer window",
2867   "Wild Card  Term appended with asterisk and processed",
2868   NULL
2869 };
2870 
ModeView_Callback(IteM i)2871 static void ModeView_Callback (IteM i)
2872 
2873 {
2874   FILE  *fp;
2875   Int2  j;
2876   Char  path [PATH_MAX];
2877 
2878   TmpNam (path);
2879   fp = FileOpen (path, "w");
2880   if (fp == NULL) return;
2881   for (j = 0; modeSummary [j] != NULL; j++) {
2882     fprintf (fp, "%s\n", modeSummary [j]);
2883   }
2884   FileClose (fp);
2885   LaunchGeneralTextViewer (path, "Mode Summary");
2886   FileRemove (path);
2887 }
2888 
2889 /*==================================================================*/
2890 /*                                                                  */
2891 /*  AddPopupItem () - Add an item to a popup list. This is used to  */
2892 /*                   create the lineage popup list in taxonomy      */
2893 /*                   mode.                                          */
2894 /*                                                                  */
2895 /*==================================================================*/
2896 
AddPopupItem(PopuP p,CharPtr str,Int2 maxwid)2897 static void AddPopupItem (PopuP p, CharPtr str, Int2 maxwid)
2898 
2899 {
2900   Char     ch;
2901   Int2     hbounds;
2902   Int2     i;
2903   CharPtr  ptr;
2904   Char     title [256];
2905   Int2     wid;
2906 
2907   if (p != NULL && str != NULL) {
2908     StringNCpy_0 (title, str, sizeof (title));
2909     i = StringLen (title);
2910     title [i] = '\0';
2911     ptr = title;
2912     ch = *ptr;
2913     while (ch != '\0') {
2914       if (ch == '/') {
2915         *ptr = '-';
2916       }
2917       ptr++;
2918       ch = *ptr;
2919     }
2920 #ifdef WIN_MAC
2921     hbounds = 13;
2922 #endif
2923 #ifdef WIN_MSWIN
2924     hbounds = 13;
2925 #endif
2926 #ifdef WIN_MOTIF
2927     hbounds = 24;
2928 #endif
2929     maxwid -= StringWidth ("...") + hbounds * 2 + StringWidth (" ");
2930     wid = 0;
2931     i = 0;
2932     ch = title [i];
2933     while (ch != '\0' && wid <= maxwid) {
2934       wid += CharWidth (ch);
2935       i++;
2936       ch = title [i];
2937     }
2938     title [i] = '\0';
2939     if (ch != '\0' && i <= (Int2) StringLen (str)) {
2940       StringCat (title, "...");
2941     }
2942     PopupItem (p, title);
2943   }
2944 }
2945 
2946 /*==================================================================*/
2947 /*                                                                  */
2948 /*  AvailGetColWidth () - Returns the pixel width of the given      */
2949 /*                       column.                                    */
2950 /*                                                                  */
2951 /*==================================================================*/
2952 
AvailGetColWidth(Int2 columnNum)2953 static Int2 AvailGetColWidth (Int2 columnNum)
2954 
2955 {
2956   return availColFmt [columnNum].pixWidth;
2957 }
2958 
2959 /*==================================================================*/
2960 /*                                                                  */
2961 /*  RepopulateTaxonomy () - Given a term and a database, will       */
2962 /*                         look up the term in the taxonomy tree    */
2963 /*                         and populate the Term Selection window   */
2964 /*                         with the term's 'children' in the tree.  */
2965 /*                                                                  */
2966 /*==================================================================*/
2967 
RepopulateTaxonomy(FormInfoPtr pFormInfo,CharPtr taxterm)2968 static Boolean RepopulateTaxonomy (FormInfoPtr pFormInfo, CharPtr taxterm)
2969 
2970 {
2971   CharPtr              aLineage [MAX_TAXONOMY_TREE_DEPTH];
2972   Int2                 delta;
2973   CharPtr              dbName;
2974   CharPtr              fieldName;
2975   Int2                 i;
2976   Int2                 maxwidth;
2977   RecT                 r;
2978   RecT                 s;
2979   Char                 str [256];
2980   Int4                 taxId;
2981   Int2                 wid;
2982   Entrez2TermPtr       childPtr;
2983   Entrez2RequestPtr    e2Request;
2984   Entrez2ReplyPtr      e2Reply;
2985   Entrez2HierNodePtr   e2TermNode;
2986   Entrez2TermPtr       currentLineage = NULL;
2987   Entrez2FieldInfoPtr  fieldInfo;
2988 
2989   /*--------------------------*/
2990   /* Build an Entrez2 request */
2991   /*--------------------------*/
2992 
2993   taxId = 0;
2994   dbName = DBGetNameFromID (pFormInfo->currDb);
2995   fieldInfo = FieldGetInfo (pFormInfo->currDb, pFormInfo->currField);
2996   fieldName = fieldInfo->field_name;
2997   if (StringHasNoText (dbName) || StringHasNoText (fieldName)) return FALSE;
2998 
2999   e2Request = EntrezCreateGetTermHierarchyRequest (dbName, fieldName, taxterm, taxId);
3000 
3001   /*----------------------------------*/
3002   /* Send off the request and extract */
3003   /* the resulting reply.             */
3004   /*----------------------------------*/
3005 
3006   if (ShowASN () == TRUE)
3007     DisplayEntrezRequest (e2Request);
3008 
3009   e2Reply = SpecialEntrezSynchronousQuery (e2Request);
3010 
3011   if (ShowASN () == TRUE)
3012     DisplayEntrezReply (e2Reply);
3013 
3014   if (e2Reply == NULL) {
3015     Show (pFormInfo->taxLineagePopup);
3016     Update ();
3017     return FALSE;
3018   }
3019 
3020   e2TermNode = EntrezExtractHierNodeReply (e2Reply);
3021   if (e2TermNode == NULL) {
3022     Show (pFormInfo->taxLineagePopup);
3023     Update ();
3024     return FALSE;
3025   }
3026 
3027   Entrez2RequestFree (e2Request);
3028 
3029   /*-------------------------*/
3030   /* Clear any old terms out */
3031   /* of the Avail window.    */
3032   /*-------------------------*/
3033 
3034   SafeSetTitle (pFormInfo->termText, taxterm);
3035   Hide (pFormInfo->taxLineagePopup);
3036   Reset (pFormInfo->taxLineagePopup);
3037   pFormInfo->taxStrings = ValNodeFreeData (pFormInfo->taxStrings);
3038   pFormInfo->availItem = 0;
3039   pFormInfo->availRow = 0;
3040   Reset (pFormInfo->availDoc);
3041   SetDocCache (pFormInfo->availDoc, NULL, NULL, NULL);
3042   Update ();
3043   maxwidth = AvailGetColWidth (0);
3044 
3045   /*------------------------------------------------*/
3046   /* Create a selection list of a term's "lineage"  */
3047   /*    NOTE: The lineage is provided in the        */
3048   /*          reverse order from how we want to     */
3049   /*          add it to the list box, so they must  */
3050   /*          be put into a random-access structure */
3051   /*          and then reverse added.               */
3052   /*------------------------------------------------*/
3053 
3054   for (i = 0; i < e2TermNode->lineage_count; i++) {
3055     if (i == 0)
3056       currentLineage = e2TermNode->lineage;
3057     else
3058       currentLineage = currentLineage->next;
3059 
3060     if (currentLineage == NULL)
3061       break;
3062 
3063     aLineage [i] = currentLineage->term;
3064   }
3065 
3066   for (i = e2TermNode->lineage_count - 1; i >= 0; i--) {
3067     AddPopupItem (pFormInfo->taxLineagePopup, aLineage [i], maxwidth);
3068     ValNodeCopyStr (&(pFormInfo->taxStrings), 0, aLineage [i]);
3069   }
3070 
3071   /*----------------------------------------------*/
3072   /* Adjust the size of the Pull Down list box to */
3073   /* accomodate the lineage list just created.    */
3074   /*----------------------------------------------*/
3075 
3076   SetValue (pFormInfo->taxLineagePopup, e2TermNode->lineage_count);
3077   ObjectRect (pFormInfo->taxLineagePopup, &r);
3078   ObjectRect (pFormInfo->availDoc, &s);
3079   InsetRect (&s, 4, 4);
3080   wid = r.right - r.left;
3081   delta = (maxwidth - wid) / 2;
3082   r.left = s.left + delta;
3083   r.right = r.left + wid;
3084   SetPosition (pFormInfo->taxLineagePopup, &r);
3085 
3086   /*---------------------------------*/
3087   /* Add the children of the current */
3088   /* term to the Selection Box.      */
3089   /*---------------------------------*/
3090 
3091   childPtr = e2TermNode->children;
3092 
3093   for (i = 0; i < e2TermNode->child_count; i++) {
3094     sprintf (str, "%s\t%ld\t%d\n", childPtr->term, (long) (childPtr->count), (int) (childPtr->is_leaf_node ? 1 : 0));
3095     AppendText (pFormInfo->availDoc, str, &availParFmt, availColFmt, systemFont);
3096     childPtr = childPtr->next;
3097   }
3098 
3099   for (i = e2TermNode->child_count; i < 7; i++)
3100     AppendText (pFormInfo->availDoc, " \n", &availParFmt, availColFmt, systemFont);
3101 
3102   /*-------------------------*/
3103   /* Redraw the avail window */
3104   /* with the new terms.     */
3105   /*-------------------------*/
3106 
3107   InvalDocument (pFormInfo->availDoc);
3108   Show (pFormInfo->taxLineagePopup);
3109   Update ();
3110   AdjustDocScroll (pFormInfo->availDoc);
3111 
3112   return TRUE;
3113 }
3114 
3115 /*==================================================================*/
3116 /*                                                                  */
3117 /*  RepopulateTaxonomyRoot () -                                     */
3118 /*                                                                  */
3119 /*==================================================================*/
3120 
RepopulateTaxonomyRoot(FormInfoPtr pFormInfo)3121 static void RepopulateTaxonomyRoot (FormInfoPtr pFormInfo)
3122 
3123 {
3124   CharPtr  dbName;
3125 
3126   dbName = DBGetNameFromID (pFormInfo->currDb);
3127 
3128   if (StringICmp (dbName, "PubMed") == 0) {
3129     RepopulateTaxonomy (pFormInfo, "All MeSH Categories");
3130   } else {
3131     RepopulateTaxonomy (pFormInfo, "root");
3132   }
3133 }
3134 
3135 /*===================================================================*/
3136 /*                                                                   */
3137 /*  ChangeTaxParents_Callback () - Called when a 'Parent' term is    */
3138 /*                                selected from the taxonomy lineage */
3139 /*                                popup list.                        */
3140 /*                                                                   */
3141 /*                                Makes the selected term the active */
3142 /*                                one and re-queries for it.         */
3143 /*                                                                   */
3144 /*===================================================================*/
3145 
ChangeTaxParents_Callback(PopuP p)3146 static void ChangeTaxParents_Callback (PopuP p)
3147 
3148 {
3149   FormInfoPtr  pFormInfo;
3150   Int2         val;
3151   ValNodePtr   vnp;
3152 
3153   pFormInfo = (FormInfoPtr) GetObjectExtra (p);
3154 
3155   val = GetValue (p);
3156   if (val <= 0) return;
3157 
3158   vnp = pFormInfo->taxStrings;
3159   while (val > 1 && vnp != NULL) {
3160     val--;
3161     vnp = vnp->next;
3162   }
3163   if (vnp != NULL) {
3164     WatchCursor ();
3165     RepopulateTaxonomy (pFormInfo, (CharPtr) vnp->data.ptrvalue);
3166     ArrowCursor ();
3167   }
3168 }
3169 
3170 /*===================================================================*/
3171 /*                                                                   */
3172 /*  TextAction () - Called when a key is type into the "Term:" text  */
3173 /*                  entry box.  Enables/disables the accept button   */
3174 /*                  and scroll to text.                              */
3175 /*                                                                   */
3176 /*===================================================================*/
3177 
TextAction(TexT t)3178 static void TextAction (TexT t)
3179 
3180 {
3181   Int2         i;
3182   FormInfoPtr  pFormInfo;
3183   Char         str [256];
3184 
3185   pFormInfo = (FormInfoPtr) GetObjectExtra (t);
3186 
3187   /* Enable or disable the 'Accept' button based */
3188   /* on the mode and the current text.           */
3189 
3190   if (pFormInfo->currMode == RANGE_MODE) {
3191     if (TextHasNoText (pFormInfo->fromText) &&
3192         TextHasNoText (pFormInfo->toText))
3193       SafeDisable (pFormInfo->acceptButton);
3194     else
3195       SafeEnable (pFormInfo->acceptButton);
3196   } else {
3197     GetTitle (pFormInfo->termText, str, sizeof (str));
3198     if (StringHasNoText (str)) {
3199       if (pFormInfo->currMode == SELECTION_MODE && str [0] == ' ')
3200         SafeEnable (pFormInfo->acceptButton);
3201       else
3202         SafeDisable (pFormInfo->acceptButton);
3203     } else
3204       SafeEnable (pFormInfo->acceptButton);
3205   }
3206 
3207   /* Get the current text */
3208 
3209   GetTitle (t, str, sizeof (str));
3210 
3211   /* If there is no text then clear */
3212   /* the 'Term Selection' window.   */
3213 
3214   if (str [0] == '\0') {
3215     pFormInfo->availItem = 0;
3216     pFormInfo->availRow = 0;
3217     Reset (pFormInfo->availDoc);
3218     for (i = 0; i < 7; i++)
3219       AppendText (pFormInfo->availDoc, " \n", &availParFmt, availColFmt,
3220           systemFont);
3221     InvalDocument (pFormInfo->availDoc);
3222     pFormInfo->textChanged = FALSE;
3223     pFormInfo->okayToAccept = FALSE;
3224     pFormInfo->availCurrentPage = 0;
3225   }
3226 
3227   /* If there is text, then attempt to scroll */
3228   /* to it in the 'Term Selection' window.    */
3229 
3230   else {
3231     pFormInfo->textChanged = TRUE;
3232     pFormInfo->okayToAccept = FALSE;
3233     if (pFormInfo->availCurrentPage > 0 &&
3234     pFormInfo->currMode == SELECTION_MODE)
3235       ScrollToText (pFormInfo, str, pFormInfo->availCurrentPage, TRUE, TRUE);
3236     Update ();
3237   }
3238 }
3239 
3240 /*==================================================================*/
3241 /*                                                                   */
3242 /*  ToTextAction () -                                                */
3243 /*                                                                   */
3244 /*===================================================================*/
3245 
ToTextAction(TexT t)3246 static void ToTextAction (TexT t)
3247 
3248 {
3249   Int2         i;
3250   FormInfoPtr  pFormInfo;
3251   Char         str [256];
3252 
3253   pFormInfo = (FormInfoPtr) GetObjectExtra (t);
3254 
3255   pFormInfo->currRangeField = E2_RANGE_TO;
3256 
3257   if (TextHasNoText (pFormInfo->fromText) &&
3258       TextHasNoText (pFormInfo->toText))
3259     SafeDisable (pFormInfo->acceptButton);
3260   else
3261     SafeEnable (pFormInfo->acceptButton);
3262 
3263   GetTitle (t, str, sizeof (str));
3264   if (str [0] == '\0') {
3265     pFormInfo->availItem = 0;
3266     pFormInfo->availRow = 0;
3267     Reset (pFormInfo->availDoc);
3268     for (i = 0; i < 7; i++)
3269       AppendText (pFormInfo->availDoc, " \n", &availParFmt, availColFmt, systemFont);
3270     InvalDocument (pFormInfo->availDoc);
3271     pFormInfo->isToTextChanged = FALSE;
3272     pFormInfo->isValidTo = FALSE;
3273     pFormInfo->availCurrentPage = 0;
3274   } else {
3275     pFormInfo->isToTextChanged = TRUE;
3276     pFormInfo->isValidTo = TRUE;
3277     if (pFormInfo->availCurrentPage > 0)
3278       ScrollToText (pFormInfo, str, pFormInfo->availCurrentPage, TRUE, TRUE);
3279     Update ();
3280   }
3281 }
3282 
3283 /*==================================================================*/
3284 /*                                                                   */
3285 /*  FromTextAction () -                                              */
3286 /*                                                                   */
3287 /*===================================================================*/
3288 
FromTextAction(TexT t)3289 static void FromTextAction (TexT t)
3290 
3291 {
3292   Int2         i;
3293   FormInfoPtr  pFormInfo;
3294   Char         str [256];
3295 
3296   pFormInfo = (FormInfoPtr) GetObjectExtra (t);
3297 
3298   pFormInfo->currRangeField = E2_RANGE_FROM;
3299 
3300   if (TextHasNoText (pFormInfo->fromText) &&
3301       TextHasNoText (pFormInfo->toText))
3302     SafeDisable (pFormInfo->acceptButton);
3303   else
3304     SafeEnable (pFormInfo->acceptButton);
3305 
3306   GetTitle (t, str, sizeof (str));
3307   if (str [0] == '\0') {
3308     pFormInfo->availItem = 0;
3309     pFormInfo->availRow = 0;
3310     Reset (pFormInfo->availDoc);
3311     for (i = 0; i < 7; i++)
3312       AppendText (pFormInfo->availDoc, " \n", &availParFmt,
3313                   availColFmt, systemFont);
3314     InvalDocument (pFormInfo->availDoc);
3315     pFormInfo->isFromTextChanged = FALSE;
3316     pFormInfo->isValidFrom = FALSE;
3317     pFormInfo->availCurrentPage = 0;
3318   } else {
3319     pFormInfo->isFromTextChanged = TRUE;
3320     pFormInfo->isValidFrom = TRUE;
3321     if (pFormInfo->availCurrentPage > 0)
3322       ScrollToText (pFormInfo, str, pFormInfo->availCurrentPage, TRUE, TRUE);
3323     Update ();
3324   }
3325 }
3326 
3327 /*==================================================================*/
3328 /*                                                                  */
3329 /*  ChangeMode () -                                                 */
3330 /*                                                                  */
3331 /*==================================================================*/
3332 
ChangeMode(PopuP p)3333 static void ChangeMode (PopuP p)
3334 
3335 {
3336   AlistDialogPtr     adp;
3337   Char               ch;
3338   Int2               i;
3339   EnumFieldAssocPtr  modeSet;
3340   ModeChoice         menuMode;
3341   ModeChoice         selectedMode;
3342   CharPtr            ptr, text;
3343   FormInfoPtr        pFormInfo;
3344 
3345 
3346   /*------------------------------------------*/
3347   /* Convert the menu choice into a mode type */
3348   /*------------------------------------------*/
3349 
3350   adp = (AlistDialogPtr) GetObjectExtra (p);
3351   pFormInfo = adp->userdata;
3352   modeSet = adp->alist;
3353   menuMode = (ModeChoice) (GetValue (p) - 1);
3354   selectedMode = (ModeChoice) modeSet [menuMode].value;
3355 
3356   pFormInfo->currMode = selectedMode;
3357 
3358   /* handle special modes, populate termlist */
3359   if (selectedMode == TAXONOMY_MODE || selectedMode == MESH_TREE_MODE) {
3360     SafeHide (pFormInfo->termGroup);
3361     SafeHide (pFormInfo->rangeGroup);
3362     text = SaveStringFromText (pFormInfo->termText);
3363     WatchCursor ();
3364     Update ();
3365     if (text != NULL) {
3366       ptr = text;
3367       ch = *ptr;
3368       while (ch != '\0' && ch >= ' ') {
3369         ptr++;
3370         ch = *ptr;
3371       }
3372       *ptr = '\0';
3373       if ((*text == '\0') || (! RepopulateTaxonomy (pFormInfo, text))) {
3374         RepopulateTaxonomyRoot (pFormInfo);
3375       }
3376     } else {
3377       RepopulateTaxonomyRoot (pFormInfo);
3378     }
3379     ArrowCursor ();
3380     MemFree (text);
3381     SafeShow (pFormInfo->taxLineagePopup);
3382     pFormInfo->textChanged = FALSE;
3383     pFormInfo->okayToAccept = TRUE;
3384   } else if (selectedMode == RANGE_MODE) {
3385     SafeHide (pFormInfo->termGroup);
3386     SafeHide (pFormInfo->taxLineagePopup);
3387     SafeShow (pFormInfo->rangeGroup);
3388     TextAction (pFormInfo->fromText);
3389     pFormInfo->availItem = 0;
3390     pFormInfo->availRow = 0;
3391     Reset (pFormInfo->availDoc);
3392     SetDocCache (pFormInfo->availDoc, NULL, NULL, NULL);
3393     for (i = 0; i < 7; i++) {
3394       AppendText (pFormInfo->availDoc, " \n", &availParFmt, availColFmt, systemFont);
3395     }
3396     InvalDocument (pFormInfo->availDoc);
3397     Select (pFormInfo->fromText);
3398   } else {
3399     SafeHide (pFormInfo->rangeGroup);
3400     SafeHide (pFormInfo->taxLineagePopup);
3401     SafeShow (pFormInfo->termGroup);
3402     pFormInfo->availItem = 0;
3403     pFormInfo->availRow = 0;
3404     pFormInfo->availCurrentPage = 0;
3405     TextAction (pFormInfo->termText);
3406     Reset (pFormInfo->availDoc);
3407     SetDocCache (pFormInfo->availDoc, NULL, NULL, NULL);
3408     for (i = 0; i < 7; i++) {
3409       AppendText (pFormInfo->availDoc, " \n", &availParFmt, availColFmt, systemFont);
3410     }
3411     InvalDocument (pFormInfo->availDoc);
3412     Select (pFormInfo->termText);
3413   }
3414 
3415   Update ();
3416 }
3417 
3418 /*==================================================================*/
3419 /*                                                                  */
3420 /*  ChangeMode_Callback () -                                        */
3421 /*                                                                  */
3422 /*==================================================================*/
3423 
ChangeMode_Callback(PopuP p)3424 static void ChangeMode_Callback (PopuP p)
3425 
3426 {
3427   ChangeMode (p);
3428 }
3429 
3430 /*==================================================================*/
3431 /*                                                                  */
3432 /*  ChangeField () - Sets the current field to the one selected in  */
3433 /*                  the given PopuP object, then selects the        */
3434 /*                  corresponding modes PopuP that contains the     */
3435 /*                  possible modes for this field.                  */
3436 /*                                                                  */
3437 /*==================================================================*/
3438 
ChangeField(PopuP p)3439 static void ChangeField (PopuP p)
3440 
3441 {
3442   AlistDialogPtr     adp;
3443   EnumFieldAssocPtr  fieldAList;
3444   Int2               fieldId;
3445   ModeIndex          md, mode;
3446   Int2               menuChoice;
3447   FormInfoPtr        pFormInfo;
3448 
3449   /*------------------------*/
3450   /* Get the selected field */
3451   /*------------------------*/
3452 
3453   adp = (AlistDialogPtr) GetObjectExtra (p);
3454   pFormInfo = adp->userdata;
3455   fieldAList = adp->alist;
3456 
3457   menuChoice = GetValue (p) - 1;
3458   if (menuChoice < 0) return;
3459 
3460   fieldId = fieldAList [menuChoice].value;
3461 
3462   /*--------------------------------*/
3463   /* Select and make active the set */
3464   /* of modes for this field.       */
3465   /*--------------------------------*/
3466 
3467   mode = (ModeIndex) FieldGetModePopup (pFormInfo->currDb, fieldId, fieldAList, pFormInfo);
3468   if (mode < 0) return;
3469 
3470   for (md = POPUP_MULT; md <= POPUP_UID; md++)
3471     if (md != mode)
3472       SafeHide (pFormInfo->modesPopup [md]);
3473 
3474   SafeShow (pFormInfo->modesPopup [mode]);
3475   ChangeMode (pFormInfo->modesPopup [mode]);
3476 }
3477 
3478 /*==================================================================*/
3479 /*                                                                  */
3480 /*  ChangeField_Callback () -                                       */
3481 /*                                                                  */
3482 /*==================================================================*/
3483 
ChangeField_Callback(PopuP p)3484 static void ChangeField_Callback (PopuP p)
3485 
3486 {
3487   ChangeField (p);
3488 }
3489 
3490 /*==================================================================*/
3491 /*                                                                  */
3492 /*  ChangeDatabase () -                                             */
3493 /*                                                                  */
3494 /*==================================================================*/
3495 
ChangeDatabase(PopuP p)3496 static void ChangeDatabase (PopuP p)
3497 
3498 {
3499   FormInfoPtr     pFormInfo;
3500   Int2            db;
3501   Int2            dbase;
3502   UIEnum          val;
3503   Entrez2InfoPtr  e2ip;
3504 
3505   pFormInfo = (FormInfoPtr) GetObjectExtra (p);
3506   if (pFormInfo == NULL || pFormInfo->fieldsPopup == NULL) return;
3507 
3508   e2ip = Query_GetInfo ();
3509 
3510   val = GetValue (p) - 1;
3511 
3512   for (db = 0; db < e2ip->db_count; db++) {
3513     if (db != (Int2) val) {
3514       SafeHide (pFormInfo->fieldsPopup [db]);
3515     }
3516   }
3517 
3518   dbase = (Int2) val;
3519   pFormInfo->currDb = dbase;
3520   SafeShow (pFormInfo->fieldsPopup [dbase]);
3521   ChangeField (pFormInfo->fieldsPopup [dbase]);
3522 
3523   DoResetAvail (pFormInfo, FALSE);
3524   ResetChosen (pFormInfo);
3525 
3526   if (pFormInfo->currMode == TAXONOMY_MODE || pFormInfo->currMode == MESH_TREE_MODE) {
3527     SafeHide (pFormInfo->termGroup);
3528     SafeHide (pFormInfo->rangeGroup);
3529     SafeShow (pFormInfo->taxLineagePopup);
3530   } else if (pFormInfo->currMode == RANGE_MODE) {
3531     SafeHide (pFormInfo->termGroup);
3532     SafeHide (pFormInfo->taxLineagePopup);
3533     SafeShow (pFormInfo->rangeGroup);
3534     Select (pFormInfo->fromText);
3535   } else {
3536     SafeHide (pFormInfo->rangeGroup);
3537     SafeHide (pFormInfo->taxLineagePopup);
3538     SafeShow (pFormInfo->termGroup);
3539     Select (pFormInfo->termText);
3540   }
3541 
3542   Reset (pFormInfo->advQueryText);
3543 }
3544 
3545 /*==================================================================*/
3546 /*                                                                  */
3547 /*  ChangeDatabase_Callback () -                                    */
3548 /*                                                                  */
3549 /*==================================================================*/
3550 
ChangeDatabase_Callback(PopuP p)3551 static void ChangeDatabase_Callback (PopuP p)
3552 
3553 {
3554   ChangeDatabase (p);
3555 }
3556 
3557 /*==================================================================*/
3558 /*                                                                  */
3559 /*  EditMessage_Callback () -                                       */
3560 /*                                                                  */
3561 /*==================================================================*/
3562 
EditMessage_Callback(ForM f,Int2 mssg)3563 static void EditMessage_Callback (ForM f, Int2 mssg)
3564 
3565 {
3566   FormInfoPtr  pFormInfo;
3567 
3568   pFormInfo = (FormInfoPtr) GetObjectExtra (f);
3569 
3570   switch (mssg) {
3571     case VIB_MSG_CUT:
3572       StdCutTextProc (NULL);
3573       break;
3574     case VIB_MSG_COPY:
3575       StdCopyTextProc (NULL);
3576       break;
3577     case VIB_MSG_PASTE:
3578       StdPasteTextProc (NULL);
3579       break;
3580     case VIB_MSG_DELETE:
3581       StdDeleteTextProc (NULL);
3582       break;
3583     default:
3584       if (pFormInfo->appmessage != NULL) {
3585         pFormInfo->appmessage (f, mssg);
3586       }
3587       break;
3588   }
3589 }
3590 
3591 /*==================================================================*/
3592 /*                                                                  */
3593 /*  TermListActivate_Callback () -                                  */
3594 /*                                                                  */
3595 /*==================================================================*/
3596 
TermListActivate_Callback(WindoW w)3597 static void TermListActivate_Callback (WindoW w)
3598 
3599 {
3600   FormInfoPtr  pFormInfo;
3601 
3602   pFormInfo = (FormInfoPtr) GetObjectExtra (w);
3603 
3604   if (pFormInfo->activate != NULL)
3605     pFormInfo->activate (w);
3606 }
3607 
3608 /*==================================================================*/
3609 /*                                                                  */
3610 /*  TermListCleanup_Callback () -                                   */
3611 /*                                                                  */
3612 /*==================================================================*/
3613 
TermListCleanup_Callback(GraphiC g,VoidPtr data)3614 static void TermListCleanup_Callback (GraphiC g, VoidPtr data)
3615 
3616 {
3617   FormInfoPtr  pFormInfo;
3618 
3619   pFormInfo = (FormInfoPtr) GetObjectExtra (g);
3620 
3621   MemFree (pFormInfo->fieldsPopup);
3622   StdCleanupFormProc (g, data);
3623 }
3624 
3625 /*==================================================================*/
3626 /*                                                                  */
3627 /*  Quit_Callback () -                                              */
3628 /*                                                                  */
3629 /*==================================================================*/
3630 
Quit_Callback(IteM i)3631 static void Quit_Callback (IteM i)
3632 
3633 {
3634   QuitProgram ();
3635 }
3636 
3637 /*==================================================================*/
3638 /*                                                                  */
3639 /*  StripNewLine () - Strip the newline character from the end of   */
3640 /*                   a string.                                      */
3641 /*                                                                  */
3642 /*==================================================================*/
3643 
StripNewLine(CharPtr str)3644 static void StripNewLine (CharPtr str)
3645 
3646 {
3647   CharPtr  chptr;
3648 
3649   if (StringHasNoText (str))
3650     return;
3651   chptr = StringRChr (str, '\n');
3652   if (chptr != NULL) {
3653     *chptr = '\0';
3654   }
3655   chptr = StringRChr (str, '\r');
3656   if (chptr != NULL) {
3657     *chptr = '\0';
3658   }
3659 }
3660 
3661 /*==================================================================*/
3662 /*                                                                  */
3663 /*  Query_AddUidsTerm () -                                          */
3664 /*                                                                  */
3665 /*==================================================================*/
3666 
Query_AddUidsTerm(ForM f,CharPtr uidListName,Int4 iUidCount,Int4Ptr uids,Int2 db)3667 static Boolean Query_AddUidsTerm (ForM f, CharPtr uidListName, Int4 iUidCount, Int4Ptr uids, Int2 db)
3668 
3669 {
3670   CharPtr            dbName;
3671   Entrez2RequestPtr  e2rq;
3672   Entrez2ReplyPtr    e2ry;
3673   StateDataPtr       sdp;
3674   StateDataPtr       prev;
3675   Char               displayStr [256];
3676   RecT               r;
3677   BaR                sb;
3678   FormInfoPtr        pFormInfo;
3679   Boolean            doNotTranslate;
3680 
3681   pFormInfo = (FormInfoPtr) GetObjectExtra (f);
3682 
3683   /*-----------------------------------------*/
3684   /* Make sure we don't add a Uid list twice */
3685   /*-----------------------------------------*/
3686 
3687   for (sdp = pFormInfo->termList; sdp != NULL; sdp = sdp->next)
3688     if (MeshStringICmp (sdp->term, uidListName) == 0) return FALSE;
3689 
3690   /*--------------------------------*/
3691   /* Create a term for the UID list */
3692   /*--------------------------------*/
3693 
3694   sdp = StateDataNew (pFormInfo);
3695   if (pFormInfo->termList == NULL)
3696     pFormInfo->termList = sdp;
3697 
3698   if (sdp == NULL) return FALSE;
3699 
3700   (pFormInfo->chosenNumLines)++;
3701 
3702   sdp->field = StringSave ("----");
3703   /* sdp->term = StringSave (uidListName); */
3704   sdp->count = iUidCount;
3705   /* sdp->uids = uids; */
3706   sdp->group = GROUP_SINGLE;
3707   sdp->above = ENTREZ_OP_NONE;
3708 
3709   dbName = DBGetNameFromID (pFormInfo->currDb);
3710   e2rq = EntrezCreateBooleanRequest (FALSE, FALSE, dbName, NULL, 0, 0, NULL, 0, 0);
3711   if (e2rq == NULL) return FALSE;
3712 
3713   doNotTranslate = FALSE;
3714   EntrezAddToBooleanRequest (e2rq, NULL, 0, NULL, NULL, NULL, 0, iUidCount, uids, NULL, FALSE, doNotTranslate);
3715   EntrezSetUseHistoryFlag (e2rq);
3716 
3717   if (ShowASN () == TRUE)
3718     DisplayEntrezRequest (e2rq);
3719 
3720   e2ry = SpecialEntrezSynchronousQuery (e2rq);
3721   if (e2ry == NULL) return FALSE;
3722 
3723   if (ShowASN () == TRUE)
3724     DisplayEntrezReply (e2ry);
3725 
3726   e2rq = Entrez2RequestFree (e2rq);
3727   sdp->key = StringSave (e2ry->key);
3728   sdp->term = StringSave (e2ry->key);
3729   Entrez2ReplyFree (e2ry);
3730 
3731   /*-------------------------------------*/
3732   /* Add the term to the current Query's */
3733   /* linked list of terms.               */
3734   /*-------------------------------------*/
3735 
3736   prev = sdp->prev;
3737   if (prev != NULL) {
3738     sdp->above = ENTREZ_OP_AND;
3739     prev->below = ENTREZ_OP_AND;
3740   }
3741   sdp->below = ENTREZ_OP_NONE;
3742   sdp->state = STATE_ON;
3743 
3744   /*---------------------------------------------*/
3745   /* Add the term to the query refinement window */
3746   /*---------------------------------------------*/
3747 
3748   sprintf (displayStr, "%s\t [%s]\t%ld\n", sdp->term, sdp->field, (long) iUidCount);
3749   AppendText (pFormInfo->chosenDoc, displayStr, &chosenParFmt, chosenColFmt, systemFont);
3750 
3751   /*---------------------------------*/
3752   /* Display our new query string in */
3753   /* Query Refinement window.        */
3754   /*---------------------------------*/
3755 
3756   InvalDocRows (pFormInfo->chosenDoc, pFormInfo->chosenNumLines, 1, 1);
3757   AdjustDocScroll (pFormInfo->chosenDoc);
3758   sb = GetSlateVScrollBar ((SlatE) pFormInfo->chosenDoc);
3759   ResetClip ();
3760   SetBarValue (sb, MAX (pFormInfo->chosenNumLines - 7, 0));
3761   ObjectRect (pFormInfo->chosenDoc, &r);
3762   InsetRect (&r, 4, 4);
3763   r.right = r.left + 16;
3764   InsetRect (&r, -1, -1);
3765   Select (pFormInfo->chosenDoc);
3766   InvalRect (&r);
3767 
3768   Update ();
3769 
3770   return TRUE;
3771 }
3772 
3773 /*==================================================================*/
3774 /*                                                                  */
3775 /*  ImportUIDs_Callback () -                                        */
3776 /*                                                                  */
3777 /*==================================================================*/
3778 
ImportUIDs_Callback(IteM i)3779 static void ImportUIDs_Callback (IteM i)
3780 
3781 {
3782   Entrez2InfoPtr    e2ip;
3783   Entrez2DbInfoPtr  e2dbInfo;
3784   FILE              *fp;
3785   FormInfoPtr       pFormInfo;
3786   ByteStorePtr      bsp;
3787   Int4              iUidCount;
3788   Char              fullName [PATH_MAX];
3789   CharPtr           baseName;
3790   Char              str [32];
3791   Int4              uid;
3792   Int4Ptr           uids = NULL;
3793   WindoW            w;
3794 
3795   /*----------------------------*/
3796   /* Get the Term Form info for */
3797   /* the parent window.         */
3798   /*----------------------------*/
3799 
3800 #ifdef WIN_MAC
3801   w = FrontWindow ();
3802 #else
3803   w = ParentWindow (i);
3804 #endif
3805 
3806   pFormInfo = (FormInfoPtr) GetObjectExtra (w);
3807 
3808   /*------------------------------*/
3809   /* Get the name of the UID file */
3810   /* and then open it.            */
3811   /*------------------------------*/
3812 
3813   if (! GetInputFileName (fullName, sizeof (fullName), "", "TEXT")) return;
3814 
3815   fp = FileOpen (fullName, "r");
3816   if (fp == NULL) return;
3817 
3818   /*-------------------------------*/
3819   /* Create a ByteStore Pointer to */
3820   /* store the UIDs in.            */
3821   /*-------------------------------*/
3822 
3823   bsp = BSNew (128);
3824   if (bsp == NULL) {
3825     FileClose (fp);
3826     return;
3827   }
3828 
3829   /*-------------------------------------*/
3830   /* Read the first line of the file and */
3831   /* verify that it contains a valid     */
3832   /* database name.                      */
3833   /*                                     */
3834   /* NOTE - Special case for medline     */
3835   /*        needs to me removed once     */
3836   /*        it is fixed on the server.   */
3837   /*                                     */
3838   /*-------------------------------------*/
3839 
3840   if (!FileGets (str, sizeof (str), fp)) {
3841     BSFree (bsp);
3842     FileClose (fp);
3843     return;
3844   }
3845 
3846   StripNewLine (str);
3847 
3848   e2ip = Query_GetInfo ();
3849 
3850   for (e2dbInfo = e2ip->db_info; e2dbInfo != NULL; e2dbInfo = e2dbInfo->next)
3851     if (StringICmp (e2dbInfo->db_menu, &str [1]) == 0) break;
3852 
3853   if (e2dbInfo == NULL) {
3854     Message (MSG_POSTERR, "First line must be in the form >DbName");
3855     BSFree (bsp);
3856     FileClose (fp);
3857     return;
3858   }
3859 
3860   /*-----------------------------------*/
3861   /* Read the rest of the lines in and */
3862   /* add each UID to the byteStore.    */
3863   /*-----------------------------------*/
3864 
3865   while (FileGets (str, sizeof (str), fp)) {
3866     StripNewLine (str);
3867     if (str [0] != '\0' && StrToLong (str, &uid))
3868       BSWrite (bsp, &uid, sizeof (DocUid));
3869   }
3870 
3871   BSSeek (bsp, 0L, 0);
3872   iUidCount = (Int4) ((BSLen (bsp)) / sizeof (Int4));
3873   uids = (Int4Ptr) BSMerge (bsp, NULL);
3874 
3875   /*--------------------------------*/
3876   /* Add the list of UIDs as a term */
3877   /* in the current query.          */
3878   /*--------------------------------*/
3879 
3880   baseName = FileNameFind (fullName);
3881   Query_AddUidsTerm (pFormInfo->form, baseName, iUidCount, uids, pFormInfo->currDb);
3882   Select (pFormInfo->termText);
3883 
3884   /*---------------------------*/
3885   /* Get a count of terms that */
3886   /* satisfy this query.       */
3887   /*---------------------------*/
3888 
3889   Update ();
3890   RecalculateChosen (pFormInfo);
3891   ArrowCursor ();
3892   Update ();
3893 
3894   /*----------------------------------*/
3895   /* Clean up and return successfully */
3896   /*----------------------------------*/
3897 
3898   BSFree (bsp);
3899   MemFree (uids);
3900   FileClose (fp);
3901 }
3902 
3903 /*==================================================================*/
3904 /*                                                                  */
3905 /*  ExportUIDs_Callback () -                                        */
3906 /*                                                                  */
3907 /*==================================================================*/
3908 
ExportUIDs_Callback(IteM i)3909 static void ExportUIDs_Callback (IteM i)
3910 
3911 {
3912   CharPtr                 dbName;
3913   Entrez2BooleanReplyPtr  e2BooleanPtr;
3914   Entrez2IdListPtr        e2UidList;
3915   FILE                    *fp;
3916   FormInfoPtr             pFormInfo;
3917   Char                    path [PATH_MAX];
3918   Char                    headerStr [32];
3919   Int4Ptr                 uids;
3920   Int4                    uidNum;
3921   Char                    uidStr [32];
3922   WindoW                  w;
3923 
3924   /*----------------------------*/
3925   /* Get the Term Form info for */
3926   /* the parent window.         */
3927   /*----------------------------*/
3928 
3929 #ifdef WIN_MAC
3930   w = FrontWindow ();
3931 #else
3932   w = ParentWindow (i);
3933 #endif
3934 
3935   pFormInfo = (FormInfoPtr) GetObjectExtra (w);
3936 
3937   /*-------------------------------*/
3938   /* Get a file name from the user */
3939   /* and open that file.           */
3940   /*-------------------------------*/
3941 
3942   if (! GetOutputFileName (path, sizeof (path), NULL)) return;
3943 
3944 #ifdef WIN_MAC
3945   FileCreate (path, "TEXT", "ttxt");
3946 #endif
3947 
3948   fp = FileOpen (path, "w");
3949   if (fp == NULL) return;
3950 
3951   WatchCursor ();
3952 
3953   /*-----------------------------------*/
3954   /* Write the header line to the file */
3955   /*-----------------------------------*/
3956 
3957   dbName = DBGetNameFromID (pFormInfo->currDb);
3958   sprintf (headerStr, ">%s\n", dbName);
3959   FilePuts (headerStr, fp);
3960 
3961   /*-----------------------*/
3962   /* Create a list of UIDS */
3963   /*-----------------------*/
3964 
3965   e2BooleanPtr = Query_FetchUIDs (pFormInfo->form);
3966   e2UidList = e2BooleanPtr->uids;
3967 
3968   uids = (Int4Ptr) BSMerge (e2UidList->uids, NULL);
3969 
3970   /*----------------------------*/
3971   /* Write the uids to the file */
3972   /*----------------------------*/
3973 
3974   for (uidNum = 0; uidNum < e2UidList->num; uidNum++) {
3975     sprintf (uidStr, "%ld\n", (long) uids [uidNum]);
3976     FilePuts (uidStr, fp);
3977   }
3978 
3979   /*----------------------------------*/
3980   /* Clean up and return successfully */
3981   /*----------------------------------*/
3982 
3983   FileClose (fp);
3984   free (uids);
3985   ArrowCursor ();
3986   Entrez2BooleanReplyFree (e2BooleanPtr);
3987 }
3988 
3989 /*==================================================================*/
3990 /*                                                                  */
3991 /*  AdvQueryInit () - Initialize the lexical static variables for   */
3992 /*                     parsing a new string.                        */
3993 /*                                                                  */
3994 /*==================================================================*/
3995 
AdvQueryInit(FormInfoPtr pFormInfo,CharPtr newStr)3996 static Int2 AdvQueryInit (FormInfoPtr pFormInfo, CharPtr newStr)
3997 
3998 {
3999   /*-----------------*/
4000   /* Check parameter */
4001   /*-----------------*/
4002 
4003   if (newStr == NULL) return -1;
4004 
4005   /*-----------------------------------------*/
4006   /* Initialize the lexical static variables */
4007   /* using the new string.                   */
4008   /*-----------------------------------------*/
4009 
4010   MemFree (pFormInfo->advQueryLexStr);
4011   pFormInfo->advQueryLexStr = StringSave (newStr);
4012   pFormInfo->advQueryLexPos = 0;
4013   pFormInfo->advQueryLexState = LEXSTATE_IDLE;
4014 
4015   /*-------------------------------------*/
4016   /* Free the linked list of query terms */
4017   /* so that we can build a new one with */
4018   /* the given string.                   */
4019   /*-------------------------------------*/
4020 
4021   ResetChosen (pFormInfo);
4022 
4023   /*---------------------*/
4024   /* Return successfully */
4025   /*---------------------*/
4026 
4027   return 0;
4028 }
4029 
4030 /*==================================================================*/
4031 /*                                                                  */
4032 /*  LexClassifyChar () -                                            */
4033 /*                                                                  */
4034 /*     NOTE -- Taken from LexClassifyChar() in accutils.c           */
4035 /*                                                                  */
4036 /*==================================================================*/
4037 
LexClassifyChar(Char c)4038 static Int2 LexClassifyChar (Char c)
4039 
4040 {
4041   Int2  retval;
4042 
4043   switch (c) {
4044     case '(':
4045       retval = LEXCHAR_LPAREN;
4046       break;
4047     case ')':
4048       retval = LEXCHAR_RPAREN;
4049       break;
4050     case '[':
4051       retval = LEXCHAR_LBRACKET;
4052       break;
4053     case ']':
4054       retval = LEXCHAR_RBRACKET;
4055       break;
4056     case '"':
4057       retval = LEXCHAR_QUOTE;
4058       break;
4059     case '&':
4060       retval = LEXCHAR_AND;
4061       break;
4062     case '|':
4063       retval = LEXCHAR_OR;
4064       break;
4065     case '-':
4066       retval = LEXCHAR_NOT;
4067       break;
4068     case ',':
4069       retval = LEXCHAR_COMMA;
4070       break;
4071     case '@':
4072       retval = LEXCHAR_ATSIGN;
4073       break;
4074     case '\\':
4075       retval = LEXCHAR_BACKSLASH;
4076       break;
4077     case ' ':
4078     case '\t':
4079       retval = LEXCHAR_WHITESPACE;
4080       break;
4081     case ';':
4082       retval = LEXCHAR_SEMICOLON;
4083       break;
4084     case ':':
4085       retval = LEXCHAR_COLON;
4086       break;
4087     case '\0':
4088       retval = LEXCHAR_NULL;
4089       break;
4090     case '\r':
4091     case '\n':
4092       retval = LEXCHAR_EOL;
4093       break;
4094     default:
4095       retval = LEXCHAR_OTHER;
4096       break;
4097   }
4098 
4099   return retval;
4100 }
4101 
4102 /*==================================================================*/
4103 /*                                                                  */
4104 /*  AdvQueryGetNextToken() -                                        */
4105 /*                                                                  */
4106 /*        Returns:                                                  */
4107 /*                                                                  */
4108 /*            StartPos - >0 : The position in the static string     */
4109 /*                            pFormInfo->advQueryLexStr where the   */
4110 /*                            token starts.                         */
4111 /*                                                                  */
4112 /*                       -1 : No token found.                       */
4113 /*                                                                  */
4114 /*        Sets:                                                     */
4115 /*                                                                  */
4116 /*            pFormInfo->advQueryNextToken : Contains an            */
4117 /*                            identifier specifying the type of     */
4118 /*                            the token, and if the token is a      */
4119 /*                            string also contains a pointer to     */
4120 /*                            the string.                           */
4121 /*                                                                  */
4122 /*                            Set to NULL if no token found.        */
4123 /*                                                                  */
4124 /*==================================================================*/
4125 
AdvQueryGetNextToken(FormInfoPtr pFormInfo)4126 static Int2 AdvQueryGetNextToken (FormInfoPtr pFormInfo)
4127 
4128 {
4129   Int2            startPos;
4130   Int2            classChar;
4131   Int2            token = 0;
4132   Boolean         done;
4133   Char            c;
4134   CharPtr         lexToken = NULL;
4135   CharPtr         lexTokenStart;
4136   Int2            len;
4137   Int2            pos;
4138 
4139   /*------------------*/
4140   /* Check conditions */
4141   /*------------------*/
4142 
4143   if (pFormInfo->advQueryLexStr == NULL) {
4144     pFormInfo->advQueryNextToken = NULL;
4145     return -1;
4146   }
4147 
4148   pFormInfo->advQueryNextToken = &pFormInfo->advQueryNextRealNode;
4149 
4150   /*--------------------------------------*/
4151   /* Find the beginning of the next token */
4152   /* and malloc space for it.             */
4153   /*--------------------------------------*/
4154 
4155   len = StringLen (pFormInfo->advQueryLexStr);
4156   startPos = pFormInfo->advQueryLexPos;
4157 
4158   if (pFormInfo->advQueryLexPos >= len) {
4159     pFormInfo->advQueryLexState = LEXSTATE_ERROR;
4160     token = -1;
4161     lexToken = MemNew (1);
4162   } else {
4163     pos = pFormInfo->advQueryLexPos;
4164     lexToken = MemNew (StringLen (&pFormInfo->advQueryLexStr [pos]) + 1);
4165   }
4166 
4167   lexTokenStart = lexToken;
4168 
4169   /*------------------*/
4170   /*------------------*/
4171 
4172   for (done = FALSE; !done && pFormInfo->advQueryLexPos <= len; pFormInfo->advQueryLexPos++) {
4173     c = pFormInfo->advQueryLexStr [pFormInfo->advQueryLexPos];
4174     classChar = LexClassifyChar (c);
4175     switch (pFormInfo->advQueryLexState) {
4176       case LEXSTATE_IDLE:
4177         switch (classChar) {
4178           case LEXCHAR_LPAREN:
4179             token = LEXTOK_LPAREN;
4180             done = TRUE;
4181             break;
4182           case LEXCHAR_RPAREN:
4183             token = LEXTOK_RPAREN;
4184             done = TRUE;
4185             break;
4186           case LEXCHAR_LBRACKET:
4187             token = LEXTOK_LBRACKET;
4188             done = TRUE;
4189             break;
4190           case LEXCHAR_RBRACKET:
4191             token = LEXTOK_RBRACKET;
4192             done = TRUE;
4193             break;
4194           case LEXCHAR_AND:
4195             token = LEXTOK_AND;
4196             done = TRUE;
4197             break;
4198           case LEXCHAR_OR:
4199             token = LEXTOK_OR;
4200             done = TRUE;
4201             break;
4202           case LEXCHAR_NOT:
4203             token = LEXTOK_NOT;
4204             done = TRUE;
4205             break;
4206           case LEXCHAR_COMMA:
4207             token = LEXTOK_COMMA;
4208             done = TRUE;
4209             break;
4210           case LEXCHAR_ATSIGN:
4211             token = LEXTOK_ATSIGN;
4212             done = TRUE;
4213             break;
4214           case LEXCHAR_COLON:
4215             token = LEXTOK_RANGE;
4216             done = TRUE;
4217             break;
4218           case LEXCHAR_QUOTE:
4219             pFormInfo->advQueryLexState = LEXSTATE_INQUOTE;
4220             break;
4221           case LEXCHAR_BACKSLASH:
4222             pFormInfo->advQueryLexState = LEXSTATE_BACKSLASHED;
4223             break;
4224           case LEXCHAR_EOL:
4225           case LEXCHAR_WHITESPACE:
4226             startPos = pFormInfo->advQueryLexPos + 1;
4227             break;
4228           case LEXCHAR_SEMICOLON:
4229           case LEXCHAR_NULL:
4230             pFormInfo->advQueryLexState = LEXSTATE_ERROR;
4231             done = TRUE;
4232             break;
4233           case LEXCHAR_OTHER:
4234           default:
4235             pFormInfo->advQueryLexState = LEXSTATE_INSTRING;
4236             *lexToken++ = c;
4237             break;
4238         }
4239         break;
4240       case LEXSTATE_BACKSLASHED:
4241         switch (classChar) {
4242           case LEXCHAR_NULL:
4243           case LEXCHAR_EOL:
4244             *lexToken++ = '\0';
4245             done = TRUE;
4246             pFormInfo->advQueryLexState = LEXSTATE_IDLE;
4247             break;
4248           case LEXCHAR_LPAREN:
4249           case LEXCHAR_RPAREN:
4250           case LEXCHAR_LBRACKET:
4251           case LEXCHAR_RBRACKET:
4252           case LEXCHAR_QUOTE:
4253           case LEXCHAR_AND:
4254           case LEXCHAR_OR:
4255           case LEXCHAR_NOT:
4256           case LEXCHAR_COMMA:
4257           case LEXCHAR_ATSIGN:
4258           case LEXCHAR_BACKSLASH:
4259           case LEXCHAR_WHITESPACE:
4260           case LEXCHAR_SEMICOLON:
4261           case LEXCHAR_COLON:
4262           case LEXCHAR_OTHER:
4263           default:
4264             pFormInfo->advQueryLexState = LEXSTATE_INSTRING;
4265             *lexToken++ = c;
4266             break;
4267         }
4268         break;
4269       case LEXSTATE_INQUOTE:
4270         switch (classChar) {
4271           case LEXCHAR_QUOTE:
4272             token = LEXTOK_STRING;
4273             *lexToken++ = '\0';
4274             done = TRUE;
4275             pFormInfo->advQueryLexState = LEXSTATE_IDLE;
4276             break;
4277           case LEXCHAR_BACKSLASH:
4278             pFormInfo->advQueryLexState = LEXSTATE_INQUOTE_AFTERBSLASH;
4279             break;
4280           case LEXCHAR_NULL:
4281           case LEXCHAR_EOL:
4282             pFormInfo->advQueryLexState = LEXSTATE_ERROR;
4283             done = TRUE;
4284             break;
4285           default:
4286             *lexToken++ = c;
4287             break;
4288         }
4289         break;
4290       case LEXSTATE_INQUOTE_AFTERBSLASH:
4291         switch (classChar) {
4292           case LEXCHAR_NULL:
4293           case LEXCHAR_EOL:
4294             pFormInfo->advQueryLexState = LEXSTATE_ERROR;
4295             done = TRUE;
4296             break;
4297           default:
4298             pFormInfo->advQueryLexState = LEXSTATE_INQUOTE;
4299             *lexToken++ = c;
4300             break;
4301         }
4302         break;
4303       case LEXSTATE_INSTRING:
4304         switch (classChar) {
4305           case LEXCHAR_WHITESPACE:
4306           case LEXCHAR_SEMICOLON:
4307           case LEXCHAR_NULL:
4308           case LEXCHAR_EOL:
4309             token = LEXTOK_STRING;
4310             *lexToken++ = '\0';
4311             done = TRUE;
4312             pFormInfo->advQueryLexState = LEXSTATE_IDLE;
4313             break;
4314           case LEXCHAR_BACKSLASH:
4315             pFormInfo->advQueryLexState = LEXSTATE_BACKSLASHED;
4316             break;
4317           case LEXCHAR_QUOTE:
4318             pFormInfo->advQueryLexState = LEXSTATE_INQUOTE;
4319             break;
4320           case LEXCHAR_OTHER:
4321             *lexToken++ = c;
4322             break;
4323           default:
4324             token = LEXTOK_STRING;
4325             *lexToken++ = '\0';
4326             done = TRUE;
4327             pFormInfo->advQueryLexState = LEXSTATE_IDLE;
4328             pFormInfo->advQueryLexPos--;        /* push back last character */
4329             break;
4330         }
4331         break;
4332       case LEXSTATE_ERROR:
4333         done = TRUE;
4334         break;
4335     }
4336   }
4337 
4338   pFormInfo->advQueryNextToken->choice = (Uint1) token;
4339   pFormInfo->advQueryNextToken->data.ptrvalue = NULL;
4340 
4341   if (token == LEXTOK_STRING)
4342     pFormInfo->advQueryNextToken->data.ptrvalue = lexTokenStart;
4343   else
4344     MemFree (lexTokenStart);
4345 
4346   if (pFormInfo->advQueryLexState == LEXSTATE_ERROR) {
4347     pFormInfo->advQueryNextToken = NULL;
4348     return -1;
4349   } else
4350     return startPos;
4351 }
4352 
4353 /*===================================================================*/
4354 /*                                                                   */
4355 /*  CloseGroup () -                                                  */
4356 /*                                                                   */
4357 /*===================================================================*/
4358 
CloseGroup(FormInfoPtr pFormInfo)4359 static Boolean CloseGroup (FormInfoPtr pFormInfo)
4360 
4361 {
4362   StateDataPtr  pLastTerm;
4363 
4364   /*--------------*/
4365   /* Sanity check */
4366   /*--------------*/
4367 
4368   if (pFormInfo == NULL || pFormInfo->termList == NULL) return FALSE;
4369 
4370   /*--------------------------------*/
4371   /* Find the last term in the list */
4372   /*--------------------------------*/
4373 
4374   pLastTerm = pFormInfo->termList;
4375   while (pLastTerm->next != NULL)
4376     pLastTerm = pLastTerm->next;
4377 
4378   /*----------------------*/
4379   /* Set its group status */
4380   /*----------------------*/
4381 
4382   switch (pLastTerm->group) {
4383     case GROUP_SINGLE:
4384     case GROUP_LAST:
4385       break;
4386     case GROUP_FIRST:
4387       pLastTerm->group = GROUP_SINGLE;
4388       break;
4389     case GROUP_MIDDLE:
4390       pLastTerm->group = GROUP_LAST;
4391       break;
4392     default:
4393       break;
4394   }
4395 
4396   /*---------------------*/
4397   /* Return successfully */
4398   /*---------------------*/
4399 
4400   return TRUE;
4401 }
4402 
4403 /*===================================================================*/
4404 /*                                                                   */
4405 /*  ParseANDedTerms () -                                             */
4406 /*                                                                   */
4407 /*     NOTE -- Brought over from accutils.c                          */
4408 /*                                                                   */
4409 /*===================================================================*/
4410 
4411 /* prototype for recursive function */
4412 
4413 static Boolean ParseTermList (FormInfoPtr pFormInfo, Int2 db, Int2 fld, Int2 currOp);
4414 
ParseANDedTerms(FormInfoPtr pFormInfo,Int2 db,Int2 fld,Int2 currOp)4415 static Boolean ParseANDedTerms (FormInfoPtr pFormInfo, Int2 db, Int2 fld, Int2 currOp)
4416 
4417 {
4418   if (! ParseTermList (pFormInfo, db, fld, currOp)) return FALSE;
4419 
4420   while (pFormInfo->advQueryNextToken != NULL && pFormInfo->advQueryNextToken->choice == LEXTOK_AND) {
4421     AdvQueryGetNextToken (pFormInfo);
4422     if (! ParseTermList (pFormInfo, db, fld, LEXCHAR_AND)) return FALSE;
4423   }
4424 
4425   return TRUE;
4426 }
4427 
4428 /*===================================================================*/
4429 /*                                                                   */
4430 /*  ParseORedTerms () -                                              */
4431 /*                                                                   */
4432 /*     NOTE -- Brought over from accutils.c                          */
4433 /*                                                                   */
4434 /*===================================================================*/
4435 
ParseORedTerms(FormInfoPtr pFormInfo,Int2 db,Int2 fld,Int2 currOp)4436 static Boolean ParseORedTerms (FormInfoPtr pFormInfo, Int2 db, Int2 fld, Int2 currOp)
4437 
4438 {
4439   if (! ParseANDedTerms (pFormInfo, db, fld, currOp)) return FALSE;
4440 
4441   while (pFormInfo->advQueryNextToken != NULL && pFormInfo->advQueryNextToken->choice == LEXTOK_OR) {
4442     AdvQueryGetNextToken (pFormInfo);
4443     if (! ParseANDedTerms (pFormInfo, db, fld, LEXCHAR_OR)) return FALSE;
4444   }
4445 
4446   return TRUE;
4447 }
4448 
4449 /*===================================================================*/
4450 /*                                                                   */
4451 /*  ParseNOTedTerms () -                                             */
4452 /*                                                                   */
4453 /*     NOTE -- This function brought over from accutils.c            */
4454 /*                                                                   */
4455 /*===================================================================*/
4456 
ParseNOTedTerms(FormInfoPtr pFormInfo,Int2 db,Int2 fld,Int2 currOp)4457 static Boolean ParseNOTedTerms (FormInfoPtr pFormInfo, Int2 db, Int2 fld, Int2 currOp)
4458 
4459 {
4460   if (! ParseORedTerms (pFormInfo, db, fld, currOp)) return FALSE;
4461 
4462   while ((pFormInfo->advQueryNextToken != NULL) && (pFormInfo->advQueryNextToken->choice == LEXTOK_NOT)) {
4463     AdvQueryGetNextToken (pFormInfo);
4464     if (! ParseORedTerms (pFormInfo, db, fld, LEXCHAR_NOT)) return FALSE;
4465   }
4466 
4467   return TRUE;
4468 }
4469 
4470 /*===================================================================*/
4471 /*                                                                   */
4472 /*  ParseTermList () -                                               */
4473 /*                                                                   */
4474 /*===================================================================*/
4475 
ParseTermList(FormInfoPtr pFormInfo,Int2 db,Int2 fld,Int2 currOp)4476 static Boolean ParseTermList (FormInfoPtr pFormInfo, Int2 db, Int2 fld, Int2 currOp)
4477 
4478 {
4479   CharPtr       term;
4480   CharPtr       fldStr;
4481   CharPtr       highRangeStr = NULL;
4482   StateDataPtr  newTermPtr;
4483   Int2          nOperator;
4484 
4485   /*---------------------------------------------*/
4486   /* Check for proper conditions to run function */
4487   /*---------------------------------------------*/
4488 
4489   if (pFormInfo->advQueryNextToken == NULL) {
4490     ErrPostEx (SEV_WARNING, ERR_CD_LEX, 0, "Null factor");
4491     return FALSE;
4492   }
4493 
4494   /*------------------------------------------*/
4495   /* If we have a left paren, then recursivly */
4496   /* parse what follows it as a term list.    */
4497   /*------------------------------------------*/
4498 
4499   if (pFormInfo->advQueryNextToken->choice == LEXTOK_LPAREN) {
4500     pFormInfo->advQueryNewGroup = TRUE;
4501     AdvQueryGetNextToken (pFormInfo);
4502     if (! ParseNOTedTerms (pFormInfo, db, fld, currOp))
4503       return FALSE;
4504 
4505       /*---------------------------*/
4506     /* If we have a right paren, */
4507     /* close out group.          */
4508       /*---------------------------*/
4509 
4510     if (pFormInfo->advQueryNextToken != NULL && pFormInfo->advQueryNextToken->choice == LEXTOK_RPAREN) {
4511       CloseGroup (pFormInfo);
4512       AdvQueryGetNextToken (pFormInfo);
4513     } else {
4514       ErrPostEx (SEV_WARNING, ERR_CD_LEX, 0, "Missing right paren");
4515       return FALSE;
4516     }
4517 
4518     return TRUE;
4519   }
4520 
4521   /*--------------------------*/
4522   /* Otherwise, grab the term */
4523   /*--------------------------*/
4524 
4525   if (pFormInfo->advQueryNextToken->choice != LEXTOK_STRING) {
4526     ErrPostEx (SEV_WARNING, ERR_CD_LEX, 0, "invalid token");
4527     return FALSE;
4528   }
4529 
4530   term = (CharPtr) (pFormInfo->advQueryNextToken->data.ptrvalue);
4531   AdvQueryGetNextToken (pFormInfo);
4532 
4533   /*---------------------------------------*/
4534   /* If it's a range, grab the second term */
4535   /*---------------------------------------*/
4536 
4537   if ((pFormInfo->advQueryNextToken != NULL) && (pFormInfo->advQueryNextToken->choice == LEXTOK_RANGE)) {
4538     AdvQueryGetNextToken (pFormInfo);
4539     if ((pFormInfo->advQueryNextToken == NULL) || (pFormInfo->advQueryNextToken->choice != LEXTOK_STRING)) {
4540       ErrPostEx (SEV_WARNING, ERR_CD_LEX, 0, "missing second half of range");
4541       MemFree (term);
4542       return FALSE;
4543     }
4544     highRangeStr = (CharPtr) (pFormInfo->advQueryNextToken->data.ptrvalue);
4545     AdvQueryGetNextToken (pFormInfo);
4546   }
4547 
4548   /*----------------------*/
4549   /* Parse the field name */
4550   /*----------------------*/
4551 
4552   if ((pFormInfo->advQueryNextToken != NULL) && (pFormInfo->advQueryNextToken->choice == LEXTOK_LBRACKET)) {
4553 
4554       /*----------------------*/
4555     /* Get the field string */
4556       /*----------------------*/
4557 
4558     AdvQueryGetNextToken (pFormInfo);
4559     if ((pFormInfo->advQueryNextToken == NULL) || (pFormInfo->advQueryNextToken->choice != LEXTOK_STRING)) {
4560       ErrPostEx (SEV_WARNING, ERR_CD_LEX, 0, "missing field id after bracket");
4561       MemFree (term);
4562       MemFree (highRangeStr);
4563       return FALSE;
4564     }
4565 
4566     fldStr = (CharPtr) (pFormInfo->advQueryNextToken->data.ptrvalue);
4567 
4568       /*-------------------------------------*/
4569     /* Convert string to field ID, mapping */
4570     /* wildcard '*' to 'ALL'.              */
4571       /*-------------------------------------*/
4572 
4573     if (fldStr != NULL && StrCmp (fldStr, "*") == 0)
4574       fld = FieldGetIDFromName (db, "ALL");
4575     else
4576       fld = FieldGetIDFromName (db, fldStr);
4577 
4578     MemFree (pFormInfo->advQueryNextToken->data.ptrvalue);
4579     if (fld < 0) {
4580       ErrPostEx (SEV_WARNING, ERR_CD_LEX, 0, "bad field identifier");
4581       MemFree (term);
4582       MemFree (highRangeStr);
4583       return FALSE;
4584     }
4585 
4586       /*----------------------------------*/
4587     /* Check to see if the fields are a */
4588     /* comma-seperated range.           */
4589       /*----------------------------------*/
4590 
4591     AdvQueryGetNextToken (pFormInfo);
4592     if ((pFormInfo->advQueryNextToken == NULL) ||
4593         (pFormInfo->advQueryNextToken->choice != LEXTOK_COMMA && pFormInfo->advQueryNextToken->choice != LEXTOK_RBRACKET)) {
4594       ErrPostEx (SEV_WARNING, ERR_CD_LEX, 0, "missing right bracket");
4595       MemFree (term);
4596       MemFree (highRangeStr);
4597       return FALSE;
4598     }
4599     if (pFormInfo->advQueryNextToken->choice == LEXTOK_COMMA) {
4600       AdvQueryGetNextToken (pFormInfo);
4601       if ((pFormInfo->advQueryNextToken == NULL) ||
4602           (pFormInfo->advQueryNextToken->choice != LEXTOK_STRING) || StringCmp (pFormInfo->advQueryNextToken->data.ptrvalue, "S") != 0) {
4603         ErrPostEx (SEV_WARNING, ERR_CD_LEX, 0, "field qualifier error");
4604         MemFree (term);
4605         MemFree (highRangeStr);
4606         return FALSE;
4607       }
4608       MemFree (pFormInfo->advQueryNextToken->data.ptrvalue);
4609       AdvQueryGetNextToken (pFormInfo);
4610       if ((pFormInfo->advQueryNextToken == NULL) || (pFormInfo->advQueryNextToken->choice != LEXTOK_RBRACKET)) {
4611         ErrPostEx (SEV_WARNING, ERR_CD_LEX, 0, "missing right bracket");
4612         MemFree (term);
4613         MemFree (highRangeStr);
4614         return FALSE;
4615       }
4616     }
4617     AdvQueryGetNextToken (pFormInfo);
4618   }
4619 
4620   /*-------------------------------------*/
4621   /* Add in the high range, if it exists */
4622   /*-------------------------------------*/
4623 
4624   if (highRangeStr != NULL) {
4625     StringCat (term, ":");
4626     StringCat (term, highRangeStr);
4627   }
4628 
4629   /*-----------------------------------------------*/
4630   /* Create a new term and add it to the term list */
4631   /*-----------------------------------------------*/
4632 
4633   newTermPtr = Query_AddBoolTerm (pFormInfo->form, db, fld, term, STATE_ON, 0);
4634 
4635   if (newTermPtr == NULL) return FALSE;
4636 
4637   /*---------------------------------------*/
4638   /* Select the proper operator with which */
4639   /* to connect it to the previous term.   */
4640   /*---------------------------------------*/
4641 
4642   switch (currOp) {
4643     case LEXCHAR_OR:
4644       nOperator = ENTREZ_OP_OR;
4645       break;
4646     case LEXCHAR_AND:
4647       nOperator = ENTREZ_OP_AND;
4648       break;
4649     case LEXCHAR_NOT:
4650       nOperator = ENTREZ_OP_BUTNOT;
4651       break;
4652     default:
4653       nOperator = ENTREZ_OP_NONE;
4654       break;
4655   }
4656   newTermPtr->above = nOperator;
4657   if (newTermPtr->prev != NULL)
4658     newTermPtr->prev->below = nOperator;
4659 
4660   /*-------------------------------*/
4661   /* Set its group status properly */
4662   /*-------------------------------*/
4663 
4664   if (pFormInfo->advQueryNewGroup == TRUE) {
4665     newTermPtr->group = GROUP_FIRST;
4666     pFormInfo->advQueryNewGroup = FALSE;
4667   } else if (newTermPtr->prev != NULL) {
4668     switch (newTermPtr->prev->group) {
4669       case GROUP_SINGLE:
4670         newTermPtr->group = GROUP_SINGLE;
4671         break;
4672       case GROUP_FIRST:
4673       case GROUP_MIDDLE:
4674         newTermPtr->group = GROUP_MIDDLE;
4675         break;
4676       default:
4677         newTermPtr->group = GROUP_SINGLE;
4678         break;
4679     }
4680   }
4681 
4682 
4683 /*----------------------------------*/
4684 /* Clean up and return successfully */
4685 /*----------------------------------*/
4686 
4687   MemFree (term);
4688   MemFree (highRangeStr);
4689 
4690   return TRUE;
4691 }
4692 
4693 /*===================================================================*/
4694 /*                                                                   */
4695 /*  Query_ParseString () -                                           */
4696 /*                                                                   */
4697 /*     NOTE -- This function is based on EntrezPMTLParseString()     */
4698 /*             from accutil.c                                        */
4699 /*                                                                   */
4700 /*===================================================================*/
4701 
Query_ParseString(ForM f,CharPtr str,Int2 db,Int2 fld)4702 static Boolean Query_ParseString (ForM f, CharPtr str, Int2 db, Int2 fld)
4703 
4704 {
4705   Boolean      retval;
4706   FormInfoPtr  pFormInfo;
4707 
4708   pFormInfo = (FormInfoPtr) GetObjectExtra (f);
4709 
4710   /*---------------------------*/
4711   /* Check parameters, setting */
4712   /* defaults if necessary.    */
4713   /*---------------------------*/
4714 
4715   if (str == NULL || *str == '\0') return FALSE;
4716 
4717   /*------------------------------------*/
4718   /* Clear out the existing query terms */
4719   /*------------------------------------*/
4720 
4721   AdvQueryInit (pFormInfo, str);
4722 
4723   /*------------------------------------*/
4724   /* Recursively parse the query string */
4725   /*------------------------------------*/
4726 
4727   AdvQueryGetNextToken (pFormInfo);
4728 
4729   if ((ParseNOTedTerms (pFormInfo, db, fld, 0) == TRUE) && (pFormInfo->advQueryNextToken == NULL))
4730     retval = TRUE;
4731   else {
4732     ResetChosen (pFormInfo);
4733     retval = FALSE;
4734   }
4735 
4736   /*---------------------*/
4737   /* Return successfully */
4738   /*---------------------*/
4739 
4740   return retval;
4741 }
4742 
4743 /*==================================================================*/
4744 /*                                                                  */
4745 /*  AdvancedQueryText_Callback () -                                 */
4746 /*                                                                  */
4747 /*==================================================================*/
4748 
AdvancedQueryText_Callback(TexT queryTextBox)4749 static void AdvancedQueryText_Callback (TexT queryTextBox)
4750 
4751 {
4752   CharPtr      curstr;
4753   FormInfoPtr  pFormInfo;
4754 
4755   pFormInfo = (FormInfoPtr) GetObjectExtra (queryTextBox);
4756 
4757   curstr = SaveStringFromText (pFormInfo->advQueryText);
4758 
4759   if (Query_ParseString (pFormInfo->form, curstr, pFormInfo->currDb, -1)) {
4760 
4761     SafeEnable (pFormInfo->advRetrieveButton);
4762     pFormInfo->advQueryState = ADV_QUERY_EVALUATE_STATE;
4763     SafeSetTitle (pFormInfo->advRetrieveButton, "Evaluate");
4764   } else {
4765     SafeDisable (pFormInfo->advRetrieveButton);
4766     pFormInfo->advQueryState = ADV_QUERY_INVALID_STATE;
4767   }
4768 
4769   MemFree (curstr);
4770 }
4771 
4772 /*==================================================================*/
4773 /*                                                                  */
4774 /*  SetAdvancedText () -                                            */
4775 /*                                                                  */
4776 /*==================================================================*/
4777 
SetAdvancedText(TexT advancedText,CharPtr str)4778 static void SetAdvancedText (TexT advancedText, CharPtr str)
4779 
4780 {
4781   SetTitle (advancedText, str);
4782 }
4783 
4784 /*==================================================================*/
4785 /*                                                                  */
4786 /*  RepopulateChosen () -                                           */
4787 /*                                                                  */
4788 /*==================================================================*/
4789 
RepopulateChosen(FormInfoPtr pFormInfo)4790 static void RepopulateChosen (FormInfoPtr pFormInfo)
4791 
4792 {
4793   Int4          off;
4794   BaR           sb;
4795   StateDataPtr  sdp;
4796   Char          strn [256];
4797 
4798   sb = GetSlateVScrollBar ((SlatE) pFormInfo->chosenDoc);
4799   off = GetBarValue (sb);
4800   Reset (pFormInfo->chosenDoc);
4801 
4802   InvalDocument (pFormInfo->chosenDoc);
4803   pFormInfo->chosenNumLines = 0;
4804   for (sdp = pFormInfo->termList; sdp != NULL; sdp = sdp->next) {
4805     (pFormInfo->chosenNumLines)++;
4806     if (sdp->field == NULL)
4807       sprintf (strn, "%s\t [----]\t%ld\n", sdp->term, (long) sdp->count);
4808     else
4809       sprintf (strn, "%s\t [%s]\t%ld\n", sdp->term, sdp->field, (long) sdp->count);
4810     AppendText (pFormInfo->chosenDoc, strn, &chosenParFmt, chosenColFmt, systemFont);
4811   }
4812   InvalDocument (pFormInfo->chosenDoc);
4813   AdjustDocScroll (pFormInfo->chosenDoc);
4814   CorrectBarValue (sb, off);
4815   Update ();
4816 }
4817 
4818 /*==================================================================*/
4819 /*                                                                  */
4820 /*  Query_ConvertToString () - Convert the current linked list of   */
4821 /*                            terms into a string that can be       */
4822 /*                            displayed in the advanced query win.  */
4823 /*                                                                  */
4824 /*==================================================================*/
4825 
Query_ConvertToString(ForM f)4826 static CharPtr Query_ConvertToString (ForM f)
4827 
4828 {
4829   Entrez2FieldInfoPtr  fieldInfo;
4830   Int2                 group;
4831   Int2                 last;
4832   CharPtr              ptr;
4833   StateDataPtr         sdp;
4834   CharPtr              tmp;
4835   CharPtr              advQueryString;
4836   FormInfoPtr          pFormInfo;
4837 
4838   pFormInfo = (FormInfoPtr) GetObjectExtra (f);
4839 
4840   if (pFormInfo->termList == NULL) return NULL;
4841 
4842   if (pFormInfo->chosenNumLines < 1) return NULL;
4843 
4844   advQueryString = MemNew (1000);
4845   advQueryString [0] = '\0';
4846   group = 0;
4847   last = 0;
4848   for (sdp = pFormInfo->termList; sdp != NULL; sdp = sdp->next) {
4849     if (sdp->group == GROUP_SINGLE || sdp->group == GROUP_FIRST)
4850       group++;
4851 
4852     if (sdp->state == STATE_ON) {
4853       if (last == 0) {
4854         StrCat (advQueryString, "( ");
4855         StrCat (advQueryString, "( ");
4856       } else if (last == group) {
4857         StrCat (advQueryString, " | ");
4858       } else if (sdp->above == ENTREZ_OP_BUTNOT) {
4859         StrCat (advQueryString, " )");
4860         StrCat (advQueryString, " )");
4861         StrCat (advQueryString, " - ");
4862         StrCat (advQueryString, "( ");
4863         StrCat (advQueryString, "( ");
4864       } else {
4865         StrCat (advQueryString, " )");
4866         StrCat (advQueryString, " & ");
4867         StrCat (advQueryString, "( ");
4868       }
4869       StringCat (advQueryString, "\"");
4870       tmp = StringSave (sdp->term);
4871       ptr = StringChr (tmp, ':');
4872       if (ptr != NULL) {
4873         *ptr = '\0';
4874         ptr++;
4875         TrimSpacesAroundString (tmp);
4876         TrimSpacesAroundString (ptr);
4877         StringCat (advQueryString, tmp);
4878         StringCat (advQueryString, "\" : \"");
4879         StringCat (advQueryString, ptr);
4880       } else
4881         StringCat (advQueryString, tmp);
4882       MemFree (tmp);
4883       StringCat (advQueryString, "\"[");
4884       fieldInfo = FieldGetInfo (sdp->db, sdp->fld);
4885       StringCat (advQueryString, fieldInfo->field_name);
4886       StringCat (advQueryString, "]");
4887       last = group;
4888     }
4889   }
4890 
4891   if (group > 0 && last > 0) {
4892     StrCat (advQueryString, " )");
4893     StrCat (advQueryString, " )");
4894   }
4895 
4896   return advQueryString;
4897 }
4898 
4899 /*==================================================================*/
4900 /*                                                                  */
4901 /*  AdvancedQueryToggle_Callback () - Called when the "Advanced     */
4902 /*                                   Queries" menu option is        */
4903 /*                                   selected.                      */
4904 /*                                                                  */
4905 /*==================================================================*/
4906 
AdvancedQueryToggle_Callback(IteM i)4907 static void AdvancedQueryToggle_Callback (IteM i)
4908 
4909 {
4910   FormInfoPtr  pFormInfo;
4911   CharPtr      str;
4912 
4913   pFormInfo = (FormInfoPtr) GetObjectExtra (i);
4914 
4915   /*-----------------------*/
4916   /* Advanced ==> Standard */
4917   /*-----------------------*/
4918 
4919   if (! GetStatus (pFormInfo->advancedQueryItem)) {
4920     SafeHide (pFormInfo->advQueryGroup);
4921     Reset (pFormInfo->advQueryText);
4922     RepopulateChosen (pFormInfo);
4923     SafeShow (pFormInfo->stdQueryGroup);
4924   }
4925 
4926   /*-----------------------*/
4927   /* Standard ==> Advanced */
4928   /*-----------------------*/
4929 
4930   else {
4931     str = Query_ConvertToString (pFormInfo->form);
4932     SetAdvancedText (pFormInfo->advQueryText, str);
4933     MemFree (str);
4934     SafeHide (pFormInfo->stdQueryGroup);
4935     SafeShow (pFormInfo->advQueryGroup);
4936   }
4937 }
4938 
4939 /*==================================================================*/
4940 /*                                                                  */
4941 /*  ExplodeTermsToggle_Callback () - Called when the "Explode       */
4942 /*                                   Terms" menu option is          */
4943 /*                                   selected.                      */
4944 /*                                                                  */
4945 /*==================================================================*/
4946 
ExplodeTermsToggle_Callback(IteM i)4947 static void ExplodeTermsToggle_Callback (IteM i)
4948 
4949 {
4950   FormInfoPtr  pFormInfo;
4951 
4952   pFormInfo = (FormInfoPtr) GetObjectExtra (i);
4953   if (pFormInfo == NULL) return;
4954 
4955   WatchCursor ();
4956   Update ();
4957   RecalculateChosen (pFormInfo);
4958   ArrowCursor ();
4959   Update ();
4960 }
4961 
4962 /*===================================================================*/
4963 /*                                                                   */
4964 /*  TermList_UnselectAll () -- Marks all terms in the term list as   */
4965 /*                            unselected.                            */
4966 /*                                                                   */
4967 /*===================================================================*/
4968 
TermList_UnselectAll(ForM f)4969 NLM_EXTERN Boolean TermList_UnselectAll (ForM f)
4970 
4971 {
4972   Int2          count = 0;
4973   Int2          item;
4974   FormInfoPtr   pFormInfo;
4975   StateDataPtr  sdp;
4976 
4977   pFormInfo = (FormInfoPtr) GetObjectExtra (f);
4978 
4979   sdp = pFormInfo->termList;
4980   while (sdp != NULL) {
4981     sdp->state = STATE_OFF;
4982     sdp = sdp->next;
4983     count++;
4984   }
4985 
4986   ResetClip ();
4987   WatchCursor ();
4988   for (item = 1; item <= count; item++) {
4989     InvalDocCols (pFormInfo->chosenDoc, item, 3, 3);
4990   }
4991   Update ();
4992   RecalculateChosen (pFormInfo);
4993   ArrowCursor ();
4994 
4995   return TRUE;
4996 }
4997 
4998 /*==================================================================*/
4999 /*                                                                  */
5000 /*  AlphabetizeGroups () -                                          */
5001 /*                                                                  */
5002 /*==================================================================*/
5003 
AlphabetizeGroups(FormInfoPtr pFormInfo)5004 static void AlphabetizeGroups (FormInfoPtr pFormInfo)
5005 
5006 {
5007   Int2          compare;
5008   Boolean       keepGoing;
5009   StateDataPtr  next;
5010   StateDataPtr  sdp;
5011   StateData     tmp;
5012 
5013   if (pFormInfo->termList == NULL) return;
5014 
5015   keepGoing = TRUE;
5016   while (keepGoing) {
5017     keepGoing = FALSE;
5018     for (sdp = pFormInfo->termList; sdp->next != NULL; sdp = sdp->next) {
5019       next = sdp->next;
5020       if (sdp->group == GROUP_FIRST || sdp->group == GROUP_MIDDLE) {
5021         compare = MeshStringICmp (sdp->term, next->term);
5022         if (compare > 0) {
5023           tmp.term = next->term;
5024           tmp.field = next->field;
5025           tmp.count = next->count;
5026           tmp.db = next->db;
5027           tmp.fld = next->fld;
5028           next->term = sdp->term;
5029           next->field = sdp->field;
5030           next->count = sdp->count;
5031           next->db = sdp->db;
5032           next->fld = sdp->fld;
5033           sdp->term = tmp.term;
5034           sdp->field = tmp.field;
5035           sdp->count = tmp.count;
5036           sdp->db = tmp.db;
5037           sdp->fld = tmp.fld;
5038           keepGoing = TRUE;
5039         }
5040       }
5041     }
5042   }
5043 }
5044 
5045 /*==================================================================*/
5046 /*                                                                  */
5047 /*  Query_ClearUnusedTerms () - Remove any terms that have been     */
5048 /*                              turned off.                         */
5049 /*                                                                  */
5050 /*==================================================================*/
5051 
Query_ClearUnusedTerms(IteM i)5052 static void Query_ClearUnusedTerms (IteM i)
5053 
5054 {
5055   StateDataPtr       next;
5056   StateDataPtr       sdp;
5057   FormInfoPtr        pFormInfo;
5058 
5059   pFormInfo = (FormInfoPtr) GetObjectExtra (i);
5060 
5061   WatchCursor ();
5062   Update ();
5063 
5064   /* Iterate through the list, removing all */
5065   /* terms that are marked as unused.       */
5066 
5067   sdp = pFormInfo->termList;
5068 
5069   while (sdp != NULL) {
5070     next = sdp->next;
5071     if (sdp->state == STATE_OFF) {
5072       RemoveTermFromList (pFormInfo, sdp, FALSE, FALSE);
5073       FreeTerm (sdp);
5074     }
5075     sdp = next;
5076   }
5077 
5078   /* Adjust the display accordingly */
5079 
5080   AlphabetizeGroups (pFormInfo);
5081   RepopulateChosen (pFormInfo);
5082   RecalculateChosen (pFormInfo);
5083   ArrowCursor ();
5084 }
5085 
5086 /*==================================================================*/
5087 /*                                                                  */
5088 /*  SetupMenus () - Create and initialize the pulldown menus.       */
5089 /*                                                                  */
5090 /*==================================================================*/
5091 
SetupMenus(WindoW w,FormInfoPtr pFormInfo,Boolean explodeToggle,Boolean advancedQueryToggle)5092 static void SetupMenus (WindoW w, FormInfoPtr pFormInfo, Boolean explodeToggle, Boolean advancedQueryToggle)
5093 
5094 {
5095   IteM  clearUnusedItem;
5096   MenU  m;
5097   MenU  s;
5098 
5099   /*-----------*/
5100   /* File menu */
5101   /*-----------*/
5102 
5103   m = PulldownMenu (w, "File");
5104   CommandItem (m, "Import UID List.../I", ImportUIDs_Callback);
5105   CommandItem (m, "Export UID List.../E", ExportUIDs_Callback);
5106   SeparatorItem (m);
5107   CommandItem (m, "Quit/Q", Quit_Callback);
5108 
5109   /*-----------*/
5110   /* Edit menu */
5111   /*-----------*/
5112 
5113   m = PulldownMenu (w, "Edit");
5114   FormCommandItem (m, CUT_MENU_ITEM, (BaseFormPtr) pFormInfo, VIB_MSG_CUT);
5115   FormCommandItem (m, COPY_MENU_ITEM, (BaseFormPtr) pFormInfo, VIB_MSG_COPY);
5116   FormCommandItem (m, PASTE_MENU_ITEM, (BaseFormPtr) pFormInfo, VIB_MSG_PASTE);
5117   FormCommandItem (m, CLEAR_MENU_ITEM, (BaseFormPtr) pFormInfo, VIB_MSG_DELETE);
5118 
5119   /*--------------*/
5120   /* Options menu */
5121   /*--------------*/
5122 
5123   m = PulldownMenu (w, "Options");
5124 
5125   clearUnusedItem = CommandItem (m, "Clear Unused Query Terms", Query_ClearUnusedTerms);
5126   SetObjectExtra (clearUnusedItem, pFormInfo, NULL);
5127   pFormInfo->advancedQueryItem = StatusItem (m, "Advanced Queries", AdvancedQueryToggle_Callback);
5128   SetStatus (pFormInfo->advancedQueryItem, advancedQueryToggle);
5129   SetObjectExtra (pFormInfo->advancedQueryItem, pFormInfo, NULL);
5130 
5131   pFormInfo->explodeItem = StatusItem (m, "Explode Terms", ExplodeTermsToggle_Callback);
5132   SetStatus (pFormInfo->explodeItem, explodeToggle);
5133   SetObjectExtra (pFormInfo->explodeItem, pFormInfo, NULL);
5134 
5135   s = SubMenu (m, "Show ASN.1");
5136   s_showASNItem = ChoiceGroup (s, NULL);
5137   ChoiceItem (s_showASNItem, "OFF");
5138   ChoiceItem (s_showASNItem, "1");
5139   ChoiceItem (s_showASNItem, "2");
5140   ChoiceItem (s_showASNItem, "3");
5141   ChoiceItem (s_showASNItem, "4");
5142   ChoiceItem (s_showASNItem, "5");
5143   ChoiceItem (s_showASNItem, "6");
5144   ChoiceItem (s_showASNItem, "7");
5145   ChoiceItem (s_showASNItem, "8");
5146   ChoiceItem (s_showASNItem, "9");
5147   ChoiceItem (s_showASNItem, "ON");
5148   ChoiceItem (s_showASNItem, "LOG");
5149   SetValue (s_showASNItem, 1);
5150 
5151   /*------------*/
5152   /* Help menu */
5153   /*------------*/
5154 
5155   m = PulldownMenu (w, "Help");
5156   CommandItem (m, "Databases...", DatabaseView_Callback);
5157   CommandItem (m, "Fields...", FieldView_Callback);
5158   CommandItem (m, "Modes...", ModeView_Callback);
5159 }
5160 
5161 /*==================================================================*/
5162 /*                                                                  */
5163 /*  SetupAdvQueryGroup () - Create and initialize the Advanced      */
5164 /*                          Query Form.                             */
5165 /*                                                                  */
5166 /*==================================================================*/
5167 
SetupAdvQueryGroup(FormInfoPtr pFormInfo,GrouP mainGroup)5168 static GrouP SetupAdvQueryGroup (FormInfoPtr pFormInfo, GrouP mainGroup)
5169 
5170 {
5171   GrouP   advQueryGroup;
5172   GrouP   buttonGroup;
5173   GrouP   instructionGroup;
5174   Char    tempStr [256];
5175 
5176   advQueryGroup = HiddenGroup (mainGroup, -1, 0, NULL);
5177   SetGroupSpacing (advQueryGroup, 5, 5);
5178 
5179   /*----------------------------------*/
5180   /* Set up alternative boolean query */
5181   /* refinement text edit box.        */
5182   /*----------------------------------*/
5183 
5184   pFormInfo->advQueryText = ScrollText (advQueryGroup, ADV_TEXT_WIDTH, ADV_TEXT_HEIGHT, programFont, TRUE, AdvancedQueryText_Callback);
5185   SetObjectExtra (pFormInfo->advQueryText, pFormInfo, NULL);
5186 
5187   /*------------------------------------------*/
5188   /* Create a group for the Retrieve/Evaluate */
5189   /* combined button and the Reset button.    */
5190   /*------------------------------------------*/
5191 
5192   buttonGroup = HiddenGroup (advQueryGroup, 5, 0, NULL);
5193   SetGroupSpacing (buttonGroup, 10, 10);
5194 
5195   pFormInfo->advRetrieveButton = PushButton (buttonGroup, "Retrieve 000000000 Documents", EvaluateRetrieve_Callback);
5196   SetObjectExtra (pFormInfo->advRetrieveButton, pFormInfo, NULL);
5197   SetTitle (pFormInfo->advRetrieveButton, "Evaluate");
5198   Disable (pFormInfo->advRetrieveButton);
5199   pFormInfo->advQueryState = ADV_QUERY_INVALID_STATE;
5200 
5201   pFormInfo->advResetButton = PushButton (buttonGroup, "Reset", Reset_Callback);
5202   SetObjectExtra (pFormInfo->advResetButton, pFormInfo, NULL);
5203 
5204   /*----------------------------------------------*/
5205   /* Create instructions for using advanced query */
5206   /*----------------------------------------------*/
5207 
5208   instructionGroup = HiddenGroup (advQueryGroup, 1, 0, NULL);
5209   StaticPrompt (instructionGroup, "Operators:", 0, 0, programFont, 'l');
5210   StaticPrompt (instructionGroup, "", 0, 0, programFont, 'l');
5211   StaticPrompt (instructionGroup, "    & (and)", 0, 0, programFont, 'l');
5212   StaticPrompt (instructionGroup, "    | (or)", 0, 0, programFont, 'l');
5213   StaticPrompt (instructionGroup, "    - (butnot)", 0, 0, programFont, 'l');
5214   StaticPrompt (instructionGroup, "    : (range)", 0, 0, programFont, 'l');
5215   StaticPrompt (instructionGroup, "", 0, 0, programFont, 'l');
5216   StaticPrompt (instructionGroup, "Example:", 0, 0, programFont, 'l');
5217   StaticPrompt (instructionGroup, "", 0, 0, programFont, 'l');
5218   tempStr [0] = '\0';
5219   StringCat (tempStr, "    ((\"glucagon\" [WORD] | \"insulin\" ");
5220   StringCat (tempStr, "[MESH]) & (\"1995\" : \"1996\" [PDAT]))");
5221   StaticPrompt (instructionGroup, tempStr, 0, 0, programFont, 'l');
5222   StaticPrompt (instructionGroup, "", 0, 0, programFont, 'l');
5223   StaticPrompt (instructionGroup, "Use [*] to search all fields.", 0, 0, programFont, 'l');
5224 
5225   /*--------------------------------*/
5226   /* Return the newly created group */
5227   /*--------------------------------*/
5228 
5229   return advQueryGroup;
5230 }
5231 
5232 /*==================================================================*/
5233 /*                                                                  */
5234 /*  GetValueFromField () -                                          */
5235 /*                                                                  */
5236 /*==================================================================*/
5237 
GetValueFromField(DoC d,Int2 item,Int2 row,Int2 col)5238 static Int4 GetValueFromField (DoC d, Int2 item, Int2 row, Int2 col)
5239 
5240 {
5241   CharPtr  str;
5242   Int4     value;
5243 
5244   value = -1;
5245   str = GetDocText (d, item, row, col);
5246   if (str != NULL) {
5247     if (! StrToLong (str, &value)) {
5248       value = -1;
5249     }
5250   }
5251 
5252   MemFree (str);
5253   return value;
5254 }
5255 
5256 /*==================================================================*/
5257 /*                                                                  */
5258 /*  DrawAvailLeaf () -                                              */
5259 /*                                                                  */
5260 /*==================================================================*/
5261 
DrawAvailLeaf(DoC d,RectPtr r,Int2 item,Int2 frst)5262 static void DrawAvailLeaf (DoC d, RectPtr r, Int2 item, Int2 frst)
5263 
5264 {
5265   RecT  q;
5266   Int2  value;
5267 
5268   if (r == NULL || frst != 0) return;
5269 
5270   value = GetValueFromField (d, item, 1, 3);
5271   if (value != 1) return;
5272 
5273   q = *r;
5274   q.left++;
5275   q.right = q.left + 4;
5276   q.top += stdLineHeight / 2 - 2;
5277   q.bottom = q.top + 4;
5278   value = GetValueFromField (d, item, 1, 3);
5279   if (value == STATE_ON) {
5280     /*
5281        InvertColors ();
5282     */
5283     EraseRect (&q);
5284     PaintRect (&q);
5285     /*
5286        InvertColors ();
5287     */
5288   } else
5289     PaintRect (&q);
5290 }
5291 
5292 /*==================================================================*/
5293 /*                                                                  */
5294 /*  HighlightAvail () -                                             */
5295 /*                                                                  */
5296 /*==================================================================*/
5297 
HighlightAvail(DoC d,Int2 item,Int2 row,Int2 col)5298 static Boolean HighlightAvail (DoC d, Int2 item, Int2 row, Int2 col)
5299 
5300 {
5301   FormInfoPtr  pFormInfo;
5302 
5303   pFormInfo = (FormInfoPtr) GetObjectExtra (d);
5304 
5305   if (item == pFormInfo->availItem && row == pFormInfo->availRow) return TRUE;
5306 
5307   return FALSE;
5308 }
5309 
5310 /*==================================================================*/
5311 /*                                                                  */
5312 /*  ClickAvail () -                                                 */
5313 /*                                                                  */
5314 /*==================================================================*/
5315 
ClickAvail(DoC d,PoinT pt)5316 static void ClickAvail (DoC d, PoinT pt)
5317 
5318 {
5319   Int2         item;
5320   Int2         row;
5321   FormInfoPtr  pFormInfo;
5322 
5323   pFormInfo = (FormInfoPtr) GetObjectExtra (d);
5324 
5325   MapDocPoint (d, pt, &item, &row, NULL, NULL);
5326   pFormInfo->availClickItem = item;
5327   pFormInfo->availClickRow = row;
5328   pFormInfo->wasDoubleClick = dblClick;
5329 
5330   SafeEnable (pFormInfo->acceptButton);
5331 }
5332 
5333 /*==================================================================*/
5334 /*                                                                  */
5335 /*  ReleaseAvail () - This is called whenever the mouse button is   */
5336 /*                   realeased in the term selection window.        */
5337 /*                                                                  */
5338 /*==================================================================*/
5339 
ReleaseAvail(DoC d,PoinT pt)5340 static void ReleaseAvail (DoC d, PoinT pt)
5341 
5342 {
5343   Char         ch;
5344   Int2         item;
5345   Int2         olditem;
5346   Int2         oldrow;
5347   CharPtr      ptr;
5348   Int2         row;
5349   CharPtr      text;
5350   Int4         iTermCount;
5351   CharPtr      sTermCount;
5352   FormInfoPtr  pFormInfo;
5353 
5354   pFormInfo = (FormInfoPtr) GetObjectExtra (d);
5355 
5356   /*------------------------------------*/
5357   /* Convert the screen location of the */
5358   /* release into an item and a row.    */
5359   /*------------------------------------*/
5360 
5361   MapDocPoint (d, pt, &item, &row, NULL, NULL);
5362 
5363   /* ---------------------------------------- */
5364   /* There's no dragging in the avail window */
5365   /* ---------------------------------------- */
5366 
5367   if (pFormInfo->availClickItem != item || pFormInfo->availClickRow != row) return;
5368 
5369   text = GetDocText (pFormInfo->availDoc, item, row, 1);
5370   if (StringHasNoText (text)) {
5371     text = MemFree (text);
5372   }
5373 
5374   olditem = pFormInfo->availItem;
5375   oldrow = pFormInfo->availRow;
5376   if (text != NULL) {
5377     pFormInfo->availItem = item;
5378     pFormInfo->availRow = row;
5379   } else {
5380     pFormInfo->availItem = 0;
5381     pFormInfo->availRow = 0;
5382   }
5383   if (olditem > 0 && oldrow > 0)
5384     InvalDocRows (pFormInfo->availDoc, olditem, oldrow, oldrow);
5385   if (text != NULL && item > 0 && row > 0)
5386     InvalDocRows (pFormInfo->availDoc, item, row, row);
5387 
5388   if (text != NULL) {
5389     ptr = text;
5390     ch = *ptr;
5391     while (ch != '\0' && ch >= ' ') {
5392       ptr++;
5393       ch = *ptr;
5394     }
5395     *ptr = '\0';
5396     if (pFormInfo->currMode == RANGE_MODE) {
5397       if (CurrentText () == pFormInfo->fromText) {
5398         SafeSetTitle (pFormInfo->fromText, text);
5399         Select (pFormInfo->fromText);
5400       } else if (CurrentText () == pFormInfo->toText) {
5401         SafeSetTitle (pFormInfo->toText, text);
5402         Select (pFormInfo->toText);
5403       }
5404     } else {
5405       SafeSetTitle (pFormInfo->termText, text);
5406       Select (pFormInfo->termText);
5407     }
5408     Update ();
5409   } else {
5410     if (pFormInfo->currMode == RANGE_MODE) {
5411       SafeSetTitle (pFormInfo->fromText, "");
5412       SafeSetTitle (pFormInfo->toText, "");
5413       Select (pFormInfo->fromText);
5414     } else {
5415       SafeSetTitle (pFormInfo->termText, "");
5416       Select (pFormInfo->termText);
5417     }
5418     Update ();
5419   }
5420 
5421   if (text != NULL && pFormInfo->wasDoubleClick) {
5422     WatchCursor ();
5423     Update ();
5424 
5425     if ((pFormInfo->currMode == TAXONOMY_MODE) || (pFormInfo->currMode == MESH_TREE_MODE)) {
5426       Update ();
5427       ResetClip ();             /* clipped to panel, need to update popup */
5428       RepopulateTaxonomy (pFormInfo, text);
5429     } else if (pFormInfo->currMode == RANGE_MODE) {
5430       ResetClip ();
5431       sTermCount = GetDocText (pFormInfo->availDoc, pFormInfo->availItem,
5432                                pFormInfo->availRow, E2_COUNT_COL);
5433       TrimSpacesAroundString (sTermCount);
5434       iTermCount = atoi (sTermCount);
5435       MemFree (sTermCount);
5436       Query_AddBoolTerm (pFormInfo->form, pFormInfo->currDb,
5437                          pFormInfo->currField, text, STATE_ON, iTermCount);
5438       Update ();
5439       RecalculateChosen (pFormInfo);
5440     } else {
5441       ResetClip ();
5442       sTermCount = GetDocText (pFormInfo->availDoc, pFormInfo->availItem,
5443                                pFormInfo->availRow, E2_COUNT_COL);
5444       TrimSpacesAroundString (sTermCount);
5445       iTermCount = atoi (sTermCount);
5446       MemFree (sTermCount);
5447       Query_AddBoolTerm (pFormInfo->form, pFormInfo->currDb,
5448                          pFormInfo->currField, text, STATE_ON, iTermCount);
5449       Update ();
5450       RecalculateChosen (pFormInfo);
5451     }
5452 
5453     ArrowCursor ();
5454   }
5455   MemFree (text);
5456 }
5457 
5458 /*==================================================================*/
5459 /*                                                                  */
5460 /*  AvailTimerProc () -                                             */
5461 /*                                                                  */
5462 /*==================================================================*/
5463 
AvailTimerProc(WindoW w)5464 static void AvailTimerProc (WindoW w)
5465 
5466 {
5467   FormInfoPtr  pFormInfo;
5468 
5469   pFormInfo = (FormInfoPtr) GetObjectExtra (w);
5470   pFormInfo->okayToAccept = TRUE;
5471 }
5472 
5473 /*==================================================================*/
5474 /*                                                                  */
5475 /*  InitAvailPanel () - Set up the Term List Panel.                 */
5476 /*                                                                  */
5477 /*==================================================================*/
5478 
InitAvailPanel(FormInfoPtr pFormInfo)5479 static void InitAvailPanel (FormInfoPtr pFormInfo)
5480 
5481 {
5482   RecT  r;
5483 
5484   pFormInfo->availItem = 0;
5485   pFormInfo->availRow = 0;
5486   SetDocShade (pFormInfo->availDoc, DrawAvailLeaf, NULL, HighlightAvail, NULL);
5487   SetDocProcs (pFormInfo->availDoc, ClickAvail, NULL, ReleaseAvail, NULL);
5488   SetDocCache (pFormInfo->availDoc, NULL, NULL, NULL);
5489 
5490   ObjectRect (pFormInfo->availDoc, &r);
5491   InsetRect (&r, 4, 4);
5492   SelectFont (systemFont);
5493 
5494   availColFmt [1].pixWidth = StringWidth ("0000000") + 10;
5495   availColFmt [0].pixWidth = (r.right - r.left) - availColFmt [1].pixWidth;
5496   availColFmt [2].pixWidth = 0;
5497 
5498   SetDocAutoAdjust (pFormInfo->availDoc, FALSE);
5499 
5500   InvalDocument (pFormInfo->availDoc);
5501 }
5502 
5503 /*==================================================================*/
5504 /*                                                                  */
5505 /*  DrawChosenBrackets () - This is the draw callback for the       */
5506 /*                         Chosen document panel. It gets called    */
5507 /*                         every time the panel is drawn.           */
5508 /*                                                                  */
5509 /*==================================================================*/
5510 
DrawChosenBrackets(DoC d,RectPtr r,Int2 item,Int2 frst)5511 static void DrawChosenBrackets (DoC d, RectPtr r, Int2 item, Int2 frst)
5512 
5513 {
5514   FormInfoPtr   pFormInfo;
5515   RecT          s;
5516   StateDataPtr  sdp;
5517   static Uint1  andsign [] = { 0x30, 0x48, 0x50, 0x20, 0x50, 0x8A, 0x84, 0x8A, 0x71, 0x00 };
5518   static Uint1  notsign [] = { 0x00, 0x00, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00 };
5519 
5520   pFormInfo = (FormInfoPtr) GetObjectExtra (d);
5521 
5522   sdp = pFormInfo->termList;
5523   while (sdp != NULL && item > 1) {
5524     sdp = sdp->next;
5525     item--;
5526   }
5527   if (sdp == NULL) return;
5528 
5529   switch (sdp->group) {
5530     case GROUP_SINGLE:
5531       break;
5532     case GROUP_FIRST:
5533       MoveTo (r->left + 16 + 1, r->top + 1);
5534       LineTo (r->left + 16 + 3, r->top + 1);
5535       MoveTo (r->left + 16 + 1, r->top + 2);
5536       LineTo (r->left + 16 + 3, r->top + 2);
5537       MoveTo (r->left + 16 + 1, r->top + 1);
5538       LineTo (r->left + 16 + 1, r->bottom);
5539       break;
5540     case GROUP_MIDDLE:
5541       MoveTo (r->left + 16 + 1, r->top);
5542       LineTo (r->left + 16 + 1, r->bottom);
5543       break;
5544     case GROUP_LAST:
5545       MoveTo (r->left + 16 + 1, r->top);
5546       LineTo (r->left + 16 + 1, r->bottom - 1);
5547       MoveTo (r->left + 16 + 1, r->bottom - 2);
5548       LineTo (r->left + 16 + 3, r->bottom - 2);
5549       MoveTo (r->left + 16 + 1, r->bottom - 1);
5550       LineTo (r->left + 16 + 3, r->bottom - 1);
5551       break;
5552     default:
5553       break;
5554   }
5555 
5556   switch (sdp->above) {
5557     case ENTREZ_OP_NONE:
5558       break;
5559     case ENTREZ_OP_AND:
5560       LoadRect (&s, r->left + 6, r->top, r->left + 14, r->top + 5);
5561       CopyBits (&s, andsign + 5);
5562       break;
5563     case ENTREZ_OP_BUTNOT:
5564       LoadRect (&s, r->left, r->top, r->left + 8, r->top + 5);
5565       CopyBits (&s, notsign + 5);
5566       break;
5567     default:
5568       break;
5569   }
5570 
5571   switch (sdp->below) {
5572     case ENTREZ_OP_NONE:
5573       break;
5574     case ENTREZ_OP_AND:
5575       LoadRect (&s, r->left + 6, r->bottom - 5, r->left + 14, r->bottom);
5576       CopyBits (&s, andsign);
5577       break;
5578     case ENTREZ_OP_BUTNOT:
5579       LoadRect (&s, r->left, r->bottom - 5, r->left + 8, r->bottom);
5580       CopyBits (&s, notsign);
5581       break;
5582     default:
5583       break;
5584   }
5585 }
5586 
5587 /*==================================================================*/
5588 /*                                                                  */
5589 /*  HighlightChosen () -                                            */
5590 /*                                                                  */
5591 /*==================================================================*/
5592 
HighlightChosen(DoC d,Int2 item,Int2 row,Int2 col)5593 static Boolean HighlightChosen (DoC d, Int2 item, Int2 row, Int2 col)
5594 
5595 {
5596   StateDataPtr  sdp;
5597   FormInfoPtr   pFormInfo;
5598 
5599   pFormInfo = (FormInfoPtr) GetObjectExtra (d);
5600 
5601   if (col == 1 || col == 2) {
5602     if (pFormInfo->chosenInAboveBox || pFormInfo->chosenInBelowBox) return FALSE;
5603     /* if (item == pFormInfo->chosenItem) return TRUE; */
5604     return FALSE;
5605   } else if (col == 3) {
5606     sdp = pFormInfo->termList;
5607     while (sdp != NULL && item > 1) {
5608       sdp = sdp->next;
5609       item--;
5610     }
5611     if (sdp == NULL) return FALSE;
5612     return (Boolean) (sdp->state == STATE_ON);
5613   } else
5614     return FALSE;
5615 }
5616 
5617 /*==================================================================*/
5618 /*                                                                  */
5619 /*  FrameChosen () -                                                */
5620 /*                                                                  */
5621 /*==================================================================*/
5622 
FrameChosen(FormInfoPtr pFormInfo)5623 static void FrameChosen (FormInfoPtr pFormInfo)
5624 
5625 {
5626   RecT  sr;
5627 
5628   ObjectRect (pFormInfo->chosenDoc, &sr);
5629   InsetRect (&sr, 4, 4);
5630 
5631   if (RectInRect (&(pFormInfo->trackRect), &sr)) {
5632     Dotted ();
5633     FrameRect (&(pFormInfo->trackRect));
5634   }
5635 }
5636 
5637 /*==================================================================*/
5638 /*                                                                  */
5639 /*  ClickChosen () -                                                */
5640 /*                                                                  */
5641 /*==================================================================*/
5642 
ClickChosen(DoC d,PoinT pt)5643 static void ClickChosen (DoC d, PoinT pt)
5644 
5645 {
5646   Int2         col;
5647   Int2         item;
5648   RecT         r;
5649   Int2         row;
5650   RecT         s;
5651   FormInfoPtr  pFormInfo;
5652 
5653   pFormInfo = (FormInfoPtr) GetObjectExtra (d);
5654 
5655   MapDocPoint (d, pt, &item, &row, &col, &r);
5656   if (item > 0 && row == 0 && col > 0)
5657     row = 1;
5658 
5659   pFormInfo->chosenClickItem = item;
5660   pFormInfo->chosenClickRow = row;
5661   pFormInfo->chosenClickCol = col;
5662   pFormInfo->wasDoubleClick = dblClick;
5663   pFormInfo->chosenInAboveBox = FALSE;
5664   pFormInfo->chosenInBelowBox = FALSE;
5665 
5666   if ((col == 1 || col == 2) && (item > 0) && (item <= pFormInfo->chosenNumLines) && (row > 0)) {
5667     pFormInfo->chosenItem = item;
5668     LoadRect (&s, r.left, r.top, r.left + 16, r.top + 5);
5669     if (PtInRect (pt, &s))
5670       pFormInfo->chosenInAboveBox = TRUE;
5671     LoadRect (&s, r.left, r.bottom - 5, r.left + 16, r.bottom);
5672     if (PtInRect (pt, &s))
5673       pFormInfo->chosenInBelowBox = TRUE;
5674     if (pFormInfo->chosenInAboveBox || pFormInfo->chosenInBelowBox)
5675       return;
5676     InvalDocCols (pFormInfo->chosenDoc, item, 1, 2);
5677     Update ();
5678     r.right = r.left + chosenColFmt [0].pixWidth + chosenColFmt [1].pixWidth;
5679     LoadRect (&(pFormInfo->trackRect), r.left + 22, r.top, r.right - 2, r.bottom);
5680     pFormInfo->trackPt = pt;
5681     InvertMode ();
5682     FrameChosen (pFormInfo);
5683   } else
5684     pFormInfo->chosenItem = 0;
5685 }
5686 
5687 /*==================================================================*/
5688 /*                                                                  */
5689 /*  DragChosen () -                                                 */
5690 /*                                                                  */
5691 /*==================================================================*/
5692 
DragChosen(DoC d,PoinT pt)5693 static void DragChosen (DoC d, PoinT pt)
5694 
5695 {
5696   Int4         off;
5697   BaR          sb;
5698   RecT         sr;
5699   FormInfoPtr  pFormInfo;
5700 
5701   pFormInfo = (FormInfoPtr) GetObjectExtra (d);
5702 
5703   if (pFormInfo->chosenItem == 0) return;
5704   if (pFormInfo->chosenInAboveBox || pFormInfo->chosenInBelowBox) return;
5705   InvertMode ();
5706   FrameChosen (pFormInfo);
5707   Update ();
5708   ObjectRect (pFormInfo->chosenDoc, &sr);
5709   InsetRect (&sr, 4, 4);
5710   if (PtInRect (pt, &sr)) {
5711     OffsetRect (&(pFormInfo->trackRect), 0, pt.y - pFormInfo->trackPt.y);
5712     pFormInfo->trackPt = pt;
5713   }
5714   sb = GetSlateVScrollBar ((SlatE) pFormInfo->chosenDoc);
5715   off = GetBarValue (sb);
5716   ResetClip ();
5717   if (pt.y < sr.top)
5718     SetBarValue (sb, off - 1);
5719   else if (pt.y > sr.bottom)
5720     SetBarValue (sb, off + 1);
5721   Update ();
5722   InvertMode ();
5723   FrameChosen (pFormInfo);
5724   Update ();
5725 }
5726 
5727 /*==================================================================*/
5728 /*                                                                  */
5729 /*  FlipOperatorBelow () -                                          */
5730 /*                                                                  */
5731 /*==================================================================*/
5732 
FlipOperatorBelow(FormInfoPtr pFormInfo,Int2 item)5733 static void FlipOperatorBelow (FormInfoPtr pFormInfo, Int2 item)
5734 
5735 {
5736   StateDataPtr  next;
5737   RecT          r;
5738   StateDataPtr  sdp;
5739 
5740   sdp = pFormInfo->termList;
5741   while (item > 1 && sdp != NULL) {
5742     item--;
5743     sdp = sdp->next;
5744   }
5745   if (sdp != NULL) {
5746     next = sdp->next;
5747     if (next != NULL) {
5748       if (sdp->below != next->above)
5749         Beep ();
5750       if (sdp->below == ENTREZ_OP_AND) {
5751         sdp->below = ENTREZ_OP_BUTNOT;
5752         next->above = ENTREZ_OP_BUTNOT;
5753       } else if (sdp->below == ENTREZ_OP_BUTNOT) {
5754         sdp->below = ENTREZ_OP_AND;
5755         next->above = ENTREZ_OP_AND;
5756       }
5757       ObjectRect (pFormInfo->chosenDoc, &r);
5758       InsetRect (&r, 4, 4);
5759       r.right = r.left + 16;
5760       Select (pFormInfo->chosenDoc);
5761       InvalRect (&r);
5762       ResetClip ();
5763       WatchCursor ();
5764       Update ();
5765       RecalculateChosen (pFormInfo);
5766       ArrowCursor ();
5767     }
5768   }
5769 }
5770 
5771 /*==================================================================*/
5772 /*                                                                  */
5773 /*  RemoveTermFromList () - Removes the given term from the given   */
5774 /*                           doubly-linked list of terms, and       */
5775 /*                           adjusts the surrounding terms          */
5776 /*                           accordingly.                           */
5777 /*                                                                  */
5778 /*==================================================================*/
5779 
RemoveTermFromList(FormInfoPtr pFormInfo,StateDataPtr sdp,Boolean goingDown,Boolean lastDraggedDown)5780 static Boolean RemoveTermFromList (FormInfoPtr pFormInfo, StateDataPtr sdp, Boolean goingDown, Boolean lastDraggedDown)
5781 
5782 {
5783   StateDataPtr  prev;
5784   StateDataPtr  next;
5785   Int2          op;
5786 
5787   /*-----------------------------*/
5788   /* Sanity check - can't remove */
5789   /* term from an empty list.    */
5790   /*-----------------------------*/
5791 
5792   if (sdp == NULL) return E2_LIST_NOT_MODIFIED;
5793 
5794   /*------------------------------------*/
5795   /* Detach term from surrounding terms */
5796   /*------------------------------------*/
5797 
5798   next = sdp->next;
5799   prev = sdp->prev;
5800   switch (sdp->group) {
5801     case GROUP_SINGLE:
5802       if (lastDraggedDown)
5803         return E2_LIST_NOT_MODIFIED;
5804       break;
5805     case GROUP_FIRST:
5806       if (next != NULL) {
5807         if (next->group == GROUP_MIDDLE)
5808           next->group = GROUP_FIRST;
5809         else if (next->group == GROUP_LAST)
5810           next->group = GROUP_SINGLE;
5811       }
5812       break;
5813     case GROUP_MIDDLE:
5814       break;
5815     case GROUP_LAST:
5816       if (prev != NULL) {
5817         if (prev->group == GROUP_MIDDLE)
5818           prev->group = GROUP_LAST;
5819         else if (prev->group == GROUP_FIRST)
5820           prev->group = GROUP_SINGLE;
5821       }
5822       break;
5823     default:
5824       break;
5825   }
5826 
5827   /*-------------------------*/
5828   /* Adjust the state of the */
5829   /* surrounding terms.      */
5830   /*-------------------------*/
5831 
5832   sdp->prev = NULL;
5833   sdp->next = NULL;
5834   if (prev != NULL)
5835     prev->next = next;
5836   if (next != NULL)
5837     next->prev = prev;
5838   if (prev == NULL)
5839     pFormInfo->termList = next;
5840   op = ENTREZ_OP_NONE;
5841   switch (sdp->group) {
5842     case GROUP_SINGLE:
5843       if (goingDown) {
5844         if (prev != NULL)
5845           op = prev->below;
5846       } else {
5847         if (next != NULL)
5848           op = next->above;
5849       }
5850       if (prev != NULL)
5851         prev->below = op;
5852       if (next != NULL)
5853         next->above = op;
5854       break;
5855     case GROUP_FIRST:
5856       if (prev != NULL)
5857         op = prev->below;
5858       if (next != NULL)
5859         next->above = op;
5860       break;
5861     case GROUP_MIDDLE:
5862       break;
5863     case GROUP_LAST:
5864       if (next != NULL)
5865         op = next->above;
5866       if (prev != NULL)
5867         prev->below = op;
5868       break;
5869     default:
5870       break;
5871   }
5872 
5873   /*---------------------*/
5874   /* Return successfully */
5875   /*---------------------*/
5876 
5877   return E2_LIST_MODIFIED;
5878 }
5879 
5880 /*====================================================================*/
5881 /*                                                                    */
5882 /*  AddTermToList () - Adds a given term to the given doubly-linked   */
5883 /*                      list of terms, and adjusts the surrounding    */
5884 /*                      terms accordingly.                            */
5885 /*                                                                    */
5886 /*====================================================================*/
5887 
AddTermToList(FormInfoPtr pFormInfo,StateDataPtr newTerm,Int2 item,Boolean merge)5888 static void AddTermToList (FormInfoPtr pFormInfo, StateDataPtr newTerm, Int2 item, Boolean merge)
5889 
5890 {
5891   StateDataPtr  prev;
5892   StateDataPtr  next;
5893   StateDataPtr  currTerm;
5894   Int2          op;
5895 
5896   /*-------------------------------------*/
5897   /* Add the new term into the term list */
5898   /*-------------------------------------*/
5899 
5900   currTerm = pFormInfo->termList;
5901   if (currTerm == NULL)
5902     pFormInfo->termList = newTerm;
5903   else {
5904     while (item > 1 && currTerm->next != NULL) {
5905       item--;
5906       currTerm = currTerm->next;
5907     }
5908     next = currTerm->next;
5909     prev = currTerm->prev;
5910     currTerm->next = newTerm;
5911     newTerm->next = next;
5912     newTerm->prev = currTerm;
5913     if (next != NULL)
5914       next->prev = newTerm;
5915     op = ENTREZ_OP_NONE;
5916     if (prev != NULL)
5917       op = prev->below;
5918     currTerm->above = op;
5919     newTerm->below = currTerm->below;
5920     currTerm->below = ENTREZ_OP_NONE;
5921     newTerm->above = ENTREZ_OP_NONE;
5922   }
5923 
5924   /*----------------------------------*/
5925   /* Do adding to group, if necessary */
5926   /*----------------------------------*/
5927 
5928   newTerm->group = GROUP_SINGLE;
5929   if (merge && currTerm != NULL) {
5930     switch (currTerm->group) {
5931       case GROUP_SINGLE:
5932         currTerm->group = GROUP_FIRST;
5933         newTerm->group = GROUP_LAST;
5934         break;
5935       case GROUP_FIRST:
5936         newTerm->group = GROUP_MIDDLE;
5937         break;
5938       case GROUP_MIDDLE:
5939         newTerm->group = GROUP_MIDDLE;
5940         break;
5941       case GROUP_LAST:
5942         currTerm->group = GROUP_MIDDLE;
5943         newTerm->group = GROUP_LAST;
5944         break;
5945       default:
5946         break;
5947     }
5948   }
5949 
5950   /*-----------------------------------------*/
5951   /* If it's not in a group, then by default */
5952   /* it's AND'd with the neighboring terms.  */
5953   /*-----------------------------------------*/
5954 
5955   else {
5956     prev = newTerm->prev;
5957     if (prev != NULL) {
5958       prev->below = ENTREZ_OP_AND;
5959       newTerm->above = ENTREZ_OP_AND;
5960     }
5961   }
5962 }
5963 
5964 /*==================================================================*/
5965 /*                                                                  */
5966 /*  ReleaseChosen () - This is the callback function that gets      */
5967 /*                    when the mouse button is released after       */
5968 /*                    dragging a term in the Query Refinement       */
5969 /*                    panel.                                        */
5970 /*                                                                  */
5971 /*==================================================================*/
5972 
ReleaseChosen(DoC d,PoinT pt)5973 static void ReleaseChosen (DoC d, PoinT pt)
5974 
5975 {
5976   Int2          col;
5977   Boolean       goingDown;
5978   Int2          inval;
5979   Int2          item;
5980   Boolean       lastDraggedDown;
5981   Boolean       merge;
5982   Int2          oldItem;
5983   RecT          r;
5984   Int2          row;
5985   RecT          s;
5986   StateDataPtr  sdp;
5987   RecT          sr;
5988   FormInfoPtr   pFormInfo;
5989 
5990   pFormInfo = (FormInfoPtr) GetObjectExtra (d);
5991 
5992   /*---------------------------------------*/
5993   /* Map the current cursor position to an */
5994   /* item in the Query Refinement panel.   */
5995   /*---------------------------------------*/
5996 
5997   MapDocPoint (d, pt, &item, &row, &col, &r);
5998   if (item > 0 && row == 0 && col > 0)
5999     row = 1;
6000 
6001   /*-------------*/
6002   /*-------------*/
6003 
6004   if (pFormInfo->chosenInAboveBox || pFormInfo->chosenInBelowBox) {
6005     LoadRect (&s, r.left, r.top, r.left + 16, r.top + 5);
6006     if (PtInRect (pt, &s)) {
6007       if ((pFormInfo->chosenInAboveBox) && (item == pFormInfo->chosenItem))
6008         FlipOperatorBelow (pFormInfo, pFormInfo->chosenItem - 1);
6009       else if ((pFormInfo->chosenInBelowBox) && (item == pFormInfo->chosenItem - 1))
6010         FlipOperatorBelow (pFormInfo, pFormInfo->chosenItem - 1);
6011     }
6012     LoadRect (&s, r.left, r.bottom - 5, r.left + 16, r.bottom);
6013     if (PtInRect (pt, &s)) {
6014       if ((pFormInfo->chosenInBelowBox) && (item == pFormInfo->chosenItem))
6015         FlipOperatorBelow (pFormInfo, pFormInfo->chosenItem);
6016       else if ((pFormInfo->chosenInAboveBox) && (item == pFormInfo->chosenItem + 1))
6017         FlipOperatorBelow (pFormInfo, pFormInfo->chosenItem);
6018     }
6019     return;
6020   }
6021 
6022   /*-----------------------*/
6023   /*-----------------------*/
6024 
6025   if (pFormInfo->chosenItem > 0) {
6026 
6027     oldItem = pFormInfo->chosenItem;
6028     pFormInfo->chosenItem = 0;
6029     InvertMode ();
6030     FrameChosen (pFormInfo);
6031     Update ();
6032     InvalDocCols (pFormInfo->chosenDoc, oldItem, 1, 2);
6033     Update ();
6034     if (item == oldItem) return;
6035     if (pFormInfo->chosenNumLines < 2) return;
6036 
6037       /*-----------------------------------------------*/
6038     /* Are we dragging the last item 'past' the end? */
6039       /*-----------------------------------------------*/
6040 
6041     lastDraggedDown = FALSE;
6042     if (oldItem == pFormInfo->chosenNumLines && item > pFormInfo->chosenNumLines)
6043       lastDraggedDown = TRUE;
6044 
6045       /*-----------*/
6046       /*-----------*/
6047 
6048     merge = TRUE;
6049     ObjectRect (pFormInfo->chosenDoc, &sr);
6050     InsetRect (&sr, 4, 4);
6051     /*
6052        if (item > pFormInfo->chosenNumLines && PtInRect (pt, &sr))
6053     */
6054     if (item == 0 && PtInRect (pt, &sr)) {
6055       merge = FALSE;
6056       item = INT2_MAX;
6057     }
6058 
6059       /*-------*/
6060       /*-------*/
6061 
6062     if ((item <= 0) || (pFormInfo->termList == NULL))
6063       return;
6064 
6065       /*--------------------------------------*/
6066     /* Are we moving an item down the list? */
6067       /*--------------------------------------*/
6068 
6069     goingDown = FALSE;
6070     if (item > oldItem) {
6071       item--;
6072       goingDown = TRUE;
6073     }
6074 
6075       /*--------------------------------*/
6076     /* Find the item being dragged in */
6077     /* the state list.                */
6078       /*--------------------------------*/
6079 
6080     sdp = pFormInfo->termList;
6081     while (oldItem > 1 && sdp != NULL) {
6082       oldItem--;
6083       sdp = sdp->next;
6084     }
6085 
6086     /*----------------------------------------*/
6087     /* Remove the term from the term list and */
6088     /* then re-add it in it's new position.   */
6089     /*----------------------------------------*/
6090 
6091     if (RemoveTermFromList (pFormInfo, sdp, goingDown, lastDraggedDown) ==
6092         E2_LIST_NOT_MODIFIED) return;
6093 
6094     AddTermToList (pFormInfo, sdp, item, merge);
6095 
6096     /*---------------------------*/
6097     /* Recalculate the new query */
6098     /* and redisplay it.         */
6099     /*---------------------------*/
6100 
6101     ResetClip ();
6102     WatchCursor ();
6103     Update ();
6104     AlphabetizeGroups (pFormInfo);
6105     RepopulateChosen (pFormInfo);
6106     RecalculateChosen (pFormInfo);
6107     ArrowCursor ();
6108   }
6109 
6110   /*------------------------------------*/
6111   /* If the count column was clicked on */
6112   /* then toggle rows state on or off.  */
6113   /*------------------------------------*/
6114 
6115   if ((pFormInfo->chosenClickItem == item) &&
6116       (pFormInfo->chosenClickRow == row)   &&
6117       (pFormInfo->chosenClickCol == col)   &&
6118       (col == 3)) {
6119     inval = item;
6120     sdp = pFormInfo->termList;
6121     while (sdp != NULL && item > 1) {
6122       sdp = sdp->next;
6123       item--;
6124     }
6125     if (sdp == NULL) return;
6126     switch (sdp->state) {
6127       case STATE_OFF:
6128         sdp->state = STATE_ON;
6129         break;
6130       case STATE_ON:
6131         sdp->state = STATE_OFF;
6132         break;
6133       default:
6134         sdp->state = STATE_OFF;
6135         break;
6136     }
6137     ResetClip ();
6138     WatchCursor ();
6139     InvalDocCols (pFormInfo->chosenDoc, inval, 3, 3);
6140     Update ();
6141     RecalculateChosen (pFormInfo);
6142     ArrowCursor ();
6143   }
6144 }
6145 
6146 /*==================================================================*/
6147 /*                                                                  */
6148 /*  InitChosenPanel () -                                            */
6149 /*                                                                  */
6150 /*==================================================================*/
6151 
InitChosenPanel(FormInfoPtr pFormInfo)6152 static void InitChosenPanel (FormInfoPtr pFormInfo)
6153 
6154 {
6155   Entrez2InfoPtr       e2ip;
6156   Entrez2DbInfoPtr     e2db;
6157   Entrez2FieldInfoPtr  e2fd;
6158   Int2                 maxWidth = 0;
6159   RecT                 r;
6160   Char                 str [32];
6161 
6162   SetDocProcs (pFormInfo->chosenDoc, ClickChosen, DragChosen, ReleaseChosen, NULL);
6163   SetDocShade (pFormInfo->chosenDoc, DrawChosenBrackets, NULL, HighlightChosen, NULL);
6164   pFormInfo->chosenNumLines = 0;
6165 
6166   ObjectRect (pFormInfo->chosenDoc, &r);
6167   InsetRect (&r, 4, 4);
6168 
6169   SelectFont (systemFont);
6170   chosenColFmt [2].pixWidth = StringWidth ("0000000") + 10;
6171   chosenColFmt [1].pixWidth = StringWidth ("0000000")  + 10;
6172 
6173   /* more accurate calculation of chosenColFmt [1].pixWidth */
6174 
6175   e2ip = Query_GetInfo ();
6176   if (e2ip != NULL) {
6177     for (e2db = e2ip->db_info; e2db != NULL; e2db = e2db->next) {
6178       for (e2fd = e2db->fields; e2fd != NULL; e2fd = e2fd->next) {
6179         if (e2fd->field_name == NULL || StringLen (e2fd->field_name) > 20) continue;
6180         sprintf (str, " [%s]", e2fd->field_name);
6181         maxWidth = MAX (maxWidth, StringWidth (str));
6182       }
6183     }
6184     chosenColFmt [1].pixWidth = maxWidth  + 10;
6185   }
6186 
6187   chosenColFmt [0].pixWidth = (r.right - r.left) - chosenColFmt [1].pixWidth - chosenColFmt [2].pixWidth;
6188   SetDocAutoAdjust (pFormInfo->chosenDoc, FALSE);
6189 
6190   InvalDocument (pFormInfo->chosenDoc);
6191 }
6192 
6193 /*==================================================================*/
6194 /*                                                                  */
6195 /*  SetupStdQueryGroup () - Create and initialize the Standard      */
6196 /*                          Query Form.                             */
6197 /*                                                                  */
6198 /*==================================================================*/
6199 
SetupStdQueryGroup(FormInfoPtr pFormInfo,GrouP mainGroup)6200 static GrouP SetupStdQueryGroup (FormInfoPtr pFormInfo, GrouP mainGroup)
6201 
6202 {
6203   Entrez2DbInfoPtr   e2db;
6204   Entrez2InfoPtr     e2ip;
6205   GrouP              stdQueryGroup;
6206   GrouP              enumlistGroup;
6207   EnumFieldAssocPtr  alist;
6208   Int2               idx;
6209   Int2               db;
6210   Int2               wid;
6211   GrouP              c;
6212   GrouP              j;
6213   GrouP              q1;
6214   GrouP              q2;
6215   GrouP              q3;
6216   PrompT             ppt1;
6217   PrompT             ppt2;
6218   ModeChoice         mc;
6219   ModeIndex          md;
6220   RecT               r;
6221 
6222   /*---------------------------------*/
6223   /* Get info about the DB server(s) */
6224   /*---------------------------------*/
6225 
6226   e2ip = Query_GetInfo ();
6227   if (e2ip == NULL) return NULL;
6228 
6229   /*---------------------------------*/
6230   /* Create the Standard Query Group */
6231   /*---------------------------------*/
6232 
6233   stdQueryGroup = HiddenGroup (mainGroup, -1, 0, NULL);
6234   SetGroupSpacing (stdQueryGroup, 5, 5);
6235 
6236   /*---------------------------------*/
6237   /* Create a group for the pulldown */
6238   /* lists and the accept button.    */
6239   /*---------------------------------*/
6240 
6241   enumlistGroup = HiddenGroup (stdQueryGroup, 0, 2, NULL);
6242   SetGroupSpacing (enumlistGroup, 15, 2);
6243 
6244   /*-------------------------------*/
6245   /* Set up database pulldown list */
6246   /*-------------------------------*/
6247 
6248   StaticPrompt (enumlistGroup, "Database:", 0, 0, programFont, 'l');
6249   q1 = HiddenGroup (enumlistGroup, 0, 0, NULL);
6250   alist = CreateDatabaseAlist (e2ip);
6251   idx = DBGetIDFromName ("PubMed");
6252 
6253   pFormInfo->databasePopup = CreateEnumPopupDialog (q1, TRUE, ChangeDatabase_Callback, alist, (UIEnum) idx, NULL);
6254   SetObjectExtra (pFormInfo->databasePopup, pFormInfo, NULL);
6255   FreeEnumFieldAlist (alist);
6256   pFormInfo->currDb = idx;
6257 
6258   /*-------------------------------*/
6259   /* Set up field pulldown list(s) */
6260   /*-------------------------------*/
6261 
6262   StaticPrompt (enumlistGroup, "Field:", 0, 0, programFont, 'l');
6263   q2 = HiddenGroup (enumlistGroup, 0, 0, NULL);
6264   pFormInfo->fieldsPopup = MemNew (sizeof (PopuP) * (e2ip->db_count + 2));
6265   idx = FieldGetIDFromName (pFormInfo->currDb, "ALL");
6266   for (e2db = e2ip->db_info; e2db != NULL; e2db = e2db->next) {
6267     db = DBGetIDFromName (e2db->db_name);
6268     alist = CreateFieldAlist (e2db);
6269     pFormInfo->fieldsPopup [db] = CreateEnumPopupDialog (q2, TRUE, ChangeField_Callback, alist, (UIEnum) idx, pFormInfo);
6270     FreeEnumFieldAlist (alist);
6271     Hide (pFormInfo->fieldsPopup [db]);
6272   }
6273   pFormInfo->currField = idx;
6274   db = DBGetIDFromName ("PubMed");
6275   Show (pFormInfo->fieldsPopup [db]);
6276 
6277   /*---------------------------*/
6278   /* Set up mode pulldown list */
6279   /*---------------------------*/
6280 
6281   StaticPrompt (enumlistGroup, "Mode:", 0, 0, programFont, 'l');
6282   q3 = HiddenGroup (enumlistGroup, 0, 0, NULL);
6283   for (md = POPUP_MULT; md <= POPUP_UID; md++) {
6284     alist = mode_alists [md];
6285     mc = SELECTION_MODE;
6286     if (md == POPUP_MULT)
6287       mc = AUTOMATIC_MODE;
6288     else if (md == POPUP_AUTO)
6289       mc = TRANSLATE_MODE;
6290     else if (md == POPUP_UID)
6291       mc = LOOKUP_UID_MODE;
6292     pFormInfo->modesPopup [md] = CreateEnumPopupDialog (q3, TRUE, ChangeMode_Callback, alist, (UIEnum) mc, pFormInfo);
6293     Hide (pFormInfo->modesPopup [md]);
6294   }
6295   pFormInfo->currMode = AUTOMATIC_MODE;
6296   md = POPUP_MULT;
6297   Show (pFormInfo->modesPopup [md]);
6298 
6299   /*----------------------*/
6300   /* Set up accept button */
6301   /*----------------------*/
6302 
6303   StaticPrompt (enumlistGroup, "", 0, 0, programFont, 'l');
6304   pFormInfo->acceptButton = DefaultButton (enumlistGroup, "Accept", Accept_Callback);
6305   SetObjectExtra (pFormInfo->acceptButton, pFormInfo, NULL);
6306   Disable (pFormInfo->acceptButton);
6307 
6308   AlignObjects (ALIGN_MIDDLE, (HANDLE) q1, (HANDLE) q2, (HANDLE) q3, (HANDLE) pFormInfo->acceptButton, NULL);
6309 
6310   /*------------------------------*/
6311   /* Create a group to contain:   */
6312   /*                              */
6313   /*    Term entry                */
6314   /*    From/To Range entry       */
6315   /*    Taxonomy 'Lineage' popup  */
6316   /*                              */
6317   /* These are mutually exclusive */
6318   /* and only one of these will   */
6319   /* be visible at a time.        */
6320   /*------------------------------*/
6321 
6322   c = HiddenGroup (stdQueryGroup, 0, 0, NULL);
6323 
6324   GetPosition (pFormInfo->acceptButton, &r);
6325   SelectFont (programFont);
6326   wid = r.right - (StringWidth ("From:") + StringWidth ("To:")) - 30;
6327   SelectFont (systemFont);
6328   wid /= 2 * stdCharWidth;
6329 
6330   pFormInfo->termGroup = HiddenGroup (c, 2, 0, NULL);
6331   StaticPrompt (pFormInfo->termGroup, "Term:", 0, dialogTextHeight, programFont, 'l');
6332   pFormInfo->termText = DialogText (pFormInfo->termGroup, "", 20, TextAction);
6333   SetObjectExtra (pFormInfo->termText, pFormInfo, NULL);
6334 
6335   pFormInfo->rangeGroup = HiddenGroup (c, 4, 0, NULL);
6336   StaticPrompt (pFormInfo->rangeGroup, "From:", 0, dialogTextHeight, programFont, 'l');
6337   pFormInfo->fromText = DialogText (pFormInfo->rangeGroup, "", wid, FromTextAction);
6338   pFormInfo->isValidFrom = FALSE;
6339   SetObjectExtra (pFormInfo->fromText, pFormInfo, NULL);
6340 
6341   StaticPrompt (pFormInfo->rangeGroup, "To:", 0, dialogTextHeight, programFont, 'l');
6342   pFormInfo->toText = DialogText (pFormInfo->rangeGroup, "", wid, ToTextAction);
6343   pFormInfo->isValidTo = FALSE;
6344   SetObjectExtra (pFormInfo->toText, pFormInfo, NULL);
6345   Hide (pFormInfo->rangeGroup);
6346 
6347   pFormInfo->taxLineagePopup = PopupList (c, TRUE, ChangeTaxParents_Callback);
6348   Hide (pFormInfo->taxLineagePopup);
6349   SetObjectExtra (pFormInfo->taxLineagePopup, pFormInfo, NULL);
6350   pFormInfo->taxStrings = NULL;
6351 
6352   /*------------------------------------*/
6353   /* Create the Avail and Chosen panels */
6354   /*------------------------------------*/
6355 
6356   c = HiddenGroup (stdQueryGroup, -1, 0, NULL);
6357   ppt1 = StaticPrompt (c, "Term Selection", 0, 0, programFont, 'c');
6358   pFormInfo->availDoc = DocumentPanel (c, 10 * stdCharWidth, 7 * stdLineHeight);
6359   SetObjectExtra (pFormInfo->availDoc, pFormInfo, NULL);
6360 
6361   ppt2 = StaticPrompt (c, "Query Refinement", 0, 0, programFont, 'c');
6362   j = HiddenGroup (c, 0, 0, NULL);
6363   pFormInfo->chosenDoc = DocumentPanel (j, 10 * stdCharWidth, 7 * stdLineHeight);
6364   SetObjectExtra (pFormInfo->chosenDoc, pFormInfo, NULL);
6365 
6366   /*-------------------*/
6367   /* Align the objects */
6368   /*-------------------*/
6369 
6370   AlignObjects (ALIGN_CENTER, (HANDLE) pFormInfo->taxLineagePopup, (HANDLE) pFormInfo->termGroup, NULL);
6371   AlignObjects (ALIGN_MIDDLE, (HANDLE) pFormInfo->taxLineagePopup, (HANDLE) pFormInfo->termGroup, (HANDLE) pFormInfo->rangeGroup, NULL);
6372   AlignObjects (ALIGN_RIGHT,
6373                 (HANDLE) pFormInfo->acceptButton,
6374                 (HANDLE) pFormInfo->termText,
6375                 (HANDLE) pFormInfo->availDoc, (HANDLE) pFormInfo->chosenDoc, (HANDLE) pFormInfo->toText, (HANDLE) ppt1, (HANDLE) ppt2, NULL);
6376 
6377   /*---------------------------------*/
6378   /* Create a group for the Retrieve */
6379   /* and Reset buttons.              */
6380   /*---------------------------------*/
6381 
6382   c = HiddenGroup (stdQueryGroup, 5, 0, NULL);
6383   SetGroupSpacing (c, 10, 10);
6384 
6385   pFormInfo->retrieveButton = PushButton (c, "Retrieve 000000000 Documents", pFormInfo->retrieveDocsProc);
6386   SetObjectExtra (pFormInfo->retrieveButton, pFormInfo, NULL);
6387   SetTitle (pFormInfo->retrieveButton, "Retrieve 0 Documents");
6388   Disable (pFormInfo->retrieveButton);
6389 
6390   pFormInfo->resetButton = PushButton (c, "Reset", Reset_Callback);
6391   SetObjectExtra (pFormInfo->resetButton, pFormInfo, NULL);
6392 
6393   /*----------------------------------------*/
6394   /* Initialize the Avail and Chosen panels */
6395   /*----------------------------------------*/
6396 
6397   InitChosenPanel (pFormInfo);
6398   InitAvailPanel (pFormInfo);
6399 
6400   /*---------------------*/
6401   /* Return successfully */
6402   /*---------------------*/
6403 
6404   return stdQueryGroup;
6405 }
6406 
6407 /*==================================================================*/
6408 /*                                                                  */
6409 /*  CreateTermlistForm() -                                          */
6410 /*                                                                  */
6411 /*     The object hierarchy is:                                     */
6412 /*                                                                  */
6413 /*        MainWindow                                                */
6414 /*           MainGroup                                              */
6415 /*                                                                  */
6416 /*              PulldownMenus                                       */
6417 /*                                                                  */
6418 /*              StdQueryGroup                                       */
6419 /*                 EnumListGroup                                    */
6420 /*                    DbPopup                                       */
6421 /*                    FieldPopup                                    */
6422 /*                    ModePopup(s)                                  */
6423 /*                    AcceptButton                                  */
6424 /*                 MiscGroup                                        */
6425 /*                    TermDialogText                                */
6426 /*                    FromDialogText                                */
6427 /*                    ToDialogText                                  */
6428 /*                    TaxLineagePopup                               */
6429 /*                 AvailGroup                                       */
6430 /*                    AvailPrompt                                   */
6431 /*                    AvailPanel                                    */
6432 /*                 ChosenGroup                                      */
6433 /*                    ChosenPrompt                                  */
6434 /*                    ChosenPanel                                   */
6435 /*                 ButtonGroup                                      */
6436 /*                    RetrieveButton                                */
6437 /*                    ResetButton                                   */
6438 /*                                                                  */
6439 /*              AdvQueryGroup                                       */
6440 /*                 AdvQueryTextBox                                  */
6441 /*                 ButtonGroup                                      */
6442 /*                    EvaluateButton                                */
6443 /*                    RetrieveButton                                */
6444 /*                    ResetButton                                   */
6445 /*                                                                  */
6446 /*==================================================================*/
6447 
CreateTermlistForm(Int2 left,Int2 top,CharPtr title,WndActnProc activateCallback,FormMessageFunc messagesCallback,E2RetrieveDocsProc retrieveCallback,E2RetrieveUidProc retrieveUidCallback,Boolean explodeToggle,Boolean advancedQueryToggle)6448 NLM_EXTERN ForM CreateTermlistForm (
6449   Int2 left,
6450   Int2 top,
6451   CharPtr title,
6452   WndActnProc activateCallback,
6453   FormMessageFunc messagesCallback,
6454   E2RetrieveDocsProc retrieveCallback,
6455   E2RetrieveUidProc retrieveUidCallback,
6456   Boolean explodeToggle,
6457   Boolean advancedQueryToggle
6458 )
6459 
6460 {
6461   WindoW       mainWindow;
6462   GrouP        mainGroup;
6463   FormInfoPtr  pFormInfo;
6464 
6465   /*-----------------------------------*/
6466   /* Create a formInfo structure to be */
6467   /* filled in by this function.       */
6468   /*-----------------------------------*/
6469 
6470   pFormInfo = (FormInfoPtr) MemNew (sizeof (FormInfo));
6471   if (pFormInfo == NULL) return NULL;
6472 
6473   /*-----------------------------*/
6474   /* Fill in some default values */
6475   /*-----------------------------*/
6476 
6477   pFormInfo->advQueryLexPos = 0;
6478   pFormInfo->advQueryLexStr = NULL;
6479   pFormInfo->advQueryLexState = LEXSTATE_IDLE;
6480   pFormInfo->advQueryNextToken = NULL;
6481   pFormInfo->form = NULL;
6482   pFormInfo->termList = NULL;
6483 
6484   /*----------------------------*/
6485   /* Create the Main Window and */
6486   /* set up basic callbacks.    */
6487   /*----------------------------*/
6488 
6489   mainWindow = FixedWindow (left, top, -10, -10, title, StdSendCloseWindowMessageProc);
6490   if (mainWindow == NULL) return NULL;
6491 
6492   pFormInfo->formmessage = EditMessage_Callback;
6493   pFormInfo->appmessage = messagesCallback;
6494   pFormInfo->activate = activateCallback;
6495   pFormInfo->retrieveDocsProc = retrieveCallback;
6496   pFormInfo->retrieveUidProc = retrieveUidCallback;
6497   SetActivate (mainWindow, TermListActivate_Callback);
6498 
6499   /*---------------------------------------*/
6500   /* Set up the menus and an overall group */
6501   /* for everything in the termlist window */
6502   /*---------------------------------------*/
6503 
6504   SetupMenus (mainWindow, pFormInfo, explodeToggle, advancedQueryToggle);
6505 
6506   mainGroup = HiddenGroup (mainWindow, 0, 0, NULL);
6507 
6508   pFormInfo->stdQueryGroup = SetupStdQueryGroup (pFormInfo, mainGroup);
6509   pFormInfo->advQueryGroup = SetupAdvQueryGroup (pFormInfo, mainGroup);
6510 
6511   AlignObjects (ALIGN_RIGHT, (HANDLE) pFormInfo->availDoc, (HANDLE) pFormInfo->advQueryText, NULL);
6512 
6513   /*----------------------------------*/
6514   /* Show the advanced query group if */
6515   /* we're in advanced query mode.    */
6516   /*----------------------------------*/
6517 
6518   if (advancedQueryToggle == TRUE)
6519     SafeHide (pFormInfo->stdQueryGroup);
6520   else
6521     SafeHide (pFormInfo->advQueryGroup);
6522 
6523   /*--------------------------------------*/
6524   /* Select the default starting database */
6525   /*--------------------------------------*/
6526 
6527   ChangeDatabase (pFormInfo->databasePopup);
6528 
6529   /*--------------------------------*/
6530   /* Fill in the FormInfo structure */
6531   /*--------------------------------*/
6532 
6533   pFormInfo->form = (ForM) mainWindow;
6534 
6535   /*---------------------*/
6536   /* Return successfully */
6537   /*---------------------*/
6538 
6539   SetObjectExtra ((ForM) mainWindow, (BaseFormPtr) pFormInfo, TermListCleanup_Callback);
6540 
6541   RealizeWindow (mainWindow);
6542   SetWindowTimer (mainWindow, AvailTimerProc);
6543 
6544   return pFormInfo->form;
6545 }
6546 
6547 /*==================================================================*/
6548 /*                                                                  */
6549 /* Query_GetInfo () - Connect to the Entrez2 server and get DB      */
6550 /*                   info -- db names, field names, etc.            */
6551 /*                                                                  */
6552 /*==================================================================*/
6553 
Query_GetInfo(void)6554 NLM_EXTERN Entrez2InfoPtr Query_GetInfo (void)
6555 
6556 {
6557   Entrez2RequestPtr  e2rq;
6558   Entrez2ReplyPtr    e2ry;
6559   FILE               *fp;
6560   ValNodePtr         head = NULL;
6561   Char               path [PATH_MAX];
6562   CharPtr            str;
6563   ValNodePtr         vnp;
6564 
6565   /*---------------------------------*/
6566   /* Only query the server once, use */
6567   /* stored version afterwards.      */
6568   /*---------------------------------*/
6569 
6570   if (s_masterE2ip != NULL) return s_masterE2ip;
6571 
6572   /*----------------------------------*/
6573   /* Request the data from the server */
6574   /*----------------------------------*/
6575 
6576   e2rq = EntrezCreateGetInfoRequest ();
6577   if (e2rq == NULL) return NULL;
6578 
6579   if (ShowASN () == TRUE)
6580     DisplayEntrezRequest (e2rq);
6581 
6582   e2ry = SpecialEntrezSynchronousQuery (e2rq);
6583   if (e2ry == NULL) return NULL;
6584 
6585   if (ShowASN () == TRUE)
6586     DisplayEntrezReply (e2ry);
6587 
6588   s_masterE2ip = EntrezExtractInfoReply (e2ry);
6589 
6590   Entrez2RequestFree (e2rq);
6591 
6592   /*------------------------------*/
6593   /* Validate EntrezInfo contents */
6594   /*------------------------------*/
6595 
6596   if (! ValidateEntrez2InfoPtrExEx (s_masterE2ip, &head, TRUE, TRUE)) {
6597     TmpNam (path);
6598     fp = FileOpen (path, "w");
6599     if (fp != NULL) {
6600       fprintf (fp, "Entrez2Info Validation Errors\n\n");
6601       for (vnp = head; vnp != NULL; vnp = vnp->next) {
6602         str = (CharPtr) vnp->data.ptrvalue;
6603         if (str == NULL) continue;
6604         fprintf (fp, "%s\n", str);
6605       }
6606       FileClose (fp);
6607       LaunchGeneralTextViewer (path, "ValidateEntrez2InfoPtr");
6608     }
6609     FileRemove (path);
6610     ValNodeFreeData (head);
6611   }
6612 
6613   /*---------------------*/
6614   /* Return successfully */
6615   /*---------------------*/
6616 
6617   return s_masterE2ip;
6618 }
6619 
6620 /*==================================================================*/
6621 /*                                                                  */
6622 /*  TermlistToRequestCloseGroup () - Builds a boolean request from  */
6623 /*                           the info in the given TermFormPtr.     */
6624 /*                                                                  */
6625 /*==================================================================*/
6626 
TermlistToRequestCloseGroup(FormInfoPtr pFormInfo,Entrez2RequestPtr e2RequestPtr)6627 static Boolean TermlistToRequestCloseGroup (FormInfoPtr pFormInfo, Entrez2RequestPtr e2RequestPtr)
6628 
6629 {
6630   Int2                 group;
6631   Int2                 last;
6632   StateDataPtr         sdp;
6633   Boolean              isEmpty = TRUE;
6634   Boolean              doNotExplode;
6635   Boolean              doNotTranslate = FALSE;
6636   CharPtr              rangeStr;
6637   CharPtr              fromTerm;
6638   CharPtr              toTerm;
6639   Entrez2FieldInfoPtr  fieldInfo;
6640   CharPtr              dbName;
6641 
6642   group = 0;
6643   last = 0;
6644   doNotExplode = ! GetStatus (pFormInfo->explodeItem);
6645   sdp = pFormInfo->termList;
6646 
6647   /* Loop through all the terms in the linked list */
6648 
6649   for (sdp = pFormInfo->termList; sdp != NULL; sdp = sdp->next) {
6650 
6651     /* Do not translate if DB is PubMed */
6652     /* and the field is ALL.            */
6653 
6654     fieldInfo = FieldGetInfo (sdp->db, sdp->fld);
6655     dbName = DBGetNameFromID (sdp->db);
6656 
6657     if ((StrICmp(dbName, "PubMed") == 0) &&
6658          (StrICmp(fieldInfo->field_name, "ALL") == 0))
6659       doNotTranslate = doNotExplode; /* doNotTranslate = TRUE; */
6660     else
6661       doNotTranslate = doNotExplode;
6662 
6663     if (sdp->group == GROUP_SINGLE || sdp->group == GROUP_FIRST)
6664       group++;
6665     if (sdp->state == STATE_ON) {
6666       isEmpty = FALSE;
6667 
6668       /* Add opening parens at beginning */
6669 
6670       if (last == 0) {
6671         EntrezAddToBooleanRequest (e2RequestPtr, NULL, ENTREZ_OP_LEFT_PAREN,
6672                                    NULL, NULL, NULL, 0, 0, NULL, NULL,
6673                                    doNotExplode, doNotTranslate);
6674         EntrezAddToBooleanRequest (e2RequestPtr, NULL, ENTREZ_OP_LEFT_PAREN,
6675                                    NULL, NULL, NULL, 0, 0, NULL, NULL,
6676                                    doNotExplode, doNotTranslate);
6677       }
6678 
6679       /* Put an 'OR' operator between groups */
6680 
6681       else if (last == group) {
6682         EntrezAddToBooleanRequest (e2RequestPtr, NULL, ENTREZ_OP_OR,
6683                                    NULL, NULL, NULL, 0, 0, NULL, NULL,
6684                                    doNotExplode, doNotTranslate);
6685       }
6686 
6687       /* Put 'BUTNOT' operator where requested */
6688 
6689       else if (sdp->above == ENTREZ_OP_BUTNOT) {
6690         EntrezAddToBooleanRequest (e2RequestPtr, NULL, ENTREZ_OP_RIGHT_PAREN,
6691                                    NULL, NULL, NULL, 0, 0, NULL, NULL,
6692                                    doNotExplode, doNotTranslate);
6693         EntrezAddToBooleanRequest (e2RequestPtr, NULL, ENTREZ_OP_RIGHT_PAREN,
6694                                    NULL, NULL, NULL, 0, 0, NULL, NULL,
6695                                    doNotExplode, doNotTranslate);
6696         EntrezAddToBooleanRequest (e2RequestPtr, NULL, ENTREZ_OP_BUTNOT,
6697                                    NULL, NULL, NULL, 0, 0, NULL, NULL,
6698                                    doNotExplode, doNotTranslate);
6699         EntrezAddToBooleanRequest (e2RequestPtr, NULL, ENTREZ_OP_LEFT_PAREN,
6700                                    NULL, NULL, NULL, 0, 0, NULL, NULL,
6701                                    doNotExplode, doNotTranslate);
6702         EntrezAddToBooleanRequest (e2RequestPtr, NULL, ENTREZ_OP_LEFT_PAREN,
6703                                    NULL, NULL, NULL, 0, 0, NULL, NULL,
6704                                    doNotExplode, doNotTranslate);
6705       }
6706 
6707       /* Otherwise default operator is 'AND' */
6708 
6709       else {
6710         EntrezAddToBooleanRequest (e2RequestPtr, NULL, ENTREZ_OP_RIGHT_PAREN,
6711                                    NULL, NULL, NULL, 0, 0, NULL, NULL,
6712                                    doNotExplode, doNotTranslate);
6713         EntrezAddToBooleanRequest (e2RequestPtr, NULL, ENTREZ_OP_AND,
6714                                    NULL, NULL, NULL, 0, 0, NULL, NULL,
6715                                    doNotExplode, doNotTranslate);
6716         EntrezAddToBooleanRequest (e2RequestPtr, NULL, ENTREZ_OP_LEFT_PAREN,
6717                                    NULL, NULL, NULL, 0, 0, NULL, NULL,
6718                                    doNotExplode, doNotTranslate);
6719       }
6720 
6721       /* Add in the term itself */
6722 
6723       if (sdp->key == NULL) {
6724 
6725         /* If it is a range, then split out the to and from */
6726 
6727         if (StringChr (sdp->term, ':') != 0) {
6728           rangeStr = (CharPtr) MemNew (strlen (sdp->term) + 1);
6729           StringCpy (rangeStr, sdp->term);
6730           fromTerm = StringTokMT(rangeStr, ":", &rangeStr);
6731           toTerm = StringTokMT(rangeStr, ":", &rangeStr);
6732           if ((fromTerm != NULL) && (toTerm != NULL)) {
6733             EntrezAddToBooleanRequest (e2RequestPtr, NULL, 0, sdp->field,
6734                                        fromTerm, NULL, 0, 0, NULL, NULL,
6735                                        doNotExplode, doNotTranslate);
6736             EntrezAddToBooleanRequest (e2RequestPtr, NULL, ENTREZ_OP_RANGE,
6737                                        NULL, NULL, NULL, 0, 0, NULL, NULL,
6738                                        doNotExplode, doNotTranslate);
6739             EntrezAddToBooleanRequest (e2RequestPtr, NULL, 0, sdp->field,
6740                                        toTerm, NULL, 0, 0, NULL, NULL,
6741                                        doNotExplode, doNotTranslate);
6742           }
6743           MemFree (rangeStr);
6744         }
6745         else
6746           EntrezAddToBooleanRequest (e2RequestPtr, NULL, 0, sdp->field,
6747                                      sdp->term, NULL, 0, 0, NULL, NULL,
6748                                      doNotExplode, doNotTranslate);
6749       } else {
6750         EntrezAddToBooleanRequest (e2RequestPtr, NULL, 0, NULL, NULL,
6751                                    sdp->key, 0, 0, NULL, NULL,
6752                                    doNotExplode, doNotTranslate);
6753         EntrezSetUseHistoryFlag (e2RequestPtr);
6754       }
6755       last = group;
6756     }
6757   }
6758 
6759   if (isEmpty == TRUE) return FALSE;
6760 
6761   /* Add on the closing parens */
6762 
6763   if (group > 0 && last > 0) {
6764     EntrezAddToBooleanRequest (e2RequestPtr, NULL, ENTREZ_OP_RIGHT_PAREN,
6765                                    NULL, NULL, NULL, 0, 0, NULL, NULL,
6766                                    doNotExplode, doNotTranslate);
6767     EntrezAddToBooleanRequest (e2RequestPtr, NULL, ENTREZ_OP_RIGHT_PAREN,
6768                                    NULL, NULL, NULL, 0, 0, NULL, NULL,
6769                                    doNotExplode, doNotTranslate);
6770   }
6771 
6772   /* Return successfully */
6773 
6774   return TRUE;
6775 }
6776 
6777 /*==================================================================*/
6778 /*                                                                  */
6779 /*  Query_FetchUIDs () - Use the linked list of terms stored in     */
6780 /*                      the TermFormPtr to generate a query that    */
6781 /*                      returns all matching UIDs.                  */
6782 /*                                                                  */
6783 /*==================================================================*/
6784 
Query_FetchUIDs(ForM f)6785 NLM_EXTERN Entrez2BooleanReplyPtr Query_FetchUIDs (ForM f)
6786 
6787 {
6788   CharPtr                 dbName;
6789   Entrez2RequestPtr       e2RequestPtr;
6790   Entrez2ReplyPtr         e2ReplyPtr;
6791   Entrez2BooleanReplyPtr  e2BooleanPtr;
6792   FormInfoPtr             pFormInfo;
6793 
6794   pFormInfo = (FormInfoPtr) GetObjectExtra (f);
6795 
6796   /*------------------------------------*/
6797   /* Make sure that we have at hand all */
6798   /* the ingredients for the query.     */
6799   /*------------------------------------*/
6800 
6801   if (pFormInfo->termList == NULL || pFormInfo->chosenNumLines < 1 || pFormInfo->termList->db < 0) return 0;
6802 
6803   /*--------------------------------*/
6804   /* Get the name of the current DB */
6805   /*--------------------------------*/
6806 
6807   dbName = DBGetNameFromID (pFormInfo->currDb);
6808   if (StringHasNoText (dbName)) return 0;
6809 
6810   /*---------------------------------*/
6811   /* Create an empty Boolean request */
6812   /*---------------------------------*/
6813 
6814   e2RequestPtr = EntrezCreateBooleanRequest (TRUE, FALSE, dbName, NULL, 0, 0, NULL, 0, 0);
6815   if (e2RequestPtr == NULL) return 0;
6816 
6817   /*------------------------------------*/
6818   /* Convert the linked list of boolean */
6819   /* terms into a boolean request and   */
6820   /* send the request to the server.    */
6821   /*------------------------------------*/
6822 
6823   if (! TermlistToRequestCloseGroup (pFormInfo, e2RequestPtr)) return 0;
6824 
6825   if (ShowASN () == TRUE)
6826     DisplayEntrezRequest (e2RequestPtr);
6827 
6828   e2ReplyPtr = SpecialEntrezSynchronousQuery (e2RequestPtr);
6829   if (e2ReplyPtr == NULL) return 0;
6830 
6831   if (ShowASN () == TRUE)
6832     DisplayEntrezReply (e2ReplyPtr);
6833 
6834   /*----------------------------------*/
6835   /* Parse the count out of the reply */
6836   /*----------------------------------*/
6837 
6838   e2BooleanPtr = EntrezExtractBooleanReply (e2ReplyPtr);
6839 
6840   /*----------------------------------*/
6841   /* Clean up and return successfully */
6842   /*----------------------------------*/
6843 
6844   Entrez2RequestFree (e2RequestPtr);
6845 
6846   return e2BooleanPtr;
6847 }
6848 
6849 /*==================================================================*/
6850 /*                                                                  */
6851 /*  Query_FetchSeveralCounts () -                                   */
6852 /*                                                                  */
6853 /*==================================================================*/
6854 
Query_FetchSeveralCounts(CharPtr dbName,CharPtr fieldName,CharPtr searchStr,Int2 count)6855 NLM_EXTERN Entrez2TermListPtr Query_FetchSeveralCounts (CharPtr dbName, CharPtr fieldName, CharPtr searchStr, Int2 count)
6856 
6857 {
6858   Entrez2RequestPtr   e2RequestPtr;
6859   Entrez2ReplyPtr     e2ReplyPtr;
6860   Entrez2TermListPtr  e2TermListPtr;
6861   Int4                termPos;
6862 
6863   /*-----------------------------------------*/
6864   /* Find the position of the requested term */
6865   /*-----------------------------------------*/
6866 
6867   e2RequestPtr = EntrezCreateGetTermPositionRequest (dbName, fieldName, searchStr);
6868   if (ShowASN () == TRUE)
6869     DisplayEntrezRequest (e2RequestPtr);
6870 
6871   e2ReplyPtr = SpecialEntrezSynchronousQuery (e2RequestPtr);
6872 
6873   if (ShowASN () == TRUE)
6874     DisplayEntrezReply (e2ReplyPtr);
6875 
6876   if (e2ReplyPtr == NULL) return NULL;
6877 
6878   termPos = EntrezExtractTermPosReply (e2ReplyPtr);
6879 
6880   /*---------------------------------*/
6881   /* Retrieve the requested term and */
6882   /* several following terms.        */
6883   /*---------------------------------*/
6884 
6885   e2RequestPtr = EntrezCreateGetTermListRequest (dbName, fieldName, termPos, count);
6886   if (ShowASN () == TRUE)
6887     DisplayEntrezRequest (e2RequestPtr);
6888 
6889   e2ReplyPtr = SpecialEntrezSynchronousQuery (e2RequestPtr);
6890 
6891   if (ShowASN () == TRUE)
6892     DisplayEntrezReply (e2ReplyPtr);
6893 
6894   if (e2ReplyPtr == NULL) return NULL;
6895 
6896   e2TermListPtr = EntrezExtractTermListReply (e2ReplyPtr);
6897 
6898   /*---------------------*/
6899   /* Return successfully */
6900   /*---------------------*/
6901 
6902   return e2TermListPtr;
6903 }
6904 
6905 /*==================================================================*/
6906 /*                                                                  */
6907 /*  Query_FetchCount () -                                           */
6908 /*                                                                  */
6909 /*==================================================================*/
6910 
Query_FetchCount(ForM f)6911 NLM_EXTERN Int4 Query_FetchCount (ForM f)
6912 
6913 {
6914   CharPtr                 dbName;
6915   Int4                    count;
6916   Entrez2RequestPtr       e2RequestPtr;
6917   Entrez2ReplyPtr         e2ReplyPtr;
6918   Entrez2BooleanReplyPtr  e2BooleanPtr;
6919   FormInfoPtr             pFormInfo;
6920 
6921   pFormInfo = (FormInfoPtr) GetObjectExtra (f);
6922 
6923   /*------------------------------------*/
6924   /* Make sure that we have at hand all */
6925   /* the ingredients for the query.     */
6926   /*------------------------------------*/
6927 
6928   if (pFormInfo->termList == NULL || pFormInfo->chosenNumLines < 1 || pFormInfo->termList->db < 0) return 0;
6929 
6930   /*--------------------------------*/
6931   /* Get the name of the current DB */
6932   /*--------------------------------*/
6933 
6934   dbName = DBGetNameFromID (pFormInfo->currDb);
6935   if (StringHasNoText (dbName)) return 0;
6936 
6937   /*---------------------------------*/
6938   /* Create an empty Boolean request */
6939   /*---------------------------------*/
6940 
6941   e2RequestPtr = EntrezCreateBooleanRequest (FALSE, FALSE, dbName, NULL, 0, 0, NULL, 0, 0);
6942   if (e2RequestPtr == NULL) return 0;
6943 
6944   /*------------------------------------*/
6945   /* Convert the linked list of boolean */
6946   /* terms into a boolean request and   */
6947   /* send the request to the server.    */
6948   /*------------------------------------*/
6949 
6950   if (! TermlistToRequestCloseGroup (pFormInfo, e2RequestPtr)) return 0;
6951 
6952   if (ShowASN () == TRUE)
6953     DisplayEntrezRequest (e2RequestPtr);
6954 
6955   e2ReplyPtr = SpecialEntrezSynchronousQuery (e2RequestPtr);
6956 
6957   if (ShowASN () == TRUE)
6958     DisplayEntrezReply (e2ReplyPtr);
6959 
6960   if (e2ReplyPtr == NULL) return 0;
6961 
6962   /*----------------------------------*/
6963   /* Parse the count out of the reply */
6964   /*----------------------------------*/
6965 
6966   e2BooleanPtr = EntrezExtractBooleanReply (e2ReplyPtr);
6967   if (e2BooleanPtr == NULL) return 0;
6968 
6969   count = e2BooleanPtr->count;
6970 
6971   /*----------------------------------*/
6972   /* Clean up and return successfully */
6973   /*----------------------------------*/
6974 
6975   Entrez2BooleanReplyFree (e2BooleanPtr);
6976   Entrez2RequestFree (e2RequestPtr);
6977 
6978   return count;
6979 }
6980 
6981 /*==================================================================*/
6982 /*                                                                  */
6983 /*  RemoveExtraQuotes () -                                          */
6984 /*                                                                  */
6985 /*==================================================================*/
6986 
RemoveExtraQuotes(CharPtr origString)6987 static CharPtr RemoveExtraQuotes (CharPtr origString)
6988 
6989 {
6990   Int2     charNum = 0;
6991   Int2     length;
6992   CharPtr  newString;
6993   Int2     newCharNum = 0;
6994 
6995   length = StringLen (origString);
6996   newString = MemNew (length + 1);
6997   for (charNum = 0; charNum < length; charNum++) {
6998     if (origString [charNum] != '"') {
6999       newString [newCharNum] = origString [charNum];
7000       newCharNum++;
7001     }
7002   }
7003 
7004   return newString;
7005 }
7006 
7007 /*==================================================================*/
7008 /*                                                                  */
7009 /*  Query_FetchParsedCount () -                                     */
7010 /*                                                                  */
7011 /*==================================================================*/
7012 
Query_FetchParsedCount(ForM f)7013 NLM_EXTERN Int4 Query_FetchParsedCount (ForM f)
7014 
7015 {
7016   CharPtr                 dbName;
7017   Entrez2RequestPtr       e2RequestPtr;
7018   Entrez2ReplyPtr         e2ReplyPtr;
7019   Int4                    count;
7020   Entrez2BooleanReplyPtr  e2BooleanPtr;
7021   FormInfoPtr             pFormInfo;
7022   Entrez2BooleanTermPtr   tmpTerm;
7023   StateDataPtr            currentTerm;
7024   Boolean                 found;
7025   ValNodePtr              valNodeTermList;
7026   CharPtr                 cleanedUpTerm;
7027 
7028   pFormInfo = (FormInfoPtr) GetObjectExtra (f);
7029 
7030   /*------------------------------------*/
7031   /* Make sure that we have at hand all */
7032   /* the ingredients for the query.     */
7033   /*------------------------------------*/
7034 
7035   if (pFormInfo->termList == NULL ||
7036       pFormInfo->chosenNumLines < 1 ||
7037       pFormInfo->termList->db < 0)
7038     return -1;
7039 
7040   /*--------------------------------*/
7041   /* Get the name of the current DB */
7042   /*--------------------------------*/
7043 
7044   dbName = DBGetNameFromID (pFormInfo->currDb);
7045   if (StringHasNoText (dbName)) return -1;
7046 
7047   /*---------------------------------*/
7048   /* Create an empty Boolean request */
7049   /*---------------------------------*/
7050 
7051   e2RequestPtr = EntrezCreateBooleanRequest (FALSE, TRUE, dbName, NULL,
7052                                              0, 0, NULL, 0, 0);
7053   if (e2RequestPtr == NULL) return -1;
7054 
7055   /*------------------------------------*/
7056   /* Convert the linked list of boolean */
7057   /* terms into a boolean request and   */
7058   /* send the request to the server.    */
7059   /*------------------------------------*/
7060 
7061   if (! TermlistToRequestCloseGroup (pFormInfo, e2RequestPtr)) return -1;
7062 
7063   if (ShowASN () == TRUE)
7064     DisplayEntrezRequest (e2RequestPtr);
7065 
7066   e2ReplyPtr = SpecialEntrezSynchronousQuery (e2RequestPtr);
7067 
7068   if (ShowASN () == TRUE)
7069     DisplayEntrezReply (e2ReplyPtr);
7070 
7071   if (e2ReplyPtr == NULL) return -1;
7072 
7073   /*--------------------------------*/
7074   /* Parse the counts for each term */
7075   /* out of the reply.              */
7076   /*--------------------------------*/
7077 
7078   e2BooleanPtr = EntrezExtractBooleanReply (e2ReplyPtr);
7079   if (e2BooleanPtr == NULL) return -1;
7080 
7081   count = e2BooleanPtr->count;
7082 
7083   if (e2BooleanPtr->query != NULL) {
7084     valNodeTermList = e2BooleanPtr->query->exp;
7085 
7086     while (valNodeTermList != NULL) {
7087       if (valNodeTermList->choice == 3) {
7088         tmpTerm = (Entrez2BooleanTermPtr) valNodeTermList->data.ptrvalue;
7089         cleanedUpTerm = RemoveExtraQuotes (tmpTerm->term);
7090         StringCpy (tmpTerm->term, cleanedUpTerm);
7091         currentTerm = pFormInfo->termList;
7092         found = FALSE;
7093         while ((currentTerm != NULL) && (! found)) {
7094           if ((StrICmp (currentTerm->field, tmpTerm->field) == 0) &&
7095               (StrICmp (currentTerm->term, tmpTerm->term) == 0)) {
7096             currentTerm->count = tmpTerm->term_count;
7097             found = TRUE;
7098           }
7099           currentTerm = currentTerm->next;
7100         }
7101       }
7102       valNodeTermList = valNodeTermList->next;
7103     }
7104   }
7105 
7106   /*----------------------------------*/
7107   /* Clean up and return successfully */
7108   /*----------------------------------*/
7109 
7110   Entrez2BooleanReplyFree (e2BooleanPtr);
7111   Entrez2RequestFree (e2RequestPtr);
7112 
7113   return count;
7114 }
7115 
7116 /*==================================================================*/
7117 /*                                                                  */
7118 /*  Query_GetTranslatedCount () -                                   */
7119 /*                                                                  */
7120 /*==================================================================*/
7121 
Query_GetTranslatedTermCount(FormInfoPtr pFormInfo,CharPtr dbName,CharPtr fieldName,CharPtr term)7122 static Int4 Query_GetTranslatedTermCount (FormInfoPtr pFormInfo, CharPtr dbName, CharPtr fieldName, CharPtr term)
7123 
7124 {
7125   Char                displayStr [256];
7126   Entrez2RequestPtr   e2RequestPtr;
7127   Entrez2ReplyPtr     e2ReplyPtr;
7128   Entrez2TermListPtr  e2TermListPtr;
7129   Int2                row;
7130   Int4                termPos;
7131   Entrez2TermPtr      termPtr;
7132 
7133   /*-----------------------------------------*/
7134   /* Find the position of the requested term */
7135   /*-----------------------------------------*/
7136 
7137   e2RequestPtr = EntrezCreateGetTermPositionRequest (dbName, fieldName, term);
7138 
7139   if (ShowASN () == TRUE)
7140     DisplayEntrezRequest (e2RequestPtr);
7141 
7142   e2ReplyPtr = SpecialEntrezSynchronousQuery (e2RequestPtr);
7143 
7144   if (ShowASN () == TRUE)
7145     DisplayEntrezReply (e2ReplyPtr);
7146 
7147   if (e2ReplyPtr == NULL) return -1;
7148 
7149   termPos = EntrezExtractTermPosReply (e2ReplyPtr);
7150 
7151   /*---------------------------------*/
7152   /* Retrieve the requested term and */
7153   /* several following terms.        */
7154   /*---------------------------------*/
7155 
7156   e2RequestPtr = EntrezCreateGetTermListRequest (dbName, fieldName, termPos, AVAIL_WINDOW_ROWS);
7157 
7158   if (ShowASN () == TRUE)
7159     DisplayEntrezRequest (e2RequestPtr);
7160 
7161   e2ReplyPtr = SpecialEntrezSynchronousQuery (e2RequestPtr);
7162 
7163   if (ShowASN () == TRUE)
7164     DisplayEntrezReply (e2ReplyPtr);
7165 
7166   if (e2ReplyPtr == NULL) return -1;
7167 
7168   e2TermListPtr = EntrezExtractTermListReply (e2ReplyPtr);
7169 
7170   if (e2TermListPtr == NULL) return -1;
7171 
7172   pFormInfo->availItem = 0;
7173   pFormInfo->availRow = 0;
7174   Reset (pFormInfo->availDoc);
7175   SetDocCache (pFormInfo->availDoc, NULL, NULL, NULL);
7176   Update ();
7177 
7178   for (row = 1, termPtr = e2TermListPtr->list; row <= AVAIL_WINDOW_ROWS && termPtr != NULL; row++, termPtr = termPtr->next) {
7179     sprintf (displayStr, "%s\t%ld\t%d\n", termPtr->term, (long) (termPtr->count), (int) (termPtr->is_leaf_node ? 1 : 0));
7180     AppendText (pFormInfo->availDoc, displayStr, &availParFmt, availColFmt, systemFont);
7181   }
7182 
7183   InvalDocument (pFormInfo->availDoc);
7184   Update ();
7185 
7186   if (e2TermListPtr != NULL &&  e2TermListPtr->list != NULL) {
7187     if (StringICmp (e2TermListPtr->list->term, term) == 0) return e2TermListPtr->list->count;
7188   }
7189 
7190   return -1;
7191 }
7192 
7193 /*==================================================================*/
7194 /*                                                                  */
7195 /*  Query_TranslateAndAddBoolTerm () -                              */
7196 /*                      Have the server translate a single term     */
7197 /*                      into multiple terms, each with their own    */
7198 /*                      count. Then add each of these terms to the  */
7199 /*                      the termlist (in an OR'd group) and display */
7200 /*                      them.                                       */
7201 /*                                                                  */
7202 /*==================================================================*/
7203 
Query_TranslateAndAddBoolTerm(ForM f,Int2 currDb,Int2 currFld,CharPtr strs,Int2 state,Int4 num)7204 static Boolean Query_TranslateAndAddBoolTerm (
7205   ForM    f,
7206   Int2    currDb,
7207   Int2    currFld,
7208   CharPtr strs,
7209   Int2    state,
7210   Int4    num
7211 )
7212 
7213 {
7214   StateDataPtr            sdp = NULL;
7215   Entrez2RequestPtr       e2RequestPtr;
7216   Entrez2ReplyPtr         e2ReplyPtr;
7217   Entrez2BooleanReplyPtr  e2BooleanPtr;
7218   CharPtr                 dbName;
7219   Entrez2BooleanTermPtr   tmpTerm;
7220   ValNodePtr              valNodeTermList;
7221   CharPtr                 cleanedUpTerm;
7222   Boolean                 firstTerm;
7223   StateDataPtr            prev = NULL;
7224   CharPtr                 fieldName;
7225   Int2                    fieldId;
7226   Entrez2FieldInfoPtr     fieldInfo;
7227   FormInfoPtr             pFormInfo;
7228   Int2                    nextOperator = ENTREZ_OP_NONE;
7229   Int2                    nextGroup;
7230   Int2                    tmpOp;
7231   Boolean                 allowDuplicates;
7232   Boolean                 doNotTranslate;
7233 
7234   pFormInfo = (FormInfoPtr) GetObjectExtra (f);
7235 
7236   /*-------------------------------------------*/
7237   /* Get the names of the current db and field */
7238   /*-------------------------------------------*/
7239 
7240   dbName = DBGetNameFromID (currDb);
7241   if (StringHasNoText (dbName)) return FALSE;
7242 
7243   fieldInfo = FieldGetInfo (currDb, currFld);
7244   if (fieldInfo == NULL) return FALSE;
7245 
7246   /*------------------------------------------*/
7247   /* Allow duplicates if the DB is PubMed and */
7248   /* the field is All.                        */
7249   /*------------------------------------------*/
7250 
7251   if ((StringICmp (dbName, "PubMed") == 0) &&
7252       (StringICmp (fieldInfo->field_name, "All") == 0))
7253     allowDuplicates = TRUE;
7254   else
7255     allowDuplicates = FALSE;
7256 
7257   /*-----------------------------------*/
7258   /* Create and send a boolean request */
7259   /* to return a translated list       */
7260   /* of terms for the given term.      */
7261   /*-----------------------------------*/
7262 
7263   doNotTranslate = TRUE;
7264   e2RequestPtr = EntrezCreateBooleanRequest (FALSE, TRUE, dbName, NULL, 0, 0, NULL, 0, 0);
7265   EntrezAddToBooleanRequest (e2RequestPtr, strs, 0, NULL, NULL, NULL, 0, 0, NULL, NULL, TRUE, doNotTranslate);
7266   if (ShowASN () == TRUE)
7267     DisplayEntrezRequest (e2RequestPtr);
7268 
7269   e2ReplyPtr = SpecialEntrezSynchronousQuery (e2RequestPtr);
7270 
7271   if (ShowASN () == TRUE)
7272     DisplayEntrezReply (e2ReplyPtr);
7273 
7274   if (e2ReplyPtr == NULL) return FALSE;
7275 
7276   e2BooleanPtr = EntrezExtractBooleanReply (e2ReplyPtr);
7277   if (e2BooleanPtr == NULL) return FALSE;
7278 
7279   if (e2BooleanPtr->query == NULL) return FALSE;
7280 
7281   /*------------------------------------------------*/
7282   /* Parse the resulting terms out of the query and */
7283   /* add them one at a time to the current list of  */
7284   /* terms and to the chosen window.                */
7285   /*------------------------------------------------*/
7286 
7287   valNodeTermList = e2BooleanPtr->query->exp;
7288 
7289   firstTerm = TRUE;
7290   nextGroup = GROUP_SINGLE;
7291   while (valNodeTermList != NULL) {
7292     if (valNodeTermList->choice == TERMLIST_OPERATOR) {
7293       tmpOp = (Int2) valNodeTermList->data.intvalue;
7294       switch (tmpOp) {
7295         case ENTREZ_OP_AND:
7296           if (sdp != NULL) {
7297             if (sdp->group == GROUP_MIDDLE) {
7298               sdp->group = GROUP_LAST;
7299             } else if (sdp->group == GROUP_FIRST) {
7300               sdp->group = GROUP_SINGLE;
7301             }
7302           }
7303           nextOperator = tmpOp;
7304           nextGroup = GROUP_SINGLE;
7305           break;
7306         case ENTREZ_OP_OR:
7307         case ENTREZ_OP_BUTNOT:
7308           nextOperator = tmpOp;
7309           break;
7310         case ENTREZ_OP_LEFT_PAREN:
7311           nextGroup = GROUP_FIRST;
7312           break;
7313         case ENTREZ_OP_RIGHT_PAREN:
7314           break;
7315       }
7316     } else if (valNodeTermList->choice == TERMLIST_TERM) {
7317 
7318       /*---------------------*/
7319       /* Parse the term info */
7320       /*---------------------*/
7321 
7322       tmpTerm = (Entrez2BooleanTermPtr) valNodeTermList->data.ptrvalue;
7323       cleanedUpTerm = RemoveExtraQuotes (tmpTerm->term);
7324       StringCpy (tmpTerm->term, cleanedUpTerm);
7325       if (IsValidFieldName (currDb, tmpTerm->field) == FALSE)
7326         fieldName = FieldGetNameFromMenuName (currDb, tmpTerm->field);
7327       else
7328         fieldName = tmpTerm->field;
7329 
7330       fieldId = -1;
7331       if (StringDoesHaveText (fieldName)) {
7332         fieldId = FieldGetIDFromName (currDb, fieldName);
7333       }
7334 
7335       if (fieldId != -1) {
7336 
7337         /*-----------------------------------*/
7338         /* Replace -1 with actual term count */
7339         /*  Note -- this also creates the    */
7340         /*    desired 'flashing' effect in   */
7341         /*    the termlist window.           */
7342         /*-----------------------------------*/
7343 
7344         tmpTerm->term_count = Query_GetTranslatedTermCount (pFormInfo, dbName, fieldName, tmpTerm->term);
7345 
7346         /*-------------------------------*/
7347         /* Add the term to the term list */
7348         /*-------------------------------*/
7349 
7350         if (NULL != sdp)
7351           prev = sdp;
7352         sdp = CreateTerm (f, currDb, fieldId, tmpTerm->term, state,
7353                           tmpTerm->term_count, allowDuplicates);
7354         if (NULL == sdp) {
7355           valNodeTermList = valNodeTermList->next;
7356           sdp = prev;
7357           continue;
7358         }
7359 
7360         /*-------------------------------*/
7361         /* Make all the translated terms */
7362         /* an or'd group of terms.       */
7363         /*-------------------------------*/
7364 
7365         switch (nextGroup) {
7366           case GROUP_SINGLE:
7367             sdp->group = GROUP_SINGLE;
7368             break;
7369           case GROUP_FIRST:
7370             sdp->group = GROUP_FIRST;
7371             nextGroup = GROUP_MIDDLE;
7372             break;
7373           case GROUP_MIDDLE:
7374             sdp->group = GROUP_MIDDLE;
7375             break;
7376           case GROUP_LAST:
7377             sdp->group = GROUP_LAST;
7378             break;
7379         }
7380 
7381         if (firstTerm == TRUE) {
7382           prev = sdp->prev;
7383           if (prev != NULL) {
7384             sdp->above = ENTREZ_OP_AND;
7385             prev->below = ENTREZ_OP_AND;
7386           }
7387           firstTerm = FALSE;
7388         } else {
7389           prev = sdp->prev;
7390           sdp->above = nextOperator;
7391           prev->below = nextOperator;
7392         }
7393 
7394         /*--------------------------------------*/
7395         /* Display the term in the chosen panel */
7396         /*--------------------------------------*/
7397 
7398         DisplayTerm (pFormInfo, tmpTerm->term, fieldName, tmpTerm->term_count);
7399 
7400       } else {
7401         if (StringDoesHaveText (tmpTerm->field)) {
7402           Message (MSG_POSTERR, "Bad field name %s ignored in expanded query", tmpTerm->field);
7403         } else {
7404           Message (MSG_POSTERR, "Empty field name ignored in expanded query");
7405         }
7406       }
7407     }
7408     valNodeTermList = valNodeTermList->next;
7409   }
7410 
7411   /*---------------------------*/
7412   /* Mark the last term as the */
7413   /* last in the group.        */
7414   /*---------------------------*/
7415 
7416   if (NULL != sdp)
7417     if (sdp->group != GROUP_SINGLE) {
7418       if (sdp->group == GROUP_FIRST)
7419         sdp->group = GROUP_SINGLE;
7420       else
7421         sdp->group = GROUP_LAST;
7422     }
7423 
7424   /*--------------------------------*/
7425   /* Flatten out nested 'OR' groups */
7426   /*       (A OR (B OR C))          */
7427   /*   becomes                      */
7428   /*       (A OR B OR C)            */
7429   /*--------------------------------*/
7430 
7431   sdp = pFormInfo->termList;
7432   while (sdp != NULL) {
7433     if ((sdp->group == GROUP_FIRST) &&
7434         (sdp->above == ENTREZ_OP_OR) &&
7435         (sdp->below == ENTREZ_OP_OR))
7436       sdp->group = GROUP_MIDDLE;
7437     sdp = sdp->next;
7438   }
7439 
7440   /*------------------------*/
7441   /* Recalculate and redraw */
7442   /*------------------------*/
7443 
7444   AlphabetizeGroups (pFormInfo);
7445   RepopulateChosen (pFormInfo);
7446   RecalculateChosen (pFormInfo);
7447 
7448   /*---------------------*/
7449   /* Return successfully */
7450   /*---------------------*/
7451 
7452   return TRUE;
7453 }
7454 
7455 /*==================================================================*/
7456 /*                                                                  */
7457 /*  RefineUIDs () -                                                 */
7458 /*                                                                  */
7459 /*==================================================================*/
7460 
RefineUIDs(ForM f,CharPtr term,Int4 num,Int4Ptr uids,Int2 db)7461 NLM_EXTERN Boolean RefineUIDs (ForM f, CharPtr term, Int4 num, Int4Ptr uids, Int2 db)
7462 
7463 {
7464   CharPtr            advQueryStr;
7465   EnumFieldAssocPtr  alist;
7466   Entrez2InfoPtr     e2ip;
7467   FormInfoPtr        pFormInfo;
7468   Char               str [64];
7469   WindoW             tempPort;
7470 
7471   pFormInfo = (FormInfoPtr) GetObjectExtra (f);
7472 
7473   /*-------------------------------*/
7474   /* Set the query window settings */
7475   /*-------------------------------*/
7476 
7477   e2ip = Query_GetInfo ();
7478   if (e2ip == NULL) return FALSE;
7479 
7480   alist = CreateDatabaseAlist (e2ip);
7481   if (pFormInfo->currDb != db) {
7482     SetEnumPopup (pFormInfo->databasePopup, alist, (UIEnum) db);
7483     ChangeDatabase (pFormInfo->databasePopup);
7484   } else
7485     DoResetAvail (pFormInfo, TRUE);
7486 
7487   SafeSetTitle (pFormInfo->termText, "");
7488   SafeSetTitle (pFormInfo->fromText, "");
7489   SafeSetTitle (pFormInfo->toText, "");
7490   SafeDisable (pFormInfo->acceptButton);
7491   if (StringHasNoText (term))
7492     term = "*Current_Documents";
7493   if (term [0] == '*')
7494     term++;
7495   StringCpy (str, "*");
7496   StringNCpy (str + 1, term, sizeof (str) - 3);
7497 
7498   /*-----------------------------------*/
7499   /* Add the term to the current query */
7500   /* in the query window.              */
7501   /*-----------------------------------*/
7502 
7503   tempPort = SavePort (pFormInfo->chosenDoc);
7504   Query_AddUidsTerm (pFormInfo->form, str, num, uids, db);
7505   RecalculateChosen (pFormInfo);
7506   RestorePort (tempPort);
7507 
7508   if (! GetStatus (pFormInfo->advancedQueryItem)) {
7509     Show (pFormInfo->termText);
7510     Select (pFormInfo->termText);
7511   } else {
7512     advQueryStr = Query_ConvertToString (pFormInfo->form);
7513     SetAdvancedText (pFormInfo->advQueryText, advQueryStr);
7514     MemFree (advQueryStr);
7515     SafeShow (pFormInfo->advQueryGroup);
7516   }
7517 
7518   /*---------------------*/
7519   /* Return successfully */
7520   /*---------------------*/
7521 
7522   return TRUE;
7523 }
7524 
7525