[comp.sources.x] v10i045: Examples from New Xt Book, Part05/05

asente@adobe.com (11/01/90)

Submitted-by: asente@adobe.com
Posting-number: Volume 10, Issue 45
Archive-name: xt-examples/part05


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	LabelGadge.c
#	Menu.c
#	MenuItem.c
#	MinMax.c
#	Pushbutton.c
# This archive created: Wed Oct 24 14:25:59 1990
export PATH; PATH=/bin:$PATH
echo shar: extracting "'LabelGadge.c'" '(12890 characters)'
if test -f 'LabelGadge.c'
then
	echo shar: will not over-write existing file "'LabelGadge.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'LabelGadge.c'
	X/***********************************************************
	XCopyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
	X
	X                        All Rights Reserved
	X
	XPermission to use, copy, modify, and distribute these examples for any
	Xpurpose and without fee is hereby granted, provided that the above
	Xcopyright notice appear in all copies and that both that copyright
	Xnotice and this permission notice appear in supporting documentation,
	Xand that the name of Digital not be used in advertising or publicity
	Xpertaining to distribution of the software without specific, written
	Xprior permission.
	X
	XDIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
	XSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
	XFITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
	XOR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
	XOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
	XOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
	XOR PERFORMANCE OF THIS SOFTWARE.
	X
	X******************************************************************/
	X
	X#include <string.h>		/* Needed for string manipulation */
	X#include <X11/IntrinsicP.h>	/* Intrinsics header file */
	X#include <X11/StringDefs.h>	/* Resource string definitions */
	X#include "LabelGadgP.h"		/* LabelGadget private header file */
	X
	X#define Offset(field) XtOffsetOf(LabelGadgetRec, label.field)
	X
	Xstatic XtResource resources[] = {
	X    {XtNlabel, XtCLabel, XtRString, sizeof(String),
	X	Offset(label), XtRString, (XtPointer) NULL},
	X    {XtNfont,  XtCFont, XtRFontStruct, sizeof(XFontStruct *),
	X	Offset(font), XtRString, (XtPointer) XtDefaultFont},
	X    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
	X	Offset(foreground), XtRString,
	X	(XtPointer) XtDefaultForeground},
	X    {XtNjustify, XtCJustify, XtRJustify, sizeof(Justify),
	X	Offset(justify), XtRImmediate, (XtPointer) Left},
	X    {XtNspace, XtCSpace, XtRDimension, sizeof(Dimension),
	X	Offset(space), XtRImmediate, (XtPointer) 2},
	X    {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
	X         XtOffsetOf(LabelGadgetRec, rectObj.border_width),
	X	 XtRImmediate, (XtPointer) 0},
	X    {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
	X	Offset(background), XtRString,
	X	(XtPointer) XtDefaultBackground},
	X    {XtNborderColor, XtCBorderColor, XtRPixel, sizeof(Pixel),
	X	Offset(border), XtRString, (XtPointer) XtDefaultForeground},
	X};
	X#undef Offset
	X
	X/* Forward declarations */
	X
	Xstatic void ClassInitialize(), Initialize(),
	X	Redisplay(), Destroy(), Resize();
	Xstatic Boolean SetValues();
	Xstatic XtGeometryResult QueryGeometry();
	X
	X/* Class record declaration */
	X
	XLabelGadgetClassRec labelGadgetClassRec = {
	X    /* RectObj class part */
	X  {
	X    /* superclass	     */	(WidgetClass) &rectObjClassRec,
	X    /* class_name	     */	"LabelGadget",
	X    /* widget_size	     */	sizeof(LabelGadgetRec),
	X    /* class_initialize      */ ClassInitialize,
	X    /* class_part_initialize */	NULL,
	X    /* class_inited          */	FALSE,
	X    /* initialize	     */	Initialize,
	X    /* initialize_hook       */	NULL,		
	X    /* rect1		     */	NULL,
	X    /* rect2		     */	NULL,
	X    /* rect3		     */	0,
	X    /* resources	     */	resources,
	X    /* num_resources	     */	XtNumber(resources),
	X    /* xrm_class	     */	NULLQUARK,
	X    /* rect4		     */	0,
	X    /* rect5		     */	0,
	X    /* rect6		     */	0,
	X    /* rect7		     */	0,
	X    /* destroy		     */	Destroy,
	X    /* resize		     */	Resize,
	X    /* expose		     */	Redisplay,
	X    /* set_values	     */	SetValues,
	X    /* set_values_hook       */	NULL,			
	X    /* set_values_almost     */	XtInheritSetValuesAlmost,  
	X    /* get_values_hook       */	NULL,			
	X    /* rect9		     */	NULL,
	X    /* version		     */	XtVersion,
	X    /* callback offsets      */ NULL,
	X    /* rect10    	     */ NULL,
	X    /* query_geometry	     */	QueryGeometry,
	X    /* rect11		     */ NULL,
	X    /* extension    	     */ NULL
	X  },
	X    /* LabelGadget class part	*/
	X  {
	X    /* extension    	     */ NULL
	X  }
	X};
	X
	X/* Class record pointer */
	X
	XWidgetClass labelGadgetClass = (WidgetClass) &labelGadgetClassRec;
	X
	Xstatic void ClassInitialize()
	X{
	X    extern void CvtStringToJustify();	/* Defined in Label.c */
	X
	X    /* Register a converter for string to justification */
	X
	X    XtSetTypeConverter(XtRString, XtRJustify, CvtStringToJustify,
	X            (XtConvertArgList) NULL, 0,
	X	    XtCacheAll, (XtDestructor) NULL);
	X}
	X
	Xstatic void SetTextWidthAndHeight(lw)
	X    LabelGadget lw;
	X{
	X    register XFontStruct *fs = lw->label.font;
	X
	X    /* Compute the text dimensions based on the string and the font */
	X
	X    lw->label.label_len = strlen(lw->label.label);
	X    lw->label.label_width =
	X	    XTextWidth(fs, lw->label.label, lw->label.label_len);
	X    lw->label.label_height =
	X	    fs->max_bounds.ascent + fs->max_bounds.descent;
	X}
	X
	Xstatic GC GetNormalGC(lw)
	X    LabelGadget lw;
	X{
	X    XGCValues	values;
	X
	X    /* Allocate a graphics context with the foreground and font */
	X
	X    values.foreground = lw->label.foreground;
	X    values.font = lw->label.font->fid;
	X    return XtGetGC((Widget) lw, GCForeground | GCFont, &values);
	X}
	X
	Xstatic GC GetBackgroundGC(lw)
	X    LabelGadget lw;
	X{
	X    XGCValues	values;
	X
	X    /* Allocate a graphics context with the background */
	X
	X    values.foreground = lw->label.background;
	X    return XtGetGC((Widget) lw, GCForeground, &values);
	X}
	X
	Xstatic GC GetBorderGC(lw)
	X    LabelGadget lw;
	X{
	X    XGCValues	values;
	X
	X    if (lw->rectObj.border_width == 0) return NULL;
	X
	X    /* Allocate a graphics context with the border values */
	X
	X    values.foreground = lw->label.border;
	X    values.line_width = lw->rectObj.border_width;
	X    return XtGetGC((Widget) lw, GCForeground | GCLineWidth, &values);
	X}
	X
	Xstatic void Initialize(request, new, args, num_args)
	X    Widget request, new;
	X    ArgList args;
	X    Cardinal *num_args;
	X{
	X    LabelGadget lw = (LabelGadget) new;
	X
	X    /* If no label is specified, use the name */
	X    if (lw->label.label == NULL) lw->label.label = XtName(lw);
	X
	X    /* Copy the label */
	X    lw->label.label = XtNewString(lw->label.label);
	X
	X    /* Compute the text dimensions and get graphics contexts. */
	X    SetTextWidthAndHeight(lw);
	X    lw->label.gc = lw->label.current_gc = GetNormalGC(lw);
	X    lw->label.background_gc =
	X	    lw->label.current_bg_gc = GetBackgroundGC(lw);
	X    lw->label.border_gc = GetBorderGC(lw);
	X
	X    /* If no size specified, compute one */
	X    lw->label.size_computed =
	X	    (lw->rectObj.width == 0) && (lw->rectObj.height == 0);
	X
	X    if (lw->rectObj.width == 0) {
	X	lw->rectObj.width = lw->label.label_width +
	X		2 * lw->label.space;
	X    }
	X    if (lw->rectObj.height == 0) {
	X	lw->rectObj.height = lw->label.label_height +
	X		2 * lw->label.space;
	X    }
	X
	X    lw->label.old_border = lw->rectObj.border_width;
	X
	X    lw->label.desired_width = lw->rectObj.width;
	X    lw->label.desired_height = lw->rectObj.height;
	X}
	X
	Xstatic Boolean SetValues(old, request, new, args, num_args)
	X    Widget  old, request, new;
	X    ArgList args;
	X    Cardinal *num_args;
	X{
	X    LabelGadget oldlw = (LabelGadget) old;
	X    LabelGadget newlw = (LabelGadget) new;
	X    Boolean redisplay = FALSE;
	X
	X#define NE(field) (oldlw->field != newlw->field)
	X
	X    /* If the label has been reset to NULL, change to the name */
	X
	X    if (newlw->label.label == NULL) {
	X	newlw->label.label = XtName(newlw);
	X    }
	X
	X    /* Decide whether to compute the size */
	X
	X    if (newlw->rectObj.width == 0 && newlw->rectObj.height == 0) {
	X	newlw->label.size_computed = TRUE;
	X    } else if (NE(rectObj.width) || NE(rectObj.height)) {
	X	newlw->label.size_computed = FALSE;
	X	if (NE(rectObj.width)) {
	X	    newlw->label.desired_width = newlw->rectObj.width;
	X	}
	X	if (NE(rectObj.height)) {
	X	    newlw->label.desired_height = newlw->rectObj.height;
	X	}
	X    } /* else leave the same */
	X
	X    /* If label, or font has changed, recopy and compute size */
	X
	X    if (NE(label.label) || NE(label.font)) {
	X	if (NE(label.label)) {
	X	    XtFree((char *) oldlw->label.label);
	X	    newlw->label.label = XtNewString(newlw->label.label);
	X	}
	X	SetTextWidthAndHeight(newlw);
	X	redisplay = TRUE;
	X    }
	X
	X    /* Compute the size if necessary */
	X
	X    if (newlw->label.size_computed || newlw->rectObj.width == 0) {
	X	newlw->label.desired_width = newlw->rectObj.width =
	X		newlw->label.label_width + 2 * newlw->label.space;
	X    }
	X    if (newlw->label.size_computed || newlw->rectObj.height == 0) {
	X	newlw->label.desired_height = newlw->rectObj.height =
	X		newlw->label.label_height + 2 * newlw->label.space;
	X    }
	X    
	X    /* If foreground or font has changed, update GC */
	X
	X    if (NE(label.foreground) || NE(label.font->fid)) {
	X	XtReleaseGC(newlw, oldlw->label.gc);
	X	newlw->label.gc = GetNormalGC(newlw);
	X
	X	if (newlw->label.current_gc == oldlw->label.gc) {
	X	    newlw->label.current_gc = newlw->label.gc;
	X	    redisplay = TRUE;
	X	}
	X    }
	X
	X    /* If background has changed, update background GC */
	X
	X    if (NE(label.background)) {
	X	XtReleaseGC(newlw, oldlw->label.background_gc);
	X	newlw->label.background_gc = GetBackgroundGC(newlw);
	X
	X	if (newlw->label.current_bg_gc == oldlw->label.background_gc) {
	X	    newlw->label.current_bg_gc = newlw->label.background_gc;
	X	    redisplay = TRUE;
	X	}
	X    }
	X
	X    /* If border has changed, update border GC */
	X
	X    if (NE(label.border) || NE(rectObj.border_width)) {
	X	if (oldlw->label.border_gc != NULL) {
	X	    XtReleaseGC(newlw, oldlw->label.border_gc);
	X	}
	X	newlw->label.border_gc = GetBorderGC(newlw);
	X	redisplay = TRUE;
	X    }
	X
	X    return redisplay || NE(label.space) || NE(label.justify);
	X#undef NE
	X}
	X
	Xstatic void Destroy(w)
	X    Widget w;
	X{
	X    LabelGadget lw = (LabelGadget) w;
	X
	X    XtFree((char *) lw->label.label);
	X
	X    XtReleaseGC(w, lw->label.gc);
	X    XtReleaseGC(w, lw->label.background_gc);
	X    if (lw->label.border_gc != NULL) {
	X	XtReleaseGC(w, lw->label.border_gc);
	X    }
	X}
	X
	Xstatic void Redisplay(w, event, region)
	X    Widget w;
	X    XEvent *event;
	X    Region region;
	X{
	X    LabelGadget lw = (LabelGadget) w;
	X    int offset, x;
	X    XRectangle rect;
	X    Region r1, r2;
	X
	X    /* Draw the background */
	X    XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
	X    	    lw->label.current_bg_gc,
	X	    lw->rectObj.x + lw->rectObj.border_width,
	X	    lw->rectObj.y + lw->rectObj.border_width,
	X	    lw->rectObj.width, lw->rectObj.height);
	X
	X    /* Draw the border */
	X    if (lw->rectObj.border_width != 0) {
	X	offset = lw->rectObj.border_width / 2;
	X	XDrawRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
	X		lw->label.border_gc,
	X		lw->rectObj.x + offset, lw->rectObj.y + offset,
	X		lw->rectObj.width + lw->rectObj.border_width,
	X		lw->rectObj.height + lw->rectObj.border_width);
	X    }
	X
	X    switch (lw->label.justify) {
	X	case Left:
	X	    x = lw->label.space;	
	X	    break;
	X	case Right:
	X	    x = (int) lw->rectObj.width - (int) lw->label.space -
	X		    (int) lw->label.label_width;
	X	    break;
	X	case Center:
	X	    x = ((int) lw->rectObj.width -
	X		    (int) lw->label.label_width) / 2;
	X	    break;
	X    }
	X
	X    /* Temporarily change the clip mask in the gc */
	X    rect.x = lw->rectObj.x + lw->rectObj.border_width;
	X    rect.y = lw->rectObj.y + lw->rectObj.border_width;
	X    rect.width = lw->rectObj.width;
	X    rect.height = lw->rectObj.height;
	X
	X    r1 = XCreateRegion();
	X    r2 = XCreateRegion();
	X    if (region != NULL) {
	X	XUnionRectWithRegion(&rect, r1, r2);	/* r2 = rectangle */
	X	XIntersectRegion(region, r2, r1);	/* r1 = intersection */
	X    } else XUnionRectWithRegion(&rect, r2, r1); /* r1 = rectangle */
	X
	X    XSetRegion(XtDisplayOfObject(w), lw->label.current_gc, r1);
	X    XDestroyRegion(r1);
	X    XDestroyRegion(r2);
	X
	X    XDrawString(XtDisplayOfObject(w), XtWindowOfObject(w),
	X	    lw->label.current_gc,
	X	    lw->rectObj.x + lw->rectObj.border_width + x,
	X	    lw->rectObj.y + lw->rectObj.border_width + 
	X		lw->label.space + lw->label.font->max_bounds.ascent,
	X	    lw->label.label, lw->label.label_len);
	X
	X    /* Restore the GC */
	X    XSetClipMask(XtDisplayOfObject(w), lw->label.current_gc, None);
	X}
	X
	Xstatic void Resize(w)
	X    Widget w;
	X{
	X    LabelGadget lw = (LabelGadget) w;
	X
	X    /* If border width changed, update border GC */
	X
	X    if (lw->label.old_border != lw->rectObj.border_width) {
	X	if (lw->label.border_gc != NULL) {
	X	    XtReleaseGC(w, lw->label.border_gc);
	X	}
	X	lw->label.border_gc = GetBorderGC(lw);
	X	lw->label.old_border = lw->rectObj.border_width;
	X    }
	X}   
	X
	Xstatic XtGeometryResult QueryGeometry(w, proposed, desired)
	X    Widget w;
	X    XtWidgetGeometry *proposed, *desired;
	X{
	X    LabelGadget lw = (LabelGadget) w;
	X#define Set(bit) (proposed->request_mode & bit)
	X
	X    desired->width = lw->label.desired_width;
	X    desired->height = lw->label.desired_height;
	X    desired->request_mode = CWWidth | CWHeight;
	X
	X    if (Set(CWWidth) && proposed->width == desired->width &&
	X	    Set(CWHeight) && proposed->height == desired->height) {
	X	return XtGeometryYes;
	X    }
	X
	X    if (desired->width == lw->rectObj.width &&
	X	    desired->height == lw->rectObj.height) {
	X	return XtGeometryNo;
	X    }
	X    return XtGeometryAlmost;
	X#undef Set
	X}
