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))
45 int SFcharWidth, SFcharAscent, SFcharHeight;
47 int SFcurrentInvert[3] = { -1, -1, -1 };
49 static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC;
51 static XtResource textResources[] = {
52 {XtNfont, XtCFont, XtRString, sizeof (char *),
53 XtOffset(textPtr, fontname), XtRString, SF_DEFAULT_FONT},
56 static XFontStruct *SFfont;
58 static int SFcurrentListY;
60 static XtIntervalId SFscrollTimerId;
67 data = XtNew(TextData);
69 XtGetApplicationResources(selFileForm, (XtPointer) data, textResources,
70 XtNumber(textResources), (Arg *) NULL, ZERO);
72 SFfont = XLoadQueryFont(SFdisplay, data->fontname);
74 SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT);
78 (void) sprintf(sbuf, "XsraSelFile: can't get font %s",
81 XtAppError(SFapp, sbuf);
85 SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2;
86 SFcharAscent = SFfont->max_bounds.ascent;
87 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;
159 SFclearList(n, doScroll)
165 SFcurrentInvert[n] = -1;
167 XClearWindow(SFdisplay, XtWindow(selFileLists[n]));
169 XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs,
173 dir = &(SFdirs[SFdirPtr + n]);
175 if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars) {
176 XawScrollbarSetThumb(
178 (float) (((double) dir->vOrigin) /
180 (float) (((double) ((dir->nEntries < SFlistSize)
181 ? dir->nEntries : SFlistSize)) /
185 XawScrollbarSetThumb(
187 (float) (((double) dir->hOrigin) / dir->nChars),
188 (float) (((double) ((dir->nChars <
189 SFcharsPerEntry) ? dir->nChars :
190 SFcharsPerEntry)) / dir->nChars)
193 XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
195 XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
203 SFdeleteEntry(dir, entry)
208 register SFEntry *end;
212 idx = entry - dir->entries;
214 if (idx < dir->beginSelection) {
215 dir->beginSelection--;
217 if (idx <= dir->endSelection) {
220 if (dir->beginSelection > dir->endSelection) {
221 dir->beginSelection = dir->endSelection = -1;
224 if (idx < dir->vOrigin) {
230 end = &(dir->entries[dir->nEntries - 1]);
232 for (e = entry; e < end; e++) {
236 if (!(--dir->nEntries)) {
240 n = dir - &(SFdirs[SFdirPtr]);
241 if ((n < 0) || (n > 2)) {
245 XawScrollbarSetThumb(
247 (float) (((double) dir->vOrigin) / dir->nEntries),
248 (float) (((double) ((dir->nEntries < SFlistSize) ?
249 dir->nEntries : SFlistSize)) / dir->nEntries)
255 SFwriteStatChar(name, last, statBuf)
258 struct stat *statBuf;
260 name[last] = SFstatChar(statBuf);
265 SFstatAndCheck(dir, entry)
274 * must be restored before returning
279 if (!SFchdir(SFcurrentPath)) {
280 last = strlen(entry->real) - 1;
281 entry->real[last] = 0;
284 (!stat(entry->real, &statBuf))
288 || (!lstat(entry->real, &statBuf))
290 #endif /* ndef S_IFLNK */
297 if (SFfunc(entry->real, &shown, &statBuf)) {
302 entry->shown = XtMalloc(
305 (void) strcpy(entry->shown,
312 entry->shown[len + 1] = 0;
315 SFdeleteEntry(dir, entry);
321 SFwriteStatChar(entry->real, last, &statBuf);
323 entry->real[last] = ' ';
332 SFdrawStrings(w, dir, from, to)
339 register SFEntry *entry;
342 x = SFtextX - dir->hOrigin * SFcharWidth;
344 if (dir->vOrigin + to >= dir->nEntries) {
345 to = dir->nEntries - dir->vOrigin - 1;
347 for (i = from; i <= to; i++) {
348 entry = &(dir->entries[dir->vOrigin + i]);
349 if (!(entry->statDone)) {
350 if (SFstatAndCheck(dir, entry)) {
351 if (dir->vOrigin + to >= dir->nEntries) {
352 to = dir->nEntries - dir->vOrigin - 1;
363 SFtextYoffset + i * SFentryHeight,
367 if (dir->vOrigin + i == dir->beginSelection) {
373 SFlowerY + i * SFentryHeight,
374 SFlineToTextH + SFentryWidth - 2,
375 SFlowerY + i * SFentryHeight
379 (dir->vOrigin + i >= dir->beginSelection) &&
380 (dir->vOrigin + i <= dir->endSelection)
382 SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
383 SFlowerY + i * SFentryHeight;
384 SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
385 SFlowerY + (i + 1) * SFentryHeight - 1;
394 if (dir->vOrigin + i == dir->endSelection) {
400 SFlowerY + (i + 1) * SFentryHeight - 1,
401 SFlineToTextH + SFentryWidth - 2,
402 SFlowerY + (i + 1) * SFentryHeight - 1
410 SFdrawList(n, doScroll)
417 SFclearList(n, doScroll);
419 if (SFdirPtr + (3-NR) + n < SFdirEnd) {
420 dir = &(SFdirs[SFdirPtr + n + (3-NR)]);
421 w = XtWindow(selFileLists[n]);
426 SFtextX - dir->hOrigin * SFcharWidth,
427 SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
431 SFdrawStrings(w, dir, 0, SFlistSize - 1);
437 SFdrawLists(doScroll)
442 for (i = 0; i < NR; i++) {
443 SFdrawList(i, doScroll);
454 XtWindow(selFileLists[n]),
457 SFcurrentInvert[n] * SFentryHeight + SFlowerY,
465 SFscrollTimerInterval()
467 static int maxVal = 200;
468 static int varyDist = 50;
469 static int minDist = 50;
473 if (SFcurrentListY < SFlowerY) {
474 dist = SFlowerY - SFcurrentListY;
475 } else if (SFcurrentListY > SFupperY) {
476 dist = SFcurrentListY - SFupperY;
478 return (unsigned long) 1;
481 t = maxVal - ((maxVal / varyDist) * (dist - minDist));
491 return (unsigned long) t;
505 dir = &(SFdirs[SFdirPtr + n]);
508 if (SFcurrentListY < SFlowerY) {
509 if (dir->vOrigin > 0) {
510 SFvSliderMovedCallback(selFileVScrolls[n], n,
513 } else if (SFcurrentListY > SFupperY) {
514 if (dir->vOrigin < dir->nEntries - SFlistSize) {
515 SFvSliderMovedCallback(selFileVScrolls[n], n,
520 if (dir->vOrigin != save) {
522 XawScrollbarSetThumb(
524 (float) (((double) dir->vOrigin) / dir->nEntries),
525 (float) (((double) ((dir->nEntries < SFlistSize) ?
526 dir->nEntries : SFlistSize)) / dir->nEntries)
531 if (SFbuttonPressed) {
532 SFscrollTimerId = XtAppAddTimeOut(SFapp,
533 SFscrollTimerInterval(), SFscrollTimer, (XtPointer) n);
538 SFnewInvertEntry(n, event)
540 register XMotionEvent *event;
544 static int SFscrollTimerAdded = 0;
549 if (SFdirPtr + n >= SFdirEnd) {
552 (x >= 0) && (x <= SFupperX) &&
553 (y >= SFlowerY) && (y <= SFupperY)
555 register SFDir *dir = &(SFdirs[SFdirPtr + n]);
557 if (SFscrollTimerAdded) {
558 SFscrollTimerAdded = 0;
559 XtRemoveTimeOut(SFscrollTimerId);
562 new = (y - SFlowerY) / SFentryHeight;
563 if (dir->vOrigin + new >= dir->nEntries) {
568 if (SFbuttonPressed) {
570 if (!SFscrollTimerAdded) {
571 SFscrollTimerAdded = 1;
572 SFscrollTimerId = XtAppAddTimeOut(SFapp,
573 SFscrollTimerInterval(), SFscrollTimer,
584 SFenterList(w, n, event)
587 register XEnterWindowEvent *event;
592 if (SFcurrentInvert[n] != -1) {
594 SFcurrentInvert[n] = -1;
597 new = SFnewInvertEntry(n, (XMotionEvent *) event);
599 SFcurrentInvert[n] = new;
606 SFleaveList(w, n, event)
611 if (SFcurrentInvert[n] != -1) {
613 SFcurrentInvert[n] = -1;
619 SFmotionList(w, n, event)
622 register XMotionEvent *event;
626 new = SFnewInvertEntry(n, event);
628 if (new != SFcurrentInvert[n]) {
629 if (SFcurrentInvert[n] != -1) {
632 SFcurrentInvert[n] = new;
642 SFvFloatSliderMovedCallback(w, n, fnew)
649 new = (*fnew) * SFdirs[SFdirPtr + n].nEntries;
651 SFvSliderMovedCallback(w, n, new);
656 SFvSliderMovedCallback(w, n, new)
665 dir = &(SFdirs[SFdirPtr + n]);
674 win = XtWindow(selFileLists[n]);
676 if (ABS(new - old) < SFlistSize) {
684 SFlowerY + (new - old) * SFentryHeight,
685 SFentryWidth + SFlineToTextH,
686 (SFlistSize - (new - old)) * SFentryHeight,
694 SFlowerY + (SFlistSize - (new - old)) *
696 SFentryWidth + SFlineToTextH,
697 (new - old) * SFentryHeight,
700 SFdrawStrings(win, dir, SFlistSize - (new - old),
710 SFentryWidth + SFlineToTextH,
711 (SFlistSize - (old - new)) * SFentryHeight,
713 SFlowerY + (old - new) * SFentryHeight
720 SFentryWidth + SFlineToTextH,
721 (old - new) * SFentryHeight,
724 SFdrawStrings(win, dir, 0, old - new);
732 SFentryWidth + SFlineToTextH,
733 SFlistSize * SFentryHeight,
736 SFdrawStrings(win, dir, 0, SFlistSize - 1);
742 SFvAreaSelectedCallback(w, n, pnew)
750 dir = &(SFdirs[SFdirPtr + n]);
753 (((double) pnew) / SFvScrollHeight) * dir->nEntries;
755 if (new > dir->nEntries - SFlistSize) {
756 new = dir->nEntries - SFlistSize;
766 f = ((double) new) / dir->nEntries;
768 XawScrollbarSetThumb(
771 (float) (((double) ((dir->nEntries < SFlistSize) ?
772 dir->nEntries : SFlistSize)) / dir->nEntries)
776 SFvSliderMovedCallback(w, n, new);
781 SFhSliderMovedCallback(w, n, new)
789 dir = &(SFdirs[SFdirPtr + n]);
791 dir->hOrigin = (*new) * dir->nChars;
792 if (dir->hOrigin == save) {
796 SFdrawList(n, SF_DO_NOT_SCROLL);
801 SFhAreaSelectedCallback(w, n, pnew)
809 dir = &(SFdirs[SFdirPtr + n]);
812 (((double) pnew) / SFhScrollWidth) * dir->nChars;
814 if (new > dir->nChars - SFcharsPerEntry) {
815 new = dir->nChars - SFcharsPerEntry;
825 f = ((double) new) / dir->nChars;
827 XawScrollbarSetThumb(
830 (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
831 dir->nChars : SFcharsPerEntry)) / dir->nChars)
834 SFhSliderMovedCallback(w, n, &f);
840 SFpathSliderMovedCallback(w, client_data, new)
842 XtPointer client_data;
850 SFdirPtrSave = SFdirPtr;
851 SFdirPtr = (*new) * SFdirEnd;
852 if (SFdirPtr == SFdirPtrSave) {
856 SFdrawLists(SF_DO_SCROLL);
859 while (SFdirPtr + n >= SFdirEnd) {
863 dir = &(SFdirs[SFdirPtr + n]);
865 pos = dir->path - SFcurrentPath;
867 if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
868 pos -= strlen(SFstartDir);
874 XawTextSetInsertionPoint(selFileField, pos);
880 SFpathAreaSelectedCallback(w, client_data, pnew)
882 XtPointer client_data;
888 new = SFdirPtr + (((double) pnew) / SFpathScrollWidth) * SFdirEnd;
890 if (new > SFdirEnd - 3) {
898 f = ((double) new) / SFdirEnd;
900 XawScrollbarSetThumb(
903 (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
907 SFpathSliderMovedCallback(w, (XtPointer) NULL, &f);
914 register SFEntry *entry;
916 for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) {
917 if (!(dir->nEntries)) {
921 entry = &(dir->entries[dir->nEntries - 1]);
922 entry >= dir->entries;
925 if (!(entry->statDone)) {
926 (void) SFstatAndCheck(dir, entry);