\input wbuildmac.tex
\Class{XfwfSlider4}
 The Slider4 class is equal to the Slider2 class, except for the
addition of a sash in the lower right corner of the thumb, with which
the thumb can be resized. Since this adds two more dgrees of freedom
to the widget (viz., width and height in addition to horizontal and
vertical position), the name becomes ``Slider4.'' A callback function
is called when the thumb is being resized and another one when the
resizing has finished.

The control area in the lower right corner of the thumb looks like a
triangular button. The actions that already existed in the Slider2
class now also check if the mouse is on that button and resize instead
of drag the button in response.



\Publicvars
\Table{XfwfSlider4}
XtNsashColor&XtCSashColor&Pixel &XtDefaultBackground \cr
XtNsashPixmap&XtCSashPixmap&Pixmap &NULL \cr
XtNsashFrameType&XtCSashFrameType&FrameType &XfwfRaised \cr
XtNsashFrameWidth&XtCSashFrameWidth&Dimension &2 \cr
XtNstretchCallback&XtCStretchCallback&Callback&NULL \cr
XtNresizeCallback&XtCResizeCallback&Callback&NULL \cr
\endTable
\Section
\Publicvar{XtNsashColor}
 The existence of another area in the widget means that that there
are additional resources needed for determining how it will look. The
first of these resources is {\tt triangleColor}, which gives the color of
the triangle, unless {\tt trianglePixmap} is also defined. In that case
the pixmap will be used to tile the triangle with.



\HCode
\Code
Pixel  sashColor = {\langle}String{\rangle}XtDefaultBackground \endCode
\endHCode


\Section
\Publicvar{XtNsashPixmap}
 When the {\tt sashPixmap} resource is set, it overrides the {\tt sashColor}
resource and causes the triangle to be tiled with a pixmap.



\HCode
\Code
Pixmap  sashPixmap = NULL \endCode
\endHCode


\Section
\Publicvar{XtNsashFrameType}
 The triangle also has a frame in one of the four types {\tt XfwfRaised},
{\tt XfwfSunken}, {\tt XfwfLedged} or {\tt XfwfChiseled}. This frame is also influenced
by the setting of the {\tt shadowScheme}, {\tt lightColor}, etc., resources
(see the Frame class). The type of frame is set with {\tt sashFrameType}.



\HCode
\Code
FrameType  sashFrameType = XfwfRaised \endCode
\endHCode


\Section
\Publicvar{XtNsashFrameWidth}
 The width of the frame around the sash:



\HCode
\Code
Dimension  sashFrameWidth = 2 \endCode
\endHCode


\Section
\Publicvar{XtNstretchCallback}
 When the thumb is being resized a callback is invoked with every
movement of the mouse. In the {\tt call{\underline}data} argument of the callback
function a pointer to a static {\tt SliderInfo} structure is passed,
containing the new (position and) size of the thumb.

To ensure smooth mouse action, only applications that can react to the
resizing fast enough should use this callback.



\HCode
\Code
{\langle}Callback{\rangle} XtCallbackList  stretchCallback = NULL \endCode
\endHCode


\Section
\Publicvar{XtNresizeCallback}
 When the resize operation has finished, another callback is called,
with the same argument.



\HCode
\Code
{\langle}Callback{\rangle} XtCallbackList  resizeCallback = NULL \endCode
\endHCode


