.\"remove .ig hn for full docs .de hi .ig eh .. .de eh .. .TH "" 3 "" "Version 3.0" "Free Widget Foundation" .SH NAME XfwfFrame .SH DESCRIPTION The Frame widget is a composite widget that accepts just one child. Its only purpose is to draw a frame around widgets that do not have a frame of their own. It always uses the size of its child, with a little extra for the frame. There are several types of frames available, selectable with a resource. Widget writers can also use the Frame class as a superclass for new widgets. The frame is drawn by the \fIexpose\fP method (which must therefore be called by subclasses). Its width is given by \fIXtNframeWidth\fP, the appearance by \fIXtNframeType\fP. The possible types are: \item{\fIXfwfRaised\fP} Gives a beveled look. The top and left borders will be lighter, the bottom and right sides darker. \item{\fIXfwfSunken\fP} Just the opposite. \item{\fIXfwfChiseled\fP} The border will look as if it was made with a chisel. \item{\fIXfwfLedged\fP} The border will be a ledge that juts out of the background. .SS "Public variables" .ps-2 .TS center box; cBsss lB|lB|lB|lB l|l|l|l. XfwfFrame Name Class Type Default XtNcursor XtCCursor Cursor None XtNframeType XtCFrameType FrameType XfwfRaised XtNframeWidth XtCFrameWidth Dimension 0 XtNouterOffset XtCOuterOffset Dimension 0 XtNinnerOffset XtCInnerOffset Dimension 0 XtNshadowScheme XtCShadowScheme ShadowScheme XfwfAuto XtNtopShadowColor XtCTopShadowColor Pixel compute_topcolor XtNbottomShadowColor XtCBottomShadowColor Pixel compute_bottomcolor XtNtopShadowStipple XtCTopShadowStipple Bitmap NULL XtNbottomShadowStipple XtCBottomShadowStipple Bitmap NULL .TE .ps .TP .I "XtNcursor" The cursor (when not \fINone\fP) is the mouse cursor that is displayed when the mouse is over the Board widget. The default value \fINone\fP causes the parent's cursor to be used. .hi .nf Cursor cursor = None .fi .eh .TP .I "XtNframeType" The \fIXtNframeType\fP determines how the border looks. .hi .nf FrameType frameType = XfwfRaised .fi .eh .TP .I "XtNframeWidth" \fIXtNframeWidth\fP gives the width of the border. The default value of 0 shows no border at all. The border is drawn {\it inside\/} the widget. (See also \fIXtNouterOffset\fP.) .hi .nf Dimension frameWidth = 0 .fi .eh .TP .I "XtNouterOffset" Normally, the border is draw along the outer edge of the widget, but it can be moved inward. \fIXtNouterOffset\fP is the number of pixels between the edge and the frame. .hi .nf Dimension outerOffset = 0 .fi .eh .TP .I "XtNinnerOffset" Between the frame and whatever is inside the widget, there is also margin. By default, however, it is 0. .hi .nf Dimension innerOffset = 0 .fi .eh .TP .I "XtNshadowScheme" The colors of the top and bottom shadows can be set with the resources \fItopShadowColor\fP and \fIbottomShadowColor\fP, but it is also possible to use a stiple of foreground and background colors. This may be preferable on workstations with limited or no color capabilities. However, the easiest way (which is also the default) is to let the widget determine its own shadow colors or stipples, based on the widget's background color and the color capabilities of the screen. The resource \fIshadowScheme\fP can be set to \fIXfwfColor\fP, \fIXfwfStipple\fP or \fIXfwfAuto\fP. The converter for the shadow pixmap accepts the strings \fI"stipple0"\fP through \fI"stipple8"\fP, which create pixmaps of the current background and foreground colors, with \fI"stipple0"\fP entirely background and \fI"stipple8"\fP entirely foreground. Setting pixmaps or colors is only useful when \fIshadowScheme\fP is set to \fIXfwfStipple\fP or \fIXfwfColor\fP respectively. The values of \fItopShadowColor\fP and \fIbottomShadowColor\fP are ignored by the Frame widget as long as \fIshadowScheme\fP is not \fIXfwfColor\fP, but the default values are computed nevertheless, since they are useful, e.g., when an icon uses `topShadowColor' and `bottomShadowColor' as dynamic colors. .hi .nf ShadowScheme shadowScheme = XfwfAuto .fi .eh .TP .I "XtNtopShadowColor" .hi .nf Pixel topShadowColor = compute_topcolor .fi .eh .TP .I "XtNbottomShadowColor" .hi .nf Pixel bottomShadowColor = compute_bottomcolor .fi .eh .TP .I "XtNtopShadowStipple" .hi .nf Bitmap topShadowStipple = NULL .fi .eh .TP .I "XtNbottomShadowStipple" .hi .nf Bitmap bottomShadowStipple = NULL .fi .eh .TP .I "XtNborder_width" The inherited resource \fIborderWidth\fP is given a default value of 0, instead of 1. .hi .nf border_width = 0 .fi .eh .ps-2 .TS center box; cBsss lB|lB|lB|lB l|l|l|l. XfwfCommon Name Class Type Default XtNtraversalOn XtCTraversalOn Boolean True XtNhighlightThickness XtCHighlightThickness Dimension 2 XtNhighlightColor XtCHighlightColor Pixel XtDefaultForeground XtNhighlightPixmap XtCHighlightPixmap Pixmap None XtNnextTop XtCNextTop Callback NULL XtNuserData XtCUserData Pointer NULL .TE .ps .ps-2 .TS center box; cBsss lB|lB|lB|lB l|l|l|l. Composite Name Class Type Default XtNchildren XtCChildren WidgetList NULL insertPosition XtCInsertPosition XTOrderProc NULL numChildren XtCNumChildren Cardinal 0 .TE .ps .ps-2 .TS center box; cBsss lB|lB|lB|lB l|l|l|l. Core Name Class Type Default XtNx XtCX Position 0 XtNy XtCY Position 0 XtNwidth XtCWidth Dimension 0 XtNheight XtCHeight Dimension 0 borderWidth XtCBorderWidth Dimension 0 XtNcolormap XtCColormap Colormap NULL XtNdepth XtCDepth Int 0 destroyCallback XtCDestroyCallback XTCallbackList NULL XtNsensitive XtCSensitive Boolean True XtNtm XtCTm XTTMRec NULL ancestorSensitive XtCAncestorSensitive Boolean False accelerators XtCAccelerators XTTranslations NULL borderColor XtCBorderColor Pixel 0 borderPixmap XtCBorderPixmap Pixmap NULL background XtCBackground Pixel 0 backgroundPixmap XtCBackgroundPixmap Pixmap NULL mappedWhenManaged XtCMappedWhenManaged Boolean True XtNscreen XtCScreen Screen * NULL .TE .ps .SS "Exports" A number of new types is introduced by the Common class. The possible types of borders are enumerated in \fIFrame3dType\fP (see the introduction). .nf .B type FrameType = enum { XfwfRaised, XfwfSunken, XfwfChiseled, XfwfLedged } .fi The shadow scheme can be used to choose colors, pixmaps or automatic shadows. .nf .B type ShadowScheme = enum {XfwfAuto, XfwfColor, XfwfStipple} .fi The type \fIBitmap\fP is an alias for \fIPixmap\fP, but it is meant to contain only bitmaps, i.e., pixmaps of depth one. .nf .B type Bitmap = Pixmap .fi The routine that draws the border is generally useful, so it is exported. \fIt\fP is the thickness of the frame. The frame is drawn inside the rectangle \fI(x, y, x+w-1, y+h-1)\fP. .nf XfwfDrawFrame( $, int x, int y, int w, int h, FrameType tp, int t, GC lightgc, GC darkgc) .fi .hi { XPoint tlPoints[7], brPoints[7]; if (t == 0) return; switch (tp) { case XfwfRaised: case XfwfSunken: tlPoints[0].x = x; tlPoints[0].y = y; tlPoints[1].x = x + w; tlPoints[1].y = y; tlPoints[2].x = x + w - t; tlPoints[2].y = y + t; tlPoints[3].x = x + t; tlPoints[3].y = y + t; tlPoints[4].x = x + t; tlPoints[4].y = y + h - t; tlPoints[5].x = x; tlPoints[5].y = y + h; tlPoints[6].x = x; tlPoints[6].y = y; brPoints[0].x = x + w; brPoints[0].y = y + h; brPoints[1].x = x; brPoints[1].y = y + h; brPoints[2].x = x + t; brPoints[2].y = y + h - t; brPoints[3].x = x + w - t; brPoints[3].y = y + h - t; brPoints[4].x = x + w - t; brPoints[4].y = y + t; brPoints[5].x = x + w; brPoints[5].y = y; brPoints[6].x = x + w; brPoints[6].y = y + h; if (tp == XfwfSunken) { XFillPolygon(XtDisplay($), XtWindow($), darkgc, tlPoints, 7, Nonconvex, CoordModeOrigin); XFillPolygon(XtDisplay($), XtWindow($), lightgc, brPoints, 7, Nonconvex, CoordModeOrigin); } else { XFillPolygon(XtDisplay($), XtWindow($), lightgc, tlPoints, 7, Nonconvex, CoordModeOrigin); XFillPolygon(XtDisplay($), XtWindow($), darkgc, brPoints, 7, Nonconvex, CoordModeOrigin); } break; case XfwfLedged: XfwfDrawFrame($, x, y, w, h, XfwfRaised, t/2, lightgc, darkgc); XfwfDrawFrame($, x+t/2, y+t/2, w-2*(int)(t/2), h-2*(int)(t/2), XfwfSunken, t/2, lightgc, darkgc); break; case XfwfChiseled: XfwfDrawFrame($, x, y, w, h, XfwfSunken, t/2, lightgc, darkgc); XfwfDrawFrame($, x+t/2, y+t/2, w-2*(int)(t/2), h-2*(int)(t/2), XfwfRaised, t/2, lightgc, darkgc); break; } } .eh \fIcvtStringToFrameType\fP converts the strings `raised', `sunken', `chiseled' and `ledged'. Case doesn't matter. .nf Boolean cvtStringToFrameType(Display * display, XrmValuePtr args, Cardinal * num_args, XrmValuePtr from, XrmValuePtr to, XtPointer * converter_data) .fi .hi { String s = (String) from->addr; if (*num_args != 0) XtAppErrorMsg(XtDisplayToApplicationContext(display), "cvtStringToFrameType", "wrongParameters", "XtToolkitError", "String to frame type conversion needs no arguments", (String*) NULL, (Cardinal*) NULL); if (XmuCompareISOLatin1(s, "raised") == 0) done(FrameType, XfwfRaised); if (XmuCompareISOLatin1(s, "sunken") == 0) done(FrameType, XfwfSunken); if (XmuCompareISOLatin1(s, "chiseled") == 0) done(FrameType, XfwfChiseled); if (XmuCompareISOLatin1(s, "ledged") == 0) done(FrameType, XfwfLedged); XtDisplayStringConversionWarning(display, s, XtRFrameType); done(FrameType, XfwfRaised); } .eh .nf Boolean cvtFrameTypeToString(Display * display, XrmValuePtr args, Cardinal * num_args, XrmValuePtr from, XrmValuePtr to, XtPointer * converter_data) .fi .hi { if (*num_args != 0) XtAppErrorMsg(XtDisplayToApplicationContext(display), "cvtFrameTypeToString", "wrongParameters", "XtToolkitError", "Fframe type to String conversion needs no arguments", (String*) NULL, (Cardinal*) NULL); switch (*(FrameType*)from->addr) { case XfwfRaised: done(String, "raised"); case XfwfSunken: done(String, "sunken"); case XfwfChiseled: done(String, "chiseled"); case XfwfLedged: done(String, "ledged"); default: XtError("Illegal FrameType"); } } .eh The converter \fIcvtStringToShadowScheme\fP converts strings `color', `auto' and `stipple' to \fIXfwfColor\fP, \fIXfwfAuto\fP and \fIXfwfStipple\fP. .nf Boolean cvtStringToShadowScheme(Display * display, XrmValuePtr args, Cardinal * num_args, XrmValuePtr from, XrmValuePtr to, XtPointer * converter_data) .fi .hi { String s = (String) from->addr; if (*num_args != 0) XtAppErrorMsg(XtDisplayToApplicationContext(display), "cvtStringToShadowScheme", "wrongParameters", "XtToolkitError", "String to shadow scheme conversion needs no arguments", (String*) NULL, (Cardinal*) NULL); if (XmuCompareISOLatin1(s, "auto")==0) done(ShadowScheme, XfwfAuto); if (XmuCompareISOLatin1(s, "color")==0) done(ShadowScheme, XfwfColor); if (XmuCompareISOLatin1(s, "stipple")==0) done(ShadowScheme, XfwfStipple); XtDisplayStringConversionWarning(display, s, XtRShadowScheme); done(ShadowScheme, XfwfAuto); } .eh .nf Boolean cvtShadowSchemeToString(Display * display, XrmValuePtr args, Cardinal * num_args, XrmValuePtr from, XrmValuePtr to, XtPointer * converter_data) .fi .hi { if (*num_args != 0) XtAppErrorMsg(XtDisplayToApplicationContext(display), "cvtShadowSchemeToString", "wrongParameters", "XtToolkitError", "Shadow scheme to String conversion needs no arguments", (String*) NULL, (Cardinal*) NULL); switch (*(ShadowScheme*)from->addr) { case XfwfAuto: done(String, "auto"); case XfwfColor: done(String, "color"); case XfwfStipple: done(String, "stipple"); default: XtError("Illegal ShadowScheme"); } } .eh .hi .SS "Actions" .TP .I "set_shadow Although the Frame widget has no translations, one action is defined, that may be of use to subclasses. The action function \fIset_shadow\fP can be used to change the shadow frame. It has zero or one argument. Without an argument, it resets the shadow to its original type; with an argument, it sets the shadow to the type given in the argument. Warning: the function uses the \fIXfwfDrawFrame\fP routine to draw the frames directly, instead of calling the \fIexpose\fP or even \fIset_values\fP methods. Any subclass that defines behaviour that depends on knowing the frame type, will have to redefine the \fIset_shadow\fP action. .hi .nf void set_shadow($, XEvent* event, String* params, Cardinal* num_params) { Position x, y; Dimension w, h; FrameType f = XfwfSunken; if (*num_params == 0) f = $old_frame_type; /* Reset to old style */ else if (strcmp("raised", params[0]) == 0) f = XfwfRaised; else if (strcmp("sunken", params[0]) == 0) f = XfwfSunken; else if (strcmp("chiseled", params[0]) == 0) f = XfwfChiseled; else if (strcmp("ledged", params[0]) == 0) f = XfwfLedged; else XtWarning("Unknown frame type in set_shadow action"); if ($frameType != f) { $frameType = f; #compute_inside($, x, y, w, h); XfwfDrawFrame($, x + $outerOffset, y + $outerOffset, w - 2*$outerOffset, h - 2*$outerOffset, $frameType, $frameWidth, $lightgc, $darkgc); } } .fi .eh .hi .hi .SH "Importss" .nf .B incl .fi .nf .B incl .fi .nf .B incl .fi .nf .B incl .fi The stipple for the shadows is loaded from a bitmap file. .nf .B incl "stip4.bm" .fi .hi .hi .SS "Private variables" The GC for drawing the light parts of the frame: .nf GC lightgc .fi The GC for drawing the dark parts of the frame: .nf GC darkgc .fi The \fIstip4\fP bitmap is used on screens with insufficient colors to simulate light and dark shadows. It will be created by the \fIinitialize\fP method, whether or not it is needed. Since it is but a small bitmap, this can't hurt much. .nf Pixmap stip4 .fi The \fIold_frame_type\fP variable is used by the \fIset_shadow\fP action function to store the original frame type, when it is temporarily changed. .nf FrameType old_frame_type .fi .hi .hi .SS "Methods" \fIclass_initialize\fP installs the type converters. The type converters back to String are installed as a convenience, so resources can be retrieved in readable form with \fIXtVaGetValues\fP. .nf class_initialize() { static XtConvertArgRec screenArg[] = { {XtBaseOffset, (XtPointer)XtOffset(Widget, core.screen), sizeof(Screen*)}}; XtSetTypeConverter(XtRString, XtRFrameType, cvtStringToFrameType, NULL, 0, XtCacheNone, NULL); XtSetTypeConverter(XtRFrameType, XtRString, cvtFrameTypeToString, NULL, 0, XtCacheNone, NULL); XtAddConverter(XtRString, XtRBitmap, XmuCvtStringToBitmap, screenArg, XtNumber(screenArg)); XtSetTypeConverter(XtRString, XtRShadowScheme, cvtStringToShadowScheme, NULL, 0, XtCacheNone, NULL); XtSetTypeConverter(XtRShadowScheme, XtRString, cvtShadowSchemeToString, NULL, 0, XtCacheNone, NULL); } .fi Much of the initialization that one would expect in the \fIinitialize\fP method is actually delegated to the \fIrealize\fP method, since a window ID is needed for most of the initializations. .nf initialize(Widget request, $, ArgList args, Cardinal * num_args) { $lightgc = NULL; $darkgc = NULL; $old_frame_type = $frameType; } .fi The \fIrealize\fP method uses the inherited method, but adds the cursor attribute. This is also the place to create the \fIstip4\fP bitmap, that is used for stippled shadows. It could not be created in \fIinitialize\fP, since creating a bitmap requires a window ID. The GC's must be created after the \fIstip4\fP bitmaps, since they might have to use it as a stipple. .nf realize($, XtValueMask * mask, XSetWindowAttributes * attributes) { *mask |= CWCursor; attributes->cursor = $cursor; #realize($, mask, attributes); $stip4 = XCreateBitmapFromData(XtDisplay($), XtWindow($), stip4_bits, stip4_width, stip4_height); if (! $topShadowStipple) $topShadowStipple = $stip4; if (! $bottomShadowStipple) $bottomShadowStipple = $stip4; create_lightgc($); create_darkgc($); } .fi The \fIset_values\fP method has to create new GC's if the resources change. It also makes sure that \fIframeWidth\fP is even if the frame type is chiseled or ledged. If the frame width was and is zero, nothing needs to be drawn, regardless of the changes in other resources. Therefore, at the end \fIneed_redisplay\fP is set to False. When the cursor changes, the \fIset_values\fP method uses the \fIXDefineCursor\fP routine to set the attribute on the widget's window, provided the widget is realized. .nf Boolean set_values(Widget old, Widget request, $, ArgList args, Cardinal * num_args) { Boolean need_redisplay = False; if ($cursor != $old$cursor XtIsRealized($)) XDefineCursor(XtDisplay($), XtWindow($), $cursor); if ($frameType == XfwfChiseled || $frameType == XfwfLedged) $frameWidth = 2 * ((int) ($frameWidth / 2)); if ($shadowScheme != $old$shadowScheme) { create_darkgc($); create_lightgc($); need_redisplay = True; } else if ($shadowScheme == XfwfColor) { if ($topShadowColor != $old$topShadowColor) { create_lightgc($); need_redisplay = True; } if ($bottomShadowColor != $old$bottomShadowColor) { create_darkgc($); need_redisplay = True; } } else if ($shadowScheme == XfwfStipple) { if ($topShadowStipple != $old$topShadowStipple) { create_lightgc($); need_redisplay = True; } if ($bottomShadowStipple != $old$bottomShadowStipple) { create_darkgc($); need_redisplay = True; } } if ($outerOffset != $old$outerOffset) need_redisplay = True; if ($innerOffset != $old$innerOffset) need_redisplay = True; if ($frameType != $old$frameType) { $old_frame_type = $frameType; need_redisplay = True; } if ($frameWidth != $old$frameWidth) need_redisplay = True; else if ($frameWidth == 0) need_redisplay = False; return need_redisplay; } .fi The \fIexpose\fP method draws the frame, for which it uses the \fIXfwfDrawFrame\fP routine. Before it calls the routine, it sets the clip region. Afterwards, the clip region is reset, because we don't know which other widgets share the same GC's. As explained in {\em X Toolkit Intrinsics Programming Manual} (Nye \& O'Reilly, Motif Edition, 1990, p~223), the test for \fIXtIsRealized\fP is there for the unlikely case when an expose event arrives after the widget has been destroyed or unrealized. .nf expose($, XEvent * event, Region region) { Position x, y; Dimension w, h; if (! XtIsRealized($)) return; if (region != NULL) { XSetRegion(XtDisplay($), $lightgc, region); XSetRegion(XtDisplay($), $darkgc, region); } #compute_inside($, x, y, w, h); XfwfDrawFrame($, x + $outerOffset, y + $outerOffset, w - 2*$outerOffset, h - 2*$outerOffset, $frameType, $frameWidth, $lightgc, $darkgc); if (region != NULL) { XSetClipMask(XtDisplay($), $lightgc, None); XSetClipMask(XtDisplay($), $darkgc, None); } #expose($, event, region); } .fi The method \fIcompute_inside\fP is re-defined. The method now returns the area inside the frame. It calls the superclass's method and then decreases the area by the width of the frame. .nf compute_inside($, Position * x, Position * y, Dimension * w, Dimension * h) { #compute_inside($, x, y, w, h); *x += $outerOffset + $frameWidth + $innerOffset; *y += $outerOffset + $frameWidth + $innerOffset; *w -= 2 * ($outerOffset + $frameWidth + $innerOffset); *h -= 2 * ($outerOffset + $frameWidth + $innerOffset); } .fi A Frame widget passes its parent's inquiry on to its (presumably) single child. If there is no child, the proposal is accepted. The border and position proposals are always accepted, the stacking order and size are left to the child to decide. .nf XtGeometryResult query_geometry($, XtWidgetGeometry * request, XtWidgetGeometry * reply) { XtWidgetGeometry request2, reply2; XtGeometryResult result; Dimension h; if ($num_children == 0) return XtGeometryYes; /* We're only interested in size and stacking order */ reply->request_mode = (CWWidth | CWHeight | CWStackMode) request->request_mode; /* If nothing of interest is left, we can return immediately */ if (reply->request_mode == 0) return XtGeometryYes; /* Prepare a request to the child */ h = 2 * ($outerOffset + $frameWidth + $innerOffset); request2.request_mode = reply->request_mode; request2.width = request->width - h; request2.height = request->height - h; request2.sibling = request->sibling; request2.stack_mode = request->stack_mode; result = XtQueryGeometry($children[0], request2, reply2); /* If the child accepted its proposal, we accept ours */ if (result == XtGeometryYes) return XtGeometryYes; /* If the child doesn't want any change, we don't want any, either */ if (result == XtGeometryNo) return XtGeometryNo; /* Otherwise, ignore everything but size and stacking order */ reply->request_mode = reply2.request_mode; if (reply->request_mode == 0) return XtGeometryYes; reply->width = reply2.width + h; reply->height = reply2.height + h; reply->sibling = reply2.sibling; reply->stack_mode = reply2.stack_mode; return XtGeometryAlmost; } .fi Requests by the child to be resized are passed on to the parent. If the parent replies with \fIXtGeometryYes\fP, the change is accepted and (if not \fIXtCWQueryOnly\fP) already done. In that case the Frame widget accepts its child's request. If the parent replies with \fIXtGeometryNo\fP, the change is denied and the denial is passed on. If the parent replies with a different geometry, the geometry is passed on, after compensating for the frame width. Requests for anything other than width or height are always granted. .nf XtGeometryResult geometry_manager(Widget child, XtWidgetGeometry * request, XtWidgetGeometry * reply) { XtWidgetGeometry request2, reply2; XtGeometryResult result; Position x, y; Dimension w, h, extraw, extrah; $compute_inside($, x, y, w, h); if (! (request->request_mode (CWWidth|CWHeight))) return XtGeometryYes; extraw = $width - w; extrah = $height - h; request2.request_mode = request->request_mode (CWWidth|CWHeight); request2.width = request->width + extraw; request2.height = request->height + extrah; result = XtMakeGeometryRequest($, request2, reply2); if (result == XtGeometryNo) return XtGeometryNo; if (result == XtGeometryYes) return XtGeometryYes; reply->request_mode = reply2.request_mode (CWWidth|CWHeight); reply->width = reply2.width - extraw; reply->height = reply2.height - extrah; return XtGeometryAlmost; } .fi The \fIresize\fP method doesn't have to recompute any private variables, but it passes on the resize message to its child, after decreasing the area by the amount needed for the frame. .nf resize($) { Position x, y; Dimension w, h; Widget child; if ($num_children == 0) return; $compute_inside($, x, y, w, h); child = $children[0]; w -= 2 * $child$border_width; h -= 2 * $child$border_width; XtConfigureWidget(child, x, y, w, h, $child$border_width); } .fi The \fIchange_managed\fP method is called when a child becomes managed or unmanaged. The task of the routine is enforcing the layout policy, which in this case consists of trying to take on the size of the child or otherwise resize the child to fit inside the frame. If the parent of the Frame widget doesn't allow the Frame widget to be resized, the child of the Frame widget will be resized instead. .nf change_managed($) { XtWidgetGeometry request2, reply2; XtGeometryResult result; Widget child; Position x, y; Dimension w, h; if ($num_children == 0) return; $compute_inside($, x, y, w, h); child = $children[0]; request2.request_mode = CWWidth | CWHeight; request2.width = $child$width + $width - w; request2.height = $child$height + $height - h; result = XtMakeGeometryRequest($, request2, reply2); $compute_inside($, x, y, w, h); w -= 2 * $child$border_width; h -= 2 * $child$border_width; XtConfigureWidget(child, x, y, w, h, $child$border_width); } .fi .hi .hi .SH "Utilities" The converters use the following macro. \fBdef\fP done(type, value) = do { if (to->addr != NULL) { if (to->size < sizeof(type)) { to->size = sizeof(type); return False; } *(type*)(to->addr) = (value); } else { static type static_val; static_val = (value); to->addr = (XtPointer)static_val; } to->size = sizeof(type); return True; }while (0 ) The variable \fIrcsid\fP isn't used for anything, except tracking of versions. The version number is that of the specification file (this file) from which the widget's source is build. .nf char rcsid[] = "$Header: Frame.w,v 1.5 92/11/02 14:07:52 bert Exp $" .fi The \fIcreate_darkgc\fP function creates the GC for the dark parts of the frame. The contents of the GC depend on the resources \fIshadowScheme\fP and possibly \fIbackground_pixel\fP, \fIbottomShadowColor\fP, \fItopShadowColor\fP, \fIbottomShadowStipple\fP and \fItopShadowStipple\fP. .nf create_darkgc($) { XtGCMask mask; XGCValues values; if ($darkgc != NULL) XtReleaseGC($, $darkgc); switch ($shadowScheme) { case XfwfColor: mask = GCForeground; values.foreground = $bottomShadowColor; break; case XfwfStipple: mask = GCFillStyle | GCStipple | GCForeground | GCBackground; values.fill_style = FillOpaqueStippled; values.stipple = $bottomShadowStipple; values.foreground = BlackPixelOfScreen(XtScreen($)); values.background = $background_pixel; break; case XfwfAuto: if (DefaultDepthOfScreen(XtScreen($)) > 4 $darker_color($, $background_pixel, values.foreground)) { mask = GCForeground; } else { mask = GCFillStyle | GCBackground | GCForeground | GCStipple; values.fill_style = FillOpaqueStippled; values.background = $background_pixel; values.foreground = WhitePixelOfScreen(XtScreen($)); values.stipple = $stip4; } break; } $darkgc = XtGetGC($, mask, values); } .fi \fIcreate_lightgc\fP does the same for the light parts of the frame. When the \fIshadowScheme\fP resource is \fIXfwfAuto\fP, the depth of the screen and the availability of colors determines whether colors or stipples will be used for the frame. .nf create_lightgc($) { XtGCMask mask; XGCValues values; if ($lightgc != NULL) XtReleaseGC($, $lightgc); switch ($shadowScheme) { case XfwfColor: mask = GCForeground; values.foreground = $topShadowColor; break; case XfwfStipple: mask = GCFillStyle | GCStipple | GCForeground | GCBackground; values.fill_style = FillOpaqueStippled; values.background = $background_pixel; values.stipple = $topShadowStipple; values.foreground = WhitePixelOfScreen(XtScreen($)); break; case XfwfAuto: if (DefaultDepthOfScreen(XtScreen($)) > 4 $lighter_color($, $background_pixel, values.foreground)) { mask = GCForeground; } else { mask = GCFillStyle | GCBackground | GCForeground | GCStipple; values.fill_style = FillOpaqueStippled; values.background = $background_pixel; values.foreground = WhitePixelOfScreen(XtScreen($)); values.stipple = $stip4; } break; } $lightgc = XtGetGC($, mask, values); } .fi The function \fIcompute_topcolor\fP is a resource default proc. It is used to compute the value of the \fItopShadowColor\fP relative to the \fIbackground\fP color. .nf compute_topcolor($, int offset, XrmValue * value) { static Pixel color; $lighter_color($, $background_pixel, color); value->addr = (XtPointer) color; } .fi .nf compute_bottomcolor($, int offset, XrmValue * value) { static Pixel color; $darker_color($, $background_pixel, color); value->addr = (XtPointer) color; } .fi .hi