/**
 *
 * $Id: IconG.c,v 1.2 1997/10/30 03:09:21 rwscott Exp $
 *
 * Copyright (C) 1995 Free Software Foundation, Inc.
 *
 * This file is part of the GNU LessTif Library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 **/

static const char rcsid[] = "$Id: IconG.c,v 1.2 1997/10/30 03:09:21 rwscott Exp $";

#include <LTconfig.h>
#include <XmI/XmI.h>

#include <Xm/XmP.h>
#include <Xm/CacheP.h>
#include <Xm/CascadeB.h>
#include <Xm/CascadeBG.h>
#include <Xm/ManagerP.h>
#include <Xm/MenuShell.h>
#include <Xm/MenuUtilP.h>
#include <Xm/IconGP.h>
#include <Xm/RowColumnP.h>
#include <Xm/XmosP.h>
#include <X11/Xfuncs.h>
#include <X11/ShellP.h>

#include <XmI/DebugUtil.h>

#ifndef XmUNSPECIFIED
#define XmUNSPECIFIED (~0)
#endif

/* Forward Declarations */

static void class_initialize();

static void class_part_initialize(WidgetClass w_class);

static void initialize(Widget request, Widget new_w,
		       ArgList args, Cardinal *num_args);

static void destroy(Widget w);

static void resize(Widget w);

static void expose(Widget w, XEvent *event, Region region);

static XtGeometryResult query_geometry(Widget w,
				       XtWidgetGeometry *proposed,
				       XtWidgetGeometry *answer);

static void get_values_hook(Widget w, ArgList args, Cardinal *num_args);

static void input_dispatch(Widget gadget, XEvent *event, Mask event_mask);

static Boolean set_values(Widget current, Widget request, Widget new_w,
			  ArgList args, Cardinal *num_args);

static void secondary_object_create(Widget request, Widget new_w,
				    ArgList args, Cardinal *num_args);

static void initialize_prehook(Widget request,
			       Widget new_w, ArgList args, Cardinal *num_args);

static void initialize_posthook(Widget request,
				Widget new_w, ArgList args, Cardinal *num_args);

static Boolean set_values_prehook(Widget old, Widget request, Widget new_w,
				  ArgList args, Cardinal *num_args);

static Boolean set_values_posthook(Widget old, Widget request, Widget new_w,
				   ArgList args, Cardinal *num_args);

static void get_values_prehook(Widget new_w, ArgList args, Cardinal *num_args);

static void get_values_posthook(Widget new_w, ArgList args, Cardinal *num_args);

static Cardinal get_sec_res_data(WidgetClass wc,
				 XmSecondaryResourceData **data);


#if 0
static void Arm(Widget w, XEvent *event,
		String *params, Cardinal *num_params);

static void Activate(Widget w, XEvent *event,
		     String *params, Cardinal *num_params);

static void Disarm(Widget w, XEvent *event,
		   String *params, Cardinal *num_params);

static void ArmAndActivate(Widget w, XEvent *event,
			   String *params, Cardinal *num_params);

static void Help(Widget w, XEvent *event,
		 String *params, Cardinal *num_params);

static void EnterWindow(Widget w, XEvent *event,
			String *params, Cardinal *num_params);

static void LeaveWindow(Widget w, XEvent *event,
			String *params, Cardinal *num_params);

static void ButtonUp(Widget w, XEvent *event,
		     String *params, Cardinal *num_params);

static void ButtonDown(Widget w, XEvent *event,
		       String *params, Cardinal *num_params);
#endif


int _XmIconCacheCompare(XtPointer A, XtPointer B);

/*
 * resources
 */
#define Offset(field) XtOffsetOf(XmIconGCacheObjRec, icon_cache.field)
static XtResource cache_resources[] =
{
    {
	XmNmultiClick, XmCMultiClick, XmRMultiClick,
	sizeof(unsigned char), Offset(multiClick),
	XmRImmediate, (XtPointer)((unsigned char)XmUNSPECIFIED)
    },
    {
	XmNdefaultButtonShadowThickness, XmCDefaultButtonShadowThickness, XmRHorizontalDimension,
	sizeof(Dimension), Offset(default_button_shadow_thickness),
	XtRImmediate, (XtPointer)0
    },
    {
	XmNfillOnArm, XmCFillOnArm, XmRBoolean,
	sizeof(Boolean), Offset(fill_on_arm),
	XmRImmediate, (XtPointer)True
    },
    {
	XmNarmColor, XmCArmColor, XmRPixel,
	sizeof(Pixel), Offset(arm_color),
	XmRCallProc, (XtPointer)_XmSelectColorDefault
    },
    {
	XmNarmPixmap, XmCArmPixmap, XmRGadgetPixmap,
	sizeof(Pixmap), Offset(arm_pixmap),
	XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP
    }
};

static XmSyntheticResource cache_syn_resources[] =
{
    {
	XmNdefaultButtonShadowThickness,
	sizeof(Dimension), Offset(default_button_shadow_thickness),
	_XmFromHorizontalPixels, _XmToHorizontalPixels
    }
};

/* *INDENT-OFF* */
XmIconGCacheObjClassRec xmIconGCacheObjClassRec = {
    /* Object class part */
    {
	/* superclass            */ (WidgetClass) &xmExtClassRec,
        /* class_name            */ "XmIconGCacheObjClass",
	/* widget_size           */ sizeof(XmIconGCacheObjRec),
	/* class_initialize      */ NULL,
	/* class_part_initialize */ NULL,
	/* class_inited          */ False,
	/* initialize            */ NULL,
	/* initialize_hook       */ NULL,
	/* realize               */ NULL,
	/* actions               */ NULL,
	/* num_actions           */ 0,
	/* resources             */ cache_resources,
	/* num_resources         */ XtNumber(cache_resources),
	/* xrm_class             */ NULLQUARK,
	/* compress_motion       */ 0,
	/* compress_exposure     */ 0,
	/* compress_enterleave   */ 0,
	/* visible_interest      */ 0,
	/* destroy               */ NULL,
	/* resize                */ NULL,
	/* expose                */ NULL,
	/* set_values            */ NULL,
	/* set_values_hook       */ NULL,
	/* set_values_almost     */ NULL,
	/* get_values_hook       */ NULL,
	/* accept_focus          */ NULL,
	/* version               */ XtVersion,
	/* callback offsets      */ NULL,
	/* tm_table              */ NULL,
	/* query_geometry        */ NULL,
        /* display_accelerator   */ NULL,
	/* extension             */ NULL
    },
    /* XmExtObject part */
    {
        /* syn_resources      */ cache_syn_resources,
        /* num_syn_resources  */ XtNumber(cache_syn_resources),
        /* extension          */ NULL
    },
    /* IconGCacheObj part */
    {
	/* foo                */ 0
    }
};

#undef Offset
#define Offset(field) XtOffsetOf(XmIconGadgetRec, icon.field)

