diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
commit | 487ca4806cc046076293cf6cc5fbba0db282bac7 (patch) | |
tree | 847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/xdvik/gui/sfDraw.c | |
parent | a3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff) |
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/xdvik/gui/sfDraw.c')
-rw-r--r-- | Build/source/texk/xdvik/gui/sfDraw.c | 819 |
1 files changed, 819 insertions, 0 deletions
diff --git a/Build/source/texk/xdvik/gui/sfDraw.c b/Build/source/texk/xdvik/gui/sfDraw.c new file mode 100644 index 00000000000..7a3ddd8cf06 --- /dev/null +++ b/Build/source/texk/xdvik/gui/sfDraw.c @@ -0,0 +1,819 @@ +/* + * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Software Research Associates not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Software Research Associates + * makes no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Erik M. van der Poel + * Software Research Associates, Inc., Tokyo, Japan + * erik@sra.co.jp + */ + +#include "xdvi-config.h" + +#include "kpathsea/c-auto.h" +#include "kpathsea/config.h" +#include "kpathsea/c-stat.h" +#include "xdvi.h" + +#include "sfDraw.h" +#include "sfDir.h" +#include "sfPath.h" + +#if !defined(MOTIF) /* for xdvik */ + +#define SF_DEFAULT_FONT "9x15" + +typedef struct { + char *font; +} TextData, *textPtr; + +int SFcharWidth, SFcharAscent, SFcharHeight; + +int SFcurrentInvert[3] = { -1, -1, -1 }; + +static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC; + +static XtResource textResources[] = { + {XtNfont, XtCFont, XtRString, sizeof(char *), + XtOffset(textPtr, font), XtRString, SF_DEFAULT_FONT}, +}; + +static XFontStruct *SFfont; + +static int SFcurrentListY; + +static XtIntervalId SFscrollTimerId; + +void +SFinitFont(void) +{ + TextData *data; + + data = XtNew(TextData); + + XtGetApplicationResources(selFileForm, (XtPointer) data, textResources, + XtNumber(textResources), (Arg *) NULL, ZERO); + + SFfont = XLoadQueryFont(SFdisplay, data->font); + if (!SFfont) { + SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT); + if (!SFfont) { + char sbuf[256]; + + (void)sprintf(sbuf, "XsraSelFile: can't get font %s", + SF_DEFAULT_FONT); + + XtAppError(SFapp, sbuf); + } + } + + TRACE_GUI((stderr, "FONT: width %d, %d\n", SFfont->max_bounds.width, SFfont->min_bounds.width)); + SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2; + SFcharAscent = SFfont->max_bounds.ascent; + SFcharHeight = SFcharAscent + SFfont->max_bounds.descent; + if (SFcharWidth == 0) { + /* if min_bounds.width = -max_bounds.width, we probably + have a scalable TT font; try to determine its actual + width by measuring the letter `x': + */ + SFcharWidth = XTextWidth(SFfont, "x", 1); + } + if (SFcharWidth == 0) { /* last resort */ + SFcharWidth = SFfont->max_bounds.width / 2; + } + TRACE_GUI((stderr, + "Using font measures: charwidth %d, ascent %d, height %d", + SFcharWidth, SFcharAscent, SFcharHeight)); +} + +void +SFcreateGC(void) +{ + XGCValues gcValues; + XRectangle rectangles[1]; + +/* XtVaGetValues(selFileLists[0], */ +/* XtNforeground, &(gcValues.foreground), */ +/* XtNbackground, &(gcValues.background), */ +/* NULL); */ + gcValues.foreground = SFfore; + + SFlineGC = XtGetGC(selFileLists[0], (XtGCMask) + GCForeground | 0, &gcValues); + + SFscrollGC = XtGetGC(selFileLists[0], (XtGCMask) + 0, &gcValues); + + gcValues.function = GXinvert; +/* gcValues.plane_mask = (gcValues.foreground ^ gcValues.background); */ + gcValues.plane_mask = (SFfore ^ SFback); + + SFinvertGC = XtGetGC(selFileLists[0], (XtGCMask) + GCFunction | GCPlaneMask | 0, &gcValues); + + gcValues.foreground = SFfore; + gcValues.background = SFback; + gcValues.font = SFfont->fid; + + SFtextGC = XCreateGC(SFdisplay, XtWindow(selFileLists[0]), (unsigned long) + GCForeground | GCBackground | GCFont | 0, &gcValues); + + rectangles[0].x = SFlineToTextH + SFbesideText; + rectangles[0].y = 0; + rectangles[0].width = SFcharsPerEntry * SFcharWidth; + rectangles[0].height = SFupperY + 1; + + XSetClipRectangles(SFdisplay, SFtextGC, 0, 0, rectangles, 1, Unsorted); +} + +void +SFclearList(int n, int doScroll) +{ + SFDir *dir; + + SFcurrentInvert[n] = -1; + + XClearWindow(SFdisplay, XtWindow(selFileLists[n])); + + XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs, 2); + + if (doScroll) { + dir = &(SFdirs[SFdirPtr + n]); + + if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars) { + XawScrollbarSetThumb(selFileVScrolls[n], + (double)dir->vOrigin / dir->nEntries, + (double)(dir->nEntries < SFlistSize + ? dir->nEntries + : SFlistSize) + / dir->nEntries); + + XawScrollbarSetThumb(selFileHScrolls[n], + (double)(dir->hOrigin) / dir->nChars, + (double)(dir->nChars < SFcharsPerEntry + ? dir-> nChars : SFcharsPerEntry) + / dir->nChars); + } + else { + XawScrollbarSetThumb(selFileVScrolls[n], 0.0, 1.0); + XawScrollbarSetThumb(selFileHScrolls[n], 0.0, 1.0); + } + } +} + +static void +SFdeleteEntry(SFDir *dir, SFEntry *entry) +{ + SFEntry *e; + SFEntry *end; + int n; + int idx; + + idx = entry - dir->entries; + + if (idx < dir->beginSelection) { + dir->beginSelection--; + } + if (idx <= dir->endSelection) { + dir->endSelection--; + } + if (dir->beginSelection > dir->endSelection) { + dir->beginSelection = dir->endSelection = -1; + } + + if (idx < dir->vOrigin) { + dir->vOrigin--; + } + + XtFree(entry->real); + + end = &(dir->entries[dir->nEntries - 1]); + + for (e = entry; e < end; e++) { + *e = *(e + 1); + } + + if (!(--dir->nEntries)) { + return; + } + + n = dir - &(SFdirs[SFdirPtr]); + if ((n < 0) || (n > 2)) { + return; + } + + XawScrollbarSetThumb(selFileVScrolls[n], + (double)(dir->vOrigin) / dir->nEntries, + (double)(dir->nEntries < SFlistSize + ? dir->nEntries : SFlistSize) + / dir->nEntries); +} + +static void +SFwriteStatChar(char *name, int last, struct stat *statBuf) +{ + name[last] = SFstatChar(statBuf); +} + +static int +SFstatAndCheck(SFDir *dir, SFEntry *entry) +{ + struct stat statBuf; + char save; + int last; + extern int SFchdir(); + + /* + * must be restored before returning + */ + save = *(dir->path); + *(dir->path) = 0; + + if (!SFchdir(SFcurrentPath)) { + last = strlen(entry->real) - 1; + entry->real[last] = 0; + entry->statDone = 1; + if ((!stat(entry->real, &statBuf)) +#ifdef S_IFLNK + || (!lstat(entry->real, &statBuf)) +#endif /* ndef S_IFLNK */ + ) { + if (SFfunc) { + char *shown; + + shown = NULL; + if (SFfunc(entry->real, &shown, &statBuf)) { + if (shown) { + int len; + + len = strlen(shown); + entry->shown = XtMalloc((unsigned)(len + 2) + ); + (void)strcpy(entry->shown, shown); + SFwriteStatChar(entry->shown, len, &statBuf); + entry->shown[len + 1] = 0; + } + } + else { + SFdeleteEntry(dir, entry); + + *(dir->path) = save; + return 1; + } + } + SFwriteStatChar(entry->real, last, &statBuf); + } + else { + entry->real[last] = ' '; + } + } + + *(dir->path) = save; + return 0; +} + +static void +SFdrawStrings(Window w, SFDir *dir, int from, int to) +{ + int i; + SFEntry *entry; + int x; + + x = SFtextX - dir->hOrigin * SFcharWidth; + + if (dir->vOrigin + to >= dir->nEntries) { + to = dir->nEntries - dir->vOrigin - 1; + } + for (i = from; i <= to; i++) { + entry = &(dir->entries[dir->vOrigin + i]); + if (!(entry->statDone)) { + if (SFstatAndCheck(dir, entry)) { + if (dir->vOrigin + to >= dir->nEntries) { + to = dir->nEntries - dir->vOrigin - 1; + } + i--; + continue; + } + } + XDrawImageString(SFdisplay, + w, + SFtextGC, + x, + SFtextYoffset + i * SFentryHeight, + entry->shown, strlen(entry->shown)); + if (dir->vOrigin + i == dir->beginSelection) { + XDrawLine(SFdisplay, + w, + SFlineGC, + SFlineToTextH + 1, + SFlowerY + i * SFentryHeight, + SFlineToTextH + SFentryWidth - 2, + SFlowerY + i * SFentryHeight); + } + if ( + (dir->vOrigin + i >= dir->beginSelection) && + (dir->vOrigin + i <= dir->endSelection)) { + SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 = + SFlowerY + i * SFentryHeight; + SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 = + SFlowerY + (i + 1) * SFentryHeight - 1; + XDrawSegments(SFdisplay, w, SFlineGC, SFcompletionSegs, 2); + } + if (dir->vOrigin + i == dir->endSelection) { + XDrawLine(SFdisplay, + w, + SFlineGC, + SFlineToTextH + 1, + SFlowerY + (i + 1) * SFentryHeight - 1, + SFlineToTextH + SFentryWidth - 2, + SFlowerY + (i + 1) * SFentryHeight - 1); + } + } +} + +void +SFdrawList(int n, int doScroll) +{ + SFDir *dir; + Window w; + + SFclearList(n, doScroll); + + if (SFdirPtr + n < SFdirEnd) { + dir = &(SFdirs[SFdirPtr + n]); + w = XtWindow(selFileLists[n]); + XDrawImageString(SFdisplay, + w, + SFtextGC, + SFtextX - dir->hOrigin * SFcharWidth, + SFlineToTextV + SFaboveAndBelowText + SFcharAscent, + dir->dir, strlen(dir->dir) + ); + SFdrawStrings(w, dir, 0, SFlistSize - 1); + } +} + +void +SFdrawLists(int doScroll) +{ + int i; + + for (i = 0; i < 3; i++) { + SFdrawList(i, doScroll); + } +} + +static void +SFinvertEntry(int n) +{ + XFillRectangle(SFdisplay, + XtWindow(selFileLists[n]), + SFinvertGC, + SFlineToTextH, + SFcurrentInvert[n] * SFentryHeight + SFlowerY, + SFentryWidth, SFentryHeight); +} + +static unsigned long +SFscrollTimerInterval(void) +{ + static int maxVal = 200; + static int varyDist = 50; + static int minDist = 50; + int t; + int dist; + + if (SFcurrentListY < SFlowerY) { + dist = SFlowerY - SFcurrentListY; + } + else if (SFcurrentListY > SFupperY) { + dist = SFcurrentListY - SFupperY; + } + else { + return (unsigned long)1; + } + + t = maxVal - ((maxVal / varyDist) * (dist - minDist)); + + if (t < 1) { + t = 1; + } + + if (t > maxVal) { + t = maxVal; + } + + return (unsigned long)t; +} + +static void +SFscrollTimer(XtPointer p, XtIntervalId *id) +{ + SFDir *dir; + int save; + int n; + + UNUSED(id); + + n = (int)p; + + fprintf(stderr, "SFscrollTimer called!\n"); + + dir = &(SFdirs[SFdirPtr + n]); + save = dir->vOrigin; + + if (SFcurrentListY < SFlowerY) { + if (dir->vOrigin > 0) { + SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin - 1); + } + } + else if (SFcurrentListY > SFupperY) { + if (dir->vOrigin < dir->nEntries - SFlistSize) { + SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin + 1); + } + } + + if (dir->vOrigin != save) { + if (dir->nEntries) { + XawScrollbarSetThumb(selFileVScrolls[n], + (double)(dir->vOrigin) / dir->nEntries, + (double)(dir->nEntries < SFlistSize + ? dir-> nEntries : SFlistSize) + / dir->nEntries); + } + } + + if (SFbuttonPressed) { + SFscrollTimerId = XtAppAddTimeOut(SFapp, + SFscrollTimerInterval(), + SFscrollTimer, (XtPointer) n); + } +} + +static int +SFnewInvertEntry(int n, XMotionEvent *event) +{ + int x, y; + int new; + static int SFscrollTimerAdded = 0; + + x = event->x; + y = event->y; + + if (SFdirPtr + n >= SFdirEnd) { + return -1; + } + else if ((x >= 0) && (x <= SFupperX) && (y >= SFlowerY) && (y <= SFupperY) + ) { + SFDir *dir = &(SFdirs[SFdirPtr + n]); + + if (SFscrollTimerAdded) { + SFscrollTimerAdded = 0; + XtRemoveTimeOut(SFscrollTimerId); + } + + new = (y - SFlowerY) / SFentryHeight; + if (dir->vOrigin + new >= dir->nEntries) { + return -1; + } + return new; + } + else { + if (SFbuttonPressed) { + SFcurrentListY = y; + if (!SFscrollTimerAdded) { + SFscrollTimerAdded = 1; + SFscrollTimerId = XtAppAddTimeOut(SFapp, + SFscrollTimerInterval(), + SFscrollTimer, (XtPointer) n); + } + } + + return -1; + } +} + +void +SFenterList(Widget w, int n, XEnterWindowEvent *event) +{ + int new; + + UNUSED(w); + + /* sanity */ + if (SFcurrentInvert[n] != -1) { + SFinvertEntry(n); + SFcurrentInvert[n] = -1; + } + + new = SFnewInvertEntry(n, (XMotionEvent *) event); + if (new != -1) { + SFcurrentInvert[n] = new; + SFinvertEntry(n); + } +} + +void +SFleaveList(Widget w, int n, XEvent *event) +{ + UNUSED(w); + UNUSED(event); + + if (SFcurrentInvert[n] != -1) { + SFinvertEntry(n); + SFcurrentInvert[n] = -1; + } +} + +void +SFmotionList(Widget w, int n, XMotionEvent *event) +{ + int new; + + UNUSED(w); + + new = SFnewInvertEntry(n, event); + + if (new != SFcurrentInvert[n]) { + if (SFcurrentInvert[n] != -1) { + SFinvertEntry(n); + } + SFcurrentInvert[n] = new; + if (new != -1) { + SFinvertEntry(n); + } + } +} + +void +SFvFloatSliderMovedCallback(Widget w, int n, float *fnew) +{ + int new; + + new = (*fnew) * SFdirs[SFdirPtr + n].nEntries; + + SFvSliderMovedCallback(w, n, new); +} + +void +SFvSliderMovedCallback(Widget w, int n, int new) +{ + int old; + Window win; + SFDir *dir; + + UNUSED(w); + + dir = &(SFdirs[SFdirPtr + n]); + + old = dir->vOrigin; + dir->vOrigin = new; + + if (old == new) { + return; + } + + win = XtWindow(selFileLists[n]); + + if (ABS(new - old) < SFlistSize) { + if (new > old) { + XCopyArea(SFdisplay, + win, + win, + SFscrollGC, + SFlineToTextH, + SFlowerY + (new - old) * SFentryHeight, + SFentryWidth + SFlineToTextH, + (SFlistSize - (new - old)) * SFentryHeight, + SFlineToTextH, SFlowerY); + XClearArea(SFdisplay, + win, + SFlineToTextH, + SFlowerY + (SFlistSize - (new - old)) * + SFentryHeight, + SFentryWidth + SFlineToTextH, + (new - old) * SFentryHeight, False); + SFdrawStrings(win, dir, SFlistSize - (new - old), SFlistSize - 1); + } + else { + XCopyArea(SFdisplay, + win, + win, + SFscrollGC, + SFlineToTextH, + SFlowerY, + SFentryWidth + SFlineToTextH, + (SFlistSize - (old - new)) * SFentryHeight, + SFlineToTextH, SFlowerY + (old - new) * SFentryHeight); + XClearArea(SFdisplay, + win, + SFlineToTextH, + SFlowerY, + SFentryWidth + SFlineToTextH, + (old - new) * SFentryHeight, False); + SFdrawStrings(win, dir, 0, old - new); + } + } + else { + XClearArea(SFdisplay, + win, + SFlineToTextH, + SFlowerY, + SFentryWidth + SFlineToTextH, + SFlistSize * SFentryHeight, False); + SFdrawStrings(win, dir, 0, SFlistSize - 1); + } +} + +void +SFvAreaSelectedCallback(Widget w, int n, int pnew) +{ + SFDir *dir; + int new; + + dir = &(SFdirs[SFdirPtr + n]); + + new = dir->vOrigin + ((double)pnew / SFvScrollHeight) * dir->nEntries; + + if (new > dir->nEntries - SFlistSize) { + new = dir->nEntries - SFlistSize; + } + + if (new < 0) { + new = 0; + } + + if (dir->nEntries) { + float f; + + f = ((double)new) / dir->nEntries; + + XawScrollbarSetThumb(w, f, + (double)(dir->nEntries < SFlistSize + ? dir->nEntries + : SFlistSize) + / dir->nEntries); + } + + SFvSliderMovedCallback(w, n, new); +} + +void +SFhSliderMovedCallback(Widget w, int n, float *new) +{ + SFDir *dir; + int save; + + UNUSED(w); + + dir = &(SFdirs[SFdirPtr + n]); + save = dir->hOrigin; + dir->hOrigin = (*new) * dir->nChars; + if (dir->hOrigin == save) { + return; + } + + SFdrawList(n, SF_DO_NOT_SCROLL); +} + +void +SFhAreaSelectedCallback(Widget w, int n, int pnew) +{ + SFDir *dir; + int new; + + dir = &(SFdirs[SFdirPtr + n]); + + new = dir->hOrigin + (((double)pnew) / SFhScrollWidth) * dir->nChars; + + if (new > dir->nChars - SFcharsPerEntry) { + new = dir->nChars - SFcharsPerEntry; + } + + if (new < 0) { + new = 0; + } + + if (dir->nChars) { + float f; + + f = (double)new / dir->nChars; + + XawScrollbarSetThumb(w, f, + (double)(dir->nChars < SFcharsPerEntry + ? dir->nChars + : SFcharsPerEntry) + / dir->nChars); + + SFhSliderMovedCallback(w, n, &f); + } +} + +void +SFpathSliderMovedCallback(Widget w, XtPointer client_data, float *new) +{ + SFDir *dir; + int n; + XawTextPosition pos; + int SFdirPtrSave; + + UNUSED(w); + UNUSED(client_data); + + SFdirPtrSave = SFdirPtr; + SFdirPtr = (*new) * SFdirEnd; + if (SFdirPtr == SFdirPtrSave) { + return; + } + + SFdrawLists(SF_DO_SCROLL); + + n = 2; + while (SFdirPtr + n >= SFdirEnd) { + n--; + } + + dir = &(SFdirs[SFdirPtr + n]); + + pos = dir->path - SFcurrentPath; + + if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) { + pos -= strlen(SFstartDir); + if (pos < 0) { + pos = 0; + } + } + + XawTextSetInsertionPoint(selFileField, pos); +} + +void +SFpathAreaSelectedCallback(Widget w, XtPointer client_data, int pnew) +{ + int new; + float f; + + UNUSED(client_data); + + new = SFdirPtr + (((double)pnew) / SFpathScrollWidth) * SFdirEnd; + + if (new > SFdirEnd - 3) { + new = SFdirEnd - 3; + } + + if (new < 0) { + new = 0; + } + + f = ((double)new) / SFdirEnd; + + XawScrollbarSetThumb(w, f, + (double)(SFdirEnd < 3 ? SFdirEnd : 3) / SFdirEnd); + + SFpathSliderMovedCallback(w, (XtPointer) NULL, &f); +} + +Boolean +SFworkProc(void) +{ + SFDir *dir; + SFEntry *entry; + + for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) { + if (!(dir->nEntries)) { + continue; + } + for (entry = &(dir->entries[dir->nEntries - 1]); + entry >= dir->entries; entry--) { + if (!(entry->statDone)) { + (void)SFstatAndCheck(dir, entry); + return False; + } + } + } + + SFworkProcAdded = 0; + + return True; +} + +#else +/* silence `empty compilation unit' warnings */ +static void bar(void); static void foo() { bar(); } static void bar(void) { foo(); } +#endif /* !defined(MOTIF) */ |