home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / unixtex-6.1b-src.tgz / tar.out / contrib / unixtex / xdvik / sfPath.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-28  |  16.9 KB  |  919 lines

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