home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / unixtex-6.1b-src.tgz / tar.out / contrib / unixtex / xdvik / sfSelFile.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  26KB  |  945 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. #ifndef NOSELFILE /* for xdvik */
  28.  
  29. /*
  30.  * Author's address:
  31.  *
  32.  *     erik@sra.co.jp
  33.  *                                            OR
  34.  *     erik%sra.co.jp@uunet.uu.net
  35.  *                                            OR
  36.  *     erik%sra.co.jp@mcvax.uucp
  37.  *                                            OR
  38.  *     try junet instead of co.jp
  39.  *                                            OR
  40.  *     Erik M. van der Poel
  41.  *     Software Research Associates, Inc.
  42.  *     1-1-1 Hirakawa-cho, Chiyoda-ku
  43.  *     Tokyo 102 Japan. TEL +81-3-234-2692
  44.  */
  45.  
  46. #include <stdio.h>
  47. #include <errno.h>
  48. /* BSD 4.3 errno.h does not declare errno */
  49. extern int errno;
  50. extern int sys_nerr;
  51. extern char *sys_errlist[];
  52.  
  53. #include <sys/param.h>
  54. #include <X11/cursorfont.h>
  55. #include <X11/Intrinsic.h>
  56. #include <X11/StringDefs.h>
  57. #include <X11/Composite.h>
  58. #include <X11/Shell.h>
  59. #include <X11/Xaw/Form.h>
  60. #include <X11/Xaw/Command.h>
  61. #include <X11/Xaw/Scrollbar.h>
  62. #include <X11/Xaw/Label.h>
  63. #include <X11/Xaw/Cardinals.h>
  64.  
  65. /* Not worth config.h just to get this.  */
  66. #include <sys/stat.h>
  67. #if !defined(S_ISDIR) && defined(S_IFDIR)
  68. #define    S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
  69. #endif
  70.  
  71. #include "sfinternal.h"
  72.  
  73. #ifndef MAXPATHLEN
  74. #define MAXPATHLEN 1024
  75. #endif /* ndef MAXPATHLEN */
  76.  
  77. extern int SFchdir ();
  78.  
  79. int SFstatus = SEL_FILE_NULL;
  80.  
  81. char
  82.     SFstartDir[MAXPATHLEN],
  83.     SFcurrentPath[MAXPATHLEN],
  84.     SFcurrentDir[MAXPATHLEN];
  85.  
  86. Widget
  87.     selFile,
  88.     selFileCancel,
  89.     selFileField,
  90.     selFileForm,
  91.     selFileHScroll,
  92.     selFileHScrolls[3],
  93.     selFileLists[3],
  94.     selFileOK,
  95.     selFilePrompt,
  96.     selFileVScrolls[3];
  97.  
  98. /* For file filter. */
  99. Widget    selFileLabel, selFileMask, selFileHide;
  100. #define MASKWIDTH 10
  101. char     fileMask[MASKWIDTH+2] = "*.dvi";
  102.  
  103. Display *SFdisplay;
  104.  
  105. Pixel SFfore, SFback;
  106.  
  107. Atom    SFwmDeleteWindow;
  108.  
  109. XSegment SFsegs[2], SFcompletionSegs[2];
  110.  
  111. XawTextPosition SFtextPos;
  112.  
  113. int SFupperX, SFlowerY, SFupperY;
  114.  
  115. int SFtextX, SFtextYoffset;
  116.  
  117. int SFentryWidth, SFentryHeight;
  118.  
  119. int SFlineToTextH = 3;
  120.  
  121. int SFlineToTextV = 3;
  122.  
  123. int SFbesideText = 3;
  124.  
  125. int SFaboveAndBelowText = 2;
  126.  
  127. int SFcharsPerEntry = 15;
  128.  
  129. int SFlistSize = 10;
  130.  
  131. int SFworkProcAdded = 0;
  132.  
  133. XtAppContext SFapp;
  134.  
  135. int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth;
  136.  
  137. char SFtextBuffer[MAXPATHLEN];
  138.  
  139. XtIntervalId SFdirModTimerId;
  140.  
  141. int (*SFfunc)();
  142.  
  143. static char *oneLineTextEditTranslations = "\
  144.     <Key>Return:    redraw-display()\n\
  145.     Ctrl<Key>M:    redraw-display()\n\
  146. ";
  147.  
  148. /* ARGSUSED */
  149. static void
  150. SFexposeList(w, n, event, cont)
  151.     Widget        w;
  152.     XtPointer    n;
  153.         XEvent       *event;
  154.         Boolean         *cont;
  155. {
  156.     extern void SFdrawList ();
  157.     
  158.     if ((event->type == NoExpose) || event->xexpose.count) {
  159.         return;
  160.     }
  161.  
  162.     SFdrawList(n, SF_DO_NOT_SCROLL);
  163. }
  164.  
  165. /* ARGSUSED */
  166. static void
  167. SFmodVerifyCallback(w, client_data, event, cont)
  168.     Widget            w;
  169.     XtPointer        client_data;
  170.         XEvent                    *event;
  171.         Boolean                 *cont;
  172. {
  173.     char    buf[2];
  174.  
  175.     if (
  176.         (XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) &&
  177.         ((*buf) == '\r')
  178.     ) {
  179.         SFstatus = SEL_FILE_OK;
  180.     } else {
  181.         SFstatus = SEL_FILE_TEXT;
  182.     }
  183. }
  184.  
  185. /* ARGSUSED */
  186. static void
  187. SFokCallback(w, cl, cd)
  188.     Widget    w;
  189.         XtPointer cl, cd;
  190. {
  191.     SFstatus = SEL_FILE_OK;
  192. }
  193.  
  194. static XtCallbackRec SFokSelect[] = {
  195.     { SFokCallback, (XtPointer) NULL },
  196.     { NULL, (XtPointer) NULL },
  197. };
  198.  
  199. /* ARGSUSED */
  200. static void
  201. SFcancelCallback(w, cl, cd)
  202.     Widget    w;
  203.         XtPointer cl, cd;
  204. {
  205.     SFstatus = SEL_FILE_CANCEL;
  206. }
  207.  
  208. static XtCallbackRec SFcancelSelect[] = {
  209.     { SFcancelCallback, (XtPointer) NULL },
  210.     { NULL, (XtPointer) NULL },
  211. };
  212.  
  213. /* ARGSUSED */
  214. static void
  215. SFdismissAction(w, event, params, num_params)
  216.     Widget    w;
  217.     XEvent *event;
  218.     String *params;
  219.     Cardinal *num_params;
  220. {
  221.     if (event->type == ClientMessage &&
  222.         event->xclient.data.l[0] != SFwmDeleteWindow) return;
  223.  
  224.     SFstatus = SEL_FILE_CANCEL;
  225. }
  226.  
  227. static char *wmDeleteWindowTranslation = "\
  228.     <Message>WM_PROTOCOLS:    SelFileDismiss()\n\
  229. ";
  230.  
  231. static XtActionsRec actions[] = {
  232.     {"SelFileDismiss",    SFdismissAction},
  233. };
  234.  
  235. /* Don't show files that don't get through the filter.  */
  236.  
  237. int
  238. maskFile(mask, filename)
  239.    char    *mask, *filename;
  240. /* return 1 if file is masked (mask does not match filename), 0 otherwise */
  241. {
  242. int     c, c1;
  243.  
  244.     while  ((c = *mask++)) {
  245.       if (c == '*') {
  246.         while ((c1 = *mask++)) {
  247.           if (c1 != '*') {
  248.         if (!(*filename)) return 1;
  249.         if (c1 != '?') {
  250.           while ((filename = strchr(filename, c1))) {
  251.             if (!maskFile(mask, ++filename)) return 0;
  252.           }
  253.           return 1;
  254.         }
  255.         else filename++;
  256.           }
  257.         }
  258.         return 0;
  259.       }
  260.       if (c == '?') { if (!*filename) return 1; }
  261.       else if (c != *filename) return 1;
  262.       filename++;
  263.     }
  264.     return (*filename)? 1 : 0;
  265. }
  266.  
  267. int    hideFlag = 1;
  268. int
  269. showEntry(entryReal, entryShown, statBuf)
  270.     char    *entryReal, **entryShown;
  271.     struct    stat    *statBuf;
  272. {
  273.     if (!(S_ISDIR(statBuf->st_mode))) {
  274.       if (hideFlag)
  275.         if (entryReal[0] == '.') return 0;
  276.       if (maskFile(fileMask, entryReal)) return 0;
  277.     }
  278.     entryReal[strlen(entryReal)] = SFstatChar(statBuf);
  279.         return 1;
  280. }
  281.  
  282. /* ARGSUSED */
  283. void
  284. maskChanged(w, client_data, event)
  285.     Widget        w;
  286.     XtPointer    client_data;
  287.     XKeyPressedEvent    *event;
  288. {
  289.     char    buf[2];
  290.     register SFDir        *dir;
  291.     extern void SFupdatePath ();
  292.  
  293.     if ((XLookupString(event, buf, 2, NULL, NULL) == 1) &&
  294.         ((*buf) == '\r')) {
  295.       for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
  296.         *(dir->dir) = 0; /* force a re-read */
  297.       SFupdatePath();
  298.     }
  299. }
  300.  
  301. /* ARGSUSED */
  302. void
  303. hideFiles(w, client_data, event)
  304.     Widget    w;
  305.     XtPointer    client_data;
  306.     XEvent    *event;
  307. {
  308.     register SFDir        *dir;
  309.     register SFEntry    *entry;
  310.     extern void SFupdatePath (), SFdrawLists ();
  311.  
  312.     hideFlag = 1 - hideFlag;
  313.     if (hideFlag) {
  314.       XtVaSetValues(w, XtNlabel, "hidden", NULL);
  315.       for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) {
  316.         if (!(dir->nEntries)) continue;
  317.         dir->vOrigin = 0;
  318.         for (entry = &(dir->entries[dir->nEntries - 1]);
  319.          entry >= dir->entries; entry--)
  320.           entry->statDone = 0;
  321.         SFdrawLists(SF_DO_SCROLL);
  322.       }
  323.     } else {
  324.       XtVaSetValues(w, XtNlabel, "shown", NULL);
  325.       for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
  326.         *(dir->dir) = 0;    /* force a re-read */
  327.       SFupdatePath();
  328.     }
  329. }
  330.  
  331.  
  332. static void
  333. SFcreateWidgets(toplevel, prompt, ok, cancel)
  334.     Widget    toplevel;
  335.     char    *prompt;
  336.     char    *ok;
  337.     char    *cancel;
  338. {
  339.     Cardinal    i, n;
  340.     int        listWidth, listHeight;
  341.     int        listSpacing = 10;
  342.     int        scrollThickness = 15;
  343.     int        hScrollX, hScrollY;
  344.     int        vScrollX, vScrollY;
  345.     Cursor
  346.             xtermCursor,
  347.             sbRightArrowCursor,
  348.             dotCursor;
  349.     Arg        arglist[20];
  350.     extern void SFinitFont (), SFcreateGC ();
  351.  
  352.     i = 0;
  353.     XtSetArg(arglist[i], XtNtransientFor, toplevel);        i++;
  354.  
  355.     selFile = XtAppCreateShell("selFile", "SelFile",
  356.         transientShellWidgetClass, SFdisplay, arglist, i);
  357.  
  358.     /* Add WM_DELETE_WINDOW protocol */
  359.     XtAppAddActions(XtWidgetToApplicationContext(selFile),
  360.         actions, XtNumber(actions));
  361.     XtOverrideTranslations(selFile,
  362.         XtParseTranslationTable(wmDeleteWindowTranslation));
  363.  
  364.     i = 0;
  365.     XtSetArg(arglist[i], XtNdefaultDistance, 30);            i++;
  366.     selFileForm = XtCreateManagedWidget("selFileForm",
  367.         formWidgetClass, selFile, arglist, i);
  368.  
  369.     i = 0;
  370.     XtSetArg(arglist[i], XtNlabel, prompt);                i++;
  371.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  372.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  373.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  374.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  375.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  376.     XtSetArg(arglist[i], XtNborderWidth, 0);            i++;
  377.     selFilePrompt = XtCreateManagedWidget("selFilePrompt",
  378.         labelWidgetClass, selFileForm, arglist, i);
  379.  
  380.     i = 0;
  381.     XtSetArg(arglist[i], XtNforeground, &SFfore);            i++;
  382.     XtSetArg(arglist[i], XtNbackground, &SFback);            i++;
  383.     XtGetValues(selFilePrompt, arglist, i);
  384.  
  385.     SFinitFont();
  386.  
  387.     SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth +
  388.             SFbesideText;
  389.     SFentryHeight = SFaboveAndBelowText + SFcharHeight +
  390.             SFaboveAndBelowText;
  391.  
  392.     listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 +
  393.             scrollThickness;
  394.     listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  395.             SFlineToTextV + SFlistSize * SFentryHeight +
  396.             SFlineToTextV + 1 + scrollThickness;
  397.  
  398.     SFpathScrollWidth = 3 * listWidth + 2 * listSpacing + 4;
  399.  
  400.     hScrollX = -1;
  401.     hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  402.             SFlineToTextV + SFlistSize * SFentryHeight +
  403.             SFlineToTextV;
  404.     SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;
  405.  
  406.     vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
  407.     vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
  408.     SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight +
  409.             SFlineToTextV;
  410.  
  411.     SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
  412.     SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  413.             SFlineToTextV;
  414.     SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  415.             SFlineToTextV + SFlistSize * SFentryHeight - 1;
  416.  
  417.     SFtextX = SFlineToTextH + SFbesideText;
  418.     SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;
  419.  
  420.     SFsegs[0].x1 = 0;
  421.     SFsegs[0].y1 = vScrollY;
  422.     SFsegs[0].x2 = vScrollX - 1;
  423.     SFsegs[0].y2 = vScrollY;
  424.     SFsegs[1].x1 = vScrollX;
  425.     SFsegs[1].y1 = 0;
  426.     SFsegs[1].x2 = vScrollX;
  427.     SFsegs[1].y2 = vScrollY - 1;
  428.  
  429.     SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
  430.     SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
  431.         SFlineToTextH + SFentryWidth - 1;
  432.  
  433.     i = 0;
  434.     XtSetArg(arglist[i], XtNwidth, 3 * listWidth + 2 * listSpacing + 4);
  435.                                     i++;
  436.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  437.  
  438.     XtSetArg(arglist[i], XtNfromVert, selFilePrompt);        i++;
  439.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  440.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  441.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  442.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  443.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  444.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  445.     XtSetArg(arglist[i], XtNstring, SFtextBuffer);            i++;
  446.     XtSetArg(arglist[i], XtNlength, MAXPATHLEN);            i++;
  447.     XtSetArg(arglist[i], XtNeditType, XawtextEdit);            i++;
  448.     XtSetArg(arglist[i], XtNwrap, XawtextWrapWord);            i++;
  449.     XtSetArg(arglist[i], XtNresize, XawtextResizeHeight);        i++;
  450.     XtSetArg(arglist[i], XtNuseStringInPlace, True);        i++;
  451.     selFileField = XtCreateManagedWidget("selFileField",
  452.         asciiTextWidgetClass, selFileForm, arglist, i);
  453.  
  454.     XtOverrideTranslations(selFileField,
  455.         XtParseTranslationTable(oneLineTextEditTranslations));
  456. /*    XtSetKeyboardFocus(selFileForm, selFileField);
  457.     need focus for selFileMask wigget to set the filter */
  458.  
  459.     i = 0;
  460.     XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);    i++;
  461.     XtSetArg(arglist[i], XtNwidth, SFpathScrollWidth);        i++;
  462.     XtSetArg(arglist[i], XtNheight, scrollThickness);        i++;
  463.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  464.     XtSetArg(arglist[i], XtNfromVert, selFileField);        i++;
  465.     XtSetArg(arglist[i], XtNvertDistance, 30);            i++;
  466.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  467.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  468.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  469.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  470.     selFileHScroll = XtCreateManagedWidget("selFileHScroll",
  471.         scrollbarWidgetClass, selFileForm, arglist, i);
  472.  
  473.     XtAddCallback(selFileHScroll, XtNjumpProc,
  474.         SFpathSliderMovedCallback, (XtPointer) NULL);
  475.     XtAddCallback(selFileHScroll, XtNscrollProc,
  476.         SFpathAreaSelectedCallback, (XtPointer) NULL);
  477.  
  478.     i = 0;
  479.     XtSetArg(arglist[i], XtNwidth, listWidth);            i++;
  480.     XtSetArg(arglist[i], XtNheight, listHeight);            i++;
  481.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  482.     XtSetArg(arglist[i], XtNfromVert, selFileHScroll);        i++;
  483.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  484.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  485.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  486.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  487.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  488.     selFileLists[0] = XtCreateManagedWidget("selFileList1",
  489.         compositeWidgetClass, selFileForm, arglist, i);
  490.  
  491.     i = 0;
  492.     XtSetArg(arglist[i], XtNwidth, listWidth);            i++;
  493.     XtSetArg(arglist[i], XtNheight, listHeight);            i++;
  494.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  495.     XtSetArg(arglist[i], XtNfromHoriz, selFileLists[0]);        i++;
  496.     XtSetArg(arglist[i], XtNfromVert, selFileHScroll);        i++;
  497.     XtSetArg(arglist[i], XtNhorizDistance, listSpacing);        i++;
  498.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  499.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  500.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  501.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  502.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  503.     selFileLists[1] = XtCreateManagedWidget("selFileList2",
  504.         compositeWidgetClass, selFileForm, arglist, i);
  505.  
  506.     i = 0;
  507.     XtSetArg(arglist[i], XtNwidth, listWidth);            i++;
  508.     XtSetArg(arglist[i], XtNheight, listHeight);            i++;
  509.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  510.     XtSetArg(arglist[i], XtNfromHoriz, selFileLists[1]);        i++;
  511.     XtSetArg(arglist[i], XtNfromVert, selFileHScroll);        i++;
  512.     XtSetArg(arglist[i], XtNhorizDistance, listSpacing);        i++;
  513.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  514.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  515.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  516.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  517.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  518.     selFileLists[2] = XtCreateManagedWidget("selFileList3",
  519.         compositeWidgetClass, selFileForm, arglist, i);
  520.  
  521.     for (n = 0; n < 3; n++) {
  522.  
  523.         i = 0;
  524.         XtSetArg(arglist[i], XtNx, vScrollX);            i++;
  525.         XtSetArg(arglist[i], XtNy, vScrollY);            i++;
  526.         XtSetArg(arglist[i], XtNwidth, scrollThickness);    i++;
  527.         XtSetArg(arglist[i], XtNheight, SFvScrollHeight);    i++;
  528.         XtSetArg(arglist[i], XtNborderColor, SFfore);        i++;
  529.         selFileVScrolls[n] = XtCreateManagedWidget("selFileVScroll",
  530.             scrollbarWidgetClass, selFileLists[n], arglist, i);
  531.  
  532.         XtAddCallback(selFileVScrolls[n], XtNjumpProc,
  533.             SFvFloatSliderMovedCallback, (XtPointer) n);
  534.         XtAddCallback(selFileVScrolls[n], XtNscrollProc,
  535.             SFvAreaSelectedCallback, (XtPointer) n);
  536.  
  537.         i = 0;
  538.  
  539.         XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);
  540.                                     i++;
  541.         XtSetArg(arglist[i], XtNx, hScrollX);            i++;
  542.         XtSetArg(arglist[i], XtNy, hScrollY);            i++;
  543.         XtSetArg(arglist[i], XtNwidth, SFhScrollWidth);        i++;
  544.         XtSetArg(arglist[i], XtNheight, scrollThickness);    i++;
  545.         XtSetArg(arglist[i], XtNborderColor, SFfore);        i++;
  546.         selFileHScrolls[n] = XtCreateManagedWidget("selFileHScroll",
  547.             scrollbarWidgetClass, selFileLists[n], arglist, i);
  548.  
  549.         XtAddCallback(selFileHScrolls[n], XtNjumpProc,
  550.             SFhSliderMovedCallback, (XtPointer) n);
  551.         XtAddCallback(selFileHScrolls[n], XtNscrollProc,
  552.             SFhAreaSelectedCallback, (XtPointer) n);
  553.     }
  554.  
  555.     i = 0;
  556.     XtSetArg(arglist[i], XtNlabel, ok);                i++;
  557.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  558.     XtSetArg(arglist[i], XtNcallback, SFokSelect);            i++;
  559.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  560.     XtSetArg(arglist[i], XtNfromVert, selFileLists[0]);        i++;
  561.     XtSetArg(arglist[i], XtNvertDistance, 30);            i++;
  562.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  563.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  564.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  565.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  566.     selFileOK = XtCreateManagedWidget("selFileOK", commandWidgetClass,
  567.         selFileForm, arglist, i);
  568.  
  569.     i = 0;
  570.     XtSetArg(arglist[i], XtNlabel, cancel);                i++;
  571.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  572.     XtSetArg(arglist[i], XtNcallback, SFcancelSelect);        i++;
  573.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  574.     XtSetArg(arglist[i], XtNfromHoriz, selFileOK);            i++;
  575.     XtSetArg(arglist[i], XtNfromVert, selFileLists[0]);        i++;
  576.     XtSetArg(arglist[i], XtNhorizDistance, 30);            i++;
  577.     XtSetArg(arglist[i], XtNvertDistance, 30);            i++;
  578.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  579.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  580.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  581.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  582.     selFileCancel = XtCreateManagedWidget("selFileCancel",
  583.         commandWidgetClass, selFileForm, arglist, i);
  584.  
  585.         /* Do the file filter stuff.  */
  586.     selFileLabel = XtVaCreateManagedWidget("selFileLabel",
  587.         labelWidgetClass, selFileForm,
  588.         XtNfromVert, selFileLists[0],
  589.         XtNvertDistance, 30,
  590.         XtNfromHoriz, selFileCancel,
  591.         XtNhorizDistance, 60,
  592.         XtNlabel,  "File Mask:",
  593.         XtNborderWidth, 0,
  594.         XtNtop, XtChainTop,
  595.         XtNbottom, XtChainTop,
  596.         NULL);
  597.     
  598.     selFileMask = XtVaCreateManagedWidget("selFileMask",
  599.         asciiTextWidgetClass, selFileForm,
  600.         XtNwidth, MASKWIDTH*SFcharWidth,
  601.         XtNfromVert, selFileLists[0],
  602.         XtNvertDistance, 30,
  603.         XtNfromHoriz, selFileLabel,
  604.         XtNhorizDistance, 0,
  605.         XtNtop, XtChainTop,
  606.         XtNbottom, XtChainTop,
  607.         XtNstring, fileMask,
  608.         XtNlength, sizeof(fileMask),
  609.         XtNeditType, XawtextEdit,
  610.         XtNwrap, XawtextWrapNever,
  611.         XtNuseStringInPlace, True,
  612.         NULL);
  613.  
  614.     for (i = 0; i < 3; i++)
  615.       XtSetKeyboardFocus(selFileLists[i], selFileField);
  616.  
  617.     XtOverrideTranslations(selFileMask,
  618.         XtParseTranslationTable(oneLineTextEditTranslations));
  619.  
  620.     XtAddEventHandler(selFileMask, KeyPressMask, False,
  621.         maskChanged, (XtPointer) NULL);
  622.  
  623.     selFileLabel = XtVaCreateManagedWidget("selFileLabel",
  624.         labelWidgetClass, selFileForm,
  625.         XtNfromVert, selFileLists[0],
  626.         XtNvertDistance, 30,
  627.         XtNfromHoriz, selFileMask,
  628.         XtNhorizDistance, 40,
  629.         XtNlabel,  "dot files",
  630.         XtNborderWidth, 0,
  631.         XtNtop, XtChainTop,
  632.         XtNbottom, XtChainTop,
  633.         NULL);
  634.  
  635.     selFileHide = XtVaCreateManagedWidget("selFileHide",
  636.         commandWidgetClass, selFileForm,
  637.         XtNfromVert, selFileLists[0],
  638.         XtNvertDistance, 30,
  639.         XtNfromHoriz, selFileLabel,
  640.         XtNhorizDistance, 2,
  641.         XtNlabel, "hidden",
  642.         XtNborderWidth, 0,
  643.         XtNtop, XtChainTop,
  644.         XtNbottom, XtChainTop,
  645. #if 0 /* missing in R4, says 
  646.          pete@lovelace.thi.informatik.uni-frankfurt.de (Peter Dyballa) */
  647.         XtNcursorName, "dot",
  648. #endif
  649.                NULL);
  650.     XtAddCallback(selFileHide, XtNcallback, hideFiles, NULL);
  651.  
  652.     XtSetMappedWhenManaged(selFile, False);
  653.     XtRealizeWidget(selFile);
  654.  
  655.     /* Add WM_DELETE_WINDOW protocol */
  656.     SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False);
  657.     XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1);
  658.  
  659.     SFcreateGC();
  660.  
  661.     xtermCursor = XCreateFontCursor(SFdisplay, XC_xterm);
  662.  
  663.     sbRightArrowCursor = XCreateFontCursor(SFdisplay, XC_sb_right_arrow);
  664.     dotCursor = XCreateFontCursor(SFdisplay, XC_dot);
  665.  
  666.     XDefineCursor(SFdisplay, XtWindow(selFileForm), xtermCursor);
  667.     XDefineCursor(SFdisplay, XtWindow(selFileField), xtermCursor);
  668.  
  669.     for (n = 0; n < 3; n++) {
  670.         XDefineCursor(SFdisplay, XtWindow(selFileLists[n]),
  671.             sbRightArrowCursor);
  672.     }
  673.     XDefineCursor(SFdisplay, XtWindow(selFileOK), dotCursor);
  674.     XDefineCursor(SFdisplay, XtWindow(selFileCancel), dotCursor);
  675.  
  676.     for (n = 0; n < 3; n++) {
  677.         XtAddEventHandler(selFileLists[n], ExposureMask, True,
  678.             SFexposeList, (XtPointer) n);
  679.         XtAddEventHandler(selFileLists[n], EnterWindowMask, False,
  680.             SFenterList, (XtPointer) n);
  681.         XtAddEventHandler(selFileLists[n], LeaveWindowMask, False,
  682.             SFleaveList, (XtPointer) n);
  683.         XtAddEventHandler(selFileLists[n], PointerMotionMask, False,
  684.             SFmotionList, (XtPointer) n);
  685.         XtAddEventHandler(selFileLists[n], ButtonPressMask, False,
  686.             SFbuttonPressList, (XtPointer) n);
  687.         XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False,
  688.             SFbuttonReleaseList, (XtPointer) n);
  689.     }
  690.  
  691.     XtAddEventHandler(selFileField, KeyPressMask, False,
  692.         SFmodVerifyCallback, (XtPointer) NULL);
  693.  
  694.     SFapp = XtWidgetToApplicationContext(selFile);
  695.  
  696. }
  697.  
  698. /* position widget under the cursor */
  699. void
  700. SFpositionWidget(w)
  701.     Widget w;
  702. {
  703.     Arg args[3];
  704.     Cardinal num_args;
  705.     Dimension width, height, b_width;
  706.     int x, y, max_x, max_y;
  707.     Window root, child;
  708.     int dummyx, dummyy;
  709.     unsigned int dummymask;
  710.     
  711.     XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, &x, &y,
  712.           &dummyx, &dummyy, &dummymask);
  713.     num_args = 0;
  714.     XtSetArg(args[num_args], XtNwidth, &width); num_args++;
  715.     XtSetArg(args[num_args], XtNheight, &height); num_args++;
  716.     XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
  717.     XtGetValues(w, args, num_args);
  718.  
  719.     width += 2 * b_width;
  720.     height += 2 * b_width;
  721.  
  722.     x -= ( (Position) width/2 );
  723.     if (x < 0) x = 0;
  724.     if ( x > (max_x = (Position) (XtScreen(w)->width - width)) ) x = max_x;
  725.  
  726.     y -= ( (Position) height/2 );
  727.     if (y < 0) y = 0;
  728.     if ( y > (max_y = (Position) (XtScreen(w)->height - height)) ) y = max_y;
  729.     
  730.     num_args = 0;
  731.     XtSetArg(args[num_args], XtNx, x); num_args++;
  732.     XtSetArg(args[num_args], XtNy, y); num_args++;
  733.     XtSetValues(w, args, num_args);
  734. }
  735.  
  736. FILE *
  737. SFopenFile(name, mode, prompt, failed)
  738.     char *name;
  739.     char *mode;
  740.     char *prompt;
  741.     char *failed;
  742. {
  743.     Arg args[1];
  744.     FILE *fp;
  745.  
  746.     SFchdir(SFstartDir);
  747.     if (!name || *name == 0 || (fp = fopen(name, mode)) == NULL) {
  748.     char *buf;
  749.     if (!name || *name == 0)
  750.       errno = sys_nerr + 1; /* no errno for an empty filename */
  751.     if (errno <= sys_nerr) {
  752.         buf = XtMalloc(strlen(failed) + strlen(sys_errlist[errno]) + 
  753.                strlen(prompt) + 2);
  754.         strcpy(buf, failed);
  755.         strcat(buf, sys_errlist[errno]);
  756. /*         strcat(buf, "\n"); */
  757.         strcat(buf, " ");
  758.         strcat(buf, prompt);
  759.     } else {
  760.         buf = XtMalloc(strlen(failed) + strlen(prompt) + 2);
  761.         strcpy(buf, failed);
  762. /*        strcat(buf, "\n"); */
  763.         strcat(buf, " ");
  764.         strcat(buf, prompt);
  765.     }
  766.     XtSetArg(args[0], XtNlabel, buf);
  767.     XtSetValues(selFilePrompt, args, ONE);
  768.     XtFree(buf);
  769.     return NULL;
  770.     }
  771.     return fp;
  772. }
  773.  
  774. void
  775. SFtextChanged()
  776. {
  777.     extern void SFupdatePath ();
  778.     
  779.     if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~')) {
  780.         (void) strcpy(SFcurrentPath, SFtextBuffer);
  781.  
  782.         SFtextPos = XawTextGetInsertionPoint(selFileField);
  783.     } else {
  784.         (void) strcat(strcpy(SFcurrentPath, SFstartDir), SFtextBuffer);
  785.  
  786.         SFtextPos = XawTextGetInsertionPoint(selFileField) +
  787.             strlen(SFstartDir);
  788.     }
  789.  
  790.     if (!SFworkProcAdded) {
  791.         (void) XtAppAddWorkProc(SFapp, SFworkProc, NULL);
  792.         SFworkProcAdded = 1;
  793.     }
  794.  
  795.     SFupdatePath();
  796. }
  797.  
  798. static char *
  799. SFgetText()
  800. {
  801.     return strcpy(XtMalloc((unsigned) (strlen(SFtextBuffer) + 1)),
  802.         SFtextBuffer);
  803. }
  804.  
  805. static void
  806. SFprepareToReturn()
  807. {
  808.     SFstatus = SEL_FILE_NULL;
  809.     XtRemoveGrab(selFile);
  810.     XtUnmapWidget(selFile);
  811.     XtRemoveTimeOut(SFdirModTimerId);
  812.     if (SFchdir(SFstartDir)) {
  813.         XtAppError(
  814.             SFapp,
  815.             "XsraSelFile: can't return to current directory"
  816.         );
  817.     }
  818. }
  819.  
  820. FILE *
  821. XsraSelFile(toplevel, prompt, ok, cancel, failed,
  822.         init_path, mode, show_entry, name_return)
  823.     Widget        toplevel;
  824.     char        *prompt;
  825.     char        *ok;
  826.     char        *cancel;
  827.     char        *failed;
  828.     char        *init_path;
  829.     char        *mode;
  830.     int        (*show_entry)();
  831.     char        **name_return;
  832. {
  833.     extern void SFsetText ();
  834.     static int    firstTime = 1;
  835.     Cardinal    i;
  836.     Arg        arglist[20];
  837.     XEvent        event;
  838.     FILE        *fp;
  839.  
  840.     if (!prompt) {
  841.         prompt = "Pathname:";
  842.     }
  843.  
  844.     if (!ok) {
  845.         ok = "OK";
  846.     }
  847.  
  848.     if (!cancel) {
  849.         cancel = "Cancel";
  850.     }
  851.  
  852.     if (firstTime) {
  853.         firstTime = 0;
  854.         SFdisplay = XtDisplay(toplevel);
  855.         SFcreateWidgets(toplevel, prompt, ok, cancel);
  856.     } else {
  857.         i = 0;
  858.  
  859.         XtSetArg(arglist[i], XtNlabel, prompt);            i++;
  860.         XtSetValues(selFilePrompt, arglist, i);
  861.  
  862.         i = 0;
  863.         XtSetArg(arglist[i], XtNlabel, ok);            i++;
  864.         XtSetValues(selFileOK, arglist, i);
  865.  
  866.         i = 0;
  867.         XtSetArg(arglist[i], XtNlabel, cancel);            i++;
  868.         XtSetValues(selFileCancel, arglist, i);
  869.     }
  870.  
  871.     SFpositionWidget(selFile);
  872.     XtMapWidget(selFile);
  873.  
  874.         {
  875.           extern char *xgetcwd (); /* In xgetcwd.c. */
  876.           char *cwd = xgetcwd ();
  877.           strcpy (SFstartDir, cwd);
  878.           free (cwd);
  879.         }
  880.     if (SFstartDir[0] == 0) {
  881.         XtAppError(SFapp, "XsraSelFile: can't get current directory");
  882.     }
  883.     (void) strcat(SFstartDir, "/");
  884.     (void) strcpy(SFcurrentDir, SFstartDir);
  885.  
  886.     if (init_path) {
  887.         if (init_path[0] == '/') {
  888.             (void) strcpy(SFcurrentPath, init_path);
  889.             if (strncmp(
  890.                 SFcurrentPath,
  891.                 SFstartDir,
  892.                 strlen(SFstartDir)
  893.             )) {
  894.                 SFsetText(SFcurrentPath);
  895.             } else {
  896.                 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
  897.             }
  898.         } else {
  899.             (void) strcat(strcpy(SFcurrentPath, SFstartDir),
  900.                 init_path);
  901.             SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
  902.         }
  903.     } else {
  904.         (void) strcpy(SFcurrentPath, SFstartDir);
  905.     }
  906.  
  907. /*    SFfunc = show_entry;
  908.     disabled in order to implement file filter */
  909.     SFfunc = showEntry;
  910.  
  911.     SFtextChanged();
  912.  
  913.     XtAddGrab(selFile, True, True);
  914.  
  915.     SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
  916.         SFdirModTimer, (XtPointer) NULL);
  917.  
  918.     while (1) {
  919.         XtAppNextEvent(SFapp, &event);
  920.         XtDispatchEvent(&event);
  921.         switch (SFstatus) {
  922.         case SEL_FILE_TEXT:
  923.             SFstatus = SEL_FILE_NULL;
  924.             SFtextChanged();
  925.             break;
  926.         case SEL_FILE_OK:
  927.             *name_return = SFgetText();
  928.             if ((fp = SFopenFile(*name_return, mode,
  929.                         prompt, failed))) {
  930.                 SFprepareToReturn();
  931.                 return fp;
  932.             }
  933.             SFstatus = SEL_FILE_NULL;
  934.             break;
  935.         case SEL_FILE_CANCEL:
  936.             SFprepareToReturn();
  937.             return NULL;
  938.         case SEL_FILE_NULL:
  939.             break;
  940.         }
  941.     }
  942. }
  943.  
  944. #endif /* not no SELFILE */
  945.