home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume4 / xdir / part02 < prev    next >
Encoding:
Text File  |  1989-06-03  |  47.7 KB  |  2,329 lines

  1. Path: uunet!island!argv
  2. From: argv@island.uu.net (Dan Heller)
  3. Newsgroups: comp.sources.x
  4. Subject: v04i015:  xdir -- Directory Browser, Part02/02
  5. Message-ID: <787@island.uu.net>
  6. Date: 3 Jun 89 21:26:06 GMT
  7. Organization: Island Graphics, Marin County, California
  8. Lines: 2318
  9. Approved: island!argv@sun.com
  10.  
  11. Submitted-by: Erik M. van der Poel <erik@sra.co.jp>
  12. Posting-number: Volume 4, Issue 15
  13. Archive-name: xdir/part02
  14.  
  15. #!/bin/sh
  16. # to extract, remove the header and type "sh filename"
  17. if `test ! -s ./Dir.c`
  18. then
  19. echo "writing ./Dir.c"
  20. cat > ./Dir.c << '\End\Of\File\'
  21. #ifndef lint
  22. static char rcsid[] = "$Header: Dir.c,v 1.3 89/05/29 15:03:50 erik Exp $";
  23. #endif
  24.  
  25. /*
  26.  * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
  27.  *
  28.  * Permission to use, copy, modify, and distribute this software and its
  29.  * documentation for any purpose and without fee is hereby granted, provided
  30.  * that the above copyright notice appear in all copies and that both that
  31.  * copyright notice and this permission notice appear in supporting
  32.  * documentation, and that the name of Software Research Associates not be used
  33.  * in advertising or publicity pertaining to distribution of the software
  34.  * without specific, written prior permission.  Software Research Associates
  35.  * makes no representations about the suitability of this software for any
  36.  * purpose.  It is provided "as is" without express or implied warranty.
  37.  *
  38.  * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  39.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  40.  * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
  41.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  42.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  43.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  44.  * PERFORMANCE OF THIS SOFTWARE.
  45.  *
  46.  * Author: Erik M. van der Poel
  47.  *         Software Research Associates, Inc., Tokyo, Japan
  48.  */
  49.  
  50. #include <stdio.h>
  51.  
  52. #ifdef SEL_FILE_IGNORE_CASE
  53. #include <ctype.h>
  54. #endif /* def SEL_FILE_IGNORE_CASE */
  55.  
  56. #include "SFinternal.h"
  57.  
  58. #ifdef SYSV
  59. #include <dirent.h>
  60. #else /* def SYSV */
  61. #include <sys/dir.h>
  62. #endif /* def SYSV */
  63.  
  64. #include <sys/stat.h>
  65.  
  66. #ifdef SYSV
  67. extern void qsort();
  68. #endif /* def SYSV */
  69.  
  70. #ifdef SEL_FILE_IGNORE_CASE
  71. int
  72. SFcompareEntries(p, q)
  73.     SFEntry    *p;
  74.     SFEntry    *q;
  75. {
  76.     register char    *r, *s;
  77.     register char    c1, c2;
  78.  
  79.     r = p->real;
  80.     s = q->real;
  81.  
  82.     c1 = *r++;
  83.     if (islower(c1)) {
  84.         c1 = toupper(c1);
  85.     }
  86.     c2 = *s++;
  87.     if (islower(c2)) {
  88.         c2 = toupper(c2);
  89.     }
  90.  
  91.     while (c1 == c2) {
  92.         if (!c1) {
  93.             return strcmp(p->real, q->real);
  94.         }
  95.         c1 = *r++;
  96.         if (islower(c1)) {
  97.             c1 = toupper(c1);
  98.         }
  99.         c2 = *s++;
  100.         if (islower(c2)) {
  101.             c2 = toupper(c2);
  102.         }
  103.     }
  104.  
  105.     return c1 - c2;
  106. }
  107. #else /* def SEL_FILE_IGNORE_CASE */
  108. int
  109. SFcompareEntries(p, q)
  110.     SFEntry    *p;
  111.     SFEntry    *q;
  112. {
  113.     return strcmp(p->real, q->real);
  114. }
  115. #endif /* def SEL_FILE_IGNORE_CASE */
  116.  
  117. int
  118. SFgetDir(dir)
  119.     SFDir    *dir;
  120. {
  121.     SFEntry        *result = NULL;
  122.     int        alloc = 0;
  123.     int        i;
  124.     DIR        *dirp;
  125.  
  126. #ifdef SYSV
  127.     struct dirent    *dp;
  128. #else /* def SYSV */
  129.     struct direct    *dp;
  130. #endif /* def SYSV */
  131.  
  132.     char        *str;
  133.     int        len;
  134.     int        maxChars;
  135.     struct stat    statBuf;
  136.  
  137.     maxChars = strlen(dir->dir) - 1;
  138.  
  139.     dir->entries = NULL;
  140.     dir->nEntries = 0;
  141.     dir->nChars = 0;
  142.  
  143.     result = NULL;
  144.     i = 0;
  145.  
  146.     dirp = opendir(".");
  147.     if (!dirp) {
  148.         return 1;
  149.     }
  150.  
  151.     (void) fstat(dirp->dd_fd, &statBuf);
  152.     dir->st_mtime = statBuf.st_mtime;
  153.  
  154.     (void) readdir(dirp);    /* throw away "." */
  155.  
  156. #ifndef S_IFLNK
  157.     (void) readdir(dirp);    /* throw away ".." */
  158. #endif /* ndef S_IFLNK */
  159.  
  160.     while (dp = readdir(dirp)) {
  161.         if (i >= alloc) {
  162.             alloc = 2 * (alloc + 1);
  163.             result = (SFEntry *) XtRealloc((char *) result,
  164.                 (unsigned) (alloc * sizeof(SFEntry)));
  165.         }
  166.         result[i].statDone = 0;
  167.         str = dp->d_name;
  168.         len = strlen(str);
  169.         result[i].real = XtMalloc((unsigned) (len + 2));
  170.         (void) strcat(strcpy(result[i].real, str), " ");
  171.         if (len > maxChars) {
  172.             maxChars = len;
  173.         }
  174.         result[i].shown = result[i].real;
  175.         i++;
  176.     }
  177.  
  178. #ifdef SYSV
  179.     qsort((char *) result, (unsigned) i, sizeof(SFEntry), SFcompareEntries);
  180. #else /* def SYSV */
  181.     qsort((char *) result, i, sizeof(SFEntry), SFcompareEntries);
  182. #endif /* def SYSV */
  183.  
  184.     dir->entries = result;
  185.     dir->nEntries = i;
  186.     dir->nChars = maxChars + 1;
  187.  
  188.     closedir(dirp);
  189.  
  190.     return 0;
  191. }
  192. \End\Of\File\
  193. else
  194.   echo "will not over write ./Dir.c"
  195. fi
  196. if `test ! -s ./Draw.c`
  197. then
  198. echo "writing ./Draw.c"
  199. cat > ./Draw.c << '\End\Of\File\'
  200. #ifndef lint
  201. static char rcsid[] = "$Header: Draw.c,v 1.6 89/05/29 15:04:26 erik Exp $";
  202. #endif
  203.  
  204. /*
  205.  * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
  206.  *
  207.  * Permission to use, copy, modify, and distribute this software and its
  208.  * documentation for any purpose and without fee is hereby granted, provided
  209.  * that the above copyright notice appear in all copies and that both that
  210.  * copyright notice and this permission notice appear in supporting
  211.  * documentation, and that the name of Software Research Associates not be used
  212.  * in advertising or publicity pertaining to distribution of the software
  213.  * without specific, written prior permission.  Software Research Associates
  214.  * makes no representations about the suitability of this software for any
  215.  * purpose.  It is provided "as is" without express or implied warranty.
  216.  *
  217.  * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  218.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  219.  * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
  220.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  221.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  222.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  223.  * PERFORMANCE OF THIS SOFTWARE.
  224.  *
  225.  * Author: Erik M. van der Poel
  226.  *         Software Research Associates, Inc., Tokyo, Japan
  227.  */
  228.  
  229. #include <stdio.h>
  230. #include "SFinternal.h"
  231. #include <sys/stat.h>
  232. #include <X11/StringDefs.h>
  233.  
  234. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  235. #include <Xw/Xw.h>
  236. #include <Xw/ScrollBar.h>
  237. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  238. #include <X11/Scroll.h>
  239. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  240.  
  241. #define SF_DEFAULT_FONT "9x15"
  242.  
  243. #define ABS(x) (((x) < 0) ? (-(x)) : (x))
  244.  
  245. typedef struct {
  246.     char *fontname;
  247. } TextData, *textPtr;
  248.  
  249. int SFcharWidth, SFcharAscent, SFcharHeight;
  250.  
  251. int SFcurrentInvert[3] = { -1, -1, -1 };
  252.  
  253. static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC;
  254.  
  255. static XtResource textResources[] = {
  256.     {XtNfont, XtCFont, XtRString, sizeof (char *),
  257.         XtOffset(textPtr, fontname), XtRString, SF_DEFAULT_FONT},
  258. };
  259.  
  260. static XFontStruct *SFfont;
  261.  
  262. static int SFcurrentListY;
  263.  
  264. static XtIntervalId SFscrollTimerId;
  265.  
  266. SFinitFont()
  267. {
  268.     TextData    *data;
  269.  
  270.     data = XtNew(TextData);
  271.  
  272.     XtGetApplicationResources(selFileForm, (caddr_t) data, textResources,
  273.         XtNumber(textResources), (Arg *) NULL, 0);
  274.  
  275.     SFfont = XLoadQueryFont(SFdisplay, data->fontname);
  276.     if (!SFfont) {
  277.         SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT);
  278.         if (!SFfont) {
  279.             char    sbuf[256];
  280.  
  281.             (void) sprintf(sbuf, "XsraSelFile: can't get font %s",
  282.                 SF_DEFAULT_FONT);
  283.             XtAppError(SFapp, sbuf);
  284.         }
  285.     }
  286.  
  287.     SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2;
  288.     SFcharAscent = SFfont->max_bounds.ascent;
  289.     SFcharHeight = SFcharAscent + SFfont->max_bounds.descent;
  290. }
  291.  
  292. SFcreateGC()
  293. {
  294.     XGCValues    gcValues;
  295.     XRectangle    rectangles[1];
  296.  
  297.     gcValues.foreground = SFfore;
  298.  
  299.     SFlineGC = XtGetGC(
  300.         selFileLists[0],
  301.         (XtGCMask)
  302.             GCForeground        |
  303.             0,
  304.         &gcValues
  305.     );
  306.  
  307.     SFscrollGC = XtGetGC(
  308.         selFileLists[0],
  309.         (XtGCMask)
  310.             0,
  311.         &gcValues
  312.     );
  313.  
  314.     gcValues.function = GXinvert;
  315.     gcValues.plane_mask = (SFfore ^ SFback);
  316.  
  317.     SFinvertGC = XtGetGC(
  318.         selFileLists[0],
  319.         (XtGCMask)
  320.             GCFunction        |
  321.             GCPlaneMask        |
  322.             0,
  323.         &gcValues
  324.     );
  325.  
  326.     gcValues.foreground = SFfore;
  327.     gcValues.background = SFback;
  328.     gcValues.font = SFfont->fid;
  329.  
  330.     SFtextGC = XCreateGC(
  331.         SFdisplay,
  332.         XtWindow(selFileLists[0]),
  333.         (u_long)
  334.             GCForeground        |
  335.             GCBackground        |
  336.             GCFont            |
  337.             0,
  338.         &gcValues
  339.     );
  340.  
  341.     rectangles[0].x = SFlineToTextH + SFbesideText;
  342.     rectangles[0].y = 0;
  343.     rectangles[0].width = SFcharsPerEntry * SFcharWidth;
  344.     rectangles[0].height = SFupperY + 1;
  345.  
  346.     XSetClipRectangles(
  347.         SFdisplay,
  348.         SFtextGC,
  349.         0,
  350.         0,
  351.         rectangles,
  352.         1,
  353.         Unsorted
  354.     );
  355. }
  356.  
  357. SFclearList(n, doScroll)
  358.     int    n;
  359.     int    doScroll;
  360. {
  361.     SFDir    *dir;
  362.  
  363. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  364.     int    i;
  365.     Arg    arglist[20];
  366. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  367.  
  368.     SFcurrentInvert[n] = -1;
  369.  
  370.     XClearWindow(SFdisplay, XtWindow(selFileLists[n]));
  371.  
  372.     XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs,
  373.         2);
  374.  
  375.     if (doScroll) {
  376.         dir = &(SFdirs[SFdirPtr + n]);
  377.  
  378. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  379.         i = 0;
  380.         if (SFdirPtr + n < SFdirEnd) {
  381.             XtSetArg(arglist[i], XtNsliderMax, dir->nEntries);
  382.                                     i++;
  383.             XtSetArg(arglist[i], XtNsliderExtent,
  384.                 dir->nEntries < SFlistSize ? dir->nEntries :
  385.                 SFlistSize);                i++;
  386.             XtSetArg(arglist[i], XtNsliderOrigin, dir->vOrigin);
  387.                                     i++;
  388.         } else {
  389.             XtSetArg(arglist[i], XtNsliderMax, SFlistSize);    i++;
  390.             XtSetArg(arglist[i], XtNsliderExtent, SFlistSize);
  391.                                     i++;
  392.             XtSetArg(arglist[i], XtNsliderOrigin, 0);    i++;
  393.         }
  394.         XtSetValues(selFileVScrolls[n], arglist, i);
  395.  
  396.         i = 0;
  397.         if (SFdirPtr + n < SFdirEnd) {
  398.             XtSetArg(arglist[i], XtNsliderMax, dir->nChars);i++;
  399.             XtSetArg(arglist[i], XtNsliderExtent,
  400.                 dir->nChars < SFcharsPerEntry ? dir->nChars :
  401.                 SFcharsPerEntry);            i++;
  402.             XtSetArg(arglist[i], XtNsliderOrigin, dir->hOrigin);
  403.                                     i++;
  404.         } else {
  405.             XtSetArg(arglist[i], XtNsliderMax, SFcharsPerEntry);
  406.                                     i++;
  407.             XtSetArg(arglist[i], XtNsliderExtent, SFcharsPerEntry);
  408.                                     i++;
  409.             XtSetArg(arglist[i], XtNsliderOrigin, 0);    i++;
  410.         }
  411.         XtSetValues(selFileHScrolls[n], arglist, i);
  412. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  413.         if (SFdirPtr + n < SFdirEnd) {
  414.             XtScrollBarSetThumb(
  415.                 selFileVScrolls[n],
  416.                 (float) (((double) dir->vOrigin) /
  417.                     dir->nEntries),
  418.                 (float) (((double) ((dir->nEntries < SFlistSize)
  419.                     ? dir->nEntries : SFlistSize)) /
  420.                     dir->nEntries)
  421.             );
  422.             XtScrollBarSetThumb(
  423.                 selFileHScrolls[n],
  424.                 (float) (((double) dir->hOrigin) / dir->nChars),
  425.                 (float) (((double) ((dir->nChars <
  426.                     SFcharsPerEntry) ? dir->nChars :
  427.                     SFcharsPerEntry)) / dir->nChars)
  428.             );
  429.         } else {
  430.             XtScrollBarSetThumb(selFileVScrolls[n], (float) 0.0,
  431.                 (float) 1.0);
  432.             XtScrollBarSetThumb(selFileHScrolls[n], (float) 0.0,
  433.                 (float) 1.0);
  434.         }
  435. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  436.  
  437.     }
  438. }
  439.  
  440. static
  441. SFdeleteEntry(dir, entry)
  442.     SFDir    *dir;
  443.     SFEntry    *entry;
  444. {
  445.     register SFEntry    *e;
  446.     register SFEntry    *end;
  447.     int            n;
  448.  
  449. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  450.  
  451.     int            i;
  452.     Arg            arglist[20];
  453.  
  454. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  455.  
  456.     XtFree(entry->real);
  457.  
  458.     end = &(dir->entries[dir->nEntries - 1]);
  459.  
  460.     for (e = entry; e < end; e++) {
  461.         *e = *(e + 1);
  462.     }
  463.  
  464.     dir->nEntries--;
  465.  
  466.     n = dir - &(SFdirs[SFdirPtr]);
  467.     if ((n < 0) || (n > 2)) {
  468.         return;
  469.     }
  470.  
  471. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  472.  
  473.     i = 0;
  474.     XtSetArg(arglist[i], XtNsliderMax, dir->nEntries);        i++;
  475.     XtSetArg(arglist[i], XtNsliderExtent, dir->nEntries < SFlistSize ?
  476.         dir->nEntries : SFlistSize);                i++;
  477.     XtSetValues(selFileVScrolls[n], arglist, i);
  478.  
  479. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  480.  
  481.     XtScrollBarSetThumb(
  482.         selFileVScrolls[n],
  483.         (float) (((double) dir->vOrigin) / dir->nEntries),
  484.         (float) (((double) ((dir->nEntries < SFlistSize) ?
  485.             dir->nEntries : SFlistSize)) / dir->nEntries)
  486.     );
  487.  
  488. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  489.  
  490. }
  491.  
  492. static
  493. SFwriteStatChar(name, last, statBuf)
  494.     char        *name;
  495.     int        last;
  496.     struct stat    *statBuf;
  497. {
  498.     switch (statBuf->st_mode & S_IFMT) {
  499.     case S_IFDIR:
  500.         name[last] = '/';
  501.         break;
  502.     case S_IFREG:
  503.         if (statBuf->st_mode & 0111) {
  504.             name[last] = '*';
  505.         } else {
  506.             name[last] = ' ';
  507.         }
  508.         break;
  509.  
  510. #ifdef S_IFSOCK
  511.     case S_IFSOCK:
  512.         name[last] = '=';
  513.         break;
  514. #endif /* def S_IFSOCK */
  515.  
  516.     default:
  517.         name[last] = ' ';
  518.         break;
  519.     }
  520. }
  521.  
  522. static int
  523. SFstatAndCheck(dir, entry)
  524.     SFDir    *dir;
  525.     SFEntry    *entry;
  526. {
  527.     struct stat    statBuf;
  528.     char        save;
  529.     int        last;
  530.  
  531.     /*
  532.      * must be restored before returning
  533.      */
  534.     save = *(dir->path);
  535.     *(dir->path) = 0;
  536.  
  537.     if (!SFchdir(SFcurrentPath)) {
  538.         last = strlen(entry->real) - 1;
  539.         entry->real[last] = 0;
  540.         entry->statDone = 1;
  541.         if (!stat(entry->real, &statBuf)) {
  542.             if (SFfunc) {
  543.                 char *shown;
  544.  
  545.                 shown = NULL;
  546.                 if (SFfunc(entry->real, &shown, &statBuf)) {
  547.                     if (shown) {
  548.                         int len;
  549.  
  550.                         len = strlen(shown);
  551.                         entry->shown = XtMalloc(
  552.                             (unsigned) (len + 2)
  553.                         );
  554.                         (void) strcpy(entry->shown,
  555.                             shown);
  556.                         SFwriteStatChar(
  557.                             entry->shown,
  558.                             len,
  559.                             &statBuf
  560.                         );
  561.                         entry->shown[len + 1] = 0;
  562.                     }
  563.                 } else {
  564.                     SFdeleteEntry(dir, entry);
  565.  
  566.                     *(dir->path) = save;
  567.                     return 1;
  568.                 }
  569.             }
  570.             SFwriteStatChar(entry->real, last, &statBuf);
  571.         } else {
  572.             entry->real[last] = ' ';
  573.         }
  574.     }
  575.  
  576.     *(dir->path) = save;
  577.     return 0;
  578. }
  579.  
  580. static
  581. SFdrawStrings(w, dir, from, to)
  582.     register Window    w;
  583.     register SFDir    *dir;
  584.     register int    from;
  585.     register int    to;
  586. {
  587.     register int        i;
  588.     register SFEntry    *entry;
  589.     int            x;
  590.  
  591.     x = SFtextX - dir->hOrigin * SFcharWidth;
  592.  
  593.     if (dir->vOrigin + to >= dir->nEntries) {
  594.         to = dir->nEntries - dir->vOrigin - 1;
  595.     }
  596.     for (i = from; i <= to; i++) {
  597.         entry = &(dir->entries[dir->vOrigin + i]);
  598.         if (!(entry->statDone)) {
  599.             if (SFstatAndCheck(dir, entry)) {
  600.                 if (dir->vOrigin + to >= dir->nEntries) {
  601.                     to = dir->nEntries - dir->vOrigin - 1;
  602.                 }
  603.                 i--;
  604.                 continue;
  605.             }
  606.         }
  607.         XDrawImageString(
  608.             SFdisplay,
  609.             w,
  610.             SFtextGC,
  611.             x,
  612.             SFtextYoffset + i * SFentryHeight,
  613.             entry->shown,
  614.             strlen(entry->shown)
  615.         );
  616.         if (dir->vOrigin + i == dir->beginSelection) {
  617.             XDrawLine(
  618.                 SFdisplay,
  619.                 w,
  620.                 SFlineGC,
  621.                 SFlineToTextH + 1,
  622.                 SFlowerY + i * SFentryHeight,
  623.                 SFlineToTextH + SFentryWidth - 2,
  624.                 SFlowerY + i * SFentryHeight
  625.             );
  626.         }
  627.         if (
  628.             (dir->vOrigin + i >= dir->beginSelection) &&
  629.             (dir->vOrigin + i <= dir->endSelection)
  630.         ) {
  631.             SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
  632.                 SFlowerY + i * SFentryHeight;
  633.             SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
  634.                 SFlowerY + (i + 1) * SFentryHeight - 1;
  635.             XDrawSegments(
  636.                 SFdisplay,
  637.                 w,
  638.                 SFlineGC,
  639.                 SFcompletionSegs,
  640.                 2
  641.             );
  642.         }
  643.         if (dir->vOrigin + i == dir->endSelection) {
  644.             XDrawLine(
  645.                 SFdisplay,
  646.                 w,
  647.                 SFlineGC,
  648.                 SFlineToTextH + 1,
  649.                 SFlowerY + (i + 1) * SFentryHeight - 1,
  650.                 SFlineToTextH + SFentryWidth - 2,
  651.                 SFlowerY + (i + 1) * SFentryHeight - 1
  652.             );
  653.         }
  654.     }
  655. }
  656.  
  657. SFdrawList(n, doScroll)
  658.     int    n;
  659.     int    doScroll;
  660. {
  661.     SFDir    *dir;
  662.     Window    w;
  663.  
  664.     SFclearList(n, doScroll);
  665.  
  666.     if (SFdirPtr + n < SFdirEnd) {
  667.         dir = &(SFdirs[SFdirPtr + n]);
  668.         w = XtWindow(selFileLists[n]);
  669.         XDrawImageString(
  670.             SFdisplay,
  671.             w,
  672.             SFtextGC,
  673.             SFtextX - dir->hOrigin * SFcharWidth,
  674.             SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
  675.             dir->dir,
  676.             strlen(dir->dir)
  677.         );
  678.         SFdrawStrings(w, dir, 0, SFlistSize - 1);
  679.     }
  680. }
  681.  
  682. SFdrawLists(doScroll)
  683.     int    doScroll;
  684. {
  685.     int    i;
  686.  
  687.     for (i = 0; i < 3; i++) {
  688.         SFdrawList(i, doScroll);
  689.     }
  690. }
  691.  
  692. static
  693. SFinvertEntry(n)
  694.     register int    n;
  695. {
  696.     XFillRectangle(
  697.         SFdisplay,
  698.         XtWindow(selFileLists[n]),
  699.         SFinvertGC,
  700.         SFlineToTextH,
  701.         SFcurrentInvert[n] * SFentryHeight + SFlowerY,
  702.         SFentryWidth,
  703.         SFentryHeight
  704.     );
  705. }
  706.  
  707. static unsigned long
  708. SFscrollTimerInterval()
  709. {
  710.     static int    maxVal = 200;
  711.     static int    varyDist = 50;
  712.     static int    minDist = 50;
  713.     int        t;
  714.     int        dist;
  715.  
  716.     if (SFcurrentListY < SFlowerY) {
  717.         dist = SFlowerY - SFcurrentListY;
  718.     } else if (SFcurrentListY > SFupperY) {
  719.         dist = SFcurrentListY - SFupperY;
  720.     } else {
  721.         return (unsigned long) 1;
  722.     }
  723.  
  724.     t = maxVal - ((maxVal / varyDist) * (dist - minDist));
  725.  
  726.     if (t < 1) {
  727.         t = 1;
  728.     }
  729.  
  730.     if (t > maxVal) {
  731.         t = maxVal;
  732.     }
  733.  
  734.     return (unsigned long) t;
  735. }
  736.  
  737. static
  738. SFscrollTimer(n)
  739.     int    n;
  740. {
  741.     SFDir    *dir;
  742.     int    save;
  743.  
  744. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  745.     int    i;
  746.     Arg    arglist[20];
  747. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  748.  
  749.     dir = &(SFdirs[SFdirPtr + n]);
  750.     save = dir->vOrigin;
  751.  
  752.     if (SFcurrentListY < SFlowerY) {
  753.         if (dir->vOrigin > 0) {
  754.             SFvSliderMovedCallback(selFileVScrolls[n], n,
  755.                 dir->vOrigin - 1);
  756.         }
  757.     } else if (SFcurrentListY > SFupperY) {
  758.         if (dir->vOrigin < dir->nEntries - SFlistSize) {
  759.             SFvSliderMovedCallback(selFileVScrolls[n], n,
  760.                 dir->vOrigin + 1);
  761.         }
  762.     }
  763.  
  764.     if (dir->vOrigin != save) {
  765.  
  766. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  767.         i = 0;
  768.         XtSetArg(arglist[i], XtNsliderOrigin, dir->vOrigin);    i++;
  769.         XtSetValues(selFileVScrolls[n], arglist, i);
  770. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  771.         XtScrollBarSetThumb(
  772.             selFileVScrolls[n],
  773.             (float) (((double) dir->vOrigin) / dir->nEntries),
  774.             (float) (((double) ((dir->nEntries < SFlistSize) ?
  775.                 dir->nEntries : SFlistSize)) / dir->nEntries)
  776.         );
  777. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  778.  
  779.     }
  780.  
  781.     if (SFbuttonPressed) {
  782.         SFscrollTimerId = XtAppAddTimeOut(SFapp,
  783.             SFscrollTimerInterval(), SFscrollTimer, (caddr_t) n);
  784.     }
  785. }
  786.  
  787. static int
  788. SFnewInvertEntry(n, event)
  789.     register int        n;
  790.     register XMotionEvent    *event;
  791. {
  792.     register int    x, y;
  793.     register int    new;
  794.     static int    SFscrollTimerAdded = 0;
  795.  
  796.     x = event->x;
  797.     y = event->y;
  798.  
  799.     if (SFdirPtr + n >= SFdirEnd) {
  800.         return -1;
  801.     } else if (
  802.         (x >= 0)    && (x <= SFupperX) &&
  803.         (y >= SFlowerY)    && (y <= SFupperY)
  804.     ) {
  805.         register SFDir *dir = &(SFdirs[SFdirPtr + n]);
  806.  
  807.         if (SFscrollTimerAdded) {
  808.             SFscrollTimerAdded = 0;
  809.             XtRemoveTimeOut(SFscrollTimerId);
  810.         }
  811.  
  812.         new = (y - SFlowerY) / SFentryHeight;
  813.         if (dir->vOrigin + new >= dir->nEntries) {
  814.             return -1;
  815.         }
  816.         return new;
  817.     } else {
  818.         if (SFbuttonPressed) {
  819.             SFcurrentListY = y;
  820.             if (!SFscrollTimerAdded) {
  821.                 SFscrollTimerAdded = 1;
  822.                 SFscrollTimerId = XtAppAddTimeOut(SFapp,
  823.                     SFscrollTimerInterval(), SFscrollTimer,
  824.                     (caddr_t) n);
  825.             }
  826.         }
  827.  
  828.         return -1;
  829.     }
  830. }
  831.  
  832. /* ARGSUSED */
  833. void
  834. SFenterList(w, n, event)
  835.     Widget                w;
  836.     register int            n;
  837.     register XEnterWindowEvent    *event;
  838. {
  839.     register int    new;
  840.  
  841.     /* sanity */
  842.     if (SFcurrentInvert[n] != -1) {
  843.         SFinvertEntry(n);
  844.         SFcurrentInvert[n] = -1;
  845.     }
  846.  
  847.     new = SFnewInvertEntry(n, (XMotionEvent *) event);
  848.     if (new != -1) {
  849.         SFcurrentInvert[n] = new;
  850.         SFinvertEntry(n);
  851.     }
  852. }
  853.  
  854. /* ARGSUSED */
  855. void
  856. SFleaveList(w, n, event)
  857.     Widget        w;
  858.     register int    n;
  859.     XEvent        *event;
  860. {
  861.     if (SFcurrentInvert[n] != -1) {
  862.         SFinvertEntry(n);
  863.         SFcurrentInvert[n] = -1;
  864.     }
  865. }
  866.  
  867. /* ARGSUSED */
  868. void
  869. SFmotionList(w, n, event)
  870.     Widget            w;
  871.     register int        n;
  872.     register XMotionEvent    *event;
  873. {
  874.     register int    new;
  875.  
  876.     new = SFnewInvertEntry(n, event);
  877.  
  878.     if (new != SFcurrentInvert[n]) {
  879.         if (SFcurrentInvert[n] != -1) {
  880.             SFinvertEntry(n);
  881.         }
  882.         SFcurrentInvert[n] = new;
  883.         if (new != -1) {
  884.             SFinvertEntry(n);
  885.         }
  886.     }
  887. }
  888.  
  889. /* ARGSUSED */
  890.  
  891. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  892. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  893. SFvFloatSliderMovedCallback(w, n, fnew)
  894.     Widget    w;
  895.     int    n;
  896.     float    *fnew;
  897. {
  898.     int    new;
  899.  
  900.     new = (*fnew) * SFdirs[SFdirPtr + n].nEntries;
  901.  
  902.     SFvSliderMovedCallback(w, n, new);
  903. }
  904. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  905.  
  906. /* ARGSUSED */
  907. SFvSliderMovedCallback(w, n, new)
  908.     Widget    w;
  909.     int    n;
  910.     int    new;
  911. {
  912.     int        old;
  913.     register Window    win;
  914.     SFDir        *dir;
  915.  
  916.     dir = &(SFdirs[SFdirPtr + n]);
  917.  
  918.     old = dir->vOrigin;
  919.     dir->vOrigin = new;
  920.  
  921. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  922. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  923.     if (old == new) {
  924.         return;
  925.     }
  926. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  927.  
  928.     win = XtWindow(selFileLists[n]);
  929.  
  930.     if (ABS(new - old) < SFlistSize) {
  931.         if (new > old) {
  932.             XCopyArea(
  933.                 SFdisplay,
  934.                 win,
  935.                 win,
  936.                 SFscrollGC,
  937.                 SFlineToTextH,
  938.                 SFlowerY + (new - old) * SFentryHeight,
  939.                 SFentryWidth + SFlineToTextH,
  940.                 (SFlistSize - (new - old)) * SFentryHeight,
  941.                 SFlineToTextH,
  942.                 SFlowerY
  943.             );
  944.             XClearArea(
  945.                 SFdisplay,
  946.                 win,
  947.                 SFlineToTextH,
  948.                 SFlowerY + (SFlistSize - (new - old)) *
  949.                     SFentryHeight,
  950.                 SFentryWidth + SFlineToTextH,
  951.                 (new - old) * SFentryHeight,
  952.                 False
  953.             );
  954.             SFdrawStrings(win, dir, SFlistSize - (new - old),
  955.                 SFlistSize - 1);
  956.         } else {
  957.             XCopyArea(
  958.                 SFdisplay,
  959.                 win,
  960.                 win,
  961.                 SFscrollGC,
  962.                 SFlineToTextH,
  963.                 SFlowerY,
  964.                 SFentryWidth + SFlineToTextH,
  965.                 (SFlistSize - (old - new)) * SFentryHeight,
  966.                 SFlineToTextH,
  967.                 SFlowerY + (old - new) * SFentryHeight
  968.             );
  969.             XClearArea(
  970.                 SFdisplay,
  971.                 win,
  972.                 SFlineToTextH,
  973.                 SFlowerY,
  974.                 SFentryWidth + SFlineToTextH,
  975.                 (old - new) * SFentryHeight,
  976.                 False
  977.             );
  978.             SFdrawStrings(win, dir, 0, old - new);
  979.         }
  980.     } else {
  981.         XClearArea(
  982.             SFdisplay,
  983.             win,
  984.             SFlineToTextH,
  985.             SFlowerY,
  986.             SFentryWidth + SFlineToTextH,
  987.             SFlistSize * SFentryHeight,
  988.             False
  989.         );
  990.         SFdrawStrings(win, dir, 0, SFlistSize - 1);
  991.     }
  992. }
  993.  
  994. /* ARGSUSED */
  995.  
  996. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  997. SFvAreaSelectedCallback(w, n, new)
  998.     Widget    w;
  999.     int    n;
  1000.     int    new;
  1001. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1002. SFvAreaSelectedCallback(w, n, pnew)
  1003.     Widget    w;
  1004.     int    n;
  1005.     int    pnew;
  1006. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1007.  
  1008. {
  1009.     SFDir    *dir;
  1010.  
  1011. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1012.     int    i;
  1013.     Arg    arglist[20];
  1014. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1015.     int    new;
  1016. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1017.  
  1018.     dir = &(SFdirs[SFdirPtr + n]);
  1019.  
  1020. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1021.     new -= (SFlistSize / 2);
  1022. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1023.     new = dir->vOrigin +
  1024.         (((double) pnew) / SFvScrollHeight) * dir->nEntries;
  1025. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1026.  
  1027.     if (new > dir->nEntries - SFlistSize) {
  1028.         new = dir->nEntries - SFlistSize;
  1029.     }
  1030.  
  1031.     if (new < 0) {
  1032.         new = 0;
  1033.     }
  1034.  
  1035. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1036.     i = 0;
  1037.     XtSetArg(arglist[i], XtNsliderOrigin, new);            i++;
  1038.     XtSetValues(w, arglist, i);
  1039. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1040.     {
  1041.         float    f;
  1042.  
  1043.         f = ((double) new) / dir->nEntries;
  1044.         XtScrollBarSetThumb(
  1045.             w,
  1046.             f,
  1047.             (float) (((double) ((dir->nEntries < SFlistSize) ?
  1048.                 dir->nEntries : SFlistSize)) / dir->nEntries)
  1049.         );
  1050.     }
  1051. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1052.  
  1053.     SFvSliderMovedCallback(w, n, new);
  1054. }
  1055.  
  1056. /* ARGSUSED */
  1057. SFhSliderMovedCallback(w, n, new)
  1058.     Widget    w;
  1059.     int    n;
  1060.  
  1061. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1062.     int    new;
  1063. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1064.     float    *new;
  1065. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1066.  
  1067. {
  1068.  
  1069. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1070.     SFdirs[SFdirPtr + n].hOrigin = new;
  1071. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1072.     {
  1073.         SFDir    *dir;
  1074.         int    save;
  1075.  
  1076.         dir = &(SFdirs[SFdirPtr + n]);
  1077.         save = dir->hOrigin;
  1078.         dir->hOrigin = (*new) * dir->nChars;
  1079.         if (dir->hOrigin == save) {
  1080.             return;
  1081.         }
  1082.     }
  1083. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1084.  
  1085.     SFdrawList(n, SF_DO_NOT_SCROLL);
  1086. }
  1087.  
  1088. /* ARGSUSED */
  1089.  
  1090. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1091. SFhAreaSelectedCallback(w, n, new)
  1092.     Widget    w;
  1093.     int    n;
  1094.     int    new;
  1095. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1096. SFhAreaSelectedCallback(w, n, pnew)
  1097.     Widget    w;
  1098.     int    n;
  1099.     int    pnew;
  1100. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1101.  
  1102. {
  1103.     SFDir    *dir;
  1104.  
  1105. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1106.     int    i;
  1107.     Arg    arglist[20];
  1108. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1109.     int    new;
  1110. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1111.  
  1112.     dir = &(SFdirs[SFdirPtr + n]);
  1113.  
  1114. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1115.     new -= (SFcharsPerEntry / 2);
  1116. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1117.     new = dir->hOrigin +
  1118.         (((double) pnew) / SFhScrollWidth) * dir->nChars;
  1119. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1120.  
  1121.     if (new > dir->nChars - SFcharsPerEntry) {
  1122.         new = dir->nChars - SFcharsPerEntry;
  1123.     }
  1124.  
  1125.     if (new < 0) {
  1126.         new = 0;
  1127.     }
  1128.  
  1129. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1130.     i = 0;
  1131.     XtSetArg(arglist[i], XtNsliderOrigin, new);            i++;
  1132.     XtSetValues(w, arglist, i);
  1133.  
  1134.     SFhSliderMovedCallback(w, n, new);
  1135. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1136.     {
  1137.         float    f;
  1138.  
  1139.         f = ((double) new) / dir->nChars;
  1140.         XtScrollBarSetThumb(
  1141.             w,
  1142.             f,
  1143.             (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
  1144.                 dir->nChars : SFcharsPerEntry)) / dir->nChars)
  1145.         );
  1146.  
  1147.         SFhSliderMovedCallback(w, n, &f);
  1148.     }
  1149. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1150.  
  1151. }
  1152.  
  1153. /* ARGSUSED */
  1154. SFpathSliderMovedCallback(w, client_data, new)
  1155.     Widget    w;
  1156.     caddr_t    client_data;
  1157.  
  1158. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1159.     int    new;
  1160. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1161.     float    *new;
  1162. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1163.  
  1164. {
  1165.     SFDir        *dir;
  1166.     int        n;
  1167.  
  1168. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWTEXTEDIT)
  1169.     XwTextPosition    pos;
  1170. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWTEXTEDIT) */
  1171.     XtTextPosition    pos;
  1172. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWTEXTEDIT) */
  1173.  
  1174. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1175.     SFdirPtr = new;
  1176. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1177.     {
  1178.         int    SFdirPtrSave;
  1179.  
  1180.         SFdirPtrSave = SFdirPtr;
  1181.         SFdirPtr = (*new) * SFdirEnd;
  1182.         if (SFdirPtr == SFdirPtrSave) {
  1183.             return;
  1184.         }
  1185.     }
  1186. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1187.  
  1188.     SFdrawLists(SF_DO_SCROLL);
  1189.  
  1190.     n = 2;
  1191.     while (SFdirPtr + n >= SFdirEnd) {
  1192.         n--;
  1193.     }
  1194.  
  1195.     dir = &(SFdirs[SFdirPtr + n]);
  1196.  
  1197.     pos = dir->path - SFcurrentPath;
  1198.  
  1199.     if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
  1200.         pos -= strlen(SFstartDir);
  1201.         if (pos < 0) {
  1202.             pos = 0;
  1203.         }
  1204.     }
  1205.  
  1206. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWTEXTEDIT)
  1207.     XwTextSetInsertPos(selFileField, pos);
  1208. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWTEXTEDIT) */
  1209.     XtTextSetInsertionPoint(selFileField, pos);
  1210. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWTEXTEDIT) */
  1211.  
  1212. }
  1213.  
  1214. /* ARGSUSED */
  1215.  
  1216. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1217. SFpathAreaSelectedCallback(w, client_data, new)
  1218.     Widget    w;
  1219.     caddr_t    client_data;
  1220.     int    new;
  1221. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1222. SFpathAreaSelectedCallback(w, client_data, pnew)
  1223.     Widget    w;
  1224.     caddr_t    client_data;
  1225.     int    pnew;
  1226. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1227.  
  1228. {
  1229.  
  1230. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1231.     int    i;
  1232.     Arg    arglist[20];
  1233. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1234.     int    new;
  1235. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1236.  
  1237. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1238.     new -= (3 / 2);
  1239. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1240.     new = SFdirPtr + (((double) pnew) / SFpathScrollWidth) * SFdirEnd;
  1241. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1242.  
  1243.     if (new > SFdirEnd - 3) {
  1244.         new = SFdirEnd - 3;
  1245.     }
  1246.  
  1247.     if (new < 0) {
  1248.         new = 0;
  1249.     }
  1250.  
  1251. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1252.     i = 0;
  1253.     XtSetArg(arglist[i], XtNsliderOrigin, new);            i++;
  1254.     XtSetValues(w, arglist, i);
  1255.  
  1256.     SFpathSliderMovedCallback(w, client_data, new);
  1257. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1258.     {
  1259.         float    f;
  1260.  
  1261.         f = ((double) new) / SFdirEnd;
  1262.         XtScrollBarSetThumb(
  1263.             w,
  1264.             f,
  1265.             (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
  1266.                 SFdirEnd)
  1267.         );
  1268.  
  1269.         SFpathSliderMovedCallback(w, (caddr_t) NULL, &f);
  1270.     }
  1271. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1272.  
  1273. }
  1274.  
  1275. Boolean
  1276. SFworkProc()
  1277. {
  1278.     register SFDir        *dir;
  1279.     register SFEntry    *entry;
  1280.  
  1281.     for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) {
  1282.         for (
  1283.             entry = &(dir->entries[dir->nEntries - 1]);
  1284.             entry >= dir->entries;
  1285.             entry--
  1286.         ) {
  1287.             if (!(entry->statDone)) {
  1288.                 (void) SFstatAndCheck(dir, entry);
  1289.                 return False;
  1290.             }
  1291.         }
  1292.     }
  1293.  
  1294.     SFworkProcAdded = 0;
  1295.  
  1296.     return True;
  1297. }
  1298. \End\Of\File\
  1299. else
  1300.   echo "will not over write ./Draw.c"
  1301. fi
  1302. if `test ! -s ./FILES`
  1303. then
  1304. echo "writing ./FILES"
  1305. cat > ./FILES << '\End\Of\File\'
  1306. Dir.c
  1307. Draw.c
  1308. FILES
  1309. Imakefile
  1310. Path.c
  1311. README
  1312. SFinternal.h
  1313. SelFile.c
  1314. SelFile.man
  1315. TODO
  1316. callback.c
  1317. xdir.c
  1318. \End\Of\File\
  1319. else
  1320.   echo "will not over write ./FILES"
  1321. fi
  1322. if `test ! -s ./Imakefile`
  1323. then
  1324. echo "writing ./Imakefile"
  1325. cat > ./Imakefile << '\End\Of\File\'
  1326. #
  1327. # This file describes how to build xdir, a simple application that uses the
  1328. # XsraSelFile file selection dialog package.
  1329. #
  1330. # The program is linked with Athena widgets (Xaw) by default. It can be linked
  1331. # with Hewlett-Packard widgets (Xw) by defining one or more of the defines below
  1332. # and adding Xw to the list of libraries. Defining `SEL_FILE_XW' is equivalent
  1333. # to defining all of them.
  1334. #
  1335. # -DSEL_FILE_XWFORM
  1336. # -DSEL_FILE_XWPUSHBUTTON
  1337. # -DSEL_FILE_XWSCROLLBAR
  1338. # -DSEL_FILE_XWSTATICTEXT
  1339. # -DSEL_FILE_XWTEXTEDIT
  1340. #
  1341. # -DSEL_FILE_XW
  1342. #
  1343. #        DEFINES = -DSEL_FILE_XW
  1344.  
  1345.            SRCS = xdir.c SelFile.c Dir.c Path.c Draw.c
  1346.            OBJS = xdir.o SelFile.o Dir.o Path.o Draw.o
  1347.  
  1348.           XWLIB = $(CONTRIBSRC)/widgets/Xhp/lib/libXw.a
  1349. LOCAL_LIBRARIES = $(XAWLIB) $(XMULIB) $(XTOOLLIB) $(XLIB)
  1350. #LOCAL_LIBRARIES = $(XWLIB) $(XAWLIB) $(XMULIB) $(XTOOLLIB) $(XLIB)
  1351.  
  1352. ComplexProgramTarget(xdir)
  1353.  
  1354. NormalLintTarget($(SRCS))
  1355. \End\Of\File\
  1356. else
  1357.   echo "will not over write ./Imakefile"
  1358. fi
  1359. if `test ! -s ./Path.c`
  1360. then
  1361. echo "writing ./Path.c"
  1362. cat > ./Path.c << '\End\Of\File\'
  1363. #ifndef lint
  1364. static char rcsid[] = "$Header: Path.c,v 1.5 89/05/29 15:05:30 erik Exp $";
  1365. #endif
  1366.  
  1367. /*
  1368.  * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
  1369.  *
  1370.  * Permission to use, copy, modify, and distribute this software and its
  1371.  * documentation for any purpose and without fee is hereby granted, provided
  1372.  * that the above copyright notice appear in all copies and that both that
  1373.  * copyright notice and this permission notice appear in supporting
  1374.  * documentation, and that the name of Software Research Associates not be used
  1375.  * in advertising or publicity pertaining to distribution of the software
  1376.  * without specific, written prior permission.  Software Research Associates
  1377.  * makes no representations about the suitability of this software for any
  1378.  * purpose.  It is provided "as is" without express or implied warranty.
  1379.  *
  1380.  * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  1381.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  1382.  * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
  1383.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  1384.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  1385.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  1386.  * PERFORMANCE OF THIS SOFTWARE.
  1387.  *
  1388.  * Author: Erik M. van der Poel
  1389.  *         Software Research Associates, Inc., Tokyo, Japan
  1390.  */
  1391.  
  1392. #include <stdio.h>
  1393.  
  1394. #ifdef SEL_FILE_IGNORE_CASE
  1395. #include <ctype.h>
  1396. #endif /* def SEL_FILE_IGNORE_CASE */
  1397.  
  1398. #include <pwd.h>
  1399. #include "SFinternal.h"
  1400. #include <sys/stat.h>
  1401.  
  1402. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1403. #include <Xw/Xw.h>
  1404. #include <Xw/ScrollBar.h>
  1405. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1406. #include <X11/Scroll.h>
  1407. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1408.  
  1409. #ifdef SYSV
  1410. extern unsigned short getuid();
  1411. extern void qsort();
  1412. #endif /* def SYSV */
  1413.  
  1414. typedef struct {
  1415.     char    *name;
  1416.     char    *dir;
  1417. } SFLogin;
  1418.  
  1419. SFDir *SFdirs = NULL;
  1420.  
  1421. int SFdirEnd;
  1422.  
  1423. int SFdirPtr;
  1424.  
  1425. int SFbuttonPressed = 0;
  1426.  
  1427. static int SFdoNotTouchDirPtr = 0;
  1428.  
  1429. static int SFdoNotTouchVorigin = 0;
  1430.  
  1431. static SFDir SFrootDir, SFhomeDir;
  1432.  
  1433. static SFLogin *SFlogins;
  1434.  
  1435. static int SFtwiddle = 0;
  1436.  
  1437. int
  1438. SFchdir(path)
  1439.     char    *path;
  1440. {
  1441.     int    result;
  1442.  
  1443.     result = 0;
  1444.  
  1445.     if (strcmp(path, SFcurrentDir)) {
  1446.         result = chdir(path);
  1447.         if (!result) {
  1448.             (void) strcpy(SFcurrentDir, path);
  1449.         }
  1450.     }
  1451.  
  1452.     return result;
  1453. }
  1454.  
  1455. static
  1456. SFfree(i)
  1457.     int    i;
  1458. {
  1459.     register SFDir    *dir;
  1460.     register int    j;
  1461.  
  1462.     dir = &(SFdirs[i]);
  1463.  
  1464.     for (j = dir->nEntries - 1; j >= 0; j--) {
  1465.         if (dir->entries[j].shown != dir->entries[j].real) {
  1466.             XtFree(dir->entries[j].shown);
  1467.         }
  1468.         XtFree(dir->entries[j].real);
  1469.     }
  1470.  
  1471.     XtFree((char *) dir->entries);
  1472.  
  1473.     XtFree(dir->dir);
  1474.  
  1475.     dir->dir = NULL;
  1476. }
  1477.  
  1478. static
  1479. SFunreadableDir(dir)
  1480.     SFDir    *dir;
  1481. {
  1482.     char    *cannotOpen = "<cannot open> ";
  1483.  
  1484.     dir->entries = (SFEntry *) XtMalloc(sizeof(SFEntry));
  1485.     dir->entries[0].statDone = 1;
  1486.     dir->entries[0].real = XtMalloc((unsigned) (strlen(cannotOpen) + 1));
  1487.     (void) strcpy(dir->entries[0].real, cannotOpen);
  1488.     dir->entries[0].shown = dir->entries[0].real;
  1489.     dir->nEntries = 1;
  1490.     dir->nChars = strlen(cannotOpen);
  1491. }
  1492.  
  1493. #ifdef SEL_FILE_IGNORE_CASE
  1494. static
  1495. SFstrncmp(p, q, n)
  1496.     register char    *p, *q;
  1497.     register int    n;
  1498. {
  1499.     register char    c1, c2;
  1500.     char        *psave, *qsave;
  1501.     int        nsave;
  1502.  
  1503.     psave = p;
  1504.     qsave = q;
  1505.     nsave = n;
  1506.  
  1507.     c1 = *p++;
  1508.     if (islower(c1)) {
  1509.         c1 = toupper(c1);
  1510.     }
  1511.     c2 = *q++;
  1512.     if (islower(c2)) {
  1513.         c2 = toupper(c2);
  1514.     }
  1515.  
  1516.     while ((--n >= 0) && (c1 == c2)) {
  1517.         if (!c1) {
  1518.             return strncmp(psave, qsave, nsave);
  1519.         }
  1520.         c1 = *p++;
  1521.         if (islower(c1)) {
  1522.             c1 = toupper(c1);
  1523.         }
  1524.         c2 = *q++;
  1525.         if (islower(c2)) {
  1526.             c2 = toupper(c2);
  1527.         }
  1528.     }
  1529.  
  1530.     if (n < 0) {
  1531.         return strncmp(psave, qsave, nsave);
  1532.     }
  1533.  
  1534.     return c1 - c2;
  1535. }
  1536. #endif /* def SEL_FILE_IGNORE_CASE */
  1537.  
  1538. static
  1539. SFreplaceText(dir, str)
  1540.     SFDir    *dir;
  1541.     char    *str;
  1542. {
  1543.     int    len;
  1544.  
  1545.     *(dir->path) = 0;
  1546.     len = strlen(str);
  1547.     if (str[len - 1] == '/') {
  1548.         (void) strcat(SFcurrentPath, str);
  1549.     } else {
  1550.         (void) strncat(SFcurrentPath, str, len - 1);
  1551.     }
  1552.     if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
  1553.         SFsetText(SFcurrentPath);
  1554.     } else {
  1555.         SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
  1556.     }
  1557.  
  1558.     SFtextChanged();
  1559. }
  1560.  
  1561. static int
  1562. SFexpand(str)
  1563.     char    *str;
  1564. {
  1565.     int    len;
  1566.     int    cmp;
  1567.     char    *name, *growing;
  1568.     SFDir    *dir;
  1569.     SFEntry    *entry, *max;
  1570.  
  1571.     len = strlen(str);
  1572.  
  1573.     dir = &(SFdirs[SFdirEnd - 1]);
  1574.  
  1575.     if (dir->beginSelection == -1) {
  1576.         str = strcpy(XtMalloc((unsigned) (strlen(str) + 1)), str);
  1577.         SFreplaceText(dir, str);
  1578.         XtFree(str);
  1579.         return;
  1580.     } else if (dir->beginSelection == dir->endSelection) {
  1581.         SFreplaceText(dir, dir->entries[dir->beginSelection].shown);
  1582.         return;
  1583.     }
  1584.  
  1585.     max = &(dir->entries[dir->endSelection + 1]);
  1586.  
  1587.     name = dir->entries[dir->beginSelection].shown;
  1588.     (void) strcpy((growing = XtMalloc((unsigned) (strlen(name) + 1))),
  1589.         name);
  1590.  
  1591.     cmp = 0;
  1592.     while (!cmp) {
  1593.         entry = &(dir->entries[dir->beginSelection]);
  1594.         while (entry < max) {
  1595.             if (cmp = strncmp(growing, entry->shown, len)) {
  1596.                 break;
  1597.             }
  1598.             entry++;
  1599.         }
  1600.         len++;
  1601.     }
  1602.  
  1603.     /*
  1604.      * SFreplaceText() expects filename
  1605.      */
  1606.     growing[len - 2] = ' ';
  1607.  
  1608.     growing[len - 1] = 0;
  1609.     SFreplaceText(dir, growing);
  1610.     XtFree(growing);
  1611. }
  1612.  
  1613. static int
  1614. SFfindFile(dir, str)
  1615.     SFDir        *dir;
  1616.     register char    *str;
  1617. {
  1618.     register int    i, last, max;
  1619.     register char    *name, save;
  1620.     SFEntry        *entries;
  1621.     int        len;
  1622.     int        begin, end;
  1623.     int        result;
  1624.  
  1625.     len = strlen(str);
  1626.  
  1627.     if (str[len - 1] == ' ') {
  1628.         SFexpand(str);
  1629.         return 1;
  1630.     } else if (str[len - 1] == '/') {
  1631.         len--;
  1632.     }
  1633.  
  1634.     max = dir->nEntries;
  1635.  
  1636.     entries = dir->entries;
  1637.  
  1638.     i = 0;
  1639.     while (i < max) {
  1640.         name = entries[i].shown;
  1641.         last = strlen(name) - 1;
  1642.         save = name[last];
  1643.         name[last] = 0;
  1644.  
  1645. #ifdef SEL_FILE_IGNORE_CASE
  1646.         result = SFstrncmp(str, name, len);
  1647. #else /* def SEL_FILE_IGNORE_CASE */
  1648.         result = strncmp(str, name, len);
  1649. #endif /* def SEL_FILE_IGNORE_CASE */
  1650.  
  1651.         name[last] = save;
  1652.         if (result <= 0) {
  1653.             break;
  1654.         }
  1655.         i++;
  1656.     }
  1657.     begin = i;
  1658.     while (i < max) {
  1659.         name = entries[i].shown;
  1660.         last = strlen(name) - 1;
  1661.         save = name[last];
  1662.         name[last] = 0;
  1663.  
  1664. #ifdef SEL_FILE_IGNORE_CASE
  1665.         result = SFstrncmp(str, name, len);
  1666. #else /* def SEL_FILE_IGNORE_CASE */
  1667.         result = strncmp(str, name, len);
  1668. #endif /* def SEL_FILE_IGNORE_CASE */
  1669.  
  1670.         name[last] = save;
  1671.         if (result) {
  1672.             break;
  1673.         }
  1674.         i++;
  1675.     }
  1676.     end = i;
  1677.  
  1678.     if (begin != end) {
  1679.         if (
  1680.             (dir->beginSelection != begin) ||
  1681.             (dir->endSelection != end - 1)
  1682.         ) {
  1683.             dir->changed = 1;
  1684.             dir->beginSelection = begin;
  1685.             if (str[strlen(str) - 1] == '/') {
  1686.                 dir->endSelection = begin;
  1687.             } else {
  1688.                 dir->endSelection = end - 1;
  1689.             }
  1690.         }
  1691.     } else {
  1692.         if (dir->beginSelection != -1) {
  1693.             dir->changed = 1;
  1694.             dir->beginSelection = -1;
  1695.             dir->endSelection = -1;
  1696.         }
  1697.     }
  1698.  
  1699.     if (
  1700.         SFdoNotTouchVorigin ||
  1701.         ((begin > dir->vOrigin) && (end < dir->vOrigin + SFlistSize))
  1702.     ) {
  1703.         SFdoNotTouchVorigin = 0;
  1704.         return 0;
  1705.     }
  1706.  
  1707.     i = begin - 1;
  1708.     if (i > max - SFlistSize) {
  1709.         i = max - SFlistSize;
  1710.     }
  1711.     if (i < 0) {
  1712.         i = 0;
  1713.     }
  1714.  
  1715.     if (dir->vOrigin != i) {
  1716.         dir->vOrigin = i;
  1717.         dir->changed = 1;
  1718.     }
  1719.  
  1720.     return 0;
  1721. }
  1722.  
  1723. static
  1724. SFunselect()
  1725. {
  1726.     SFDir    *dir;
  1727.  
  1728.     dir = &(SFdirs[SFdirEnd - 1]);
  1729.     if (dir->beginSelection != -1) {
  1730.         dir->changed = 1;
  1731.     }
  1732.     dir->beginSelection = -1;
  1733.     dir->endSelection = -1;
  1734. }
  1735.  
  1736. static int
  1737. SFcompareLogins(p, q)
  1738.     SFLogin    *p, *q;
  1739. {
  1740.     return strcmp(p->name, q->name);
  1741. }
  1742.  
  1743. static
  1744. SFgetHomeDirs()
  1745. {
  1746.     struct passwd    *pw;
  1747.     struct stat    statBuf;
  1748.     int        alloc;
  1749.     int        i;
  1750.     SFEntry        *entries;
  1751.     int        len;
  1752.     int        maxChars;
  1753.  
  1754.     alloc = 0;
  1755.     i = 0;
  1756.  
  1757.     maxChars = -1;
  1758.  
  1759.     if (pw = getpwuid((int) getuid())) {
  1760.         if (
  1761.             (!stat(pw->pw_dir, &statBuf)) &&
  1762.             ((statBuf.st_mode & S_IFMT) == S_IFDIR)
  1763.         ) {
  1764.             alloc = 1;
  1765.             i = 1;
  1766.             entries = (SFEntry *) XtMalloc(sizeof(SFEntry));
  1767.             SFlogins = (SFLogin *) XtMalloc(sizeof(SFLogin));
  1768.             entries[0].real = XtMalloc(2);
  1769.             (void) strcpy(entries[0].real, "~");
  1770.             entries[0].shown = entries[0].real;
  1771.             entries[0].statDone = 1;
  1772.             SFlogins[0].name = "";
  1773.             SFlogins[0].dir = XtMalloc((unsigned)
  1774.                 (strlen(pw->pw_dir) + 1));
  1775.             (void) strcpy(SFlogins[0].dir, pw->pw_dir);
  1776.         }
  1777.     }
  1778.  
  1779.     (void) setpwent();
  1780.  
  1781.     while ((pw = getpwent()) && (*(pw->pw_name))) {
  1782.         if (
  1783.             (!stat(pw->pw_dir, &statBuf)) &&
  1784.             ((statBuf.st_mode & S_IFMT) == S_IFDIR)
  1785.         ) {
  1786.             if (i >= alloc) {
  1787.                 alloc *= 2;
  1788.                 entries = (SFEntry *) XtRealloc(
  1789.                     (char *) entries,
  1790.                     (unsigned) (alloc * sizeof(SFEntry))
  1791.                 );
  1792.                 SFlogins = (SFLogin *) XtRealloc(
  1793.                     (char *) SFlogins,
  1794.                     (unsigned) (alloc * sizeof(SFLogin))
  1795.                 );
  1796.             }
  1797.             len = strlen(pw->pw_name);
  1798.             entries[i].real = XtMalloc((unsigned) (len + 3));
  1799.             (void) strcat(strcpy(entries[i].real, "~"),
  1800.                 pw->pw_name);
  1801.             entries[i].shown = entries[i].real;
  1802.             entries[i].statDone = 1;
  1803.             if (len > maxChars) {
  1804.                 maxChars = len;
  1805.             }
  1806.             SFlogins[i].name = XtMalloc((unsigned)
  1807.                 (strlen(pw->pw_name) + 1));
  1808.             (void) strcpy(SFlogins[i].name, pw->pw_name);
  1809.             SFlogins[i].dir = XtMalloc((unsigned)
  1810.                 (strlen(pw->pw_dir) + 1));
  1811.             (void) strcpy(SFlogins[i].dir, pw->pw_dir);
  1812.             i++;
  1813.         }
  1814.     }
  1815.  
  1816.     SFhomeDir.dir            = XtMalloc(1)    ;
  1817.     SFhomeDir.dir[0]        = 0        ;
  1818.     SFhomeDir.path            = SFcurrentPath    ;
  1819.     SFhomeDir.entries        = entries    ;
  1820.     SFhomeDir.nEntries        = i        ;
  1821.     SFhomeDir.vOrigin        = 0        ;    /* :-) */
  1822.     SFhomeDir.nChars        = maxChars + 2    ;
  1823.     SFhomeDir.hOrigin        = 0        ;
  1824.     SFhomeDir.changed        = 1        ;
  1825.     SFhomeDir.beginSelection    = -1        ;
  1826.     SFhomeDir.endSelection        = -1        ;
  1827.  
  1828. #ifdef SYSV
  1829.     qsort((char *) entries, (unsigned)i, sizeof(SFEntry), SFcompareEntries);
  1830.     qsort((char *) SFlogins, (unsigned)i, sizeof(SFLogin), SFcompareLogins);
  1831. #else /* def SYSV */
  1832.     qsort((char *) entries, i, sizeof(SFEntry), SFcompareEntries);
  1833.     qsort((char *) SFlogins, i, sizeof(SFLogin), SFcompareLogins);
  1834. #endif /* def SYSV */
  1835.  
  1836.     for (i--; i >= 0; i--) {
  1837.         (void) strcat(entries[i].real, "/");
  1838.     }
  1839. }
  1840.  
  1841. static int
  1842. SFfindHomeDir(begin, end)
  1843.     char    *begin, *end;
  1844. {
  1845.     char    save;
  1846.     char    *theRest;
  1847.     int    i;
  1848.  
  1849.     save = *end;
  1850.     *end = 0;
  1851.  
  1852.     for (i = SFhomeDir.nEntries - 1; i >= 0; i--) {
  1853.         if (!strcmp(SFhomeDir.entries[i].real, begin)) {
  1854.             *end = save;
  1855.             theRest = XtMalloc((unsigned) (strlen(end) + 1));
  1856.             (void) strcpy(theRest, end);
  1857.             (void) strcat(strcat(strcpy(SFcurrentPath,
  1858.                 SFlogins[i].dir), "/"), theRest);
  1859.             XtFree(theRest);
  1860.             SFsetText(SFcurrentPath);
  1861.             SFtextChanged();
  1862.             return 1;
  1863.         }
  1864.     }
  1865.  
  1866.     *end = save;
  1867.  
  1868.     return 0;
  1869. }
  1870.  
  1871. SFupdatePath()
  1872. {
  1873.     static int    alloc;
  1874.     static int    wasTwiddle = 0;
  1875.     char        *begin, *end;
  1876.     int        i, j;
  1877.     int        len;
  1878.     int        prevChange;
  1879.     int        SFdirPtrSave, SFdirEndSave;
  1880.     SFDir        *dir;
  1881.  
  1882. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  1883.     Arg        arglist[20];
  1884. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  1885.  
  1886.     if (!SFdirs) {
  1887.         SFdirs = (SFDir *) XtMalloc((alloc = 10) * sizeof(SFDir));
  1888.         dir = &(SFdirs[0]);
  1889.         dir->dir = XtMalloc(2);
  1890.         (void) strcpy(dir->dir, "/");
  1891.         (void) SFchdir("/");
  1892.         (void) SFgetDir(dir);
  1893.         for (j = 1; j < alloc; j++) {
  1894.             SFdirs[j].dir = NULL;
  1895.         }
  1896.         dir->path = SFcurrentPath + 1;
  1897.         dir->vOrigin = 0;
  1898.         dir->hOrigin = 0;
  1899.         dir->changed = 1;
  1900.         dir->beginSelection = -1;
  1901.         dir->endSelection = -1;
  1902.         SFrootDir = *dir;
  1903.         SFgetHomeDirs();
  1904.     }
  1905.  
  1906.     SFdirEndSave = SFdirEnd;
  1907.     SFdirEnd = 1;
  1908.  
  1909.     SFdirPtrSave = SFdirPtr;
  1910.     SFdirPtr = 0;
  1911.  
  1912.     begin = NULL;
  1913.  
  1914.     if (SFcurrentPath[0] == '~') {
  1915.         if (!SFtwiddle) {
  1916.             SFtwiddle = 1;
  1917.             dir = &(SFdirs[0]);
  1918.             *dir = SFhomeDir;
  1919.             dir->changed = 1;
  1920.         }
  1921.         end = SFcurrentPath;
  1922.         SFdoNotTouchDirPtr = 1;
  1923.         wasTwiddle = 1;
  1924.     } else {
  1925.         if (SFtwiddle) {
  1926.             SFtwiddle = 0;
  1927.             dir = &(SFdirs[0]);
  1928.             *dir = SFrootDir;
  1929.             dir->changed = 1;
  1930.         }
  1931.         end = SFcurrentPath + 1;
  1932.     }
  1933.  
  1934.     i = 0;
  1935.  
  1936.     prevChange = 0;
  1937.  
  1938.     while (*end) {
  1939.         while (*end++ == '/') {
  1940.             ;
  1941.         }
  1942.         end--;
  1943.         begin = end;
  1944.         while ((*end) && (*end++ != '/')) {
  1945.             ;
  1946.         }
  1947.         if ((end - SFcurrentPath <= SFtextPos) && (*(end - 1) == '/')) {
  1948.             SFdirPtr = i - 1;
  1949.             if (SFdirPtr < 0) {
  1950.                 SFdirPtr = 0;
  1951.             }
  1952.         }
  1953.         if (*begin) {
  1954.             if (*(end - 1) == '/') {
  1955.                 char save = *end;
  1956.  
  1957.                 if (SFtwiddle) {
  1958.                     if (SFfindHomeDir(begin, end)) {
  1959.                         return;
  1960.                     }
  1961.                 }
  1962.                 *end = 0;
  1963.                 i++;
  1964.                 SFdirEnd++;
  1965.                 if (i >= alloc) {
  1966.                     SFdirs = (SFDir *) XtRealloc(
  1967.                         (char *) SFdirs,
  1968.                         (unsigned) ((alloc *= 2) *
  1969.                             sizeof(SFDir))
  1970.                     );
  1971.                     for (j = alloc / 2; j < alloc; j++) {
  1972.                         SFdirs[j].dir = NULL;
  1973.                     }
  1974.                 }
  1975.                 dir = &(SFdirs[i]);
  1976.                 if (
  1977.                     (!(dir->dir)) ||
  1978.                     prevChange ||
  1979.                     strcmp(dir->dir, begin)
  1980.                 ) {
  1981.                     if (dir->dir) {
  1982.                         SFfree(i);
  1983.                     }
  1984.                     prevChange = 1;
  1985.                     len = strlen(begin) + 1;
  1986.                     dir->dir = XtMalloc((unsigned) len);
  1987.                     (void) strcpy(dir->dir, begin);
  1988.                     dir->path = end;
  1989.                     dir->vOrigin = 0;
  1990.                     dir->hOrigin = 0;
  1991.                     dir->changed = 1;
  1992.                     dir->beginSelection = -1;
  1993.                     dir->endSelection = -1;
  1994.                     (void) SFfindFile(dir - 1, begin);
  1995.                     if (
  1996.                         SFchdir(SFcurrentPath) ||
  1997.                         SFgetDir(dir)
  1998.                     ) {
  1999.                         SFunreadableDir(dir);
  2000.                         break;
  2001.                     }
  2002.                 }
  2003.                 *end = save;
  2004.                 if (!save) {
  2005.                     SFunselect();
  2006.                 }
  2007.             } else {
  2008.                 if (SFfindFile(&(SFdirs[SFdirEnd-1]), begin)) {
  2009.                     return;
  2010.                 }
  2011.             }
  2012.         } else {
  2013.             SFunselect();
  2014.         }
  2015.     }
  2016.  
  2017.     if ((end == SFcurrentPath + 1) && (!SFtwiddle)) {
  2018.         SFunselect();
  2019.     }
  2020.  
  2021.     for (i = SFdirEnd; i < alloc; i++) {
  2022.         if (SFdirs[i].dir) {
  2023.             SFfree(i);
  2024.         }
  2025.     }
  2026.  
  2027.     if (SFdoNotTouchDirPtr) {
  2028.         if (wasTwiddle) {
  2029.             wasTwiddle = 0;
  2030.             SFdirPtr = SFdirEnd - 2;
  2031.             if (SFdirPtr < 0) {
  2032.                 SFdirPtr = 0;
  2033.             }
  2034.         } else {
  2035.             SFdirPtr = SFdirPtrSave;
  2036.         }
  2037.         SFdoNotTouchDirPtr = 0;
  2038.     }
  2039.  
  2040.     if ((SFdirPtr != SFdirPtrSave) || (SFdirEnd != SFdirEndSave)) {
  2041.  
  2042. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR)
  2043.         i = 0;
  2044.         XtSetArg(arglist[i], XtNsliderMax, SFdirEnd + 3 - 1);    i++;
  2045.         XtSetArg(arglist[i], XtNsliderOrigin, SFdirPtr);    i++;
  2046.         XtSetValues(selFileHScroll, arglist, i);
  2047. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  2048.         XtScrollBarSetThumb(
  2049.             selFileHScroll,
  2050.             (float) (((double) SFdirPtr) / SFdirEnd),
  2051.             (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
  2052.                 SFdirEnd)
  2053.         );
  2054. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWSCROLLBAR) */
  2055.  
  2056.     }
  2057.  
  2058.     if (SFdirPtr != SFdirPtrSave) {
  2059.         SFdrawLists(SF_DO_SCROLL);
  2060.     } else {
  2061.         for (i = 0; i < 3; i++) {
  2062.             if (SFdirPtr + i < SFdirEnd) {
  2063.                 if (SFdirs[SFdirPtr + i].changed) {
  2064.                     SFdirs[SFdirPtr + i].changed = 0;
  2065.                     SFdrawList(i, SF_DO_SCROLL);
  2066.                 }
  2067.             } else {
  2068.                 SFclearList(i, SF_DO_SCROLL);
  2069.             }
  2070.         }
  2071.     }
  2072. }
  2073.  
  2074. SFsetText(path)
  2075.     char    *path;
  2076. {
  2077.  
  2078. #if defined(SEL_FILE_XW) || defined(SEL_FILE_XWTEXTEDIT)
  2079.  
  2080. #ifdef SEL_FILE_JAPANESE
  2081.     static wchar_t    *wstr = NULL;
  2082.     static int    alloc = 0;
  2083.     int        len;
  2084.  
  2085.     len = convEUCtoWS((unsigned char *) path, (wchar_t *) NULL);
  2086.     while (len + 1 > alloc) {
  2087.         alloc = 2 * (alloc + 1);
  2088.         wstr = (wchar_t *) XtRealloc((char *) wstr, (unsigned) (alloc *
  2089.             sizeof(wchar_t)));
  2090.     }
  2091.     (void) convEUCtoWS((unsigned char *) path, wstr);
  2092.  
  2093.     XwTextClearBuffer(selFileField);
  2094.     XwTextInsert(selFileField, wstr);
  2095. #else /* def SEL_FILE_JAPANESE */
  2096.     XwTextClearBuffer(selFileField);
  2097.     XwTextInsert(selFileField, path);
  2098. #endif /* def SEL_FILE_JAPANESE */
  2099.  
  2100. #else /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWTEXTEDIT) */
  2101.     {
  2102.         XtTextBlock    text;
  2103.  
  2104.         text.firstPos = 0;
  2105.         text.length = strlen(path);
  2106.         text.ptr = path;
  2107.         text.format = FMT8BIT;
  2108.         XtTextReplace(selFileField, 0, strlen(SFtextBuffer), &text);
  2109.     }
  2110. #endif /* defined(SEL_FILE_XW) || defined(SEL_FILE_XWTEXTEDIT) */
  2111.  
  2112. }
  2113.  
  2114. /* ARGSUSED */
  2115. void
  2116. SFbuttonPressList(w, n, event)
  2117.     Widget            w;
  2118.     int            n;
  2119.     XButtonPressedEvent    *event;
  2120. {
  2121.     SFbuttonPressed = 1;
  2122. }
  2123.  
  2124. /* ARGSUSED */
  2125. void
  2126. SFbuttonReleaseList(w, n, event)
  2127.     Widget            w;
  2128.     int            n;
  2129.     XButtonReleasedEvent    *event;
  2130. {
  2131.     SFDir    *dir;
  2132.  
  2133.     SFbuttonPressed = 0;
  2134.  
  2135.     if (SFcurrentInvert[n] != -1) {
  2136.         if (n < 2) {
  2137.             SFdoNotTouchDirPtr = 1;
  2138.         }
  2139.         SFdoNotTouchVorigin = 1;
  2140.         dir = &(SFdirs[SFdirPtr + n]);
  2141.         SFreplaceText(
  2142.             dir,
  2143.             dir->entries[dir->vOrigin + SFcurrentInvert[n]].shown
  2144.         );
  2145.         SFmotionList(w, n, event);
  2146.     }
  2147. }
  2148.  
  2149. static int
  2150. SFcheckDir(n, dir)
  2151.     int        n;
  2152.     SFDir        *dir;
  2153. {
  2154.     struct stat    statBuf;
  2155.     int        i;
  2156.  
  2157.     if (
  2158.         (!stat(".", &statBuf)) &&
  2159.         (statBuf.st_mtime != dir->st_mtime)
  2160.     ) {
  2161.  
  2162.         /*
  2163.          * If the pointer is currently in the window that we are about
  2164.          * to update, we must warp it to prevent the user from
  2165.          * accidentally selecting the wrong file.
  2166.          */
  2167.         if (SFcurrentInvert[n] != -1) {
  2168.             XWarpPointer(
  2169.                 SFdisplay,
  2170.                 None,
  2171.                 XtWindow(selFileLists[n]),
  2172.                 0,
  2173.                 0,
  2174.                 0,
  2175.                 0,
  2176.                 0,
  2177.                 0
  2178.             );
  2179.         }
  2180.  
  2181.         for (i = dir->nEntries - 1; i >= 0; i--) {
  2182.             if (dir->entries[i].shown != dir->entries[i].real) {
  2183.                 XtFree(dir->entries[i].shown);
  2184.             }
  2185.             XtFree(dir->entries[i].real);
  2186.         }
  2187.         XtFree((char *) dir->entries);
  2188.         if (SFgetDir(dir)) {
  2189.             SFunreadableDir(dir);
  2190.         }
  2191.         if (dir->vOrigin > dir->nEntries - SFlistSize) {
  2192.             dir->vOrigin = dir->nEntries - SFlistSize;
  2193.         }
  2194.         if (dir->vOrigin < 0) {
  2195.             dir->vOrigin = 0;
  2196.         }
  2197.         if (dir->hOrigin > dir->nChars - SFcharsPerEntry) {
  2198.             dir->hOrigin = dir->nChars - SFcharsPerEntry;
  2199.         }
  2200.         if (dir->hOrigin < 0) {
  2201.             dir->hOrigin = 0;
  2202.         }
  2203.         dir->beginSelection = -1;
  2204.         dir->endSelection = -1;
  2205.         SFdoNotTouchVorigin = 1;
  2206.         if ((dir + 1)->dir) {
  2207.             (void) SFfindFile(dir, (dir + 1)->dir);
  2208.         } else {
  2209.             (void) SFfindFile(dir, dir->path);
  2210.         }
  2211.         return 1;
  2212.     }
  2213.  
  2214.     return 0;
  2215. }
  2216.  
  2217. static int
  2218. SFcheckFiles(dir)
  2219.     SFDir    *dir;
  2220. {
  2221.     int        from, to;
  2222.     int        result;
  2223.     char        old, new;
  2224.     int        i;
  2225.     char        *str;
  2226.     int        last;
  2227.     struct stat    statBuf;
  2228.  
  2229.     result = 0;
  2230.  
  2231.     from = dir->vOrigin;
  2232.     to = dir->vOrigin + SFlistSize;
  2233.     if (to > dir->nEntries) {
  2234.         to = dir->nEntries;
  2235.     }
  2236.  
  2237.     for (i = from; i < to; i++) {
  2238.         str = dir->entries[i].real;
  2239.         last = strlen(str) - 1;
  2240.         old = str[last];
  2241.         str[last] = 0;
  2242.         if (stat(str, &statBuf)) {
  2243.             new = ' ';
  2244.         } else {
  2245.             switch (statBuf.st_mode & S_IFMT) {
  2246.             case S_IFDIR:
  2247.                 new = '/';
  2248.                 break;
  2249.             case S_IFREG:
  2250.                 if (statBuf.st_mode & 0111) {
  2251.                     new = '*';
  2252.                 } else {
  2253.                     new = ' ';
  2254.                 }
  2255.                 break;
  2256.  
  2257. #ifdef S_IFSOCK
  2258.             case S_IFSOCK:
  2259.                 new = '=';
  2260.                 break;
  2261. #endif /* def S_IFSOCK */
  2262.  
  2263.             default:
  2264.                 new = ' ';
  2265.                 break;
  2266.             }
  2267.         }
  2268.         str[last] = new;
  2269.         if (new != old) {
  2270.             result = 1;
  2271.         }
  2272.     }
  2273.  
  2274.     return result;
  2275. }
  2276.  
  2277. SFdirModTimer()
  2278. {
  2279.     static int    n = -1;
  2280.     static int    f = 0;
  2281.     char        save;
  2282.     SFDir        *dir;
  2283.  
  2284.     if ((!SFtwiddle) && (SFdirPtr < SFdirEnd)) {
  2285.         n++;
  2286.         if ((n > 2) || (SFdirPtr + n >= SFdirEnd)) {
  2287.             n = 0;
  2288.             f++;
  2289.             if ((f > 2) || (SFdirPtr + f >= SFdirEnd)) {
  2290.                 f = 0;
  2291.             }
  2292.         }
  2293.         dir = &(SFdirs[SFdirPtr + n]);
  2294.         save = *(dir->path);
  2295.         *(dir->path) = 0;
  2296.         if (SFchdir(SFcurrentPath)) {
  2297.             *(dir->path) = save;
  2298.  
  2299.             /*
  2300.              * force a re-read
  2301.              */
  2302.             *(dir->dir) = 0;
  2303.  
  2304.             SFupdatePath();
  2305.         } else {
  2306.             *(dir->path) = save;
  2307.             if (
  2308.                 SFcheckDir(n, dir) ||
  2309.                 ((f == n) && SFcheckFiles(dir))
  2310.             ) {
  2311.                 SFdrawList(n, SF_DO_SCROLL);
  2312.             }
  2313.         }
  2314.     }
  2315.  
  2316.     SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
  2317.         SFdirModTimer, (caddr_t) NULL);
  2318. }
  2319. \End\Of\File\
  2320. else
  2321.   echo "will not over write ./Path.c"
  2322. fi
  2323. echo "Finished archive 2 of 2"
  2324. exit
  2325. --
  2326. Erik M. van der Poel                  erik@sra.co.jp             (Japan)
  2327. SRA, 1-1-1 Hirakawa-cho, Chiyoda-ku   erik%sra.co.jp@uunet.uu.net  (USA)
  2328. Tokyo 102 Japan. TEL +81-3-234-2692   erik%sra.co.jp@mcvax.uucp (Europe)
  2329.