"Fossies" - the Fresh Open Source Software Archive 
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 }