\End\Table{XfwfSlider2}
XtNthumbColor&XtCThumbColor&Pixel &XtDefaultBackground \cr
XtNthumbPixmap&XtCThumbPixmap&Pixmap &NULL \cr
XtNminsize&XtCMinsize&Dimension &20 \cr
XtNthumbFrameWidth&XtCThumbFrameWidth&Dimension &2 \cr
XtNthumbFrameType&XtCThumbFrameType&FrameType &XfwfRaised \cr
XtNdragCallback&XtCDragCallback&Callback&NULL \cr
XtNdropCallback&XtCDropCallback&Callback&NULL \cr
XtNjumpCallback&XtCJumpCallback&Callback&NULL \cr
\endTable
\Table{XfwfLabel}
XtNlabel&XtCLabel&String &NULL \cr
XtNfont&XtCFont&FontStruct&XtDefaultFont \cr
XtNforeground&XtCForeground&Pixel &XtDefaultForeground \cr
XtNalignment&XtCAlignment&Alignment &0 \cr
XtNmargin&XtCMargin&Int &2 \cr
XtNshrinkToFit&XtCShrinkToFit&Boolean &False \cr
\endTable
\Table{XfwfBoard}
XtNcursor&XtCCursor&Cursor &None \cr
XtNabs{\underline}x&XtCAbs{\underline}x&Int &0 \cr
XtNrel{\underline}x&XtCRel{\underline}x&Float &"0.0"\cr
XtNabs{\underline}y&XtCAbs{\underline}y&Int &0 \cr
XtNrel{\underline}y&XtCRel{\underline}y&Float &"0.0"\cr
XtNabs{\underline}width&XtCAbs{\underline}width&Int &0 \cr
XtNrel{\underline}width&XtCRel{\underline}width&Float &"1.0"\cr
XtNabs{\underline}height&XtCAbs{\underline}height&Int &0 \cr
XtNrel{\underline}height&XtCRel{\underline}height&Float &"1.0"\cr
XtNhunit&XtCHunit&Int &1 \cr
XtNvunit&XtCVunit&Int &1 \cr
XtNlocation&XtCLocation&String &NULL \cr
\endTable
\Table{XfwfFrame}
XtNframeType&XtCFrameType&FrameType &XfwfRaised \cr
XtNframeWidth&XtCFrameWidth&Dimension &0 \cr
XtNframeOffset&XtCFrameOffset&Dimension &0 \cr
XtNshadowScheme&XtCShadowScheme&ShadowScheme &XfwfAuto \cr
XtNlightColor&XtCLightColor&Pixel &XtDefaultBackground \cr
XtNdarkColor&XtCDarkColor&Pixel &XtDefaultForeground \cr
XtNlightStipple&XtCLightStipple&Bitmap &NULL \cr
XtNdarkStipple&XtCDarkStipple&Bitmap &NULL \cr
\endTable
\Table{XfwfCommon}
XtNhighlighted&XtCHighlighted&Boolean &False \cr
XtNselected&XtCSelected&Boolean &False \cr
XtNtext&XtCText&String &NULL \cr
XtNhandlers&XtCHandlers&Program *&NULL \cr
\endTable
\Table{Composite}
XtNchildren&XtCChildren&WidgetList &NULL \cr
insertPosition&XtCInsertPosition&XTOrderProc &NULL \cr
numChildren&XtCNumChildren&Cardinal &0 \cr
\endTable
\Table{Core}
XtNx&XtCX&Position &0 \cr
XtNy&XtCY&Position &0 \cr
XtNwidth&XtCWidth&Dimension &0 \cr
XtNheight&XtCHeight&Dimension &0 \cr
borderWidth&XtCBorderWidth&Dimension &0 \cr
XtNcolormap&XtCColormap&Colormap &NULL \cr
XtNdepth&XtCDepth&Int &0 \cr
destroyCallback&XtCDestroyCallback&XTCallbackList &NULL \cr
XtNsensitive&XtCSensitive&Boolean &True \cr
XtNtranslations&XtCTranslations&XTTranslations &NULL \cr
ancestorSensitive&XtCAncestorSensitive&Boolean &False \cr
accelerators&XtCAccelerators&XTTranslations &NULL \cr
borderColor&XtCBorderColor&Pixel &0 \cr
borderPixmap&XtCBorderPixmap&Pixmap &NULL \cr
background&XtCBackground&Pixel &0 \cr
backgroundPixmap&XtCBackgroundPixmap&Pixmap &NULL \cr
mappedWhenManaged&XtCMappedWhenManaged&Boolean &True \cr
XtNscreen&XtCScreen&Screen *&NULL \cr
\endTable
\Translations
\Section
 The default translations are the same as in the Slider2 widget, but
the actions have added functionality.



\Code
{\langle}Btn1Down{\rangle}: start() \endCode


\Section


\Code
{\langle}Btn1Motion{\rangle}: drag() \endCode


\Section


\Code
{\langle}Btn1Up{\rangle}: finish() \endCode


\End\Actions
\Section


\HCode
\Macro
min(a, b) =
((a ){\langle}(b )?(a ):(b ))\endMacro
\endHCode


