Back to index

tetex-bin  3.0
sfDraw.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
00003  *
00004  * Permission to use, copy, modify, and distribute this software and its
00005  * documentation for any purpose and without fee is hereby granted, provided
00006  * that the above copyright notice appear in all copies and that both that
00007  * copyright notice and this permission notice appear in supporting
00008  * documentation, and that the name of Software Research Associates not be used
00009  * in advertising or publicity pertaining to distribution of the software
00010  * without specific, written prior permission.  Software Research Associates
00011  * makes no representations about the suitability of this software for any
00012  * purpose.  It is provided "as is" without express or implied warranty.
00013  *
00014  * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
00015  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
00016  * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
00017  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00018  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00019  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00020  * PERFORMANCE OF THIS SOFTWARE.
00021  *
00022  * Author: Erik M. van der Poel
00023  *         Software Research Associates, Inc., Tokyo, Japan
00024  *         erik@sra.co.jp
00025  */
00026 
00027 #include "xdvi-config.h"
00028 
00029 #include "kpathsea/c-auto.h"
00030 #include "kpathsea/config.h"
00031 #include "kpathsea/c-stat.h"
00032 #include "xdvi.h"
00033 
00034 #include "sfDraw.h"
00035 #include "sfDir.h"
00036 #include "sfPath.h"
00037 
00038 #if !defined(MOTIF)  /* for xdvik */
00039 
00040 #define SF_DEFAULT_FONT "9x15"
00041 
00042 typedef struct {
00043     char *font;
00044 } TextData, *textPtr;
00045 
00046 int SFcharWidth, SFcharAscent, SFcharHeight;
00047 
00048 int SFcurrentInvert[3] = { -1, -1, -1 };
00049 
00050 static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC;
00051 
00052 static XtResource textResources[] = {
00053     {XtNfont, XtCFont, XtRString, sizeof(char *),
00054      XtOffset(textPtr, font), XtRString, SF_DEFAULT_FONT},
00055 };
00056 
00057 static XFontStruct *SFfont;
00058 
00059 static int SFcurrentListY;
00060 
00061 static XtIntervalId SFscrollTimerId;
00062 
00063 void
00064 SFinitFont(void)
00065 {
00066     TextData *data;
00067 
00068     data = XtNew(TextData);
00069 
00070     XtGetApplicationResources(selFileForm, (XtPointer) data, textResources,
00071                            XtNumber(textResources), (Arg *) NULL, ZERO);
00072 
00073     SFfont = XLoadQueryFont(SFdisplay, data->font);
00074     if (!SFfont) {
00075        SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT);
00076        if (!SFfont) {
00077            char sbuf[256];
00078 
00079            (void)sprintf(sbuf, "XsraSelFile: can't get font %s",
00080                        SF_DEFAULT_FONT);
00081 
00082            XtAppError(SFapp, sbuf);
00083        }
00084     }
00085 
00086     TRACE_GUI((stderr, "FONT: width %d, %d\n", SFfont->max_bounds.width, SFfont->min_bounds.width));
00087     SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2;
00088     SFcharAscent = SFfont->max_bounds.ascent;
00089     SFcharHeight = SFcharAscent + SFfont->max_bounds.descent;
00090     if (SFcharWidth == 0) {
00091        /* if min_bounds.width = -max_bounds.width, we probably
00092           have a scalable TT font; try to determine its actual
00093           width by measuring the letter `x':
00094        */
00095        SFcharWidth = XTextWidth(SFfont, "x", 1);
00096     }
00097     if (SFcharWidth == 0) { /* last resort */
00098        SFcharWidth = SFfont->max_bounds.width / 2;
00099     }
00100     TRACE_GUI((stderr,
00101               "Using font measures: charwidth %d, ascent %d, height %d",
00102               SFcharWidth, SFcharAscent, SFcharHeight));
00103 }
00104 
00105 void
00106 SFcreateGC(void)
00107 {
00108     XGCValues gcValues;
00109     XRectangle rectangles[1];
00110 
00111 /*     XtVaGetValues(selFileLists[0], */
00112 /*              XtNforeground, &(gcValues.foreground), */
00113 /*              XtNbackground, &(gcValues.background), */
00114 /*              NULL); */
00115     gcValues.foreground = SFfore;
00116 
00117     SFlineGC = XtGetGC(selFileLists[0], (XtGCMask)
00118                      GCForeground | 0, &gcValues);
00119 
00120     SFscrollGC = XtGetGC(selFileLists[0], (XtGCMask)
00121                       0, &gcValues);
00122 
00123     gcValues.function = GXinvert;
00124 /*     gcValues.plane_mask = (gcValues.foreground ^ gcValues.background); */
00125     gcValues.plane_mask = (SFfore ^ SFback);
00126 
00127     SFinvertGC = XtGetGC(selFileLists[0], (XtGCMask)
00128                       GCFunction | GCPlaneMask | 0, &gcValues);
00129 
00130     gcValues.foreground = SFfore;
00131     gcValues.background = SFback;
00132     gcValues.font = SFfont->fid;
00133 
00134     SFtextGC = XCreateGC(SFdisplay, XtWindow(selFileLists[0]), (unsigned long)
00135                       GCForeground | GCBackground | GCFont | 0, &gcValues);
00136 
00137     rectangles[0].x = SFlineToTextH + SFbesideText;
00138     rectangles[0].y = 0;
00139     rectangles[0].width = SFcharsPerEntry * SFcharWidth;
00140     rectangles[0].height = SFupperY + 1;
00141 
00142     XSetClipRectangles(SFdisplay, SFtextGC, 0, 0, rectangles, 1, Unsorted);
00143 }
00144 
00145 void
00146 SFclearList(int n, int doScroll)
00147 {
00148     SFDir *dir;
00149 
00150     SFcurrentInvert[n] = -1;
00151 
00152     XClearWindow(SFdisplay, XtWindow(selFileLists[n]));
00153 
00154     XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs, 2);
00155 
00156     if (doScroll) {
00157        dir = &(SFdirs[SFdirPtr + n]);
00158 
00159        if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars) {
00160            XawScrollbarSetThumb(selFileVScrolls[n],
00161                              (double)dir->vOrigin / dir->nEntries,
00162                              (double)(dir->nEntries < SFlistSize
00163                                      ? dir->nEntries
00164                                      : SFlistSize)
00165                              / dir->nEntries);
00166 
00167            XawScrollbarSetThumb(selFileHScrolls[n],
00168                              (double)(dir->hOrigin) / dir->nChars,
00169                              (double)(dir->nChars < SFcharsPerEntry
00170                                      ? dir-> nChars : SFcharsPerEntry)
00171                              / dir->nChars);
00172        }
00173        else {
00174            XawScrollbarSetThumb(selFileVScrolls[n], 0.0, 1.0);
00175            XawScrollbarSetThumb(selFileHScrolls[n], 0.0, 1.0);
00176        }
00177     }
00178 }
00179 
00180 static void
00181 SFdeleteEntry(SFDir *dir, SFEntry *entry)
00182 {
00183     SFEntry *e;
00184     SFEntry *end;
00185     int n;
00186     int idx;
00187 
00188     idx = entry - dir->entries;
00189 
00190     if (idx < dir->beginSelection) {
00191        dir->beginSelection--;
00192     }
00193     if (idx <= dir->endSelection) {
00194        dir->endSelection--;
00195     }
00196     if (dir->beginSelection > dir->endSelection) {
00197        dir->beginSelection = dir->endSelection = -1;
00198     }
00199 
00200     if (idx < dir->vOrigin) {
00201        dir->vOrigin--;
00202     }
00203 
00204     XtFree(entry->real);
00205 
00206     end = &(dir->entries[dir->nEntries - 1]);
00207 
00208     for (e = entry; e < end; e++) {
00209        *e = *(e + 1);
00210     }
00211 
00212     if (!(--dir->nEntries)) {
00213        return;
00214     }
00215 
00216     n = dir - &(SFdirs[SFdirPtr]);
00217     if ((n < 0) || (n > 2)) {
00218        return;
00219     }
00220 
00221     XawScrollbarSetThumb(selFileVScrolls[n],
00222                       (double)(dir->vOrigin) / dir->nEntries,
00223                       (double)(dir->nEntries < SFlistSize
00224                               ? dir->nEntries : SFlistSize)
00225                       / dir->nEntries);
00226 }
00227 
00228 static void
00229 SFwriteStatChar(char *name, int last, struct stat *statBuf)
00230 {
00231     name[last] = SFstatChar(statBuf);
00232 }
00233 
00234 static int
00235 SFstatAndCheck(SFDir *dir, SFEntry *entry)
00236 {
00237     struct stat statBuf;
00238     char save;
00239     int last;
00240     extern int SFchdir();
00241 
00242     /*
00243      * must be restored before returning
00244      */
00245     save = *(dir->path);
00246     *(dir->path) = 0;
00247 
00248     if (!SFchdir(SFcurrentPath)) {
00249        last = strlen(entry->real) - 1;
00250        entry->real[last] = 0;
00251        entry->statDone = 1;
00252        if ((!stat(entry->real, &statBuf))
00253 #ifdef S_IFLNK
00254            || (!lstat(entry->real, &statBuf))
00255 #endif /* ndef S_IFLNK */
00256            ) {
00257            if (SFfunc) {
00258               char *shown;
00259 
00260               shown = NULL;
00261               if (SFfunc(entry->real, &shown, &statBuf)) {
00262                   if (shown) {
00263                      int len;
00264 
00265                      len = strlen(shown);
00266                      entry->shown = XtMalloc((unsigned)(len + 2)
00267                          );
00268                      (void)strcpy(entry->shown, shown);
00269                      SFwriteStatChar(entry->shown, len, &statBuf);
00270                      entry->shown[len + 1] = 0;
00271                   }
00272               }
00273               else {
00274                   SFdeleteEntry(dir, entry);
00275 
00276                   *(dir->path) = save;
00277                   return 1;
00278               }
00279            }
00280            SFwriteStatChar(entry->real, last, &statBuf);
00281        }
00282        else {
00283            entry->real[last] = ' ';
00284        }
00285     }
00286 
00287     *(dir->path) = save;
00288     return 0;
00289 }
00290 
00291 static void
00292 SFdrawStrings(Window w, SFDir *dir, int from, int to)
00293 {
00294     int i;
00295     SFEntry *entry;
00296     int x;
00297 
00298     x = SFtextX - dir->hOrigin * SFcharWidth;
00299 
00300     if (dir->vOrigin + to >= dir->nEntries) {
00301        to = dir->nEntries - dir->vOrigin - 1;
00302     }
00303     for (i = from; i <= to; i++) {
00304        entry = &(dir->entries[dir->vOrigin + i]);
00305        if (!(entry->statDone)) {
00306            if (SFstatAndCheck(dir, entry)) {
00307               if (dir->vOrigin + to >= dir->nEntries) {
00308                   to = dir->nEntries - dir->vOrigin - 1;
00309               }
00310               i--;
00311               continue;
00312            }
00313        }
00314        XDrawImageString(SFdisplay,
00315                       w,
00316                       SFtextGC,
00317                       x,
00318                       SFtextYoffset + i * SFentryHeight,
00319                       entry->shown, strlen(entry->shown));
00320        if (dir->vOrigin + i == dir->beginSelection) {
00321            XDrawLine(SFdisplay,
00322                     w,
00323                     SFlineGC,
00324                     SFlineToTextH + 1,
00325                     SFlowerY + i * SFentryHeight,
00326                     SFlineToTextH + SFentryWidth - 2,
00327                     SFlowerY + i * SFentryHeight);
00328        }
00329        if (
00330            (dir->vOrigin + i >= dir->beginSelection) &&
00331            (dir->vOrigin + i <= dir->endSelection)) {
00332            SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
00333               SFlowerY + i * SFentryHeight;
00334            SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
00335               SFlowerY + (i + 1) * SFentryHeight - 1;
00336            XDrawSegments(SFdisplay, w, SFlineGC, SFcompletionSegs, 2);
00337        }
00338        if (dir->vOrigin + i == dir->endSelection) {
00339            XDrawLine(SFdisplay,
00340                     w,
00341                     SFlineGC,
00342                     SFlineToTextH + 1,
00343                     SFlowerY + (i + 1) * SFentryHeight - 1,
00344                     SFlineToTextH + SFentryWidth - 2,
00345                     SFlowerY + (i + 1) * SFentryHeight - 1);
00346        }
00347     }
00348 }
00349 
00350 void
00351 SFdrawList(int n, int doScroll)
00352 {
00353     SFDir *dir;
00354     Window w;
00355 
00356     SFclearList(n, doScroll);
00357 
00358     if (SFdirPtr + n < SFdirEnd) {
00359        dir = &(SFdirs[SFdirPtr + n]);
00360        w = XtWindow(selFileLists[n]);
00361        XDrawImageString(SFdisplay,
00362                       w,
00363                       SFtextGC,
00364                       SFtextX - dir->hOrigin * SFcharWidth,
00365                       SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
00366                       dir->dir, strlen(dir->dir)
00367            );
00368        SFdrawStrings(w, dir, 0, SFlistSize - 1);
00369     }
00370 }
00371 
00372 void
00373 SFdrawLists(int doScroll)
00374 {
00375     int i;
00376 
00377     for (i = 0; i < 3; i++) {
00378        SFdrawList(i, doScroll);
00379     }
00380 }
00381 
00382 static void
00383 SFinvertEntry(int n)
00384 {
00385     XFillRectangle(SFdisplay,
00386                  XtWindow(selFileLists[n]),
00387                  SFinvertGC,
00388                  SFlineToTextH,
00389                  SFcurrentInvert[n] * SFentryHeight + SFlowerY,
00390                  SFentryWidth, SFentryHeight);
00391 }
00392 
00393 static unsigned long
00394 SFscrollTimerInterval(void)
00395 {
00396     static int maxVal = 200;
00397     static int varyDist = 50;
00398     static int minDist = 50;
00399     int t;
00400     int dist;
00401 
00402     if (SFcurrentListY < SFlowerY) {
00403        dist = SFlowerY - SFcurrentListY;
00404     }
00405     else if (SFcurrentListY > SFupperY) {
00406        dist = SFcurrentListY - SFupperY;
00407     }
00408     else {
00409        return (unsigned long)1;
00410     }
00411 
00412     t = maxVal - ((maxVal / varyDist) * (dist - minDist));
00413 
00414     if (t < 1) {
00415        t = 1;
00416     }
00417 
00418     if (t > maxVal) {
00419        t = maxVal;
00420     }
00421 
00422     return (unsigned long)t;
00423 }
00424 
00425 static void
00426 SFscrollTimer(XtPointer p, XtIntervalId *id)
00427 {
00428     SFDir *dir;
00429     int save;
00430     int n;
00431 
00432     UNUSED(id);
00433     
00434     n = (int)p;
00435 
00436     fprintf(stderr, "SFscrollTimer called!\n");
00437     
00438     dir = &(SFdirs[SFdirPtr + n]);
00439     save = dir->vOrigin;
00440 
00441     if (SFcurrentListY < SFlowerY) {
00442        if (dir->vOrigin > 0) {
00443            SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin - 1);
00444        }
00445     }
00446     else if (SFcurrentListY > SFupperY) {
00447        if (dir->vOrigin < dir->nEntries - SFlistSize) {
00448            SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin + 1);
00449        }
00450     }
00451 
00452     if (dir->vOrigin != save) {
00453        if (dir->nEntries) {
00454            XawScrollbarSetThumb(selFileVScrolls[n],
00455                              (double)(dir->vOrigin) / dir->nEntries,
00456                              (double)(dir->nEntries < SFlistSize
00457                                      ? dir-> nEntries : SFlistSize)
00458                              / dir->nEntries);
00459        }
00460     }
00461 
00462     if (SFbuttonPressed) {
00463        SFscrollTimerId = XtAppAddTimeOut(SFapp,
00464                                      SFscrollTimerInterval(),
00465                                      SFscrollTimer, (XtPointer) n);
00466     }
00467 }
00468 
00469 static int
00470 SFnewInvertEntry(int n, XMotionEvent *event)
00471 {
00472     int x, y;
00473     int new;
00474     static int SFscrollTimerAdded = 0;
00475 
00476     x = event->x;
00477     y = event->y;
00478 
00479     if (SFdirPtr + n >= SFdirEnd) {
00480        return -1;
00481     }
00482     else if ((x >= 0) && (x <= SFupperX) && (y >= SFlowerY) && (y <= SFupperY)
00483        ) {
00484        SFDir *dir = &(SFdirs[SFdirPtr + n]);
00485 
00486        if (SFscrollTimerAdded) {
00487            SFscrollTimerAdded = 0;
00488            XtRemoveTimeOut(SFscrollTimerId);
00489        }
00490 
00491        new = (y - SFlowerY) / SFentryHeight;
00492        if (dir->vOrigin + new >= dir->nEntries) {
00493            return -1;
00494        }
00495        return new;
00496     }
00497     else {
00498        if (SFbuttonPressed) {
00499            SFcurrentListY = y;
00500            if (!SFscrollTimerAdded) {
00501               SFscrollTimerAdded = 1;
00502               SFscrollTimerId = XtAppAddTimeOut(SFapp,
00503                                             SFscrollTimerInterval(),
00504                                             SFscrollTimer, (XtPointer) n);
00505            }
00506        }
00507 
00508        return -1;
00509     }
00510 }
00511 
00512 void
00513 SFenterList(Widget w, int n, XEnterWindowEvent *event)
00514 {
00515     int new;
00516 
00517     UNUSED(w);
00518     
00519     /* sanity */
00520     if (SFcurrentInvert[n] != -1) {
00521        SFinvertEntry(n);
00522        SFcurrentInvert[n] = -1;
00523     }
00524 
00525     new = SFnewInvertEntry(n, (XMotionEvent *) event);
00526     if (new != -1) {
00527        SFcurrentInvert[n] = new;
00528        SFinvertEntry(n);
00529     }
00530 }
00531 
00532 void
00533 SFleaveList(Widget w, int n, XEvent *event)
00534 {
00535     UNUSED(w);
00536     UNUSED(event);
00537     
00538     if (SFcurrentInvert[n] != -1) {
00539        SFinvertEntry(n);
00540        SFcurrentInvert[n] = -1;
00541     }
00542 }
00543 
00544 void
00545 SFmotionList(Widget w, int n, XMotionEvent *event)
00546 {
00547     int new;
00548 
00549     UNUSED(w);
00550     
00551     new = SFnewInvertEntry(n, event);
00552 
00553     if (new != SFcurrentInvert[n]) {
00554        if (SFcurrentInvert[n] != -1) {
00555            SFinvertEntry(n);
00556        }
00557        SFcurrentInvert[n] = new;
00558        if (new != -1) {
00559            SFinvertEntry(n);
00560        }
00561     }
00562 }
00563 
00564 void
00565 SFvFloatSliderMovedCallback(Widget w, int n, float *fnew)
00566 {
00567     int new;
00568 
00569     new = (*fnew) * SFdirs[SFdirPtr + n].nEntries;
00570 
00571     SFvSliderMovedCallback(w, n, new);
00572 }
00573 
00574 void
00575 SFvSliderMovedCallback(Widget w, int n, int new)
00576 {
00577     int old;
00578     Window win;
00579     SFDir *dir;
00580 
00581     UNUSED(w);
00582     
00583     dir = &(SFdirs[SFdirPtr + n]);
00584 
00585     old = dir->vOrigin;
00586     dir->vOrigin = new;
00587 
00588     if (old == new) {
00589        return;
00590     }
00591 
00592     win = XtWindow(selFileLists[n]);
00593 
00594     if (ABS(new - old) < SFlistSize) {
00595        if (new > old) {
00596            XCopyArea(SFdisplay,
00597                     win,
00598                     win,
00599                     SFscrollGC,
00600                     SFlineToTextH,
00601                     SFlowerY + (new - old) * SFentryHeight,
00602                     SFentryWidth + SFlineToTextH,
00603                     (SFlistSize - (new - old)) * SFentryHeight,
00604                     SFlineToTextH, SFlowerY);
00605            XClearArea(SFdisplay,
00606                      win,
00607                      SFlineToTextH,
00608                      SFlowerY + (SFlistSize - (new - old)) *
00609                      SFentryHeight,
00610                      SFentryWidth + SFlineToTextH,
00611                      (new - old) * SFentryHeight, False);
00612            SFdrawStrings(win, dir, SFlistSize - (new - old), SFlistSize - 1);
00613        }
00614        else {
00615            XCopyArea(SFdisplay,
00616                     win,
00617                     win,
00618                     SFscrollGC,
00619                     SFlineToTextH,
00620                     SFlowerY,
00621                     SFentryWidth + SFlineToTextH,
00622                     (SFlistSize - (old - new)) * SFentryHeight,
00623                     SFlineToTextH, SFlowerY + (old - new) * SFentryHeight);
00624            XClearArea(SFdisplay,
00625                      win,
00626                      SFlineToTextH,
00627                      SFlowerY,
00628                      SFentryWidth + SFlineToTextH,
00629                      (old - new) * SFentryHeight, False);
00630            SFdrawStrings(win, dir, 0, old - new);
00631        }
00632     }
00633     else {
00634        XClearArea(SFdisplay,
00635                  win,
00636                  SFlineToTextH,
00637                  SFlowerY,
00638                  SFentryWidth + SFlineToTextH,
00639                  SFlistSize * SFentryHeight, False);
00640        SFdrawStrings(win, dir, 0, SFlistSize - 1);
00641     }
00642 }
00643 
00644 void
00645 SFvAreaSelectedCallback(Widget w, int n, int pnew)
00646 {
00647     SFDir *dir;
00648     int new;
00649 
00650     dir = &(SFdirs[SFdirPtr + n]);
00651 
00652     new = dir->vOrigin + ((double)pnew / SFvScrollHeight) * dir->nEntries;
00653 
00654     if (new > dir->nEntries - SFlistSize) {
00655        new = dir->nEntries - SFlistSize;
00656     }
00657 
00658     if (new < 0) {
00659        new = 0;
00660     }
00661 
00662     if (dir->nEntries) {
00663        float f;
00664 
00665        f = ((double)new) / dir->nEntries;
00666 
00667        XawScrollbarSetThumb(w, f,
00668                           (double)(dir->nEntries < SFlistSize
00669                                   ? dir->nEntries
00670                                   : SFlistSize)
00671                           / dir->nEntries);
00672     }
00673 
00674     SFvSliderMovedCallback(w, n, new);
00675 }
00676 
00677 void
00678 SFhSliderMovedCallback(Widget w, int n, float *new)
00679 {
00680     SFDir *dir;
00681     int save;
00682 
00683     UNUSED(w);
00684     
00685     dir = &(SFdirs[SFdirPtr + n]);
00686     save = dir->hOrigin;
00687     dir->hOrigin = (*new) * dir->nChars;
00688     if (dir->hOrigin == save) {
00689        return;
00690     }
00691 
00692     SFdrawList(n, SF_DO_NOT_SCROLL);
00693 }
00694 
00695 void
00696 SFhAreaSelectedCallback(Widget w, int n, int pnew)
00697 {
00698     SFDir *dir;
00699     int new;
00700 
00701     dir = &(SFdirs[SFdirPtr + n]);
00702 
00703     new = dir->hOrigin + (((double)pnew) / SFhScrollWidth) * dir->nChars;
00704 
00705     if (new > dir->nChars - SFcharsPerEntry) {
00706        new = dir->nChars - SFcharsPerEntry;
00707     }
00708 
00709     if (new < 0) {
00710        new = 0;
00711     }
00712 
00713     if (dir->nChars) {
00714        float f;
00715 
00716        f = (double)new / dir->nChars;
00717 
00718        XawScrollbarSetThumb(w, f,
00719                           (double)(dir->nChars < SFcharsPerEntry
00720                                   ? dir->nChars
00721                                   : SFcharsPerEntry)
00722                           / dir->nChars);
00723 
00724        SFhSliderMovedCallback(w, n, &f);
00725     }
00726 }
00727 
00728 void
00729 SFpathSliderMovedCallback(Widget w, XtPointer client_data, float *new)
00730 {
00731     SFDir *dir;
00732     int n;
00733     XawTextPosition pos;
00734     int SFdirPtrSave;
00735 
00736     UNUSED(w);
00737     UNUSED(client_data);
00738     
00739     SFdirPtrSave = SFdirPtr;
00740     SFdirPtr = (*new) * SFdirEnd;
00741     if (SFdirPtr == SFdirPtrSave) {
00742        return;
00743     }
00744 
00745     SFdrawLists(SF_DO_SCROLL);
00746 
00747     n = 2;
00748     while (SFdirPtr + n >= SFdirEnd) {
00749        n--;
00750     }
00751 
00752     dir = &(SFdirs[SFdirPtr + n]);
00753 
00754     pos = dir->path - SFcurrentPath;
00755 
00756     if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
00757        pos -= strlen(SFstartDir);
00758        if (pos < 0) {
00759            pos = 0;
00760        }
00761     }
00762 
00763     XawTextSetInsertionPoint(selFileField, pos);
00764 }
00765 
00766 void
00767 SFpathAreaSelectedCallback(Widget w, XtPointer client_data, int pnew)
00768 {
00769     int new;
00770     float f;
00771 
00772     UNUSED(client_data);
00773     
00774     new = SFdirPtr + (((double)pnew) / SFpathScrollWidth) * SFdirEnd;
00775 
00776     if (new > SFdirEnd - 3) {
00777        new = SFdirEnd - 3;
00778     }
00779 
00780     if (new < 0) {
00781        new = 0;
00782     }
00783 
00784     f = ((double)new) / SFdirEnd;
00785 
00786     XawScrollbarSetThumb(w, f,
00787                       (double)(SFdirEnd < 3 ? SFdirEnd : 3) / SFdirEnd);
00788 
00789     SFpathSliderMovedCallback(w, (XtPointer) NULL, &f);
00790 }
00791 
00792 Boolean
00793 SFworkProc(void)
00794 {
00795     SFDir *dir;
00796     SFEntry *entry;
00797 
00798     for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) {
00799        if (!(dir->nEntries)) {
00800            continue;
00801        }
00802        for (entry = &(dir->entries[dir->nEntries - 1]);
00803             entry >= dir->entries; entry--) {
00804            if (!(entry->statDone)) {
00805               (void)SFstatAndCheck(dir, entry);
00806               return False;
00807            }
00808        }
00809     }
00810 
00811     SFworkProcAdded = 0;
00812 
00813     return True;
00814 }
00815 
00816 #else
00817 /* silence `empty compilation unit' warnings */
00818 static void bar(void); static void foo() { bar(); } static void bar(void) { foo(); }
00819 #endif /* !defined(MOTIF) */