"Fossies" - the Fresh Open Source Software Archive

Member "ghostview-1.5/Path.c" (24 Jul 1993, 17020 Bytes) of package /linux/misc/old/ghost/gnu/ghostview/ghostview-1.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

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