\Section
\Action{start} The {\tt start} action checks where the mouse is and does one of three
things depending on the mouse position. If the mouse is outside the
thumb, the {\tt jump{\underline}callback} list is called with as {\tt call{\underline}data} argument
the direction in which the mouse click occurred. If the mouse is on
the thumb, but not in the triangle, a drag operation is started and
{\tt start} sets some private variables for use by the next action. If the
mouse is on the triangle, a resize operation is started and the
private variables are set accordingly.



\HCode
\Code
void start({\dollar}, XEvent* event, String* params, Cardinal* num{\underline}params)
{\lbrace}
    Dimension w, h;
    Position x, y;
    float b;
    int direction = 0;

    if (event-{\rangle}type != ButtonPress {\ampersand}{\ampersand} event-{\rangle}type != ButtonRelease
        {\ampersand}{\ampersand} event-{\rangle}type != MotionNotify)
        XtError("The start action must be bound to a mouse event");
    {\dollar}compute{\underline}thumb({\dollar}, {\ampersand}x, {\ampersand}y, {\ampersand}w, {\ampersand}h);
    if (event-{\rangle}xbutton.x {\langle} x)       direction {\bar}= XfwfLeft;
    if (event-{\rangle}xbutton.x {\rangle}= x + w)  direction {\bar}= XfwfRight;
    if (event-{\rangle}xbutton.y {\langle} y)       direction {\bar}= XfwfTop;
    if (event-{\rangle}xbutton.y {\rangle}= y + h)  direction {\bar}= XfwfBottom;
    if (direction != 0) {\lbrace}			/* Outside the thumb */
        XtCallCallbackList({\dollar}, {\dollar}jumpCallback, {\ampersand}direction);
    {\rbrace} else {\lbrace}					/* Inside the thumb */
        b = y + x + h + w - 2*{\dollar}thumbFrameWidth
	    - (min(h, w) - 2 * {\dollar}thumbFrameWidth)/2;
        if (event-{\rangle}xbutton.y {\rangle}= -event-{\rangle}xbutton.x + b) {\lbrace}
            {\dollar}resize{\underline}in{\underline}progress = True;		/* Inside the triangle */
            {\dollar}m{\underline}delta{\underline}x = w - event-{\rangle}xbutton.x;
            {\dollar}m{\underline}delta{\underline}y = h - event-{\rangle}xbutton.y;
        {\rbrace} else {\lbrace}
            {\dollar}drag{\underline}in{\underline}progress = True;		/* Outside the triangle */
            {\dollar}m{\underline}delta{\underline}x = x - event-{\rangle}xbutton.x;
            {\dollar}m{\underline}delta{\underline}y = y - event-{\rangle}xbutton.y;
        {\rbrace}
    {\rbrace}
{\rbrace}\endCode
\endHCode


\Section
\Action{finish} The {\tt finish} action checks what type of action just finished and
either does nothing (if the action was a click outside the thumb),
invokes the drop callbacks (if the mouse was dragging the thumb) or
invokes the resize callbacks (if the mouse was pulling the sash). The
callbacks get a pointer to a static {\tt SliderInfo} structure as
{\tt call{\underline}data} argument.



\HCode
\Code
void finish({\dollar}, XEvent* event, String* params, Cardinal* num{\underline}params)
{\lbrace}
    static XfwfSliderInfo info;

    if ({\dollar}drag{\underline}in{\underline}progress) {\lbrace}
        {\dollar}drag{\underline}in{\underline}progress = False;
        info.x = {\dollar}thumb{\underline}x;  info.width = {\dollar}thumb{\underline}wd;
        info.y = {\dollar}thumb{\underline}y;  info.height = {\dollar}thumb{\underline}ht;
        XtCallCallbackList({\dollar}, {\dollar}dropCallback, {\ampersand}info);
    {\rbrace} else if ({\dollar}resize{\underline}in{\underline}progress) {\lbrace}
        {\dollar}resize{\underline}in{\underline}progress = False;
        info.x = {\dollar}thumb{\underline}x;  info.width = {\dollar}thumb{\underline}wd;
        info.y = {\dollar}thumb{\underline}y;  info.height = {\dollar}thumb{\underline}ht;
        XtCallCallbackList({\dollar}, {\dollar}resizeCallback, {\ampersand}info);
    {\rbrace}
{\rbrace}\endCode
\endHCode