SHAR_EOF
if test 12890 -ne "`wc -c < 'LabelGadge.c'`"
then
	echo shar: error transmitting "'LabelGadge.c'" '(should have been 12890 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Menu.c'" '(18170 characters)'
if test -f 'Menu.c'
then
	echo shar: will not over-write existing file "'Menu.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'Menu.c'
	X/***********************************************************
	XCopyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
	X
	X                        All Rights Reserved
	X
	XPermission to use, copy, modify, and distribute these examples for any
	Xpurpose and without fee is hereby granted, provided that the above
	Xcopyright notice appear in all copies and that both that copyright
	Xnotice and this permission notice appear in supporting documentation,
	Xand that the name of Digital not be used in advertising or publicity
	Xpertaining to distribution of the software without specific, written
	Xprior permission.
	X
	XDIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
	XSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
	XFITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
	XOR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
	XOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
	XOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
	XOR PERFORMANCE OF THIS SOFTWARE.
	X
	X******************************************************************/
	X
	X#include <X11/IntrinsicP.h>	/* Intrinsics header file */
	X#include <X11/StringDefs.h>	/* Resource string definitions */
	X#include "MenuP.h"		/* Menu private header file */
	X#include "LabelGadge.h"		/* To check LabelGadgets */
	X
	Xstatic Cardinal InsertBefore();
	X
	Xstatic XtResource resources[] = {
	X    {XtNinsertPosition, XtCInsertPosition,
	X	XtRFunction, sizeof(XtOrderProc),
	X        XtOffsetOf(MenuRec, composite.insert_position),
	X	XtRImmediate, (XtPointer) InsertBefore}
	X};
	X
	Xstatic Cardinal InsertBefore(w)
	X    Widget w;
	X{
	X    MenuWidget menu = (MenuWidget) XtParent(w);
	X    MenuConstraint mc = (MenuConstraint) w->core.constraints;
	X    int i;
	X
	X    if (mc->menu.insert_before == NULL) {
	X	return menu->composite.num_children;
	X    }
	X
	X    for (i = 0; i < menu->composite.num_children; i++) {
	X	if (mc->menu.insert_before == menu->composite.children[i]) {
	X	    return i;
	X	}
	X    }
	X
	X    return menu->composite.num_children;
	X}
	X
	Xstatic XtResource constraintResources[] = {
	X    {XtNinsertBefore, XtCInsertBefore, XtRWidget, sizeof(Widget),
	X	XtOffsetOf(MenuConstraintRec, menu.insert_before), 
	X	XtRImmediate, NULL},
	X};
	X
	X/* Forward declarations */
	X
	Xstatic void ClassInitialize(), ChangeManaged(), Initialize(),
	X	ConstraintInitialize(), Resize(), InsertChild(),
	X	Redisplay(), Destroy(), ConstraintGetValuesHook();
	Xstatic XtGeometryResult GeometryManager();
	Xstatic Boolean ConstraintSetValues();
	X
	Xstatic CompositeClassExtensionRec compositeExtension = {
	X    /* next_extension	    */ NULL,
	X    /* record_type	    */ NULLQUARK,
	X    /* version		    */ XtCompositeExtensionVersion,
	X    /* record_size	    */ sizeof(CompositeClassExtensionRec),
	X    /* accepts_objects	    */ TRUE
	X};
	X
	Xstatic ConstraintClassExtensionRec constraintExtension = {
	X    /* next_extension	    */ NULL,
	X    /* record_type	    */ NULLQUARK,
	X    /* version		    */ XtConstraintExtensionVersion,
	X    /* record_size	    */ sizeof(ConstraintClassExtensionRec),
	X    /* get_values_hook	    */ ConstraintGetValuesHook
	X};
	X
	XMenuClassRec menuClassRec = {
	X    /* Core class part */
	X  {
	X    /* superclass	     */	(WidgetClass) &constraintClassRec,
	X    /* class_name	     */ "Menu",
	X    /* widget_size	     */ sizeof(MenuRec),
	X    /* class_initialize      */ ClassInitialize,
	X    /* class_part_initialize */ NULL,
	X    /* class_inited          */	FALSE,
	X    /* initialize	     */	Initialize,
	X    /* initialize_hook       */	NULL,
	X    /* realize		     */	XtInheritRealize,
	X    /* actions		     */	NULL,
	X    /* num_actions	     */	0,
	X    /* resources	     */	resources,
	X    /* num_resources	     */	XtNumber(resources),
	X    /* xrm_class	     */	NULLQUARK,
	X    /* compress_motion	     */	TRUE,
	X    /* compress_exposure     */	XtExposeCompressMultiple,
	X    /* compress_enterleave   */	TRUE,
	X    /* visible_interest	     */	FALSE,
	X    /* destroy		     */	Destroy,
	X    /* resize		     */	Resize,
	X    /* expose		     */	Redisplay,
	X    /* set_values	     */	NULL,
	X    /* set_values_hook       */	NULL,			
	X    /* set_values_almost     */	XtInheritSetValuesAlmost,  
	X    /* get_values_hook       */	NULL,			
	X    /* accept_focus	     */	NULL,
	X    /* version		     */	XtVersion,
	X    /* callback offsets      */	NULL,
	X    /* tm_table              */	NULL,
	X    /* query_geometry	     */	XtInheritQueryGeometry,
	X    /* display_accelerator   */	NULL,
	X    /* extension	     */	NULL,
	X  },
	X   /* Composite class part */
	X  {
	X    /* geometry_manager	     */	GeometryManager,
	X    /* change_managed	     */	ChangeManaged,
	X    /* insert_child	     */	InsertChild,
	X    /* delete_child	     */	XtInheritDeleteChild,
	X    /* extension	     */	(XtPointer) &compositeExtension,
	X  },
	X   /* Constraint class part */
	X  {
	X   /* resources		     */ constraintResources,
	X   /* num_resources	     */ XtNumber(constraintResources),
	X   /* constraint_size	     */ sizeof(MenuConstraintRec),
	X   /* initialize	     */ ConstraintInitialize,
	X   /* destroy		     */ NULL,
	X   /* set_values	     */ ConstraintSetValues,
	X   /* extension		     */ (XtPointer) &constraintExtension,
	X  },
	X   /* Menu class part */
	X  {
	X    /* extension	     */	NULL,
	X  }
	X};
	X
	XWidgetClass menuWidgetClass = (WidgetClass) &menuClassRec;
	X
	Xstatic void InsertChild(w)
	X    Widget w;
	X{
	X    String params[2];
	X    Cardinal num_params;
	X    Widget parent = XtParent(w);
	X
	X    if (!XtIsWidget(w) && !XtIsSubclass(w, labelGadgetClass)) {
	X	params[0] = XtClass(w)->core_class.class_name;
	X	params[1] = XtClass(parent)->core_class.class_name;
	X	num_params = 2;
	X	XtAppErrorMsg(XtWidgetToApplicationContext(w),
	X		"childError", "class", "WidgetError",
	X		"Children of class %s cannot be added to %n widgets",
	X		params, &num_params);
	X    }
	X
	X    (*((CompositeWidgetClass)(menuWidgetClass->
	X	    core_class.superclass))->composite_class.insert_child) (w);
	X}
	X
	Xstatic Boolean CvtStringToWidget(dpy, args, num_args, from, to, data)
	X    Display *dpy;
	X    XrmValuePtr args;
	X    Cardinal *num_args;
	X    XrmValuePtr from, to;
	X    XtPointer *data;
	X{
	X    static Widget w;
	X    Widget parent;
	X    Boolean badConvert;
	X
	X    if (*num_args != 1) {
	X	XtAppErrorMsg(XtDisplayToApplicationContext(dpy),
	X		"wrongParameters", "cvtStringToWidget",
	X		"XtToolkitError",
	X		"StringToWidget conversion needs parent arg",
	X		(String *) NULL, (Cardinal *) NULL);
	X    }
	X
	X    /* Convert first arg into parent */
	X
	X    parent = *(Widget*) args[0].addr;
	X
	X    w = XtNameToWidget(parent, (String) from->addr);
	X    badConvert = (w == NULL);
	X
	X    if (badConvert) {
	X        XtDisplayStringConversionWarning(dpy, from->addr, "Widget");
	X    } else {
	X	if (to->addr == NULL) to->addr = (caddr_t) &w;
	X	else if (to->size < sizeof(Widget)) badConvert = TRUE;
	X	else *(Widget *) to->addr = w;
	X
	X	to->size = sizeof(Widget);
	X    }
	X    return !badConvert;
	X}
	X
	Xstatic void ClassInitialize()
	X{
	X    static XtConvertArgRec parentConvertArgs[] = {
	X	{XtBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.parent),
	X		sizeof(Widget)},
	X    };
	X
	X
	X    /* Register a converter for string to widget */
	X
	X    XtSetTypeConverter(XtRString, XtRWidget, CvtStringToWidget,
	X	    parentConvertArgs, XtNumber(parentConvertArgs),
	X	    XtCacheNone, (XtDestructor) NULL);
	X}
	X
	Xstatic void HandleMenuButton(w, client_data, event,
	X	continue_to_dispatch)
	X    Widget w;
	X    XtPointer client_data;
	X    XEvent *event;
	X    Boolean *continue_to_dispatch;
	X{
	X    switch (event->type) {
	X	case ButtonPress:
	X	    /* The new grab does an implicit AllowEvents */
	X	    (void) XtGrabPointer(w, True,
	X		    EnterWindowMask | LeaveWindowMask | 
	X			    ButtonReleaseMask,
	X		    GrabModeAsync, GrabModeAsync, None, None,
	X		    event->xbutton.time);
	X	    break;
	X
	X	case ButtonRelease:
	X	    /* Popping down also ungrabs the pointer */
	X	    XtPopdown(w);
	X	    break;
	X    }
	X}
	X
	Xstatic void Initialize(req, new)
	X    Widget req, new;
	X{
	X    ((MenuWidget) new)->menu.save_border = -1;
	X
	X    if (XtIsShell(XtParent(new))) {
	X	XtAddRawEventHandler(XtParent(new),
	X		ButtonPressMask | ButtonReleaseMask,
	X		FALSE, HandleMenuButton, NULL);
	X    }
	X}
	X
	Xstatic void ConstraintInitialize(req, new, args, num_args)
	X    Widget req, new;
	X    ArgList args;
	X    Cardinal *num_args;
	X{
	X    MenuConstraint mc = (MenuConstraint) new->core.constraints;
	X
	X    mc->menu.desired_height = new->core.height;
	X    mc->menu.desired_border_width = new->core.border_width;
	X}
	X
	Xstatic void Destroy(w)
	X    Widget w;
	X{
	X    XtRemoveRawEventHandler(XtParent(w), XtAllEvents, TRUE,
	X	    HandleMenuButton, NULL);
	X}
	X
	Xstatic void PositionChildren(menu, initiator)
	X    register MenuWidget menu;
	X    Widget initiator;
	X{
	X    int i, y;
	X    register int last_border;
	X    register Widget child;
	X    MenuConstraint mc;
	X    Boolean first = TRUE;
	X
	X    if (menu->composite.num_children == 0) return;
	X
	X    for (i = 0; i < menu->composite.num_children; i++) {
	X	child = menu->composite.children[i];
	X	if (!XtIsManaged(child)) continue;
	X	mc = (MenuConstraint) child->core.constraints;
	X
	X	if (first) {
	X	    first = FALSE;
	X	    last_border = mc->menu.desired_border_width;
	X	    y = -last_border;
	X	}
	X
	X	if (child == initiator) {
	X	    if (last_border > child->core.border_width) {
	X		y += last_border - child->core.border_width;
	X	    }
	X	    last_border = child->core.border_width;
	X
	X	    child->core.x = -last_border;
	X	    child->core.y = y;
	X	    child->core.width = menu->core.width;
	X	} else {
	X	    if (last_border > mc->menu.desired_border_width) {
	X		y += last_border - mc->menu.desired_border_width;
	X	    }
	X	    last_border = mc->menu.desired_border_width;
	X
	X	    XtConfigureWidget(child, -last_border, y,
	X		    menu->core.width, mc->menu.desired_height,
	X		    last_border);
	X	}
	X
	X	y += (int) child->core.height + last_border;
	X    }
	X}
	X
	Xstatic void Resize(w)
	X    Widget w;
	X{
	X    PositionChildren((MenuWidget) w, (Widget) NULL);
	X}
	X
	Xstatic int WidestDesiredSize(menu, initiator)
	X    MenuWidget menu;
	X    Widget initiator;
	X{
	X    register int i, width = 0;
	X    register Widget child;
	X    XtWidgetGeometry desired;
	X
	X    for (i = 0; i < menu->composite.num_children; i++) {
	X        child = menu->composite.children[i];
	X	if (!XtIsManaged(child)) continue;
	X
	X	if (child == initiator) {
	X	    if (child->core.width > width) {
	X		width = child->core.width;
	X	    }
	X	} else {
	X	    (void) XtQueryGeometry(child, NULL, &desired);
	X	    if (desired.width > width) width = desired.width;
	X	}
	X    }
	X
	X    if (width <= 0) return 1;
	X    else return width;
	X}
	X
	Xstatic void CalculateDesiredSizes(menu, width, initiator)
	X    MenuWidget menu;
	X    Dimension width;
	X    Widget initiator;
	X{
	X    XtWidgetGeometry proposed, desired;
	X    register Widget child;
	X    MenuConstraint mc;
	X    register int i;
	X
	X    for (i = 0; i < menu->composite.num_children; i++) {
	X        child = menu->composite.children[i];
	X	if (!XtIsManaged(child)) continue;
	X	mc = (MenuConstraint) child->core.constraints;
	X
	X	if (child == initiator) {
	X	    mc->menu.desired_height = child->core.height;
	X	    mc->menu.desired_border_width = 
	X		    child->core.border_width;
	X	} else {
	X	    proposed.width = width;
	X	    proposed.request_mode = CWWidth;
	X	    (void) XtQueryGeometry(child, &proposed, &desired);
	X
	X	    mc->menu.desired_height = desired.height;
	X	    mc->menu.desired_border_width = desired.border_width;
	X	}
	X    }
	X}
	X
	Xstatic void CalculateNewSize(menu, width, height, initiator)
	X    register MenuWidget menu;
	X    Dimension *width, *height;
	X    Widget initiator;
	X{
	X    register int i;
	X    register int last_border;
	X    register Widget child;
	X    int y;
	X    MenuConstraint mc;
	X    Boolean first = TRUE;
	X
	X    if (menu->composite.num_children == 0) {
	X	*width = *height = 10;	/* Arbitrary */
	X	return;
	X    }
	X
	X    *width = WidestDesiredSize(menu, initiator);
	X
	X    CalculateDesiredSizes(menu, *width, initiator);
	X
	X    for (i = 0; i < menu->composite.num_children; i++) {
	X        child = menu->composite.children[i];
	X	if (!XtIsManaged(child)) continue;
	X	mc = (MenuConstraint) child->core.constraints;
	X
	X	if (first) {
	X	    first = FALSE;
	X	    last_border = mc->menu.desired_border_width;
	X	    y = -last_border;
	X	}
	X
	X	if (last_border > mc->menu.desired_border_width) {
	X	    y += last_border - (int) mc->menu.desired_border_width;
	X	}
	X	last_border = mc->menu.desired_border_width;
	X	y += (int) mc->menu.desired_height + last_border;
	X    }    
	X    
	X    if (y <= 0) y = 1;
	X    *height = y;
	X}
	X
	Xstatic void ChangeManaged(w)
	X    Widget w;
	X{
	X    MenuWidget menu = (MenuWidget) w;
	X    XtWidgetGeometry request;
	X    XtGeometryResult result;
	X
	X    CalculateNewSize(menu, &request.width, &request.height,
	X	    (Widget) NULL);
	X
	X    if (request.width != menu->core.width ||
	X	    request.height != menu->core.height) {
	X	request.request_mode = CWWidth | CWHeight;
	X	do {
	X	    result = XtMakeGeometryRequest(w, &request, &request);
	X	} while (result == XtGeometryAlmost);
	X    }
	X
	X    PositionChildren(menu, (Widget) NULL);
	X}
	X
	Xstatic XtGeometryResult GeometryManager(w, desired, allowed)
	X    Widget w;
	X    XtWidgetGeometry *desired, *allowed;
	X{
	X    MenuWidget menu = (MenuWidget) XtParent(w);
	X    XtWidgetGeometry request;
	X    XtGeometryResult result;
	X    Dimension save_width, save_height, save_border_width;
	X
	X#define Wants(flag) (desired->request_mode & flag)
	X#define RestoreGeometry(w) { \
	X	w->core.width = save_width; \
	X	w->core.height = save_height; \
	X        w->core.border_width = save_border_width; }
	X
	X    if (menu->menu.save_border != -1) {
	X	/* This was caused by a child set-values */
	X	w->core.border_width = menu->menu.save_border;
	X	menu->menu.save_border = -1;
	X	desired->border_width -= 1000;
	X    }
	X
	X    if (Wants(CWX) || Wants(CWY)) {
	X	return XtGeometryNo;
	X    }
	X
	X    /* If only requesting a stack mode change, allow it */
	X
	X    if (!Wants(CWWidth) && !Wants(CWHeight) && !Wants(CWBorderWidth)) {
	X	return XtGeometryYes;
	X    }
	X
	X    /* Figure out how big we would be with this change */
	X
	X    save_width = w->core.width;
	X    save_height = w->core.height;
	X    save_border_width = w->core.border_width;
	X    if (Wants(CWWidth)) w->core.width = desired->width;
	X    if (Wants(CWHeight)) w->core.height = desired->height;
	X    if (Wants(CWBorderWidth)) {
	X	w->core.border_width = desired->border_width;
	X    }
	X
	X    CalculateNewSize(menu, &request.width, &request.height, w);
	X
	X    /* If the new width is the same as the old and the child requested
	X       a width change, CalculateNewSize was not able to accommodate
	X       the width change, so refuse the geometry request. */
	X
	X    if (request.width == menu->core.width && Wants(CWWidth)) {
	X	RestoreGeometry(w);
	X	return XtGeometryNo;
	X    }
	X
	X    /* If new width is equal to child's width, we are going to try
	X       to accommodate the child.  Make a geometry request.  This also
	X       covers cases where the child requested no width
	X       change since that wouldn't cause the menu to change width. */
	X
	X    if (request.width == w->core.width) {
	X	request.request_mode = CWWidth | CWHeight;
	X	if (Wants(XtCWQueryOnly)) {
	X	    request.request_mode |= XtCWQueryOnly;
	X	}
	X	result = XtMakeGeometryRequest((Widget) menu, &request, NULL);
	X
	X        /* Almost isn't good enough here; must be allowed */
	X
	X	if (result == XtGeometryAlmost) result = XtGeometryNo;
	X	if (result == XtGeometryNo || Wants(XtCWQueryOnly)) {
	X	    RestoreGeometry(w);
	X	} else PositionChildren(menu, w);
	X	return result;
	X    }
	X
	X    /* New width is different from child's width, so we want to return
	X       XtGeometryAlmost.  See if this is allowed. */
	X
	X    RestoreGeometry(w);
	X
	X    request.request_mode = CWWidth | CWHeight | XtCWQueryOnly;
	X    result = XtMakeGeometryRequest((Widget) menu, &request, NULL);
	X
	X    /* Almost isn't good enough here; must be allowed */
	X
	X    if (result != XtGeometryYes) return XtGeometryNo;
	X
	X    /* It would be allowed, so return suggested geometry */
	X
	X    *allowed = *desired;
	X    allowed->width = request.width;
	X    return XtGeometryAlmost;
	X#undef Wants
	X#undef RestoreGeometry
	X}
	X
	Xstatic Boolean ConstraintSetValues(old, req, new, args, num_args)
	X    Widget old, req, new;
	X    ArgList args;
	X    Cardinal *num_args;
	X{
	X    MenuConstraint newmc = (MenuConstraint) new->core.constraints;
	X    MenuConstraint oldmc = (MenuConstraint) old->core.constraints;
	X    register MenuWidget menu;
	X    register int i, j;
	X
	X    if (newmc->menu.insert_before != oldmc->menu.insert_before) {
	X	menu = (MenuWidget) XtParent(new);
	X
	X	/* Remove child from current position */
	X
	X	for (i = 0; i < menu->composite.num_children &&
	X		menu->composite.children[i] != new; i++) {}
	X
	X	for (; i < menu->composite.num_children - 1; i++) {
	X	    menu->composite.children[i] =
	X		    menu->composite.children[i+1];
	X	}
	X
	X	/* Find new widget to insert before */
	X
	X	for (i = 0; i < menu->composite.num_children - 1 &&
	X		menu->composite.children[i] !=
	X			newmc->menu.insert_before;
	X		i++) {}
	X
	X	/* Move the rest of them up */
	X
	X	for (j = menu->composite.num_children - 1; j > i; j--) {
	X	    menu->composite.children[j] =
	X		    menu->composite.children[j-1];
	X	}
	X
	X	menu->composite.children[i] = new;
	X	
	X	/* Cause a geometry request */
	X
	X	menu->menu.save_border = new->core.border_width;
	X	new->core.border_width += 1000;
	X    }
	X
	X    return FALSE;
	X}
	X
	Xstatic void Redisplay(w, event, region)
	X    Widget w;
	X    XEvent *event;
	X    Region region;
	X{
	X    CompositeWidget comp = (CompositeWidget) w;
	X    int i;
	X    Widget c;		/* child */
	X
	X    for (i = 0; i < comp->composite.num_children; i++) {
	X	c = comp->composite.children[i];
	X	if (XtIsManaged(c) && XtIsSubclass(c, labelGadgetClass) &&
	X		XRectInRegion(region, c->core.x, c->core.y,
	X			c->core.width + 2*c->core.border_width,
	X			c->core.height + 2*c->core.border_width)
	X		    != RectangleOut) {
	X	    (*(XtClass(c)->core_class.expose))(c, event, region);
	X        }
	X    }
	X}
	X
	Xstatic void ConstraintGetValuesHook(w, args, num_args)
	X    Widget w;
	X    ArgList args;
	X    Cardinal *num_args;
	X{
	X    register int i, j;
	X
	X    for (i = 0; i < *num_args; i++) {
	X	if (strcmp(args[i].name, XtNinsertBefore) == 0) {
	X	    MenuConstraint mc = (MenuConstraint) w->core.constraints;
	X	    MenuWidget menu = (MenuWidget) XtParent(w);
	X
	X	    for (j = 0; j < menu->composite.num_children; j++) {
	X		if (menu->composite.children[j] == w) {
	X		    if (j == menu->composite.num_children - 1) {
	X			args[i].value = NULL;
	X		    } else {
	X			*(Widget *) (args[i].value) = 
	X				menu->composite.children[j+1];
	X		    }
	X		    break;
	X		}
	X	    } /* End of for loop checking children */
	X	}
	X    }
	X}
