home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / s / stex2-18.zip / SeeTeX / Xtex / SelFile.c < prev    next >
C/C++ Source or Header  |  1992-05-05  |  21KB  |  751 lines

  1. /*
  2.  * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and its
  5.  * documentation for any purpose and without fee is hereby granted, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Software Research Associates not be used
  9.  * in advertising or publicity pertaining to distribution of the software
  10.  * without specific, written prior permission.  Software Research Associates
  11.  * makes no representations about the suitability of this software for any
  12.  * purpose.  It is provided "as is" without express or implied warranty.
  13.  *
  14.  * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  15.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  16.  * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
  17.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  18.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  19.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20.  * PERFORMANCE OF THIS SOFTWARE.
  21.  *
  22.  * Author: Erik M. van der Poel
  23.  *         Software Research Associates, Inc., Tokyo, Japan
  24.  *         erik@sra.co.jp
  25.  */
  26.  
  27. /*
  28.  * Author's address:
  29.  *
  30.  *     erik@sra.co.jp
  31.  *                                            OR
  32.  *     erik%sra.co.jp@uunet.uu.net
  33.  *                                            OR
  34.  *     erik%sra.co.jp@mcvax.uucp
  35.  *                                            OR
  36.  *     try junet instead of co.jp
  37.  *                                            OR
  38.  *     Erik M. van der Poel
  39.  *     Software Research Associates, Inc.
  40.  *     1-1-1 Hirakawa-cho, Chiyoda-ku
  41.  *     Tokyo 102 Japan. TEL +81-3-234-2692
  42.  */
  43.  
  44. #include <stdio.h>
  45. #include <errno.h>
  46. /* BSD 4.3 errno.h does not declare errno */
  47. extern int errno;
  48. extern int sys_nerr;
  49. extern char *sys_errlist[];
  50.  
  51. #include <sys/param.h>
  52. #include <X11/cursorfont.h>
  53. #include <X11/Intrinsic.h>
  54. #include <X11/StringDefs.h>
  55. #include <X11/Composite.h>
  56. #include <X11/Shell.h>
  57. #include <X11/Xaw/Form.h>
  58. #include <X11/Xaw/Command.h>
  59. #include <X11/Xaw/Scrollbar.h>
  60. #include <X11/Xaw/Label.h>
  61.  
  62. #include "SFinternal.h"
  63.  
  64. #ifndef MAXPATHLEN
  65. #define MAXPATHLEN 1024
  66. #endif /* ndef MAXPATHLEN */
  67.  
  68. #if !defined(SYSV) && !defined(USG)
  69. extern char *getwd();
  70. #endif /* !defined(SYSV) && !defined(USG) */
  71.  
  72. int SFstatus = SEL_FILE_NULL;
  73.  
  74. char
  75.     SFstartDir[MAXPATHLEN],
  76.     SFcurrentPath[MAXPATHLEN],
  77.     SFcurrentDir[MAXPATHLEN];
  78.  
  79. Widget
  80.     selFile,
  81.     selFileCancel,
  82.     selFileField,
  83.     selFileForm,
  84.     selFileHScroll,
  85.     selFileHScrolls[3],
  86.     selFileLists[3],
  87.     selFileOK,
  88.     selFilePrompt,
  89.     selFileVScrolls[3];
  90.  
  91. Display *SFdisplay;
  92.  
  93. Pixel SFfore, SFback;
  94.  
  95. Atom    SFwmDeleteWindow;
  96.  
  97. XSegment SFsegs[2], SFcompletionSegs[2];
  98.  
  99. XawTextPosition SFtextPos;
  100.  
  101. int SFupperX, SFlowerY, SFupperY;
  102.  
  103. int SFtextX, SFtextYoffset;
  104.  
  105. int SFentryWidth, SFentryHeight;
  106.  
  107. int SFlineToTextH = 3;
  108.  
  109. int SFlineToTextV = 3;
  110.  
  111. int SFbesideText = 3;
  112.  
  113. int SFaboveAndBelowText = 2;
  114.  
  115. int SFcharsPerEntry = 15;
  116.  
  117. int SFlistSize = 10;
  118.  
  119. int SFworkProcAdded = 0;
  120.  
  121. XtAppContext SFapp;
  122.  
  123. int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth;
  124.  
  125. char SFtextBuffer[MAXPATHLEN];
  126.  
  127. XtIntervalId SFdirModTimerId;
  128.  
  129. int (*SFfunc)();
  130.  
  131. static char *oneLineTextEditTranslations = "\
  132.     <Key>Return:    redraw-display()\n\
  133.     Ctrl<Key>M:    redraw-display()\n\
  134. ";
  135.  
  136. /* ARGSUSED */
  137. static void
  138. SFexposeList(w, n, event)
  139.     Widget        w;
  140.     int        n;
  141.     XExposeEvent    *event;
  142. {
  143.     if ((event->type == NoExpose) || event->count) {
  144.         return;
  145.     }
  146.  
  147.     SFdrawList(n, SF_DO_NOT_SCROLL);
  148. }
  149.  
  150. /* ARGSUSED */
  151. static void
  152. SFmodVerifyCallback(w, client_data, event)
  153.     Widget            w;
  154.     XtPointer        client_data;
  155.     XKeyPressedEvent    *event;
  156. {
  157.     char    buf[2];
  158.  
  159.     if (
  160.         (XLookupString(event, buf, 2, NULL, NULL) == 1) &&
  161.         ((*buf) == '\r')
  162.     ) {
  163.         SFstatus = SEL_FILE_OK;
  164.     } else {
  165.         SFstatus = SEL_FILE_TEXT;
  166.     }
  167. }
  168.  
  169. /* ARGSUSED */
  170. static void
  171. SFokCallback(w)
  172.     Widget    w;
  173. {
  174.     SFstatus = SEL_FILE_OK;
  175. }
  176.  
  177. static XtCallbackRec SFokSelect[] = {
  178.     { SFokCallback, (XtPointer) NULL },
  179.     { NULL, (XtPointer) NULL },
  180. };
  181.  
  182. /* ARGSUSED */
  183. static void
  184. SFcancelCallback(w)
  185.     Widget    w;
  186. {
  187.     SFstatus = SEL_FILE_CANCEL;
  188. }
  189.  
  190. static XtCallbackRec SFcancelSelect[] = {
  191.     { SFcancelCallback, (XtPointer) NULL },
  192.     { NULL, (XtPointer) NULL },
  193. };
  194.  
  195. /* ARGSUSED */
  196. static void
  197. SFdismissAction(w, event, params, num_params)
  198.     Widget    w;
  199.     XEvent *event;
  200.     String *params;
  201.     Cardinal *num_params;
  202. {
  203.     if (event->type == ClientMessage &&
  204.         event->xclient.data.l[0] != SFwmDeleteWindow) return;
  205.  
  206.     SFstatus = SEL_FILE_CANCEL;
  207. }
  208.  
  209. static char *wmDeleteWindowTranslation = "\
  210.     <Message>WM_PROTOCOLS:    SelFileDismiss()\n\
  211. ";
  212.  
  213. static XtActionsRec actions[] = {
  214.     {"SelFileDismiss",    SFdismissAction},
  215. };
  216.  
  217. static void
  218. SFcreateWidgets(toplevel, prompt, ok, cancel)
  219.     Widget    toplevel;
  220.     char    *prompt;
  221.     char    *ok;
  222.     char    *cancel;
  223. {
  224.     int        i, n;
  225.     int        listWidth, listHeight;
  226.     int        listSpacing = 10;
  227.     int        scrollThickness = 15;
  228.     int        hScrollX, hScrollY;
  229.     int        vScrollX, vScrollY;
  230.     Cursor
  231.             xtermCursor,
  232.             sbRightArrowCursor,
  233.             dotCursor;
  234.     Arg        arglist[20];
  235.  
  236.     i = 0;
  237.     XtSetArg(arglist[i], XtNallowShellResize, True);        i++;
  238.     XtSetArg(arglist[i], XtNinput, True);                i++;
  239.     XtSetArg(arglist[i], XtNtransientFor, toplevel);        i++;
  240.  
  241.     selFile = XtAppCreateShell("selFile", "SelFile",
  242.         transientShellWidgetClass, SFdisplay, arglist, i);
  243.  
  244.     /* Add WM_DELETE_WINDOW protocol */
  245.     XtAppAddActions(XtWidgetToApplicationContext(selFile),
  246.         actions, XtNumber(actions));
  247.     XtOverrideTranslations(selFile,
  248.         XtParseTranslationTable(wmDeleteWindowTranslation));
  249.  
  250.     i = 0;
  251.     XtSetArg(arglist[i], XtNdefaultDistance, 30);            i++;
  252.     selFileForm = XtCreateManagedWidget("selFileForm",
  253.         formWidgetClass, selFile, arglist, i);
  254.  
  255.     i = 0;
  256.     XtSetArg(arglist[i], XtNlabel, prompt);                i++;
  257.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  258.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  259.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  260.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  261.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  262.     XtSetArg(arglist[i], XtNborderWidth, 0);            i++;
  263.     selFilePrompt = XtCreateManagedWidget("selFilePrompt",
  264.         labelWidgetClass, selFileForm, arglist, i);
  265.  
  266.     i = 0;
  267.     XtSetArg(arglist[i], XtNforeground, &SFfore);            i++;
  268.     XtSetArg(arglist[i], XtNbackground, &SFback);            i++;
  269.     XtGetValues(selFilePrompt, arglist, i);
  270.  
  271.     SFinitFont();
  272.  
  273.     SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth +
  274.             SFbesideText;
  275.     SFentryHeight = SFaboveAndBelowText + SFcharHeight +
  276.             SFaboveAndBelowText;
  277.  
  278.     listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 +
  279.             scrollThickness;
  280.     listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  281.             SFlineToTextV + SFlistSize * SFentryHeight +
  282.             SFlineToTextV + 1 + scrollThickness;
  283.  
  284.     SFpathScrollWidth = 3 * listWidth + 2 * listSpacing + 4;
  285.  
  286.     hScrollX = -1;
  287.     hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  288.             SFlineToTextV + SFlistSize * SFentryHeight +
  289.             SFlineToTextV;
  290.     SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;
  291.  
  292.     vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
  293.     vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
  294.     SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight +
  295.             SFlineToTextV;
  296.  
  297.     SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
  298.     SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  299.             SFlineToTextV;
  300.     SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  301.             SFlineToTextV + SFlistSize * SFentryHeight - 1;
  302.  
  303.     SFtextX = SFlineToTextH + SFbesideText;
  304.     SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;
  305.  
  306.     SFsegs[0].x1 = 0;
  307.     SFsegs[0].y1 = vScrollY;
  308.     SFsegs[0].x2 = vScrollX - 1;
  309.     SFsegs[0].y2 = vScrollY;
  310.     SFsegs[1].x1 = vScrollX;
  311.     SFsegs[1].y1 = 0;
  312.     SFsegs[1].x2 = vScrollX;
  313.     SFsegs[1].y2 = vScrollY - 1;
  314.  
  315.     SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
  316.     SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
  317.         SFlineToTextH + SFentryWidth - 1;
  318.  
  319.     i = 0;
  320.     XtSetArg(arglist[i], XtNwidth, 3 * listWidth + 2 * listSpacing + 4);
  321.                                     i++;
  322.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  323.  
  324.     XtSetArg(arglist[i], XtNfromVert, selFilePrompt);        i++;
  325.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  326.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  327.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  328.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  329.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  330.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  331.     XtSetArg(arglist[i], XtNstring, SFtextBuffer);            i++;
  332.     XtSetArg(arglist[i], XtNlength, MAXPATHLEN);            i++;
  333.     XtSetArg(arglist[i], XtNeditType, XawtextEdit);            i++;
  334.     XtSetArg(arglist[i], XtNwrap, XawtextWrapWord);            i++;
  335.     XtSetArg(arglist[i], XtNresize, XawtextResizeHeight);        i++;
  336.     XtSetArg(arglist[i], XtNuseStringInPlace, True);        i++;
  337.     selFileField = XtCreateManagedWidget("selFileField",
  338.         asciiTextWidgetClass, selFileForm, arglist, i);
  339.  
  340.     XtOverrideTranslations(selFileField,
  341.         XtParseTranslationTable(oneLineTextEditTranslations));
  342.     XtSetKeyboardFocus(selFileForm, selFileField);
  343.  
  344.     i = 0;
  345.     XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);    i++;
  346.     XtSetArg(arglist[i], XtNwidth, SFpathScrollWidth);        i++;
  347.     XtSetArg(arglist[i], XtNheight, scrollThickness);        i++;
  348.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  349.     XtSetArg(arglist[i], XtNfromVert, selFileField);        i++;
  350.     XtSetArg(arglist[i], XtNvertDistance, 30);            i++;
  351.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  352.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  353.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  354.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  355.     selFileHScroll = XtCreateManagedWidget("selFileHScroll",
  356.         scrollbarWidgetClass, selFileForm, arglist, i);
  357.  
  358.     XtAddCallback(selFileHScroll, XtNjumpProc,
  359.         SFpathSliderMovedCallback, (XtPointer) NULL);
  360.     XtAddCallback(selFileHScroll, XtNscrollProc,
  361.         SFpathAreaSelectedCallback, (XtPointer) NULL);
  362.  
  363.     i = 0;
  364.     XtSetArg(arglist[i], XtNwidth, listWidth);            i++;
  365.     XtSetArg(arglist[i], XtNheight, listHeight);            i++;
  366.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  367.     XtSetArg(arglist[i], XtNfromVert, selFileHScroll);        i++;
  368.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  369.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  370.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  371.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  372.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  373.     selFileLists[0] = XtCreateManagedWidget("selFileList1",
  374.         compositeWidgetClass, selFileForm, arglist, i);
  375.  
  376.     i = 0;
  377.     XtSetArg(arglist[i], XtNwidth, listWidth);            i++;
  378.     XtSetArg(arglist[i], XtNheight, listHeight);            i++;
  379.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  380.     XtSetArg(arglist[i], XtNfromHoriz, selFileLists[0]);        i++;
  381.     XtSetArg(arglist[i], XtNfromVert, selFileHScroll);        i++;
  382.     XtSetArg(arglist[i], XtNhorizDistance, listSpacing);        i++;
  383.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  384.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  385.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  386.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  387.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  388.     selFileLists[1] = XtCreateManagedWidget("selFileList2",
  389.         compositeWidgetClass, selFileForm, arglist, i);
  390.  
  391.     i = 0;
  392.     XtSetArg(arglist[i], XtNwidth, listWidth);            i++;
  393.     XtSetArg(arglist[i], XtNheight, listHeight);            i++;
  394.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  395.     XtSetArg(arglist[i], XtNfromHoriz, selFileLists[1]);        i++;
  396.     XtSetArg(arglist[i], XtNfromVert, selFileHScroll);        i++;
  397.     XtSetArg(arglist[i], XtNhorizDistance, listSpacing);        i++;
  398.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  399.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  400.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  401.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  402.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  403.     selFileLists[2] = XtCreateManagedWidget("selFileList3",
  404.         compositeWidgetClass, selFileForm, arglist, i);
  405.  
  406.     for (n = 0; n < 3; n++) {
  407.  
  408.         i = 0;
  409.         XtSetArg(arglist[i], XtNx, vScrollX);            i++;
  410.         XtSetArg(arglist[i], XtNy, vScrollY);            i++;
  411.         XtSetArg(arglist[i], XtNwidth, scrollThickness);    i++;
  412.         XtSetArg(arglist[i], XtNheight, SFvScrollHeight);    i++;
  413.         XtSetArg(arglist[i], XtNborderColor, SFfore);        i++;
  414.         selFileVScrolls[n] = XtCreateManagedWidget("selFileVScroll",
  415.             scrollbarWidgetClass, selFileLists[n], arglist, i);
  416.  
  417.         XtAddCallback(selFileVScrolls[n], XtNjumpProc,
  418.             SFvFloatSliderMovedCallback, (XtPointer) n);
  419.         XtAddCallback(selFileVScrolls[n], XtNscrollProc,
  420.             SFvAreaSelectedCallback, (XtPointer) n);
  421.  
  422.         i = 0;
  423.  
  424.         XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);
  425.                                     i++;
  426.         XtSetArg(arglist[i], XtNx, hScrollX);            i++;
  427.         XtSetArg(arglist[i], XtNy, hScrollY);            i++;
  428.         XtSetArg(arglist[i], XtNwidth, SFhScrollWidth);        i++;
  429.         XtSetArg(arglist[i], XtNheight, scrollThickness);    i++;
  430.         XtSetArg(arglist[i], XtNborderColor, SFfore);        i++;
  431.         selFileHScrolls[n] = XtCreateManagedWidget("selFileHScroll",
  432.             scrollbarWidgetClass, selFileLists[n], arglist, i);
  433.  
  434.         XtAddCallback(selFileHScrolls[n], XtNjumpProc,
  435.             SFhSliderMovedCallback, (XtPointer) n);
  436.         XtAddCallback(selFileHScrolls[n], XtNscrollProc,
  437.             SFhAreaSelectedCallback, (XtPointer) n);
  438.     }
  439.  
  440.     i = 0;
  441.     XtSetArg(arglist[i], XtNlabel, ok);                i++;
  442.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  443.     XtSetArg(arglist[i], XtNcallback, SFokSelect);            i++;
  444.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  445.     XtSetArg(arglist[i], XtNfromVert, selFileLists[0]);        i++;
  446.     XtSetArg(arglist[i], XtNvertDistance, 30);            i++;
  447.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  448.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  449.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  450.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  451.     selFileOK = XtCreateManagedWidget("selFileOK", commandWidgetClass,
  452.         selFileForm, arglist, i);
  453.  
  454.     i = 0;
  455.     XtSetArg(arglist[i], XtNlabel, cancel);                i++;
  456.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  457.     XtSetArg(arglist[i], XtNcallback, SFcancelSelect);        i++;
  458.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  459.     XtSetArg(arglist[i], XtNfromHoriz, selFileOK);            i++;
  460.     XtSetArg(arglist[i], XtNfromVert, selFileLists[0]);        i++;
  461.     XtSetArg(arglist[i], XtNhorizDistance, 30);            i++;
  462.     XtSetArg(arglist[i], XtNvertDistance, 30);            i++;
  463.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  464.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  465.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  466.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  467.     selFileCancel = XtCreateManagedWidget("selFileCancel",
  468.         commandWidgetClass, selFileForm, arglist, i);
  469.  
  470.     XtSetMappedWhenManaged(selFile, False);
  471.     XtRealizeWidget(selFile);
  472.  
  473.     /* Add WM_DELETE_WINDOW protocol */
  474.     SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False);
  475.     XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1);
  476.  
  477.     SFcreateGC();
  478.  
  479.     xtermCursor = XCreateFontCursor(SFdisplay, XC_xterm);
  480.  
  481.     sbRightArrowCursor = XCreateFontCursor(SFdisplay, XC_sb_right_arrow);
  482.     dotCursor = XCreateFontCursor(SFdisplay, XC_dot);
  483.  
  484.     XDefineCursor(SFdisplay, XtWindow(selFileForm), xtermCursor);
  485.     XDefineCursor(SFdisplay, XtWindow(selFileField), xtermCursor);
  486.  
  487.     for (n = 0; n < 3; n++) {
  488.         XDefineCursor(SFdisplay, XtWindow(selFileLists[n]),
  489.             sbRightArrowCursor);
  490.     }
  491.     XDefineCursor(SFdisplay, XtWindow(selFileOK), dotCursor);
  492.     XDefineCursor(SFdisplay, XtWindow(selFileCancel), dotCursor);
  493.  
  494.     for (n = 0; n < 3; n++) {
  495.         XtAddEventHandler(selFileLists[n], ExposureMask, True,
  496.             SFexposeList, (XtPointer) n);
  497.         XtAddEventHandler(selFileLists[n], EnterWindowMask, False,
  498.             SFenterList, (XtPointer) n);
  499.         XtAddEventHandler(selFileLists[n], LeaveWindowMask, False,
  500.             SFleaveList, (XtPointer) n);
  501.         XtAddEventHandler(selFileLists[n], PointerMotionMask, False,
  502.             SFmotionList, (XtPointer) n);
  503.         XtAddEventHandler(selFileLists[n], ButtonPressMask, False,
  504.             SFbuttonPressList, (XtPointer) n);
  505.         XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False,
  506.             SFbuttonReleaseList, (XtPointer) n);
  507.     }
  508.  
  509.     XtAddEventHandler(selFileField, KeyPressMask, False,
  510.         SFmodVerifyCallback, (XtPointer) NULL);
  511.  
  512.     SFapp = XtWidgetToApplicationContext(selFile);
  513.  
  514. }
  515.  
  516. /* position widget under the cursor */
  517. void
  518. SFpositionWidget(w)
  519.     Widget w;
  520. {
  521.     Arg args[3];
  522.     Cardinal num_args;
  523.     Dimension width, height, b_width;
  524.     int x, y, max_x, max_y;
  525.     Window root, child;
  526.     int dummyx, dummyy;
  527.     unsigned int dummymask;
  528.     
  529.     XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, &x, &y,
  530.           &dummyx, &dummyy, &dummymask);
  531.     num_args = 0;
  532.     XtSetArg(args[num_args], XtNwidth, &width); num_args++;
  533.     XtSetArg(args[num_args], XtNheight, &height); num_args++;
  534.     XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
  535.     XtGetValues(w, args, num_args);
  536.  
  537.     width += 2 * b_width;
  538.     height += 2 * b_width;
  539.  
  540.     x -= ( (Position) width/2 );
  541.     if (x < 0) x = 0;
  542.     if ( x > (max_x = (Position) (XtScreen(w)->width - width)) ) x = max_x;
  543.  
  544.     y -= ( (Position) height/2 );
  545.     if (y < 0) y = 0;
  546.     if ( y > (max_y = (Position) (XtScreen(w)->height - height)) ) y = max_y;
  547.     
  548.     num_args = 0;
  549.     XtSetArg(args[num_args], XtNx, x); num_args++;
  550.     XtSetArg(args[num_args], XtNy, y); num_args++;
  551.     XtSetValues(w, args, num_args);
  552. }
  553.  
  554. FILE *
  555. SFopenFile(name, mode, prompt, failed)
  556.     char *name;
  557.     char *mode;
  558.     char *prompt;
  559.     char *failed;
  560. {
  561.     Arg args[1];
  562.     FILE *fp;
  563.  
  564.     SFchdir(SFstartDir);
  565.     if ((fp = fopen(name, mode)) == NULL) {
  566.     char *buf;
  567.     if (errno <= sys_nerr) {
  568.         buf = XtMalloc(strlen(failed) + strlen(sys_errlist[errno]) + 
  569.                strlen(prompt) + 2);
  570.         strcpy(buf, failed);
  571.         strcat(buf, sys_errlist[errno]);
  572.         strcat(buf, "\n");
  573.         strcat(buf, prompt);
  574.     } else {
  575.         buf = XtMalloc(strlen(failed) + strlen(prompt) + 2);
  576.         strcpy(buf, failed);
  577.         strcat(buf, "\n");
  578.         strcat(buf, prompt);
  579.     }
  580.     XtSetArg(args[0], XtNlabel, buf);
  581.     XtSetValues(selFilePrompt, args, 1);
  582.     XtFree(buf);
  583.     return NULL;
  584.     }
  585.     return fp;
  586. }
  587.  
  588. SFtextChanged()
  589. {
  590.  
  591.     if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~')) {
  592.         (void) strcpy(SFcurrentPath, SFtextBuffer);
  593.  
  594.         SFtextPos = XawTextGetInsertionPoint(selFileField);
  595.     } else {
  596.         (void) strcat(strcpy(SFcurrentPath, SFstartDir), SFtextBuffer);
  597.  
  598.         SFtextPos = XawTextGetInsertionPoint(selFileField) +
  599.             strlen(SFstartDir);
  600.     }
  601.  
  602.     if (!SFworkProcAdded) {
  603.         (void) XtAppAddWorkProc(SFapp, SFworkProc, NULL);
  604.         SFworkProcAdded = 1;
  605.     }
  606.  
  607.     SFupdatePath();
  608. }
  609.  
  610. static char *
  611. SFgetText()
  612. {
  613.     return strcpy(XtMalloc((unsigned) (strlen(SFtextBuffer) + 1)),
  614.         SFtextBuffer);
  615. }
  616.  
  617. static
  618. SFprepareToReturn()
  619. {
  620.     SFstatus = SEL_FILE_NULL;
  621.     XtRemoveGrab(selFile);
  622.     XtUnmapWidget(selFile);
  623.     XtRemoveTimeOut(SFdirModTimerId);
  624.     if (SFchdir(SFstartDir)) {
  625.         XtAppError(
  626.             SFapp,
  627.             "XsraSelFile: can't return to current directory"
  628.         );
  629.     }
  630. }
  631.  
  632. FILE *
  633. XsraSelFile(toplevel, prompt, ok, cancel, failed,
  634.         init_path, mode, show_entry, name_return)
  635.     Widget        toplevel;
  636.     char        *prompt;
  637.     char        *ok;
  638.     char        *cancel;
  639.     char        *failed;
  640.     char        *init_path;
  641.     char        *mode;
  642.     int        (*show_entry)();
  643.     char        **name_return;
  644. {
  645.     static int    firstTime = 1;
  646.     int        i;
  647.     Arg        arglist[20];
  648.     XEvent        event;
  649.     FILE        *fp;
  650.  
  651.     if (!prompt) {
  652.         prompt = "Pathname:";
  653.     }
  654.  
  655.     if (!ok) {
  656.         ok = "OK";
  657.     }
  658.  
  659.     if (!cancel) {
  660.         cancel = "Cancel";
  661.     }
  662.  
  663.     if (firstTime) {
  664.         firstTime = 0;
  665.         SFdisplay = XtDisplay(toplevel);
  666.         SFcreateWidgets(toplevel, prompt, ok, cancel);
  667.     } else {
  668.         i = 0;
  669.  
  670.         XtSetArg(arglist[i], XtNlabel, prompt);            i++;
  671.         XtSetValues(selFilePrompt, arglist, i);
  672.  
  673.         i = 0;
  674.         XtSetArg(arglist[i], XtNlabel, ok);            i++;
  675.         XtSetValues(selFileOK, arglist, i);
  676.  
  677.         i = 0;
  678.         XtSetArg(arglist[i], XtNlabel, cancel);            i++;
  679.         XtSetValues(selFileCancel, arglist, i);
  680.     }
  681.  
  682.     SFpositionWidget(selFile);
  683.     XtMapWidget(selFile);
  684.  
  685. #if defined(SYSV) || defined(USG)
  686.     if (!getcwd(SFstartDir, MAXPATHLEN)) {
  687. #else /* defined(SYSV) || defined(USG) */
  688.     if (!getwd(SFstartDir)) {
  689. #endif /* defined(SYSV) || defined(USG) */
  690.  
  691.         XtAppError(SFapp, "XsraSelFile: can't get current directory");
  692.     }
  693.     (void) strcat(SFstartDir, "/");
  694.     (void) strcpy(SFcurrentDir, SFstartDir);
  695.  
  696.     if (init_path) {
  697.         if (init_path[0] == '/') {
  698.             (void) strcpy(SFcurrentPath, init_path);
  699.             if (strncmp(
  700.                 SFcurrentPath,
  701.                 SFstartDir,
  702.                 strlen(SFstartDir)
  703.             )) {
  704.                 SFsetText(SFcurrentPath);
  705.             } else {
  706.                 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
  707.             }
  708.         } else {
  709.             (void) strcat(strcpy(SFcurrentPath, SFstartDir),
  710.                 init_path);
  711.             SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
  712.         }
  713.     } else {
  714.         (void) strcpy(SFcurrentPath, SFstartDir);
  715.     }
  716.  
  717.     SFfunc = show_entry;
  718.  
  719.     SFtextChanged();
  720.  
  721.     XtAddGrab(selFile, True, True);
  722.  
  723.     SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
  724.         SFdirModTimer, (XtPointer) NULL);
  725.  
  726.     while (1) {
  727.         XtAppNextEvent(SFapp, &event);
  728.         XtDispatchEvent(&event);
  729.         switch (SFstatus) {
  730.         case SEL_FILE_TEXT:
  731.             SFstatus = SEL_FILE_NULL;
  732.             SFtextChanged();
  733.             break;
  734.         case SEL_FILE_OK:
  735.             *name_return = SFgetText();
  736.             if (fp = SFopenFile(*name_return, mode,
  737.                         prompt, failed)) {
  738.                 SFprepareToReturn();
  739.                 return fp;
  740.             }
  741.             SFstatus = SEL_FILE_NULL;
  742.             break;
  743.         case SEL_FILE_CANCEL:
  744.             SFprepareToReturn();
  745.             return NULL;
  746.         case SEL_FILE_NULL:
  747.             break;
  748.         }
  749.     }
  750. }
  751.