\Section
\Action{drag} The {\tt drag} action moves the thumb if a drag is in progress or
resizes the thumb if a resize operation is in progress; otherwise, it
does nothing. It also calls the appropriate callbacks {\tt drag{\underline}callback}
or {\tt stretch{\underline}callback}.  Moving the thumb is done by calling the
{\tt move{\underline}thumb} method, resizing is done by calling {\tt expose}.



\HCode
\Code
void drag({\dollar}, XEvent* event, String* params, Cardinal* num{\underline}params)
{\lbrace}
    Dimension oldw, oldh, neww, newh, fw, fh, wd, ht;
    Position newx, newy, x, y, oldx, oldy, fx, fy;
    float dum1, dum2;
    XfwfSliderInfo info;
    XEvent pseudoevent;
    XRectangle rect;
    Region reg;

    if (event-{\rangle}type != ButtonPress {\ampersand}{\ampersand} event-{\rangle}type != ButtonRelease
        {\ampersand}{\ampersand} event-{\rangle}type != MotionNotify)
        XtError("The drag action must be bound to a mouse event");
    if ({\dollar}drag{\underline}in{\underline}progress) {\lbrace}
        {\dollar}compute{\underline}thumb({\dollar}, {\ampersand}oldx, {\ampersand}oldy, {\ampersand}wd, {\ampersand}ht);
        newx = event-{\rangle}xbutton.x + {\dollar}m{\underline}delta{\underline}x;
        newy = event-{\rangle}xbutton.y + {\dollar}m{\underline}delta{\underline}y;
        {\dollar}compute{\underline}info({\dollar}, {\ampersand}newx, {\ampersand}newy,{\ampersand}wd,{\ampersand}ht,{\ampersand}{\dollar}thumb{\underline}x,{\ampersand}{\dollar}thumb{\underline}y,{\ampersand}dum1,{\ampersand}dum2);
        {\dollar}move{\underline}thumb({\dollar}, oldx, oldy, wd, ht, newx, newy);
        info.x = {\dollar}thumb{\underline}x;  info.width = {\dollar}thumb{\underline}wd;
        info.y = {\dollar}thumb{\underline}y;  info.height = {\dollar}thumb{\underline}ht;
        XtCallCallbackList({\dollar}, {\dollar}dragCallback, {\ampersand}info);
    {\rbrace} else if ({\dollar}resize{\underline}in{\underline}progress) {\lbrace}
        {\dollar}compute{\underline}thumb({\dollar}, {\ampersand}x, {\ampersand}y, {\ampersand}oldw, {\ampersand}oldh);
        neww = event-{\rangle}xbutton.x + {\dollar}m{\underline}delta{\underline}x;
        newh = event-{\rangle}xbutton.y + {\dollar}m{\underline}delta{\underline}y;
        {\dollar}compute{\underline}info({\dollar}, {\ampersand}x, {\ampersand}y,{\ampersand}neww,{\ampersand}newh,{\ampersand}dum1,{\ampersand}dum2,{\ampersand}{\dollar}thumb{\underline}wd,{\ampersand}{\dollar}thumb{\underline}ht);
        rect.x = pseudoevent.xexpose.x = x;
        rect.y = pseudoevent.xexpose.y = y;
	rect.height = pseudoevent.xexpose.height = max(oldh, newh);
	rect.width = pseudoevent.xexpose.width = max(oldw, neww);
	XClearArea(XtDisplay({\dollar}), XtWindow({\dollar}), x, y, rect.width,
		   rect.height, False);
        reg = XCreateRegion();
        XUnionRectWithRegion({\ampersand}rect, reg, reg);
        {\dollar}expose({\dollar}, {\ampersand}pseudoevent, reg);
        XDestroyRegion(reg);
        info.x = {\dollar}thumb{\underline}x;  info.width = {\dollar}thumb{\underline}wd;
        info.y = {\dollar}thumb{\underline}y;  info.height = {\dollar}thumb{\underline}ht;
        XtCallCallbackList({\dollar}, {\dollar}stretchCallback, {\ampersand}info);
    {\rbrace}
{\rbrace}\endCode
\endHCode


\End\Privatevars
\Section
 Three more GC's are needed to draw the sash and the frame around it.



\Code
GC  sashgc\endCode


\Section


\Code
GC  sashlightgc\endCode


\Section


\Code
GC  sashdarkgc\endCode


\Section
 The boolean {\tt resize{\underline}in{\underline}progress} is set to {\tt True} when a resizing
action is initiated (by pressing a mouse button on the sash).



