~ubuntu-branches/ubuntu/lucid/graphviz/lucid-security

« back to all changes in this revision

Viewing changes to lefty/ws/x11/libfilereq/Path.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen M Moraco
  • Date: 2002-02-05 18:52:12 UTC
  • Revision ID: james.westby@ubuntu.com-20020205185212-8i04c70te00rc40y
Tags: upstream-1.7.16
ImportĀ upstreamĀ versionĀ 1.7.16

Show diffs side-by-side

added added

removed removed

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