"Fossies" - the Fresh Open Source Software Archive

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