\Code
Boolean  resize{\underline}in{\underline}progress\endCode


\End\Methods
\Section
 The {\tt initialize} method sets the private variables and calls three
routines to set the GC's for drawing the triangle.



\Code
initialize(Widget  request, {\dollar}, ArgList  args, Cardinal * num{\underline}args)
{\lbrace}
    {\dollar}sashgc = NULL; create{\underline}sashgc({\dollar});
    {\dollar}sashlightgc = NULL; create{\underline}sashlightgc({\dollar});
    {\dollar}sashdarkgc = NULL; create{\underline}sashdarkgc({\dollar});
    {\dollar}resize{\underline}in{\underline}progress = False;
{\rbrace}\endCode


\Section
 The {\tt expose} method uses the {\tt expose} method of the superclass to
draw the widget and then adds the triangle in the lower right corner
of the thumb.  Drawing the triangle is so simple (for the X server,
not for the programmer :-) that it isn't useful to set the clipping
rectangle.



\Code
expose({\dollar}, XEvent * event, Region  region)
{\lbrace}
    Position x, y;
    Dimension w, h, b;
    XPoint p[9];

    if (! XtIsRealized({\dollar})) return;
    {\hashmark}expose({\dollar}, event, region);
    {\dollar}compute{\underline}inside({\dollar}, {\ampersand}x, {\ampersand}y, {\ampersand}w, {\ampersand}h);
    b = min(h, w)/2;
    p[0].x = x + w - b;
    p[0].y = y + h;
    p[1].x = x + w;
    p[1].y = p[0].y;
    p[2].x = p[1].x;
    p[2].y = y + h - b;
    XFillPolygon(XtDisplay({\dollar}), XtWindow({\dollar}), {\dollar}sashgc, p, 3, Convex,
		 CoordModeOrigin);
    if ({\dollar}sashFrameType == XfwfRaised {\bar}{\bar} {\dollar}sashFrameType == XfwfSunken) {\lbrace}
	p[0].x = x + w - b + 2 * {\dollar}sashFrameWidth;
	p[0].y = y + h - {\dollar}sashFrameWidth;
	p[1].x = x + w - {\dollar}sashFrameWidth;
	p[1].y = p[0].y;
	p[2].x = p[1].x;
	p[2].y = y + h - b + 2 * {\dollar}sashFrameWidth;
        p[3].x = x + w;
        p[3].y = y + h - b;
        p[4].x = p[3].x;
        p[4].y = y + h;
        p[5].x = x + w - b;
        p[5].y = p[4].y;
        XFillPolygon(XtDisplay({\dollar}), XtWindow({\dollar}),
		     {\dollar}sashFrameType == XfwfRaised ? {\dollar}sashdarkgc : {\dollar}sashlightgc,
		     p, 6, Nonconvex, CoordModeOrigin);
	p[1].x = p[2].x;
	p[1].y = p[2].y;
	p[2].x = p[3].x;
	p[2].y = p[3].y;
	p[3].x = p[5].x;
	p[3].y = p[5].y;
        XFillPolygon(XtDisplay({\dollar}), XtWindow({\dollar}),
		     {\dollar}sashFrameType == XfwfSunken ? {\dollar}sashdarkgc : {\dollar}sashlightgc,
		     p, 4, Nonconvex, CoordModeOrigin);
    {\rbrace} else {\lbrace}
	p[0].x = x + w - b + 2 * {\dollar}sashFrameWidth;
	p[0].y = y + h - {\dollar}sashFrameWidth;
	p[1].x = x + w - {\dollar}sashFrameWidth;
	p[1].y = p[0].y;
	p[2].x = p[1].x;
	p[2].y = y + h - b + 2 * {\dollar}sashFrameWidth;
        p[3].x = x + w - {\dollar}sashFrameWidth/2;
        p[3].y = y + h - b + {\dollar}sashFrameWidth;
        p[4].x = p[3].x;
        p[4].y = y + h - {\dollar}sashFrameWidth/2;
        p[5].x = x + w - b + {\dollar}sashFrameWidth;
        p[5].y = p[4].y;
        XFillPolygon(XtDisplay({\dollar}), XtWindow({\dollar}),
		     {\dollar}sashFrameType == XfwfChiseled ? {\dollar}sashdarkgc : {\dollar}sashlightgc,
		     p, 6, Nonconvex, CoordModeOrigin);
        p[2].x = x + w;
        p[2].y = y + h - b;
        p[1].x = p[2].x;
        p[1].y = y + h;
        p[0].x = x + w - b;
        p[0].y = p[1].y;
        XFillPolygon(XtDisplay({\dollar}), XtWindow({\dollar}),
		     {\dollar}sashFrameType == XfwfChiseled ? {\dollar}sashlightgc : {\dollar}sashdarkgc,
		     p, 6, Nonconvex, CoordModeOrigin);
        p[0].x = x + w - b + 2 * {\dollar}sashFrameWidth;
        p[0].y = y + h - {\dollar}sashFrameWidth;
        p[1].x = x + w - {\dollar}sashFrameWidth;
        p[1].y = p[0].y;
        p[2].x = x + w - {\dollar}sashFrameWidth/2;
        p[2].y = y + h - b + {\dollar}sashFrameWidth;
        p[3].x = x + w - b + {\dollar}sashFrameWidth;
        p[3].y = y + h - {\dollar}sashFrameWidth/2;
        XFillPolygon(XtDisplay({\dollar}), XtWindow({\dollar}),
		     {\dollar}sashFrameType == XfwfChiseled ? {\dollar}sashlightgc : {\dollar}sashdarkgc,
		     p, 4, Convex, CoordModeOrigin);
        p[0].x = x + w - b;
        p[0].y = y + h;
        p[1].x = x + w;
        p[1].y = y + h - b;
        XFillPolygon(XtDisplay({\dollar}), XtWindow({\dollar}),
		     {\dollar}sashFrameType == XfwfChiseled ? {\dollar}sashdarkgc : {\dollar}sashlightgc,
		     p, 4, Convex, CoordModeOrigin);
    {\rbrace}
{\rbrace}\endCode


