Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

611014 views
1
/****************************************************************************
2
**
3
*W selfile.c XGAP Source Erik M. van der Poel
4
*W modified by Frank Celler
5
**
6
**
7
** This file is based on the file selector distributed with ghostview, it
8
** contained the following notice:
9
**
10
*Y Copyright 1989, Software Research Associates Inc., Tokyo, Japan
11
**
12
** Permission to use, copy, modify, and distribute this software and its
13
** documentation for any purpose and without fee is hereby granted, provided
14
** that the above copyright notice appear in all copies and that both that
15
** copyright notice and this permission notice appear in supporting
16
** documentation, and that the name of Software Research Associates not be
17
** used in advertising or publicity pertaining to distribution of the
18
** software without specific, written prior permission. Software Research
19
** Associates makes no representations about the suitability of this
20
** software for any purpose. It is provided "as is" without express or
21
** implied warranty.
22
**
23
** SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
24
** SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
25
** FITNESS, IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY
26
** SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
27
** RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
28
** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
29
** CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30
**
31
** Author: Erik M. van der Poel
32
** Software Research Associates, Inc., Tokyo, Japan
33
** [email protected]
34
**
35
** Author's address:
36
**
37
** [email protected]
38
** OR
39
** erik%[email protected]
40
** OR
41
** erik%[email protected]
42
** OR
43
** try junet instead of co.jp
44
** OR
45
** Erik M. van der Poel
46
** Software Research Associates, Inc.
47
** 1-1-1 Hirakawa-cho, Chiyoda-ku
48
** Tokyo 102 Japan. TEL +81-3-234-2692
49
*/
50
#ifndef NO_FILE_SELECTOR
51
52
#ifdef hpux
53
# define USG
54
#endif
55
56
#include "utils.h"
57
58
#if HAVE_DIRENT_H
59
# include <dirent.h>
60
# define NAMLEN(dirent) strlen((dirent)->d_name)
61
#else
62
# define dirent direct
63
# define NAMLEN(dirent) (dirent)->d_namlen
64
# if HAVE_SYS_NDIR_H
65
# include <sys/ndir.h>
66
# endif
67
# if HAVE_SYS_DIR_H
68
# include <sys/dir.h>
69
# endif
70
# if HAVE_NDIR_H
71
# include <ndir.h>
72
# endif
73
#endif
74
75
#include <unistd.h>
76
77
#include "selfile.h"
78
79
#define SEL_FILE_CANCEL -1
80
#define SEL_FILE_OK 0
81
#define SEL_FILE_NULL 1
82
#define SEL_FILE_TEXT 2
83
84
#define SF_DO_SCROLL 1
85
#define SF_DO_NOT_SCROLL 0
86
87
88
/****************************************************************************
89
**
90
91
*T Typedefs . . . . . . . . . . . . . . . . . . . various private typedefs
92
*/
93
typedef struct {
94
int statDone;
95
char *real;
96
char *shown;
97
} SFEntry;
98
99
typedef struct {
100
char *dir;
101
char *path;
102
SFEntry *entries;
103
int nEntries;
104
int vOrigin;
105
int nChars;
106
int hOrigin;
107
int changed;
108
int beginSelection;
109
int endSelection;
110
time_t mtime;
111
} SFDir;
112
113
static void
114
SFenterList(),
115
SFleaveList(),
116
SFmotionList(),
117
SFbuttonPressList(),
118
SFbuttonReleaseList();
119
120
static void
121
SFvSliderMovedCallback(),
122
SFvFloatSliderMovedCallback(),
123
SFhSliderMovedCallback(),
124
SFpathSliderMovedCallback(),
125
SFvAreaSelectedCallback(),
126
SFhAreaSelectedCallback(),
127
SFpathAreaSelectedCallback();
128
129
static Boolean SFworkProc();
130
131
static int SFcompareEntries();
132
133
static void SFdirModTimer();
134
135
static char SFstatChar();
136
137
138
/* BSD 4.3 errno.h does not declare errno */
139
extern int errno;
140
/* extern int sys_nerr; */
141
142
#if !defined(S_ISDIR) && defined(S_IFDIR)
143
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
144
#endif
145
#if !defined(S_ISREG) && defined(S_IFREG)
146
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
147
#endif
148
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
149
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
150
#endif
151
152
#ifndef S_IXUSR
153
#define S_IXUSR 0100
154
#endif
155
#ifndef S_IXGRP
156
#define S_IXGRP 0010
157
#endif
158
#ifndef S_IXOTH
159
#define S_IXOTH 0001
160
#endif
161
162
#define S_ISXXX(m) ((m) & (S_IXUSR | S_IXGRP | S_IXOTH))
163
164
#ifndef MAXPATHLEN
165
#define MAXPATHLEN 1024
166
#endif /* ndef MAXPATHLEN */
167
168
static int SFstatus = SEL_FILE_NULL;
169
170
static char
171
SFstartDir[MAXPATHLEN],
172
SFcurrentPath[MAXPATHLEN],
173
SFcurrentDir[MAXPATHLEN];
174
175
static Widget
176
selFile,
177
selFileCancel,
178
selFileField,
179
selFileForm,
180
selFileHScroll,
181
selFileHScrolls[3],
182
selFileLists[3],
183
selFileOK,
184
selFileHome,
185
selFilePrompt,
186
selFileVScrolls[3];
187
188
static Display *SFdisplay = 0;
189
190
static Pixel SFfore, SFback;
191
192
static Atom SFwmDeleteWindow;
193
194
static XSegment SFsegs[2], SFcompletionSegs[2];
195
196
static XawTextPosition SFtextPos;
197
198
static int SFupperX, SFlowerY, SFupperY;
199
200
static int SFtextX, SFtextYoffset;
201
202
static int SFentryWidth, SFentryHeight;
203
204
static int SFlineToTextH = 3;
205
206
static int SFlineToTextV = 3;
207
208
static int SFbesideText = 3;
209
210
static int SFaboveAndBelowText = 2;
211
212
static int SFcharsPerEntry = 15;
213
214
static int SFlistSize = 10;
215
216
static int SFworkProcAdded = 0;
217
218
static XtAppContext SFapp;
219
220
static int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth;
221
222
static char SFtextBuffer[MAXPATHLEN];
223
224
static XtIntervalId SFdirModTimerId;
225
226
static int (*SFfunc)( String, String*, struct stat* ) = 0;
227
228
229
static SFDir *SFdirs = NULL;
230
231
static int SFdirEnd;
232
233
static int SFdirPtr;
234
235
static int SFbuttonPressed = 0;
236
237
static int SFdoNotTouchDirPtr = 0;
238
239
static int SFdoNotTouchVorigin = 0;
240
241
static SFDir SFrootDir, SFhomeDir;
242
243
typedef struct {
244
char *name;
245
char *dir;
246
} SFLogin;
247
248
static SFLogin *SFlogins;
249
250
static int SFtwiddle = 0;
251
252
253
254
/****************************************************************************
255
**
256
*F SFcompareEntries( <p>, <q> ) . . . . . . . . . . compare two sf entries
257
*/
258
static int SFcompareEntries ( const void *p, const void *q )
259
{
260
return strcmp(((const SFEntry *)p)->real, ((const SFEntry *)q)->real);
261
}
262
263
264
static int SFgetDir( SFDir *dir )
265
{
266
SFEntry *result = NULL;
267
int alloc = 0;
268
int i;
269
DIR *dirp;
270
struct dirent *dp;
271
char *str;
272
int len;
273
int maxChars;
274
struct stat statBuf;
275
276
maxChars = strlen(dir->dir) - 1;
277
278
dir->entries = NULL;
279
dir->nEntries = 0;
280
dir->nChars = 0;
281
282
result = NULL;
283
i = 0;
284
285
dirp = opendir(".");
286
if (!dirp) {
287
return 1;
288
}
289
290
(void) stat(".", &statBuf);
291
dir->mtime = statBuf.st_mtime;
292
293
(void) readdir(dirp); /* throw away "." */
294
295
#ifndef S_IFLNK
296
(void) readdir(dirp); /* throw away ".." */
297
#endif /* ndef S_IFLNK */
298
299
while ( (dp=readdir(dirp)) ) {
300
if (i >= alloc) {
301
alloc = 2 * (alloc + 1);
302
result = (SFEntry *) XtRealloc((char *) result,
303
(unsigned) (alloc * sizeof(SFEntry)));
304
}
305
result[i].statDone = 0;
306
str = dp->d_name;
307
len = strlen(str);
308
result[i].real = XtMalloc((unsigned) (len + 2));
309
(void) strcat(strcpy(result[i].real, str), " ");
310
if (len > maxChars) {
311
maxChars = len;
312
}
313
result[i].shown = result[i].real;
314
i++;
315
}
316
317
qsort(result, i, sizeof(SFEntry), SFcompareEntries);
318
319
dir->entries = result;
320
dir->nEntries = i;
321
dir->nChars = maxChars + 1;
322
323
closedir(dirp);
324
325
return 0;
326
}
327
328
static char *oneLineTextEditTranslations = "\
329
<Key>Return: redraw-display()\n\
330
Ctrl<Key>M: redraw-display()\n\
331
";
332
333
#define SF_DEFAULT_FONT "9x15"
334
335
#ifdef ABS
336
#undef ABS
337
#endif
338
#define ABS(x) (((x) < 0) ? (-(x)) : (x))
339
340
typedef struct {
341
char *fontname;
342
} TextData, *textPtr;
343
344
int SFcharWidth, SFcharAscent, SFcharHeight;
345
346
int SFcurrentInvert[3] = { -1, -1, -1 };
347
348
static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC;
349
350
static XtResource textResources[] = {
351
{XtNfont, XtCFont, XtRString, sizeof (char *),
352
XtOffset(textPtr, fontname), XtRString, SF_DEFAULT_FONT},
353
};
354
355
static XFontStruct *SFfont;
356
357
static int SFcurrentListY;
358
359
static XtIntervalId SFscrollTimerId;
360
361
void SFinitFont()
362
{
363
TextData *data;
364
365
data = XtNew(TextData);
366
367
XtGetApplicationResources(selFileForm, (XtPointer) data, textResources,
368
XtNumber(textResources), (Arg *) NULL, ZERO);
369
370
SFfont = XLoadQueryFont(SFdisplay, data->fontname);
371
if (!SFfont) {
372
SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT);
373
if (!SFfont) {
374
char sbuf[256];
375
376
(void) sprintf(sbuf, "XsraSelFile: can't get font %s",
377
SF_DEFAULT_FONT);
378
379
XtAppError(SFapp, sbuf);
380
}
381
}
382
383
SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2;
384
SFcharAscent = SFfont->max_bounds.ascent;
385
SFcharHeight = SFcharAscent + SFfont->max_bounds.descent;
386
}
387
388
void SFcreateGC()
389
{
390
XGCValues gcValues;
391
XRectangle rectangles[1];
392
393
gcValues.foreground = SFfore;
394
395
SFlineGC = XtGetGC(
396
selFileLists[0],
397
(XtGCMask)
398
GCForeground |
399
0,
400
&gcValues
401
);
402
403
SFscrollGC = XtGetGC(
404
selFileLists[0],
405
(XtGCMask)
406
0,
407
&gcValues
408
);
409
410
gcValues.function = GXinvert;
411
gcValues.plane_mask = (SFfore ^ SFback);
412
413
SFinvertGC = XtGetGC(
414
selFileLists[0],
415
(XtGCMask)
416
GCFunction |
417
GCPlaneMask |
418
0,
419
&gcValues
420
);
421
422
gcValues.foreground = SFfore;
423
gcValues.background = SFback;
424
gcValues.font = SFfont->fid;
425
426
SFtextGC = XCreateGC(
427
SFdisplay,
428
XtWindow(selFileLists[0]),
429
(unsigned long)
430
GCForeground |
431
GCBackground |
432
GCFont |
433
0,
434
&gcValues
435
);
436
437
rectangles[0].x = SFlineToTextH + SFbesideText;
438
rectangles[0].y = 0;
439
rectangles[0].width = SFcharsPerEntry * SFcharWidth;
440
rectangles[0].height = SFupperY + 1;
441
442
XSetClipRectangles(
443
SFdisplay,
444
SFtextGC,
445
0,
446
0,
447
rectangles,
448
1,
449
Unsorted
450
);
451
}
452
453
void SFclearList(int n, int doScroll)
454
{
455
SFDir *dir;
456
457
SFcurrentInvert[n] = -1;
458
459
XClearWindow(SFdisplay, XtWindow(selFileLists[n]));
460
461
XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs,
462
2);
463
464
if (doScroll) {
465
dir = &(SFdirs[SFdirPtr + n]);
466
467
if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars) {
468
XawScrollbarSetThumb(
469
selFileVScrolls[n],
470
(float) (((double) dir->vOrigin) /
471
dir->nEntries),
472
(float) (((double) ((dir->nEntries < SFlistSize)
473
? dir->nEntries : SFlistSize)) /
474
dir->nEntries)
475
);
476
477
XawScrollbarSetThumb(
478
selFileHScrolls[n],
479
(float) (((double) dir->hOrigin) / dir->nChars),
480
(float) (((double) ((dir->nChars <
481
SFcharsPerEntry) ? dir->nChars :
482
SFcharsPerEntry)) / dir->nChars)
483
);
484
} else {
485
XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
486
(float) 1.0);
487
XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
488
(float) 1.0);
489
}
490
}
491
}
492
493
static void
494
SFdeleteEntry(SFDir *dir, SFEntry *entry)
495
{
496
register SFEntry *e;
497
register SFEntry *end;
498
int n;
499
int idx;
500
501
idx = entry - dir->entries;
502
503
if (idx < dir->beginSelection) {
504
dir->beginSelection--;
505
}
506
if (idx <= dir->endSelection) {
507
dir->endSelection--;
508
}
509
if (dir->beginSelection > dir->endSelection) {
510
dir->beginSelection = dir->endSelection = -1;
511
}
512
513
if (idx < dir->vOrigin) {
514
dir->vOrigin--;
515
}
516
517
XtFree(entry->real);
518
519
end = &(dir->entries[dir->nEntries - 1]);
520
521
for (e = entry; e < end; e++) {
522
*e = *(e + 1);
523
}
524
525
if (!(--dir->nEntries)) {
526
return;
527
}
528
529
n = dir - &(SFdirs[SFdirPtr]);
530
if ((n < 0) || (n > 2)) {
531
return;
532
}
533
534
XawScrollbarSetThumb(
535
selFileVScrolls[n],
536
(float) (((double) dir->vOrigin) / dir->nEntries),
537
(float) (((double) ((dir->nEntries < SFlistSize) ?
538
dir->nEntries : SFlistSize)) / dir->nEntries)
539
);
540
}
541
542
static void
543
SFwriteStatChar(char *name, int last, struct stat *statBuf)
544
{
545
name[last] = SFstatChar(statBuf);
546
}
547
548
static int SFchdir(char *path)
549
{
550
int result;
551
552
result = 0;
553
554
if (strcmp(path, SFcurrentDir)) {
555
result = chdir(path);
556
if (!result) {
557
(void) strcpy(SFcurrentDir, path);
558
}
559
}
560
561
return result;
562
}
563
564
static int
565
SFstatAndCheck(SFDir *dir, SFEntry *entry)
566
{
567
struct stat statBuf;
568
char save;
569
int last;
570
571
/*
572
* must be restored before returning
573
*/
574
save = *(dir->path);
575
*(dir->path) = 0;
576
577
if (!SFchdir(SFcurrentPath)) {
578
last = strlen(entry->real) - 1;
579
entry->real[last] = 0;
580
entry->statDone = 1;
581
if (
582
(!stat(entry->real, &statBuf))
583
584
#ifdef S_IFLNK
585
586
|| (!lstat(entry->real, &statBuf))
587
588
#endif /* ndef S_IFLNK */
589
590
) {
591
if (SFfunc) {
592
char *shown;
593
594
shown = NULL;
595
if (SFfunc(entry->real, &shown, &statBuf)) {
596
if (shown) {
597
int len;
598
599
len = strlen(shown);
600
entry->shown = XtMalloc(
601
(unsigned) (len + 2)
602
);
603
(void) strcpy(entry->shown,
604
shown);
605
SFwriteStatChar(
606
entry->shown,
607
len,
608
&statBuf
609
);
610
entry->shown[len + 1] = 0;
611
}
612
} else {
613
SFdeleteEntry(dir, entry);
614
615
*(dir->path) = save;
616
return 1;
617
}
618
}
619
SFwriteStatChar(entry->real, last, &statBuf);
620
} else {
621
entry->real[last] = ' ';
622
}
623
}
624
625
*(dir->path) = save;
626
return 0;
627
}
628
629
static void
630
SFdrawStrings(Window w, SFDir *dir, int from, int to)
631
{
632
register int i;
633
register SFEntry *entry;
634
int x;
635
636
x = SFtextX - dir->hOrigin * SFcharWidth;
637
638
if (dir->vOrigin + to >= dir->nEntries) {
639
to = dir->nEntries - dir->vOrigin - 1;
640
}
641
for (i = from; i <= to; i++) {
642
entry = &(dir->entries[dir->vOrigin + i]);
643
if (!(entry->statDone)) {
644
if (SFstatAndCheck(dir, entry)) {
645
if (dir->vOrigin + to >= dir->nEntries) {
646
to = dir->nEntries - dir->vOrigin - 1;
647
}
648
i--;
649
continue;
650
}
651
}
652
XDrawImageString(
653
SFdisplay,
654
w,
655
SFtextGC,
656
x,
657
SFtextYoffset + i * SFentryHeight,
658
entry->shown,
659
strlen(entry->shown)
660
);
661
if (dir->vOrigin + i == dir->beginSelection) {
662
XDrawLine(
663
SFdisplay,
664
w,
665
SFlineGC,
666
SFlineToTextH + 1,
667
SFlowerY + i * SFentryHeight,
668
SFlineToTextH + SFentryWidth - 2,
669
SFlowerY + i * SFentryHeight
670
);
671
}
672
if (
673
(dir->vOrigin + i >= dir->beginSelection) &&
674
(dir->vOrigin + i <= dir->endSelection)
675
) {
676
SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
677
SFlowerY + i * SFentryHeight;
678
SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
679
SFlowerY + (i + 1) * SFentryHeight - 1;
680
XDrawSegments(
681
SFdisplay,
682
w,
683
SFlineGC,
684
SFcompletionSegs,
685
2
686
);
687
}
688
if (dir->vOrigin + i == dir->endSelection) {
689
XDrawLine(
690
SFdisplay,
691
w,
692
SFlineGC,
693
SFlineToTextH + 1,
694
SFlowerY + (i + 1) * SFentryHeight - 1,
695
SFlineToTextH + SFentryWidth - 2,
696
SFlowerY + (i + 1) * SFentryHeight - 1
697
);
698
}
699
}
700
}
701
702
void SFdrawList(int n, int doScroll)
703
{
704
SFDir *dir;
705
Window w;
706
707
SFclearList(n, doScroll);
708
709
if (SFdirPtr + n < SFdirEnd) {
710
dir = &(SFdirs[SFdirPtr + n]);
711
w = XtWindow(selFileLists[n]);
712
XDrawImageString(
713
SFdisplay,
714
w,
715
SFtextGC,
716
SFtextX - dir->hOrigin * SFcharWidth,
717
SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
718
dir->dir,
719
strlen(dir->dir)
720
);
721
SFdrawStrings(w, dir, 0, SFlistSize - 1);
722
}
723
}
724
725
void SFdrawLists(int doScroll)
726
{
727
int i;
728
729
for (i = 0; i < 3; i++) {
730
SFdrawList(i, doScroll);
731
}
732
}
733
734
static void
735
SFinvertEntry(register int n)
736
{
737
XFillRectangle(
738
SFdisplay,
739
XtWindow(selFileLists[n]),
740
SFinvertGC,
741
SFlineToTextH,
742
SFcurrentInvert[n] * SFentryHeight + SFlowerY,
743
SFentryWidth,
744
SFentryHeight
745
);
746
}
747
748
static unsigned long
749
SFscrollTimerInterval()
750
{
751
static int maxVal = 200;
752
static int varyDist = 50;
753
static int minDist = 50;
754
int t;
755
int dist;
756
757
if (SFcurrentListY < SFlowerY) {
758
dist = SFlowerY - SFcurrentListY;
759
} else if (SFcurrentListY > SFupperY) {
760
dist = SFcurrentListY - SFupperY;
761
} else {
762
return (unsigned long) 1;
763
}
764
765
t = maxVal - ((maxVal / varyDist) * (dist - minDist));
766
767
if (t < 1) {
768
t = 1;
769
}
770
771
if (t > maxVal) {
772
t = maxVal;
773
}
774
775
return (unsigned long) t;
776
}
777
778
static void
779
SFscrollTimer(XtPointer p, XtIntervalId *id)
780
{
781
SFDir *dir;
782
int save;
783
long n;
784
785
n = (long) p;
786
787
dir = &(SFdirs[SFdirPtr + n]);
788
save = dir->vOrigin;
789
790
if (SFcurrentListY < SFlowerY) {
791
if (dir->vOrigin > 0) {
792
SFvSliderMovedCallback(selFileVScrolls[n], n,
793
dir->vOrigin - 1);
794
}
795
} else if (SFcurrentListY > SFupperY) {
796
if (dir->vOrigin < dir->nEntries - SFlistSize) {
797
SFvSliderMovedCallback(selFileVScrolls[n], n,
798
dir->vOrigin + 1);
799
}
800
}
801
802
if (dir->vOrigin != save) {
803
if (dir->nEntries) {
804
XawScrollbarSetThumb(
805
selFileVScrolls[n],
806
(float) (((double) dir->vOrigin) / dir->nEntries),
807
(float) (((double) ((dir->nEntries < SFlistSize) ?
808
dir->nEntries : SFlistSize)) / dir->nEntries)
809
);
810
}
811
}
812
813
if (SFbuttonPressed) {
814
SFscrollTimerId = XtAppAddTimeOut(SFapp,
815
SFscrollTimerInterval(), SFscrollTimer, (XtPointer) n);
816
}
817
}
818
819
static int
820
SFnewInvertEntry(long n, XMotionEvent *event)
821
{
822
register int x, y;
823
register int new;
824
static int SFscrollTimerAdded = 0;
825
826
x = event->x;
827
y = event->y;
828
829
if (SFdirPtr + n >= SFdirEnd) {
830
return -1;
831
} else if (
832
(x >= 0) && (x <= SFupperX) &&
833
(y >= SFlowerY) && (y <= SFupperY)
834
) {
835
register SFDir *dir = &(SFdirs[SFdirPtr + n]);
836
837
if (SFscrollTimerAdded) {
838
SFscrollTimerAdded = 0;
839
XtRemoveTimeOut(SFscrollTimerId);
840
}
841
842
new = (y - SFlowerY) / SFentryHeight;
843
if (dir->vOrigin + new >= dir->nEntries) {
844
return -1;
845
}
846
return new;
847
} else {
848
if (SFbuttonPressed) {
849
SFcurrentListY = y;
850
if (!SFscrollTimerAdded) {
851
SFscrollTimerAdded = 1;
852
SFscrollTimerId = XtAppAddTimeOut(SFapp,
853
SFscrollTimerInterval(), SFscrollTimer,
854
(XtPointer) n);
855
}
856
}
857
858
return -1;
859
}
860
}
861
862
/* ARGSUSED */
863
static void
864
SFenterList(Widget w, long n, XEnterWindowEvent *event)
865
{
866
register int new;
867
868
/* sanity */
869
if (SFcurrentInvert[n] != -1) {
870
SFinvertEntry(n);
871
SFcurrentInvert[n] = -1;
872
}
873
874
new = SFnewInvertEntry(n, (XMotionEvent *) event);
875
if (new != -1) {
876
SFcurrentInvert[n] = new;
877
SFinvertEntry(n);
878
}
879
}
880
881
/* ARGSUSED */
882
static void
883
SFleaveList(Widget w, int n, XEvent *event)
884
{
885
if (SFcurrentInvert[n] != -1) {
886
SFinvertEntry(n);
887
SFcurrentInvert[n] = -1;
888
}
889
}
890
891
/* ARGSUSED */
892
static void
893
SFmotionList(Widget w, int n, XMotionEvent *event)
894
{
895
register int new;
896
897
new = SFnewInvertEntry(n, event);
898
899
if (new != SFcurrentInvert[n]) {
900
if (SFcurrentInvert[n] != -1) {
901
SFinvertEntry(n);
902
}
903
SFcurrentInvert[n] = new;
904
if (new != -1) {
905
SFinvertEntry(n);
906
}
907
}
908
}
909
910
/* ARGSUSED */
911
static void
912
SFvFloatSliderMovedCallback(Widget w, int n, float *fnew)
913
{
914
int new;
915
916
new = (*fnew) * SFdirs[SFdirPtr + n].nEntries;
917
918
SFvSliderMovedCallback(w, n, new);
919
}
920
921
/* ARGSUSED */
922
static void
923
SFvSliderMovedCallback(Widget w, long n, int new)
924
{
925
int old;
926
register Window win;
927
SFDir *dir;
928
929
dir = &(SFdirs[SFdirPtr + n]);
930
931
old = dir->vOrigin;
932
dir->vOrigin = new;
933
934
if (old == new) {
935
return;
936
}
937
938
win = XtWindow(selFileLists[n]);
939
940
if (ABS(new - old) < SFlistSize) {
941
if (new > old) {
942
XCopyArea(
943
SFdisplay,
944
win,
945
win,
946
SFscrollGC,
947
SFlineToTextH,
948
SFlowerY + (new - old) * SFentryHeight,
949
SFentryWidth + SFlineToTextH,
950
(SFlistSize - (new - old)) * SFentryHeight,
951
SFlineToTextH,
952
SFlowerY
953
);
954
XClearArea(
955
SFdisplay,
956
win,
957
SFlineToTextH,
958
SFlowerY + (SFlistSize - (new - old)) *
959
SFentryHeight,
960
SFentryWidth + SFlineToTextH,
961
(new - old) * SFentryHeight,
962
False
963
);
964
SFdrawStrings(win, dir, SFlistSize - (new - old),
965
SFlistSize - 1);
966
} else {
967
XCopyArea(
968
SFdisplay,
969
win,
970
win,
971
SFscrollGC,
972
SFlineToTextH,
973
SFlowerY,
974
SFentryWidth + SFlineToTextH,
975
(SFlistSize - (old - new)) * SFentryHeight,
976
SFlineToTextH,
977
SFlowerY + (old - new) * SFentryHeight
978
);
979
XClearArea(
980
SFdisplay,
981
win,
982
SFlineToTextH,
983
SFlowerY,
984
SFentryWidth + SFlineToTextH,
985
(old - new) * SFentryHeight,
986
False
987
);
988
SFdrawStrings(win, dir, 0, old - new);
989
}
990
} else {
991
XClearArea(
992
SFdisplay,
993
win,
994
SFlineToTextH,
995
SFlowerY,
996
SFentryWidth + SFlineToTextH,
997
SFlistSize * SFentryHeight,
998
False
999
);
1000
SFdrawStrings(win, dir, 0, SFlistSize - 1);
1001
}
1002
}
1003
1004
/* ARGSUSED */
1005
static void
1006
SFvAreaSelectedCallback(Widget w, int n, int pnew)
1007
{
1008
SFDir *dir;
1009
int new;
1010
1011
dir = &(SFdirs[SFdirPtr + n]);
1012
1013
new = dir->vOrigin +
1014
(((double) pnew) / SFvScrollHeight) * dir->nEntries;
1015
1016
if (new > dir->nEntries - SFlistSize) {
1017
new = dir->nEntries - SFlistSize;
1018
}
1019
1020
if (new < 0) {
1021
new = 0;
1022
}
1023
1024
if (dir->nEntries) {
1025
float f;
1026
1027
f = ((double) new) / dir->nEntries;
1028
1029
XawScrollbarSetThumb(
1030
w,
1031
f,
1032
(float) (((double) ((dir->nEntries < SFlistSize) ?
1033
dir->nEntries : SFlistSize)) / dir->nEntries)
1034
);
1035
}
1036
1037
SFvSliderMovedCallback(w, n, new);
1038
}
1039
1040
/* ARGSUSED */
1041
static void
1042
SFhSliderMovedCallback(Widget w, int n, float *new)
1043
{
1044
SFDir *dir;
1045
int save;
1046
1047
dir = &(SFdirs[SFdirPtr + n]);
1048
save = dir->hOrigin;
1049
dir->hOrigin = (*new) * dir->nChars;
1050
if (dir->hOrigin == save) {
1051
return;
1052
}
1053
1054
SFdrawList(n, SF_DO_NOT_SCROLL);
1055
}
1056
1057
/* ARGSUSED */
1058
static void
1059
SFhAreaSelectedCallback(Widget w, int n, int pnew)
1060
{
1061
SFDir *dir;
1062
int new;
1063
1064
dir = &(SFdirs[SFdirPtr + n]);
1065
1066
new = dir->hOrigin +
1067
(((double) pnew) / SFhScrollWidth) * dir->nChars;
1068
1069
if (new > dir->nChars - SFcharsPerEntry) {
1070
new = dir->nChars - SFcharsPerEntry;
1071
}
1072
1073
if (new < 0) {
1074
new = 0;
1075
}
1076
1077
if (dir->nChars) {
1078
float f;
1079
1080
f = ((double) new) / dir->nChars;
1081
1082
XawScrollbarSetThumb(
1083
w,
1084
f,
1085
(float) (((double) ((dir->nChars < SFcharsPerEntry) ?
1086
dir->nChars : SFcharsPerEntry)) / dir->nChars)
1087
);
1088
1089
SFhSliderMovedCallback(w, n, &f);
1090
}
1091
}
1092
1093
/* ARGSUSED */
1094
static void
1095
SFpathSliderMovedCallback(Widget w, XtPointer client_data, float *new)
1096
{
1097
SFDir *dir;
1098
int n;
1099
XawTextPosition pos;
1100
int SFdirPtrSave;
1101
1102
SFdirPtrSave = SFdirPtr;
1103
SFdirPtr = (*new) * SFdirEnd;
1104
if (SFdirPtr == SFdirPtrSave) {
1105
return;
1106
}
1107
1108
SFdrawLists(SF_DO_SCROLL);
1109
1110
n = 2;
1111
while (SFdirPtr + n >= SFdirEnd) {
1112
n--;
1113
}
1114
1115
dir = &(SFdirs[SFdirPtr + n]);
1116
1117
pos = dir->path - SFcurrentPath;
1118
1119
if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
1120
pos -= strlen(SFstartDir);
1121
if (pos < 0) {
1122
pos = 0;
1123
}
1124
}
1125
1126
XawTextSetInsertionPoint(selFileField, pos);
1127
}
1128
1129
/* ARGSUSED */
1130
1131
static void
1132
SFpathAreaSelectedCallback(Widget w, XtPointer client_data, int pnew)
1133
{
1134
int new;
1135
float f;
1136
1137
new = SFdirPtr + (((double) pnew) / SFpathScrollWidth) * SFdirEnd;
1138
1139
if (new > SFdirEnd - 3) {
1140
new = SFdirEnd - 3;
1141
}
1142
1143
if (new < 0) {
1144
new = 0;
1145
}
1146
1147
f = ((double) new) / SFdirEnd;
1148
1149
XawScrollbarSetThumb(
1150
w,
1151
f,
1152
(float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
1153
SFdirEnd)
1154
);
1155
1156
SFpathSliderMovedCallback(w, (XtPointer) NULL, &f);
1157
}
1158
1159
static Boolean
1160
SFworkProc()
1161
{
1162
register SFDir *dir;
1163
register SFEntry *entry;
1164
1165
for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) {
1166
if (!(dir->nEntries)) {
1167
continue;
1168
}
1169
for (
1170
entry = &(dir->entries[dir->nEntries - 1]);
1171
entry >= dir->entries;
1172
entry--
1173
) {
1174
if (!(entry->statDone)) {
1175
(void) SFstatAndCheck(dir, entry);
1176
return False;
1177
}
1178
}
1179
}
1180
1181
SFworkProcAdded = 0;
1182
1183
return True;
1184
}
1185
1186
1187
static void
1188
SFfree(int i)
1189
{
1190
register SFDir *dir;
1191
register int j;
1192
1193
dir = &(SFdirs[i]);
1194
1195
for (j = dir->nEntries - 1; j >= 0; j--) {
1196
if (dir->entries[j].shown != dir->entries[j].real) {
1197
XtFree(dir->entries[j].shown);
1198
}
1199
XtFree(dir->entries[j].real);
1200
}
1201
1202
XtFree((char *) dir->entries);
1203
1204
XtFree(dir->dir);
1205
1206
dir->dir = NULL;
1207
}
1208
1209
static void
1210
SFstrdup(char **s1, char *s2)
1211
{
1212
*s1 = strcpy(XtMalloc((unsigned) (strlen(s2) + 1)), s2);
1213
}
1214
1215
static void
1216
SFunreadableDir(SFDir *dir)
1217
{
1218
char *cannotOpen = "<cannot open> ";
1219
1220
dir->entries = (SFEntry *) XtMalloc(sizeof(SFEntry));
1221
dir->entries[0].statDone = 1;
1222
SFstrdup(&dir->entries[0].real, cannotOpen);
1223
dir->entries[0].shown = dir->entries[0].real;
1224
dir->nEntries = 1;
1225
dir->nChars = strlen(cannotOpen);
1226
}
1227
1228
static void SFtextChanged( void );
1229
1230
static void SFsetText(char *path)
1231
{
1232
XawTextBlock text;
1233
1234
text.firstPos = 0;
1235
text.length = strlen(path);
1236
text.ptr = path;
1237
text.format = FMT8BIT;
1238
1239
XawTextReplace(selFileField, 0, strlen(SFtextBuffer), &text);
1240
XawTextSetInsertionPoint(selFileField, strlen(SFtextBuffer));
1241
}
1242
1243
static void
1244
SFreplaceText(SFDir *dir, char *str)
1245
{
1246
int len;
1247
1248
*(dir->path) = 0;
1249
len = strlen(str);
1250
if (str[len - 1] == '/') {
1251
(void) strcat(SFcurrentPath, str);
1252
} else {
1253
(void) strncat(SFcurrentPath, str, len - 1);
1254
}
1255
if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
1256
SFsetText(SFcurrentPath);
1257
} else {
1258
SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
1259
}
1260
1261
SFtextChanged();
1262
}
1263
1264
static void
1265
SFexpand(char *str)
1266
{
1267
int len;
1268
int cmp;
1269
char *name, *growing;
1270
SFDir *dir;
1271
SFEntry *entry, *max;
1272
1273
len = strlen(str);
1274
1275
dir = &(SFdirs[SFdirEnd - 1]);
1276
1277
if (dir->beginSelection == -1) {
1278
SFstrdup(&str, str);
1279
SFreplaceText(dir, str);
1280
XtFree(str);
1281
return;
1282
} else if (dir->beginSelection == dir->endSelection) {
1283
SFreplaceText(dir, dir->entries[dir->beginSelection].shown);
1284
return;
1285
}
1286
1287
max = &(dir->entries[dir->endSelection + 1]);
1288
1289
name = dir->entries[dir->beginSelection].shown;
1290
SFstrdup(&growing, name);
1291
1292
cmp = 0;
1293
while (!cmp) {
1294
entry = &(dir->entries[dir->beginSelection]);
1295
while (entry < max) {
1296
if ((cmp = strncmp(growing, entry->shown, len))) {
1297
break;
1298
}
1299
entry++;
1300
}
1301
len++;
1302
}
1303
1304
/*
1305
* SFreplaceText() expects filename
1306
*/
1307
growing[len - 2] = ' ';
1308
1309
growing[len - 1] = 0;
1310
SFreplaceText(dir, growing);
1311
XtFree(growing);
1312
}
1313
1314
static int
1315
SFfindFile(SFDir *dir, char *str)
1316
{
1317
register int i, last, max;
1318
register char *name, save;
1319
SFEntry *entries;
1320
int len;
1321
int begin, end;
1322
int result;
1323
1324
len = strlen(str);
1325
1326
if (str[len - 1] == ' ') {
1327
SFexpand(str);
1328
return 1;
1329
} else if (str[len - 1] == '/') {
1330
len--;
1331
}
1332
1333
max = dir->nEntries;
1334
1335
entries = dir->entries;
1336
1337
i = 0;
1338
while (i < max) {
1339
name = entries[i].shown;
1340
last = strlen(name) - 1;
1341
save = name[last];
1342
name[last] = 0;
1343
1344
result = strncmp(str, name, len);
1345
1346
name[last] = save;
1347
if (result <= 0) {
1348
break;
1349
}
1350
i++;
1351
}
1352
begin = i;
1353
while (i < max) {
1354
name = entries[i].shown;
1355
last = strlen(name) - 1;
1356
save = name[last];
1357
name[last] = 0;
1358
1359
result = strncmp(str, name, len);
1360
1361
name[last] = save;
1362
if (result) {
1363
break;
1364
}
1365
i++;
1366
}
1367
end = i;
1368
1369
if (begin != end) {
1370
if (
1371
(dir->beginSelection != begin) ||
1372
(dir->endSelection != end - 1)
1373
) {
1374
dir->changed = 1;
1375
dir->beginSelection = begin;
1376
if (str[strlen(str) - 1] == '/') {
1377
dir->endSelection = begin;
1378
} else {
1379
dir->endSelection = end - 1;
1380
}
1381
}
1382
} else {
1383
if (dir->beginSelection != -1) {
1384
dir->changed = 1;
1385
dir->beginSelection = -1;
1386
dir->endSelection = -1;
1387
}
1388
}
1389
1390
if (
1391
SFdoNotTouchVorigin ||
1392
((begin > dir->vOrigin) && (end < dir->vOrigin + SFlistSize))
1393
) {
1394
SFdoNotTouchVorigin = 0;
1395
return 0;
1396
}
1397
1398
i = begin - 1;
1399
if (i > max - SFlistSize) {
1400
i = max - SFlistSize;
1401
}
1402
if (i < 0) {
1403
i = 0;
1404
}
1405
1406
if (dir->vOrigin != i) {
1407
dir->vOrigin = i;
1408
dir->changed = 1;
1409
}
1410
1411
return 0;
1412
}
1413
1414
static void
1415
SFunselect()
1416
{
1417
SFDir *dir;
1418
1419
dir = &(SFdirs[SFdirEnd - 1]);
1420
if (dir->beginSelection != -1) {
1421
dir->changed = 1;
1422
}
1423
dir->beginSelection = -1;
1424
dir->endSelection = -1;
1425
}
1426
1427
static int
1428
SFcompareLogins(const void *p, const void *q)
1429
{
1430
return strcmp(((const SFLogin *)p)->name, ((const SFLogin *)q)->name);
1431
}
1432
1433
static void
1434
SFgetHomeDirs()
1435
{
1436
struct passwd *pw;
1437
int alloc;
1438
int i;
1439
SFEntry *entries = NULL;
1440
int len;
1441
int maxChars;
1442
1443
{
1444
alloc = 1;
1445
i = 1;
1446
entries = (SFEntry *) XtMalloc(sizeof(SFEntry));
1447
SFlogins = (SFLogin *) XtMalloc(sizeof(SFLogin));
1448
entries[0].real = XtMalloc(3);
1449
(void) strcpy(entries[0].real, "~");
1450
entries[0].shown = entries[0].real;
1451
entries[0].statDone = 1;
1452
SFlogins[0].name = "";
1453
pw = getpwuid((int) getuid());
1454
SFstrdup(&SFlogins[0].dir, pw ? pw->pw_dir : "/");
1455
maxChars = 0;
1456
}
1457
1458
(void) setpwent();
1459
1460
while ((pw = getpwent()) && (*(pw->pw_name))) {
1461
if (i >= alloc) {
1462
alloc *= 2;
1463
entries = (SFEntry *) XtRealloc(
1464
(char *) entries,
1465
(unsigned) (alloc * sizeof(SFEntry))
1466
);
1467
SFlogins = (SFLogin *) XtRealloc(
1468
(char *) SFlogins,
1469
(unsigned) (alloc * sizeof(SFLogin))
1470
);
1471
}
1472
len = strlen(pw->pw_name);
1473
entries[i].real = XtMalloc((unsigned) (len + 3));
1474
(void) strcat(strcpy(entries[i].real, "~"),
1475
pw->pw_name);
1476
entries[i].shown = entries[i].real;
1477
entries[i].statDone = 1;
1478
if (len > maxChars) {
1479
maxChars = len;
1480
}
1481
SFstrdup(&SFlogins[i].name, pw->pw_name);
1482
SFstrdup(&SFlogins[i].dir, pw->pw_dir);
1483
i++;
1484
}
1485
1486
SFhomeDir.dir = XtMalloc(1) ;
1487
SFhomeDir.dir[0] = 0 ;
1488
SFhomeDir.path = SFcurrentPath ;
1489
SFhomeDir.entries = entries ;
1490
SFhomeDir.nEntries = i ;
1491
SFhomeDir.vOrigin = 0 ; /* :-) */
1492
SFhomeDir.nChars = maxChars + 2 ;
1493
SFhomeDir.hOrigin = 0 ;
1494
SFhomeDir.changed = 1 ;
1495
SFhomeDir.beginSelection = -1 ;
1496
SFhomeDir.endSelection = -1 ;
1497
1498
qsort(entries, i, sizeof(SFEntry), SFcompareEntries);
1499
qsort(SFlogins, i, sizeof(SFLogin), SFcompareLogins);
1500
1501
for (i--; i >= 0; i--) {
1502
(void) strcat(entries[i].real, "/");
1503
}
1504
}
1505
1506
static int
1507
SFfindHomeDir(char *begin, char *end)
1508
{
1509
char save;
1510
char *theRest;
1511
int i;
1512
1513
save = *end;
1514
*end = 0;
1515
1516
for (i = SFhomeDir.nEntries - 1; i >= 0; i--) {
1517
if (!strcmp(SFhomeDir.entries[i].real, begin)) {
1518
*end = save;
1519
SFstrdup(&theRest, end);
1520
(void) strcat(strcat(strcpy(SFcurrentPath,
1521
SFlogins[i].dir), "/"), theRest);
1522
XtFree(theRest);
1523
SFsetText(SFcurrentPath);
1524
SFtextChanged();
1525
return 1;
1526
}
1527
}
1528
1529
*end = save;
1530
1531
return 0;
1532
}
1533
1534
static void SFupdatePath()
1535
{
1536
static int alloc;
1537
static int wasTwiddle = 0;
1538
char *begin, *end;
1539
int i, j;
1540
int prevChange;
1541
int SFdirPtrSave, SFdirEndSave;
1542
SFDir *dir;
1543
1544
if (!SFdirs) {
1545
SFdirs = (SFDir *) XtMalloc((alloc = 10) * sizeof(SFDir));
1546
dir = &(SFdirs[0]);
1547
SFstrdup(&dir->dir, "/");
1548
(void) SFchdir("/");
1549
(void) SFgetDir(dir);
1550
for (j = 1; j < alloc; j++) {
1551
SFdirs[j].dir = NULL;
1552
}
1553
dir->path = SFcurrentPath + 1;
1554
dir->vOrigin = 0;
1555
dir->hOrigin = 0;
1556
dir->changed = 1;
1557
dir->beginSelection = -1;
1558
dir->endSelection = -1;
1559
SFhomeDir.dir = NULL;
1560
}
1561
1562
SFdirEndSave = SFdirEnd;
1563
SFdirEnd = 1;
1564
1565
SFdirPtrSave = SFdirPtr;
1566
SFdirPtr = 0;
1567
1568
begin = NULL;
1569
1570
if (SFcurrentPath[0] == '~') {
1571
if (!SFtwiddle) {
1572
SFtwiddle = 1;
1573
dir = &(SFdirs[0]);
1574
SFrootDir = *dir;
1575
if (!SFhomeDir.dir) {
1576
SFgetHomeDirs();
1577
}
1578
*dir = SFhomeDir;
1579
dir->changed = 1;
1580
}
1581
end = SFcurrentPath;
1582
SFdoNotTouchDirPtr = 1;
1583
wasTwiddle = 1;
1584
} else {
1585
if (SFtwiddle) {
1586
SFtwiddle = 0;
1587
dir = &(SFdirs[0]);
1588
*dir = SFrootDir;
1589
dir->changed = 1;
1590
}
1591
end = SFcurrentPath + 1;
1592
}
1593
1594
i = 0;
1595
1596
prevChange = 0;
1597
1598
while (*end) {
1599
while (*end++ == '/') {
1600
;
1601
}
1602
end--;
1603
begin = end;
1604
while ((*end) && (*end++ != '/')) {
1605
;
1606
}
1607
if ((end - SFcurrentPath <= SFtextPos) && (*(end - 1) == '/')) {
1608
SFdirPtr = i - 1;
1609
if (SFdirPtr < 0) {
1610
SFdirPtr = 0;
1611
}
1612
}
1613
if (*begin) {
1614
if (*(end - 1) == '/') {
1615
char save = *end;
1616
1617
if (SFtwiddle) {
1618
if (SFfindHomeDir(begin, end)) {
1619
return;
1620
}
1621
}
1622
*end = 0;
1623
i++;
1624
SFdirEnd++;
1625
if (i >= alloc) {
1626
SFdirs = (SFDir *) XtRealloc(
1627
(char *) SFdirs,
1628
(unsigned) ((alloc *= 2) *
1629
sizeof(SFDir))
1630
);
1631
for (j = alloc / 2; j < alloc; j++) {
1632
SFdirs[j].dir = NULL;
1633
}
1634
}
1635
dir = &(SFdirs[i]);
1636
if (
1637
(!(dir->dir)) ||
1638
prevChange ||
1639
strcmp(dir->dir, begin)
1640
) {
1641
if (dir->dir) {
1642
SFfree(i);
1643
}
1644
prevChange = 1;
1645
SFstrdup(&dir->dir, begin);
1646
dir->path = end;
1647
dir->vOrigin = 0;
1648
dir->hOrigin = 0;
1649
dir->changed = 1;
1650
dir->beginSelection = -1;
1651
dir->endSelection = -1;
1652
(void) SFfindFile(dir - 1, begin);
1653
if (
1654
SFchdir(SFcurrentPath) ||
1655
SFgetDir(dir)
1656
) {
1657
SFunreadableDir(dir);
1658
break;
1659
}
1660
}
1661
*end = save;
1662
if (!save) {
1663
SFunselect();
1664
}
1665
} else {
1666
if (SFfindFile(&(SFdirs[SFdirEnd-1]), begin)) {
1667
return;
1668
}
1669
}
1670
} else {
1671
SFunselect();
1672
}
1673
}
1674
1675
if ((end == SFcurrentPath + 1) && (!SFtwiddle)) {
1676
SFunselect();
1677
}
1678
1679
for (i = SFdirEnd; i < alloc; i++) {
1680
if (SFdirs[i].dir) {
1681
SFfree(i);
1682
}
1683
}
1684
1685
if (SFdoNotTouchDirPtr) {
1686
if (wasTwiddle) {
1687
wasTwiddle = 0;
1688
SFdirPtr = SFdirEnd - 2;
1689
if (SFdirPtr < 0) {
1690
SFdirPtr = 0;
1691
}
1692
} else {
1693
SFdirPtr = SFdirPtrSave;
1694
}
1695
SFdoNotTouchDirPtr = 0;
1696
}
1697
1698
if ((SFdirPtr != SFdirPtrSave) || (SFdirEnd != SFdirEndSave)) {
1699
XawScrollbarSetThumb(
1700
selFileHScroll,
1701
(float) (((double) SFdirPtr) / SFdirEnd),
1702
(float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
1703
SFdirEnd)
1704
);
1705
}
1706
1707
if (SFdirPtr != SFdirPtrSave) {
1708
SFdrawLists(SF_DO_SCROLL);
1709
} else {
1710
for (i = 0; i < 3; i++) {
1711
if (SFdirPtr + i < SFdirEnd) {
1712
if (SFdirs[SFdirPtr + i].changed) {
1713
SFdirs[SFdirPtr + i].changed = 0;
1714
SFdrawList(i, SF_DO_SCROLL);
1715
}
1716
} else {
1717
SFclearList(i, SF_DO_SCROLL);
1718
}
1719
}
1720
}
1721
}
1722
1723
1724
/* ARGSUSED */
1725
static void
1726
SFbuttonPressList(Widget w, int n, XButtonPressedEvent *event)
1727
{
1728
SFbuttonPressed = 1;
1729
}
1730
1731
/* ARGSUSED */
1732
static void
1733
SFbuttonReleaseList(Widget w, int n, XButtonReleasedEvent *event)
1734
{
1735
SFDir *dir;
1736
1737
SFbuttonPressed = 0;
1738
1739
if (SFcurrentInvert[n] != -1) {
1740
if (n < 2) {
1741
SFdoNotTouchDirPtr = 1;
1742
}
1743
SFdoNotTouchVorigin = 1;
1744
dir = &(SFdirs[SFdirPtr + n]);
1745
SFreplaceText(
1746
dir,
1747
dir->entries[dir->vOrigin + SFcurrentInvert[n]].shown
1748
);
1749
SFmotionList(w, n, (XMotionEvent *)event);
1750
}
1751
}
1752
1753
static int
1754
SFcheckDir(int n, SFDir *dir)
1755
{
1756
struct stat statBuf;
1757
int i;
1758
1759
if (
1760
(!stat(".", &statBuf)) &&
1761
(statBuf.st_mtime != dir->mtime)
1762
) {
1763
1764
/*
1765
* If the pointer is currently in the window that we are about
1766
* to update, we must warp it to prevent the user from
1767
* accidentally selecting the wrong file.
1768
*/
1769
if (SFcurrentInvert[n] != -1) {
1770
XWarpPointer(
1771
SFdisplay,
1772
None,
1773
XtWindow(selFileLists[n]),
1774
0,
1775
0,
1776
0,
1777
0,
1778
0,
1779
0
1780
);
1781
}
1782
1783
for (i = dir->nEntries - 1; i >= 0; i--) {
1784
if (dir->entries[i].shown != dir->entries[i].real) {
1785
XtFree(dir->entries[i].shown);
1786
}
1787
XtFree(dir->entries[i].real);
1788
}
1789
XtFree((char *) dir->entries);
1790
if (SFgetDir(dir)) {
1791
SFunreadableDir(dir);
1792
}
1793
if (dir->vOrigin > dir->nEntries - SFlistSize) {
1794
dir->vOrigin = dir->nEntries - SFlistSize;
1795
}
1796
if (dir->vOrigin < 0) {
1797
dir->vOrigin = 0;
1798
}
1799
if (dir->hOrigin > dir->nChars - SFcharsPerEntry) {
1800
dir->hOrigin = dir->nChars - SFcharsPerEntry;
1801
}
1802
if (dir->hOrigin < 0) {
1803
dir->hOrigin = 0;
1804
}
1805
dir->beginSelection = -1;
1806
dir->endSelection = -1;
1807
SFdoNotTouchVorigin = 1;
1808
if ((dir + 1)->dir) {
1809
(void) SFfindFile(dir, (dir + 1)->dir);
1810
} else {
1811
(void) SFfindFile(dir, dir->path);
1812
}
1813
1814
if (!SFworkProcAdded) {
1815
(void) XtAppAddWorkProc(SFapp, SFworkProc, NULL);
1816
SFworkProcAdded = 1;
1817
}
1818
1819
return 1;
1820
}
1821
1822
return 0;
1823
}
1824
1825
static int
1826
SFcheckFiles(SFDir *dir)
1827
{
1828
int from, to;
1829
int result;
1830
char old, new;
1831
int i;
1832
char *str;
1833
int last;
1834
struct stat statBuf;
1835
1836
result = 0;
1837
1838
from = dir->vOrigin;
1839
to = dir->vOrigin + SFlistSize;
1840
if (to > dir->nEntries) {
1841
to = dir->nEntries;
1842
}
1843
1844
for (i = from; i < to; i++) {
1845
str = dir->entries[i].real;
1846
last = strlen(str) - 1;
1847
old = str[last];
1848
str[last] = 0;
1849
if (stat(str, &statBuf)) {
1850
new = ' ';
1851
} else {
1852
new = SFstatChar(&statBuf);
1853
}
1854
str[last] = new;
1855
if (new != old) {
1856
result = 1;
1857
}
1858
}
1859
1860
return result;
1861
}
1862
1863
static void
1864
SFdirModTimer(XtPointer cl, XtIntervalId *id)
1865
{
1866
static int n = -1;
1867
static int f = 0;
1868
char save;
1869
SFDir *dir;
1870
1871
if ((!SFtwiddle) && (SFdirPtr < SFdirEnd)) {
1872
n++;
1873
if ((n > 2) || (SFdirPtr + n >= SFdirEnd)) {
1874
n = 0;
1875
f++;
1876
if ((f > 2) || (SFdirPtr + f >= SFdirEnd)) {
1877
f = 0;
1878
}
1879
}
1880
dir = &(SFdirs[SFdirPtr + n]);
1881
save = *(dir->path);
1882
*(dir->path) = 0;
1883
if (SFchdir(SFcurrentPath)) {
1884
*(dir->path) = save;
1885
1886
/*
1887
* force a re-read
1888
*/
1889
*(dir->dir) = 0;
1890
1891
SFupdatePath();
1892
} else {
1893
*(dir->path) = save;
1894
if (
1895
SFcheckDir(n, dir) ||
1896
((f == n) && SFcheckFiles(dir))
1897
) {
1898
SFdrawList(n, SF_DO_SCROLL);
1899
}
1900
}
1901
}
1902
1903
SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
1904
SFdirModTimer, (XtPointer) NULL);
1905
}
1906
1907
/* Return a single character describing what kind of file STATBUF is. */
1908
1909
static char
1910
SFstatChar (struct stat *statBuf)
1911
{
1912
if (S_ISDIR (statBuf->st_mode)) {
1913
return '/';
1914
} else if (S_ISREG (statBuf->st_mode)) {
1915
return S_ISXXX (statBuf->st_mode) ? '*' : ' ';
1916
#ifdef S_ISSOCK
1917
} else if (S_ISSOCK (statBuf->st_mode)) {
1918
return '=';
1919
#endif /* S_ISSOCK */
1920
} else {
1921
return ' ';
1922
}
1923
}
1924
1925
/* ARGSUSED */
1926
static void
1927
SFexposeList(Widget w, XtPointer n, XEvent *event, Boolean *cont)
1928
{
1929
if ((event->type == NoExpose) || event->xexpose.count) {
1930
return;
1931
}
1932
1933
SFdrawList((ULong)n, SF_DO_NOT_SCROLL);
1934
}
1935
1936
/* ARGSUSED */
1937
static void
1938
SFmodVerifyCallback(Widget w, XtPointer client_data, XEvent *event, Boolean *cont)
1939
{
1940
char buf[2];
1941
1942
if (
1943
(XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) &&
1944
((*buf) == '\r')
1945
) {
1946
SFstatus = SEL_FILE_OK;
1947
} else {
1948
SFstatus = SEL_FILE_TEXT;
1949
}
1950
}
1951
1952
/* ARGSUSED */
1953
static void
1954
SFokCallback(Widget w, XtPointer cl, XtPointer cd)
1955
{
1956
SFstatus = SEL_FILE_OK;
1957
}
1958
1959
static XtCallbackRec SFokSelect[] = {
1960
{ SFokCallback, (XtPointer) NULL },
1961
{ NULL, (XtPointer) NULL },
1962
};
1963
1964
/* ARGSUSED */
1965
static void
1966
SFcancelCallback(Widget w, XtPointer cl, XtPointer cd)
1967
{
1968
SFstatus = SEL_FILE_CANCEL;
1969
}
1970
1971
static XtCallbackRec SFcancelSelect[] = {
1972
{ SFcancelCallback, (XtPointer) NULL },
1973
{ NULL, (XtPointer) NULL },
1974
};
1975
1976
static void
1977
SFhomeCallback(Widget w, XtPointer cl, XtPointer cd)
1978
{
1979
SFsetText("~/");
1980
SFtextChanged();
1981
}
1982
1983
static XtCallbackRec SFhomeSelect[] = {
1984
{ SFhomeCallback, (XtPointer) NULL },
1985
{ NULL, (XtPointer) NULL },
1986
};
1987
1988
/* ARGSUSED */
1989
static void
1990
SFdismissAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
1991
{
1992
if (event->type == ClientMessage &&
1993
event->xclient.data.l[0] != SFwmDeleteWindow) return;
1994
1995
SFstatus = SEL_FILE_CANCEL;
1996
}
1997
1998
static XtActionsRec actions[] = {
1999
{"SelFileDismiss", SFdismissAction},
2000
};
2001
2002
/****************************************************************************
2003
**
2004
*F SFpositionWidget( <w> ) . . . . . . . . position widget under the cursor
2005
*/
2006
static void SFpositionWidget(Widget w)
2007
{
2008
Dimension width, height, b_width;
2009
Int dummyx, dummyy;
2010
Int x, y, max_x, max_y;
2011
UInt dummymask;
2012
Window root, child;
2013
2014
/* find out where the pointer is */
2015
XQueryPointer( XtDisplay(w), XtWindow(w), &root, &child, &x, &y,
2016
&dummyx, &dummyy, &dummymask );
2017
2018
/* get the dimensions of the widget */
2019
XtVaGetValues( w, XtNwidth, &width,
2020
XtNheight, &height,
2021
XtNborderWidth, &b_width,
2022
NULL );
2023
2024
/* calculate a nice position */
2025
width += 2 * b_width;
2026
height += 2 * b_width;
2027
x -= ( (Position) width/2 );
2028
y -= ( (Position) height/2 );
2029
2030
/* make sure that the widget lies within the screen boundaries */
2031
if ( x < 0 )
2032
x = 0;
2033
if ( x > (max_x = (Position) (XtScreen(w)->width - width)) )
2034
x = max_x;
2035
if (y < 0)
2036
y = 0;
2037
if ( y > (max_y = (Position) (XtScreen(w)->height - height)) )
2038
y = max_y;
2039
2040
/* set the x and y position in <w> */
2041
XtVaSetValues( w, XtNx, x, XtNy, y, NULL );
2042
}
2043
2044
2045
/****************************************************************************
2046
**
2047
*F SFtextChanged() . . . . . . . . . . . . . . . path text has been changed
2048
*/
2049
static void SFtextChanged()
2050
{
2051
if ( (SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~') )
2052
{
2053
(void) strcpy(SFcurrentPath, SFtextBuffer);
2054
SFtextPos = XawTextGetInsertionPoint(selFileField);
2055
}
2056
else
2057
{
2058
(void) strcat(strcpy(SFcurrentPath, SFstartDir), SFtextBuffer);
2059
SFtextPos = XawTextGetInsertionPoint(selFileField)
2060
+ strlen(SFstartDir);
2061
}
2062
2063
if (!SFworkProcAdded) {
2064
(void) XtAppAddWorkProc(SFapp, SFworkProc, NULL);
2065
SFworkProcAdded = 1;
2066
}
2067
SFupdatePath();
2068
}
2069
2070
2071
/****************************************************************************
2072
**
2073
*F SFcreateWidgets( <toplevel> ) . . . . . . . create file selector widgets
2074
*/
2075
static char *wmDeleteWindowTranslation =
2076
"<Message>WM_PROTOCOLS: SelFileDismiss()\n";
2077
2078
static void SFcreateWidgets ( Widget toplevel )
2079
{
2080
Long n;
2081
Int listWidth, listHeight;
2082
Int listSpacing = 10;
2083
Int scrollThickness = 15;
2084
Int hScrollX, hScrollY;
2085
Int vScrollX, vScrollY;
2086
Cursor xtermCursor;
2087
Cursor sbRightArrowCursor;
2088
Cursor dotCursor;
2089
2090
/* create a new toplevel shell */
2091
selFile = XtVaAppCreateShell(
2092
"XGap", "FileSelector",
2093
transientShellWidgetClass, SFdisplay,
2094
XtNtransientFor, (XtArgVal)toplevel,
2095
(String)NULL );
2096
2097
/* Add WM_DELETE_WINDOW protocol */
2098
XtAppAddActions( XtWidgetToApplicationContext(selFile),
2099
actions, XtNumber(actions) );
2100
XtOverrideTranslations( selFile,
2101
XtParseTranslationTable(wmDeleteWindowTranslation) );
2102
2103
/* create the file selector components */
2104
selFileForm = XtVaCreateManagedWidget(
2105
"selFileForm", formWidgetClass, selFile,
2106
XtNdefaultDistance, (XtArgVal)30,
2107
(String)NULL);
2108
2109
selFilePrompt = XtVaCreateManagedWidget(
2110
"selFilePrompt", labelWidgetClass, selFileForm,
2111
XtNlabel, (XtArgVal)"Enter a Filename",
2112
XtNresizable, (XtArgVal)True,
2113
XtNtop, (XtArgVal)XtChainTop,
2114
XtNbottom, (XtArgVal)XtChainTop,
2115
XtNleft, (XtArgVal)XtChainLeft,
2116
XtNright, (XtArgVal)XtChainLeft,
2117
XtNborderWidth, (XtArgVal)0,
2118
(String)NULL );
2119
XtVaGetValues( selFilePrompt,
2120
XtNforeground, (XtArgVal)&SFfore,
2121
XtNbackground, (XtArgVal)&SFback,
2122
(String)NULL );
2123
2124
/* initialize fonts */
2125
SFinitFont();
2126
2127
/* compute positions */
2128
SFentryWidth = 2*SFbesideText + SFcharsPerEntry*SFcharWidth;
2129
SFentryHeight = 2*SFaboveAndBelowText + SFcharHeight;
2130
2131
listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1
2132
+ scrollThickness;
2133
listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1
2134
+ SFlineToTextV + SFlistSize * SFentryHeight
2135
+ SFlineToTextV + 1 + scrollThickness;
2136
2137
SFpathScrollWidth = 3 * listWidth + 2 * listSpacing + 4;
2138
2139
hScrollX = -1;
2140
hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1
2141
+ SFlineToTextV + SFlistSize * SFentryHeight
2142
+ SFlineToTextV;
2143
SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;
2144
2145
vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
2146
vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
2147
SFvScrollHeight = 2*SFlineToTextV + SFlistSize * SFentryHeight;
2148
2149
SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
2150
SFlowerY = 2*SFlineToTextV + SFentryHeight + SFlineToTextV + 1;
2151
SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1
2152
+ SFlineToTextV + SFlistSize * SFentryHeight - 1;
2153
2154
SFtextX = SFlineToTextH + SFbesideText;
2155
SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;
2156
2157
SFsegs[0].x1 = 0;
2158
SFsegs[0].y1 = vScrollY;
2159
SFsegs[0].x2 = vScrollX - 1;
2160
SFsegs[0].y2 = vScrollY;
2161
SFsegs[1].x1 = vScrollX;
2162
SFsegs[1].y1 = 0;
2163
SFsegs[1].x2 = vScrollX;
2164
SFsegs[1].y2 = vScrollY - 1;
2165
2166
SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
2167
SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
2168
SFlineToTextH + SFentryWidth - 1;
2169
2170
/* create more widgets */
2171
selFileField = XtVaCreateManagedWidget(
2172
"selFileField", asciiTextWidgetClass, selFileForm,
2173
XtNwidth, (XtArgVal)3*listWidth+2*listSpacing+4,
2174
XtNborderColor, (XtArgVal)SFfore,
2175
XtNfromVert, (XtArgVal)selFilePrompt,
2176
XtNvertDistance, (XtArgVal)10,
2177
XtNresizable, (XtArgVal)True,
2178
XtNtop, (XtArgVal)XtChainTop,
2179
XtNbottom, (XtArgVal)XtChainTop,
2180
XtNleft, (XtArgVal)XtChainLeft,
2181
XtNright, (XtArgVal)XtChainLeft,
2182
XtNstring, (XtArgVal)SFtextBuffer,
2183
XtNlength, (XtArgVal)MAXPATHLEN,
2184
XtNeditType, (XtArgVal)XawtextEdit,
2185
XtNwrap, (XtArgVal)XawtextWrapWord,
2186
XtNresize, (XtArgVal)XawtextResizeHeight,
2187
XtNuseStringInPlace, (XtArgVal)True,
2188
(String)NULL );
2189
XtOverrideTranslations( selFileField,
2190
XtParseTranslationTable(oneLineTextEditTranslations) );
2191
XtSetKeyboardFocus(selFileForm, selFileField);
2192
2193
selFileHScroll = XtVaCreateManagedWidget(
2194
"selFileHScroll", scrollbarWidgetClass, selFileForm,
2195
XtNorientation, (XtArgVal)XtorientHorizontal,
2196
XtNwidth, (XtArgVal)SFpathScrollWidth,
2197
XtNheight, (XtArgVal)scrollThickness,
2198
XtNborderColor, (XtArgVal)SFfore,
2199
XtNfromVert, (XtArgVal)selFileField,
2200
XtNvertDistance, (XtArgVal)30,
2201
XtNtop, (XtArgVal)XtChainTop,
2202
XtNbottom, (XtArgVal)XtChainTop,
2203
XtNleft, (XtArgVal)XtChainLeft,
2204
XtNright, (XtArgVal)XtChainLeft,
2205
(String)NULL );
2206
XtAddCallback( selFileHScroll, XtNjumpProc,
2207
(XtCallbackProc)SFpathSliderMovedCallback, (XtPointer) NULL);
2208
XtAddCallback( selFileHScroll, XtNscrollProc,
2209
(XtCallbackProc)SFpathAreaSelectedCallback, (XtPointer) NULL);
2210
2211
selFileLists[0] = XtVaCreateManagedWidget(
2212
"selFileList1", compositeWidgetClass, selFileForm,
2213
XtNwidth, (XtArgVal)listWidth,
2214
XtNheight, (XtArgVal)listHeight,
2215
XtNborderColor, (XtArgVal)SFfore,
2216
XtNfromVert, (XtArgVal)selFileHScroll,
2217
XtNvertDistance, (XtArgVal)10,
2218
XtNtop, (XtArgVal)XtChainTop,
2219
XtNbottom, (XtArgVal)XtChainTop,
2220
XtNleft, (XtArgVal)XtChainLeft,
2221
XtNright, (XtArgVal)XtChainLeft,
2222
(String)NULL );
2223
2224
selFileLists[1] = XtVaCreateManagedWidget(
2225
"selFileList2", compositeWidgetClass, selFileForm,
2226
XtNwidth, (XtArgVal)listWidth,
2227
XtNheight, (XtArgVal)listHeight,
2228
XtNborderColor, (XtArgVal)SFfore,
2229
XtNfromHoriz, (XtArgVal)selFileLists[0],
2230
XtNfromVert, (XtArgVal)selFileHScroll,
2231
XtNhorizDistance, (XtArgVal)listSpacing,
2232
XtNvertDistance, (XtArgVal)10,
2233
XtNtop, (XtArgVal)XtChainTop,
2234
XtNbottom, (XtArgVal)XtChainTop,
2235
XtNleft, (XtArgVal)XtChainLeft,
2236
XtNright, (XtArgVal)XtChainLeft,
2237
(String)NULL );
2238
selFileLists[2] = XtVaCreateManagedWidget(
2239
"selFileList3", compositeWidgetClass, selFileForm,
2240
XtNwidth, (XtArgVal)listWidth,
2241
XtNheight, (XtArgVal)listHeight,
2242
XtNborderColor, (XtArgVal)SFfore,
2243
XtNfromHoriz, (XtArgVal)selFileLists[1],
2244
XtNfromVert, (XtArgVal)selFileHScroll,
2245
XtNhorizDistance, (XtArgVal)listSpacing,
2246
XtNvertDistance, (XtArgVal)10,
2247
XtNtop, (XtArgVal)XtChainTop,
2248
XtNbottom, (XtArgVal)XtChainTop,
2249
XtNleft, (XtArgVal)XtChainLeft,
2250
XtNright, (XtArgVal)XtChainLeft,
2251
(String)NULL );
2252
2253
for ( n = 0; n < 3; n++ )
2254
{
2255
selFileVScrolls[n] = XtVaCreateManagedWidget(
2256
"selFileVScroll", scrollbarWidgetClass, selFileLists[n],
2257
XtNx, (XtArgVal)vScrollX,
2258
XtNy, (XtArgVal)vScrollY,
2259
XtNwidth, (XtArgVal)scrollThickness,
2260
XtNheight, (XtArgVal)SFvScrollHeight,
2261
XtNborderColor, (XtArgVal)SFfore,
2262
(String)NULL );
2263
XtAddCallback( selFileVScrolls[n], XtNjumpProc,
2264
(XtCallbackProc)SFvFloatSliderMovedCallback, (XtPointer) n );
2265
XtAddCallback( selFileVScrolls[n], XtNscrollProc,
2266
(XtCallbackProc)SFvAreaSelectedCallback, (XtPointer) n );
2267
2268
selFileHScrolls[n] = XtVaCreateManagedWidget(
2269
"selFileHScroll", scrollbarWidgetClass, selFileLists[n],
2270
XtNorientation, (XtArgVal)XtorientHorizontal,
2271
XtNx, (XtArgVal)hScrollX,
2272
XtNy, (XtArgVal)hScrollY,
2273
XtNwidth, (XtArgVal)SFhScrollWidth,
2274
XtNheight, (XtArgVal)scrollThickness,
2275
XtNborderColor, (XtArgVal)SFfore,
2276
(String)NULL );
2277
XtAddCallback( selFileHScrolls[n], XtNjumpProc,
2278
(XtCallbackProc)SFhSliderMovedCallback, (XtPointer) n );
2279
XtAddCallback( selFileHScrolls[n], XtNscrollProc,
2280
(XtCallbackProc)SFhAreaSelectedCallback, (XtPointer) n );
2281
}
2282
2283
selFileOK = XtVaCreateManagedWidget(
2284
"selFileOK", commandWidgetClass, selFileForm,
2285
XtNresizable, (XtArgVal)True,
2286
XtNcallback, (XtArgVal)SFokSelect,
2287
XtNborderColor, (XtArgVal)SFfore,
2288
XtNfromVert, (XtArgVal)(selFileLists[0]),
2289
XtNvertDistance, (XtArgVal)30,
2290
XtNtop, (XtArgVal)XtChainTop,
2291
XtNbottom, (XtArgVal)XtChainTop,
2292
XtNleft, (XtArgVal)XtChainLeft,
2293
XtNright, (XtArgVal)XtChainLeft,
2294
(String)NULL );
2295
selFileCancel = XtVaCreateManagedWidget(
2296
"selFileCancel", commandWidgetClass, selFileForm,
2297
XtNresizable, (XtArgVal)True,
2298
XtNcallback, (XtArgVal)SFcancelSelect,
2299
XtNborderColor, (XtArgVal)SFfore,
2300
XtNfromHoriz, (XtArgVal)selFileOK,
2301
XtNfromVert, (XtArgVal)selFileLists[0],
2302
XtNhorizDistance, (XtArgVal)30,
2303
XtNvertDistance, (XtArgVal)30,
2304
XtNtop, (XtArgVal)XtChainTop,
2305
XtNbottom, (XtArgVal)XtChainTop,
2306
XtNleft, (XtArgVal)XtChainLeft,
2307
XtNright, (XtArgVal)XtChainLeft,
2308
(String)NULL );
2309
selFileHome = XtVaCreateManagedWidget(
2310
"selFileHome", commandWidgetClass, selFileForm,
2311
XtNresizable, (XtArgVal)True,
2312
XtNcallback, (XtArgVal)SFhomeSelect,
2313
XtNborderColor, (XtArgVal)SFfore,
2314
XtNfromHoriz, (XtArgVal)selFileCancel,
2315
XtNfromVert, (XtArgVal)selFileLists[0],
2316
XtNhorizDistance, (XtArgVal)30,
2317
XtNvertDistance, (XtArgVal)30,
2318
XtNtop, (XtArgVal)XtChainTop,
2319
XtNbottom, (XtArgVal)XtChainTop,
2320
XtNleft, (XtArgVal)XtChainLeft,
2321
XtNright, (XtArgVal)XtChainLeft,
2322
(String)NULL );
2323
2324
/* realise toplevel */
2325
XtSetMappedWhenManaged( selFile, False );
2326
XtRealizeWidget(selFile);
2327
2328
/* Add WM_DELETE_WINDOW protocol */
2329
SFwmDeleteWindow = XInternAtom( SFdisplay, "WM_DELETE_WINDOW", False );
2330
XSetWMProtocols( SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1 );
2331
2332
/* create default graphic context */
2333
SFcreateGC();
2334
2335
/* create cursors */
2336
xtermCursor = XCreateFontCursor( SFdisplay, XC_xterm );
2337
sbRightArrowCursor = XCreateFontCursor( SFdisplay, XC_sb_right_arrow );
2338
dotCursor = XCreateFontCursor( SFdisplay, XC_dot );
2339
2340
XDefineCursor( SFdisplay, XtWindow(selFileOK), dotCursor );
2341
XDefineCursor( SFdisplay, XtWindow(selFileCancel), dotCursor );
2342
XDefineCursor( SFdisplay, XtWindow(selFileHome), dotCursor );
2343
XDefineCursor( SFdisplay, XtWindow(selFileForm), xtermCursor );
2344
XDefineCursor( SFdisplay, XtWindow(selFileField), xtermCursor );
2345
for (n = 0; n < 3; n++)
2346
XDefineCursor( SFdisplay, XtWindow(selFileLists[n]),
2347
sbRightArrowCursor);
2348
2349
/* set event handler */
2350
for ( n = 0; n < 3; n++ )
2351
{
2352
XtAddEventHandler( selFileLists[n], ExposureMask, True,
2353
(XtEventHandler)SFexposeList, (XtPointer) n );
2354
XtAddEventHandler( selFileLists[n], EnterWindowMask, False,
2355
(XtEventHandler)SFenterList, (XtPointer) n );
2356
XtAddEventHandler( selFileLists[n], LeaveWindowMask, False,
2357
(XtEventHandler)SFleaveList, (XtPointer) n );
2358
XtAddEventHandler( selFileLists[n], PointerMotionMask, False,
2359
(XtEventHandler)SFmotionList, (XtPointer) n );
2360
XtAddEventHandler( selFileLists[n], ButtonPressMask, False,
2361
(XtEventHandler)SFbuttonPressList, (XtPointer) n );
2362
XtAddEventHandler( selFileLists[n], ButtonReleaseMask, False,
2363
(XtEventHandler)SFbuttonReleaseList, (XtPointer) n );
2364
}
2365
XtAddEventHandler( selFileField, KeyPressMask, False,
2366
SFmodVerifyCallback, (XtPointer) NULL);
2367
SFapp = XtWidgetToApplicationContext(selFile);
2368
}
2369
2370
2371
/****************************************************************************
2372
**
2373
*F SFgetText() . . . . . . . . . . . . . . . . . . . . . copy user selection
2374
*/
2375
static String SFgetText ()
2376
{
2377
return strcpy( XtMalloc((strlen(SFtextBuffer)+1)), SFtextBuffer );
2378
}
2379
2380
2381
/****************************************************************************
2382
**
2383
*F SFprepareToReturn() . . . . . . . . . . remove grab, unmap file selector
2384
*/
2385
static void SFprepareToReturn ()
2386
{
2387
SFstatus = SEL_FILE_NULL;
2388
XtRemoveGrab(selFile);
2389
XtUnmapWidget(selFile);
2390
XtRemoveTimeOut(SFdirModTimerId);
2391
if ( SFchdir(SFstartDir) )
2392
XtAppWarning(SFapp,"XsraSelFile: can't return to current directory");
2393
}
2394
2395
2396
/****************************************************************************
2397
**
2398
*F XsraSelFile( <top>, <prompt>, <path>, <show>, <name> ) . . file selector
2399
*/
2400
Boolean XsraSelFile ( Widget toplevel, String prompt, String init_path,
2401
Int (*show_entry)( String, String*, struct stat* ), String *name_return )
2402
{
2403
XEvent event;
2404
2405
/* set nice prompt */
2406
if ( !prompt || !prompt[0] )
2407
prompt = "Enter Filename";
2408
2409
/* initialize widgets */
2410
if ( !SFdisplay )
2411
{
2412
SFdisplay = XtDisplay(toplevel);
2413
SFcreateWidgets(toplevel);
2414
}
2415
XtVaSetValues( selFilePrompt, XtNlabel, (XtArgVal)prompt, (String)NULL );
2416
2417
/* position widget under cursor */
2418
SFpositionWidget(selFile);
2419
XtMapWidget(selFile);
2420
2421
/* get current directory */
2422
if ( !getcwd(SFstartDir, MAXPATHLEN) ) {
2423
*SFstartDir = 0;
2424
XtAppWarning( SFapp, "XsraSelFile: can't get current directory" );
2425
}
2426
(void) strcat(SFstartDir, "/");
2427
(void) strcpy(SFcurrentDir, SFstartDir);
2428
2429
/* set init path */
2430
if (init_path)
2431
{
2432
if (init_path[0] == '/')
2433
{
2434
strcpy(SFcurrentPath, init_path);
2435
if ( strncmp( SFcurrentPath, SFstartDir, strlen(SFstartDir) ))
2436
SFsetText(SFcurrentPath);
2437
else
2438
SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
2439
}
2440
else
2441
{
2442
strcat( strcpy( SFcurrentPath, SFstartDir ), init_path );
2443
SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
2444
}
2445
}
2446
else
2447
(void) strcpy(SFcurrentPath, SFstartDir);
2448
2449
/* function to filter entries */
2450
SFfunc = show_entry;
2451
2452
/* force redisplay */
2453
SFtextChanged();
2454
2455
/* grab input for modal widget */
2456
XtAddGrab(selFile, True, True);
2457
2458
/* set time out function */
2459
SFdirModTimerId = XtAppAddTimeOut( SFapp, (unsigned long) 1000,
2460
SFdirModTimer, (XtPointer) 0 );
2461
2462
/* loop until user selects OK or CANCEL */
2463
while (1)
2464
{
2465
XtAppNextEvent( SFapp, &event );
2466
XtDispatchEvent(&event);
2467
switch (SFstatus)
2468
{
2469
case SEL_FILE_TEXT:
2470
SFstatus = SEL_FILE_NULL;
2471
SFtextChanged();
2472
break;
2473
case SEL_FILE_OK:
2474
*name_return = SFgetText();
2475
SFprepareToReturn();
2476
return True;
2477
case SEL_FILE_CANCEL:
2478
SFprepareToReturn();
2479
return False;
2480
case SEL_FILE_NULL:
2481
break;
2482
}
2483
}
2484
}
2485
2486
#endif
2487
2488
2489
/****************************************************************************
2490
**
2491
2492
*E selfile.h . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here
2493
*/
2494
2495