home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / s / stex2-18.zip / SeeTeX / Xtex / Path.c < prev    next >
C/C++ Source or Header  |  1992-05-05  |  18KB  |  949 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. #include <stdio.h>
  28.  
  29. #ifdef SEL_FILE_IGNORE_CASE
  30. #include <ctype.h>
  31. #endif /* def SEL_FILE_IGNORE_CASE */
  32.  
  33. #include <pwd.h>
  34. #include "SFinternal.h"
  35. #include <sys/stat.h>
  36. #include <X11/Xaw/Scrollbar.h>
  37.  
  38. #if defined(SYSV) || defined(USG)
  39. #if !defined(_AIX) && !defined(hpux)
  40. extern unsigned short getuid();
  41. #endif /* !defined(_AIX) && !defined(hpux) */
  42. extern void qsort();
  43. #endif /* defined(SYSV) || defined(USG) */
  44.  
  45. typedef struct {
  46.     char    *name;
  47.     char    *dir;
  48. } SFLogin;
  49.  
  50. SFDir *SFdirs = NULL;
  51.  
  52. int SFdirEnd;
  53.  
  54. int SFdirPtr;
  55.  
  56. int SFbuttonPressed = 0;
  57.  
  58. static int SFdoNotTouchDirPtr = 0;
  59.  
  60. static int SFdoNotTouchVorigin = 0;
  61.  
  62. static SFDir SFrootDir, SFhomeDir;
  63.  
  64. static SFLogin *SFlogins;
  65.  
  66. static int SFtwiddle = 0;
  67.  
  68. int
  69. SFchdir(path)
  70.     char    *path;
  71. {
  72.     int    result;
  73.  
  74.     result = 0;
  75.  
  76.     if (strcmp(path, SFcurrentDir)) {
  77.         result = chdir(path);
  78.         if (!result) {
  79.             (void) strcpy(SFcurrentDir, path);
  80.         }
  81.     }
  82.  
  83.     return result;
  84. }
  85.  
  86. static
  87. SFfree(i)
  88.     int    i;
  89. {
  90.     register SFDir    *dir;
  91.     register int    j;
  92.  
  93.     dir = &(SFdirs[i]);
  94.  
  95.     for (j = dir->nEntries - 1; j >= 0; j--) {
  96.         if (dir->entries[j].shown != dir->entries[j].real) {
  97.             XtFree(dir->entries[j].shown);
  98.         }
  99.         XtFree(dir->entries[j].real);
  100.     }
  101.  
  102.     XtFree((char *) dir->entries);
  103.  
  104.     XtFree(dir->dir);
  105.  
  106.     dir->dir = NULL;
  107. }
  108.  
  109. static
  110. SFunreadableDir(dir)
  111.     SFDir    *dir;
  112. {
  113.     char    *cannotOpen = "<cannot open> ";
  114.  
  115.     dir->entries = (SFEntry *) XtMalloc(sizeof(SFEntry));
  116.     dir->entries[0].statDone = 1;
  117.     dir->entries[0].real = XtMalloc((unsigned) (strlen(cannotOpen) + 1));
  118.     (void) strcpy(dir->entries[0].real, cannotOpen);
  119.     dir->entries[0].shown = dir->entries[0].real;
  120.     dir->nEntries = 1;
  121.     dir->nChars = strlen(cannotOpen);
  122. }
  123.  
  124. #ifdef SEL_FILE_IGNORE_CASE
  125. static
  126. SFstrncmp(p, q, n)
  127.     register char    *p, *q;
  128.     register int    n;
  129. {
  130.     register char    c1, c2;
  131.     char        *psave, *qsave;
  132.     int        nsave;
  133.  
  134.     psave = p;
  135.     qsave = q;
  136.     nsave = n;
  137.  
  138.     c1 = *p++;
  139.     if (islower(c1)) {
  140.         c1 = toupper(c1);
  141.     }
  142.     c2 = *q++;
  143.     if (islower(c2)) {
  144.         c2 = toupper(c2);
  145.     }
  146.  
  147.     while ((--n >= 0) && (c1 == c2)) {
  148.         if (!c1) {
  149.             return strncmp(psave, qsave, nsave);
  150.         }
  151.         c1 = *p++;
  152.         if (islower(c1)) {
  153.             c1 = toupper(c1);
  154.         }
  155.         c2 = *q++;
  156.         if (islower(c2)) {
  157.             c2 = toupper(c2);
  158.         }
  159.     }
  160.  
  161.     if (n < 0) {
  162.         return strncmp(psave, qsave, nsave);
  163.     }
  164.  
  165.     return c1 - c2;
  166. }
  167. #endif /* def SEL_FILE_IGNORE_CASE */
  168.  
  169. static
  170. SFreplaceText(dir, str)
  171.     SFDir    *dir;
  172.     char    *str;
  173. {
  174.     int    len;
  175.  
  176.     *(dir->path) = 0;
  177.     len = strlen(str);
  178.     if (str[len - 1] == '/') {
  179.         (void) strcat(SFcurrentPath, str);
  180.     } else {
  181.         (void) strncat(SFcurrentPath, str, len - 1);
  182.     }
  183.     if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
  184.         SFsetText(SFcurrentPath);
  185.     } else {
  186.         SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
  187.     }
  188.  
  189.     SFtextChanged();
  190. }
  191.  
  192. static void
  193. SFexpand(str)
  194.     char    *str;
  195. {
  196.     int    len;
  197.     int    cmp;
  198.     char    *name, *growing;
  199.     SFDir    *dir;
  200.     SFEntry    *entry, *max;
  201.  
  202.     len = strlen(str);
  203.  
  204.     dir = &(SFdirs[SFdirEnd - 1]);
  205.  
  206.     if (dir->beginSelection == -1) {
  207.         str = strcpy(XtMalloc((unsigned) (strlen(str) + 1)), str);
  208.         SFreplaceText(dir, str);
  209.         XtFree(str);
  210.         return;
  211.     } else if (dir->beginSelection == dir->endSelection) {
  212.         SFreplaceText(dir, dir->entries[dir->beginSelection].shown);
  213.         return;
  214.     }
  215.  
  216.     max = &(dir->entries[dir->endSelection + 1]);
  217.  
  218.     name = dir->entries[dir->beginSelection].shown;
  219.     (void) strcpy((growing = XtMalloc((unsigned) (strlen(name) + 1))),
  220.         name);
  221.  
  222.     cmp = 0;
  223.     while (!cmp) {
  224.         entry = &(dir->entries[dir->beginSelection]);
  225.         while (entry < max) {
  226.             if (cmp = strncmp(growing, entry->shown, len)) {
  227.                 break;
  228.             }
  229.             entry++;
  230.         }
  231.         len++;
  232.     }
  233.  
  234.     /*
  235.      * SFreplaceText() expects filename
  236.      */
  237.     growing[len - 2] = ' ';
  238.  
  239.     growing[len - 1] = 0;
  240.     SFreplaceText(dir, growing);
  241.     XtFree(growing);
  242. }
  243.  
  244. static int
  245. SFfindFile(dir, str)
  246.     SFDir        *dir;
  247.     register char    *str;
  248. {
  249.     register int    i, last, max;
  250.     register char    *name, save;
  251.     SFEntry        *entries;
  252.     int        len;
  253.     int        begin, end;
  254.     int        result;
  255.  
  256.     len = strlen(str);
  257.  
  258.     if (str[len - 1] == ' ') {
  259.         SFexpand(str);
  260.         return 1;
  261.     } else if (str[len - 1] == '/') {
  262.         len--;
  263.     }
  264.  
  265.     max = dir->nEntries;
  266.  
  267.     entries = dir->entries;
  268.  
  269.     i = 0;
  270.     while (i < max) {
  271.         name = entries[i].shown;
  272.         last = strlen(name) - 1;
  273.         save = name[last];
  274.         name[last] = 0;
  275.  
  276. #ifdef SEL_FILE_IGNORE_CASE
  277.         result = SFstrncmp(str, name, len);
  278. #else /* def SEL_FILE_IGNORE_CASE */
  279.         result = strncmp(str, name, len);
  280. #endif /* def SEL_FILE_IGNORE_CASE */
  281.  
  282.         name[last] = save;
  283.         if (result <= 0) {
  284.             break;
  285.         }
  286.         i++;
  287.     }
  288.     begin = i;
  289.     while (i < max) {
  290.         name = entries[i].shown;
  291.         last = strlen(name) - 1;
  292.         save = name[last];
  293.         name[last] = 0;
  294.  
  295. #ifdef SEL_FILE_IGNORE_CASE
  296.         result = SFstrncmp(str, name, len);
  297. #else /* def SEL_FILE_IGNORE_CASE */
  298.         result = strncmp(str, name, len);
  299. #endif /* def SEL_FILE_IGNORE_CASE */
  300.  
  301.         name[last] = save;
  302.         if (result) {
  303.             break;
  304.         }
  305.         i++;
  306.     }
  307.     end = i;
  308.  
  309.     if (begin != end) {
  310.         if (
  311.             (dir->beginSelection != begin) ||
  312.             (dir->endSelection != end - 1)
  313.         ) {
  314.             dir->changed = 1;
  315.             dir->beginSelection = begin;
  316.             if (str[strlen(str) - 1] == '/') {
  317.                 dir->endSelection = begin;
  318.             } else {
  319.                 dir->endSelection = end - 1;
  320.             }
  321.         }
  322.     } else {
  323.         if (dir->beginSelection != -1) {
  324.             dir->changed = 1;
  325.             dir->beginSelection = -1;
  326.             dir->endSelection = -1;
  327.         }
  328.     }
  329.  
  330.     if (
  331.         SFdoNotTouchVorigin ||
  332.         ((begin > dir->vOrigin) && (end < dir->vOrigin + SFlistSize))
  333.     ) {
  334.         SFdoNotTouchVorigin = 0;
  335.         return 0;
  336.     }
  337.  
  338.     i = begin - 1;
  339.     if (i > max - SFlistSize) {
  340.         i = max - SFlistSize;
  341.     }
  342.     if (i < 0) {
  343.         i = 0;
  344.     }
  345.  
  346.     if (dir->vOrigin != i) {
  347.         dir->vOrigin = i;
  348.         dir->changed = 1;
  349.     }
  350.  
  351.     return 0;
  352. }
  353.  
  354. static
  355. SFunselect()
  356. {
  357.     SFDir    *dir;
  358.  
  359.     dir = &(SFdirs[SFdirEnd - 1]);
  360.     if (dir->beginSelection != -1) {
  361.         dir->changed = 1;
  362.     }
  363.     dir->beginSelection = -1;
  364.     dir->endSelection = -1;
  365. }
  366.  
  367. static int
  368. SFcompareLogins(p, q)
  369.     SFLogin    *p, *q;
  370. {
  371.     return strcmp(p->name, q->name);
  372. }
  373.  
  374. static
  375. SFgetHomeDirs()
  376. {
  377.     struct passwd    *pw;
  378.     struct stat    statBuf;
  379.     int        alloc;
  380.     int        i;
  381.     SFEntry        *entries = NULL;
  382. #ifndef    HOME_ON_DEMAND /* by Y.Kawabe */
  383.     int        len;
  384. #endif    /* HOME_ON_DEMAND */
  385.     int        maxChars;
  386.  
  387.     alloc = 0;
  388.     i = 0;
  389.  
  390.     maxChars = -1;
  391.  
  392.     if (pw = getpwuid((int) getuid())) {
  393.         if (
  394.             (!stat(pw->pw_dir, &statBuf)) &&
  395.             ((statBuf.st_mode & S_IFMT) == S_IFDIR)
  396.         ) {
  397.             alloc = 1;
  398.             i = 1;
  399.             entries = (SFEntry *) XtMalloc(sizeof(SFEntry));
  400.             SFlogins = (SFLogin *) XtMalloc(sizeof(SFLogin));
  401.             entries[0].real = XtMalloc(3);
  402.             (void) strcpy(entries[0].real, "~");
  403.             entries[0].shown = entries[0].real;
  404.             entries[0].statDone = 1;
  405.             SFlogins[0].name = "";
  406.             SFlogins[0].dir = XtMalloc((unsigned)
  407.                 (strlen(pw->pw_dir) + 1));
  408.             (void) strcpy(SFlogins[0].dir, pw->pw_dir);
  409.             maxChars = 1;
  410.         }
  411.     }
  412.  
  413. #ifndef    HOME_ON_DEMAND /* by Y.Kawabe */
  414.  
  415.     (void) setpwent();
  416.  
  417.     while ((pw = getpwent()) && (*(pw->pw_name))) {
  418.         if (
  419.             (!stat(pw->pw_dir, &statBuf)) &&
  420.             ((statBuf.st_mode & S_IFMT) == S_IFDIR)
  421.         ) {
  422.             if (i >= alloc) {
  423.                 alloc *= 2;
  424.                 entries = (SFEntry *) XtRealloc(
  425.                     (char *) entries,
  426.                     (unsigned) (alloc * sizeof(SFEntry))
  427.                 );
  428.                 SFlogins = (SFLogin *) XtRealloc(
  429.                     (char *) SFlogins,
  430.                     (unsigned) (alloc * sizeof(SFLogin))
  431.                 );
  432.             }
  433.             len = strlen(pw->pw_name);
  434.             entries[i].real = XtMalloc((unsigned) (len + 3));
  435.             (void) strcat(strcpy(entries[i].real, "~"),
  436.                 pw->pw_name);
  437.             entries[i].shown = entries[i].real;
  438.             entries[i].statDone = 1;
  439.             if (len > maxChars) {
  440.                 maxChars = len;
  441.             }
  442.             SFlogins[i].name = XtMalloc((unsigned)
  443.                 (strlen(pw->pw_name) + 1));
  444.             (void) strcpy(SFlogins[i].name, pw->pw_name);
  445.             SFlogins[i].dir = XtMalloc((unsigned)
  446.                 (strlen(pw->pw_dir) + 1));
  447.             (void) strcpy(SFlogins[i].dir, pw->pw_dir);
  448.             i++;
  449.         }
  450.     }
  451.  
  452. #endif    /* HOME_ON_DEMAND */
  453.  
  454.     SFhomeDir.dir            = XtMalloc(1)    ;
  455.     SFhomeDir.dir[0]        = 0        ;
  456.     SFhomeDir.path            = SFcurrentPath    ;
  457.     SFhomeDir.entries        = entries    ;
  458.     SFhomeDir.nEntries        = i        ;
  459.     SFhomeDir.vOrigin        = 0        ;    /* :-) */
  460.     SFhomeDir.nChars        = maxChars + 2    ;
  461.     SFhomeDir.hOrigin        = 0        ;
  462.     SFhomeDir.changed        = 1        ;
  463.     SFhomeDir.beginSelection    = -1        ;
  464.     SFhomeDir.endSelection        = -1        ;
  465.  
  466. #if defined(SYSV) || defined(USG)
  467.     qsort((char *) entries, (unsigned)i, sizeof(SFEntry), SFcompareEntries);
  468.     qsort((char *) SFlogins, (unsigned)i, sizeof(SFLogin), SFcompareLogins);
  469. #else /* defined(SYSV) || defined(USG) */
  470.     qsort((char *) entries, i, sizeof(SFEntry), SFcompareEntries);
  471.     qsort((char *) SFlogins, i, sizeof(SFLogin), SFcompareLogins);
  472. #endif /* defined(SYSV) || defined(USG) */
  473.  
  474.     for (i--; i >= 0; i--) {
  475.         (void) strcat(entries[i].real, "/");
  476.     }
  477. }
  478.  
  479.  
  480. static int
  481. SFfindHomeDir(begin, end)
  482.     char    *begin, *end;
  483. {
  484.     char    save;
  485.     char    *theRest;
  486.     int    i;
  487.  
  488.     save = *end;
  489.     *end = 0;
  490.  
  491.     for (i = SFhomeDir.nEntries - 1; i >= 0; i--) {
  492.         if (!strcmp(SFhomeDir.entries[i].real, begin)) {
  493.             *end = save;
  494.             theRest = XtMalloc((unsigned) (strlen(end) + 1));
  495.             (void) strcpy(theRest, end);
  496.             (void) strcat(strcat(strcpy(SFcurrentPath,
  497.                 SFlogins[i].dir), "/"), theRest);
  498.             XtFree(theRest);
  499.             SFsetText(SFcurrentPath);
  500.             SFtextChanged();
  501.             return 1;
  502.         }
  503.     }
  504.  
  505. #ifdef    HOME_ON_DEMAND /* by Y.Kawabe */
  506.     if (*(++begin)) {
  507.         struct passwd *pwd;
  508.         char user[256];
  509.         int i = 0;
  510.  
  511.         while (*begin && *begin != '/' && i < sizeof(user))
  512.             user[i++] = *begin++;
  513.         user[i] = '\0';
  514.  
  515.         if (pwd = getpwnam(user)) {
  516.             theRest = XtMalloc((unsigned) (strlen(end) + 1));
  517.             (void) strcpy(theRest, end);
  518.             (void) strcat(strcat(strcpy(SFcurrentPath,
  519.                 pwd->pw_dir), "/"), theRest);
  520.             XtFree(theRest);
  521.             SFsetText(SFcurrentPath);
  522.             SFtextChanged();
  523.             return 1;
  524.         }
  525.     }
  526. #endif    /* HOME_ON_DEMAND */
  527.  
  528.     *end = save;
  529.  
  530.     return 0;
  531. }
  532.  
  533. SFupdatePath()
  534. {
  535.     static int    alloc;
  536.     static int    wasTwiddle = 0;
  537.     char        *begin, *end;
  538.     int        i, j;
  539.     int        len;
  540.     int        prevChange;
  541.     int        SFdirPtrSave, SFdirEndSave;
  542.     SFDir        *dir;
  543.  
  544.     if (!SFdirs) {
  545.         SFdirs = (SFDir *) XtMalloc((alloc = 10) * sizeof(SFDir));
  546.         dir = &(SFdirs[0]);
  547.         dir->dir = XtMalloc(2);
  548.         (void) strcpy(dir->dir, "/");
  549.         (void) SFchdir("/");
  550.         (void) SFgetDir(dir);
  551.         for (j = 1; j < alloc; j++) {
  552.             SFdirs[j].dir = NULL;
  553.         }
  554.         dir->path = SFcurrentPath + 1;
  555.         dir->vOrigin = 0;
  556.         dir->hOrigin = 0;
  557.         dir->changed = 1;
  558.         dir->beginSelection = -1;
  559.         dir->endSelection = -1;
  560.         SFgetHomeDirs();
  561.     }
  562.  
  563.     SFdirEndSave = SFdirEnd;
  564.     SFdirEnd = 1;
  565.  
  566.     SFdirPtrSave = SFdirPtr;
  567.     SFdirPtr = 0;
  568.  
  569.     begin = NULL;
  570.  
  571.     if (SFcurrentPath[0] == '~') {
  572.         if (!SFtwiddle) {
  573.             SFtwiddle = 1;
  574.             dir = &(SFdirs[0]);
  575.             SFrootDir = *dir;
  576.             *dir = SFhomeDir;
  577.             dir->changed = 1;
  578.         }
  579.         end = SFcurrentPath;
  580.         SFdoNotTouchDirPtr = 1;
  581.         wasTwiddle = 1;
  582.     } else {
  583.         if (SFtwiddle) {
  584.             SFtwiddle = 0;
  585.             dir = &(SFdirs[0]);
  586.             *dir = SFrootDir;
  587.             dir->changed = 1;
  588.         }
  589.         end = SFcurrentPath + 1;
  590.     }
  591.  
  592.     i = 0;
  593.  
  594.     prevChange = 0;
  595.  
  596.     while (*end) {
  597.         while (*end++ == '/') {
  598.             ;
  599.         }
  600.         end--;
  601.         begin = end;
  602.         while ((*end) && (*end++ != '/')) {
  603.             ;
  604.         }
  605.         if ((end - SFcurrentPath <= SFtextPos) && (*(end - 1) == '/')) {
  606.             SFdirPtr = i - 1;
  607.             if (SFdirPtr < 0) {
  608.                 SFdirPtr = 0;
  609.             }
  610.         }
  611.         if (*begin) {
  612.             if (*(end - 1) == '/') {
  613.                 char save = *end;
  614.  
  615.                 if (SFtwiddle) {
  616.                     if (SFfindHomeDir(begin, end)) {
  617.                         return;
  618.                     }
  619.                 }
  620.                 *end = 0;
  621.                 i++;
  622.                 SFdirEnd++;
  623.                 if (i >= alloc) {
  624.                     SFdirs = (SFDir *) XtRealloc(
  625.                         (char *) SFdirs,
  626.                         (unsigned) ((alloc *= 2) *
  627.                             sizeof(SFDir))
  628.                     );
  629.                     for (j = alloc / 2; j < alloc; j++) {
  630.                         SFdirs[j].dir = NULL;
  631.                     }
  632.                 }
  633.                 dir = &(SFdirs[i]);
  634.                 if (
  635.                     (!(dir->dir)) ||
  636.                     prevChange ||
  637.                     strcmp(dir->dir, begin)
  638.                 ) {
  639.                     if (dir->dir) {
  640.                         SFfree(i);
  641.                     }
  642.                     prevChange = 1;
  643.                     len = strlen(begin) + 1;
  644.                     dir->dir = XtMalloc((unsigned) len);
  645.                     (void) strcpy(dir->dir, begin);
  646.                     dir->path = end;
  647.                     dir->vOrigin = 0;
  648.                     dir->hOrigin = 0;
  649.                     dir->changed = 1;
  650.                     dir->beginSelection = -1;
  651.                     dir->endSelection = -1;
  652.                     (void) SFfindFile(dir - 1, begin);
  653.                     if (
  654.                         SFchdir(SFcurrentPath) ||
  655.                         SFgetDir(dir)
  656.                     ) {
  657.                         SFunreadableDir(dir);
  658.                         break;
  659.                     }
  660.                 }
  661.                 *end = save;
  662.                 if (!save) {
  663.                     SFunselect();
  664.                 }
  665.             } else {
  666.                 if (SFfindFile(&(SFdirs[SFdirEnd-1]), begin)) {
  667.                     return;
  668.                 }
  669.             }
  670.         } else {
  671.             SFunselect();
  672.         }
  673.     }
  674.  
  675.     if ((end == SFcurrentPath + 1) && (!SFtwiddle)) {
  676.         SFunselect();
  677.     }
  678.  
  679.     for (i = SFdirEnd; i < alloc; i++) {
  680.         if (SFdirs[i].dir) {
  681.             SFfree(i);
  682.         }
  683.     }
  684.  
  685.     if (SFdoNotTouchDirPtr) {
  686.         if (wasTwiddle) {
  687.             wasTwiddle = 0;
  688.             SFdirPtr = SFdirEnd - 2;
  689.             if (SFdirPtr < 0) {
  690.                 SFdirPtr = 0;
  691.             }
  692.         } else {
  693.             SFdirPtr = SFdirPtrSave;
  694.         }
  695.         SFdoNotTouchDirPtr = 0;
  696.     }
  697.  
  698.     if ((SFdirPtr != SFdirPtrSave) || (SFdirEnd != SFdirEndSave)) {
  699.         XawScrollbarSetThumb(
  700.             selFileHScroll,
  701.             (float) (((double) SFdirPtr) / SFdirEnd),
  702.             (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
  703.                 SFdirEnd)
  704.         );
  705.     }
  706.  
  707.     if (SFdirPtr != SFdirPtrSave) {
  708.         SFdrawLists(SF_DO_SCROLL);
  709.     } else {
  710.         for (i = 0; i < 3; i++) {
  711.             if (SFdirPtr + i < SFdirEnd) {
  712.                 if (SFdirs[SFdirPtr + i].changed) {
  713.                     SFdirs[SFdirPtr + i].changed = 0;
  714.                     SFdrawList(i, SF_DO_SCROLL);
  715.                 }
  716.             } else {
  717.                 SFclearList(i, SF_DO_SCROLL);
  718.             }
  719.         }
  720.     }
  721. }
  722.  
  723. SFsetText(path)
  724.     char    *path;
  725. {
  726.     XawTextBlock    text;
  727.  
  728.     text.firstPos = 0;
  729.     text.length = strlen(path);
  730.     text.ptr = path;
  731.     text.format = FMT8BIT;
  732.  
  733.     XawTextReplace(selFileField, 0, strlen(SFtextBuffer), &text);
  734.     XawTextSetInsertionPoint(selFileField, strlen(SFtextBuffer));
  735. }
  736.  
  737. /* ARGSUSED */
  738. void
  739. SFbuttonPressList(w, n, event)
  740.     Widget            w;
  741.     int            n;
  742.     XButtonPressedEvent    *event;
  743. {
  744.     SFbuttonPressed = 1;
  745. }
  746.  
  747. /* ARGSUSED */
  748. void
  749. SFbuttonReleaseList(w, n, event)
  750.     Widget            w;
  751.     int            n;
  752.     XButtonReleasedEvent    *event;
  753. {
  754.     SFDir    *dir;
  755.  
  756.     SFbuttonPressed = 0;
  757.  
  758.     if (SFcurrentInvert[n] != -1) {
  759.         if (n < 2) {
  760.             SFdoNotTouchDirPtr = 1;
  761.         }
  762.         SFdoNotTouchVorigin = 1;
  763.         dir = &(SFdirs[SFdirPtr + n]);
  764.         SFreplaceText(
  765.             dir,
  766.             dir->entries[dir->vOrigin + SFcurrentInvert[n]].shown
  767.         );
  768.         SFmotionList(w, n, event);
  769.     }
  770. }
  771.  
  772. static int
  773. SFcheckDir(n, dir)
  774.     int        n;
  775.     SFDir        *dir;
  776. {
  777.     struct stat    statBuf;
  778.     int        i;
  779.  
  780.     if (
  781.         (!stat(".", &statBuf)) &&
  782.         (statBuf.st_mtime != dir->st_mtime)
  783.     ) {
  784.  
  785.         /*
  786.          * If the pointer is currently in the window that we are about
  787.          * to update, we must warp it to prevent the user from
  788.          * accidentally selecting the wrong file.
  789.          */
  790.         if (SFcurrentInvert[n] != -1) {
  791.             XWarpPointer(
  792.                 SFdisplay,
  793.                 None,
  794.                 XtWindow(selFileLists[n]),
  795.                 0,
  796.                 0,
  797.                 0,
  798.                 0,
  799.                 0,
  800.                 0
  801.             );
  802.         }
  803.  
  804.         for (i = dir->nEntries - 1; i >= 0; i--) {
  805.             if (dir->entries[i].shown != dir->entries[i].real) {
  806.                 XtFree(dir->entries[i].shown);
  807.             }
  808.             XtFree(dir->entries[i].real);
  809.         }
  810.         XtFree((char *) dir->entries);
  811.         if (SFgetDir(dir)) {
  812.             SFunreadableDir(dir);
  813.         }
  814.         if (dir->vOrigin > dir->nEntries - SFlistSize) {
  815.             dir->vOrigin = dir->nEntries - SFlistSize;
  816.         }
  817.         if (dir->vOrigin < 0) {
  818.             dir->vOrigin = 0;
  819.         }
  820.         if (dir->hOrigin > dir->nChars - SFcharsPerEntry) {
  821.             dir->hOrigin = dir->nChars - SFcharsPerEntry;
  822.         }
  823.         if (dir->hOrigin < 0) {
  824.             dir->hOrigin = 0;
  825.         }
  826.         dir->beginSelection = -1;
  827.         dir->endSelection = -1;
  828.         SFdoNotTouchVorigin = 1;
  829.         if ((dir + 1)->dir) {
  830.             (void) SFfindFile(dir, (dir + 1)->dir);
  831.         } else {
  832.             (void) SFfindFile(dir, dir->path);
  833.         }
  834.  
  835.         if (!SFworkProcAdded) {
  836.             (void) XtAppAddWorkProc(SFapp, SFworkProc, NULL);
  837.             SFworkProcAdded = 1;
  838.         }
  839.  
  840.         return 1;
  841.     }
  842.  
  843.     return 0;
  844. }
  845.  
  846. static int
  847. SFcheckFiles(dir)
  848.     SFDir    *dir;
  849. {
  850.     int        from, to;
  851.     int        result;
  852.     char        old, new;
  853.     int        i;
  854.     char        *str;
  855.     int        last;
  856.     struct stat    statBuf;
  857.  
  858.     result = 0;
  859.  
  860.     from = dir->vOrigin;
  861.     to = dir->vOrigin + SFlistSize;
  862.     if (to > dir->nEntries) {
  863.         to = dir->nEntries;
  864.     }
  865.  
  866.     for (i = from; i < to; i++) {
  867.         str = dir->entries[i].real;
  868.         last = strlen(str) - 1;
  869.         old = str[last];
  870.         str[last] = 0;
  871.         if (stat(str, &statBuf)) {
  872.             new = ' ';
  873.         } else {
  874.             switch (statBuf.st_mode & S_IFMT) {
  875.             case S_IFDIR:
  876.                 new = '/';
  877.                 break;
  878.             case S_IFREG:
  879.                 if (statBuf.st_mode & 0111) {
  880.                     new = '*';
  881.                 } else {
  882.                     new = ' ';
  883.                 }
  884.                 break;
  885.  
  886. #ifdef S_IFSOCK
  887.             case S_IFSOCK:
  888.                 new = '=';
  889.                 break;
  890. #endif /* def S_IFSOCK */
  891.  
  892.             default:
  893.                 new = ' ';
  894.                 break;
  895.             }
  896.         }
  897.         str[last] = new;
  898.         if (new != old) {
  899.             result = 1;
  900.         }
  901.     }
  902.  
  903.     return result;
  904. }
  905.  
  906. void
  907. SFdirModTimer()
  908. {
  909.     static int    n = -1;
  910.     static int    f = 0;
  911.     char        save;
  912.     SFDir        *dir;
  913.  
  914.     if ((!SFtwiddle) && (SFdirPtr < SFdirEnd)) {
  915.         n++;
  916.         if ((n > 2) || (SFdirPtr + n >= SFdirEnd)) {
  917.             n = 0;
  918.             f++;
  919.             if ((f > 2) || (SFdirPtr + f >= SFdirEnd)) {
  920.                 f = 0;
  921.             }
  922.         }
  923.         dir = &(SFdirs[SFdirPtr + n]);
  924.         save = *(dir->path);
  925.         *(dir->path) = 0;
  926.         if (SFchdir(SFcurrentPath)) {
  927.             *(dir->path) = save;
  928.  
  929.             /*
  930.              * force a re-read
  931.              */
  932.             *(dir->dir) = 0;
  933.  
  934.             SFupdatePath();
  935.         } else {
  936.             *(dir->path) = save;
  937.             if (
  938.                 SFcheckDir(n, dir) ||
  939.                 ((f == n) && SFcheckFiles(dir))
  940.             ) {
  941.                 SFdrawList(n, SF_DO_SCROLL);
  942.             }
  943.         }
  944.     }
  945.  
  946.     SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
  947.         SFdirModTimer, (XtPointer) NULL);
  948. }
  949.