/* Resources for the icon class */
static XtResource resources[] = {
    {
	XmNdetail, XmCDetail, XmRXmStringTable,
	sizeof(XmStringTable), Offset(detail),
	XmRStringTable, (XtPointer)NULL
    },
    {
	XmNdetailCount, XmCDetailCount, XmRInt,
	sizeof(int), Offset(detailCount),
	XmRImmediate, (XtPointer)0
    },
    {
	XmNfontList, XmCFontList, XmRFontList,
	sizeof(XmFontList), Offset(font),
	XmRImmediate, (XtPointer)NULL
    },
    {
	XmNlabelString, XmCXmString, XmRXmString,
	sizeof(XmString), Offset(labelString),
	XmRImmediate, (XtPointer)NULL
    },
    {
	XmNlargeIconMask, XmCIconMask, XmRGadgetPixmap,
	sizeof(Pixmap), Offset(largeIconMask),
	XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP
    },
    {
	XmNlargeIconPixmap, XmCIconPixmap, XmRGadgetPixmap,
	sizeof(Pixmap), Offset(largeIconPixmap),
	XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP
    },
    {
	XmNrenderTable, XmCRenderTable, XmRRenderTable,
	sizeof(XmRenderTable), Offset(renderTable),
	XmRImmediate, (XtPointer)NULL
    },
    {
	XmNsmallIconMask, XmCIconMask, XmRGadgetPixmap,
	sizeof(Pixmap), Offset(smallIconMask),
	XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP
    },
    {
	XmNsmallIconPixmap, XmCIconPixmap, XmRGadgetPixmap,
	sizeof(Pixmap), Offset(smallIconPixmap),
	XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP
    },
    {
	XmNviewType, XmCViewType, XmRViewType,
	sizeof(unsigned char), Offset(viewType),
	XmRImmediate, (XtPointer)XmLARGE_ICON
    },
    {
	XmNvisualEmphasis, XmCVisualEmphasis, XmRVisualEmphasis,
	sizeof(unsigned char), Offset(visualEmphasis),
	XmRImmediate, (XtPointer)XmNOT_SELECTED
    },
    {
	XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension,
	sizeof(Dimension), XtOffsetOf(XmIconGadgetRec, gadget.shadow_thickness),
	XmRImmediate, (XtPointer)2
    },
    {
	XmNtraversalOn, XmCTraversalOn, XmRBoolean,
	sizeof(Boolean), XtOffsetOf(XmIconGadgetRec, gadget.traversal_on),
	XmRImmediate, (XtPointer)True
    },
    {
	XmNhighlightThickness, XmCHighlightThickness, XmRHorizontalDimension,
	sizeof(Dimension), XtOffsetOf(XmIconGadgetRec,gadget.highlight_thickness),
	XmRImmediate, (XtPointer)2
    }
};

static XmSyntheticResource syn_resources[] = {
    {
	XmNlabelString,
	sizeof(XmString), Offset(labelString),
	_XmExportLabelString, NULL
    }
};

static XmCacheClassPart cache_part = {
    /* cache head part */
    {
        /* next         */ NULL,
        /* prev         */ NULL,
        /* ref_count    */ 0
    },
    _XmCacheCopy,
    _XmCacheDelete,
    _XmIconCacheCompare
};

static XmBaseClassExtRec _XmIconGRectClassExtRec = {
    /* next_extension            */ NULL,
    /* record_type               */ NULLQUARK,                             
    /* version                   */ XmBaseClassExtVersion,
    /* size                      */ sizeof(XmBaseClassExtRec),
    /* initialize_prehook        */ initialize_prehook,
    /* set_values_prehook        */ set_values_prehook,
    /* initialize_posthook       */ initialize_posthook,
    /* set_values_posthook       */ set_values_posthook,
    /* secondary_object_class    */ (WidgetClass)&xmIconGCacheObjClassRec,
    /* secondary_object_create   */ secondary_object_create,
    /* get_secondary_resources   */ get_sec_res_data,
    /* fast_subclass             */ { 0 },
    /* get_values_prehook        */ get_values_prehook,
    /* get_values_posthook       */ get_values_posthook,
    /* class_part_init_prehook   */ NULL,
    /* class_part_init_posthook  */ NULL,
    /* ext_resources             */ NULL,
    /* compiled_ext_resources    */ NULL,
    /* num_ext_resources         */ 0,
    /* use_sub_resources         */ False,
    /* widget_navigable          */ XmInheritWidgetNavigable,
    /* focus_change              */ XmInheritFocusChange,
    /* wrapper_data              */ NULL
};

static XmGadgetClassExtRec _XmIconGadgetClassExtRec = {
    /* next_extension            */ NULL,
    /* record_type               */ NULLQUARK,
    /* version                   */ XmGadgetClassExtVersion,
    /* size                      */ sizeof(XmGadgetClassExtRec),
    /* widget_baseline_proc      */ NULL,
    /* display_rect_proc         */ NULL,
};

XmIconGadgetClassRec xmIconGadgetClassRec = {
    /* RectObj class part */
    {
	/* superclass            */ (WidgetClass) &xmGadgetClassRec,
	/* class_name            */ "XmIconGadget",
	/* widget_size           */ sizeof(XmIconGadgetRec),
	/* class_initialize      */ class_initialize,
	/* class_part_initialize */ class_part_initialize,
	/* class_inited          */ False,
	/* initialize            */ initialize,
	/* initialize_hook       */ NULL,
	/* realize               */ NULL,
	/* actions               */ NULL,
	/* num_actions           */ 0,
	/* resources             */ resources,
	/* num_resources         */ XtNumber(resources),
	/* xrm_class             */ NULLQUARK,
	/* compress_motion       */ False,
	/* compress_exposure     */ XtExposeNoCompress,
	/* compress_enterleave   */ False,
 	/* visible_interest      */ False,
	/* destroy               */ destroy,
	/* resize                */ resize,
	/* expose                */ expose,
	/* set_values            */ set_values,
	/* set_values_hook       */ NULL,
	/* set_values_almost     */ XtInheritSetValuesAlmost,
	/* get_values_hook       */ get_values_hook,
	/* accept_focus          */ NULL,
	/* version               */ XtVersion,
	/* callback offsets      */ NULL,
	/* tm_table              */ NULL,
	/* query_geometry        */ query_geometry,
	/* display_accelerator   */ NULL,
	/* extension             */ (XtPointer)&_XmIconGRectClassExtRec
    },
    /* XmGadget part */
    {
	/* border_highlight   */ XmInheritBorderHighlight, 
	/* border_unhighlight */ XmInheritBorderUnhighlight, /* FIX ME */
	/* arm_and_activate   */ NULL,
	/* input_dispatch     */ input_dispatch,
	/* visual_change      */ NULL,
	/* syn_resources      */ syn_resources,
	/* num_syn_resources  */ XtNumber(syn_resources),
	/* cache_part         */ &cache_part,
	/* extension          */ (XtPointer)&_XmIconGadgetClassExtRec
    },
    /* XmIconGadget part */
    {
	/* extension          */ NULL, 
    },
};
/* *INDENT-ON* */

WidgetClass xmIconGadgetClass = (WidgetClass)&xmIconGadgetClassRec;

/* 
 * Some #defines to make the code below more readable
 */
#if 0
#define IN_MENU(w) (LabG_MenuType(w) == XmMENU_POPUP || \
                    LabG_MenuType(w) == XmMENU_PULLDOWN)
#endif

/******************************* GADGET PART *********************************/
static void
secondary_object_create(Widget request, Widget new_w,
			ArgList args, Cardinal *num_args)
{
    XmBaseClassExt *bce;
    XtPointer nsec, rsec;
    XmWidgetExtData ed;
    int size;

    DEBUGOUT(XdbDebug(__FILE__, new_w,
		      "IconGCacheRec %s being initialized.\n",
		      XtName(new_w)));

    bce = _XmGetBaseClassExtPtr(XtClass(new_w), XmQmotif);

    size = (*bce)->secondaryObjectClass->core_class.widget_size;
    nsec = _XmExtObjAlloc(size);
    rsec = _XmExtObjAlloc(size);

    ((XmExtRec *)nsec)->object.self = (Widget)nsec;
    ((XmExtRec *)nsec)->object.widget_class = (*bce)->secondaryObjectClass;
    ((XmExtRec *)nsec)->object.parent = XtParent(new_w);
    ((XmExtRec *)nsec)->object.xrm_name = new_w->core.xrm_name;
    ((XmExtRec *)nsec)->object.being_destroyed = False;
    ((XmExtRec *)nsec)->object.destroy_callbacks = NULL;
    ((XmExtRec *)nsec)->object.constraints = NULL;

    ExtObj_LogicalParent(nsec) = new_w;
    ExtObj_ExtensionType(nsec) = XmCACHE_EXTENSION;

    XtGetSubresources(new_w, nsec, NULL, NULL,
		      (*bce)->secondaryObjectClass->core_class.resources,
		      (*bce)->secondaryObjectClass->core_class.num_resources,
		      args, *num_args);

    ed = (XmWidgetExtData)XtMalloc(sizeof(XmWidgetExtDataRec));
    ed->widget = (Widget)nsec;
    ed->reqWidget = (Widget)rsec;

    bcopy(nsec, rsec, size);
    ((XmExtRec *)rsec)->object.self = (Widget)rsec;

    _XmPushWidgetExtData(new_w, ed, XmCACHE_EXTENSION);

#if 0
    LabG_Cache(new_w) = &(((XmLabelGCacheObject)nsec)->label_cache);
    LabG_Cache(request) = &(((XmLabelGCacheObject)rsec)->label_cache);
#endif

    IG_Cache(new_w) = &(((XmIconGCacheObject)nsec)->icon_cache);
    IG_Cache(request) = &(((XmIconGCacheObject)rsec)->icon_cache);
}

