2 * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
4 * Permission to use, copy, modify, and distribute this software and its
5 * documentation for any purpose and without fee is hereby granted, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Software Research Associates not be used
9 * in advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. Software Research Associates
11 * makes no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
14 * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
16 * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
17 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
18 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
19 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
22 * Author: Erik M. van der Poel
23 * Software Research Associates, Inc., Tokyo, Japan
30 #include <X11/StringDefs.h>
31 #include <X11/Xaw/Scrollbar.h>
32 #include <X11/Xaw/Cardinals.h>
34 #define SF_DEFAULT_FONT "9x15"
39 #define ABS(x) (((x) < 0) ? (-(x)) : (x))
41 /* added missing prototypes */
42 extern char SFstatChar(struct stat*);
43 extern int SFchdir(char *);
44 void SFvSliderMovedCallback(Widget, int, int);
50 int SFcharWidth, SFcharAscent, SFcharHeight;
52 int SFcurrentInvert[3] = { -1, -1, -1 };
54 static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC;
56 static XtResource textResources[] = {
57 {XtNfont, XtCFont, XtRString, sizeof (char *),
58 XtOffset(textPtr, fontname), XtRString, SF_DEFAULT_FONT},
61 static XFontStruct *SFfont;
63 static int SFcurrentListY;
65 static XtIntervalId SFscrollTimerId;
72 data = XtNew(TextData);
74 XtGetApplicationResources(selFileForm, (XtPointer) data, textResources,
75 XtNumber(textResources), (Arg *) NULL, ZERO);
77 SFfont = XLoadQueryFont(SFdisplay, data->fontname);
79 SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT);
83 (void) sprintf(sbuf, "XsraSelFile: can't get font %s",
86 XtAppError(SFapp, sbuf);
90 SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2;
91 SFcharAscent = SFfont->max_bounds.ascent;
92 SFcharHeight = SFcharAscent + SFfont->max_bounds.descent;
100 XRectangle rectangles[1];
102 gcValues.foreground = SFfore;
112 SFscrollGC = XtGetGC(
119 gcValues.function = GXinvert;
120 gcValues.plane_mask = (SFfore ^ SFback);
122 SFinvertGC = XtGetGC(
131 gcValues.foreground = SFfore;
132 gcValues.background = SFback;
133 gcValues.font = SFfont->fid;
135 SFtextGC = XCreateGC(
137 XtWindow(selFileLists[0]),
146 rectangles[0].x = SFlineToTextH + SFbesideText;
148 rectangles[0].width = SFcharsPerEntry * SFcharWidth;
149 rectangles[0].height = SFupperY + 1;
164 SFclearList(n, doScroll)
170 SFcurrentInvert[n] = -1;
172 XClearWindow(SFdisplay, XtWindow(selFileLists[n]));
174 XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs,
178 dir = &(SFdirs[SFdirPtr + n]);
180 if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars) {
181 XawScrollbarSetThumb(
183 (float) (((double) dir->vOrigin) /
185 (float) (((double) ((dir->nEntries < SFlistSize)
186 ? dir->nEntries : SFlistSize)) /
190 XawScrollbarSetThumb(
192 (float) (((double) dir->hOrigin) / dir->nChars),
193 (float) (((double) ((dir->nChars <
194 SFcharsPerEntry) ? dir->nChars :
195 SFcharsPerEntry)) / dir->nChars)
198 XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
200 XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
208 SFdeleteEntry(dir, entry)
213 register SFEntry *end;
217 idx = entry - dir->entries;
219 if (idx < dir->beginSelection) {
220 dir->beginSelection--;
222 if (idx <= dir->endSelection) {
225 if (dir->beginSelection > dir->endSelection) {
226 dir->beginSelection = dir->endSelection = -1;
229 if (idx < dir->vOrigin) {
235 end = &(dir->entries[dir->nEntries - 1]);
237 for (e = entry; e < end; e++) {
241 if (!(--dir->nEntries)) {
245 n = dir - &(SFdirs[SFdirPtr]);
246 if ((n < 0) || (n > 2)) {
250 XawScrollbarSetThumb(
252 (float) (((double) dir->vOrigin) / dir->nEntries),
253 (float) (((double) ((dir->nEntries < SFlistSize) ?
254 dir->nEntries : SFlistSize)) / dir->nEntries)
260 SFwriteStatChar(name, last, statBuf)
263 struct stat *statBuf;
265 name[last] = SFstatChar(statBuf);
270 SFstatAndCheck(dir, entry)
279 * must be restored before returning
284 if (!SFchdir(SFcurrentPath)) {
285 last = strlen(entry->real) - 1;
286 entry->real[last] = 0;
289 (!stat(entry->real, &statBuf))
293 || (!lstat(entry->real, &statBuf))
295 #endif /* ndef S_IFLNK */
302 if (SFfunc(entry->real, &shown, &statBuf)) {
307 entry->shown = XtMalloc(
310 (void) strcpy(entry->shown,
317 entry->shown[len + 1] = 0;
320 SFdeleteEntry(dir, entry);
326 SFwriteStatChar(entry->real, last, &statBuf);
328 entry->real[last] = ' ';
337 SFdrawStrings(w, dir, from, to)
344 register SFEntry *entry;
347 x = SFtextX - dir->hOrigin * SFcharWidth;
349 if (dir->vOrigin + to >= dir->nEntries) {
350 to = dir->nEntries - dir->vOrigin - 1;
352 for (i = from; i <= to; i++) {
353 entry = &(dir->entries[dir->vOrigin + i]);
354 if (!(entry->statDone)) {
355 if (SFstatAndCheck(dir, entry)) {
356 if (dir->vOrigin + to >= dir->nEntries) {
357 to = dir->nEntries - dir->vOrigin - 1;
368 SFtextYoffset + i * SFentryHeight,
372 if (dir->vOrigin + i == dir->beginSelection) {
378 SFlowerY + i * SFentryHeight,
379 SFlineToTextH + SFentryWidth - 2,
380 SFlowerY + i * SFentryHeight
384 (dir->vOrigin + i >= dir->beginSelection) &&
385 (dir->vOrigin + i <= dir->endSelection)
387 SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
388 SFlowerY + i * SFentryHeight;
389 SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
390 SFlowerY + (i + 1) * SFentryHeight - 1;
399 if (dir->vOrigin + i == dir->endSelection) {
405 SFlowerY + (i + 1) * SFentryHeight - 1,
406 SFlineToTextH + SFentryWidth - 2,
407 SFlowerY + (i + 1) * SFentryHeight - 1
415 SFdrawList(n, doScroll)
422 SFclearList(n, doScroll);
424 if (SFdirPtr + (3-NR) + n < SFdirEnd) {
425 dir = &(SFdirs[SFdirPtr + n + (3-NR)]);
426 w = XtWindow(selFileLists[n]);
431 SFtextX - dir->hOrigin * SFcharWidth,
432 SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
436 SFdrawStrings(w, dir, 0, SFlistSize - 1);
442 SFdrawLists(doScroll)
447 for (i = 0; i < NR; i++) {
448 SFdrawList(i, doScroll);
459 XtWindow(selFileLists[n]),
462 SFcurrentInvert[n] * SFentryHeight + SFlowerY,
470 SFscrollTimerInterval()
472 static int maxVal = 200;
473 static int varyDist = 50;
474 static int minDist = 50;
478 if (SFcurrentListY < SFlowerY) {
479 dist = SFlowerY - SFcurrentListY;
480 } else if (SFcurrentListY > SFupperY) {
481 dist = SFcurrentListY - SFupperY;
483 return (unsigned long) 1;
486 t = maxVal - ((maxVal / varyDist) * (dist - minDist));
496 return (unsigned long) t;
508 n = (int)(intptr_t) p;
510 dir = &(SFdirs[SFdirPtr + n]);
513 if (SFcurrentListY < SFlowerY) {
514 if (dir->vOrigin > 0) {
515 SFvSliderMovedCallback(selFileVScrolls[n], n,
518 } else if (SFcurrentListY > SFupperY) {
519 if (dir->vOrigin < dir->nEntries - SFlistSize) {
520 SFvSliderMovedCallback(selFileVScrolls[n], n,
525 if (dir->vOrigin != save) {
527 XawScrollbarSetThumb(
529 (float) (((double) dir->vOrigin) / dir->nEntries),
530 (float) (((double) ((dir->nEntries < SFlistSize) ?
531 dir->nEntries : SFlistSize)) / dir->nEntries)
536 if (SFbuttonPressed) {
537 SFscrollTimerId = XtAppAddTimeOut(SFapp,
538 SFscrollTimerInterval(), SFscrollTimer, (XtPointer)(intptr_t) n);
543 SFnewInvertEntry(n, event)
545 register XMotionEvent *event;
549 static int SFscrollTimerAdded = 0;
554 if (SFdirPtr + n >= SFdirEnd) {
557 (x >= 0) && (x <= SFupperX) &&
558 (y >= SFlowerY) && (y <= SFupperY)
560 register SFDir *dir = &(SFdirs[SFdirPtr + n]);
562 if (SFscrollTimerAdded) {
563 SFscrollTimerAdded = 0;
564 XtRemoveTimeOut(SFscrollTimerId);
567 new = (y - SFlowerY) / SFentryHeight;
568 if (dir->vOrigin + new >= dir->nEntries) {
573 if (SFbuttonPressed) {
575 if (!SFscrollTimerAdded) {
576 SFscrollTimerAdded = 1;
577 SFscrollTimerId = XtAppAddTimeOut(SFapp,
578 SFscrollTimerInterval(), SFscrollTimer,
579 (XtPointer)(intptr_t) n);
589 SFenterList(w, n, event)
592 register XEnterWindowEvent *event;
597 if (SFcurrentInvert[n] != -1) {
599 SFcurrentInvert[n] = -1;
602 new = SFnewInvertEntry(n, (XMotionEvent *) event);
604 SFcurrentInvert[n] = new;
611 SFleaveList(w, n, event)
616 if (SFcurrentInvert[n] != -1) {
618 SFcurrentInvert[n] = -1;
624 SFmotionList(w, n, event)
627 register XMotionEvent *event;
631 new = SFnewInvertEntry(n, event);
633 if (new != SFcurrentInvert[n]) {
634 if (SFcurrentInvert[n] != -1) {
637 SFcurrentInvert[n] = new;
647 SFvSliderMovedCallback(w, n, new)
656 dir = &(SFdirs[SFdirPtr + n]);
665 win = XtWindow(selFileLists[n]);
667 if (ABS(new - old) < SFlistSize) {
675 SFlowerY + (new - old) * SFentryHeight,
676 SFentryWidth + SFlineToTextH,
677 (SFlistSize - (new - old)) * SFentryHeight,
685 SFlowerY + (SFlistSize - (new - old)) *
687 SFentryWidth + SFlineToTextH,
688 (new - old) * SFentryHeight,
691 SFdrawStrings(win, dir, SFlistSize - (new - old),
701 SFentryWidth + SFlineToTextH,
702 (SFlistSize - (old - new)) * SFentryHeight,
704 SFlowerY + (old - new) * SFentryHeight
711 SFentryWidth + SFlineToTextH,
712 (old - new) * SFentryHeight,
715 SFdrawStrings(win, dir, 0, old - new);
723 SFentryWidth + SFlineToTextH,
724 SFlistSize * SFentryHeight,
727 SFdrawStrings(win, dir, 0, SFlistSize - 1);
733 SFvFloatSliderMovedCallback(w, n, fnew)
740 new = (*fnew) * SFdirs[SFdirPtr + n].nEntries;
742 SFvSliderMovedCallback(w, n, new);
748 SFvAreaSelectedCallback(w, n, pnew)
756 dir = &(SFdirs[SFdirPtr + n]);
759 (((double) pnew) / SFvScrollHeight) * dir->nEntries;
761 if (new > dir->nEntries - SFlistSize) {
762 new = dir->nEntries - SFlistSize;
772 f = ((double) new) / dir->nEntries;
774 XawScrollbarSetThumb(
777 (float) (((double) ((dir->nEntries < SFlistSize) ?
778 dir->nEntries : SFlistSize)) / dir->nEntries)
782 SFvSliderMovedCallback(w, n, new);
787 SFhSliderMovedCallback(w, n, new)
795 dir = &(SFdirs[SFdirPtr + n]);
797 dir->hOrigin = (*new) * dir->nChars;
798 if (dir->hOrigin == save) {
802 SFdrawList(n, SF_DO_NOT_SCROLL);
807 SFhAreaSelectedCallback(w, n, pnew)
815 dir = &(SFdirs[SFdirPtr + n]);
818 (((double) pnew) / SFhScrollWidth) * dir->nChars;
820 if (new > dir->nChars - SFcharsPerEntry) {
821 new = dir->nChars - SFcharsPerEntry;
831 f = ((double) new) / dir->nChars;
833 XawScrollbarSetThumb(
836 (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
837 dir->nChars : SFcharsPerEntry)) / dir->nChars)
840 SFhSliderMovedCallback(w, n, &f);
846 SFpathSliderMovedCallback(w, client_data, new)
848 XtPointer client_data;
856 SFdirPtrSave = SFdirPtr;
857 SFdirPtr = (*new) * SFdirEnd;
858 if (SFdirPtr == SFdirPtrSave) {
862 SFdrawLists(SF_DO_SCROLL);
865 while (SFdirPtr + n >= SFdirEnd) {
869 dir = &(SFdirs[SFdirPtr + n]);
871 pos = dir->path - SFcurrentPath;
873 if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
874 pos -= strlen(SFstartDir);
880 XawTextSetInsertionPoint(selFileField, pos);
886 SFpathAreaSelectedCallback(w, client_data, pnew)
888 XtPointer client_data;
894 new = SFdirPtr + (((double) pnew) / SFpathScrollWidth) * SFdirEnd;
896 if (new > SFdirEnd - 3) {
904 f = ((double) new) / SFdirEnd;
906 XawScrollbarSetThumb(
909 (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
913 SFpathSliderMovedCallback(w, (XtPointer) NULL, &f);
920 register SFEntry *entry;
922 for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) {
923 if (!(dir->nEntries)) {
927 entry = &(dir->entries[dir->nEntries - 1]);
928 entry >= dir->entries;
931 if (!(entry->statDone)) {
932 (void) SFstatAndCheck(dir, entry);