SHAR_EOF
if test 18170 -ne "`wc -c < 'Menu.c'`"
then
	echo shar: error transmitting "'Menu.c'" '(should have been 18170 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'MenuItem.c'" '(3153 characters)'
if test -f 'MenuItem.c'
then
	echo shar: will not over-write existing file "'MenuItem.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'MenuItem.c'
	X/***********************************************************
	XCopyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
	X
	X                        All Rights Reserved
	X
	XPermission to use, copy, modify, and distribute these examples for any
	Xpurpose and without fee is hereby granted, provided that the above
	Xcopyright notice appear in all copies and that both that copyright
	Xnotice and this permission notice appear in supporting documentation,
	Xand that the name of Digital not be used in advertising or publicity
	Xpertaining to distribution of the software without specific, written
	Xprior permission.
	X
	XDIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
	XSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
	XFITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
	XOR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
	XOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
	XOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
	XOR PERFORMANCE OF THIS SOFTWARE.
	X
	X******************************************************************/
	X
	X#include <X11/IntrinsicP.h>	/* Intrinsics header file */
	X#include "MenuItemP.h"		/* MenuItem private header file */
	X
	Xstatic char defaultTranslations[] =
	X	"<EnterWindow>	: invert()		\n\
	X	 <LeaveWindow>	: uninvert()		\n\
	X	 <BtnUp>	: notify() uninvert()";
	X
	X/* Class record declaration */
	X
	XMenuItemClassRec menuItemClassRec = {
	X    /* Core class part */
	X  {
	X    /* superclass	     */	(WidgetClass) &pushbuttonClassRec,
	X    /* class_name	     */	"MenuItem",
	X    /* widget_size	     */	sizeof(MenuItemRec),
	X    /* class_initialize      */ NULL,
	X    /* class_part_initialize */	NULL,
	X    /* class_inited          */	FALSE,
	X    /* initialize	     */	NULL,
	X    /* initialize_hook       */	NULL,		
	X    /* realize		     */	XtInheritRealize,
	X    /* actions		     */	NULL,
	X    /* num_actions	     */	0,
	X    /* resources	     */	NULL,
	X    /* num_resources	     */	0,
	X    /* xrm_class	     */	NULLQUARK,
	X    /* compress_motion	     */	TRUE,
	X    /* compress_exposure     */	XtExposeCompressMultiple,
	X    /* compress_enterleave   */	TRUE,
	X    /* visible_interest	     */	FALSE,
	X    /* destroy		     */	NULL,
	X    /* resize		     */	XtInheritResize,
	X    /* expose		     */	XtInheritExpose,
	X    /* set_values	     */	NULL,
	X    /* set_values_hook       */	NULL,			
	X    /* set_values_almost     */	XtInheritSetValuesAlmost,  
	X    /* get_values_hook       */	NULL,			
	X    /* accept_focus	     */	NULL,
	X    /* version		     */	XtVersion,
	X    /* callback offsets      */ NULL,
	X    /* tm_table              */ defaultTranslations,
	X    /* query_geometry	     */	XtInheritQueryGeometry,
	X    /* display_accelerator   */ XtInheritDisplayAccelerator,
	X    /* extension    	     */ NULL
	X  },
	X    /* Label class part */
	X  {
	X    /* select_text	     */ InheritSelectText,
	X    /* extension    	     */ NULL
	X  },
	X    /* Pushbutton class part */
	X  {
	X    /* extension    	     */ NULL
	X  },
	X    /* MenuItem class part */
	X  {
	X    /* extension    	     */ NULL
	X  }
	X};
	X
	X/* Class record pointer */
	X
	XWidgetClass menuItemWidgetClass = (WidgetClass) &menuItemClassRec;