int
_XmIconCacheCompare(XtPointer A, XtPointer B)
{
    return !bcmp(((XmIconGCacheObjPart *)A),
		 ((XmIconGCacheObjPart *)B),
		 sizeof(XmIconGCacheObjPart));
}

/******************************* GADGET PART *********************************/
static void
class_initialize()
{
#if 0
    XtResourceList combined, labels;
    int ncom;
    Cardinal nlabels;
#endif

    /* don't let the nulls fool you.  look at the header file -- the arg
     * isn't used. */
    ClassCacheHead(IG_ClassCachePart(NULL)).prev =
	&ClassCacheHead(IG_ClassCachePart(NULL));
    ClassCacheHead(IG_ClassCachePart(NULL)).next =
	&ClassCacheHead(IG_ClassCachePart(NULL));

    _XmIconGRectClassExtRec.record_type = XmQmotif;
#if 0

    /*
     * Label subclasses (ToggleBG, PushBG, CascadeBG) have a problem.  Since
     * we do all the subpart manipulation in the pre- and post- hooks, and
     * since those hooks aren't chained, we have to either make multiple
     * calls to XtGetSubresources/Xt[Get|Set]Subvalues, or merge the resource
     * lists.  Since I just wrote _XmTransformSubresources, seems like a
     * waste not to use it.
     */
    ncom = XtNumber(cache_resources) +
	xmLabelGCacheObjClassRec.object_class.num_resources;

    _XmTransformSubResources(xmLabelGCacheObjClassRec.object_class.resources,
			   xmLabelGCacheObjClassRec.object_class.num_resources,
			     &labels, &nlabels);

    combined = (XtResourceList)XtMalloc(sizeof(XtResource) * ncom);
    bcopy(labels, combined, nlabels * sizeof(XtResource));
    bcopy(cache_resources,
	  &combined[nlabels],
	  XtNumber(cache_resources) * sizeof(XtResource));
    XtFree((char *)labels);

    xmIconGCacheObjClassRec.object_class.resources = combined;
    xmIconGCacheObjClassRec.object_class.num_resources = ncom;
#endif
}

static void
class_part_initialize(WidgetClass widget_class)
{
    _XmFastSubclassInit(widget_class, XmICON_GADGET_BIT);
}

static void
CreateNormalGC(Widget w)
{
    XGCValues values;
    XtGCMask mask;

    mask = GCForeground | GCBackground | GCFillStyle | GCFunction |
	GCSubwindowMode | GCGraphicsExposures | GCPlaneMask;
    values.function = GXcopy;
    values.plane_mask = -1;
    values.subwindow_mode = ClipByChildren;
    values.graphics_exposures = False;
    values.foreground = XmParentForeground(w);
    values.background = XmParentBackground(w);
    values.fill_style = FillSolid;

    IG_NormalGC(w) = XtGetGC(w, mask, &values);
}

#if 0
static void
CreateBackgroundGC(Widget w)
{
    XGCValues values;
    XtGCMask mask;

    mask = GCForeground | GCBackground | GCFillStyle | GCFunction |
	GCSubwindowMode | GCGraphicsExposures | GCPlaneMask;
    values.function = GXcopy;
    values.plane_mask = -1;
    values.subwindow_mode = ClipByChildren;
    values.graphics_exposures = False;
    values.foreground = XmParentBackground(w);
    values.background = XmParentForeground(w);
    values.fill_style = FillSolid;

    IG_BackgroundGC(w) = XtGetGC(w, mask, &values);
}
#endif

static void
initialize_prehook(Widget request, Widget new_w,
		   ArgList args, Cardinal *num_args)
{
    DEBUGOUT(XdbDebug(__FILE__, new_w, "IconG InitializePrehook\n"));
}

static void
initialize_posthook(Widget request, Widget new_w,
		    ArgList args, Cardinal *num_args)
{
    XmWidgetExtData ext;

    DEBUGOUT(XdbDebug(__FILE__, new_w, "IconG InitializePosthook\n"));

    /* don't let the null fool you */
#if 0
    LabG_Cache(new_w) = (XmLabelGCacheObjPart *)
	_XmCachePart(LabG_ClassCachePart(NULL),
		     (XtPointer)LabG_Cache(new_w),
		     sizeof(XmLabelGCacheObjPart));
#endif
    IG_Cache(new_w) = (XmIconGCacheObjPart *)
	_XmCachePart(IG_ClassCachePart(NULL),
		     (XtPointer)IG_Cache(new_w),
		     sizeof(XmIconGCacheObjPart));

    _XmPopWidgetExtData(new_w, &ext, XmCACHE_EXTENSION);
    _XmExtObjFree((XtPointer)ext->widget);
    _XmExtObjFree((XtPointer)ext->reqWidget);
    XtFree((char *)ext);
}

void
_XmCalcIconGDimensions(Widget w)
{
Dimension TextHeight, TextWidth;
unsigned int IconHeight, IconWidth;

    DEBUGOUT(XdbDebug(__FILE__, w, "_XmCalcIconGDimensions\n"));
    if (_XmStringIsXmString((XmString)IG_Label(w)))
    {
	IG_Label(w) = _XmStringCreate((XmString)IG_Label(w));
    }

    _XmStringExtent(IG_Font(w),
		    IG_Label(w),
		    &TextWidth,
		    &TextHeight);
    DEBUGOUT(XdbDebug(__FILE__, w, "\t Text width %d height %d\n",
    		TextWidth, TextHeight));

    {
    unsigned int tmp;
    int tmpx,tmpy;
    Window tmpwin;
    unsigned Depth;

    XGetGeometry(XtDisplayOfObject(w),
		 IG_SmallIconPixmap(w),
		 &tmpwin,
		 &tmpx, &tmpy,
		 &IconWidth, &IconHeight,
		 &tmp, &Depth);
    }
    DEBUGOUT(XdbDebug(__FILE__, w, "\t Icon width %d height %d\n",
    		IconWidth, IconHeight));

    XtWidth(w) = TextWidth + IconWidth
	    + 2 * (G_ShadowThickness(w) 
	    + G_HighlightThickness(w));
    XtHeight(w) = TextHeight > IconHeight ? TextHeight : IconHeight
	    + 2 * G_HighlightThickness(w);
    DEBUGOUT(XdbDebug(__FILE__, w, "\t width %d height %d\n",
    		XtWidth(w), XtHeight(w)));
}

