"Fossies" - the Fresh Open Source Software Archive

Member "ghostview-1.4.1/Draw.c" (15 Apr 1992, 16800 Bytes) of package /linux/misc/old/ghost/gnu/ghostview/ghostview-1.4.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
    3  *
    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.
   13  *
   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.
   21  *
   22  * Author: Erik M. van der Poel
   23  *         Software Research Associates, Inc., Tokyo, Japan
   24  *         erik@sra.co.jp
   25  */
   26 
   27 #include <stdio.h>
   28 #include "SFinternal.h"
   29 #include "xstat.h"
   30 #include <X11/StringDefs.h>
   31 #include <X11/Xaw/Scrollbar.h>
   32 
   33 #define SF_DEFAULT_FONT "9x15"
   34 
   35 #define ABS(x) (((x) < 0) ? (-(x)) : (x))
   36 
   37 typedef struct {
   38     char *fontname;
   39 } TextData, *textPtr;
   40 
   41 int SFcharWidth, SFcharAscent, SFcharHeight;
   42 
   43 int SFcurrentInvert[3] = { -1, -1, -1 };
   44 
   45 static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC;
   46 
   47 static XtResource textResources[] = {
   48     {XtNfont, XtCFont, XtRString, sizeof (char *),
   49         XtOffset(textPtr, fontname), XtRString, SF_DEFAULT_FONT},
   50 };
   51 
   52 static XFontStruct *SFfont;
   53 
   54 static int SFcurrentListY;
   55 
   56 static XtIntervalId SFscrollTimerId;
   57 
   58 SFinitFont()
   59 {
   60     TextData    *data;
   61 
   62     data = XtNew(TextData);
   63 
   64     XtGetApplicationResources(selFileForm, (XtPointer) data, textResources,
   65         XtNumber(textResources), (Arg *) NULL, 0);
   66 
   67     SFfont = XLoadQueryFont(SFdisplay, data->fontname);
   68     if (!SFfont) {
   69         SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT);
   70         if (!SFfont) {
   71             char    sbuf[256];
   72 
   73             (void) sprintf(sbuf, "XsraSelFile: can't get font %s",
   74                 SF_DEFAULT_FONT);
   75 
   76             XtAppError(SFapp, sbuf);
   77         }
   78     }
   79 
   80     SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2;
   81     SFcharAscent = SFfont->max_bounds.ascent;
   82     SFcharHeight = SFcharAscent + SFfont->max_bounds.descent;
   83 }
   84 
   85 SFcreateGC()
   86 {
   87     XGCValues   gcValues;
   88     XRectangle  rectangles[1];
   89 
   90     gcValues.foreground = SFfore;
   91 
   92     SFlineGC = XtGetGC(
   93         selFileLists[0],
   94         (XtGCMask)
   95             GCForeground        |
   96             0,
   97         &gcValues
   98     );
   99 
  100     SFscrollGC = XtGetGC(
  101         selFileLists[0],
  102         (XtGCMask)
  103             0,
  104         &gcValues
  105     );
  106 
  107     gcValues.function = GXinvert;
  108     gcValues.plane_mask = (SFfore ^ SFback);
  109 
  110     SFinvertGC = XtGetGC(
  111         selFileLists[0],
  112         (XtGCMask)
  113             GCFunction      |
  114             GCPlaneMask     |
  115             0,
  116         &gcValues
  117     );
  118 
  119     gcValues.foreground = SFfore;
  120     gcValues.background = SFback;
  121     gcValues.font = SFfont->fid;
  122 
  123     SFtextGC = XCreateGC(
  124         SFdisplay,
  125         XtWindow(selFileLists[0]),
  126         (unsigned long)
  127             GCForeground        |
  128             GCBackground        |
  129             GCFont          |
  130             0,
  131         &gcValues
  132     );
  133 
  134     rectangles[0].x = SFlineToTextH + SFbesideText;
  135     rectangles[0].y = 0;
  136     rectangles[0].width = SFcharsPerEntry * SFcharWidth;
  137     rectangles[0].height = SFupperY + 1;
  138 
  139     XSetClipRectangles(
  140         SFdisplay,
  141         SFtextGC,
  142         0,
  143         0,
  144         rectangles,
  145         1,
  146         Unsorted
  147     );
  148 }
  149 
  150 SFclearList(n, doScroll)
  151     int n;
  152     int doScroll;
  153 {
  154     SFDir   *dir;
  155 
  156     SFcurrentInvert[n] = -1;
  157 
  158     XClearWindow(SFdisplay, XtWindow(selFileLists[n]));
  159 
  160     XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs,
  161         2);
  162 
  163     if (doScroll) {
  164         dir = &(SFdirs[SFdirPtr + n]);
  165 
  166         if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars) {
  167             XawScrollbarSetThumb(
  168                 selFileVScrolls[n],
  169                 (float) (((double) dir->vOrigin) /
  170                     dir->nEntries),
  171                 (float) (((double) ((dir->nEntries < SFlistSize)
  172                     ? dir->nEntries : SFlistSize)) /
  173                     dir->nEntries)
  174             );
  175 
  176             XawScrollbarSetThumb(
  177                 selFileHScrolls[n],
  178                 (float) (((double) dir->hOrigin) / dir->nChars),
  179                 (float) (((double) ((dir->nChars <
  180                     SFcharsPerEntry) ? dir->nChars :
  181                     SFcharsPerEntry)) / dir->nChars)
  182             );
  183         } else {
  184             XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
  185                 (float) 1.0);
  186             XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
  187                 (float) 1.0);
  188         }
  189     }
  190 }
  191 
  192 static
  193 SFdeleteEntry(dir, entry)
  194     SFDir   *dir;
  195     SFEntry *entry;
  196 {
  197     register SFEntry    *e;
  198     register SFEntry    *end;
  199     int         n;
  200     int         idx;
  201 
  202     idx = entry - dir->entries;
  203 
  204     if (idx < dir->beginSelection) {
  205         dir->beginSelection--;
  206     }
  207     if (idx <= dir->endSelection) {
  208         dir->endSelection--;
  209     }
  210     if (dir->beginSelection > dir->endSelection) {
  211         dir->beginSelection = dir->endSelection = -1;
  212     }
  213 
  214     if (idx < dir->vOrigin) {
  215         dir->vOrigin--;
  216     }
  217 
  218     XtFree(entry->real);
  219 
  220     end = &(dir->entries[dir->nEntries - 1]);
  221 
  222     for (e = entry; e < end; e++) {
  223         *e = *(e + 1);
  224     }
  225 
  226     if (!(--dir->nEntries)) {
  227         return;
  228     }
  229 
  230     n = dir - &(SFdirs[SFdirPtr]);
  231     if ((n < 0) || (n > 2)) {
  232         return;
  233     }
  234 
  235     XawScrollbarSetThumb(
  236         selFileVScrolls[n],
  237         (float) (((double) dir->vOrigin) / dir->nEntries),
  238         (float) (((double) ((dir->nEntries < SFlistSize) ?
  239             dir->nEntries : SFlistSize)) / dir->nEntries)
  240     );
  241 }
  242 
  243 static
  244 SFwriteStatChar(name, last, statBuf)
  245     char        *name;
  246     int     last;
  247     struct stat *statBuf;
  248 {
  249     name[last] = SFstatChar(statBuf);
  250 }
  251 
  252 static int
  253 SFstatAndCheck(dir, entry)
  254     SFDir   *dir;
  255     SFEntry *entry;
  256 {
  257     struct stat statBuf;
  258     char        save;
  259     int     last;
  260 
  261     /*
  262      * must be restored before returning
  263      */
  264     save = *(dir->path);
  265     *(dir->path) = 0;
  266 
  267     if (!SFchdir(SFcurrentPath)) {
  268         last = strlen(entry->real) - 1;
  269         entry->real[last] = 0;
  270         entry->statDone = 1;
  271         if (
  272             (!stat(entry->real, &statBuf))
  273 
  274 #ifdef S_IFLNK
  275 
  276              || (!lstat(entry->real, &statBuf))
  277 
  278 #endif /* ndef S_IFLNK */
  279 
  280         ) {
  281             if (SFfunc) {
  282                 char *shown;
  283 
  284                 shown = NULL;
  285                 if (SFfunc(entry->real, &shown, &statBuf)) {
  286                     if (shown) {
  287                         int len;
  288 
  289                         len = strlen(shown);
  290                         entry->shown = XtMalloc(
  291                             (unsigned) (len + 2)
  292                         );
  293                         (void) strcpy(entry->shown,
  294                             shown);
  295                         SFwriteStatChar(
  296                             entry->shown,
  297                             len,
  298                             &statBuf
  299                         );
  300                         entry->shown[len + 1] = 0;
  301                     }
  302                 } else {
  303                     SFdeleteEntry(dir, entry);
  304 
  305                     *(dir->path) = save;
  306                     return 1;
  307                 }
  308             }
  309             SFwriteStatChar(entry->real, last, &statBuf);
  310         } else {
  311             entry->real[last] = ' ';
  312         }
  313     }
  314 
  315     *(dir->path) = save;
  316     return 0;
  317 }
  318 
  319 static
  320 SFdrawStrings(w, dir, from, to)
  321     register Window w;
  322     register SFDir  *dir;
  323     register int    from;
  324     register int    to;
  325 {
  326     register int        i;
  327     register SFEntry    *entry;
  328     int         x;
  329 
  330     x = SFtextX - dir->hOrigin * SFcharWidth;
  331 
  332     if (dir->vOrigin + to >= dir->nEntries) {
  333         to = dir->nEntries - dir->vOrigin - 1;
  334     }
  335     for (i = from; i <= to; i++) {
  336         entry = &(dir->entries[dir->vOrigin + i]);
  337         if (!(entry->statDone)) {
  338             if (SFstatAndCheck(dir, entry)) {
  339                 if (dir->vOrigin + to >= dir->nEntries) {
  340                     to = dir->nEntries - dir->vOrigin - 1;
  341                 }
  342                 i--;
  343                 continue;
  344             }
  345         }
  346         XDrawImageString(
  347             SFdisplay,
  348             w,
  349             SFtextGC,
  350             x,
  351             SFtextYoffset + i * SFentryHeight,
  352             entry->shown,
  353             strlen(entry->shown)
  354         );
  355         if (dir->vOrigin + i == dir->beginSelection) {
  356             XDrawLine(
  357                 SFdisplay,
  358                 w,
  359                 SFlineGC,
  360                 SFlineToTextH + 1,
  361                 SFlowerY + i * SFentryHeight,
  362                 SFlineToTextH + SFentryWidth - 2,
  363                 SFlowerY + i * SFentryHeight
  364             );
  365         }
  366         if (
  367             (dir->vOrigin + i >= dir->beginSelection) &&
  368             (dir->vOrigin + i <= dir->endSelection)
  369         ) {
  370             SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
  371                 SFlowerY + i * SFentryHeight;
  372             SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
  373                 SFlowerY + (i + 1) * SFentryHeight - 1;
  374             XDrawSegments(
  375                 SFdisplay,
  376                 w,
  377                 SFlineGC,
  378                 SFcompletionSegs,
  379                 2
  380             );
  381         }
  382         if (dir->vOrigin + i == dir->endSelection) {
  383             XDrawLine(
  384                 SFdisplay,
  385                 w,
  386                 SFlineGC,
  387                 SFlineToTextH + 1,
  388                 SFlowerY + (i + 1) * SFentryHeight - 1,
  389                 SFlineToTextH + SFentryWidth - 2,
  390                 SFlowerY + (i + 1) * SFentryHeight - 1
  391             );
  392         }
  393     }
  394 }
  395 
  396 SFdrawList(n, doScroll)
  397     int n;
  398     int doScroll;
  399 {
  400     SFDir   *dir;
  401     Window  w;
  402 
  403     SFclearList(n, doScroll);
  404 
  405     if (SFdirPtr + n < SFdirEnd) {
  406         dir = &(SFdirs[SFdirPtr + n]);
  407         w = XtWindow(selFileLists[n]);
  408         XDrawImageString(
  409             SFdisplay,
  410             w,
  411             SFtextGC,
  412             SFtextX - dir->hOrigin * SFcharWidth,
  413             SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
  414             dir->dir,
  415             strlen(dir->dir)
  416         );
  417         SFdrawStrings(w, dir, 0, SFlistSize - 1);
  418     }
  419 }
  420 
  421 SFdrawLists(doScroll)
  422     int doScroll;
  423 {
  424     int i;
  425 
  426     for (i = 0; i < 3; i++) {
  427         SFdrawList(i, doScroll);
  428     }
  429 }
  430 
  431 static
  432 SFinvertEntry(n)
  433     register int    n;
  434 {
  435     XFillRectangle(
  436         SFdisplay,
  437         XtWindow(selFileLists[n]),
  438         SFinvertGC,
  439         SFlineToTextH,
  440         SFcurrentInvert[n] * SFentryHeight + SFlowerY,
  441         SFentryWidth,
  442         SFentryHeight
  443     );
  444 }
  445 
  446 static unsigned long
  447 SFscrollTimerInterval()
  448 {
  449     static int  maxVal = 200;
  450     static int  varyDist = 50;
  451     static int  minDist = 50;
  452     int     t;
  453     int     dist;
  454 
  455     if (SFcurrentListY < SFlowerY) {
  456         dist = SFlowerY - SFcurrentListY;
  457     } else if (SFcurrentListY > SFupperY) {
  458         dist = SFcurrentListY - SFupperY;
  459     } else {
  460         return (unsigned long) 1;
  461     }
  462 
  463     t = maxVal - ((maxVal / varyDist) * (dist - minDist));
  464 
  465     if (t < 1) {
  466         t = 1;
  467     }
  468 
  469     if (t > maxVal) {
  470         t = maxVal;
  471     }
  472 
  473     return (unsigned long) t;
  474 }
  475 
  476 static void
  477 SFscrollTimer(n)
  478     int n;
  479 {
  480     SFDir   *dir;
  481     int save;
  482 
  483     dir = &(SFdirs[SFdirPtr + n]);
  484     save = dir->vOrigin;
  485 
  486     if (SFcurrentListY < SFlowerY) {
  487         if (dir->vOrigin > 0) {
  488             SFvSliderMovedCallback(selFileVScrolls[n], n,
  489                 dir->vOrigin - 1);
  490         }
  491     } else if (SFcurrentListY > SFupperY) {
  492         if (dir->vOrigin < dir->nEntries - SFlistSize) {
  493             SFvSliderMovedCallback(selFileVScrolls[n], n,
  494                 dir->vOrigin + 1);
  495         }
  496     }
  497 
  498     if (dir->vOrigin != save) {
  499         if (dir->nEntries) {
  500             XawScrollbarSetThumb(
  501             selFileVScrolls[n],
  502             (float) (((double) dir->vOrigin) / dir->nEntries),
  503             (float) (((double) ((dir->nEntries < SFlistSize) ?
  504                 dir->nEntries : SFlistSize)) / dir->nEntries)
  505             );
  506         }
  507     }
  508 
  509     if (SFbuttonPressed) {
  510         SFscrollTimerId = XtAppAddTimeOut(SFapp,
  511             SFscrollTimerInterval(), SFscrollTimer, (XtPointer) n);
  512     }
  513 }
  514 
  515 static int
  516 SFnewInvertEntry(n, event)
  517     register int        n;
  518     register XMotionEvent   *event;
  519 {
  520     register int    x, y;
  521     register int    new;
  522     static int  SFscrollTimerAdded = 0;
  523 
  524     x = event->x;
  525     y = event->y;
  526 
  527     if (SFdirPtr + n >= SFdirEnd) {
  528         return -1;
  529     } else if (
  530         (x >= 0)    && (x <= SFupperX) &&
  531         (y >= SFlowerY) && (y <= SFupperY)
  532     ) {
  533         register SFDir *dir = &(SFdirs[SFdirPtr + n]);
  534 
  535         if (SFscrollTimerAdded) {
  536             SFscrollTimerAdded = 0;
  537             XtRemoveTimeOut(SFscrollTimerId);
  538         }
  539 
  540         new = (y - SFlowerY) / SFentryHeight;
  541         if (dir->vOrigin + new >= dir->nEntries) {
  542             return -1;
  543         }
  544         return new;
  545     } else {
  546         if (SFbuttonPressed) {
  547             SFcurrentListY = y;
  548             if (!SFscrollTimerAdded) {
  549                 SFscrollTimerAdded = 1;
  550                 SFscrollTimerId = XtAppAddTimeOut(SFapp,
  551                     SFscrollTimerInterval(), SFscrollTimer,
  552                     (XtPointer) n);
  553             }
  554         }
  555 
  556         return -1;
  557     }
  558 }
  559 
  560 /* ARGSUSED */
  561 void
  562 SFenterList(w, n, event)
  563     Widget              w;
  564     register int            n;
  565     register XEnterWindowEvent  *event;
  566 {
  567     register int    new;
  568 
  569     /* sanity */
  570     if (SFcurrentInvert[n] != -1) {
  571         SFinvertEntry(n);
  572         SFcurrentInvert[n] = -1;
  573     }
  574 
  575     new = SFnewInvertEntry(n, (XMotionEvent *) event);
  576     if (new != -1) {
  577         SFcurrentInvert[n] = new;
  578         SFinvertEntry(n);
  579     }
  580 }
  581 
  582 /* ARGSUSED */
  583 void
  584 SFleaveList(w, n, event)
  585     Widget      w;
  586     register int    n;
  587     XEvent      *event;
  588 {
  589     if (SFcurrentInvert[n] != -1) {
  590         SFinvertEntry(n);
  591         SFcurrentInvert[n] = -1;
  592     }
  593 }
  594 
  595 /* ARGSUSED */
  596 void
  597 SFmotionList(w, n, event)
  598     Widget          w;
  599     register int        n;
  600     register XMotionEvent   *event;
  601 {
  602     register int    new;
  603 
  604     new = SFnewInvertEntry(n, event);
  605 
  606     if (new != SFcurrentInvert[n]) {
  607         if (SFcurrentInvert[n] != -1) {
  608             SFinvertEntry(n);
  609         }
  610         SFcurrentInvert[n] = new;
  611         if (new != -1) {
  612             SFinvertEntry(n);
  613         }
  614     }
  615 }
  616 
  617 /* ARGSUSED */
  618 void
  619 SFvFloatSliderMovedCallback(w, n, fnew)
  620     Widget  w;
  621     int n;
  622     float   *fnew;
  623 {
  624     int new;
  625 
  626     new = (*fnew) * SFdirs[SFdirPtr + n].nEntries;
  627 
  628     SFvSliderMovedCallback(w, n, new);
  629 }
  630 
  631 /* ARGSUSED */
  632 void
  633 SFvSliderMovedCallback(w, n, new)
  634     Widget  w;
  635     int n;
  636     int new;
  637 {
  638     int     old;
  639     register Window win;
  640     SFDir       *dir;
  641 
  642     dir = &(SFdirs[SFdirPtr + n]);
  643 
  644     old = dir->vOrigin;
  645     dir->vOrigin = new;
  646 
  647     if (old == new) {
  648         return;
  649     }
  650 
  651     win = XtWindow(selFileLists[n]);
  652 
  653     if (ABS(new - old) < SFlistSize) {
  654         if (new > old) {
  655             XCopyArea(
  656                 SFdisplay,
  657                 win,
  658                 win,
  659                 SFscrollGC,
  660                 SFlineToTextH,
  661                 SFlowerY + (new - old) * SFentryHeight,
  662                 SFentryWidth + SFlineToTextH,
  663                 (SFlistSize - (new - old)) * SFentryHeight,
  664                 SFlineToTextH,
  665                 SFlowerY
  666             );
  667             XClearArea(
  668                 SFdisplay,
  669                 win,
  670                 SFlineToTextH,
  671                 SFlowerY + (SFlistSize - (new - old)) *
  672                     SFentryHeight,
  673                 SFentryWidth + SFlineToTextH,
  674                 (new - old) * SFentryHeight,
  675                 False
  676             );
  677             SFdrawStrings(win, dir, SFlistSize - (new - old),
  678                 SFlistSize - 1);
  679         } else {
  680             XCopyArea(
  681                 SFdisplay,
  682                 win,
  683                 win,
  684                 SFscrollGC,
  685                 SFlineToTextH,
  686                 SFlowerY,
  687                 SFentryWidth + SFlineToTextH,
  688                 (SFlistSize - (old - new)) * SFentryHeight,
  689                 SFlineToTextH,
  690                 SFlowerY + (old - new) * SFentryHeight
  691             );
  692             XClearArea(
  693                 SFdisplay,
  694                 win,
  695                 SFlineToTextH,
  696                 SFlowerY,
  697                 SFentryWidth + SFlineToTextH,
  698                 (old - new) * SFentryHeight,
  699                 False
  700             );
  701             SFdrawStrings(win, dir, 0, old - new);
  702         }
  703     } else {
  704         XClearArea(
  705             SFdisplay,
  706             win,
  707             SFlineToTextH,
  708             SFlowerY,
  709             SFentryWidth + SFlineToTextH,
  710             SFlistSize * SFentryHeight,
  711             False
  712         );
  713         SFdrawStrings(win, dir, 0, SFlistSize - 1);
  714     }
  715 }
  716 
  717 /* ARGSUSED */
  718 void
  719 SFvAreaSelectedCallback(w, n, pnew)
  720     Widget  w;
  721     int n;
  722     int pnew;
  723 {
  724     SFDir   *dir;
  725     int new;
  726 
  727     dir = &(SFdirs[SFdirPtr + n]);
  728 
  729     new = dir->vOrigin +
  730         (((double) pnew) / SFvScrollHeight) * dir->nEntries;
  731 
  732     if (new > dir->nEntries - SFlistSize) {
  733         new = dir->nEntries - SFlistSize;
  734     }
  735 
  736     if (new < 0) {
  737         new = 0;
  738     }
  739 
  740     if (dir->nEntries) {
  741         float   f;
  742 
  743         f = ((double) new) / dir->nEntries;
  744 
  745         XawScrollbarSetThumb(
  746             w,
  747             f,
  748             (float) (((double) ((dir->nEntries < SFlistSize) ?
  749                 dir->nEntries : SFlistSize)) / dir->nEntries)
  750         );
  751     }
  752 
  753     SFvSliderMovedCallback(w, n, new);
  754 }
  755 
  756 /* ARGSUSED */
  757 void
  758 SFhSliderMovedCallback(w, n, new)
  759     Widget  w;
  760     int n;
  761     float   *new;
  762 {
  763     SFDir   *dir;
  764     int save;
  765 
  766     dir = &(SFdirs[SFdirPtr + n]);
  767     save = dir->hOrigin;
  768     dir->hOrigin = (*new) * dir->nChars;
  769     if (dir->hOrigin == save) {
  770         return;
  771     }
  772 
  773     SFdrawList(n, SF_DO_NOT_SCROLL);
  774 }
  775 
  776 /* ARGSUSED */
  777 void
  778 SFhAreaSelectedCallback(w, n, pnew)
  779     Widget  w;
  780     int n;
  781     int pnew;
  782 {
  783     SFDir   *dir;
  784     int new;
  785 
  786     dir = &(SFdirs[SFdirPtr + n]);
  787 
  788     new = dir->hOrigin +
  789         (((double) pnew) / SFhScrollWidth) * dir->nChars;
  790 
  791     if (new > dir->nChars - SFcharsPerEntry) {
  792         new = dir->nChars - SFcharsPerEntry;
  793     }
  794 
  795     if (new < 0) {
  796         new = 0;
  797     }
  798 
  799     if (dir->nChars) {
  800         float   f;
  801 
  802         f = ((double) new) / dir->nChars;
  803 
  804         XawScrollbarSetThumb(
  805             w,
  806             f,
  807             (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
  808                 dir->nChars : SFcharsPerEntry)) / dir->nChars)
  809         );
  810 
  811         SFhSliderMovedCallback(w, n, &f);
  812     }
  813 }
  814 
  815 /* ARGSUSED */
  816 void
  817 SFpathSliderMovedCallback(w, client_data, new)
  818     Widget      w;
  819     XtPointer   client_data;
  820     float   *new;
  821 {
  822     SFDir       *dir;
  823     int     n;
  824     XawTextPosition pos;
  825     int SFdirPtrSave;
  826 
  827     SFdirPtrSave = SFdirPtr;
  828     SFdirPtr = (*new) * SFdirEnd;
  829     if (SFdirPtr == SFdirPtrSave) {
  830         return;
  831     }
  832 
  833     SFdrawLists(SF_DO_SCROLL);
  834 
  835     n = 2;
  836     while (SFdirPtr + n >= SFdirEnd) {
  837         n--;
  838     }
  839 
  840     dir = &(SFdirs[SFdirPtr + n]);
  841 
  842     pos = dir->path - SFcurrentPath;
  843 
  844     if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
  845         pos -= strlen(SFstartDir);
  846         if (pos < 0) {
  847             pos = 0;
  848         }
  849     }
  850 
  851     XawTextSetInsertionPoint(selFileField, pos);
  852 }
  853 
  854 /* ARGSUSED */
  855 
  856 void
  857 SFpathAreaSelectedCallback(w, client_data, pnew)
  858     Widget      w;
  859     XtPointer   client_data;
  860     int     pnew;
  861 {
  862     int new;
  863     float   f;
  864 
  865     new = SFdirPtr + (((double) pnew) / SFpathScrollWidth) * SFdirEnd;
  866 
  867     if (new > SFdirEnd - 3) {
  868         new = SFdirEnd - 3;
  869     }
  870 
  871     if (new < 0) {
  872         new = 0;
  873     }
  874 
  875     f = ((double) new) / SFdirEnd;
  876 
  877     XawScrollbarSetThumb(
  878         w,
  879         f,
  880         (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
  881             SFdirEnd)
  882     );
  883 
  884     SFpathSliderMovedCallback(w, (XtPointer) NULL, &f);
  885 }
  886 
  887 Boolean
  888 SFworkProc()
  889 {
  890     register SFDir      *dir;
  891     register SFEntry    *entry;
  892 
  893     for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) {
  894         if (!(dir->nEntries)) {
  895             continue;
  896         }
  897         for (
  898             entry = &(dir->entries[dir->nEntries - 1]);
  899             entry >= dir->entries;
  900             entry--
  901         ) {
  902             if (!(entry->statDone)) {
  903                 (void) SFstatAndCheck(dir, entry);
  904                 return False;
  905             }
  906         }
  907     }
  908 
  909     SFworkProcAdded = 0;
  910 
  911     return True;
  912 }