Back to index

tetex-bin  3.0
sfPath.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
00003  *
00004  * Permission to use, copy, modify, and distribute this software and its
00005  * documentation for any purpose and without fee is hereby granted, provided
00006  * that the above copyright notice appear in all copies and that both that
00007  * copyright notice and this permission notice appear in supporting
00008  * documentation, and that the name of Software Research Associates not be used
00009  * in advertising or publicity pertaining to distribution of the software
00010  * without specific, written prior permission.  Software Research Associates
00011  * makes no representations about the suitability of this software for any
00012  * purpose.  It is provided "as is" without express or implied warranty.
00013  *
00014  * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
00015  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
00016  * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
00017  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00018  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00019  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00020  * PERFORMANCE OF THIS SOFTWARE.
00021  *
00022  * Author: Erik M. van der Poel
00023  *         Software Research Associates, Inc., Tokyo, Japan
00024  *         erik@sra.co.jp
00025  */
00026 
00027 #include "xdvi-config.h"
00028 
00029 #include "kpathsea/c-auto.h"
00030 #include "kpathsea/config.h"
00031 #include "kpathsea/c-stat.h"
00032 
00033 #include "xdvi.h"
00034 #include "sfDir.h"
00035 #include "sfDraw.h"
00036 #include "sfPath.h"
00037 #include "sfSelFile.h"
00038 
00039 #if !defined(MOTIF) /* entire file */
00040 
00041 #include <stdio.h>
00042 
00043 #include <X11/Intrinsic.h>
00044 #include <X11/StringDefs.h>
00045 #include <X11/Xos.h>
00046 #include <X11/Xaw/Text.h>
00047 #include <X11/Xaw/AsciiText.h>
00048 #include <X11/Xaw/Scrollbar.h>
00049 #include <X11/Xaw/Cardinals.h>
00050 
00051 
00052 #ifdef SEL_FILE_IGNORE_CASE
00053 #include <ctype.h>
00054 #endif /* def SEL_FILE_IGNORE_CASE */
00055 
00056 #ifndef S_IXUSR
00057 #define S_IXUSR 0100
00058 #endif
00059 #ifndef S_IXGRP
00060 #define S_IXGRP 0010
00061 #endif
00062 #ifndef S_IXOTH
00063 #define S_IXOTH 0001
00064 #endif
00065 
00066 #define S_ISXXX(m) ((m) & (S_IXUSR | S_IXGRP | S_IXOTH))
00067 
00068 #include <X11/Xos.h>
00069 #include <pwd.h>
00070 #include <X11/Xaw/Scrollbar.h>
00071 
00072 typedef struct {
00073     char *name;
00074     char *dir;
00075 } SFLogin;
00076 
00077 SFDir *SFdirs = NULL;
00078 
00079 int SFdirEnd;
00080 
00081 int SFdirPtr;
00082 
00083 int SFbuttonPressed = 0;
00084 
00085 static int SFdoNotTouchDirPtr = 0;
00086 
00087 static int SFdoNotTouchVorigin = 0;
00088 
00089 static SFDir SFrootDir, SFhomeDir;
00090 
00091 static SFLogin *SFlogins;
00092 
00093 static int SFtwiddle = 0;
00094 
00095 int
00096 SFchdir(char *path)
00097 {
00098     int result;
00099 
00100     result = 0;
00101 
00102     if (strcmp(path, SFcurrentDir)) {
00103        result = chdir(path);
00104        if (!result) {
00105            (void)strcpy(SFcurrentDir, path);
00106        }
00107     }
00108 
00109     return result;
00110 }
00111 
00112 static void
00113 SFfree(int i)
00114 {
00115     SFDir *dir;
00116     int j;
00117 
00118     dir = &(SFdirs[i]);
00119 
00120     for (j = dir->nEntries - 1; j >= 0; j--) {
00121        if (dir->entries[j].shown != dir->entries[j].real) {
00122            XtFree(dir->entries[j].shown);
00123        }
00124        XtFree(dir->entries[j].real);
00125     }
00126 
00127     XtFree((char *)dir->entries);
00128 
00129     XtFree(dir->dir);
00130 
00131     dir->dir = NULL;
00132 }
00133 
00134 static void
00135 SFstrdup(char **s1, char *s2)
00136 {
00137     *s1 = strcpy(XtMalloc((unsigned)(strlen(s2) + 1)), s2);
00138 }
00139 
00140 static void
00141 SFunreadableDir(SFDir *dir)
00142 {
00143     char *cannotOpen = "<cannot open> ";
00144 
00145     dir->entries = (SFEntry *) XtMalloc(sizeof(SFEntry));
00146     dir->entries[0].statDone = 1;
00147     SFstrdup(&dir->entries[0].real, cannotOpen);
00148     dir->entries[0].shown = dir->entries[0].real;
00149     dir->nEntries = 1;
00150     dir->nChars = strlen(cannotOpen);
00151 }
00152 
00153 #ifdef SEL_FILE_IGNORE_CASE
00154 static
00155 SFstrncmp(char *p, char *q, int n)
00156 {
00157     char c1, c2;
00158     char *psave, *qsave;
00159     int nsave;
00160 
00161     psave = p;
00162     qsave = q;
00163     nsave = n;
00164 
00165     c1 = *p++;
00166     if (islower(c1)) {
00167        c1 = toupper(c1);
00168     }
00169     c2 = *q++;
00170     if (islower(c2)) {
00171        c2 = toupper(c2);
00172     }
00173 
00174     while ((--n >= 0) && (c1 == c2)) {
00175        if (!c1) {
00176            return strncmp(psave, qsave, nsave);
00177        }
00178        c1 = *p++;
00179        if (islower(c1)) {
00180            c1 = toupper(c1);
00181        }
00182        c2 = *q++;
00183        if (islower(c2)) {
00184            c2 = toupper(c2);
00185        }
00186     }
00187 
00188     if (n < 0) {
00189        return strncmp(psave, qsave, nsave);
00190     }
00191 
00192     return c1 - c2;
00193 }
00194 #endif /* def SEL_FILE_IGNORE_CASE */
00195 
00196 static void
00197 SFreplaceText(SFDir *dir, char *str)
00198 {
00199     int len;
00200 
00201     *(dir->path) = 0;
00202     len = strlen(str);
00203     if (str[len - 1] == '/') {
00204        (void)strcat(SFcurrentPath, str);
00205     }
00206     else {
00207        (void)strncat(SFcurrentPath, str, len - 1);
00208     }
00209 /*     if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) { */
00210 /*     SFsetText(SFcurrentPath); */
00211 /*     } */
00212 /*     else { */
00213 /*     SFsetText(&(SFcurrentPath[strlen(SFstartDir)])); */
00214 /*     } */
00215     SFsetText(SFcurrentPath);
00216 
00217     SFtextChanged();
00218 }
00219 
00220 static void
00221 SFexpand(char *str)
00222 {
00223     int len;
00224     int cmp;
00225     char *name, *growing;
00226     SFDir *dir;
00227     SFEntry *entry, *max;
00228 
00229     len = strlen(str);
00230 
00231     dir = &(SFdirs[SFdirEnd - 1]);
00232 
00233     if (dir->beginSelection == -1) {
00234        SFstrdup(&str, str);
00235        SFreplaceText(dir, str);
00236        XtFree(str);
00237        return;
00238     }
00239     else if (dir->beginSelection == dir->endSelection) {
00240        SFreplaceText(dir, dir->entries[dir->beginSelection].shown);
00241        return;
00242     }
00243 
00244     max = &(dir->entries[dir->endSelection + 1]);
00245 
00246     name = dir->entries[dir->beginSelection].shown;
00247     SFstrdup(&growing, name);
00248 
00249     cmp = 0;
00250     while (!cmp) {
00251        entry = &(dir->entries[dir->beginSelection]);
00252        while (entry < max) {
00253            if ((cmp = strncmp(growing, entry->shown, len))) {
00254               break;
00255            }
00256            entry++;
00257        }
00258        len++;
00259     }
00260 
00261     /*
00262      * SFreplaceText() expects filename
00263      */
00264     growing[len - 2] = ' ';
00265 
00266     growing[len - 1] = 0;
00267     SFreplaceText(dir, growing);
00268     XtFree(growing);
00269 }
00270 
00271 static int
00272 SFfindFile(SFDir *dir, char *str)
00273 {
00274     int i, last, max;
00275     char *name, save;
00276     SFEntry *entries;
00277     int len;
00278     int begin, end;
00279     int result;
00280 
00281     len = strlen(str);
00282 
00283     if (str[len - 1] == ' ') {
00284        SFexpand(str);
00285        return 1;
00286     }
00287     else if (str[len - 1] == '/') {
00288        len--;
00289     }
00290 
00291     max = dir->nEntries;
00292 
00293     entries = dir->entries;
00294 
00295     i = 0;
00296     while (i < max) {
00297        name = entries[i].shown;
00298        last = strlen(name) - 1;
00299        save = name[last];
00300        name[last] = 0;
00301 
00302 #ifdef SEL_FILE_IGNORE_CASE
00303        result = SFstrncmp(str, name, len);
00304 #else /* def SEL_FILE_IGNORE_CASE */
00305        result = strncmp(str, name, len);
00306 #endif /* def SEL_FILE_IGNORE_CASE */
00307 
00308        name[last] = save;
00309        if (result <= 0) {
00310            break;
00311        }
00312        i++;
00313     }
00314     begin = i;
00315     while (i < max) {
00316        name = entries[i].shown;
00317        last = strlen(name) - 1;
00318        save = name[last];
00319        name[last] = 0;
00320 
00321 #ifdef SEL_FILE_IGNORE_CASE
00322        result = SFstrncmp(str, name, len);
00323 #else /* def SEL_FILE_IGNORE_CASE */
00324        result = strncmp(str, name, len);
00325 #endif /* def SEL_FILE_IGNORE_CASE */
00326 
00327        name[last] = save;
00328        if (result) {
00329            break;
00330        }
00331        i++;
00332     }
00333     end = i;
00334 
00335     if (begin != end) {
00336        if ((dir->beginSelection != begin) || (dir->endSelection != end - 1)
00337            ) {
00338            dir->changed = 1;
00339            dir->beginSelection = begin;
00340            if (str[strlen(str) - 1] == '/') {
00341               dir->endSelection = begin;
00342            }
00343            else {
00344               dir->endSelection = end - 1;
00345            }
00346        }
00347     }
00348     else {
00349        if (dir->beginSelection != -1) {
00350            dir->changed = 1;
00351            dir->beginSelection = -1;
00352            dir->endSelection = -1;
00353        }
00354     }
00355 
00356     if (SFdoNotTouchVorigin ||
00357        ((begin > dir->vOrigin) && (end < dir->vOrigin + SFlistSize))) {
00358        SFdoNotTouchVorigin = 0;
00359        return 0;
00360     }
00361 
00362     i = begin - 1;
00363     if (i > max - SFlistSize) {
00364        i = max - SFlistSize;
00365     }
00366     if (i < 0) {
00367        i = 0;
00368     }
00369 
00370     if (dir->vOrigin != i) {
00371        dir->vOrigin = i;
00372        dir->changed = 1;
00373     }
00374 
00375     return 0;
00376 }
00377 
00378 static void
00379 SFunselect(void)
00380 {
00381     SFDir *dir;
00382 
00383     dir = &(SFdirs[SFdirEnd - 1]);
00384     if (dir->beginSelection != -1) {
00385        dir->changed = 1;
00386     }
00387     dir->beginSelection = -1;
00388     dir->endSelection = -1;
00389 }
00390 
00391 static int
00392 SFcompareLogins(const void *vp, const void *vq)
00393 {
00394     const SFLogin *p = vp;
00395     const SFLogin *q = vq;
00396     return strcmp(p->name, q->name);
00397 }
00398 
00399 static void
00400 SFgetHomeDirs(void)
00401 {
00402     struct passwd *pw;
00403     int alloc;
00404     int i;
00405     SFEntry *entries = NULL;
00406     int len;
00407     int maxChars;
00408 
00409     {
00410        alloc = 1;
00411        i = 1;
00412        entries = (SFEntry *) XtMalloc(sizeof(SFEntry));
00413        SFlogins = (SFLogin *) XtMalloc(sizeof(SFLogin));
00414        entries[0].real = XtMalloc(3);
00415        (void)strcpy(entries[0].real, "~");
00416        entries[0].shown = entries[0].real;
00417        entries[0].statDone = 1;
00418        SFlogins[0].name = "";
00419        pw = getpwuid((int)getuid());
00420        SFstrdup(&SFlogins[0].dir, pw ? pw->pw_dir : "/");
00421        maxChars = 0;
00422     }
00423 
00424     (void)setpwent();
00425 
00426     while ((pw = (struct passwd *)getpwent()) && (*(pw->pw_name))) {
00427        if (i >= alloc) {
00428            alloc *= 2;
00429            entries = (SFEntry *) XtRealloc(
00430                                        (char *)entries,
00431                                        (unsigned)(alloc *
00432                                                  sizeof(SFEntry)));
00433            SFlogins =
00434               (SFLogin *) XtRealloc((char *)SFlogins,
00435                                   (unsigned)(alloc * sizeof(SFLogin))
00436               );
00437        }
00438        len = strlen(pw->pw_name);
00439        entries[i].real = XtMalloc((unsigned)(len + 3));
00440        (void)strcat(strcpy(entries[i].real, "~"), pw->pw_name);
00441        entries[i].shown = entries[i].real;
00442        entries[i].statDone = 1;
00443        if (len > maxChars) {
00444            maxChars = len;
00445        }
00446        SFstrdup(&SFlogins[i].name, pw->pw_name);
00447        SFstrdup(&SFlogins[i].dir, pw->pw_dir);
00448        i++;
00449     }
00450 
00451     SFhomeDir.dir = XtMalloc(1);
00452     SFhomeDir.dir[0] = 0;
00453     SFhomeDir.path = SFcurrentPath;
00454     SFhomeDir.entries = entries;
00455     SFhomeDir.nEntries = i;
00456     SFhomeDir.vOrigin = 0;  /* :-) */
00457     SFhomeDir.nChars = maxChars + 2;
00458     SFhomeDir.hOrigin = 0;
00459     SFhomeDir.changed = 1;
00460     SFhomeDir.beginSelection = -1;
00461     SFhomeDir.endSelection = -1;
00462 
00463 #if defined(SVR4) || defined(SYSV) || defined(USG)
00464     qsort((char *)entries, (unsigned)i, sizeof(SFEntry), SFcompareEntries);
00465     qsort((char *)SFlogins, (unsigned)i, sizeof(SFLogin), SFcompareLogins);
00466 #else /* defined(SVR4) || defined(SYSV) || defined(USG) */
00467     qsort((char *)entries, i, sizeof(SFEntry), SFcompareEntries);
00468     qsort((char *)SFlogins, i, sizeof(SFLogin), SFcompareLogins);
00469 #endif /* defined(SVR4) || defined(SYSV) || defined(USG) */
00470 
00471     for (i--; i >= 0; i--) {
00472        (void)strcat(entries[i].real, "/");
00473     }
00474 }
00475 
00476 static int
00477 SFfindHomeDir(char *begin, char *end)
00478 {
00479     char save;
00480     char *theRest;
00481     int i;
00482 
00483     save = *end;
00484     *end = 0;
00485 
00486     for (i = SFhomeDir.nEntries - 1; i >= 0; i--) {
00487        if (!strcmp(SFhomeDir.entries[i].real, begin)) {
00488            *end = save;
00489            SFstrdup(&theRest, end);
00490            (void)strcat(strcat(strcpy(SFcurrentPath,
00491                                    SFlogins[i].dir), "/"), theRest);
00492            XtFree(theRest);
00493            SFsetText(SFcurrentPath);
00494            SFtextChanged();
00495            return 1;
00496        }
00497     }
00498 
00499     *end = save;
00500 
00501     return 0;
00502 }
00503 
00504 void
00505 SFupdatePath(void)
00506 {
00507     static int alloc;
00508     static int wasTwiddle = 0;
00509     char *begin, *end;
00510     int i, j;
00511     int prevChange;
00512     int SFdirPtrSave, SFdirEndSave;
00513     SFDir *dir;
00514 
00515     if (!SFdirs) {
00516        SFdirs = (SFDir *) XtMalloc((alloc = 10) * sizeof(SFDir));
00517        dir = &(SFdirs[0]);
00518        SFstrdup(&dir->dir, "/");
00519        (void)SFchdir("/");
00520        (void)SFgetDir(dir);
00521        for (j = 1; j < alloc; j++) {
00522            SFdirs[j].dir = NULL;
00523        }
00524        dir->path = SFcurrentPath + 1;
00525        dir->vOrigin = 0;
00526        dir->hOrigin = 0;
00527        dir->changed = 1;
00528        dir->beginSelection = -1;
00529        dir->endSelection = -1;
00530        SFhomeDir.dir = NULL;
00531     }
00532 
00533     SFdirEndSave = SFdirEnd;
00534     SFdirEnd = 1;
00535 
00536     SFdirPtrSave = SFdirPtr;
00537     SFdirPtr = 0;
00538 
00539     begin = NULL;
00540 
00541     if (SFcurrentPath[0] == '~') {
00542        if (!SFtwiddle) {
00543            SFtwiddle = 1;
00544            dir = &(SFdirs[0]);
00545            SFrootDir = *dir;
00546            if (!SFhomeDir.dir) {
00547               SFgetHomeDirs();
00548            }
00549            *dir = SFhomeDir;
00550            dir->changed = 1;
00551        }
00552        end = SFcurrentPath;
00553        SFdoNotTouchDirPtr = 1;
00554        wasTwiddle = 1;
00555     }
00556     else {
00557        if (SFtwiddle) {
00558            SFtwiddle = 0;
00559            dir = &(SFdirs[0]);
00560            *dir = SFrootDir;
00561            dir->changed = 1;
00562        }
00563        end = SFcurrentPath + 1;
00564     }
00565 
00566     i = 0;
00567 
00568     prevChange = 0;
00569 
00570     while (*end) {
00571        while (*end++ == '/') {
00572            ;
00573        }
00574        end--;
00575        begin = end;
00576        while ((*end) && (*end++ != '/')) {
00577            ;
00578        }
00579        if ((end - SFcurrentPath <= SFtextPos) && (*(end - 1) == '/')) {
00580            SFdirPtr = i - 1;
00581            if (SFdirPtr < 0) {
00582               SFdirPtr = 0;
00583            }
00584        }
00585        if (*begin) {
00586            if (*(end - 1) == '/') {
00587               char save = *end;
00588 
00589               if (SFtwiddle) {
00590                   if (SFfindHomeDir(begin, end)) {
00591                      return;
00592                   }
00593               }
00594               *end = 0;
00595               i++;
00596               SFdirEnd++;
00597               if (i >= alloc) {
00598                   SFdirs = (SFDir *) XtRealloc(
00599                                            (char *)SFdirs,
00600                                            (unsigned)((alloc *= 2) *
00601                                                      sizeof(SFDir))
00602                      );
00603                   for (j = alloc / 2; j < alloc; j++) {
00604                      SFdirs[j].dir = NULL;
00605                   }
00606               }
00607               dir = &(SFdirs[i]);
00608               if ((!(dir->dir)) || prevChange || strcmp(dir->dir, begin)
00609                   ) {
00610                   if (dir->dir) {
00611                      SFfree(i);
00612                   }
00613                   prevChange = 1;
00614                   SFstrdup(&dir->dir, begin);
00615                   dir->path = end;
00616                   dir->vOrigin = 0;
00617                   dir->hOrigin = 0;
00618                   dir->changed = 1;
00619                   dir->beginSelection = -1;
00620                   dir->endSelection = -1;
00621                   (void)SFfindFile(dir - 1, begin);
00622                   if (SFchdir(SFcurrentPath) || SFgetDir(dir)
00623                      ) {
00624                      SFunreadableDir(dir);
00625                      break;
00626                   }
00627               }
00628               *end = save;
00629               if (!save) {
00630                   SFunselect();
00631               }
00632            }
00633            else {
00634               if (SFfindFile(&(SFdirs[SFdirEnd - 1]), begin)) {
00635                   return;
00636               }
00637            }
00638        }
00639        else {
00640            SFunselect();
00641        }
00642     }
00643 
00644     if ((end == SFcurrentPath + 1) && (!SFtwiddle)) {
00645        SFunselect();
00646     }
00647 
00648     for (i = SFdirEnd; i < alloc; i++) {
00649        if (SFdirs[i].dir) {
00650            SFfree(i);
00651        }
00652     }
00653 
00654     if (SFdoNotTouchDirPtr) {
00655        if (wasTwiddle) {
00656            wasTwiddle = 0;
00657            SFdirPtr = SFdirEnd - 2;
00658            if (SFdirPtr < 0) {
00659               SFdirPtr = 0;
00660            }
00661        }
00662        else {
00663            SFdirPtr = SFdirPtrSave;
00664        }
00665        SFdoNotTouchDirPtr = 0;
00666     }
00667 
00668     if ((SFdirPtr != SFdirPtrSave) || (SFdirEnd != SFdirEndSave)) {
00669        XawScrollbarSetThumb(selFileHScroll,
00670                           (double)(SFdirPtr) / SFdirEnd,
00671                           (double)(SFdirEnd < 3 ? SFdirEnd : 3) / SFdirEnd);
00672     }
00673 
00674     if (SFdirPtr != SFdirPtrSave) {
00675        SFdrawLists(SF_DO_SCROLL);
00676     }
00677     else {
00678        for (i = 0; i < 3; i++) {
00679            if (SFdirPtr + i < SFdirEnd) {
00680               if (SFdirs[SFdirPtr + i].changed) {
00681                   SFdirs[SFdirPtr + i].changed = 0;
00682                   SFdrawList(i, SF_DO_SCROLL);
00683               }
00684            }
00685            else {
00686               SFclearList(i, SF_DO_SCROLL);
00687            }
00688        }
00689     }
00690 }
00691 
00692 void
00693 SFsetText(char *path)
00694 {
00695     XawTextBlock text;
00696 
00697     text.firstPos = 0;
00698     text.length = strlen(path);
00699     text.ptr = path;
00700     text.format = FMT8BIT;
00701 
00702     XawTextReplace(selFileField, 0, strlen(SFtextBuffer), &text);
00703     XawTextSetInsertionPoint(selFileField, strlen(SFtextBuffer));
00704 }
00705 
00706 void
00707 SFbuttonPressList(Widget w, int n, XButtonPressedEvent *event)
00708 {
00709     UNUSED(w);
00710     UNUSED(n);
00711     UNUSED(event);
00712     
00713     SFbuttonPressed = 1;
00714 }
00715 
00716 void
00717 SFbuttonReleaseList(Widget w, int n, XButtonReleasedEvent *event)
00718 {
00719     SFDir *dir;
00720 
00721     SFbuttonPressed = 0;
00722 
00723     if (SFcurrentInvert[n] != -1) {
00724        if (n < 2) {
00725            SFdoNotTouchDirPtr = 1;
00726        }
00727        SFdoNotTouchVorigin = 1;
00728        dir = &(SFdirs[SFdirPtr + n]);
00729        SFreplaceText(dir,
00730                     dir->entries[dir->vOrigin + SFcurrentInvert[n]].shown);
00731        SFmotionList(w, n, (XMotionEvent *)event);
00732     }
00733 }
00734 
00735 static int
00736 SFcheckDir(int n, SFDir *dir)
00737 {
00738     struct stat statBuf;
00739     int i;
00740 
00741     if ((!stat(".", &statBuf)) && (statBuf.st_mtime != dir->mtime)
00742        ) {
00743 
00744        /*
00745         * If the pointer is currently in the window that we are about
00746         * to update, we must warp it to prevent the user from
00747         * accidentally selecting the wrong file.
00748         */
00749        if (SFcurrentInvert[n] != -1) {
00750            XWarpPointer(SFdisplay,
00751                       None, XtWindow(selFileLists[n]), 0, 0, 0, 0, 0, 0);
00752        }
00753 
00754        for (i = dir->nEntries - 1; i >= 0; i--) {
00755            if (dir->entries[i].shown != dir->entries[i].real) {
00756               XtFree(dir->entries[i].shown);
00757            }
00758            XtFree(dir->entries[i].real);
00759        }
00760        XtFree((char *)dir->entries);
00761        if (SFgetDir(dir)) {
00762            SFunreadableDir(dir);
00763        }
00764        if (dir->vOrigin > dir->nEntries - SFlistSize) {
00765            dir->vOrigin = dir->nEntries - SFlistSize;
00766        }
00767        if (dir->vOrigin < 0) {
00768            dir->vOrigin = 0;
00769        }
00770        if (dir->hOrigin > dir->nChars - SFcharsPerEntry) {
00771            dir->hOrigin = dir->nChars - SFcharsPerEntry;
00772        }
00773        if (dir->hOrigin < 0) {
00774            dir->hOrigin = 0;
00775        }
00776        dir->beginSelection = -1;
00777        dir->endSelection = -1;
00778        SFdoNotTouchVorigin = 1;
00779        if ((dir + 1)->dir) {
00780            (void)SFfindFile(dir, (dir + 1)->dir);
00781        }
00782        else {
00783            (void)SFfindFile(dir, dir->path);
00784        }
00785 
00786        if (!SFworkProcAdded) {
00787            (void)XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL);
00788            SFworkProcAdded = 1;
00789        }
00790 
00791        return 1;
00792     }
00793 
00794     return 0;
00795 }
00796 
00797 static int
00798 SFcheckFiles(SFDir *dir)
00799 {
00800     int from, to;
00801     int result;
00802     char old, new;
00803     int i;
00804     char *str;
00805     int last;
00806     struct stat statBuf;
00807 
00808     result = 0;
00809 
00810     from = dir->vOrigin;
00811     to = dir->vOrigin + SFlistSize;
00812     if (to > dir->nEntries) {
00813        to = dir->nEntries;
00814     }
00815 
00816     for (i = from; i < to; i++) {
00817        str = dir->entries[i].real;
00818        last = strlen(str) - 1;
00819        old = str[last];
00820        str[last] = 0;
00821        if (stat(str, &statBuf)) {
00822            new = ' ';
00823        }
00824        else {
00825            new = SFstatChar(&statBuf);
00826        }
00827        str[last] = new;
00828        if (new != old) {
00829            result = 1;
00830        }
00831     }
00832 
00833     return result;
00834 }
00835 
00836 void
00837 SFdirModTimer(XtPointer cl, XtIntervalId *id)
00838 {
00839     static int n = -1;
00840     static int f = 0;
00841     char save;
00842     SFDir *dir;
00843 
00844     UNUSED(cl);
00845     UNUSED(id);
00846 
00847     fprintf(stderr, "sfdirmodtimer called!\n");
00848     
00849     if ((!SFtwiddle) && (SFdirPtr < SFdirEnd)) {
00850        n++;
00851        if ((n > 2) || (SFdirPtr + n >= SFdirEnd)) {
00852            n = 0;
00853            f++;
00854            if ((f > 2) || (SFdirPtr + f >= SFdirEnd)) {
00855               f = 0;
00856            }
00857        }
00858        dir = &(SFdirs[SFdirPtr + n]);
00859        save = *(dir->path);
00860        *(dir->path) = 0;
00861        if (SFchdir(SFcurrentPath)) {
00862            *(dir->path) = save;
00863 
00864            /*
00865             * force a re-read
00866             */
00867            *(dir->dir) = 0;
00868 
00869            SFupdatePath();
00870        }
00871        else {
00872            *(dir->path) = save;
00873            if (SFcheckDir(n, dir) || ((f == n) && SFcheckFiles(dir))
00874               ) {
00875               SFdrawList(n, SF_DO_SCROLL);
00876            }
00877        }
00878     }
00879 
00880     SFdirModTimerId = XtAppAddTimeOut(SFapp, 1500UL,
00881                                   SFdirModTimer, (XtPointer) NULL);
00882 }
00883 
00884 /* Return a single character describing what kind of file STATBUF is.  */
00885 
00886 char
00887 SFstatChar(struct stat *statBuf)
00888 {
00889     if (S_ISDIR(statBuf->st_mode)) {
00890        return '/';
00891     }
00892     else if (S_ISREG(statBuf->st_mode)) {
00893        return S_ISXXX(statBuf->st_mode) ? '*' : ' ';
00894 #ifdef S_ISSOCK
00895     }
00896     else if (S_ISSOCK(statBuf->st_mode)) {
00897        return '=';
00898 #endif /* S_ISSOCK */
00899     }
00900     else {
00901        return ' ';
00902     }
00903 }
00904 
00905 #else
00906 /* silence `empty compilation unit' warnings */
00907 static void bar(void); static void foo() { bar(); } static void bar(void) { foo(); }
00908 #endif /* !defined(MOTIF) */