static void
initialize(Widget request, Widget new_w,
	   ArgList args, Cardinal *num_args)
{
    DEBUGOUT(XdbDebug(__FILE__, new_w,
		      "initialize: %i args\n"
		      "\trequest X %5i Y %5i W %5i H %5i\n"
		      "\t  new_w X %5i Y %5i W %5i H %5i\n",
		      *num_args,
		      XtX(request), XtY(request),
		      XtWidth(request), XtHeight(request),
		      XtX(new_w), XtY(new_w),
		      XtWidth(new_w), XtHeight(new_w)));
    DEBUGOUT(XdbPrintArgList(__FILE__, new_w, args, *num_args, False));

    /* get the default fontlist if the label was created without one. */
    /* this should come from the renderTable (whatever that is??) FIXME */
    if (IG_Font(new_w) == (XmFontList)XmUNSPECIFIED ||
	IG_Font(new_w) == NULL)
    {
	IG_Font(new_w) = _XmGetDefaultFontList(new_w, XmLABEL_FONTLIST);
    }
    /* if the user specified one, COPY it */
    else
    {
	IG_Font(new_w) = XmFontListCopy(IG_Font(new_w));
    }

    /* If the label was not initialized with the resource labelString set,
       use its name -- the follow _XmString code comes from MegaButton */
    if (IG_Label(new_w) == (_XmString)XmUNSPECIFIED ||
	IG_Label(new_w) == (_XmString)0)
    {				/* Shouldn't be necessary but is */
	XmString xmstring;

	xmstring = _XmOSGetLocalizedString((char *)NULL,
					   (Widget)new_w,
					   XmNlabelString,
					   XtName(new_w));

	IG_Label(new_w) = _XmStringCreate(xmstring);
    }

    if (_XmStringIsXmString((XmString)IG_Label(new_w)))
    {
	IG_Label(new_w) = _XmStringCreate((XmString)IG_Label(new_w));
    }

    if (IG_LargeIconPixmap(new_w) != XmUNSPECIFIED_PIXMAP &&
        IG_LargeIconMask(new_w) == XmUNSPECIFIED_PIXMAP)
    {
    }

    if (IG_SmallIconPixmap(new_w) != XmUNSPECIFIED_PIXMAP &&
        IG_SmallIconMask(new_w) == XmUNSPECIFIED_PIXMAP)
    {
    }

    if (IG_RenderTable(new_w) != (XmRenderTable)NULL)
    {
    }

#if 0
/* We do not have a container yet!!! */
    if (XmIsContainerWidget(XtParent(new_w)) &&
        (Container_EntryViewType(XtParent(new_w)) == XmLARGE_ICON ||
         Container_EntryViewType(XtParent(new_w)) == XmSMALL_ICON))
    {
    	IG_ViewType(new_w) = Container_ViewType(XtParent(new_w));
    }
#endif

    /* have to check request since new_w may have been polluted by a
     * superclass 
     */
    if (XtWidth(request) == (Dimension)0)
    {
	XtWidth(new_w) = 0;
    }
    if (XtHeight(request) == (Dimension)0)
    {
	XtHeight(new_w) = 0;
    }

    _XmCalcIconGDimensions(new_w);
    resize(new_w);

    /*
     * the user might have wanted something.  Change it back, if so
     */
    if (XtWidth(request) != 0)
    {
	XtWidth(new_w) = XtWidth(request);
    }
    if (XtHeight(request) != 0)
    {
	XtHeight(new_w) = XtHeight(request);
    }

    /* surge protection */
    if (XtWidth(new_w) == 0)
    {
	XtWidth(new_w) = 1;
    }
    if (XtHeight(new_w) == 0)
    {
	XtHeight(new_w) = 1;
    }

    CreateNormalGC(new_w);

    if (!XtIsSubclass(XtParent(new_w), xmManagerWidgetClass))
    {
	_XmError(new_w, "parent should be manager.");
    }

#if 0
    if (LabG_Pixmap(new_w) == XmUNSPECIFIED_PIXMAP &&
	IG_ArmPixmap(new_w) != XmUNSPECIFIED_PIXMAP)
    {

	LabG_Pixmap(new_w) = IG_ArmPixmap(new_w);

	if (XtWidth(request) == 0)
	{
	    XtWidth(new_w) = 0;
	}
	if (XtHeight(request) == 0)
	{
	    XtHeight(new_w) = 0;
	}

	_XmCalcLabelGDimensions(new_w);

	(*xmLabelGadgetClassRec.rect_class.resize) (new_w);
    }

    IG_UnarmPixmap(new_w) = LabG_Pixmap(new_w);

    if (IN_MENU(new_w))
    {
	LabG_Highlight(new_w) = 0;
	/* FIX ME - I just added the line below because I think it belongs here;
	 * not sure if it's right though. Danny 18/5/1996 */
	G_TraversalOn(new_w) = True;
    }
    else
    {
	/* take care of the default button shadow stuff */
	/*
	 * This new code adjusts button size in two cases : when ShowAsDefault
	 * is non-zero, and when DefaultButtonShadow is non-zero.
	 */
	/*
	 * This really new code finally figures out what that damned
	 * compatible flag does.  Back in the days of 1.1 and earlier,
	 * DefaultButtonShadow didn't exist.  Lesstif has come full
	 * circle, in the same way and for the same reason I suspect
	 * Motif did -- to avoid unnecessary geometry negotiation.
	 * What our original code did caused geometry negotiation to happen
	 * in the set_values method when we changed ShowAsDefault -- even
	 * though we weren't actually changing the geometry of the widget...
	 * See the tail end of the set_values method for changing ShowAsDefault
	 * MLM
	 */

	if (IG_DefaultButtonShadowThickness(new_w) > 0)
	{
	    IG_Compatible(new_w) = False;
	}
	else
	{
	    IG_Compatible(new_w) = True;
	}

	if (IG_Compatible(new_w))
	{
	    IG_DefaultButtonShadowThickness(new_w) = IG_ShowAsDefault(new_w);
	}

	if (IG_DefaultButtonShadowThickness(new_w))
	{
	    margin = 2 * IG_DefaultButtonShadowThickness(new_w) + LabG_Shadow(new_w);
	    margin_extra = Xm3D_ENHANCE_PIXEL;

	    LabG_MarginLeft(new_w) = margin + margin_extra;
	    LabG_MarginRight(new_w) = margin + margin_extra;
	    LabG_MarginTop(new_w) = margin + margin_extra;
	    LabG_MarginBottom(new_w) = margin + margin_extra;

	    XtWidth(new_w) += (margin + margin_extra) * 2;
	    XtHeight(new_w) += 2 * (margin + margin_extra);

	    (*xmLabelGadgetClassRec.rect_class.resize) (new_w);

	}
    }

    G_EventMask(new_w) = XmARM_EVENT | XmACTIVATE_EVENT | XmENTER_EVENT |
	XmLEAVE_EVENT | XmFOCUS_IN_EVENT | XmFOCUS_OUT_EVENT |
	XmMULTI_ARM_EVENT | XmMULTI_ACTIVATE_EVENT |
	XmHELP_EVENT | XmBDRAG_EVENT;
#endif
}

static void
destroy(Widget w)
{
    _XmCacheDelete((XtPointer)IG_Cache(w));
}

static void
resize(Widget w)
{
    DEBUGOUT(XdbDebug(__FILE__, w,"resize\n"));

    if (!XmIsLabelGadget(w))
    {
	return;
    }
}

static Boolean
set_values_prehook(Widget old, Widget request, Widget new_w,
		   ArgList args, Cardinal *num_args)
{
    XmBaseClassExt *bce;
    XmWidgetExtData ed;
    int size;
    XtPointer nsec, rsec;

    bce = _XmGetBaseClassExtPtr(XtClass(new_w), XmQmotif);
    size = (*bce)->secondaryObjectClass->core_class.widget_size;

    nsec = _XmExtObjAlloc(size);
    rsec = _XmExtObjAlloc(size);

    ((XmExtRec *)nsec)->object.self = (Widget)nsec;
    ((XmExtRec *)nsec)->object.widget_class = (*bce)->secondaryObjectClass;
    ((XmExtRec *)nsec)->object.parent = XtParent(new_w);
    ((XmExtRec *)nsec)->object.xrm_name = new_w->core.xrm_name;
    ((XmExtRec *)nsec)->object.being_destroyed = False;
    ((XmExtRec *)nsec)->object.destroy_callbacks = NULL;
    ((XmExtRec *)nsec)->object.constraints = NULL;

    ExtObj_LogicalParent(nsec) = new_w;
    ExtObj_ExtensionType(nsec) = XmCACHE_EXTENSION;

#if 0
    bcopy(LabG_Cache(new_w),
	  &((XmLabelGCacheObject)nsec)->label_cache,
	  sizeof(XmLabelGCacheObjPart));
#endif
    bcopy(IG_Cache(new_w),
	  &((XmIconGCacheObject)nsec)->icon_cache,
	  sizeof(XmIconGCacheObjPart));

    ed = (XmWidgetExtData)XtMalloc(sizeof(XmWidgetExtDataRec));
    ed->widget = (Widget)nsec;
    ed->reqWidget = (Widget)rsec;

    _XmPushWidgetExtData(new_w, ed, XmCACHE_EXTENSION);

    _XmGadgetImportSecondaryArgs(new_w, args, num_args);

    XtSetSubvalues((XtPointer)nsec,
		   (*bce)->secondaryObjectClass->core_class.resources,
		   (*bce)->secondaryObjectClass->core_class.num_resources,
		   args, *num_args);

    bcopy(nsec, rsec, size);

#if 0
    LabG_Cache(new_w) = &(((XmIconGCacheObject)nsec)->label_cache);
    LabG_Cache(request) = &(((XmIconGCacheObject)rsec)->label_cache);
#endif
    IG_Cache(new_w) = &(((XmIconGCacheObject)nsec)->icon_cache);
    IG_Cache(request) = &(((XmIconGCacheObject)rsec)->icon_cache);

    _XmExtImportArgs((Widget)nsec, args, num_args);

    return False;
}

