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