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;
66 data = XtNew(TextData);
68 XtGetApplicationResources(selFileForm, (XtPointer) data, textResources,
69 XtNumber(textResources), (Arg *) NULL, ZERO);
71 SFfont = XLoadQueryFont(SFdisplay, data->fontname);
73 SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT);
77 (void) sprintf(sbuf, "XsraSelFile: can't get font %s",
80 XtAppError(SFapp, sbuf);
84 SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2;
85 SFcharAscent = SFfont->max_bounds.ascent;
86 SFcharHeight = SFcharAscent + SFfont->max_bounds.descent;
92 XRectangle rectangles[1];
94 gcValues.foreground = SFfore;
104 SFscrollGC = XtGetGC(
111 gcValues.function = GXinvert;
112 gcValues.plane_mask = (SFfore ^ SFback);
114 SFinvertGC = XtGetGC(
123 gcValues.foreground = SFfore;
124 gcValues.background = SFback;
125 gcValues.font = SFfont->fid;
127 SFtextGC = XCreateGC(
129 XtWindow(selFileLists[0]),
138 rectangles[0].x = SFlineToTextH + SFbesideText;
140 rectangles[0].width = SFcharsPerEntry * SFcharWidth;
141 rectangles[0].height = SFupperY + 1;
154 SFclearList(n, doScroll)
160 SFcurrentInvert[n] = -1;
162 XClearWindow(SFdisplay, XtWindow(selFileLists[n]));
164 XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs,
168 dir = &(SFdirs[SFdirPtr + n]);
170 if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars) {
171 XawScrollbarSetThumb(
173 (float) (((double) dir->vOrigin) /
175 (float) (((double) ((dir->nEntries < SFlistSize)
176 ? dir->nEntries : SFlistSize)) /
180 XawScrollbarSetThumb(
182 (float) (((double) dir->hOrigin) / dir->nChars),
183 (float) (((double) ((dir->nChars <
184 SFcharsPerEntry) ? dir->nChars :
185 SFcharsPerEntry)) / dir->nChars)
188 XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
190 XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
197 SFdeleteEntry(dir, entry)
202 register SFEntry *end;
206 idx = entry - dir->entries;
208 if (idx < dir->beginSelection) {
209 dir->beginSelection--;
211 if (idx <= dir->endSelection) {
214 if (dir->beginSelection > dir->endSelection) {
215 dir->beginSelection = dir->endSelection = -1;
218 if (idx < dir->vOrigin) {
224 end = &(dir->entries[dir->nEntries - 1]);
226 for (e = entry; e < end; e++) {
230 if (!(--dir->nEntries)) {
234 n = dir - &(SFdirs[SFdirPtr]);
235 if ((n < 0) || (n > 2)) {
239 XawScrollbarSetThumb(
241 (float) (((double) dir->vOrigin) / dir->nEntries),
242 (float) (((double) ((dir->nEntries < SFlistSize) ?
243 dir->nEntries : SFlistSize)) / dir->nEntries)
248 SFwriteStatChar(name, last, statBuf)
251 struct stat *statBuf;
253 name[last] = SFstatChar(statBuf);
257 SFstatAndCheck(dir, entry)
266 * must be restored before returning
271 if (!SFchdir(SFcurrentPath)) {
272 last = strlen(entry->real) - 1;
273 entry->real[last] = 0;
276 (!stat(entry->real, &statBuf))
280 || (!lstat(entry->real, &statBuf))
282 #endif /* ndef S_IFLNK */
289 if (SFfunc(entry->real, &shown, &statBuf)) {
294 entry->shown = XtMalloc(
297 (void) strcpy(entry->shown,
304 entry->shown[len + 1] = 0;
307 SFdeleteEntry(dir, entry);
313 SFwriteStatChar(entry->real, last, &statBuf);
315 entry->real[last] = ' ';
324 SFdrawStrings(w, dir, from, to)
331 register SFEntry *entry;
334 x = SFtextX - dir->hOrigin * SFcharWidth;
336 if (dir->vOrigin + to >= dir->nEntries) {
337 to = dir->nEntries - dir->vOrigin - 1;
339 for (i = from; i <= to; i++) {
340 entry = &(dir->entries[dir->vOrigin + i]);
341 if (!(entry->statDone)) {
342 if (SFstatAndCheck(dir, entry)) {
343 if (dir->vOrigin + to >= dir->nEntries) {
344 to = dir->nEntries - dir->vOrigin - 1;
355 SFtextYoffset + i * SFentryHeight,
359 if (dir->vOrigin + i == dir->beginSelection) {
365 SFlowerY + i * SFentryHeight,
366 SFlineToTextH + SFentryWidth - 2,
367 SFlowerY + i * SFentryHeight
371 (dir->vOrigin + i >= dir->beginSelection) &&
372 (dir->vOrigin + i <= dir->endSelection)
374 SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
375 SFlowerY + i * SFentryHeight;
376 SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
377 SFlowerY + (i + 1) * SFentryHeight - 1;
386 if (dir->vOrigin + i == dir->endSelection) {
392 SFlowerY + (i + 1) * SFentryHeight - 1,
393 SFlineToTextH + SFentryWidth - 2,
394 SFlowerY + (i + 1) * SFentryHeight - 1
400 SFdrawList(n, doScroll)
407 SFclearList(n, doScroll);
409 if (SFdirPtr + (3-NR) + n < SFdirEnd) {
410 dir = &(SFdirs[SFdirPtr + n + (3-NR)]);
411 w = XtWindow(selFileLists[n]);
416 SFtextX - dir->hOrigin * SFcharWidth,
417 SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
421 SFdrawStrings(w, dir, 0, SFlistSize - 1);
425 SFdrawLists(doScroll)
430 for (i = 0; i < NR; i++) {
431 SFdrawList(i, doScroll);
441 XtWindow(selFileLists[n]),
444 SFcurrentInvert[n] * SFentryHeight + SFlowerY,
451 SFscrollTimerInterval()
453 static int maxVal = 200;
454 static int varyDist = 50;
455 static int minDist = 50;
459 if (SFcurrentListY < SFlowerY) {
460 dist = SFlowerY - SFcurrentListY;
461 } else if (SFcurrentListY > SFupperY) {
462 dist = SFcurrentListY - SFupperY;
464 return (unsigned long) 1;
467 t = maxVal - ((maxVal / varyDist) * (dist - minDist));
477 return (unsigned long) t;
491 dir = &(SFdirs[SFdirPtr + n]);
494 if (SFcurrentListY < SFlowerY) {
495 if (dir->vOrigin > 0) {
496 SFvSliderMovedCallback(selFileVScrolls[n], n,
499 } else if (SFcurrentListY > SFupperY) {
500 if (dir->vOrigin < dir->nEntries - SFlistSize) {
501 SFvSliderMovedCallback(selFileVScrolls[n], n,
506 if (dir->vOrigin != save) {
508 XawScrollbarSetThumb(
510 (float) (((double) dir->vOrigin) / dir->nEntries),
511 (float) (((double) ((dir->nEntries < SFlistSize) ?
512 dir->nEntries : SFlistSize)) / dir->nEntries)
517 if (SFbuttonPressed) {
518 SFscrollTimerId = XtAppAddTimeOut(SFapp,
519 SFscrollTimerInterval(), SFscrollTimer, (XtPointer) n);
524 SFnewInvertEntry(n, event)
526 register XMotionEvent *event;
530 static int SFscrollTimerAdded = 0;
535 if (SFdirPtr + n >= SFdirEnd) {
538 (x >= 0) && (x <= SFupperX) &&
539 (y >= SFlowerY) && (y <= SFupperY)
541 register SFDir *dir = &(SFdirs[SFdirPtr + n]);
543 if (SFscrollTimerAdded) {
544 SFscrollTimerAdded = 0;
545 XtRemoveTimeOut(SFscrollTimerId);
548 new = (y - SFlowerY) / SFentryHeight;
549 if (dir->vOrigin + new >= dir->nEntries) {
554 if (SFbuttonPressed) {
556 if (!SFscrollTimerAdded) {
557 SFscrollTimerAdded = 1;
558 SFscrollTimerId = XtAppAddTimeOut(SFapp,
559 SFscrollTimerInterval(), SFscrollTimer,
570 SFenterList(w, n, event)
573 register XEnterWindowEvent *event;
578 if (SFcurrentInvert[n] != -1) {
580 SFcurrentInvert[n] = -1;
583 new = SFnewInvertEntry(n, (XMotionEvent *) event);
585 SFcurrentInvert[n] = new;
592 SFleaveList(w, n, event)
597 if (SFcurrentInvert[n] != -1) {
599 SFcurrentInvert[n] = -1;
605 SFmotionList(w, n, event)
608 register XMotionEvent *event;
612 new = SFnewInvertEntry(n, event);
614 if (new != SFcurrentInvert[n]) {
615 if (SFcurrentInvert[n] != -1) {
618 SFcurrentInvert[n] = new;
627 SFvFloatSliderMovedCallback(w, n, fnew)
634 new = (*fnew) * SFdirs[SFdirPtr + n].nEntries;
636 SFvSliderMovedCallback(w, n, new);
641 SFvSliderMovedCallback(w, n, new)
650 dir = &(SFdirs[SFdirPtr + n]);
659 win = XtWindow(selFileLists[n]);
661 if (ABS(new - old) < SFlistSize) {
669 SFlowerY + (new - old) * SFentryHeight,
670 SFentryWidth + SFlineToTextH,
671 (SFlistSize - (new - old)) * SFentryHeight,
679 SFlowerY + (SFlistSize - (new - old)) *
681 SFentryWidth + SFlineToTextH,
682 (new - old) * SFentryHeight,
685 SFdrawStrings(win, dir, SFlistSize - (new - old),
695 SFentryWidth + SFlineToTextH,
696 (SFlistSize - (old - new)) * SFentryHeight,
698 SFlowerY + (old - new) * SFentryHeight
705 SFentryWidth + SFlineToTextH,
706 (old - new) * SFentryHeight,
709 SFdrawStrings(win, dir, 0, old - new);
717 SFentryWidth + SFlineToTextH,
718 SFlistSize * SFentryHeight,
721 SFdrawStrings(win, dir, 0, SFlistSize - 1);
727 SFvAreaSelectedCallback(w, n, pnew)
735 dir = &(SFdirs[SFdirPtr + n]);
738 (((double) pnew) / SFvScrollHeight) * dir->nEntries;
740 if (new > dir->nEntries - SFlistSize) {
741 new = dir->nEntries - SFlistSize;
751 f = ((double) new) / dir->nEntries;
753 XawScrollbarSetThumb(
756 (float) (((double) ((dir->nEntries < SFlistSize) ?
757 dir->nEntries : SFlistSize)) / dir->nEntries)
761 SFvSliderMovedCallback(w, n, new);
766 SFhSliderMovedCallback(w, n, new)
774 dir = &(SFdirs[SFdirPtr + n]);
776 dir->hOrigin = (*new) * dir->nChars;
777 if (dir->hOrigin == save) {
781 SFdrawList(n, SF_DO_NOT_SCROLL);
786 SFhAreaSelectedCallback(w, n, pnew)
794 dir = &(SFdirs[SFdirPtr + n]);
797 (((double) pnew) / SFhScrollWidth) * dir->nChars;
799 if (new > dir->nChars - SFcharsPerEntry) {
800 new = dir->nChars - SFcharsPerEntry;
810 f = ((double) new) / dir->nChars;
812 XawScrollbarSetThumb(
815 (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
816 dir->nChars : SFcharsPerEntry)) / dir->nChars)
819 SFhSliderMovedCallback(w, n, &f);
825 SFpathSliderMovedCallback(w, client_data, new)
827 XtPointer client_data;
835 SFdirPtrSave = SFdirPtr;
836 SFdirPtr = (*new) * SFdirEnd;
837 if (SFdirPtr == SFdirPtrSave) {
841 SFdrawLists(SF_DO_SCROLL);
844 while (SFdirPtr + n >= SFdirEnd) {
848 dir = &(SFdirs[SFdirPtr + n]);
850 pos = dir->path - SFcurrentPath;
852 if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
853 pos -= strlen(SFstartDir);
859 XawTextSetInsertionPoint(selFileField, pos);
865 SFpathAreaSelectedCallback(w, client_data, pnew)
867 XtPointer client_data;
873 new = SFdirPtr + (((double) pnew) / SFpathScrollWidth) * SFdirEnd;
875 if (new > SFdirEnd - 3) {
883 f = ((double) new) / SFdirEnd;
885 XawScrollbarSetThumb(
888 (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
892 SFpathSliderMovedCallback(w, (XtPointer) NULL, &f);
899 register SFEntry *entry;
901 for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) {
902 if (!(dir->nEntries)) {
906 entry = &(dir->entries[dir->nEntries - 1]);
907 entry >= dir->entries;
910 if (!(entry->statDone)) {
911 (void) SFstatAndCheck(dir, entry);