static Boolean
set_values_posthook(Widget old, Widget request, Widget new_w,
		    ArgList args, Cardinal *num_args)
{
    XmWidgetExtData ext;

#if 0
    /* Gaaaa.  Forgot the CachePart copy!!! */
    if (!_XmLabelCacheCompare((XtPointer)LabG_Cache(new_w),
			      (XtPointer)LabG_Cache(old)))
    {

	_XmCacheDelete((XtPointer)LabG_Cache(old));

	LabG_Cache(new_w) = (XmLabelGCacheObjPart *)
	    _XmCachePart(LabG_ClassCachePart(NULL),
			 (XtPointer)LabG_Cache(new_w),
			 sizeof(XmLabelGCacheObjPart));
    }
    else
    {
	LabG_Cache(new_w) = LabG_Cache(old);
    }
#endif

    if (!_XmIconCacheCompare((XtPointer)IG_Cache(new_w),
			      (XtPointer)IG_Cache(old)))
    {

	_XmCacheDelete((XtPointer)IG_Cache(old));

	IG_Cache(new_w) = (XmIconGCacheObjPart *)
	    _XmCachePart(IG_ClassCachePart(NULL),
			 (XtPointer)IG_Cache(new_w),
			 sizeof(XmIconGCacheObjPart));
    }
    else
    {
	IG_Cache(new_w) = IG_Cache(old);
    }

    _XmPopWidgetExtData(new_w, &ext, XmCACHE_EXTENSION);

    _XmExtObjFree((XtPointer)ext->widget);
    _XmExtObjFree((XtPointer)ext->reqWidget);

    XtFree((char *)ext);

    return False;
}

static Boolean
set_values(Widget old, Widget request, Widget new_w,
	   ArgList args, Cardinal *num_args)
{
    Boolean refresh_needed = False;

    DEBUGOUT(XdbDebug(__FILE__, new_w,
		      "set_values: %i args\n"
		      "\t    old X %5i Y %5i W %5i H %5i\n"
		      "\trequest X %5i Y %5i W %5i H %5i\n"
		      "\t  new_w X %5i Y %5i W %5i H %5i\n",
		      *num_args,
		      XtX(old), XtY(old),
		      XtWidth(old), XtHeight(old),
		      XtX(request), XtY(request),
		      XtWidth(request), XtHeight(request),
		      XtX(new_w), XtY(new_w),
		      XtWidth(new_w), XtHeight(new_w)));
    DEBUGOUT(XdbPrintArgList(__FILE__, new_w, args, *num_args, False));

#if 0
    if (IG_ArmColor(new_w) != IG_ArmColor(old))
    {
	XtReleaseGC(new_w, IG_FillGC(new_w));
	CreateFillGC(new_w);
	refresh_needed = True;
    }
    if (XmParentBackground(new_w) != XmParentBackground(old))
    {
	XtReleaseGC(new_w, IG_BackgroundGC(new_w));
	CreateBackgroundGC(new_w);
	refresh_needed = True;
    }
#endif

#if 0
    if (!IN_MENU(new_w))
    {
	if (PBG_DefaultButtonShadow(new_w) != PBG_DefaultButtonShadow(old))
	{
	    PBG_Compatible(new_w) = False;
	}

	if (PBG_Compatible(new_w))
	{
	    PBG_DefaultButtonShadow(new_w) = PBG_ShowAsDefault(new_w);
	}

	if (PBG_DefaultButtonShadow(new_w) != PBG_DefaultButtonShadow(old))
	{
	    margin = 2 * PBG_DefaultButtonShadow(new_w) + LabG_Shadow(new_w);
	    margin_extra = Xm3D_ENHANCE_PIXEL;

	    LabG_MarginLeft(new_w) = margin + margin_extra;
	    LabG_MarginRight(new_w) = margin + margin_extra;
	    LabG_MarginTop(new_w) = margin + margin_extra;
	    LabG_MarginBottom(new_w) = margin + margin_extra;

	    XtWidth(new_w) += 2 * (margin + margin_extra);
	    XtHeight(new_w) += 2 * (margin + margin_extra);

	    (*xmLabelGadgetClassRec.rect_class.resize) (new_w);

	    refresh_needed = True;
	}
    }
#endif

#if 0
    if (IG_ArmPixmap(new_w) != IG_ArmPixmap(old) &&
	LabG_IsPixmap(new_w) && IG_Armed(new_w))
    {
	refresh_needed = True;
    }

    if (LabG_Pixmap(new_w) == XmUNSPECIFIED_PIXMAP &&
	IG_ArmPixmap(new_w) != XmUNSPECIFIED_PIXMAP)
    {

	LabG_Pixmap(new_w) = IG_ArmPixmap(new_w);

	if (LabG_RecomputeSize(new_w) && XtWidth(new_w) == XtWidth(old))
	{
	    XtWidth(new_w) = 0;
	}
	if (LabG_RecomputeSize(new_w) && XtHeight(new_w) == XtHeight(old))
	{
	    XtHeight(new_w) = 0;
	}

	_XmCalcLabelGDimensions(new_w);

	(*xmLabelGadgetClassRec.rect_class.resize) (new_w);
    }

    if (LabG_Pixmap(new_w) != LabG_Pixmap(old))
    {
	IG_UnarmPixmap(new_w) = LabG_Pixmap(new_w);
	if (LabG_IsPixmap(new_w) && !IG_Armed(new_w))
	{
	    refresh_needed = True;
	}
    }

    if (LabG_IsPixmap(new_w) && IG_Armed(new_w) &&
	IG_ArmPixmap(new_w) != IG_ArmPixmap(old))
    {
	if (LabG_RecomputeSize(new_w) && XtWidth(new_w) == XtWidth(old))
	{
	    XtWidth(new_w) = 0;
	}
	if (LabG_RecomputeSize(new_w) && XtHeight(new_w) == XtHeight(old))
	{
	    XtHeight(new_w) = 0;
	}

	_XmCalcLabelGDimensions(new_w);

	(*xmLabelGadgetClassRec.rect_class.resize) (new_w);

	refresh_needed = True;
    }

    if (IG_FillOnArm(new_w) != IG_FillOnArm(old) && IG_Armed(new_w))
    {
	refresh_needed = True;
    }

    if (XtIsRealized(new_w) && !refresh_needed)
    {
	Position normal_shadow_x, normal_shadow_y;
	Dimension normal_shadow_width, normal_shadow_height, shad;

	normal_shadow_x = LabG_Highlight(new_w) + LabG_MarginLeft(new_w);
	normal_shadow_y = LabG_Highlight(new_w) + LabG_MarginTop(new_w);

	normal_shadow_width = XtWidth(new_w) - 2 * LabG_Highlight(new_w) -
	    LabG_MarginLeft(new_w) - LabG_MarginRight(new_w);
	normal_shadow_height = XtHeight(new_w) - 2 * LabG_Highlight(new_w) -
	    LabG_MarginTop(new_w) - LabG_MarginBottom(new_w);

	shad = IG_DefaultButtonShadowThickness(new_w);

	if (IG_ShowAsDefault(new_w) && !IG_ShowAsDefault(old))
	{
	    _XmDrawShadows(XtDisplay(new_w), XtWindow(new_w),
			   XmParentTopShadowGC(new_w),
			   XmParentBottomShadowGC(new_w),
			   XtX(new_w) + normal_shadow_x -
			   (2 * shad + LabG_Shadow(new_w)),
			   XtY(new_w) + normal_shadow_y -
			   (2 * shad + LabG_Shadow(new_w)),
			   normal_shadow_width + 2 *
			   (2 * shad + LabG_Shadow(new_w)),
			   normal_shadow_height + 2 *
			   (2 * shad + LabG_Shadow(new_w)),
			   shad,
			   XmSHADOW_IN);
	}
	else if (!IG_ShowAsDefault(new_w) && IG_ShowAsDefault(old))
	{
	    _XmClearBorder(XtDisplay(new_w), XtWindow(new_w),
			   XtX(new_w) + normal_shadow_x -
			   (2 * shad + LabG_Shadow(new_w)),
			   XtY(new_w) + normal_shadow_y -
			   (2 * shad + LabG_Shadow(new_w)),
			   normal_shadow_width + 2 *
			   (2 * shad + LabG_Shadow(new_w)),
			   normal_shadow_height + 2 *
			   (2 * shad + LabG_Shadow(new_w)),
			   shad);
	}
    }
#endif

    return refresh_needed;
}