\Section
 The {\tt set{\underline}values} method is responsible for creating new GC's when
resources change. It also makes sure the {\tt sashFrameWidth} is even when
the frame type is chiseled or ledged.



\Code
Boolean  set{\underline}values(Widget  old, Widget  request, {\dollar}, ArgList  args, Cardinal * num{\underline}args)
{\lbrace}
    Boolean need{\underline}redisplay = False;

    if ({\dollar}sashPixmap != {\dollar}old{\dollar}sashPixmap) {\lbrace}
        XFreePixmap(XtDisplay({\dollar}), {\dollar}old{\dollar}sashPixmap);
        create{\underline}sashgc({\dollar});
        need{\underline}redisplay = True;
    {\rbrace} else if ({\dollar}sashColor != {\dollar}old{\dollar}sashColor) {\lbrace}
        XFreePixmap(XtDisplay({\dollar}), {\dollar}sashPixmap);
        {\dollar}sashPixmap = NULL;
        create{\underline}sashgc({\dollar});
        need{\underline}redisplay = True;
    {\rbrace}
    if ({\dollar}sashFrameType != {\dollar}old{\dollar}sashFrameType)
        need{\underline}redisplay = True;
    if ({\dollar}sashFrameType == XfwfChiseled {\bar}{\bar} {\dollar}sashFrameType == XfwfLedged)
        {\dollar}sashFrameWidth = 2 * ({\dollar}sashFrameWidth/2);
    if ({\dollar}sashFrameWidth != {\dollar}old{\dollar}sashFrameWidth)
        need{\underline}redisplay = True;
    if ({\dollar}shadowScheme != {\dollar}old{\dollar}shadowScheme
        {\bar}{\bar} ({\dollar}shadowScheme == XfwfAuto {\ampersand}{\ampersand} {\dollar}sashColor != {\dollar}old{\dollar}sashColor)
        {\bar}{\bar} ({\dollar}shadowScheme == XfwfStipple {\ampersand}{\ampersand} {\dollar}lightStipple != {\dollar}old{\dollar}lightStipple)
        {\bar}{\bar} ({\dollar}shadowScheme == XfwfColor {\ampersand}{\ampersand} {\dollar}lightColor != {\dollar}old{\dollar}lightColor)) {\lbrace}
        create{\underline}sashlightgc({\dollar});
        need{\underline}redisplay = True;
    {\rbrace}
    if ({\dollar}shadowScheme != {\dollar}old{\dollar}shadowScheme
        {\bar}{\bar} ({\dollar}shadowScheme == XfwfAuto {\ampersand}{\ampersand} {\dollar}sashColor != {\dollar}old{\dollar}sashColor)
        {\bar}{\bar} ({\dollar}shadowScheme == XfwfStipple {\ampersand}{\ampersand} {\dollar}darkStipple != {\dollar}old{\dollar}darkStipple)
        {\bar}{\bar} ({\dollar}shadowScheme == XfwfColor {\ampersand}{\ampersand} {\dollar}darkColor != {\dollar}old{\dollar}darkColor)) {\lbrace}
        create{\underline}sashdarkgc({\dollar});
        need{\underline}redisplay = True;
    {\rbrace}
    return need{\underline}redisplay = True;
{\rbrace}\endCode


