5
* Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
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.
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.
25
* Author: Erik M. van der Poel
26
* Software Research Associates, Inc., Tokyo, Japan
31
#include "SFinternal.h"
33
#include <X11/StringDefs.h>
34
#include <X11/Xaw/Scrollbar.h>
35
#include <X11/Xaw/Cardinals.h>
37
#define SF_DEFAULT_FONT "9x15"
42
#define ABS(x) (((x) < 0) ? (-(x)) : (x))
48
int SFcharWidth, SFcharAscent, SFcharHeight;
50
int SFcurrentInvert[3] = { -1, -1, -1 };
52
static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC;
54
static XtResource textResources[] = {
55
{XtNfont, XtCFont, XtRString, sizeof (char *),
56
XtOffset(textPtr, fontname), XtRString, SF_DEFAULT_FONT},
59
static XFontStruct *SFfont;
61
static int SFcurrentListY;
63
static XtIntervalId SFscrollTimerId;
69
data = XtNew(TextData);
71
XtGetApplicationResources(selFileForm, (XtPointer) data, textResources,
72
XtNumber(textResources), (Arg *) NULL, ZERO);
74
SFfont = XLoadQueryFont(SFdisplay, data->fontname);
76
SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT);
80
(void) sprintf(sbuf, "XsraSelFile: can't get font %s",
83
XtAppError(SFapp, sbuf);
87
SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2;
88
SFcharAscent = SFfont->max_bounds.ascent;
89
SFcharHeight = SFcharAscent + SFfont->max_bounds.descent;
95
XRectangle rectangles[1];
97
gcValues.foreground = SFfore;
107
SFscrollGC = XtGetGC(
114
gcValues.function = GXinvert;
115
gcValues.plane_mask = (SFfore ^ SFback);
117
SFinvertGC = XtGetGC(
126
gcValues.foreground = SFfore;
127
gcValues.background = SFback;
128
gcValues.font = SFfont->fid;
130
SFtextGC = XCreateGC(
132
XtWindow(selFileLists[0]),
141
rectangles[0].x = SFlineToTextH + SFbesideText;
143
rectangles[0].width = SFcharsPerEntry * SFcharWidth;
144
rectangles[0].height = SFupperY + 1;
157
void SFclearList(n, doScroll)
163
SFcurrentInvert[n] = -1;
165
XClearWindow(SFdisplay, XtWindow(selFileLists[n]));
167
XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs,
171
dir = &(SFdirs[SFdirPtr + n]);
173
if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars) {
174
XawScrollbarSetThumb(
176
(float) (((double) dir->vOrigin) /
178
(float) (((double) ((dir->nEntries < SFlistSize)
179
? dir->nEntries : SFlistSize)) /
183
XawScrollbarSetThumb(
185
(float) (((double) dir->hOrigin) / dir->nChars),
186
(float) (((double) ((dir->nChars <
187
SFcharsPerEntry) ? dir->nChars :
188
SFcharsPerEntry)) / dir->nChars)
191
XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
193
XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
200
SFdeleteEntry(dir, entry)
205
register SFEntry *end;
209
idx = entry - dir->entries;
211
if (idx < dir->beginSelection) {
212
dir->beginSelection--;
214
if (idx <= dir->endSelection) {
217
if (dir->beginSelection > dir->endSelection) {
218
dir->beginSelection = dir->endSelection = -1;
221
if (idx < dir->vOrigin) {
227
end = &(dir->entries[dir->nEntries - 1]);
229
for (e = entry; e < end; e++) {
233
if (!(--dir->nEntries)) {
237
n = dir - &(SFdirs[SFdirPtr]);
238
if ((n < 0) || (n > 2)) {
242
XawScrollbarSetThumb(
244
(float) (((double) dir->vOrigin) / dir->nEntries),
245
(float) (((double) ((dir->nEntries < SFlistSize) ?
246
dir->nEntries : SFlistSize)) / dir->nEntries)
251
SFwriteStatChar(name, last, statBuf)
254
struct stat *statBuf;
256
name[last] = SFstatChar(statBuf);
260
SFstatAndCheck(dir, entry)
269
* must be restored before returning
274
if (!SFchdir(SFcurrentPath)) {
275
last = strlen(entry->real) - 1;
276
entry->real[last] = 0;
279
(!stat(entry->real, &statBuf))
283
|| (!lstat(entry->real, &statBuf))
285
#endif /* ndef S_IFLNK */
292
if (SFfunc(entry->real, &shown, &statBuf)) {
297
entry->shown = XtMalloc(
300
(void) strcpy(entry->shown,
307
entry->shown[len + 1] = 0;
310
SFdeleteEntry(dir, entry);
316
SFwriteStatChar(entry->real, last, &statBuf);
318
entry->real[last] = ' ';
327
SFdrawStrings(w, dir, from, to)
334
register SFEntry *entry;
337
x = SFtextX - dir->hOrigin * SFcharWidth;
339
if (dir->vOrigin + to >= dir->nEntries) {
340
to = dir->nEntries - dir->vOrigin - 1;
342
for (i = from; i <= to; i++) {
343
entry = &(dir->entries[dir->vOrigin + i]);
344
if (!(entry->statDone)) {
345
if (SFstatAndCheck(dir, entry)) {
346
if (dir->vOrigin + to >= dir->nEntries) {
347
to = dir->nEntries - dir->vOrigin - 1;
358
SFtextYoffset + i * SFentryHeight,
362
if (dir->vOrigin + i == dir->beginSelection) {
368
SFlowerY + i * SFentryHeight,
369
SFlineToTextH + SFentryWidth - 2,
370
SFlowerY + i * SFentryHeight
374
(dir->vOrigin + i >= dir->beginSelection) &&
375
(dir->vOrigin + i <= dir->endSelection)
377
SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
378
SFlowerY + i * SFentryHeight;
379
SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
380
SFlowerY + (i + 1) * SFentryHeight - 1;
389
if (dir->vOrigin + i == dir->endSelection) {
395
SFlowerY + (i + 1) * SFentryHeight - 1,
396
SFlineToTextH + SFentryWidth - 2,
397
SFlowerY + (i + 1) * SFentryHeight - 1
403
void SFdrawList(n, doScroll)
410
SFclearList(n, doScroll);
412
if (SFdirPtr + n < SFdirEnd) {
413
dir = &(SFdirs[SFdirPtr + n]);
414
w = XtWindow(selFileLists[n]);
419
SFtextX - dir->hOrigin * SFcharWidth,
420
SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
424
SFdrawStrings(w, dir, 0, SFlistSize - 1);
428
void SFdrawLists(doScroll)
433
for (i = 0; i < 3; i++) {
434
SFdrawList(i, doScroll);
444
XtWindow(selFileLists[n]),
447
SFcurrentInvert[n] * SFentryHeight + SFlowerY,
454
SFscrollTimerInterval()
456
static int maxVal = 200;
457
static int varyDist = 50;
458
static int minDist = 50;
462
if (SFcurrentListY < SFlowerY) {
463
dist = SFlowerY - SFcurrentListY;
464
} else if (SFcurrentListY > SFupperY) {
465
dist = SFcurrentListY - SFupperY;
467
return (unsigned long) 1;
470
t = maxVal - ((maxVal / varyDist) * (dist - minDist));
480
return (unsigned long) t;
494
dir = &(SFdirs[SFdirPtr + n]);
497
if (SFcurrentListY < SFlowerY) {
498
if (dir->vOrigin > 0) {
499
SFvSliderMovedCallback(selFileVScrolls[n], n,
502
} else if (SFcurrentListY > SFupperY) {
503
if (dir->vOrigin < dir->nEntries - SFlistSize) {
504
SFvSliderMovedCallback(selFileVScrolls[n], n,
509
if (dir->vOrigin != save) {
511
XawScrollbarSetThumb(
513
(float) (((double) dir->vOrigin) / dir->nEntries),
514
(float) (((double) ((dir->nEntries < SFlistSize) ?
515
dir->nEntries : SFlistSize)) / dir->nEntries)
520
if (SFbuttonPressed) {
521
SFscrollTimerId = XtAppAddTimeOut(SFapp,
522
SFscrollTimerInterval(), SFscrollTimer, (XtPointer) n);
527
SFnewInvertEntry(n, event)
529
register XMotionEvent *event;
533
static int SFscrollTimerAdded = 0;
538
if (SFdirPtr + n >= SFdirEnd) {
541
(x >= 0) && (x <= SFupperX) &&
542
(y >= SFlowerY) && (y <= SFupperY)
544
register SFDir *dir = &(SFdirs[SFdirPtr + n]);
546
if (SFscrollTimerAdded) {
547
SFscrollTimerAdded = 0;
548
XtRemoveTimeOut(SFscrollTimerId);
551
new = (y - SFlowerY) / SFentryHeight;
552
if (dir->vOrigin + new >= dir->nEntries) {
557
if (SFbuttonPressed) {
559
if (!SFscrollTimerAdded) {
560
SFscrollTimerAdded = 1;
561
SFscrollTimerId = XtAppAddTimeOut(SFapp,
562
SFscrollTimerInterval(), SFscrollTimer,
573
SFenterList(w, n, event)
576
register XEnterWindowEvent *event;
581
if (SFcurrentInvert[n] != -1) {
583
SFcurrentInvert[n] = -1;
586
new = SFnewInvertEntry(n, (XMotionEvent *) event);
588
SFcurrentInvert[n] = new;
595
SFleaveList(w, n, event)
600
if (SFcurrentInvert[n] != -1) {
602
SFcurrentInvert[n] = -1;
608
SFmotionList(w, n, event)
611
register XMotionEvent *event;
615
new = SFnewInvertEntry(n, event);
617
if (new != SFcurrentInvert[n]) {
618
if (SFcurrentInvert[n] != -1) {
621
SFcurrentInvert[n] = new;
630
SFvFloatSliderMovedCallback(w, n, fnew)
637
new = (*fnew) * SFdirs[SFdirPtr + n].nEntries;
639
SFvSliderMovedCallback(w, n, new);
644
SFvSliderMovedCallback(w, n, new)
653
dir = &(SFdirs[SFdirPtr + n]);
662
win = XtWindow(selFileLists[n]);
664
if (ABS(new - old) < SFlistSize) {
672
SFlowerY + (new - old) * SFentryHeight,
673
SFentryWidth + SFlineToTextH,
674
(SFlistSize - (new - old)) * SFentryHeight,
682
SFlowerY + (SFlistSize - (new - old)) *
684
SFentryWidth + SFlineToTextH,
685
(new - old) * SFentryHeight,
688
SFdrawStrings(win, dir, SFlistSize - (new - old),
698
SFentryWidth + SFlineToTextH,
699
(SFlistSize - (old - new)) * SFentryHeight,
701
SFlowerY + (old - new) * SFentryHeight
708
SFentryWidth + SFlineToTextH,
709
(old - new) * SFentryHeight,
712
SFdrawStrings(win, dir, 0, old - new);
720
SFentryWidth + SFlineToTextH,
721
SFlistSize * SFentryHeight,
724
SFdrawStrings(win, dir, 0, SFlistSize - 1);
730
SFvAreaSelectedCallback(w, n, pnew)
738
dir = &(SFdirs[SFdirPtr + n]);
741
(((double) pnew) / SFvScrollHeight) * dir->nEntries;
743
if (new > dir->nEntries - SFlistSize) {
744
new = dir->nEntries - SFlistSize;
754
f = ((double) new) / dir->nEntries;
756
XawScrollbarSetThumb(
759
(float) (((double) ((dir->nEntries < SFlistSize) ?
760
dir->nEntries : SFlistSize)) / dir->nEntries)
764
SFvSliderMovedCallback(w, n, new);
769
SFhSliderMovedCallback(w, n, new)
777
dir = &(SFdirs[SFdirPtr + n]);
779
dir->hOrigin = (*new) * dir->nChars;
780
if (dir->hOrigin == save) {
784
SFdrawList(n, SF_DO_NOT_SCROLL);
789
SFhAreaSelectedCallback(w, n, pnew)
797
dir = &(SFdirs[SFdirPtr + n]);
800
(((double) pnew) / SFhScrollWidth) * dir->nChars;
802
if (new > dir->nChars - SFcharsPerEntry) {
803
new = dir->nChars - SFcharsPerEntry;
813
f = ((double) new) / dir->nChars;
815
XawScrollbarSetThumb(
818
(float) (((double) ((dir->nChars < SFcharsPerEntry) ?
819
dir->nChars : SFcharsPerEntry)) / dir->nChars)
822
SFhSliderMovedCallback(w, n, &f);
828
SFpathSliderMovedCallback(w, client_data, new)
830
XtPointer client_data;
838
SFdirPtrSave = SFdirPtr;
839
SFdirPtr = (*new) * SFdirEnd;
840
if (SFdirPtr == SFdirPtrSave) {
844
SFdrawLists(SF_DO_SCROLL);
847
while (SFdirPtr + n >= SFdirEnd) {
851
dir = &(SFdirs[SFdirPtr + n]);
853
pos = dir->path - SFcurrentPath;
855
if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
856
pos -= strlen(SFstartDir);
862
XawTextSetInsertionPoint(selFileField, pos);
868
SFpathAreaSelectedCallback(w, client_data, pnew)
870
XtPointer client_data;
876
new = SFdirPtr + (((double) pnew) / SFpathScrollWidth) * SFdirEnd;
878
if (new > SFdirEnd - 3) {
886
f = ((double) new) / SFdirEnd;
888
XawScrollbarSetThumb(
891
(float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
895
SFpathSliderMovedCallback(w, (XtPointer) NULL, &f);
902
register SFEntry *entry;
904
for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) {
905
if (!(dir->nEntries)) {
909
entry = &(dir->entries[dir->nEntries - 1]);
910
entry >= dir->entries;
913
if (!(entry->statDone)) {
914
(void) SFstatAndCheck(dir, entry);