static void
get_values_prehook(Widget new_w, ArgList args, Cardinal *num_args)
{
    XmBaseClassExt *bce;
    XmWidgetExtData ed;
    int size;
    XtPointer nsec;

    bce = _XmGetBaseClassExtPtr(XtClass(new_w), XmQmotif);
    size = (*bce)->secondaryObjectClass->core_class.widget_size;

    nsec = _XmExtObjAlloc(size);

#if 0
    bcopy(LabG_Cache(new_w),
	  &((XmLabelGCacheObject)nsec)->label_cache,
	  sizeof(XmLabelGCacheObjPart));
#endif
    bcopy(IG_Cache(new_w),
	  &((XmIconGCacheObject)nsec)->icon_cache,
	  sizeof(XmIconGCacheObjPart));

    /*
     * don't do this and ResInd will blow up.
     */
    ((XmExtRec *)nsec)->object.self = (Widget)nsec;
    ((XmExtRec *)nsec)->object.widget_class = (*bce)->secondaryObjectClass;
    ((XmExtRec *)nsec)->object.parent = XtParent(new_w);
    ((XmExtRec *)nsec)->object.xrm_name = new_w->core.xrm_name;
    ((XmExtRec *)nsec)->object.being_destroyed = False;
    ((XmExtRec *)nsec)->object.destroy_callbacks = NULL;
    ((XmExtRec *)nsec)->object.constraints = NULL;

    ExtObj_LogicalParent(nsec) = new_w;
    ExtObj_ExtensionType(nsec) = XmCACHE_EXTENSION;

    ed = (XmWidgetExtData)XtMalloc(sizeof(XmWidgetExtDataRec));
    ed->widget = (Widget)nsec;

    _XmPushWidgetExtData(new_w, ed, XmCACHE_EXTENSION);

    XtGetSubvalues((XtPointer)nsec,
		   (*bce)->secondaryObjectClass->core_class.resources,
		   (*bce)->secondaryObjectClass->core_class.num_resources,
		   args, *num_args);

    _XmExtGetValuesHook((Widget)nsec, args, num_args);
}

static void
get_values_posthook(Widget new_w, ArgList args, Cardinal *num_args)
{
    XmWidgetExtData ext;

    _XmPopWidgetExtData(new_w, &ext, XmCACHE_EXTENSION);

    _XmExtObjFree((XtPointer)ext->widget);

    XtFree((char *)ext);
}

static void
get_values_hook(Widget w, ArgList args, Cardinal *num_args)
{
    DEBUGOUT(XdbDebug(__FILE__, w, "GetValuesHook\n"));
}

static void
expose(Widget w, XEvent *event, Region region)
{
    Position TextX, TextY;
    Dimension TextHeight, TextWidth;
    Position IconX, IconY;
    unsigned int IconHeight, IconWidth;
    XRectangle cliprect;
    GC myGC;

    DEBUGOUT(XdbDebug(__FILE__, w, "expose\n"));
    /*
     * I'm getting paranoid - Danny - see testXm/filesb/test3
     */
    if (!XtIsRealized(w))
    {
	return;
    }

    /* if the internals of the widget haven't been recomputed yet,
     * recompute them now (happens if resize isn't called after set_values)
     */
    resize(w);

    myGC = IG_NormalGC(w);

    /* Set a clip rectangle for the GC - ensure we don't overwrite shadows */
    /* the rectangle used to include MarginWidth and MarginHeight.  */
    cliprect.x = XtX(w) + G_HighlightThickness(w) + G_ShadowThickness(w);
    cliprect.y = XtY(w) + G_HighlightThickness(w) /*+ G_ShadowThickness(w)*/;
    cliprect.width = XtWidth(w) -
	2 * (G_ShadowThickness(w) + G_HighlightThickness(w));
    cliprect.height = XtHeight(w) -
	2 * (/*G_ShadowThickness(w) +*/ G_HighlightThickness(w));

    XSetClipRectangles(XtDisplay(w), myGC, 0, 0, &cliprect, 1, Unsorted);
    DEBUGOUT(XdbDebug(__FILE__, w, "cliprect x %d y %d width %d height %d\n",
    		cliprect.x, cliprect.y,
    		cliprect.width, cliprect.height));

    {
    unsigned int tmp;
    int tmpx,tmpy;
    Window tmpwin;
    unsigned Depth;

    XGetGeometry(XtDisplayOfObject(w),
		 IG_SmallIconPixmap(w),
		 &tmpwin,
		 &tmpx, &tmpy,
		 &IconWidth, &IconHeight,
		 &tmp, &Depth);
    }

    _XmStringExtent(IG_Font(w),
		    IG_Label(w),
		    &TextWidth,
		    &TextHeight);

    switch (IG_ViewType(w))
    {
    default:
    case XmLARGE_ICON:
    case XmSMALL_ICON:
	IconX = XtX(w) + G_HighlightThickness(w) + G_ShadowThickness(w);
	IconY = ((XtHeight(w) - IconHeight) / 2) + XtY(w);
	TextX = IconX + IconWidth + G_ShadowThickness(w);
	TextY = ((XtHeight(w) - TextHeight) / 2) + XtY(w);
	break;
    }

    XCopyArea(XtDisplay(w),
		  IG_SmallIconPixmap(w),
		  XtWindow(w),
		  myGC,
		  0,
		  0,
		  IconWidth, IconHeight,
		  IconX, IconY);

    _XmStringDraw(XtDisplayOfObject(w),
		  XtWindowOfObject(w),
		  IG_Font(w),
		  IG_Label(w),
		  myGC,
		  TextX,
		  TextY,
		  TextWidth,
		  XmALIGNMENT_BEGINNING,
		  0,
		  NULL);
    _XmDrawShadows(XtDisplayOfObject(w),
		       XtWindowOfObject(w),
		       XmParentTopShadowGC(w),
		       XmParentBottomShadowGC(w),
		       TextX - (G_ShadowThickness(w) + G_HighlightThickness(w)),
		       TextY - (G_ShadowThickness(w) + G_HighlightThickness(w)),
		       TextWidth + 2 * (G_ShadowThickness(w) + G_HighlightThickness(w)),
		       TextHeight + 2 * (G_ShadowThickness(w) + G_HighlightThickness(w)),
		       G_ShadowThickness(w),
		       XmSHADOW_OUT);

    XSetClipMask(XtDisplay(w), myGC, None);
}

static XtGeometryResult
query_geometry(Widget w, XtWidgetGeometry *proposed, XtWidgetGeometry *answer)
{
    XtWidgetGeometry a;		/* Standin for answer if NULL parameter */
    Dimension wd, ht;

#define	Wants(x)	(proposed->request_mode & x)

    DEBUGOUT(XdbDebug(__FILE__, w, "query_geometry %s\n",
		      XdbWidgetGeometry2String(proposed)));

    wd = XtWidth(w);
    ht = XtHeight(w);

    if (proposed->request_mode & CWWidth)
    {
	XtWidth(w) = proposed->width;
    }
    if (proposed->request_mode & CWHeight)
    {
	XtHeight(w) = proposed->height;
    }

    _XmCalcIconGDimensions(w);

    a.width = XtWidth(w);
    a.height = XtHeight(w);
    a.request_mode = CWWidth | CWHeight;
    DEBUGOUT(XdbDebug(__FILE__, w,
		      "IconGadget queried for size: reporting %d %d %08x\n",
		      XtWidth(w), XtHeight(w), answer));

    XtWidth(w) = wd;
    XtHeight(w) = ht;

    if (answer)
    {
	*answer = a;
    }

    if ((proposed->request_mode & (CWWidth | CWHeight)) ==
	(CWWidth | CWHeight) &&
	proposed->width >= answer->width && proposed->height >= answer->height)
    {
	return XtGeometryYes;
    }
    else if (answer->width == XtWidth(w) && answer->height == XtHeight(w))
    {
	return XtGeometryNo;
    }
    else
    {
	return XtGeometryAlmost;
    }
}

