home *** CD-ROM | disk | FTP | other *** search
/ ftp.uv.es / 2014.11.ftp.uv.es.tar / ftp.uv.es / pub / unix / wais-8-b5.tar.Z / wais-8-b5.tar / wais-8-b5 / x / qcommands.c < prev    next >
C/C++ Source or Header  |  1992-05-07  |  38KB  |  1,630 lines

  1. /* WIDE AREA INFORMATION SERVER SOFTWARE:
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.
  4.  
  5.    This is part of the X user-interface for the WAIS software.  Do with it
  6.    as you please.
  7.  
  8.    jonathan@Think.COM
  9.  
  10.  *
  11.  * $Log:    qcommands.c,v $
  12.  * Revision 1.24  92/05/07  14:51:22  jonathan
  13.  * Changed use of setitimer to alarm.  Thanks to
  14.  * steinkel@carlisle-emh2.army.mil.
  15.  * 
  16.  * Revision 1.23  92/04/30  12:22:11  jonathan
  17.  * Modified to understand "quit no save" and desensitivize it when necessary.
  18.  * 
  19.  * Revision 1.22  92/04/28  15:28:24  jonathan
  20.  * Cleaned up use of scrollists.  Fixed bugs in double clicking.  Added
  21.  * ability to view selected sources and relevant documents.
  22.  * 
  23.  * Revision 1.21  92/03/23  16:08:43  jonathan
  24.  * Added file requester, save as button, changed some sensitivity, that kind
  25.  * of stuff.
  26.  * 
  27.  * Revision 1.20  92/03/17  14:24:17  jonathan
  28.  * Added Cursor code, timers, etc.  Really a lot of stuff.
  29.  * 
  30.  * Revision 1.19  92/03/06  14:47:16  jonathan
  31.  * New and Improved source loading!
  32.  * 
  33.  * Revision 1.18  92/03/02  14:34:20  jonathan
  34.  * Added -f to csh call, per blaze@think.com.
  35.  * 
  36.  * Revision 1.17  92/03/01  14:02:08  jonathan
  37.  * Modified all calls to PrintStatus to use PrintStatusW for compatibility
  38.  * with ui PrintStatus.
  39.  * 
  40.  * Revision 1.16  92/02/17  17:48:27  jonathan
  41.  * Moved last_doc to a global, so it can be reset on a new search.
  42.  * 
  43.  * 
  44.  * Revision 1.15  92/02/17  12:55:38  jonathan
  45.  * Added WCAT type to text display.  Added RCSid and $Log too.
  46.  * 
  47.  *
  48.  */
  49.  
  50. /* this file contains X specific code - it is an integral part of XWAIS */
  51.  
  52. #ifndef lint
  53. static char *RCSid = "$Header: /tmp_mnt/net/quake/proj/wais/wais-8-b5/x/RCS/qcommands.c,v 1.24 92/05/07 14:51:22 jonathan Exp $";
  54. #endif
  55.  
  56. #define _C_QCOMMANDS
  57.  
  58. #include "xwais.h"
  59. #include <setjmp.h>
  60.  
  61. static jmp_buf jbuf;
  62.  
  63. static Boolean editting_new_question, 
  64.   busy = FALSE, searching = FALSE,
  65.   quit = FALSE, save_question = FALSE;
  66.  
  67. static int last_doc = NO_ITEM_SELECTED, 
  68.   last_qdoc = NO_ITEM_SELECTED,
  69.   last_source = NO_ITEM_SELECTED;
  70.  
  71. static XQuestion helpquestion = NULL;
  72. static Textbuff current_text;
  73.  
  74. /* forward declarations */
  75. static void DoTSaveCB _AP((Widget w,
  76.                XtPointer closure,
  77.                XtPointer call_data));
  78.  
  79. static long
  80. GetLineFromPos(text, p)
  81. char *text;
  82. XawTextPosition p;
  83. {
  84.   Textbuff t;
  85.   long i, lines;
  86.  
  87.   for(lines=0, i=0; (i < p) && (*text != 0); i++, text++)
  88.     if(*text == '\n') lines++;
  89.  
  90.   return lines;
  91. }
  92.  
  93. static XawTextPosition
  94. GetPosFromLine(text, line)
  95. char *text;
  96. long line;
  97. {
  98.   Textbuff t;
  99.   long i;
  100.   XawTextPosition pos;
  101.  
  102.   for(pos=0, i=0; (i < line) && (*text != 0); pos++, text++)
  103.     if(*text == '\n') i++;
  104.  
  105.   return pos;
  106. }
  107.  
  108. static int get_selected_type()
  109. {
  110.   return(get_selected_item(typewindow->ListWidget));
  111. }
  112.  
  113. static int get_selected_qsource(question)
  114. XQuestion question;
  115. {
  116.   return(get_selected_item(question->window->Sources->ListWidget));
  117. }
  118.  
  119. static int get_selected_qdoc(question)
  120. XQuestion question;
  121. {
  122.   return(get_selected_item(question->window->RelevantDocuments->ListWidget));
  123. }
  124.  
  125. static int get_selected_response(question)
  126. XQuestion question;
  127. {
  128.   return(get_selected_item(question->window->ResultDocuments->ListWidget));
  129. }
  130.  
  131. #include <signal.h>
  132.  
  133. #define TIMEOUT 1
  134.  
  135. static int new, old; /* timer values */
  136. typedef void (voidfunc)();
  137. static void* alarm_signal;
  138.  
  139. static void
  140. SetCursors(cursor)
  141. Cursor cursor;
  142. {
  143.   QuestionWindow qw = the_Question->window;
  144.   static Cursor xterm_cursor = NULL;
  145.  
  146.   if(xterm_cursor == NULL)
  147.     xterm_cursor = XCreateFontCursor(CurDpy, XC_xterm);
  148.  
  149.   if(cursor != NULL) {
  150.     XDefineCursor(CurDpy, XtWindow(qw->keywordwid), cursor);
  151.     XDefineCursor(CurDpy, XtWindow(qw->shell), cursor);
  152.     XDefineCursor(CurDpy, XtWindow(qw->Sources->ListWidget), cursor);
  153.     XDefineCursor(CurDpy, XtWindow(qw->RelevantDocuments->ListWidget), cursor);
  154.     XDefineCursor(CurDpy, XtWindow(qw->ResultDocuments->ListWidget), cursor);
  155.     XDefineCursor(CurDpy, XtWindow(qw->StatusWindow), cursor);
  156.   }
  157.   else {
  158.     XDefineCursor(CurDpy, XtWindow(qw->keywordwid), xterm_cursor);
  159.     XUndefineCursor(CurDpy, XtWindow(qw->shell));
  160.     XUndefineCursor(CurDpy, XtWindow(qw->Sources->ListWidget));
  161.     XUndefineCursor(CurDpy, XtWindow(qw->RelevantDocuments->ListWidget));
  162.     XUndefineCursor(CurDpy, XtWindow(qw->ResultDocuments->ListWidget));
  163.     XUndefineCursor(CurDpy, XtWindow(qw->StatusWindow));
  164.   }
  165. }
  166.  
  167. static void
  168. alarmhandler(sig, code, scp, addr)
  169. long sig, code;
  170. struct sigcontext *scp;
  171. char *addr;
  172. {
  173.   XEvent event;
  174.   static int cursor = 0;
  175.  
  176.   SetCursors(wais_cursors[cursor]);
  177.   cursor = (cursor+1)%NUM_CURSORS;
  178.  
  179.   while((XtAppPending(app_context)&XtIMXEvent) != 0) {
  180.     XtAppNextEvent(app_context, &event);
  181.     XtDispatchEvent(&event);
  182.   }
  183.   alarm(new);
  184.   return;
  185. }
  186.  
  187. static void
  188. fuzzButtons()
  189. {
  190.   Arg args[1];
  191.   XEvent event;
  192.  
  193.   XtSetArg(args[0], XtNsensitive, False);
  194.   if(searching) {
  195.     XtSetValues(viewbutton, args, ONE);
  196.     XtCallActionProc(searchButton, "set", NULL, NULL, 0);
  197.   }
  198.   else {
  199.     XtSetValues(searchButton, args, ONE);
  200.     XtCallActionProc(viewbutton, "set", NULL, NULL, 0);
  201.   }
  202.   XtSetValues(addSourceButton, args, ONE);
  203.   XtSetValues(delSourceButton, args, ONE);
  204.   XtSetValues(addDocButton, args, ONE);
  205.   XtSetValues(delDocButton, args, ONE);
  206.   XtSetValues(helpButton, args, ONE);
  207.   XtSetValues(saveAsButton, args, ONE);
  208.   XtSetValues(doneButton, args, ONE);
  209.   XtSetArg(args[0], XtNsensitive, True);
  210.   XtSetValues(abortButton, args, ONE);
  211. }
  212.  
  213. void
  214. unfuzzButtons()
  215. {
  216.   Arg args[1];
  217.   XEvent event;
  218.  
  219.   XtSetArg(args[0], XtNsensitive, True);
  220.   XtSetValues(searchButton, args, ONE);
  221.   XtSetValues(addSourceButton, args, ONE);
  222.   XtSetValues(delSourceButton, args, ONE);
  223.   XtSetValues(addDocButton, args, ONE);
  224.   XtSetValues(delDocButton, args, ONE);
  225.   XtSetValues(helpButton, args, ONE);
  226.   XtSetValues(saveAsButton, args, ONE);
  227.   XtSetValues(doneButton, args, ONE);
  228.   XtSetValues(viewbutton, args, ONE);
  229.   XtSetArg(args[0], XtNsensitive, False);
  230.   XtSetValues(abortButton, args, ONE);
  231. }
  232.  
  233. void
  234. Abort(w, closure, call_data)
  235. Widget w;
  236. XtPointer closure, call_data;
  237. {
  238.   if(busy) {
  239.     unfuzzButtons();
  240.     longjmp(jbuf, 1);
  241.   }
  242. }  
  243.  
  244. /* these are the commands used in the question widget */
  245.  
  246.  
  247. /* ARGSUSED */
  248. void
  249. DoSearch(w, closure, call_data)
  250. Widget w;
  251. XtPointer closure, call_data;
  252. {
  253.   Arg args[2];
  254.   Question q = the_Question->q;
  255.   QuestionWindow qw = the_Question->window;
  256.   char message[255];
  257.   DocList resdocs = q->ResultDocuments;
  258.  
  259.   double_click = FALSE;
  260.   LastClicked = w;
  261.   last_doc = -1;
  262.  
  263.   if(busy) return;
  264.  
  265.   /* update the info */
  266.  
  267.   strncpy(q->keywords, GetString(qw->keywordwid), STRINGSIZE);
  268.  
  269.   new = TIMEOUT;
  270.  
  271.   busy = TRUE;
  272.   searching = TRUE;
  273.  
  274.   fuzzButtons();
  275.   if (setjmp(jbuf) != 0) {
  276.     busy = FALSE;
  277.     XtCallActionProc(searchButton, "unset", NULL, NULL, 0);
  278.     q->ResultDocuments = resdocs;
  279.     SetCursors(NULL);
  280.     if(q->Sources != NULL) {
  281.       SourceList slist;
  282.       Source source;
  283.       for(slist = q->Sources;
  284.       slist != NULL;
  285.       slist = slist->nextSource) {
  286.     if((source = findsource(slist->thisSource->filename)) != NULL)
  287.       close_source(source);
  288.       }
  289.     }
  290.     PrintStatus("\nAbort Search.  Question unmodified.");
  291.     return;
  292.   }
  293.  
  294.   alarm_signal = (void*)signal(SIGALRM, alarmhandler);
  295.   old = alarm(new);
  296.   SearchWais(q);
  297.   alarm(old);
  298.   signal(SIGALRM, alarm_signal);
  299.   SetCursors(NULL);
  300.   freeDocList(resdocs);
  301.   busy = FALSE;
  302.   unfuzzButtons();
  303.   XtSetArg(args[0], XtNsensitive, False);
  304.   XtSetArg(args[1], XtNlabel, " View  ");
  305.   XtSetValues(viewbutton, args, TWO);
  306.   XtSetValues(saveAsButton, args, ONE);
  307.   XtCallActionProc(searchButton, "unset", NULL, NULL, 0);
  308.  
  309.   the_Question->Result_Items = buildDocumentItemList(q->ResultDocuments, TRUE);
  310.   RebuildListWidget(qw->ResultDocuments, the_Question->Result_Items);
  311. }
  312.  
  313. void
  314. SaveQuestion(w, closure, call_data)
  315. Widget w;
  316. XtPointer closure, call_data;
  317. {
  318.   Arg        args[5];
  319.   Position    x, y;
  320.   Dimension    width, height;
  321.   Cardinal    n;
  322.   static char** files;
  323.  
  324.   n = 0;
  325.   XtSetArg(args[0], XtNwidth, &width); n++;
  326.   XtSetArg(args[1], XtNheight, &height); n++;
  327.   XtGetValues(top, args, n);
  328.   XtTranslateCoords(top, (Position) (width / 2), (Position) (height / 2),
  329.             &x, &y);
  330.  
  331.   n = 0;
  332.   XtSetArg(args[n], XtNx, MAX(x-150, 0));        n++;
  333.   XtSetArg(args[n], XtNy, y);                n++;
  334.  
  335.   if(savelist == NULL)
  336.     savelist = MakeSaveRequester(top);
  337.   
  338.   XtSetValues(savereq, args, n);
  339.  
  340.   ReplaceText(dirnamewidget, app_resources.questionDirectory);
  341.   ReplaceText(filenamewidget, the_Question->q->name);
  342.   SetDir(NULL, NULL, NULL);
  343.   save_question = TRUE;
  344.  
  345.   XtSetArg(args[0], XtNsensitive, True);
  346.   XtSetValues(quitbutton, args, ONE);
  347.   XtSetArg(args[0], XtNlabel, "Save&Quit");
  348.   XtSetValues(savebutton, args, ONE);
  349.  
  350.   XtAddCallback(savebutton, XtNcallback, DoSave, NULL);
  351.   XtAddCallback(quitbutton, XtNcallback, DontSave, NULL);
  352.  
  353.   XtPopup(savereq, XtGrabNone);
  354. }
  355.  
  356. /* ARGSUSED */
  357. void CloseQuestionEdit(w, closure, call_data)
  358. Widget w;
  359. XtPointer closure, call_data;
  360. {
  361.   char filename[STRINGSIZE];
  362.  
  363.   strncpy(the_Question->q->keywords,
  364.       GetString(the_Question->window->keywordwid),
  365.       STRINGSIZE);
  366.  
  367.   if(strcmp(the_Question->q->name, "New Question") == 0) {
  368.     quit = TRUE;
  369.     SaveQuestion(NULL, NULL, NULL);
  370.   }
  371.   else {
  372.     sprintf(filename, "%s%s", app_resources.questionDirectory,
  373.         the_Question->q->name);
  374.     WriteQuestion(filename, the_Question->q);
  375.     exit(0);
  376.   }
  377. }
  378.  
  379. static int get_question_response(questionwindow)
  380. QuestionWindow questionwindow;
  381. {
  382.   return(get_selected_item(questionwindow->ResultDocuments->ListWidget));
  383. }
  384.  
  385. /* ARGSUSED */
  386. void
  387. AddResponseToQuestion(w, closure, call_data)
  388. Widget w;
  389. caddr_t closure, call_data;
  390. {
  391.   int numdocs, document_number, i;
  392.   Question q = the_Question->q;
  393.   QuestionWindow qw = the_Question->window;
  394.   DocList this, last;
  395.   float top, shown;
  396.  
  397.   double_click = FALSE;
  398.   LastClicked = w;
  399.  
  400.   document_number = get_question_response(qw);
  401.  
  402.   if(document_number == NO_ITEM_SELECTED) {
  403.     PrintStatusW("\nNo selected response.  Select one and try again.",
  404.        qw->StatusWindow);
  405.     return;
  406.   }
  407.  
  408.   /* find and add document to question's relevant documents */
  409.  
  410.   last = findLast(q->RelevantDocuments);
  411.  
  412.   for(this = q->ResultDocuments, i = 0; i < document_number; i++)
  413.     this = this->nextDoc;
  414.  
  415.   if(last != NULL) 
  416.     last->nextDoc = makeDocList(copy_docid(this->thisDoc), NULL);
  417.   else q->RelevantDocuments = makeDocList(copy_docid(this->thisDoc), NULL);
  418.  
  419.   if(the_Question->Relevant_Items != NULL)
  420.     freeItemList(the_Question->Relevant_Items);
  421.  
  422.   the_Question->Relevant_Items =
  423.     buildDocumentItemList(q->RelevantDocuments, FALSE);
  424.  
  425.   q->numdocs = charlistlength(the_Question->Relevant_Items);
  426.  
  427.   RebuildListWidget(qw->RelevantDocuments, the_Question->Relevant_Items);
  428.  
  429.   q->modified = TRUE;
  430. }
  431.  
  432. /* ARGSUSED */
  433.  
  434. void
  435. AddDocToQuestion(w, closure, call_data)
  436. Widget w;
  437. XtPointer closure, call_data;
  438. {
  439.   int i;
  440.   int SelectedDoc;
  441.   Question q = the_Question->q;
  442.   QuestionWindow qw = the_Question->window;
  443.   float top, shown;
  444.   DocumentID docid;
  445.   DocList dlist;
  446.  
  447.   if ((SelectedDoc = get_selected_response(the_Question)) == NO_ITEM_SELECTED) {
  448.     PrintStatusW("\nNo selected ResultDocument - select one and try again.",
  449.        qw->StatusWindow);
  450.     return;
  451.   }
  452.  
  453.   docid = (DocumentID)s_malloc(sizeof(_DocumentID));
  454.   docid->doc = (CRetDocument)s_malloc(sizeof(_CRetDocument));
  455.  
  456.   dlist = makeDocList(docid, NULL);
  457.   
  458.   /* need to get DocID too - that's not as easy. */
  459.  
  460.   docid->doc->headline = the_Question->Result_Items[SelectedDoc];
  461.  
  462.   /* append it to the current sourcelist */
  463.   
  464.   if(q->RelevantDocuments != NULL) {
  465.     DocList doc;
  466.  
  467.     for(doc = q->RelevantDocuments; doc->nextDoc != NULL; doc = doc->nextDoc);
  468.     doc->nextDoc = dlist;
  469.   }
  470.   else
  471.     q->RelevantDocuments = dlist;
  472.  
  473.   if (the_Question->Relevant_Items != NULL) 
  474.     freeItemList(the_Question->Relevant_Items);
  475.  
  476.   the_Question->Relevant_Items = 
  477.     buildDocumentItemList(q->RelevantDocuments, FALSE);
  478.   q->numdocs = charlistlength(the_Question->Relevant_Items);
  479.  
  480.   RebuildListWidget(qw->RelevantDocuments, the_Question->Relevant_Items);
  481. }
  482.  
  483. /* ARGSUSED */
  484. void
  485. DeleteQuestionDoc(w, closure, call_data)
  486. Widget w;
  487. XtPointer closure, call_data;
  488. {
  489.   int i;
  490.   float shown;
  491.   int SelectedDoc;
  492.   Question q = the_Question->q;
  493.   QuestionWindow qw = the_Question->window;
  494.   DocList doc, last;
  495.  
  496.   if((SelectedDoc = get_selected_qdoc(the_Question)) == NO_ITEM_SELECTED) {
  497.     double_click = FALSE;
  498.     LastClicked = w;
  499.     PrintStatusW("\nNo Document selected.  Please select one and try again.",
  500.         qw->StatusWindow);
  501.     return;
  502.   }
  503.  
  504.   /* rip out the bugger */
  505.  
  506.   last_qdoc = NO_ITEM_SELECTED;
  507.  
  508.   q->modified = TRUE;
  509.  
  510.   double_click = FALSE;
  511.   LastClicked = NULL;
  512.   if (SelectedDoc == 0)
  513.     q->RelevantDocuments = q->RelevantDocuments->nextDoc;
  514.   else {
  515.     for (doc = q->RelevantDocuments, i = 0; i < SelectedDoc-1; i++) {
  516.       doc = doc->nextDoc;
  517.     }
  518.     if(doc->nextDoc != NULL)
  519.       doc->nextDoc = doc->nextDoc->nextDoc;
  520.   }
  521.   if(the_Question->Relevant_Items != NULL) freeItemList(the_Question->Relevant_Items);
  522.   the_Question->Relevant_Items = buildDocumentItemList(q->RelevantDocuments, FALSE);
  523.  
  524.   q->numdocs--;
  525.   RebuildListWidget(qw->RelevantDocuments, the_Question->Relevant_Items);
  526. }
  527.  
  528. /* ARGSUSED */
  529. void
  530. PopupSourceMenu(w, closure, call_data)
  531. Widget w;
  532. XtPointer closure, call_data;
  533. {
  534.   Arg        args[5];
  535.   Position    x, y;
  536.   Dimension    width, height;
  537.   Cardinal    n;
  538.  
  539.   n = 0;
  540.   XtSetArg(args[0], XtNwidth, &width); n++;
  541.   XtSetArg(args[1], XtNheight, &height); n++;
  542.   XtGetValues(w, args, n);
  543.   XtTranslateCoords(w, (Position) 0, (Position)height,
  544.             &x, &y);
  545.  
  546.   n = 0;
  547.   XtSetArg(args[n], XtNx, x); n++;
  548.   XtSetArg(args[n], XtNy, y); n++;
  549.  
  550.   XtSetValues(sshell, args, n);
  551.  
  552.   XawListUnhighlight(sourcewindow->ListWidget);
  553.   XtPopup(sshell, XtGrabExclusive);
  554. }
  555.  
  556.   
  557. /* ARGSUSED */
  558. void
  559. AddSourceToQuestion(w, closure, call_data)
  560. Widget w;
  561. XtPointer closure, call_data;
  562. {
  563.   int i, snum;
  564.   Question q = the_Question->q;
  565.   QuestionWindow qw = the_Question->window;
  566.   SourceID sid;
  567.   SourceList slist;
  568.  
  569.   if((snum = get_selected_source()) != NO_ITEM_SELECTED) {
  570.     if(last_source != snum) {
  571.       last_source = snum;
  572.     }
  573.     else {
  574.       XtPopdown(sshell);
  575.       sid = (SourceID)s_malloc(sizeof(_SourceID));
  576.       slist = makeSourceList(sid, NULL);
  577.   
  578.       sid->filename = s_strdup(Source_items[snum]);
  579.  
  580.       /* append it to the current sourcelist */
  581.   
  582.       if(q->Sources != NULL) {
  583.     SourceList source;
  584.  
  585.     /* check to see if it's already in the list */
  586.  
  587.     for(source = q->Sources; source != NULL; source = source->nextSource) {
  588.       if(strcmp(source->thisSource->filename, sid->filename) == 0) {
  589.         s_free(sid);
  590.         s_free(slist);
  591.         return;
  592.       }
  593.       if(source->nextSource == NULL) break;
  594.     }
  595.     source->nextSource = slist;
  596.       }
  597.       else
  598.     q->Sources = slist;
  599.  
  600.       the_Question->Source_Items = buildSourceItemList(q->Sources);
  601.       q->numsources = charlistlength(the_Question->Source_Items);
  602.  
  603.       RebuildListWidget(qw->Sources, the_Question->Source_Items);
  604.  
  605.       q->modified = TRUE;
  606.     }
  607.   }
  608.   else XtPopdown(sshell);
  609. }
  610.  
  611. /* ARGSUSED */
  612. void
  613. EditQuestionSource(w, closure, call_data)
  614. Widget w;
  615. XtPointer closure, call_data;
  616. {
  617.   SList s;
  618.   int CurrentSource;
  619.   char msg[1000];
  620.   Source edit_source = NULL;
  621.  
  622.   double_click = FALSE;
  623.   LastClicked = w;
  624.  
  625.   if ((CurrentSource = get_selected_qsource(the_Question))
  626.       != NO_ITEM_SELECTED) {
  627.     if (last_source == CurrentSource) {
  628.       if((edit_source = 
  629.       findsource(the_Question->Source_Items[CurrentSource])) == NULL) {
  630.     sprintf(msg, "Cant find source: %s\n", the_Question->Source_Items[CurrentSource]);
  631.     PrintStatus(msg);
  632.     return;
  633.       }
  634.       else {
  635.     sprintf(msg, "Viewing source: %s\n", edit_source->name);
  636.     PrintStatus(msg);
  637.     PopupSource(edit_source);
  638.       }
  639.     }
  640.     else last_source = CurrentSource;
  641.   } 
  642.   else {
  643.     last_source = -1;
  644.     XwaisPrintf("No source selected.\nPlease selected one and try again.\n");
  645.   }
  646. }
  647.  
  648. /* ARGSUSED */
  649. void
  650. DeleteQuestionSource(w, closure, call_data)
  651. Widget w;
  652. XtPointer closure, call_data;
  653. {
  654.   int i;
  655.   float shown;
  656.   int SelectedSource;
  657.   Question q = the_Question->q;
  658.   QuestionWindow qw = the_Question->window;
  659.   SourceList source, last;
  660.  
  661.   if((SelectedSource = get_selected_qsource(the_Question)) == NO_ITEM_SELECTED) {
  662.     double_click = FALSE;
  663.     LastClicked = w;
  664.     PrintStatusW("\nNo source selected.  Please select one and try again.",
  665.         qw->StatusWindow);
  666.     return;
  667.   }
  668.  
  669.   /* rip out the bugger */
  670.  
  671.   last_source = NO_ITEM_SELECTED;
  672.   q->modified = TRUE;
  673.  
  674.   double_click = FALSE;
  675.   LastClicked = NULL;
  676.   if (SelectedSource == 0)
  677.     q->Sources = q->Sources->nextSource;
  678.   else {
  679.     for (source = q->Sources, i = 0; i < SelectedSource-1; i++) {
  680.       source = source->nextSource;
  681.     }
  682.     if(source->nextSource != NULL)
  683.       source->nextSource = source->nextSource->nextSource;
  684.   }
  685.   the_Question->Source_Items = buildSourceItemList(q->Sources);
  686.  
  687.   q->numsources--;
  688.   RebuildListWidget(qw->Sources, the_Question->Source_Items);
  689. }
  690.  
  691. static char *
  692. findFilter(type)
  693. char *type;
  694. {
  695.   char *p, *i1, *i2, t[80];
  696.   static char result[80];
  697.  
  698.   /* filters are of the form TYPE,FILTER;... */
  699.  
  700.   p = app_resources.filters;
  701.   
  702.   while (*p != 0) {
  703.     if((i1 = strchr(p, ',')) == NULL) break;
  704.     strncpy(t, p, i1-p);
  705.     if(!strncmp(t, type, i1-p)) {
  706.       if((i2 = strchr(i1, ';')) != NULL) {
  707.     strncpy(result, i1+1, i2-i1-1);
  708.     result[i2-i1] = 0;
  709.       }
  710.       else strcpy(result, i1+1);
  711.       return result;
  712.     }
  713.     if((p = strchr(i1, ';')) == NULL) break;
  714.     p++;
  715.   }
  716.   return NULL;
  717. }
  718.  
  719. static Boolean
  720. tryFilter(t, type, filename)
  721. Textbuff t;
  722. char *type;
  723. char *filename;
  724. {
  725.   char fname[STRINGSIZE], command[STRINGSIZE], *text, *viewer;
  726.   FILE *fp;
  727.   long i;
  728.  
  729.   if((viewer = findFilter(type)) == NULL) return FALSE;
  730.  
  731.   sprintf(fname, "%s%s",
  732.       app_resources.documentDirectory,
  733.       get_filename(t->docid->doc->headline));
  734.   
  735.   if((fp = fopen(fname, "w")) == NULL) {
  736.     sprintf(command, "Error opening file: %s.", fname);
  737.     PrintStatusW(command, the_Question->window->StatusWindow);
  738.     return;
  739.   }
  740.  
  741.   dumptext(fp, t->text, t->size);
  742.   fclose(fp);
  743.  
  744.   KillText(t);
  745.  
  746.   sprintf(command, "\nRunning '%s %s'", viewer, fname);
  747.   PrintStatusW(command, the_Question->window->StatusWindow);
  748.   sprintf(command, "csh -fc '%s %s;/bin/rm %s' &", viewer, fname, fname);
  749.   system(command);
  750.  
  751.   return TRUE;
  752. }
  753.  
  754. static void
  755. DoSource(t)
  756. Textbuff t;
  757. {
  758.   char f[STRINGSIZE], message[STRINGSIZE];
  759.   FILE *fp;
  760.  
  761.   sprintf(f, "/tmp/src%d", getpid());
  762.   if((fp = fopen(f, "w")) == NULL) {
  763.     sprintf(message, "\nError opening file: %s.", f);
  764.     PrintStatusW(message, the_Question->window->StatusWindow);
  765.     return;
  766.   }
  767.  
  768.   fprintf(fp, t->text);
  769.  
  770.   fclose(fp);
  771.   if((fp = fopen(f, "r")) == NULL) {
  772.     sprintf(message, "\nError opening file: %s.", f);
  773.     PrintStatusW(message, the_Question->window->StatusWindow);
  774.     return;
  775.   }
  776.  
  777.   memset(the_Source, 0, sizeof(_Source));
  778.  
  779.   ReadSource(the_Source, fp);
  780.   fclose(fp);
  781.  
  782.   if (the_Source->name != NULL) s_free(the_Source->name);
  783.   the_Source->name = s_strdup(get_filename(t->docid->doc->headline));
  784.  
  785.   unlink(f);
  786.  
  787.   PopupSource(the_Source);
  788. }
  789.  
  790. static void do_other_thing(t, type)
  791. Textbuff t;
  792. char *type;
  793. {
  794.   Arg        args[5];
  795.   Position    x, y;
  796.   Dimension    width, height;
  797.   Cardinal    n;
  798.   char message[STRINGSIZE];
  799.  
  800.   if (type != NULL && type[0] != 0) {
  801.     sprintf(message,
  802.         "\nDocument is of type: %s, which is unknown. Using Save routine.",
  803.         type);
  804.     PrintStatusW(message, the_Question->window->StatusWindow);
  805.   }
  806.  
  807.   n = 0;
  808.   XtSetArg(args[0], XtNwidth, &width); n++;
  809.   XtSetArg(args[1], XtNheight, &height); n++;
  810.   XtGetValues(the_Question->window->shell, args, n);
  811.   XtTranslateCoords(the_Question->window->shell, (Position) (width / 2), (Position) (height / 2),
  812.             &x, &y);
  813.  
  814.   n = 0;
  815.   XtSetArg(args[n], XtNx, MAX(x-150, 0));        n++;
  816.   XtSetArg(args[n], XtNy, y);                n++;
  817.  
  818.   current_text = t;
  819.  
  820.   if(savelist == NULL)
  821.     savelist = MakeSaveRequester(top);
  822.   
  823.   XtSetValues(savereq, args, n);
  824.  
  825.   ReplaceText(filenamewidget, "");
  826.   ReplaceText(dirnamewidget, app_resources.documentDirectory);
  827.   SetDir(NULL, NULL, NULL);
  828.   save_question = FALSE;
  829.  
  830.   XtPopup(savereq, XtGrabNone);
  831.   clearReqButtons();
  832.  
  833.   XtRemoveAllCallbacks(savebutton, XtNcallback);
  834.   XtAddCallback(savebutton, XtNcallback, DoTSaveCB, t);
  835. }
  836.  
  837. static boolean
  838.   GetDoc(doc, type, textstruct)
  839. DocumentID doc;
  840. char* type;
  841. Textbuff textstruct;
  842. {
  843.   Question q = the_Question->q;
  844.  
  845.   new = TIMEOUT;
  846.  
  847.   busy = TRUE;
  848.   searching = FALSE;
  849.   fuzzButtons();
  850.  
  851.   if (setjmp(jbuf) != 0) {
  852.     busy = FALSE;
  853.     XtCallActionProc(viewbutton, "unset", NULL, NULL, 0);
  854.     SetCursors(NULL);
  855.     if(q->Sources != NULL) {
  856.       SourceList slist;
  857.       Source source;
  858.       for(slist = q->Sources;
  859.       slist != NULL;
  860.       slist = slist->nextSource) {
  861.     if((source = findsource(slist->thisSource->filename)) != NULL)
  862.       close_source(source);
  863.       }
  864.     }
  865.     KillText(textstruct);
  866.     PrintStatus("\nRetrieval aborted.");
  867.     return(false);
  868.   }
  869.  
  870.   alarm_signal = (void*)signal(SIGALRM, alarmhandler);
  871.   old = alarm(new);
  872.   textstruct->text = GetWaisDocument(q, doc, type, NULL, &textstruct->size);
  873.   alarm(old);
  874.   signal(SIGALRM, alarm_signal);
  875.  
  876.   busy = FALSE;
  877.   unfuzzButtons();
  878.   XtCallActionProc(viewbutton, "unset", NULL, NULL, 0);
  879.   SetCursors(NULL);
  880.   return(true);
  881. }
  882.  
  883. static void
  884.   ViewDoc(doc, type, size, savep)
  885. DocumentID doc;
  886. char *type;
  887. long size;
  888. Boolean savep;
  889. {
  890.   Arg args[5];
  891.   Cardinal num_args;
  892.   static long request_length = 0;
  893.   static int document_number;
  894.   WAISDocumentText *text;
  895.   char *viewtext, message[255];
  896.   int i;
  897.   Question q = the_Question->q;
  898.   QuestionWindow qw = the_Question->window;
  899.   Textbuff textstruct;
  900.   TextList thisText, a_tList;
  901.  
  902.   if((textstruct = findTextDoc(doc, type)) != NULL) {
  903.     if(textstruct->shell != NULL) {
  904.       XtPopdown(textstruct->shell);
  905.       XtPopup(textstruct->shell, XtGrabNone);
  906.     }
  907.     return;
  908.   }
  909.  
  910.   if(busy) return;
  911.  
  912.   if(NULL == (thisText = NewText())) {
  913.     PrintStatus("\nUnable to allocate Text structure.  Bummer.");
  914.     return;
  915.   }
  916.  
  917.   textstruct = thisText->thisText;
  918.   textstruct->size = size;
  919.   if(savep)
  920.     textstruct->type = s_strdup("WaIsOddBall");
  921.   else
  922.     textstruct->type = s_strdup(type);
  923.  
  924.   if(GetDoc(doc, type, textstruct) &&
  925.      textstruct->text != NULL) {
  926.     textstruct->docid = doc;
  927.  
  928.     if(textstruct->size == 0) {
  929.       KillText(textstruct);
  930.       PrintStatus("\nNo data returned");
  931.       sleep(2);
  932.       return;
  933.     }
  934.  
  935.     if(savep)
  936.      do_other_thing(textstruct, NULL);
  937.     else if(tryFilter(textstruct, type)) 
  938.       return;
  939.     else if (type == NULL ||
  940.          substrcmp(type, "TEXT") ||
  941.          !strcmp(type, "WCAT")) {
  942.       textstruct->textwindow = MakeTextPopup(top, textstruct, doc->doc->headline);
  943.       num_args = 0;
  944.       XtSetArg(args[num_args], XtNtype, XawAsciiString); num_args++;
  945.       XtSetArg(args[num_args], XtNstring, textstruct->text); num_args++;
  946.       XtSetValues(textstruct->textwindow, args, num_args);
  947.       if (doc->doc->best > 0)
  948.     XawTextSetInsertionPoint(textstruct->textwindow,
  949.                  GetPosFromLine(textstruct->text, doc->doc->best));
  950.       XawTextDisplay(textstruct->textwindow);
  951.     }
  952.     else if (!strcmp(type, "WSRC")) {
  953.       DoSource(textstruct);
  954.     }
  955.     else do_other_thing(textstruct, type);
  956.   }
  957. }
  958.  
  959. static void PopupTypeMenu(w, doc)
  960. Widget w;
  961. DocumentID doc;
  962. {
  963.   char** types = doc->doc->type;
  964.   int i;
  965.   Arg        args[5];
  966.   Position    x, y;
  967.   Dimension    width, height;
  968.   Cardinal    n;
  969.  
  970.   n = 0;
  971.   XtSetArg(args[0], XtNwidth, &width); n++;
  972.   XtSetArg(args[1], XtNheight, &height); n++;
  973.   XtGetValues(w, args, n);
  974.   XtTranslateCoords(w, (Position) 0, (Position)height,
  975.             &x, &y);
  976.  
  977.   n = 0;
  978.   XtSetArg(args[n], XtNx, x); n++;
  979.   XtSetArg(args[n], XtNy, y); n++;
  980.  
  981.   XtSetValues(typeshell, args, n);
  982.  
  983.   for(i = 0; types[i] != NULL; i++)
  984.     Type_items[i] = types[i];
  985.  
  986.   RebuildListWidget(typewindow, Type_items);
  987.  
  988.   XtPopup(typeshell, XtGrabExclusive);
  989. }  
  990.  
  991. void doType(w, closure, call_data)
  992. Widget w;
  993. XtPointer closure, call_data;
  994. {
  995.   long tnum, dnum, size = -1;
  996.   DocumentID doc;
  997.   
  998.   if((tnum = get_selected_type()) != NO_ITEM_SELECTED) {
  999.     XtPopdown(typeshell);
  1000.     dnum = get_selected_response(the_Question);
  1001.     if((doc = findDoc(the_Question->q->ResultDocuments, dnum)) != NULL)
  1002.       ViewDoc(doc, Type_items[tnum], size, false);
  1003.   }
  1004.   else
  1005.     XtPopdown(typeshell);
  1006. }
  1007.  
  1008. /* ARGSUSED */
  1009. void
  1010. ViewResponse(w, closure, call_data)
  1011. Widget w;
  1012. XtPointer closure, call_data;
  1013. {
  1014.   Arg args[2];
  1015.   static int document_number;
  1016.   Question q = the_Question->q;
  1017.   QuestionWindow qw = the_Question->window;
  1018.   DocumentID doc;
  1019.   Boolean savep;
  1020.  
  1021.   double_click = FALSE;
  1022.   LastClicked = w;
  1023.  
  1024.   if(busy) return;
  1025.  
  1026.   if(w == saveAsButton) 
  1027.     savep = true;
  1028.   else
  1029.     savep = false;
  1030.  
  1031.   document_number = get_selected_response(the_Question);
  1032.  
  1033.   if(document_number == NO_ITEM_SELECTED) {
  1034.     PrintStatusW("\nNo selected response.  Select one and try again.",
  1035.         qw->StatusWindow);
  1036.     return;
  1037.   }
  1038.  
  1039.   if((doc = findDoc(q->ResultDocuments, document_number)) == NULL) {
  1040.     PrintStatusW("\nUnable to find document.  This should not happen.",
  1041.         qw->StatusWindow);
  1042.     return;
  1043.   }
  1044.  
  1045.   if (document_number != last_doc) {
  1046.     XtSetArg(args[0], XtNsensitive, True);
  1047.     if((w != viewbutton) && (doc->doc->type[1] != NULL)) {
  1048.       XtSetArg(args[1], XtNlabel, "View...");
  1049.     }
  1050.     else {
  1051.       XtSetArg(args[1], XtNlabel, " View  ");
  1052.     }
  1053.     XtSetValues(viewbutton, args, TWO);
  1054.     XtSetValues(saveAsButton, args, ONE);
  1055.     last_doc = document_number;
  1056.     return;
  1057.   }
  1058.  
  1059.   if((w == viewbutton) && (doc->doc->type[1] != NULL)) {
  1060.     PopupTypeMenu(w, doc);
  1061.   }
  1062.   else ViewDoc(doc, doc->doc->type[0], 0, savep);
  1063. }
  1064.  
  1065. /* ARGSUSED */
  1066. void
  1067. ViewRelevant(w, closure, call_data)
  1068. Widget w;
  1069. XtPointer closure, call_data;
  1070. {
  1071.   int document_number;
  1072.   Question q = the_Question->q;
  1073.   QuestionWindow qw = the_Question->window;
  1074.   DocumentID doc;
  1075.  
  1076.   double_click = FALSE;
  1077.   LastClicked = w;
  1078.  
  1079.   if(busy) return;
  1080.  
  1081.   document_number = get_selected_qdoc(the_Question);
  1082.  
  1083.   if(document_number == NO_ITEM_SELECTED) {
  1084.     PrintStatusW("\nNo selected response.  Select one and try again.",
  1085.         qw->StatusWindow);
  1086.     return;
  1087.   }
  1088.  
  1089.   if((doc = findDoc(q->RelevantDocuments, document_number)) == NULL) {
  1090.     PrintStatusW("\nUnable to find document.  This should not happen.",
  1091.         qw->StatusWindow);
  1092.     return;
  1093.   }
  1094.  
  1095.   if (document_number != last_qdoc) {
  1096.     last_qdoc = document_number;
  1097.     return;
  1098.   }
  1099.  
  1100.   ViewDoc(doc, doc->doc->type[0], 0, false);
  1101. }
  1102.  
  1103. void
  1104. EndText(w, closure, call_data)
  1105. Widget w;
  1106. XtPointer closure, call_data;
  1107. {
  1108.   Textbuff t;
  1109.  
  1110.   t = findText(w);
  1111.  
  1112.   if(t != NULL) {
  1113.     XtPopdown(t->shell);
  1114.     KillText(t);
  1115.   }
  1116. }
  1117. static Widget helpwindow = NULL;
  1118.  
  1119. void EndHelp(w, closure, call_data)
  1120. Widget w;
  1121. XtPointer closure, call_data;
  1122. {
  1123.   XtPopdown(helpwindow);
  1124. }
  1125.  
  1126. void XwaisHelp(w, closure, call_data)
  1127. Widget w;
  1128. XtPointer closure, call_data;
  1129. {
  1130.   Widget textwindow, frame, button;
  1131.   Arg arglist[10];
  1132.   Cardinal num_args;
  1133.   static String items[] = {NULL};
  1134.  
  1135.   if (helpwindow == NULL) {
  1136.     num_args = 0;
  1137.     XtSetArg(arglist[num_args], XtNtitle, "X WAIS Help"); num_args++;
  1138.     XtSetArg(arglist[num_args], XtNiconName, "X WAIS Help"); num_args++;
  1139.     helpwindow = XtCreatePopupShell("textpopup", applicationShellWidgetClass,
  1140.                     XtParent(w), arglist, num_args);
  1141.     frame =
  1142.       XtCreateManagedWidget("helppopupform", formWidgetClass,
  1143.                 helpwindow, NULL, ZERO);
  1144.     num_args = 0;
  1145.     XtSetArg(arglist[num_args], XtNtype, XawAsciiFile); num_args++;
  1146.     XtSetArg(arglist[num_args], XtNstring, app_resources.helpFile); num_args++;
  1147.     XtSetArg(arglist[num_args], XtNeditType, XawtextRead); num_args++;
  1148.     textwindow =
  1149.       XtCreateManagedWidget("textWindow", asciiTextWidgetClass, frame, arglist, num_args);
  1150.     button = MakeCommandButton(frame, "tdone", EndHelp,
  1151.                    textwindow, NULL, NULL);
  1152.     SettIcon(helpwindow);
  1153.   }
  1154.   XtPopup(helpwindow, XtGrabNone);
  1155. }
  1156.  
  1157. #include <X11/Xaw/TextP.h>
  1158.  
  1159.  
  1160. static XawTextPosition
  1161. findstring(text, string, casesensitive)
  1162. char *text, *string;
  1163. Boolean casesensitive;
  1164. {
  1165.   char *t, *t2, *t3;
  1166.  
  1167.   if (casesensitive) {
  1168.     for (t = text; *t != 0; t++) {
  1169.       if (*t == *string) {
  1170.     t2 = t;
  1171.     t3 = string;
  1172.     do {
  1173.       t2++;
  1174.       t3++;
  1175.       if(*t3 == 0) return((XawTextPosition)(t-text));
  1176.     }
  1177.     while(*t2 == *t3);
  1178.       }
  1179.     }
  1180.     return -1;
  1181.   }
  1182.   else {
  1183.     for (t = text; *t != 0; t++) {
  1184.       if (tolower(*t) == tolower(*string)) {
  1185.     t2 = t;
  1186.     t3 = string;
  1187.     do {
  1188.       t2++;
  1189.       t3++;
  1190.       if(*t3 == 0) return((XawTextPosition)(t-text));
  1191.     }
  1192.     while(tolower(*t2) == tolower(*t3));
  1193.       }
  1194.     }
  1195.     return -1;
  1196.   }
  1197. }
  1198.  
  1199. /* ARGSUSED */
  1200. void
  1201. showKeyword(w, closure, call_data)
  1202. Widget w;
  1203. XtPointer closure, call_data;
  1204. {
  1205.   Question q = the_Question->q;
  1206.   QuestionWindow qw = the_Question->window;
  1207.   Textbuff t;
  1208.   static char msg[STRINGSIZE], str[STRINGSIZE], minstr[STRINGSIZE], *keys;
  1209.   Widget tw;
  1210.   XawTextPosition minpos, pos, pos2, offset;
  1211.   XawTextBlock text;
  1212.   int i, j, k;
  1213.   char c1, c2;
  1214.  
  1215.   if((t = findText(w)) == NULL) {
  1216.     XwaisPrintf("couldn't find text.\n");
  1217.     return;
  1218.   }
  1219.  
  1220.   keys = q->keywords;
  1221.   tw = t->textwindow;
  1222.  
  1223.   minpos = 999999;
  1224.   minstr[0] = 0;
  1225.  
  1226.   sprintf(msg, "\nSearching for next keyword...");
  1227.   PrintStatusW(msg, t->status);
  1228.  
  1229.   /* parse the keywords into individual words */
  1230.   for(j = 0, i = 0; i <= strlen(keys); i++) {
  1231.     str[j] = keys[i];
  1232.     if ((keys[i] == 0) || (keys[i] == ' ') || (keys[i] == '\n')) {
  1233.       str[j] = 0;
  1234.       j = 0;
  1235.  
  1236.       text.ptr = str;
  1237.       text.length = strlen(str);
  1238.       text.firstPos = 0;
  1239.       text.format = FMT8BIT;
  1240.       
  1241.       for(offset = XawTextGetInsertionPoint(tw), 
  1242.       pos = findstring(t->text+offset, str, FALSE);
  1243.       pos > 0;
  1244.       offset=pos+1, 
  1245.       pos = findstring(t->text+offset, str, FALSE)) {
  1246.     pos+=offset;
  1247.     c1 = t->text[pos-1];
  1248.     c2 = t->text[pos+text.length];
  1249.     if((isspace(c1) || ispunct(c1)) &&
  1250.        (isspace(c2) || ispunct(c2))) {
  1251.       if (pos < minpos) {
  1252.         minpos = pos;
  1253.         strcpy(minstr, str);
  1254.         break;
  1255.       }
  1256.     }
  1257.       }
  1258.     }
  1259.     else
  1260.       j++;
  1261.   }
  1262.  
  1263.   if (minpos == 999999) {
  1264.     sprintf( msg, "\nCould not find any more keywords.");
  1265.     XawTextUnsetSelection(tw);
  1266.     PrintStatusW(msg, t->status);
  1267.     return;
  1268.   }
  1269.   else {
  1270.     XawTextSetInsertionPoint( tw, minpos + strlen(minstr));
  1271.     sprintf(msg, "\nSearching for next keyword...done");
  1272.     PrintStatusW(msg, t->status);
  1273.     XawTextSetSelection( tw, minpos, minpos + strlen(minstr));
  1274.     return;
  1275.   }
  1276. }
  1277.  
  1278. void
  1279. SaveText(w, closure, call_data)
  1280. Widget w;
  1281. XtPointer closure, call_data;
  1282. {
  1283.   Arg        args[5];
  1284.   Position    x, y;
  1285.   Dimension    width, height;
  1286.   Cardinal    n;
  1287.   Textbuff t;
  1288.  
  1289.   if((t = findText(w)) == NULL) {
  1290.     XwaisPrintf("couldn't find text.\n");
  1291.     return;
  1292.   }
  1293.  
  1294.   n = 0;
  1295.   XtSetArg(args[0], XtNwidth, &width); n++;
  1296.   XtSetArg(args[1], XtNheight, &height); n++;
  1297.   XtGetValues(t->textwindow, args, n);
  1298.   XtTranslateCoords(t->textwindow, (Position) (width / 2), (Position) (height / 2),
  1299.             &x, &y);
  1300.  
  1301.   n = 0;
  1302.   XtSetArg(args[n], XtNx, MAX(x-150, 0));        n++;
  1303.   XtSetArg(args[n], XtNy, y);                n++;
  1304.  
  1305.   current_text = t;
  1306.  
  1307.   if(savelist == NULL)
  1308.     savelist = MakeSaveRequester(top);
  1309.   
  1310.   XtSetValues(savereq, args, n);
  1311.  
  1312.   ReplaceText(filenamewidget, "");
  1313.   ReplaceText(dirnamewidget, app_resources.documentDirectory);
  1314.   SetDir(NULL, NULL, NULL);
  1315.   save_question = FALSE;
  1316.  
  1317.   XtPopup(savereq, XtGrabNone);
  1318.   clearReqButtons();
  1319.  
  1320.   XtRemoveAllCallbacks(savebutton, XtNcallback);
  1321.   XtAddCallback(savebutton, XtNcallback, DoTSaveCB, t);
  1322. }
  1323.  
  1324. void
  1325. DoSave(w, closure, call_data)
  1326. Widget w;
  1327. XtPointer closure, call_data;
  1328. {
  1329.   FILE *fp;
  1330.   char message[STRINGSIZE], filename[STRINGSIZE];
  1331.   Arg arglist[10];
  1332.   Cardinal num_args;
  1333.  
  1334.   XtPopdown(savereq);
  1335.   clearReqButtons();
  1336.  
  1337.   if(save_question) {
  1338.     strncpy(the_Question->q->name, GetString(filenamewidget), STRINGSIZE);
  1339.     sprintf(filename, "%s/%s",
  1340.         GetString(dirnamewidget), the_Question->q->name);
  1341.  
  1342.     WriteQuestion(filename, the_Question->q);
  1343.     if(quit)
  1344.       exit(0);
  1345.     else {
  1346.       char name[STRINGSIZE];
  1347.       num_args = 0;
  1348.       sprintf(name, "X WAIS Question: %s",  the_Question->q->name);
  1349.       XtSetArg(arglist[num_args], XtNtitle, name); num_args++;
  1350.       XtSetArg(arglist[num_args], XtNiconName, the_Question->q->name); num_args++;
  1351.       XtSetValues(top, arglist, num_args);
  1352.     }
  1353.   }
  1354.   else {
  1355.     DoTSave(w, closure, call_data);
  1356.   }
  1357. }
  1358.  
  1359. void
  1360. DontSave(w, closure, call_data)
  1361. Widget w;
  1362. XtPointer closure, call_data;
  1363. {
  1364.   XtPopdown(savereq);
  1365.   clearReqButtons();
  1366.  
  1367.   if(quit)
  1368.     exit(0);
  1369. }
  1370.  
  1371. void
  1372. DoTSave(w, closure, call_data)
  1373. Widget w;
  1374. XtPointer closure, call_data;
  1375. {
  1376.   DoTSaveCB(w, (XtPointer)current_text, NULL);
  1377. }
  1378.  
  1379. static void
  1380. DoTSaveCB(w, closure, call_data)
  1381. Widget w;
  1382. XtPointer closure, call_data;
  1383. {
  1384.   FILE *fp;
  1385.   char message[STRINGSIZE], filename[STRINGSIZE];
  1386.  
  1387.   Textbuff t = (Textbuff) closure;
  1388.  
  1389.   strncpy(filename, GetString(filenamewidget), STRINGSIZE);
  1390.  
  1391.   if(filename[0]==0) {
  1392.     PrintStatusW("\nYou have to enter a filename.",
  1393.         the_Question->window->StatusWindow);
  1394.     return;
  1395.   }
  1396.   
  1397.   XtPopdown(savereq);
  1398.   clearReqButtons();
  1399.  
  1400.   if (filename[0] != '/') {
  1401.     if(t->type != NULL &&
  1402.        !strcmp(t->type, "WSRC"))
  1403.        sprintf(message, "%s%s", app_resources.userSourceDirectory, filename);
  1404.     else    
  1405.       sprintf(message, "%s%s", GetString(dirnamewidget), filename);
  1406.     strcpy(filename, message);
  1407.   }
  1408.  
  1409.   if((fp = fopen(filename, "w")) == NULL) {
  1410.     sprintf(message, "\nUnable to save %s.", filename);
  1411.     PrintStatusW(message, the_Question->window->StatusWindow);
  1412.   }
  1413.   else {
  1414.     dumptext(fp, t->text, t->size);
  1415.     fclose(fp);
  1416.   }
  1417.   if(t->type != NULL && strcmp(t->type, "TEXT") != 0)
  1418.     KillText(t);
  1419. }
  1420.  
  1421. void
  1422. DontTSave(w, closure, call_data)
  1423. Widget w;
  1424. XtPointer closure, call_data;
  1425. {
  1426.   XtPopdown(savereq);
  1427.   clearReqButtons();
  1428. }
  1429.  
  1430. void
  1431. setSourceMenu()
  1432. {
  1433.   /*
  1434.   SList s;
  1435.   Widget entry;
  1436.  
  1437.   if(sourcemenu) 
  1438.     XtDestroyWidget(sourcemenu);
  1439.  
  1440.   sourcemenu = XtCreatePopupShell("menu", simpleMenuWidgetClass, sourcebutton, 
  1441.                   NULL, ZERO);
  1442.     
  1443.   for (s = Sources; s != NULL; s = s->nextSource) {
  1444.     char * item = s->thisSource->name;
  1445.     
  1446.     entry = XtCreateManagedWidget(item, smeBSBObjectClass, sourcemenu,
  1447.                       NULL, ZERO);
  1448.     XtAddCallback(entry, XtNcallback, AddSourceToQuestion, NULL);
  1449.   }
  1450.   */
  1451. }
  1452.  
  1453. void
  1454. addSection(w, closure, call_data)
  1455. Widget w;
  1456. XtPointer closure, call_data;
  1457. {
  1458.   int i;
  1459.   Question q = the_Question->q;
  1460.   QuestionWindow qw = the_Question->window;
  1461.   float top, shown;
  1462.   DocList dlist;
  1463.   DocumentID doc;
  1464.   XawTextPosition p1, p2;
  1465.   long l1, l2;
  1466.   Textbuff t;
  1467.  
  1468.   t = findText(w);
  1469.   
  1470.   XawTextGetSelectionPos(t->textwindow, &p1, &p2);
  1471.  
  1472.   if(p1 >= 0 && p2 > 0) {
  1473.     /* find the line positions */
  1474.     l1 = GetLineFromPos(t->text, p1);
  1475.     l2 = GetLineFromPos(t->text, p2);
  1476.  
  1477.     doc = copy_docid(t->docid);
  1478.     doc->start = l1;
  1479.     doc->end = l2;
  1480.     dlist = makeDocList(doc, NULL);
  1481.     /* append it to the current rellist */
  1482.   
  1483.     if(q->RelevantDocuments != NULL) {
  1484.       DocList doc;
  1485.  
  1486.       for(doc = q->RelevantDocuments; doc->nextDoc != NULL; doc = doc->nextDoc);
  1487.       doc->nextDoc = dlist;
  1488.     }
  1489.     else
  1490.       q->RelevantDocuments = dlist;
  1491.  
  1492.     if(the_Question->Relevant_Items != NULL)
  1493.       freeItemList(the_Question->Relevant_Items);
  1494.     the_Question->Relevant_Items = 
  1495.       buildDocumentItemList(q->RelevantDocuments, FALSE);
  1496.     q->numdocs = charlistlength(the_Question->Relevant_Items);
  1497.  
  1498.     RebuildListWidget(qw->RelevantDocuments, the_Question->Relevant_Items);
  1499.   }
  1500. }
  1501.  
  1502. void
  1503. DoSSave(w, closure, call_data)
  1504. Widget w;
  1505. XtPointer closure, call_data;
  1506. {
  1507.   FILE *fp;
  1508.   char name[STRINGSIZE];
  1509.   Source source;
  1510.   SList current_sources;
  1511.  
  1512.   source = the_Source;
  1513.  
  1514.   XtPopdown(sourcepopup);
  1515.  
  1516.   strcpy(name, GetString(snamewid));
  1517.  
  1518.   if(!((strlen(name) > 4) && 
  1519.        strstr(name, ".src") &&
  1520.        (!strcmp(".src", strstr(name, ".src")))))
  1521.     strcat(name, ".src");
  1522.  
  1523.   if(source->name != NULL) s_free(source->name);
  1524.   source->name = s_strdup(name);
  1525.  
  1526.   if (source->maintainer != NULL) s_free(source->maintainer);
  1527.   source->maintainer = s_strdup(GetString(maintainerwid));
  1528.  
  1529.   if (source->description != NULL) s_free(source->description);
  1530.   source->description = s_strdup(GetString(descwid));
  1531.  
  1532.   strncpy(source->server, GetString(serverwid), STRINGSIZE);
  1533.   strncpy(source->service, GetString(servicewid), STRINGSIZE);
  1534.   strncpy(source->database, GetString(dbwid), STRINGSIZE);
  1535.   strncpy(source->cost, GetString(costwid), STRINGSIZE);
  1536.   strncpy(source->units, GetString(unitwid), STRINGSIZE);
  1537.  
  1538.   WriteSource(app_resources.userSourceDirectory, source, TRUE);
  1539.  
  1540.   NumSources = 0;
  1541.  
  1542.   GetSourceNames(app_resources.userSourceDirectory);
  1543.   if(app_resources.commonSourceDirectory[0] != 0)
  1544.     GetSourceNames(app_resources.commonSourceDirectory);
  1545.  
  1546.   RebuildListWidget(sourcewindow, Source_items);
  1547. }
  1548.  
  1549. void
  1550. DontSSave(w, closure, call_data)
  1551. Widget w;
  1552. XtPointer closure, call_data;
  1553. {
  1554.   XtPopdown(sourcepopup);
  1555. }
  1556.  
  1557. void showNext(w, closure, call_data)
  1558. Widget w;
  1559. XtPointer closure, call_data;
  1560. {
  1561.   Textbuff t;
  1562.   DocumentID d;
  1563.   Source source;
  1564.   Question q = the_Question->q;
  1565.  
  1566.   t = findText(w);
  1567.   if(t != NULL) {
  1568.     if(t->docid->doc != NULL &&
  1569.        t->docid->doc->sourceID != NULL &&
  1570.        t->docid->doc->sourceID->filename != NULL)
  1571.       source = findsource(t->docid->doc->sourceID->filename);
  1572.     
  1573.     if (source == NULL) {
  1574.       PrintStatusW("\nCould not find Source for this document!",
  1575.            t->status);
  1576.       return;
  1577.     }
  1578.  
  1579.     if((d = getNextorPrevDoc(q, source, t->docid, TRUE)) != NULL)
  1580.       ViewDoc(d, d->doc->type[0], 0, false);
  1581.     else
  1582.       PrintStatusW("\nCould not get next document.", t->status);
  1583.   }
  1584. }
  1585.  
  1586. void showPrevious(w, closure, call_data)
  1587. Widget w;
  1588. XtPointer closure, call_data;
  1589. {
  1590.   Textbuff t;
  1591.   DocumentID d;
  1592.   Source source;
  1593.  
  1594.   t = findText(w);
  1595.   if(t != NULL) {
  1596.     if(t->docid->doc != NULL &&
  1597.        t->docid->doc->sourceID != NULL &&
  1598.        t->docid->doc->sourceID->filename != NULL)
  1599.       source = findsource(t->docid->doc->sourceID->filename);
  1600.     
  1601.     if (source == NULL) {
  1602.       PrintStatusW("\nCould not find Source for this document!",
  1603.            t->status);
  1604.       return;
  1605.     }
  1606.  
  1607.     if((d = getNextorPrevDoc(the_Question->q, source, t->docid, FALSE))
  1608.        != NULL)
  1609.       ViewDoc(d, d->doc->type[0], 0, false);
  1610.     else
  1611.       PrintStatusW("\nCould not get previous document.", t->status);
  1612.   }
  1613. }
  1614.  
  1615. void setFile(w, closure, call_data)
  1616. Widget w;
  1617. XtPointer closure, call_data;
  1618. {
  1619.   XtPopdown(savereq);
  1620.   clearReqButtons();
  1621. }
  1622.  
  1623. void quitFile(w, closure, call_data)
  1624. Widget w;
  1625. XtPointer closure, call_data;
  1626. {
  1627.   XtPopdown(savereq);
  1628.   clearReqButtons();
  1629. }
  1630.