SHAR_EOF
if test 3153 -ne "`wc -c < 'MenuItem.c'`"
then
	echo shar: error transmitting "'MenuItem.c'" '(should have been 3153 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'MinMax.c'" '(15738 characters)'
if test -f 'MinMax.c'
then
	echo shar: will not over-write existing file "'MinMax.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'MinMax.c'
	X/***********************************************************
	XCopyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
	X
	X                        All Rights Reserved
	X
	XPermission to use, copy, modify, and distribute these examples for any
	Xpurpose and without fee is hereby granted, provided that the above
	Xcopyright notice appear in all copies and that both that copyright
	Xnotice and this permission notice appear in supporting documentation,
	Xand that the name of Digital not be used in advertising or publicity
	Xpertaining to distribution of the software without specific, written
	Xprior permission.
	X
	XDIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
	XSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
	XFITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
	XOR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
	XOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
	XOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
	XOR PERFORMANCE OF THIS SOFTWARE.
	X
	X******************************************************************/
	X
	X#include <X11/IntrinsicP.h>	/* Intrinsics header file */
	X#include <X11/StringDefs.h>	/* Resource string definitions */
	X#include "MinMaxP.h"		/* MinMax private header file */
	X#include "LabelGadge.h"		/* To check LabelGadgets */
	X
	X#define Offset(field) XtOffsetOf(MinMaxRec, minMax.field)
	X
	Xstatic XtResource resources[] = {
	X    {XtNmargin, XtCMargin, XtRDimension, sizeof(Dimension),
	X	Offset(margin), XtRImmediate, (XtPointer) 10},
	X};
	X
	X#undef Offset
	X
	X#define Offset(field) XtOffsetOf(MinMaxConstraintRec, field)
	X
	Xstatic XtResource constraintResources[] = {
	X    {XtNminWidth, XtCMinWidth, XtRShort, sizeof(short),
	X        Offset(minMax.min_width), XtRImmediate, (XtPointer) -1},
	X    {XtNmaxWidth, XtCMaxWidth, XtRShort, sizeof(short),
	X        Offset(minMax.max_width), XtRImmediate, (XtPointer) -1},
	X    {XtNminHeight, XtCMinHeight, XtRShort, sizeof(short),
	X        Offset(minMax.min_height), XtRImmediate, (XtPointer) -1},
	X    {XtNmaxHeight, XtCMaxHeight, XtRShort, sizeof(short),
	X        Offset(minMax.max_height), XtRImmediate, (XtPointer) -1},
	X};
	X#undef Offset
	X
	X/* Forward declarations */
	X
	Xstatic void ChangeManaged(), Initialize(), ConstraintInitialize(),
	X	Resize(), InsertChild(), DeleteChild(), Redisplay();
	Xstatic XtGeometryResult GeometryManager();
	Xstatic Boolean SetValues(), AcceptFocus(), ConstraintSetValues();
	X
	Xstatic CompositeClassExtensionRec compositeExtension = {
	X    /* next_extension	    */ NULL,
	X    /* record_type	    */ NULLQUARK,
	X    /* version		    */ XtCompositeExtensionVersion,
	X    /* record_size	    */ sizeof(CompositeClassExtensionRec),
	X    /* accepts_objects	    */ TRUE
	X};
	X
	XMinMaxClassRec minMaxClassRec = {
	X    /* Core class part */
	X  {
	X    /* superclass	     */	(WidgetClass) &constraintClassRec,
	X    /* class_name	     */ "MinMax",
	X    /* widget_size	     */ sizeof(MinMaxRec),
	X    /* class_initialize      */ NULL,
	X    /* class_part_initialize */ NULL,
	X    /* class_inited          */	FALSE,
	X    /* initialize	     */	Initialize,
	X    /* initialize_hook       */	NULL,
	X    /* realize		     */	XtInheritRealize,
	X    /* actions		     */	NULL,
	X    /* num_actions	     */	0,
	X    /* resources	     */	resources,
	X    /* num_resources	     */	XtNumber(resources),
	X    /* xrm_class	     */	NULLQUARK,
	X    /* compress_motion	     */	TRUE,
	X    /* compress_exposure     */	XtExposeCompressMultiple,
	X    /* compress_enterleave   */	TRUE,
	X    /* visible_interest	     */	FALSE,
	X    /* destroy		     */	NULL,
	X    /* resize		     */	Resize,
	X    /* expose		     */	Redisplay,
	X    /* set_values	     */	SetValues,
	X    /* set_values_hook       */	NULL,			
	X    /* set_values_almost     */	XtInheritSetValuesAlmost,  
	X    /* get_values_hook       */	NULL,			
	X    /* accept_focus	     */	AcceptFocus,
	X    /* version		     */	XtVersion,
	X    /* callback offsets      */	NULL,
	X    /* tm_table              */	NULL,
	X    /* query_geometry	     */	XtInheritQueryGeometry,
	X    /* display_accelerator   */	NULL,
	X    /* extension	     */	NULL,
	X  },
	X   /* Composite class part */
	X  {
	X    /* geometry_manager	     */	GeometryManager,
	X    /* change_managed	     */	ChangeManaged,
	X    /* insert_child	     */	InsertChild,
	X    /* delete_child	     */	DeleteChild,
	X    /* extension	     */	(XtPointer) &compositeExtension,
	X  },
	X   /* Constraint class part */
	X  {
	X   /* resources		     */ constraintResources,
	X   /* num_resources	     */ XtNumber(constraintResources),
	X   /* constraint_size	     */ sizeof(MinMaxConstraintRec),
	X   /* initialize	     */ ConstraintInitialize,
	X   /* destroy		     */ NULL,
	X   /* set_values	     */ ConstraintSetValues,
	X   /* extension		     */ NULL
	X  },
	X   /* MinMax class part */
	X  {
	X    /* extension	     */	NULL,
	X  }
	X};
	X
	XWidgetClass minMaxWidgetClass = (WidgetClass) &minMaxClassRec;
	X
	Xstatic void InsertChild(w)
	X    Widget w;
	X{
	X    String params[2];
	X    Cardinal num_params;
	X    Widget parent = XtParent(w);
	X
	X    if (!XtIsWidget(w) && !XtIsSubclass(w, labelGadgetClass)) {
	X	params[0] = XtClass(w)->core_class.class_name;
	X	params[1] = XtClass(parent)->core_class.class_name;
	X	num_params = 2;
	X	XtAppErrorMsg(XtWidgetToApplicationContext(w),
	X		"childError", "class", "WidgetError",
	X		"Children of class %s cannot be added to %n widgets",
	X		params, &num_params);
	X    }
	X
	X    (*((CompositeWidgetClass)(minMaxWidgetClass->
	X	    core_class.superclass))->composite_class.insert_child) (w);
	X}
	X
	Xstatic void DeleteChild(w)
	X    Widget w;
	X{
	X    MinMaxWidget minMax = (MinMaxWidget) XtParent(w);
	X
	X    if (minMax->minMax.last_focus == w) {
	X	minMax->minMax.last_focus = NULL;
	X    }
	X
	X    (*((CompositeWidgetClass)(minMaxWidgetClass->
	X	    core_class.superclass))->composite_class.delete_child) (w);
	X}
	X
	Xstatic void Initialize(req, new, args, num_args)
	X    Widget req, new;
	X    ArgList args;
	X    Cardinal *num_args;
	X{
	X    ((MinMaxWidget) new)->minMax.last_focus = NULL;
	X}
	X
	Xstatic void CheckConstraint(w, smaller, larger, which)
	X    Widget w;
	X    short *smaller, *larger;
	X    String which;
	X{
	X    String params[3];
	X    Cardinal num_params;
	X
	X    if (*smaller > *larger) {
	X	params[0] = params[1] = which;
	X	params[2] = XtName(w);
	X	num_params = 3;
	X	XtAppWarningMsg(XtWidgetToApplicationContext(w),
	X		"constraintError",
	X		"width", "WidgetError", 
	X		"Min %s greater than max %s for widget %s",
	X		params, &num_params);
	X	*smaller = *larger;
	X    }
	X}
	X
	Xstatic void ResizeWithinConstraints(w, width, height)
	X    Widget w;
	X    Dimension *width, *height;
	X{
	X    register MinMaxConstraint mmc =
	X	    (MinMaxConstraint) w->core.constraints;
	X
	X    if (*width < mmc->minMax.min_width) {
	X	*width = mmc->minMax.min_width;
	X    } else if (*width > mmc->minMax.max_width) {
	X	*width = mmc->minMax.max_width;
	X    }
	X
	X    if (*height < mmc->minMax.min_height) {
	X	*height = mmc->minMax.min_height;
	X    } else if (*height > mmc->minMax.max_height) {
	X	*height = mmc->minMax.max_height;
	X    }
	X}
	X
	Xstatic void ConstraintInitialize(req, new, args, num_args)
	X    Widget req, new;
	X    ArgList args;
	X    Cardinal *num_args;
	X{
	X    MinMaxConstraint mmc = (MinMaxConstraint) new->core.constraints;
	X    Dimension width = new->core.width, height = new->core.height;
	X#define MAXDIM 32768
	X
	X    if (mmc->minMax.min_width == -1 && mmc->minMax.max_width == -1) {
	X	mmc->minMax.min_width = mmc->minMax.max_width = width;
	X    }
	X    if (mmc->minMax.min_height == -1 && mmc->minMax.max_height == -1) {
	X	mmc->minMax.min_height = mmc->minMax.max_height = height;
	X    }
	X
	X    if (mmc->minMax.min_width == -1) mmc->minMax.min_width = 1;
	X    if (mmc->minMax.max_width == -1) mmc->minMax.max_width = MAXDIM;
	X    if (mmc->minMax.min_height == -1) mmc->minMax.min_height = 1;
	X    if (mmc->minMax.max_height == -1) mmc->minMax.max_height = MAXDIM;
	X
	X    CheckConstraint(new, &mmc->minMax.min_width,
	X	    &mmc->minMax.max_width, "width");
	X    CheckConstraint(new, &mmc->minMax.min_height,
	X	    &mmc->minMax.max_height, "height");
	X    ResizeWithinConstraints(new, &width, &height);
	X
	X    if (width != new->core.width || height != new->core.height) {
	X	XtResizeWidget(new, width, height);
	X    }
	X#undef MAXDIM
	X}
	X
	Xstatic void CalculateNewSize(minMax, width, height)
	X    MinMaxWidget minMax;
	X    register Dimension *width, *height;
	X{
	X    register Widget child;
	X    register int i;
	X    int right, bottom;
	X
	X    *width = *height = 0;
	X
	X    for (i = 0; i < minMax->composite.num_children; i++) {
	X        child = minMax->composite.children[i];
	X	if (!XtIsManaged(child)) continue;
	X	right = child->core.x + child->core.width +
	X		2 * child->core.border_width;
	X	bottom = child->core.y + child->core.height +
	X		2 * child->core.border_width;
	X	if (right > (int) *width) *width = right;
	X	if (bottom > (int) *height) *height = bottom;
	X    }
	X
	X    *width += minMax->minMax.margin;
	X    *height += minMax->minMax.margin;
	X
	X    if (*width == 0) *width = 1;
	X    if (*height == 0) *height = 1;
	X}
	X
	Xstatic void ResizeChildren(minMax, initiator)
	X    MinMaxWidget minMax;
	X    Widget initiator;
	X{
	X    register Widget child;
	X    register MinMaxConstraint mmc;
	X    register int i;
	X    int right, bottom;
	X    int new_width, new_height;
	X    int minMax_right = minMax->core.width - minMax->minMax.margin,
	X	minMax_bottom = minMax->core.height - minMax->minMax.margin;
	X
	X    for (i = 0; i < minMax->composite.num_children; i++) {
	X        child = minMax->composite.children[i];
	X	if (!XtIsManaged(child) || child == initiator) continue;
	X
	X	mmc = (MinMaxConstraint) child->core.constraints;
	X	new_width = child->core.width;
	X	new_height = child->core.height;
	X
	X	right = child->core.x + child->core.width +
	X		2 * child->core.border_width;
	X	bottom = child->core.y + child->core.height +
	X		2 * child->core.border_width;
	X
	X	if (right > minMax_right &&
	X		child->core.width > mmc->minMax.min_width) {
	X	    new_width -= right - minMax_right;
	X	    if (new_width < mmc->minMax.min_width) {
	X		new_width = mmc->minMax.min_width;
	X	    }
	X	} else if (right < minMax_right &&
	X		child->core.width < mmc->minMax.max_width) {
	X	    new_width += minMax_right - right;
	X	    if (new_width > mmc->minMax.max_width) {
	X		new_width = mmc->minMax.max_width;
	X	    }
	X	}
	X
	X	if (bottom > minMax_bottom &&
	X		child->core.height > mmc->minMax.min_height) {
	X	    new_height -= bottom - minMax_bottom;
	X	    if (new_height < mmc->minMax.min_height) {
	X		new_height = mmc->minMax.min_height;
	X	    }
	X	} else if (bottom < minMax_bottom &&
	X		child->core.height < mmc->minMax.max_height) {
	X	    new_height += minMax_bottom - bottom;
	X	    if (new_height > mmc->minMax.max_height) {
	X		new_height = mmc->minMax.max_height;
	X	    }
	X	}
	X
	X	XtResizeWidget(child, new_width, new_height,
	X		child->core.border_width);
	X    }
	X}
	X
	Xstatic void Resize(w)
	X    Widget w;
	X{
	X    ResizeChildren((MinMaxWidget) w, (Widget) NULL);
	X}
	X
	Xstatic void ChangeManaged(w)
	X    Widget w;
	X{
	X    MinMaxWidget minMax = (MinMaxWidget) w;
	X    XtWidgetGeometry request;
	X    XtGeometryResult result;
	X
	X    CalculateNewSize(minMax, &request.width, &request.height);
	X
	X    if (request.width != minMax->core.width ||
	X	    request.height != minMax->core.height) {
	X	request.request_mode = CWWidth | CWHeight;
	X	do {
	X	    result = XtMakeGeometryRequest(w,
	X		    &request, (XtWidgetGeometry *) NULL);
	X	} while (result == XtGeometryAlmost);
	X
	X	if (result == XtGeometryYes) {
	X	    ResizeChildren(minMax, (Widget) NULL);
	X	}
	X    }
	X}
	X
	Xstatic XtGeometryResult GeometryManager(w, desired, allowed)
	X    Widget w;
	X    XtWidgetGeometry *desired, *allowed;
	X{
	X    MinMaxWidget minMax = (MinMaxWidget) XtParent(w);
	X    MinMaxConstraint mmc = (MinMaxConstraint) w->core.constraints;
	X    XtWidgetGeometry request;
	X    XtGeometryResult result;
	X    Dimension save_width, save_height, save_border_width;
	X    Position save_x, save_y;
	X
	X#define Wants(flag) (desired->request_mode & flag)
	X#define RestoreGeometry(w) { \
	X    w->core.x = save_x;		w->core.y = save_y; \
	X    w->core.width = save_width; w->core.height = save_height; \
	X    w->core.border_width = save_border_width; }
	X
	X    /* If the desired change goes outside the constraints, say no */
	X
	X    if ((Wants(CWWidth) && (desired->width < mmc->minMax.min_width ||
	X		    desired->width > mmc->minMax.max_width)) ||
	X	    (Wants(CWHeight) &&
	X		    (desired->height < mmc->minMax.min_height ||
	X		    desired->height > mmc->minMax.max_height))) {
	X	return XtGeometryNo;
	X    }
	X
	X    /* Figure out how big we would be with this change */
	X
	X    save_x = w->core.x;
	X    save_y = w->core.y;
	X    save_width = w->core.width;
	X    save_height = w->core.height;
	X    save_border_width = w->core.border_width;
	X    if (Wants(CWX)) w->core.x = desired->x;
	X    if (Wants(CWY)) w->core.y = desired->y;
	X    if (Wants(CWWidth)) w->core.width = desired->width;
	X    if (Wants(CWHeight)) w->core.height = desired->height;
	X    if (Wants(CWBorderWidth)) {
	X	w->core.border_width = desired->border_width;
	X    }
	X
	X    CalculateNewSize(minMax, &request.width, &request.height);
	X
	X    if (request.width == minMax->core.width && 
	X	    request.height == minMax->core.height) {
	X	if (Wants(XtCWQueryOnly)) RestoreGeometry(w);
	X	return XtGeometryYes;
	X    }
	X
	X    /* We need to change size in order to accommodate; see if we can */
	X
	X    request.request_mode = CWWidth | CWHeight;
	X    if (Wants(XtCWQueryOnly)) request.request_mode |= XtCWQueryOnly;
	X
	X    result = XtMakeGeometryRequest((Widget) minMax, &request, NULL);
	X    if (result == XtGeometryAlmost) result = XtGeometryNo;
	X
	X    if (result == XtGeometryYes && !Wants(XtCWQueryOnly)) {
	X	ResizeChildren(minMax, w);
	X	return XtGeometryYes;
	X    }
	X
	X    /* Undo the saved changes */
	X
	X    RestoreGeometry(w);
	X    return result;
	X#undef Wants
	X#undef RestoreGeometry
	X}
	X
	Xstatic Boolean SetValues(old, req, new, args, num_args)
	X    Widget old, req, new;
	X    ArgList args;
	X    Cardinal *num_args;
	X{
	X    register MinMaxWidget oldminMax = (MinMaxWidget) old;
	X    register MinMaxWidget newminMax = (MinMaxWidget) new;
	X
	X    if (newminMax->minMax.margin != oldminMax->minMax.margin ||
	X	    newminMax->core.width == 0 ||
	X	    newminMax->core.height == 0) {
	X	CalculateNewSize(newminMax,
	X		&newminMax->core.width, &newminMax->core.height);
	X    }
	X
	X    return FALSE;
	X}
	X
	Xstatic Boolean ConstraintSetValues(old, req, new, args, num_args)
	X    Widget old, req;
	X    ArgList args;
	X    Cardinal *num_args;
	X    register Widget new;
	X{
	X    register MinMaxConstraint mmc = 
	X	    (MinMaxConstraint) new->core.constraints;
	X
	X    CheckConstraint(new, &mmc->minMax.min_width,
	X	    &mmc->minMax.max_width, "width");
	X    CheckConstraint(new, &mmc->minMax.min_height,
	X	    &mmc->minMax.max_height, "height");
	X    ResizeWithinConstraints(new, &new->core.width, &new->core.height);
	X
	X    return FALSE;
	X}
	X
	Xstatic Boolean AcceptFocus(w, time)
	X    Widget w;
	X    Time *time;
	X{
	X    MinMaxWidget minMax = (MinMaxWidget) w;
	X    register int i;
	X
	X    if (minMax->minMax.last_focus != NULL && 
	X	    XtIsManaged(minMax->minMax.last_focus)) {
	X	if (XtCallAcceptFocus(minMax->minMax.last_focus, time)) {
	X	    return TRUE;
	X	}
	X    }
	X
	X    for (i = 0; i < minMax->composite.num_children; i++) {
	X	if (!XtIsManaged(minMax->composite.children[i])) continue;
	X	if (XtCallAcceptFocus(minMax->composite.children[i], time)) {
	X	    minMax->minMax.last_focus = minMax->composite.children[i];
	X	    return TRUE;
	X	}
	X    }
	X
	X    minMax->minMax.last_focus = NULL;
	X    return FALSE;
	X}
	X
	Xstatic void Redisplay(w, event, region)
	X    Widget w;
	X    XEvent *event;
	X    Region region;
	X{
	X    CompositeWidget comp = (CompositeWidget) w;
	X    int i;
	X    Widget c;		/* child */
	X
	X    for (i = 0; i < comp->composite.num_children; i++) {
	X	c = comp->composite.children[i];
	X	if (XtIsManaged(c) && XtIsSubclass(c, labelGadgetClass) &&
	X		XRectInRegion(region, c->core.x, c->core.y,
	X			c->core.width + 2*c->core.border_width,
	X			c->core.height + 2*c->core.border_width)
	X		    != RectangleOut) {
	X	    (*(XtClass(c)->core_class.expose))(c, event, region);
	X        }
	X    }
	X}