static Cardinal
get_sec_res_data(WidgetClass wc, XmSecondaryResourceData **data)
{
    /* FIX ME */

    return _XmSecondaryResourceData(&_XmIconGRectClassExtRec,
				    data, NULL, NULL, NULL, NULL);
}

#if 0
static void
Arm(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
    XmPushButtonCallbackStruct cbs;
    XtExposeProc exp = XtClass(w)->core_class.expose;

    XmProcessTraversal(w, XmTRAVERSE_CURRENT);

    IG_Armed(w) = True;

    (*exp) (w, event, NULL);

    if (IG_ArmCallback(w))
    {
	cbs.reason = XmCR_ARM;
	cbs.event = event;
	cbs.click_count = IG_ClickCount(w);

	XFlush(XtDisplay(w));

	XtCallCallbackList(w,
			   IG_ArmCallback(w),
			   (XtPointer)&cbs);
    }
}

static void
Disarm(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
    XmPushButtonCallbackStruct cbs;
    XtExposeProc exp = XtClass(w)->core_class.expose;

    if (IG_Armed(w))
    {
	IG_Armed(w) = False;
	(*exp) (w, event, NULL);
    }

    if (IG_DisarmCallback(w))
    {
	cbs.reason = XmCR_DISARM;
	cbs.event = event;
	cbs.click_count = IG_ClickCount(w);

	XFlush(XtDisplay(w));
	XtCallCallbackList(w,
			   IG_DisarmCallback(w),
			   (XtPointer)&cbs);
    }
}

static void
Activate(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
    XmPushButtonCallbackStruct cbs;
    XButtonEvent *ev = (XButtonEvent *)event;
    XtExposeProc exp = XtClass(w)->core_class.expose;

    DEBUGOUT(XdbDebug(__FILE__, w, "Activate\n"));

    if (IG_Armed(w) == False)
    {
	return;
    }

    IG_Armed(w) = False;

    (*exp) (w, event, NULL);

    /*
     * Having this test breaks accelerators. Danny
     * MLM: Not having means PB's break if the button is released outside
     * the widget after it is armed.
     *
     * Test refined so it doesn't fail for accelerators. -- Danny
     */
    if (ev->type == KeyPress || ev->type == KeyRelease
	|| ((ev->x > XtX(w) && ev->x < XtX(w) + XtWidth(w))
	    && (ev->y > XtY(w) && ev->y < XtY(w) + XtHeight(w))))
    {

	if (!LabG_SkipCallback(w) && IG_ActivateCallback(w))
	{
	    cbs.reason = XmCR_ACTIVATE;
	    cbs.event = event;
	    cbs.click_count = IG_ClickCount(w);

	    XFlush(XtDisplay(w));

	    XtCallCallbackList(w,
			       IG_ActivateCallback(w),
			       (XtPointer)&cbs);
	}
    }

    Disarm(w, event, params, num_params);
}

static void
ArmTimeout(XtPointer data, XtIntervalId *id)
{
    XmPushButtonCallbackStruct cbs;
    Widget w = (Widget)data;
    XtExposeProc exp = XtClass(w)->core_class.expose;

    DEBUGOUT(XdbDebug(__FILE__, w, "Activate\n"));

    if (IG_Armed(w) == False)
    {
	return;
    }

    IG_Armed(w) = False;

    (*exp) (w, NULL, NULL);

    if (!LabG_SkipCallback(w) && IG_ActivateCallback(w))
    {
	cbs.reason = XmCR_ACTIVATE;
	cbs.event = NULL;
	cbs.click_count = IG_ClickCount(w);

	XFlush(XtDisplay(w));

	XtCallCallbackList(w,
			   IG_ActivateCallback(w),
			   (XtPointer)&cbs);
    }

    Disarm(w, NULL, NULL, 0);
}

static void
ArmAndActivate(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
    DEBUGOUT(XdbDebug(__FILE__, w, "ArmAndActivate\n"));

    Arm(w, event, params, num_params);

    IG_Timer(w) = XtAppAddTimeOut(XtWidgetToApplicationContext(w),
				   ACTIVATE_DELAY, ArmTimeout, (XtPointer)w);
}

static void
EnterWindow(Widget w,
	    XEvent *event,
	    String *params,
	    Cardinal *num_params)
{
    /*
    XmPushButtonCallbackStruct cbs;
    XtExposeProc exp = XtClass(w)->core_class.expose;
    */

    DEBUGOUT(XdbDebug(__FILE__, w, "EnterWindow()\n"));

#if 0
    if (!IN_MENU(w))
#endif
    {
	_XmEnterGadget(w, event, NULL, NULL);
#if 0
	if (IG_Armed(w))
	{
	    (*exp) (w, event, NULL);
	}
#endif
    }
#if 0
    else
	/* we're in a menu */
    {
	if (_XmGetInDragMode(w))
	{
	    ShellWidget popupShell;

	    popupShell = (ShellWidget)_XmGetRC_PopupPosted(XtParent(w));
	    if (popupShell)
	    {
		if (popupShell->shell.popped_up)
		    (*xmLabelGadgetClassRec.label_class.menuProcs) (XmMENU_SHELL_POPDOWN,
							    (Widget)popupShell,
								    NULL,
								    event,
								    NULL);
	    }

	    IG_Armed(w) = True;

	    (*exp) (w, event, NULL);

	    MGR_SelectedGadget(XtParent(w)) = (XmGadget)w;

	    if (IG_ArmCallback(w))
	    {
		cbs.reason = XmCR_ARM;
		cbs.event = event;
		cbs.click_count = IG_ClickCount(w);

		XFlush(XtDisplay(w));

		XtCallCallbackList(w,
				   IG_ArmCallback(w),
				   (XtPointer)&cbs);
	    }
	}
    }
#endif
}

static void
LeaveWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
    /*
    XmPushButtonCallbackStruct cbs;
    XtExposeProc exp = XtClass(w)->core_class.expose;
    */

#if 0
    if (!IN_MENU(w))
#endif
    {
	_XmLeaveGadget(w, event, NULL, NULL);
#if 0
	if (IG_Armed(w))
	{
	    (*exp) (w, event, NULL);
	}
#endif
    }
#if 0
    else
	/* we're in a menu */
    {
	if (_XmGetInDragMode(w))
	{
	    IG_Armed(w) = False;

	    (*exp) (w, event, NULL);

	    MGR_SelectedGadget(XtParent(w)) = NULL;

	    if (IG_DisarmCallback(w))
	    {
		cbs.reason = XmCR_DISARM;
		cbs.event = event;
		cbs.click_count = IG_ClickCount(w);

		XFlush(XtDisplay(w));

		XtCallCallbackList(w,
				   IG_DisarmCallback(w),
				   (XtPointer)&cbs);
	    }
	}
    }
#endif
}
#endif