\End\Utilities
\Section
 The {\tt create{\underline}sashgc} function creates a GC for drawing the sash.



\Code
create{\underline}sashgc({\dollar})
{\lbrace}
    XtGCMask mask;
    XGCValues values;

    if ({\dollar}sashPixmap != NULL) {\lbrace}
        mask = GCTile {\bar} GCFillStyle;
        values.tile = {\dollar}sashPixmap;
        values.fill{\underline}style = FillTiled;
    {\rbrace} else {\lbrace}
        mask = GCForeground;
        values.foreground = {\dollar}sashColor;
    {\rbrace}
    {\dollar}sashgc = XtGetGC({\dollar}, mask, {\ampersand}values);
{\rbrace}\endCode


\Section
 The GC for the light parts of the frame around the triangle depends
on the setting of the {\tt shadowScheme} resource.



\Code
create{\underline}sashlightgc({\dollar})
{\lbrace}
    XtGCMask mask;
    XGCValues values;

    switch ({\dollar}shadowScheme) {\lbrace}
    case XfwfColor:
        mask = GCForeground;
        values.foreground = {\dollar}lightColor;
        break;
    case XfwfStipple:
        mask = GCForeground {\bar} GCFillStyle {\bar} GCStipple;
        values.foreground = WhitePixelOfScreen(XtScreen({\dollar}));
        values.fill{\underline}style = FillStippled;
        values.stipple = {\dollar}lightStipple;
        break;
    case XfwfAuto:
        mask = GCForeground;
        if (DefaultDepthOfScreen(XtScreen({\dollar})) {\langle} 5
            {\bar}{\bar} ! {\dollar}lighter{\underline}color({\dollar}, {\dollar}sashColor, {\ampersand}values.foreground)) {\lbrace}
            mask = GCForeground {\bar} GCFillStyle {\bar} GCStipple;
            values.foreground = WhitePixelOfScreen(XtScreen({\dollar}));
            values.fill{\underline}style = FillStippled;
            values.stipple = {\dollar}stip4;
        {\rbrace}
    {\rbrace}
    {\dollar}sashlightgc = XtGetGC({\dollar}, mask, {\ampersand}values);
{\rbrace}\endCode


\Section
 The GC for the dark parts of the frame around the triangle.



\Code
create{\underline}sashdarkgc({\dollar})
{\lbrace}
    XtGCMask mask;
    XGCValues values;

    switch ({\dollar}shadowScheme) {\lbrace}
    case XfwfColor:
        mask = GCForeground;
        values.foreground = {\dollar}darkColor;
        break;
    case XfwfStipple:
        mask = GCForeground {\bar} GCFillStyle {\bar} GCStipple;
        values.foreground = BlackPixelOfScreen(XtScreen({\dollar}));
        values.fill{\underline}style = FillStippled;
        values.stipple = {\dollar}darkStipple;
        break;
    case XfwfAuto:
        mask = GCForeground;
        if (DefaultDepthOfScreen(XtScreen({\dollar})) {\langle} 5
            {\bar}{\bar} ! {\dollar}darker{\underline}color({\dollar}, {\dollar}sashColor, {\ampersand}values.foreground)) {\lbrace}
            mask = GCForeground {\bar} GCFillStyle {\bar} GCStipple;
            values.foreground = BlackPixelOfScreen(XtScreen({\dollar}));
            values.fill{\underline}style = FillStippled;
            values.stipple = {\dollar}stip4;
        {\rbrace}
    {\rbrace}
    {\dollar}sashdarkgc = XtGetGC({\dollar}, mask, {\ampersand}values);
{\rbrace}\endCode


\End\bye
