home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / s / stex2-18.zip / SeeTeX / Xtex / Draw.c < prev    next >
C/C++ Source or Header  |  1992-05-05  |  17KB  |  934 lines

  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 <sys/stat.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.         (u_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.     switch (statBuf->st_mode & S_IFMT) {
  250.     case S_IFDIR:
  251.         name[last] = '/';
  252.         break;
  253.     case S_IFREG:
  254.         if (statBuf->st_mode & 0111) {
  255.             name[last] = '*';
  256.         } else {
  257.             name[last] = ' ';
  258.         }
  259.         break;
  260.  
  261. #ifdef S_IFSOCK
  262.     case S_IFSOCK:
  263.         name[last] = '=';
  264.         break;
  265. #endif /* def S_IFSOCK */
  266.  
  267.     default:
  268.         name[last] = ' ';
  269.         break;
  270.     }
  271. }
  272.  
  273. static int
  274. SFstatAndCheck(dir, entry)
  275.     SFDir    *dir;
  276.     SFEntry    *entry;
  277. {
  278.     struct stat    statBuf;
  279.     char        save;
  280.     int        last;
  281.  
  282.     /*
  283.      * must be restored before returning
  284.      */
  285.     save = *(dir->path);
  286.     *(dir->path) = 0;
  287.  
  288.     if (!SFchdir(SFcurrentPath)) {
  289.         last = strlen(entry->real) - 1;
  290.         entry->real[last] = 0;
  291.         entry->statDone = 1;
  292.         if (
  293.             (!stat(entry->real, &statBuf))
  294.  
  295. #ifdef S_IFLNK
  296.  
  297.              || (!lstat(entry->real, &statBuf))
  298.  
  299. #endif /* ndef S_IFLNK */
  300.  
  301.         ) {
  302.             if (SFfunc) {
  303.                 char *shown;
  304.  
  305.                 shown = NULL;
  306.                 if (SFfunc(entry->real, &shown, &statBuf)) {
  307.                     if (shown) {
  308.                         int len;
  309.  
  310.                         len = strlen(shown);
  311.                         entry->shown = XtMalloc(
  312.                             (unsigned) (len + 2)
  313.                         );
  314.                         (void) strcpy(entry->shown,
  315.                             shown);
  316.                         SFwriteStatChar(
  317.                             entry->shown,
  318.                             len,
  319.                             &statBuf
  320.                         );
  321.                         entry->shown[len + 1] = 0;
  322.                     }
  323.                 } else {
  324.                     SFdeleteEntry(dir, entry);
  325.  
  326.                     *(dir->path) = save;
  327.                     return 1;
  328.                 }
  329.             }
  330.             SFwriteStatChar(entry->real, last, &statBuf);
  331.         } else {
  332.             entry->real[last] = ' ';
  333.         }
  334.     }
  335.  
  336.     *(dir->path) = save;
  337.     return 0;
  338. }
  339.  
  340. static
  341. SFdrawStrings(w, dir, from, to)
  342.     register Window    w;
  343.     register SFDir    *dir;
  344.     register int    from;
  345.     register int    to;
  346. {
  347.     register int        i;
  348.     register SFEntry    *entry;
  349.     int            x;
  350.  
  351.     x = SFtextX - dir->hOrigin * SFcharWidth;
  352.  
  353.     if (dir->vOrigin + to >= dir->nEntries) {
  354.         to = dir->nEntries - dir->vOrigin - 1;
  355.     }
  356.     for (i = from; i <= to; i++) {
  357.         entry = &(dir->entries[dir->vOrigin + i]);
  358.         if (!(entry->statDone)) {
  359.             if (SFstatAndCheck(dir, entry)) {
  360.                 if (dir->vOrigin + to >= dir->nEntries) {
  361.                     to = dir->nEntries - dir->vOrigin - 1;
  362.                 }
  363.                 i--;
  364.                 continue;
  365.             }
  366.         }
  367.         XDrawImageString(
  368.             SFdisplay,
  369.             w,
  370.             SFtextGC,
  371.             x,
  372.             SFtextYoffset + i * SFentryHeight,
  373.             entry->shown,
  374.             strlen(entry->shown)
  375.         );
  376.         if (dir->vOrigin + i == dir->beginSelection) {
  377.             XDrawLine(
  378.                 SFdisplay,
  379.                 w,
  380.                 SFlineGC,
  381.                 SFlineToTextH + 1,
  382.                 SFlowerY + i * SFentryHeight,
  383.                 SFlineToTextH + SFentryWidth - 2,
  384.                 SFlowerY + i * SFentryHeight
  385.             );
  386.         }
  387.         if (
  388.             (dir->vOrigin + i >= dir->beginSelection) &&
  389.             (dir->vOrigin + i <= dir->endSelection)
  390.         ) {
  391.             SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
  392.                 SFlowerY + i * SFentryHeight;
  393.             SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
  394.                 SFlowerY + (i + 1) * SFentryHeight - 1;
  395.             XDrawSegments(
  396.                 SFdisplay,
  397.                 w,
  398.                 SFlineGC,
  399.                 SFcompletionSegs,
  400.                 2
  401.             );
  402.         }
  403.         if (dir->vOrigin + i == dir->endSelection) {
  404.             XDrawLine(
  405.                 SFdisplay,
  406.                 w,
  407.                 SFlineGC,
  408.                 SFlineToTextH + 1,
  409.                 SFlowerY + (i + 1) * SFentryHeight - 1,
  410.                 SFlineToTextH + SFentryWidth - 2,
  411.                 SFlowerY + (i + 1) * SFentryHeight - 1
  412.             );
  413.         }
  414.     }
  415. }
  416.  
  417. SFdrawList(n, doScroll)
  418.     int    n;
  419.     int    doScroll;
  420. {
  421.     SFDir    *dir;
  422.     Window    w;
  423.  
  424.     SFclearList(n, doScroll);
  425.  
  426.     if (SFdirPtr + n < SFdirEnd) {
  427.         dir = &(SFdirs[SFdirPtr + n]);
  428.         w = XtWindow(selFileLists[n]);
  429.         XDrawImageString(
  430.             SFdisplay,
  431.             w,
  432.             SFtextGC,
  433.             SFtextX - dir->hOrigin * SFcharWidth,
  434.             SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
  435.             dir->dir,
  436.             strlen(dir->dir)
  437.         );
  438.         SFdrawStrings(w, dir, 0, SFlistSize - 1);
  439.     }
  440. }
  441.  
  442. SFdrawLists(doScroll)
  443.     int    doScroll;
  444. {
  445.     int    i;
  446.  
  447.     for (i = 0; i < 3; i++) {
  448.         SFdrawList(i, doScroll);
  449.     }
  450. }
  451.  
  452. static
  453. SFinvertEntry(n)
  454.     register int    n;
  455. {
  456.     XFillRectangle(
  457.         SFdisplay,
  458.         XtWindow(selFileLists[n]),
  459.         SFinvertGC,
  460.         SFlineToTextH,
  461.         SFcurrentInvert[n] * SFentryHeight + SFlowerY,
  462.         SFentryWidth,
  463.         SFentryHeight
  464.     );
  465. }
  466.  
  467. static unsigned long
  468. SFscrollTimerInterval()
  469. {
  470.     static int    maxVal = 200;
  471.     static int    varyDist = 50;
  472.     static int    minDist = 50;
  473.     int        t;
  474.     int        dist;
  475.  
  476.     if (SFcurrentListY < SFlowerY) {
  477.         dist = SFlowerY - SFcurrentListY;
  478.     } else if (SFcurrentListY > SFupperY) {
  479.         dist = SFcurrentListY - SFupperY;
  480.     } else {
  481.         return (unsigned long) 1;
  482.     }
  483.  
  484.     t = maxVal - ((maxVal / varyDist) * (dist - minDist));
  485.  
  486.     if (t < 1) {
  487.         t = 1;
  488.     }
  489.  
  490.     if (t > maxVal) {
  491.         t = maxVal;
  492.     }
  493.  
  494.     return (unsigned long) t;
  495. }
  496.  
  497. static void
  498. SFscrollTimer(n)
  499.     int    n;
  500. {
  501.     SFDir    *dir;
  502.     int    save;
  503.  
  504.     dir = &(SFdirs[SFdirPtr + n]);
  505.     save = dir->vOrigin;
  506.  
  507.     if (SFcurrentListY < SFlowerY) {
  508.         if (dir->vOrigin > 0) {
  509.             SFvSliderMovedCallback(selFileVScrolls[n], n,
  510.                 dir->vOrigin - 1);
  511.         }
  512.     } else if (SFcurrentListY > SFupperY) {
  513.         if (dir->vOrigin < dir->nEntries - SFlistSize) {
  514.             SFvSliderMovedCallback(selFileVScrolls[n], n,
  515.                 dir->vOrigin + 1);
  516.         }
  517.     }
  518.  
  519.     if (dir->vOrigin != save) {
  520.         if (dir->nEntries) {
  521.             XawScrollbarSetThumb(
  522.             selFileVScrolls[n],
  523.             (float) (((double) dir->vOrigin) / dir->nEntries),
  524.             (float) (((double) ((dir->nEntries < SFlistSize) ?
  525.                 dir->nEntries : SFlistSize)) / dir->nEntries)
  526.             );
  527.         }
  528.     }
  529.  
  530.     if (SFbuttonPressed) {
  531.         SFscrollTimerId = XtAppAddTimeOut(SFapp,
  532.             SFscrollTimerInterval(), SFscrollTimer, (XtPointer) n);
  533.     }
  534. }
  535.  
  536. static int
  537. SFnewInvertEntry(n, event)
  538.     register int        n;
  539.     register XMotionEvent    *event;
  540. {
  541.     register int    x, y;
  542.     register int    new;
  543.     static int    SFscrollTimerAdded = 0;
  544.  
  545.     x = event->x;
  546.     y = event->y;
  547.  
  548.     if (SFdirPtr + n >= SFdirEnd) {
  549.         return -1;
  550.     } else if (
  551.         (x >= 0)    && (x <= SFupperX) &&
  552.         (y >= SFlowerY)    && (y <= SFupperY)
  553.     ) {
  554.         register SFDir *dir = &(SFdirs[SFdirPtr + n]);
  555.  
  556.         if (SFscrollTimerAdded) {
  557.             SFscrollTimerAdded = 0;
  558.             XtRemoveTimeOut(SFscrollTimerId);
  559.         }
  560.  
  561.         new = (y - SFlowerY) / SFentryHeight;
  562.         if (dir->vOrigin + new >= dir->nEntries) {
  563.             return -1;
  564.         }
  565.         return new;
  566.     } else {
  567.         if (SFbuttonPressed) {
  568.             SFcurrentListY = y;
  569.             if (!SFscrollTimerAdded) {
  570.                 SFscrollTimerAdded = 1;
  571.                 SFscrollTimerId = XtAppAddTimeOut(SFapp,
  572.                     SFscrollTimerInterval(), SFscrollTimer,
  573.                     (XtPointer) n);
  574.             }
  575.         }
  576.  
  577.         return -1;
  578.     }
  579. }
  580.  
  581. /* ARGSUSED */
  582. void
  583. SFenterList(w, n, event)
  584.     Widget                w;
  585.     register int            n;
  586.     register XEnterWindowEvent    *event;
  587. {
  588.     register int    new;
  589.  
  590.     /* sanity */
  591.     if (SFcurrentInvert[n] != -1) {
  592.         SFinvertEntry(n);
  593.         SFcurrentInvert[n] = -1;
  594.     }
  595.  
  596.     new = SFnewInvertEntry(n, (XMotionEvent *) event);
  597.     if (new != -1) {
  598.         SFcurrentInvert[n] = new;
  599.         SFinvertEntry(n);
  600.     }
  601. }
  602.  
  603. /* ARGSUSED */
  604. void
  605. SFleaveList(w, n, event)
  606.     Widget        w;
  607.     register int    n;
  608.     XEvent        *event;
  609. {
  610.     if (SFcurrentInvert[n] != -1) {
  611.         SFinvertEntry(n);
  612.         SFcurrentInvert[n] = -1;
  613.     }
  614. }
  615.  
  616. /* ARGSUSED */
  617. void
  618. SFmotionList(w, n, event)
  619.     Widget            w;
  620.     register int        n;
  621.     register XMotionEvent    *event;
  622. {
  623.     register int    new;
  624.  
  625.     new = SFnewInvertEntry(n, event);
  626.  
  627.     if (new != SFcurrentInvert[n]) {
  628.         if (SFcurrentInvert[n] != -1) {
  629.             SFinvertEntry(n);
  630.         }
  631.         SFcurrentInvert[n] = new;
  632.         if (new != -1) {
  633.             SFinvertEntry(n);
  634.         }
  635.     }
  636. }
  637.  
  638. /* ARGSUSED */
  639. void
  640. SFvFloatSliderMovedCallback(w, n, fnew)
  641.     Widget    w;
  642.     int    n;
  643.     float    *fnew;
  644. {
  645.     int    new;
  646.  
  647.     new = (*fnew) * SFdirs[SFdirPtr + n].nEntries;
  648.  
  649.     SFvSliderMovedCallback(w, n, new);
  650. }
  651.  
  652. /* ARGSUSED */
  653. void
  654. SFvSliderMovedCallback(w, n, new)
  655.     Widget    w;
  656.     int    n;
  657.     int    new;
  658. {
  659.     int        old;
  660.     register Window    win;
  661.     SFDir        *dir;
  662.  
  663.     dir = &(SFdirs[SFdirPtr + n]);
  664.  
  665.     old = dir->vOrigin;
  666.     dir->vOrigin = new;
  667.  
  668.     if (old == new) {
  669.         return;
  670.     }
  671.  
  672.     win = XtWindow(selFileLists[n]);
  673.  
  674.     if (ABS(new - old) < SFlistSize) {
  675.         if (new > old) {
  676.             XCopyArea(
  677.                 SFdisplay,
  678.                 win,
  679.                 win,
  680.                 SFscrollGC,
  681.                 SFlineToTextH,
  682.                 SFlowerY + (new - old) * SFentryHeight,
  683.                 SFentryWidth + SFlineToTextH,
  684.                 (SFlistSize - (new - old)) * SFentryHeight,
  685.                 SFlineToTextH,
  686.                 SFlowerY
  687.             );
  688.             XClearArea(
  689.                 SFdisplay,
  690.                 win,
  691.                 SFlineToTextH,
  692.                 SFlowerY + (SFlistSize - (new - old)) *
  693.                     SFentryHeight,
  694.                 SFentryWidth + SFlineToTextH,
  695.                 (new - old) * SFentryHeight,
  696.                 False
  697.             );
  698.             SFdrawStrings(win, dir, SFlistSize - (new - old),
  699.                 SFlistSize - 1);
  700.         } else {
  701.             XCopyArea(
  702.                 SFdisplay,
  703.                 win,
  704.                 win,
  705.                 SFscrollGC,
  706.                 SFlineToTextH,
  707.                 SFlowerY,
  708.                 SFentryWidth + SFlineToTextH,
  709.                 (SFlistSize - (old - new)) * SFentryHeight,
  710.                 SFlineToTextH,
  711.                 SFlowerY + (old - new) * SFentryHeight
  712.             );
  713.             XClearArea(
  714.                 SFdisplay,
  715.                 win,
  716.                 SFlineToTextH,
  717.                 SFlowerY,
  718.                 SFentryWidth + SFlineToTextH,
  719.                 (old - new) * SFentryHeight,
  720.                 False
  721.             );
  722.             SFdrawStrings(win, dir, 0, old - new);
  723.         }
  724.     } else {
  725.         XClearArea(
  726.             SFdisplay,
  727.             win,
  728.             SFlineToTextH,
  729.             SFlowerY,
  730.             SFentryWidth + SFlineToTextH,
  731.             SFlistSize * SFentryHeight,
  732.             False
  733.         );
  734.         SFdrawStrings(win, dir, 0, SFlistSize - 1);
  735.     }
  736. }
  737.  
  738. /* ARGSUSED */
  739. void
  740. SFvAreaSelectedCallback(w, n, pnew)
  741.     Widget    w;
  742.     int    n;
  743.     int    pnew;
  744. {
  745.     SFDir    *dir;
  746.     int    new;
  747.  
  748.     dir = &(SFdirs[SFdirPtr + n]);
  749.  
  750.     new = dir->vOrigin +
  751.         (((double) pnew) / SFvScrollHeight) * dir->nEntries;
  752.  
  753.     if (new > dir->nEntries - SFlistSize) {
  754.         new = dir->nEntries - SFlistSize;
  755.     }
  756.  
  757.     if (new < 0) {
  758.         new = 0;
  759.     }
  760.  
  761.     if (dir->nEntries) {
  762.         float    f;
  763.  
  764.         f = ((double) new) / dir->nEntries;
  765.  
  766.         XawScrollbarSetThumb(
  767.             w,
  768.             f,
  769.             (float) (((double) ((dir->nEntries < SFlistSize) ?
  770.                 dir->nEntries : SFlistSize)) / dir->nEntries)
  771.         );
  772.     }
  773.  
  774.     SFvSliderMovedCallback(w, n, new);
  775. }
  776.  
  777. /* ARGSUSED */
  778. void
  779. SFhSliderMovedCallback(w, n, new)
  780.     Widget    w;
  781.     int    n;
  782.     float    *new;
  783. {
  784.     SFDir    *dir;
  785.     int    save;
  786.  
  787.     dir = &(SFdirs[SFdirPtr + n]);
  788.     save = dir->hOrigin;
  789.     dir->hOrigin = (*new) * dir->nChars;
  790.     if (dir->hOrigin == save) {
  791.         return;
  792.     }
  793.  
  794.     SFdrawList(n, SF_DO_NOT_SCROLL);
  795. }
  796.  
  797. /* ARGSUSED */
  798. void
  799. SFhAreaSelectedCallback(w, n, pnew)
  800.     Widget    w;
  801.     int    n;
  802.     int    pnew;
  803. {
  804.     SFDir    *dir;
  805.     int    new;
  806.  
  807.     dir = &(SFdirs[SFdirPtr + n]);
  808.  
  809.     new = dir->hOrigin +
  810.         (((double) pnew) / SFhScrollWidth) * dir->nChars;
  811.  
  812.     if (new > dir->nChars - SFcharsPerEntry) {
  813.         new = dir->nChars - SFcharsPerEntry;
  814.     }
  815.  
  816.     if (new < 0) {
  817.         new = 0;
  818.     }
  819.  
  820.     if (dir->nChars) {
  821.         float    f;
  822.  
  823.         f = ((double) new) / dir->nChars;
  824.  
  825.         XawScrollbarSetThumb(
  826.             w,
  827.             f,
  828.             (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
  829.                 dir->nChars : SFcharsPerEntry)) / dir->nChars)
  830.         );
  831.  
  832.         SFhSliderMovedCallback(w, n, &f);
  833.     }
  834. }
  835.  
  836. /* ARGSUSED */
  837. void
  838. SFpathSliderMovedCallback(w, client_data, new)
  839.     Widget        w;
  840.     XtPointer    client_data;
  841.     float    *new;
  842. {
  843.     SFDir        *dir;
  844.     int        n;
  845.     XawTextPosition    pos;
  846.     int    SFdirPtrSave;
  847.  
  848.     SFdirPtrSave = SFdirPtr;
  849.     SFdirPtr = (*new) * SFdirEnd;
  850.     if (SFdirPtr == SFdirPtrSave) {
  851.         return;
  852.     }
  853.  
  854.     SFdrawLists(SF_DO_SCROLL);
  855.  
  856.     n = 2;
  857.     while (SFdirPtr + n >= SFdirEnd) {
  858.         n--;
  859.     }
  860.  
  861.     dir = &(SFdirs[SFdirPtr + n]);
  862.  
  863.     pos = dir->path - SFcurrentPath;
  864.  
  865.     if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
  866.         pos -= strlen(SFstartDir);
  867.         if (pos < 0) {
  868.             pos = 0;
  869.         }
  870.     }
  871.  
  872.     XawTextSetInsertionPoint(selFileField, pos);
  873. }
  874.  
  875. /* ARGSUSED */
  876.  
  877. void
  878. SFpathAreaSelectedCallback(w, client_data, pnew)
  879.     Widget        w;
  880.     XtPointer    client_data;
  881.     int        pnew;
  882. {
  883.     int    new;
  884.     float    f;
  885.  
  886.     new = SFdirPtr + (((double) pnew) / SFpathScrollWidth) * SFdirEnd;
  887.  
  888.     if (new > SFdirEnd - 3) {
  889.         new = SFdirEnd - 3;
  890.     }
  891.  
  892.     if (new < 0) {
  893.         new = 0;
  894.     }
  895.  
  896.     f = ((double) new) / SFdirEnd;
  897.  
  898.     XawScrollbarSetThumb(
  899.         w,
  900.         f,
  901.         (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
  902.             SFdirEnd)
  903.     );
  904.  
  905.     SFpathSliderMovedCallback(w, (XtPointer) NULL, &f);
  906. }
  907.  
  908. Boolean
  909. SFworkProc()
  910. {
  911.     register SFDir        *dir;
  912.     register SFEntry    *entry;
  913.  
  914.     for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) {
  915.         if (!(dir->nEntries)) {
  916.             continue;
  917.         }
  918.         for (
  919.             entry = &(dir->entries[dir->nEntries - 1]);
  920.             entry >= dir->entries;
  921.             entry--
  922.         ) {
  923.             if (!(entry->statDone)) {
  924.                 (void) SFstatAndCheck(dir, entry);
  925.                 return False;
  926.             }
  927.         }
  928.     }
  929.  
  930.     SFworkProcAdded = 0;
  931.  
  932.     return True;
  933. }
  934.