#if 0
static void
ButtonUp(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
    Widget parent, shell;
    Boolean validButton, poppedUp;
    XmPushButtonCallbackStruct cbs;

    DEBUGOUT(XdbDebug(__FILE__, w, "ButtonUp()\n"));

    /* queue events until the next button event */
    XAllowEvents(XtDisplay(w), SyncPointer, CurrentTime);

    parent = XtParent(w);

    shell = parent;
    while (!XtIsShell(shell))
	shell = XtParent(shell);

    if (event && (event->type == ButtonRelease))
    {
	(*xmLabelGadgetClassRec.label_class.menuProcs) (XmMENU_BUTTON, parent,
						    NULL, event, &validButton);
    }

    if (!validButton)
    {
	return;
    }

    if (!IG_Armed(w))
    {
	return;
    }

    IG_Armed(w) = False;

#if 0
    if (IN_MENU(w) && !XmIsMenuShell(shell))
    {
	(*xmLabelGadgetClassRec.label_class.menuProcs) (XmMENU_POPDOWN, w,
							NULL, event, &poppedUp);
    }
    else
#endif
    {
	(*xmLabelGadgetClassRec.label_class.menuProcs) (XmMENU_BUTTON_POPDOWN, w,
							NULL, event, &poppedUp);
    }

    _XmRecordEvent(event);

    if (poppedUp)
#if 0
/* rws 28 Mar 1997 Like pushb Why ?? */
	return;
#endif

    _XmDrawShadows(XtDisplay(w),
		   XtWindow(w),
		   XmParentTopShadowGC(w),
		   XmParentBottomShadowGC(w),
		   LabG_Highlight(w),
		   LabG_Highlight(w),
		   XtWidth(w) - 2 * LabG_Highlight(w),
		   XtHeight(w) - 2 * LabG_Highlight(w),
		   LabG_Shadow(w),
		   XmNO_LINE);

    if (!LabG_SkipCallback(w) && IG_ActivateCallback(w))
    {
	cbs.reason = XmCR_ACTIVATE;
	cbs.event = event;
	cbs.click_count = IG_ClickCount(w);

	XFlush(XtDisplay(w));

	XtCallCallbackList(w,
			   IG_ActivateCallback(w),
			   (XtPointer)&cbs);
    }
    if (IG_DisarmCallback(w))
    {
	cbs.reason = XmCR_DISARM;
	cbs.event = event;
	cbs.click_count = IG_ClickCount(w);

	XFlush(XtDisplay(w));

	XtCallCallbackList(w,
			   IG_DisarmCallback(w),
			   (XtPointer)&cbs);
    }

    _XmSetInDragMode(w, False);
}


static void
ButtonDown(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
    /* modified from the MegaButton widget */
    ShellWidget popupShell;
    int validButton;
    XmPushButtonCallbackStruct cbs;

    /* queue events until the next button event */
    XAllowEvents(XtDisplay(w), SyncPointer, CurrentTime);

    if (event && (event->type == ButtonPress))
    {
	(*xmLabelGadgetClassRec.label_class.menuProcs) (XmMENU_BUTTON,
							XtParent(w),
							NULL,
							event,
							&validButton);
	if (!validButton)
	{
	    return;
	}
    }

    _XmSetInDragMode(w, True);

    MGR_SelectedGadget(XtParent(w)) = (XmGadget)w;

    popupShell = (ShellWidget)_XmGetRC_PopupPosted(XtParent(w));
    if (popupShell)
    {
	if (popupShell->shell.popped_up)
	{
	    (*xmLabelGadgetClassRec.label_class.menuProcs) (XmMENU_SHELL_POPDOWN,
							    (Widget)popupShell,
							    NULL,
							    event,
							    NULL);
	}
    }

    _XmDrawShadows(XtDisplay(w),
		   XtWindow(w),
		   XmParentTopShadowGC(w),
		   XmParentBottomShadowGC(w),
		   XtX(w) + LabG_Highlight(w),
		   XtY(w) + LabG_Highlight(w),
		   XtWidth(w) - 2 * LabG_Highlight(w),
		   XtHeight(w) - 2 * LabG_Highlight(w),
		   LabG_Shadow(w),
		   XmSHADOW_OUT);

    if (!IG_Armed(w))
    {
	IG_Armed(w) = True;
	if (IG_ArmCallback(w))
	{
	    cbs.reason = XmCR_DISARM;
	    cbs.event = event;
	    cbs.click_count = IG_ClickCount(w);

	    XFlush(XtDisplay(w));

	    XtCallCallbackList(w,
			       IG_DisarmCallback(w),
			       (XtPointer)&cbs);
	}
    }

    _XmRecordEvent(event);
}

static void
Help(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
    Widget cur = w;
    XmAnyCallbackStruct cbs;

    cbs.reason = XmCR_HELP;
    cbs.event = event;

    while (cur != NULL)
    {
	if (XtHasCallbacks(w, XmNhelpCallback) == XtCallbackHasSome)
	{
	    XtCallCallbacks(w, XmNhelpCallback, (XtPointer)&cbs);
	    return;
	}
	cur = XtParent(cur);
    }
}
#endif

static void
input_dispatch(Widget gadget, XEvent *event, Mask event_mask)
{
    DEBUGOUT(XdbDebug(__FILE__, gadget, "input_dispatch\n"));
#if 0
    Cardinal num_params = 0;

    switch (event_mask)
    {
    case XmARM_EVENT:
	DEBUGOUT(XdbDebug(__FILE__, gadget, "got arm event\n"));
#if 0
	if (IN_MENU(gadget))
	{
	    ButtonDown(gadget, event, NULL, &num_params);
	}
	else
#endif
	{
	    Arm(gadget, event, NULL, &num_params);
	}
	break;

    case XmMULTI_ARM_EVENT:
	if (IG_MultiClick(gadget) == XmMULTICLICK_KEEP)
	{
#if 0
	    if (IN_MENU(gadget))
	    {
		ButtonDown(gadget, event, NULL, &num_params);
	    }
	    else
#endif
	    {
		Arm(gadget, event, NULL, &num_params);
	    }
	}
	break;

    case XmACTIVATE_EVENT:
	DEBUGOUT(XdbDebug(__FILE__, gadget, "got activate event\n"));
	/*
	 * The test below is expanded so it also checks for the Shell.
	 * In tearoff menus, the shell will be a TransientShell, thus we'll
	 * trigger the Activate event.
	 */
	IG_ClickCount(gadget) = 1;
	if (LabG_MenuType(gadget) == XmMENU_PULLDOWN &&
	    XtIsSubclass(XtParent(XtParent(gadget)), xmMenuShellWidgetClass))
	{
	    ButtonUp(gadget, event, NULL, &num_params);
	}
	else
	{
	    Activate(gadget, event, NULL, &num_params);
	}
	break;

    case XmMULTI_ACTIVATE_EVENT:
	if (IG_MultiClick(gadget) == XmMULTICLICK_KEEP)
	{
	    IG_ClickCount(gadget)++;
	    if (LabG_MenuType(gadget) == XmMENU_PULLDOWN &&
	      XtIsSubclass(XtParent(XtParent(gadget)), xmMenuShellWidgetClass))
	    {
		ButtonUp(gadget, event, NULL, &num_params);
	    }
	    else
	    {
		Activate(gadget, event, NULL, &num_params);
	    }
	}
	break;

    case XmENTER_EVENT:
	DEBUGOUT(XdbDebug(__FILE__, gadget, "got an enter window\n"));
	EnterWindow(gadget, event, NULL, &num_params);
	break;

    case XmLEAVE_EVENT:
	DEBUGOUT(XdbDebug(__FILE__, gadget, "got a leave window\n"));
	LeaveWindow(gadget, event, NULL, &num_params);
	break;

    case XmMOTION_EVENT:
	DEBUGOUT(XdbDebug(__FILE__, gadget, "got a motion event\n"));
	break;

    case XmFOCUS_IN_EVENT:
	_XmFocusInGadget(gadget, event, NULL, &num_params);
	break;

    case XmFOCUS_OUT_EVENT:
	_XmFocusOutGadget(gadget, event, NULL, &num_params);
	break;

    case XmHELP_EVENT:
	Help(gadget, event, NULL, &num_params);
	break;

    case XmBDRAG_EVENT:
	_XmProcessDrag(gadget, event, NULL, NULL);
	break;

    default:
	_XmWarning(gadget, "PushButtonGadget got unknown event\n");
    }
#endif
}

void
_XmClearIconCompatibility(Widget pbg)
{
}

Widget
XmCreateIconGadget(Widget parent, char *name,
			 Arg *arglist, Cardinal argcount)
{
    return XtCreateWidget(name, xmIconGadgetClass, parent,
			  arglist, argcount);
}