SHAR_EOF
if test 15738 -ne "`wc -c < 'MinMax.c'`"
then
	echo shar: error transmitting "'MinMax.c'" '(should have been 15738 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Pushbutton.c'" '(13083 characters)'
if test -f 'Pushbutton.c'
then
	echo shar: will not over-write existing file "'Pushbutton.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'Pushbutton.c'
	X/***********************************************************
	XCopyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
	X
	X                        All Rights Reserved
	X
	XPermission to use, copy, modify, and distribute these examples for any
	Xpurpose and without fee is hereby granted, provided that the above
	Xcopyright notice appear in all copies and that both that copyright
	Xnotice and this permission notice appear in supporting documentation,
	Xand that the name of Digital not be used in advertising or publicity
	Xpertaining to distribution of the software without specific, written
	Xprior permission.
	X
	XDIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
	XSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
	XFITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
	XOR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
	XOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
	XOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
	XOR PERFORMANCE OF THIS SOFTWARE.
	X
	X******************************************************************/
	X
	X#include <string.h>		/* Needed for string manipulation */
	X#include <X11/IntrinsicP.h>	/* Intrinsics header file */
	X#include <X11/StringDefs.h>	/* Resource string definitions */
	X#include "PushbuttoP.h"		/* Pushbutton private header file */
	X
	Xstatic void InsPixel(), InsPixmap();
	X
	X#define Offset(field) XtOffsetOf(PushbuttonRec, pushbutton.field)
	X
	Xstatic XtResource resources[] = { 
	X    {XtNcallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
	X	Offset(callback), XtRCallback, (XtPointer) NULL},
	X    {"pri.vate", "Pri.vate", XtRBoolean, sizeof(Boolean),
	X	Offset(use_insens_pixel), XtRImmediate, (XtPointer) TRUE},
	X    {XtNinsensitiveForeground, XtCForeground, XtRPixel, sizeof(Pixel),
	X	Offset(insensitive_foreground),
	X	XtRCallProc, (XtPointer) InsPixel},
	X    {XtNinsensitivePixmap, XtCPixmap, XtRPixmap, sizeof(Pixmap),
	X	Offset(insensitive_pixmap),
	X	XtRCallProc, (XtPointer) InsPixmap},
	X    {XtNhighlightBorder, XtCBorderWidth,
	X	XtRDimension, sizeof(Dimension),
	X	Offset(highlight_border), XtRImmediate, (XtPointer) 1},
	X    {XtNaccelString, XtCAccelString, XtRString, sizeof(String),
	X	XtOffsetOf(PushbuttonRec, label.accel_string),
	X	XtRString, NULL},
	X    {XtNacceleratorString, XtCAcceleratorString,
	X	XtRString, sizeof(String),
	X	Offset(accelerator_string), XtRString, NULL},
	X    {XtNborderWidth, XtCBorderWidth,
	X	XtRDimension, sizeof(Dimension),
	X	XtOffsetOf(PushbuttonRec, core.border_width),
	X	XtRImmediate, (XtPointer) 1},
	X};  
	X
	X#undef Offset
	X
	Xstatic void InsPixel(w, offset, value)
	X    Widget w;
	X    int offset;		/* Not used */
	X    XrmValue *value;
	X{
	X    PushbuttonWidget p = (PushbuttonWidget) w;
	X
	X    /* Any value will work; it won't be used */
	X    value->addr = (caddr_t) &p->label.foreground;
	X    p->pushbutton.use_insens_pixel = FALSE;
	X}
	X
	X/* Return a 2x2 pixmap with the foreground at 50% */
	X
	Xstatic Pixmap GetPixmap(pw)
	X    PushbuttonWidget pw;
	X{
	X    static char bits[] = {0x01, 0x02};
	X
	X    return XCreatePixmapFromBitmapData(XtDisplay(pw),
	X	    RootWindowOfScreen(XtScreen(pw)), bits, 2, 2,
	X	    pw->label.foreground, pw->core.background_pixel,
	X	    pw->core.depth);
	X}
	X
	Xstatic void InsPixmap(w, offset, value)
	X    Widget w;
	X    int offset;		/* Not used */
	X    XrmValue *value;
	X{
	X    PushbuttonWidget pw = (PushbuttonWidget) w;
	X    static Pixmap pixmap;
	X
	X    if (pw->pushbutton.use_insens_pixel) pixmap = None;
	X    else pixmap = GetPixmap(pw);
	X
	X    value->addr = (caddr_t) &pixmap;
	X}
	X
	Xstatic char defaultTranslations[] =
	X	"<EnterWindow>	: highlight()		\n\
	X	 <LeaveWindow>	: unhighlight()		\n\
	X	 <Btn1Down>	: invert()		\n\
	X	 <Btn1Up>	: notify() uninvert()";
	X
	Xstatic void Highlight(), Unhighlight(), Invert(), Uninvert(), Notify();
	X
	Xstatic XtActionsRec actions[] = {
	X  {"highlight",		Highlight},
	X  {"unhighlight",	Unhighlight},
	X  {"invert",		Invert},
	X  {"uninvert",		Uninvert},
	X  {"notify",		Notify},
	X};
	X
	X/* Forward declarations */
	X
	Xstatic void Initialize(), DisplayAccelerator(), Destroy(), Redisplay();
	Xstatic Boolean SetValues();
	X
	X/* Class record declaration */
	X
	XPushbuttonClassRec pushbuttonClassRec = {
	X    /* Core class part */
	X  {
	X    /* superclass	     */	(WidgetClass) &labelClassRec,
	X    /* class_name	     */	"Pushbutton",
	X    /* widget_size	     */	sizeof(PushbuttonRec),
	X    /* class_initialize      */ NULL,
	X    /* class_part_initialize */	NULL,
	X    /* class_inited          */	FALSE,
	X    /* initialize	     */	Initialize,
	X    /* initialize_hook       */	NULL,		
	X    /* realize		     */	XtInheritRealize,
	X    /* actions		     */	actions,
	X    /* num_actions	     */	XtNumber(actions),
	X    /* resources	     */	resources,
	X    /* num_resources	     */	XtNumber(resources),
	X    /* xrm_class	     */	NULLQUARK,
	X    /* compress_motion	     */	TRUE,
	X    /* compress_exposure     */	XtExposeCompressMultiple,
	X    /* compress_enterleave   */	TRUE,
	X    /* visible_interest	     */	FALSE,
	X    /* destroy		     */	NULL,
	X    /* resize		     */	XtInheritResize,
	X    /* expose		     */	Redisplay,
	X    /* set_values	     */	SetValues,
	X    /* set_values_hook       */	NULL,			
	X    /* set_values_almost     */	XtInheritSetValuesAlmost,  
	X    /* get_values_hook       */	NULL,			
	X    /* accept_focus	     */	NULL,
	X    /* version		     */	XtVersion,
	X    /* callback offsets      */ NULL,
	X    /* tm_table              */ defaultTranslations,
	X    /* query_geometry	     */	XtInheritQueryGeometry,
	X    /* display_accelerator   */ DisplayAccelerator,
	X    /* extension    	     */ NULL
	X  },
	X    /* Label class part */
	X  {
	X    /* select_text	     */ InheritSelectText,
	X    /* extension    	     */ NULL
	X  },
	X    /* Pushbutton class part */
	X  {
	X    /* extension    	     */ NULL
	X  }
	X};
	X
	X/* Class record pointer */
	X
	XWidgetClass pushbuttonWidgetClass = (WidgetClass) &pushbuttonClassRec;
	X
	Xstatic void Highlight(w, event, params, num_params)
	X    Widget w;
	X    XEvent *event;
	X    String *params;
	X    Cardinal *num_params;
	X{
	X    PushbuttonWidget pw = (PushbuttonWidget) w;
	X
	X    if (!pw->pushbutton.highlighted) {
	X	pw->pushbutton.highlighted = TRUE;
	X	if (XtIsRealized(w)) {
	X	    XClearWindow(XtDisplay(w), XtWindow(w));
	X	    (*(XtClass(w)->core_class.expose))(w, event, NULL);
	X	}
	X    }
	X}
	X
	Xstatic void Unhighlight(w, event, params, num_params)
	X    Widget w;
	X    XEvent *event;
	X    String *params;
	X    Cardinal *num_params;
	X{
	X    PushbuttonWidget pw = (PushbuttonWidget) w;
	X
	X    if (pw->pushbutton.highlighted) {
	X	pw->pushbutton.highlighted = FALSE;
	X	if (XtIsRealized(w)) {
	X	    XClearWindow(XtDisplay(w), XtWindow(w));
	X	    (*(XtClass(w)->core_class.expose))(w, event, NULL);
	X	}
	X    }
	X}
	X
	Xstatic void Invert(w, event, params, num_params)
	X    Widget w;
	X    XEvent *event;
	X    String *params;
	X    Cardinal *num_params;
	X{
	X    PushbuttonWidget pw = (PushbuttonWidget) w;
	X
	X    if (!pw->pushbutton.inverted) {
	X	pw->pushbutton.inverted = TRUE;
	X	pw->label.current_gc = pw->pushbutton.inverted_gc;
	X	if (XtIsRealized(w)) {
	X	    XClearWindow(XtDisplay(w), XtWindow(w));
	X	    (*(XtClass(w)->core_class.expose))(w, event, NULL);
	X	}
	X    }
	X}
	X
	Xstatic void Uninvert(w, event, params, num_params)
	X    Widget w;
	X    XEvent *event;
	X    String *params;
	X    Cardinal *num_params;
	X{
	X    PushbuttonWidget pw = (PushbuttonWidget) w;
	X
	X    if (pw->pushbutton.inverted) {
	X	pw->pushbutton.inverted = FALSE;
	X	if (XtIsSensitive(w)) {
	X	    pw->label.current_gc = pw->label.gc;
	X	} else pw->label.current_gc = pw->pushbutton.insensitive_gc;
	X
	X	if (XtIsRealized(w)) {
	X	    XClearWindow(XtDisplay(w), XtWindow(w));
	X	    (*(XtClass(w)->core_class.expose))(w, event, NULL);
	X	}
	X    }
	X}
	X
	Xstatic void Notify(w, event, params, num_params)
	X    Widget w;
	X    XEvent *event;
	X    String *params;
	X    Cardinal *num_params;
	X{
	X    PushbuttonWidget pw = (PushbuttonWidget) w;
	X
	X    /* If event is a button event, and the event's window is the
	X       widget's window, we were invoked normally.  Make sure
	X       the pointer is really in the window */
	X
	X    if (event != NULL && event->type == ButtonRelease &&
	X	    event->xany.window == XtWindow(w)) {
	X	XButtonEvent *b = &event->xbutton;
	X	if (b->x < 0 || b->y < 0 ||
	X	    b->x >= w->core.width || b->y >= w->core.height) return;
	X    }
	X
	X    XtCallCallbackList(pw, pw->pushbutton.callback, NULL);
	X}
	X
	Xstatic GC GetInvertedGC(pw)
	X    PushbuttonWidget pw;
	X{
	X    XGCValues	values;
	X
	X    values.foreground = pw->core.background_pixel;
	X    values.font = pw->label.font->fid;
	X    return XtGetGC((Widget) pw, GCForeground | GCFont, &values);
	X}
	X
	Xstatic GC GetInsensitiveGC(pw)
	X    PushbuttonWidget pw;
	X{
	X    XGCValues	values;
	X
	X    values.font = pw->label.font->fid;
	X
	X    if (pw->pushbutton.use_insens_pixel) {
	X	values.foreground = pw->pushbutton.insensitive_foreground;
	X	return XtGetGC((Widget) pw, GCForeground | GCFont, &values);
	X    } else {
	X	values.tile = pw->pushbutton.insensitive_pixmap;
	X	values.fill_style = FillTiled;
	X	return XtGetGC((Widget) pw,
	X		GCTile | GCFont | GCFillStyle, &values);
	X    }
	X}
	X
	Xstatic void Initialize(req, new)
	X    Widget req, new;
	X{
	X    PushbuttonWidget pw = (PushbuttonWidget) new;
	X
	X    pw->pushbutton.insensitive_gc = GetInsensitiveGC(pw);
	X    pw->pushbutton.inverted_gc = GetInvertedGC(pw);
	X    pw->pushbutton.accelerator_string =
	X	    XtNewString(pw->pushbutton.accelerator_string);
	X
	X    pw->pushbutton.highlighted = pw->pushbutton.inverted = FALSE;
	X
	X    if (!XtIsSensitive(pw)) {
	X	pw->label.current_gc = pw->pushbutton.insensitive_gc;
	X    }
	X}
	X
	Xstatic Boolean SetValues(old, req, new, args, num_args)
	X    Widget  old, req, new;
	X    ArgList args;
	X    Cardinal *num_args;
	X{
	X    PushbuttonWidget oldpw = (PushbuttonWidget) old;
	X    PushbuttonWidget newpw = (PushbuttonWidget) new;
	X
	X#define NE(field) (oldpw->field != newpw->field)
	X
	X    /* If insensitive fields or button's font has changed, 
	X       update insensitive GC */
	X
	X    if (NE(pushbutton.insensitive_foreground)) {
	X	newpw->pushbutton.use_insens_pixel = TRUE;
	X    }
	X
	X    if (NE(pushbutton.insensitive_pixmap)) {
	X	if (newpw->pushbutton.insensitive_pixmap == None) {
	X	    newpw->pushbutton.insensitive_pixmap = GetPixmap(newpw);
	X	}
	X        newpw->pushbutton.use_insens_pixel = FALSE;
	X    }
	X
	X    if (NE(pushbutton.insensitive_foreground) || 
	X	    NE(pushbutton.insensitive_pixmap) || NE(label.font->fid)) {
	X	XtReleaseGC(newpw, oldpw->pushbutton.insensitive_gc);
	X	newpw->pushbutton.insensitive_gc = GetInsensitiveGC(newpw);
	X
	X	if (newpw->label.current_gc ==
	X		oldpw->pushbutton.insensitive_gc) {
	X	    newpw->label.current_gc = newpw->pushbutton.insensitive_gc;
	X	}
	X    }
	X
	X    /* If background or font has changed, update inverted GC */
	X
	X    if (NE(core.background_pixel) || NE(label.font->fid)) {
	X	XtReleaseGC(newpw, oldpw->pushbutton.inverted_gc);
	X	newpw->pushbutton.inverted_gc = GetInvertedGC(newpw);
	X
	X	if (newpw->pushbutton.inverted) {
	X	    newpw->label.current_gc = newpw->pushbutton.inverted_gc;
	X	}
	X    }
	X
	X    /* If sensitivity changing, adjust appearance */
	X
	X    if (NE(core.sensitive) || NE(core.ancestor_sensitive)) {
	X	if (XtIsSensitive(newpw)) {	/* Just made sensitive */
	X	    newpw->label.current_gc = newpw->label.gc;
	X
	X	} else {			/* Just made insensitive */
	X	    newpw->label.current_gc = 
	X		    newpw->pushbutton.insensitive_gc;
	X
	X	    /* If currently highlighted, will never receive
	X	       leave event to unhighlight, so unhighlight */
	X	    newpw->pushbutton.highlighted = FALSE;
	X	}
	X    }
	X
	X    /* If current graphics context has changed, inverted
	X       and foreground has changed, or highlighted and highlight
	X       width has changed, redisplay */
	X
	X    return NE(label.current_gc) ||
	X	   (NE(label.foreground) && newpw->pushbutton.inverted) ||
	X	   (NE(pushbutton.highlight_border) &&
	X		   newpw->pushbutton.highlighted);
	X#undef NE
	X}
	X
	Xstatic void Destroy(w)
	X    Widget w;
	X{
	X    PushbuttonWidget pw = (PushbuttonWidget) w;
	X
	X    /* Release the GCs */
	X
	X    XtReleaseGC(w, pw->pushbutton.insensitive_gc);
	X    XtReleaseGC(w, pw->pushbutton.inverted_gc);
	X
	X    XtFree(pw->pushbutton.accelerator_string);
	X    XtFree(pw->label.accel_string);
	X}
	X
	Xstatic void Redisplay(w, event, region)
	X    Widget w;
	X    XEvent *event;
	X    Region region;
	X{
	X    PushbuttonWidget pw = (PushbuttonWidget) w;
	X    int offset;
	X
	X    /* If inverted, fill background with the foreground color */
	X
	X    if (pw->pushbutton.inverted) {
	X	XFillRectangle(XtDisplay(w), XtWindow(w), pw->label.gc,
	X		0, 0, pw->core.width, pw->core.height);
	X    }
	X
	X    /* If highlighted, draw highlighting border */
	X
	X    if (pw->pushbutton.highlighted) {
	X	offset = pw->pushbutton.highlight_border / 2;
	X	XDrawRectangle(XtDisplay(w), XtWindow(w), pw->label.current_gc,
	X		offset, offset,
	X		pw->core.width - pw->pushbutton.highlight_border,
	X		pw->core.height - pw->pushbutton.highlight_border);
	X    }
	X
	X    /* Make Label redisplay the string */
	X
	X    (*pushbuttonWidgetClass->core_class.superclass->core_class.expose)
	X	    (w, event, region);
	X}
	X
	Xstatic void DisplayAccelerator(w, string)
	X    Widget w;
	X    String string;
	X{
	X    PushbuttonWidget pw = (PushbuttonWidget) w;
	X    Arg args[1];
	X
	X    if (pw->pushbutton.accelerator_string != NULL) {
	X	XtSetArg(args[0], XtNaccelString,
	X		pw->pushbutton.accelerator_string);
	X	XtSetValues(w, args, 1);
	X    }
	X}
SHAR_EOF
if test 13083 -ne "`wc -c < 'Pushbutton.c'`"
then
	echo shar: error transmitting "'Pushbutton.c'" '(should have been 13083 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.