/* 
 *  @OPENGROUP_COPYRIGHT@
 *  COPYRIGHT NOTICE
 *  Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc.
 *  Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group
 *  ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for
 *  the full copyright text.
 *  
 *  This software is subject to an open license. It may only be
 *  used on, with or for operating systems which are themselves open
 *  source systems. You must contact The Open Group for a license
 *  allowing distribution and sublicensing of this software on, with,
 *  or for operating systems which are not Open Source programs.
 *  
 *  See http://www.opengroup.org/openmotif/license for full
 *  details of the license agreement. Any use, reproduction, or
 *  distribution of the program constitutes recipient's acceptance of
 *  this agreement.
 *  
 *  EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
 *  PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
 *  WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
 *  OR FITNESS FOR A PARTICULAR PURPOSE
 *  
 *  EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
 *  NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT,
 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 *  DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED
 *  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
 *  EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGES.
*/ 
/* 
 * HISTORY
*/ 
#ifdef REV_INFO
#ifndef lint
static char rcsid[] = "$TOG: DrawnB.c /main/20 1999/04/29 13:05:14 samborn $"
#endif
#endif
/* (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */
/*
 * Include files & Static Routine Definitions
 */

#include <stdio.h>
#include <X11/X.h>
#include <Xm/ActivatableT.h>
#include <Xm/DisplayP.h>
#include <Xm/DrawP.h>   
#include <Xm/DrawnBP.h>
#include <Xm/LabelP.h>
#include <Xm/ManagerP.h>
#include <Xm/MenuT.h>
#include <Xm/RowColumnP.h>
#include <Xm/TraitP.h>
#include <Xm/TransltnsP.h>
#include "XmI.h"
#include "RepTypeI.h"
#include "LabelI.h"
#include "MenuUtilI.h"
#include "MenuProcI.h"
#include "MenuStateI.h"
#include "PrimitiveI.h"
#include "TravActI.h"
#include "TraversalI.h"
#include "UniqueEvnI.h"


#define DELAY_DEFAULT 100	

/********    Static Function Declarations    ********/

static void Arm( 
                        Widget wid,
                        XEvent *event,
                        String *params,
                        Cardinal *num_params) ;
static void MultiArm( 
                        Widget wid,
                        XEvent *event,
                        String *params,
                        Cardinal *num_params) ;
static void Activate( 
                        Widget wid,
                        XEvent *buttonEvent,
                        String *params,
                        Cardinal *num_params) ;
static void MultiActivate( 
                        Widget wid,
                        XEvent *buttonEvent,
                        String *params,
                        Cardinal *num_params) ;
static void ActivateCommon( 
                        Widget wid,
                        XEvent *event,
                        String *params,
                        Cardinal *num_params) ;
static void ArmAndActivate( 
                        Widget wid,
                        XEvent *event,
                        String *params,
                        Cardinal *num_params) ;
static void ArmTimeout (
        		XtPointer closure,
        		XtIntervalId *id ) ;
static void Disarm( 
                        Widget wid,
                        XEvent *event,
                        String *params,
                        Cardinal *num_params) ;
static void BtnDown( 
                        Widget wid,
                        XEvent *event,
                        String *params,
                        Cardinal *num_params) ;
static void BtnUp( 
                        Widget wid,
                        XEvent *event,
                        String *params,
                        Cardinal *num_params) ;
static void Enter( 
                        Widget wid,
                        XEvent *event,
                        String *params,
                        Cardinal *num_params) ;
static void Leave( 
                        Widget wid,
                        XEvent *event,
                        String *params,
                        Cardinal *num_params) ;
static void BorderHighlight( 
                        Widget wid) ;
static void BorderUnhighlight( 
                        Widget wid) ;
static void ClassInitialize( void ) ;
static void ClassPartInitialize( 
                        WidgetClass wc) ;
static void InitializePrehook( 
                        Widget rw,
                        Widget nw,
                        ArgList args,
                        Cardinal *num_args) ;
static void InitializePosthook( 
                        Widget rw,
                        Widget nw,
                        ArgList args,
                        Cardinal *num_args) ;
static void Initialize( 
                        Widget rw,
                        Widget nw,
                        ArgList args,
                        Cardinal *num_args) ;
static void Resize( 
                        Widget wid) ;
static void Redisplay( 
                        Widget wid,
                        XEvent *event,
                        Region region) ;
static void DrawPushButton( 
                        XmDrawnButtonWidget db,
#if NeedWidePrototypes
                        int armed) ;
#else
                        Boolean armed) ;
#endif /* NeedWidePrototypes */
static Boolean SetValuesPrehook( 
			Widget cw,
                        Widget rw,
                        Widget nw,
                        ArgList args,
                        Cardinal *num_args) ;
static Boolean SetValues( 
                        Widget cw,
                        Widget rw,
                        Widget nw,
                        ArgList args,
                        Cardinal *num_args) ;
static void Realize( 
                        Widget w,
                        XtValueMask *p_valueMask,
                        XSetWindowAttributes *attributes) ;
static void Destroy( 
                        Widget wid) ;

static void ChangeCB(Widget w, 
		     XtCallbackProc activCB,
		     XtPointer closure,
		     Boolean setunset) ;

static void DB_FixTearoff(XmDrawnButtonWidget db);

/********    End Static Function Declarations    ********/

/*************************************<->*************************************
 *
 *
 *   Description:   translation tables for class: DrawnButton
 *   -----------
 *
 *   Matches events with string descriptors for internal routines.
 *
 *************************************<->***********************************/

static XtTranslations default_parsed;

#define defaultTranslations	_XmDrawnB_defaultTranslations

static XtTranslations menu_parsed;

#define menuTranslations	_XmDrawnB_menuTranslations


/*************************************<->*************************************
 *
 *
 *   Description:  action list for class: DrawnButton
 *   -----------
 *
 *   Matches string descriptors with internal routines.
 *   Note that Primitive will register additional event handlers
 *   for traversal.
 *
 *************************************<->***********************************/

static XtActionsRec actionsList[] =
{
  {"Arm", 	Arm		 },
  {"Activate", 	Activate		 },
  {"MultiActivate", MultiActivate		 },
  {"MultiArm",	MultiArm },
  {"ArmAndActivate", ArmAndActivate },
  {"Disarm", 	Disarm		 },
  {"BtnDown", 	BtnDown		 },
  {"BtnUp", 	BtnUp		 },
  {"Enter", 	Enter		 },
  {"Leave",	Leave		 },
  {"ButtonTakeFocus", _XmButtonTakeFocus },
  {"MenuButtonTakeFocus", _XmMenuButtonTakeFocus	 },
  {"MenuButtonTakeFocusUp", _XmMenuButtonTakeFocusUp }
};


/*  The resource list for Drawn Button  */

static XtResource resources[] = 
{     
   {
     XmNmultiClick, XmCMultiClick, XmRMultiClick, sizeof (unsigned char),
     XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.multiClick),
     XmRImmediate, (XtPointer) XmMULTICLICK_KEEP
   },

   {
     XmNpushButtonEnabled, XmCPushButtonEnabled, XmRBoolean, sizeof (Boolean),
     XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.pushbutton_enabled),
     XmRImmediate, (XtPointer) False
   },

   {
     XmNshadowType, XmCShadowType, XmRShadowType, sizeof(unsigned char),
     XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.shadow_type),
     XmRImmediate, (XtPointer) XmSHADOW_ETCHED_IN
   },

   {
     XmNactivateCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
     XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.activate_callback),
     XmRPointer, (XtPointer) NULL
   },

   {
     XmNarmCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
     XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.arm_callback),
     XmRPointer, (XtPointer) NULL
   },

   {
     XmNdisarmCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
     XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.disarm_callback),
     XmRPointer, (XtPointer) NULL
   },
   
   {
     XmNexposeCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
     XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.expose_callback),
     XmRPointer, (XtPointer) NULL
   },

   {
     XmNresizeCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
     XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.resize_callback),
     XmRPointer, (XtPointer) NULL
   },
   
   {
     XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension, 
     sizeof(Dimension),
     XtOffsetOf( struct _XmDrawnButtonRec, primitive.shadow_thickness),
     XmRCallProc, (XtPointer) _XmSetThickness
   },

   {    
     XmNlabelString, XmCXmString, XmRXmString, sizeof(XmString),
     XtOffsetOf( struct _XmDrawnButtonRec, label._label),
     XmRImmediate, (XtPointer) XmUNSPECIFIED
   },
   {
	XmNtraversalOn,
	XmCTraversalOn,
	XmRBoolean,
	sizeof(Boolean),
	XtOffsetOf( struct _XmPrimitiveRec, primitive.traversal_on),
	XmRImmediate,
	(XtPointer) True
   },

   {
	XmNhighlightThickness,
	XmCHighlightThickness,
	XmRHorizontalDimension,
	sizeof (Dimension),
	XtOffsetOf( struct _XmPrimitiveRec, primitive.highlight_thickness),
	XmRCallProc,
	(XtPointer) _XmSetThickness
   }
};

static XmBaseClassExtRec       drawnBBaseClassExtRec = {
    NULL,                                     /* Next extension       */
    NULLQUARK,                                /* record type XmQmotif */
    XmBaseClassExtVersion,                    /* version              */
    sizeof(XmBaseClassExtRec),                /* size                 */
    InitializePrehook,                        /* initialize prehook   */
    SetValuesPrehook,			      /* set_values prehook   */
    InitializePosthook,                       /* initialize posthook  */
    XmInheritSetValuesPosthook,               /* set_values posthook  */
    XmInheritClass,                           /* secondary class      */
    XmInheritSecObjectCreate,                 /* creation proc        */
    XmInheritGetSecResData,                   /* getSecResData        */
    {0},                                      /* fast subclass        */
    XmInheritGetValuesPrehook,                /* get_values prehook   */
    XmInheritGetValuesPosthook,               /* get_values posthook  */
    XmInheritClassPartInitPrehook,            /* classPartInitPrehook */
    XmInheritClassPartInitPosthook,           /* classPartInitPosthook*/
    NULL,                                     /* ext_resources        */
    NULL,                                     /* compiled_ext_resources*/
    0,                                        /* num_ext_resources    */
    FALSE,                                    /* use_sub_resources    */
    XmInheritWidgetNavigable,                 /* widgetNavigable      */
    XmInheritFocusChange,                     /* focusChange          */
};



/*************************************<->*************************************
 *
 *
 *   Description:  global class record for instances of class: DrawnButton
 *   -----------
 *
 *   Defines default field settings for this class record.
 *
 *************************************<->***********************************/

externaldef(xmdrawnbuttonclassrec) XmDrawnButtonClassRec xmDrawnButtonClassRec ={
  {
/* core_class record */	
    /* superclass	  */	(WidgetClass) &xmLabelClassRec,
    /* class_name	  */	"XmDrawnButton",
    /* widget_size	  */	sizeof(XmDrawnButtonRec),
    /* class_initialize   */    ClassInitialize,
    /* class_part_init    */    ClassPartInitialize,
    /* class_inited       */	FALSE,
    /* initialize	  */	Initialize,
    /* initialize_hook    */    NULL,
    /* realize		  */	Realize,
    /* actions		  */	actionsList,
    /* num_actions	  */	XtNumber(actionsList),
    /* resources	  */	resources,
    /* num_resources	  */	XtNumber(resources),
    /* xrm_class	  */	NULLQUARK,
    /* compress_motion	  */	TRUE,
    /* compress_exposure  */	XtExposeNoCompress,
    /* compress_enterlv   */    TRUE,
    /* visible_interest	  */	FALSE,
    /* destroy		  */	Destroy,
    /* resize		  */	Resize,
    /* expose		  */	Redisplay,
    /* set_values	  */	SetValues,
    /* set_values_hook    */    NULL,
    /* set_values_almost  */    XtInheritSetValuesAlmost,
    /* get_values_hook    */	NULL,
    /* accept_focus	  */	NULL,
    /* version            */	XtVersion,
    /* callback_private   */    NULL,
    /* tm_table           */    defaultTranslations,
    /* query_geometry     */	NULL, 
    /* display_accelerator */   NULL,
    /* extension          */    (XtPointer) &drawnBBaseClassExtRec,
  },

  { /* primitive_class record       */

   /* Primitive border_highlight   */	BorderHighlight,
    /* Primitive border_unhighlight */	BorderUnhighlight,
    /* translations		    */  XtInheritTranslations,
    /* arm_and_activate		    */  ArmAndActivate,
    /* get resources		    */  NULL,
    /* num get_resources	    */  0,
    /* extension		    */  NULL,
  },

  { /* label_class record */
 
    /* setOverrideCallback*/    XmInheritWidgetProc,
    /* Menu procedures    */    XmInheritMenuProc,
    /* menu trav xlations */	XtInheritTranslations,
    /* extension	  */	NULL,
  },

  { /* drawnbutton_class record */

    /* extension	  */    NULL,	
  }

};
externaldef(xmdrawnbuttonwidgetclass) WidgetClass xmDrawnButtonWidgetClass =
			     (WidgetClass)&xmDrawnButtonClassRec;

/* Trait record for drawnButton */

static XmConst XmActivatableTraitRec drawnButtonAT = {
  0,		/* version */
  ChangeCB,
};

/* Menu Savvy trait record */
static XmMenuSavvyTraitRec MenuSavvyRecord = {
    /* version: */
    -1,
    NULL,
    NULL,
    NULL,
    _XmCBNameActivate,
};


/************************************************************************
 *
 *     Arm
 *
 *     This function processes button 1 down occuring on the drawnbutton.
 *     Mark the drawnbutton as armed if XmNpushButtonEnabled is TRUE.
 *     The callbacks for XmNarmCallback are called.
 *
 ************************************************************************/
/*ARGSUSED*/
static void 
Arm(
        Widget wid,
        XEvent *event,
        String *params,		/* unused */
        Cardinal *num_params )	/* unused */
{
    XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
    XButtonEvent *buttonEvent = (XButtonEvent *) event;
    XmDrawnButtonCallbackStruct call_value;
   
    (void) XmProcessTraversal((Widget) db, XmTRAVERSE_CURRENT);

    db -> drawnbutton.armed = TRUE;
    if (event && (event->type == ButtonPress))
	db -> drawnbutton.armTimeStamp = buttonEvent->time;
    
    if (db->drawnbutton.pushbutton_enabled)
	DrawPushButton(db, db->drawnbutton.armed);

    if (db->drawnbutton.arm_callback) {
	XFlush(XtDisplay (db));

	call_value.reason = XmCR_ARM;
	call_value.event = event;
	call_value.window = XtWindow (db);
	XtCallCallbackList ((Widget) db, db->drawnbutton.arm_callback, 
			    &call_value);
    }
}


/*ARGSUSED*/
static void 
MultiArm(
        Widget wid,
        XEvent *event,
        String *params,		/* unused */
        Cardinal *num_params )	/* unused */
{
    if (((XmDrawnButtonWidget) wid)->drawnbutton.multiClick == XmMULTICLICK_KEEP)
			Arm (wid, event, NULL, NULL);
}

/************************************************************************
 *
 *     Activate
 *
 *     Mark the drawnbutton as unarmed (i.e. inactive).
 *     The foreground and background colors will revert to the 
 *     unarmed state if XmNinvertOnArm is set to TRUE.
 *     If the button release occurs inside of the DrawnButton, the 
 *     callbacks for XmNactivateCallback are called.
 *
 ************************************************************************/
static void 
Activate(
        Widget wid,
        XEvent *buttonEvent,
        String *params,
        Cardinal *num_params )
{
        XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
   if (db -> drawnbutton.armed == FALSE)
      return;

   db->drawnbutton.click_count = 1;
   ActivateCommon ((Widget) db, buttonEvent, params, num_params);

}

static void 
MultiActivate(
        Widget wid,
        XEvent *buttonEvent,
        String *params,
        Cardinal *num_params )
{
        XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
   /* When a multi click sequence occurs and the user Button Presses and
    * holds for a length of time, the final release should look like a
    * new/separate activate.
    */
  if (db->drawnbutton.multiClick == XmMULTICLICK_KEEP)  
  { if ((buttonEvent->xbutton.time - db->drawnbutton.armTimeStamp) >
	   XtGetMultiClickTime(XtDisplay(db)))
     db->drawnbutton.click_count = 1;
   else
     db->drawnbutton.click_count++;
   ActivateCommon ((Widget) db, buttonEvent, params, num_params) ;
   Disarm ((Widget) db, buttonEvent, params, num_params) ;
 }
}

/*ARGSUSED*/
static void 
ActivateCommon(
        Widget wid,
        XEvent *event,
        String *params,		/* unused */
        Cardinal *num_params )	/* unused */
{
   XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
   XmDrawnButtonCallbackStruct call_value;
   XmMenuSystemTrait menuSTrait;

   menuSTrait = (XmMenuSystemTrait) 
     XmeTraitGet((XtPointer) XtClass(XtParent(wid)), XmQTmenuSystem);
      
   if (event && (event->xbutton.type != ButtonRelease))
       return;
      
   db -> drawnbutton.armed = FALSE;
   if (db->drawnbutton.pushbutton_enabled)
	DrawPushButton(db, db->drawnbutton.armed);


  /* CR 9181: Consider clipping when testing visibility. */
  if ((db->drawnbutton.activate_callback) &&
      ((event->xany.type == ButtonPress) || 
       (event->xany.type == ButtonRelease)) &&
      _XmGetPointVisibility(wid, event->xbutton.x_root, event->xbutton.y_root))
   {
      XFlush(XtDisplay (db));

      call_value.reason = XmCR_ACTIVATE;
      call_value.event = event;
      call_value.window = XtWindow (db);
      call_value.click_count = db->drawnbutton.click_count;

      if ((db->drawnbutton.multiClick == XmMULTICLICK_DISCARD) &&
	  (call_value.click_count > 1))
      {
	  return;
      }

      if (menuSTrait != NULL)
      {
	menuSTrait->entryCallback(XtParent(db), (Widget) db, 
					   &call_value);
      }

      if ((! db->label.skipCallback) &&
	  (db->drawnbutton.activate_callback))
      {
	 XtCallCallbackList ((Widget) db, db->drawnbutton.activate_callback,
				&call_value);
      }
   }
}



static void 
DB_FixTearoff( XmDrawnButtonWidget db)	
{
	 if  (XmMENU_PULLDOWN == db->label.menu_type) 
	 {							
		Widget mwid = XmGetPostedFromWidget(XtParent(db));	
		if (mwid && XmIsRowColumn(mwid)
			&& (XmMENU_OPTION == RC_Type(mwid)) 
			&& _XmIsActiveTearOff(XtParent(db))) 
			XmProcessTraversal((Widget) db, XmTRAVERSE_CURRENT);
	 }							
}
/************************************************************************
 *
 *     ArmAndActivate
 *
 ************************************************************************/
/*ARGSUSED*/
static void 
ArmAndActivate(
        Widget wid,
        XEvent *event,
        String *params,		/* unused */
        Cardinal *num_params )	/* unused */
{
   XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
   XmDrawnButtonCallbackStruct call_value;
   XmMenuSystemTrait menuSTrait;

   menuSTrait = (XmMenuSystemTrait) 
     XmeTraitGet((XtPointer) XtClass(XtParent(wid)), XmQTmenuSystem);

   db -> drawnbutton.armed = TRUE;
   if (db->drawnbutton.pushbutton_enabled)
	DrawPushButton(db, db->drawnbutton.armed);

   XFlush(XtDisplay (db));

   if (db->drawnbutton.arm_callback)
   {
      call_value.reason = XmCR_ARM;
      call_value.event = event;
      call_value.window = XtWindow (db);
      XtCallCallbackList ((Widget) db, db->drawnbutton.arm_callback, &call_value);
   }

   call_value.reason = XmCR_ACTIVATE;
   call_value.event = event;
   call_value.window = XtWindow (db);
   call_value.click_count = 1;		/* always 1 in kselect */

   if (menuSTrait != NULL)
   {
     menuSTrait->entryCallback(XtParent(db), (Widget) db, 
					&call_value);
   }

   if ((! db->label.skipCallback) &&
       (db->drawnbutton.activate_callback))
   {
      XtCallCallbackList ((Widget) db, db->drawnbutton.activate_callback,
			  &call_value);
   }

   db->drawnbutton.armed = FALSE;
   
   if (db->drawnbutton.disarm_callback)
   {
      call_value.reason = XmCR_DISARM;
      XtCallCallbackList ((Widget) db, db->drawnbutton.disarm_callback,
                             &call_value);
   }

   /* If the button is still around, show it released, after a short delay */
   if (!db->core.being_destroyed && db->drawnbutton.pushbutton_enabled)
   {
       db->drawnbutton.timer = XtAppAddTimeOut(
				       XtWidgetToApplicationContext((Widget)db),
                                       (unsigned long) DELAY_DEFAULT,
                                       ArmTimeout,
                                       (XtPointer)db);
   }
}

/*ARGSUSED*/
static void 
ArmTimeout (
	XtPointer closure,
	XtIntervalId *id )
{
  XmDrawnButtonWidget db = (XmDrawnButtonWidget) closure ;

  db -> drawnbutton.timer = 0;

  if (db->drawnbutton.pushbutton_enabled &&
      XtIsRealized((Widget)db) && XtIsManaged((Widget)db))
   {
     DrawPushButton(db, db->drawnbutton.armed);
     XFlush (XtDisplay (db));
   }
}



/************************************************************************
 *
 *    Disarm
 *
 *     Mark the drawnbutton as unarmed (i.e. active).
 *     The foreground and background colors will revert to the 
 *     unarmed state if XmNinvertOnSelect is set to TRUE and the
 *     drawnbutton is not in a menu.
 *     The callbacks for XmNdisarmCallback are called..
 *
 ************************************************************************/
/*ARGSUSED*/
static void 
Disarm(
        Widget wid,
        XEvent *event,
        String *params,		/* unused */
        Cardinal *num_params )	/* unused */
{
   XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
   XmDrawnButtonCallbackStruct call_value;

   db -> drawnbutton.armed = FALSE;

   if (db->drawnbutton.disarm_callback)
   {
      XFlush(XtDisplay (db));

      call_value.reason = XmCR_DISARM;
      call_value.event = event;
      call_value.window = XtWindow (db);
      XtCallCallbackList ((Widget) db, db->drawnbutton.disarm_callback, &call_value);
   }
}



/************************************************************************
 *
 *     BtnDown
 *
 *     This function processes a button down occuring on the drawnbutton
 *     when it is in a popup, pulldown, or option menu.
 *     Popdown the posted menu.
 *     Turn parent's traversal off.
 *     Mark the drawnbutton as armed (i.e. active).
 *     The callbacks for XmNarmCallback are called.
 *
 ************************************************************************/

/*ARGSUSED*/
static void 
BtnDown(
        Widget wid,
        XEvent *event,
        String *params,		/* unused */
        Cardinal *num_params )	/* unused */
{
  XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
  XmDrawnButtonCallbackStruct call_value;
  Boolean validButton = False;
  Boolean already_armed;
  ShellWidget popup;
  XmMenuSystemTrait menuSTrait;
  
  /* Support menu replay, free server input queue until next button event */
  XAllowEvents(XtDisplay(db), SyncPointer, CurrentTime);
  
  /* If no menu system trait then parent isn't a menu as it should be. */
  menuSTrait = (XmMenuSystemTrait) 
    XmeTraitGet((XtPointer) XtClass(XtParent(db)), XmQTmenuSystem);
  if (menuSTrait == NULL) 
    return;
  
  if (event && (event->type == ButtonPress))
    validButton = menuSTrait->verifyButton(XtParent(db), event);
  
  if (!validButton)
    return;
  
  _XmSetInDragMode((Widget)db, True);
  
  /* Popdown other popus that may be up */
  if (!(popup = (ShellWidget)_XmGetRC_PopupPosted(XtParent(db))))
    {
      if (!XmIsMenuShell(XtParent(XtParent(db))))
	{
	  /* In case tear off not armed and no grabs in place, do it now.
	   * Ok if already armed and grabbed - nothing done.
	   */
	  menuSTrait->tearOffArm(XtParent(db));
	}
    }
  
  if (popup)
    {
      if (popup->shell.popped_up)
	menuSTrait->popdownEveryone((Widget) popup, event);
    } 
  
  /* Set focus to this drawnbutton.  This must follow the possible
   * unhighlighting of the CascadeButton else it'll screw up active_child.
   */
  (void)XmProcessTraversal ((Widget) db, XmTRAVERSE_CURRENT);
  /* get the location cursor - get consistent with Gadgets */
  
  already_armed = db->drawnbutton.armed;
  db->drawnbutton.armed = TRUE;
  
  if (db->drawnbutton.arm_callback && !already_armed)
    {
      XFlush (XtDisplay (db));
      
      call_value.reason = XmCR_ARM;
      call_value.event = event;
      XtCallCallbackList((Widget) db, db->drawnbutton.arm_callback, &call_value);
    }
  _XmRecordEvent (event);
}

/************************************************************************
 *
 *     BtnUp
 *
 *     This function processes a button up occuring on the drawnbutton
 *     when it is in a popup, pulldown, or option menu.
 *     Mark the drawnbutton as unarmed (i.e. inactive).
 *     The callbacks for XmNactivateCallback are called.
 *     The callbacks for XmNdisarmCallback are called.
 *
 ************************************************************************/

/*ARGSUSED*/
static void 
BtnUp(
        Widget wid,
        XEvent *event,
        String *params,		/* unused */
        Cardinal *num_params )	/* unused */
{
  XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
  Widget parent =  XtParent(db);
  XmDrawnButtonCallbackStruct call_value;
  Boolean flushDone = False;
  Boolean validButton = False;
  Boolean popped_up;
  Boolean is_menupane = Lab_IsMenupane(db);
  Widget shell = XtParent(XtParent(db));
  XmMenuSystemTrait menuSTrait;
  
  /* If no menu system trait then parent isn't a menu as it should be. */
  menuSTrait = (XmMenuSystemTrait) 
    XmeTraitGet((XtPointer) XtClass(XtParent(db)), XmQTmenuSystem);
  if (menuSTrait == NULL) 
    return;
  
  if (event && (event->type == ButtonRelease))
    validButton = menuSTrait->verifyButton(parent, event);
  
  if (!validButton || (db->drawnbutton.armed == FALSE))
    return;
  
  db->drawnbutton.armed = FALSE;
  
  if (is_menupane && !XmIsMenuShell(shell))
    popped_up = menuSTrait->popdown((Widget) db, event);
  else
    popped_up = menuSTrait->buttonPopdown((Widget) db, event);
  
  _XmRecordEvent(event);
  
  /* XmMENU_POPDOWN left the menu posted on button click - don't activate! */
  if (popped_up)
    return;
  
  call_value.reason = XmCR_ACTIVATE;
  call_value.event = event;
  call_value.click_count = 1;  

  /* if the parent is menu system able, notify it about the select */
  if (menuSTrait != NULL)
    {
      menuSTrait->entryCallback(parent, (Widget) db, &call_value);
      flushDone = True;
    }
  
  if ((! db->label.skipCallback) &&
      (db->drawnbutton.activate_callback))
    {
      XFlush (XtDisplay (db));
      flushDone = True;
      XtCallCallbackList ((Widget) db, db->drawnbutton.activate_callback,
			  &call_value);
    }
  if (db->drawnbutton.disarm_callback)
    {
      if (!flushDone)
	XFlush (XtDisplay (db));
      call_value.reason = XmCR_DISARM;
      call_value.event = event;
      XtCallCallbackList ((Widget) db, db->drawnbutton.disarm_callback,
			  &call_value);
    }
  
  /* If the original shell does not indicate an active menu, but rather a
   * tear off pane, leave the button in an armed state.  Also, briefly
   * display the button as depressed to give the user some feedback of
   * the selection.
   */
  
  if (is_menupane) /* necessary check? */
    {
      if (!XmIsMenuShell(shell))
	{
	  if (XtIsSensitive((Widget)db))
	    {
	      XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(db));
	      Boolean etched_in = dpy->display.enable_etched_in_menu;
	      
	      if ((db->core.width > 2 * db->primitive.highlight_thickness) &&
		  (db->core.height > 2 * db->primitive.highlight_thickness))
		XmeDrawShadows
		  (XtDisplay (db), XtWindow (db),
		   db->primitive.bottom_shadow_GC,
		   db->primitive.top_shadow_GC,
		   db->primitive.highlight_thickness,
		   db->primitive.highlight_thickness,
		   db->core.width - 2 * db->primitive.highlight_thickness,
		   db->core.height - 2 * db->primitive.highlight_thickness,
		   db->primitive.shadow_thickness, 
		   etched_in ? XmSHADOW_IN : XmSHADOW_OUT);
	      
	      XFlush (XtDisplay (db));
	      flushDone = True;

	      if (db->core.being_destroyed == False)
		{
		  if (!db->drawnbutton.timer)
		    db->drawnbutton.timer =
		      XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)db),
				      (unsigned long) DELAY_DEFAULT,
				      ArmTimeout,
				      (XtPointer)(db));
		}
	      
	      db->drawnbutton.armed = TRUE;
	      if (db->drawnbutton.arm_callback)
		{
		  if (!flushDone)
		    XFlush (XtDisplay (db));
		  call_value.reason = XmCR_ARM;
		  call_value.event = event;
		  XtCallCallbackList ((Widget) db, db->drawnbutton.arm_callback,
				      &call_value);
		}
	    }
	}
      else
	menuSTrait->reparentToTearOffShell(XtParent(db), event);
    }
  
  _XmSetInDragMode((Widget)db, False);
  
  /* For the benefit of tear off menus, we must set the focus item
   * to this button.  In normal menus, this would not be a problem
   * because the focus is cleared when the menu is unposted.
   */
  if (!XmIsMenuShell(shell))
    XmProcessTraversal((Widget) db, XmTRAVERSE_CURRENT);
  DB_FixTearoff(db);
}

/************************************************************************
 *
 *  Enter
 *
 ************************************************************************/
static void 
Enter(
        Widget wid,
        XEvent *event,
        String *params,
        Cardinal *num_params )
{
   XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
   XmDrawnButtonCallbackStruct call_value;

   if (Lab_IsMenupane(db)) {
     if ((((ShellWidget) XtParent(XtParent(db)))->shell.popped_up) &&
	 _XmGetInDragMode((Widget)db))
       {
	 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid));

	 if (db->drawnbutton.armed)
	   return;
	  
	 /* So KHelp event is delivered correctly */
	 _XmSetFocusFlag (XtParent(XtParent(db)), XmFOCUS_IGNORE, TRUE);
	 XtSetKeyboardFocus(XtParent(XtParent(db)), (Widget)db);
	 _XmSetFocusFlag (XtParent(XtParent(db)), XmFOCUS_IGNORE, FALSE);

	 db -> drawnbutton.armed = TRUE;

	 ((XmManagerWidget) XtParent(wid))->manager.active_child = wid;

	 if (db->drawnbutton.pushbutton_enabled)
	   DrawPushButton(db, db->drawnbutton.armed);

	 if (db->drawnbutton.arm_callback)
	   {
	     XFlush (XtDisplay (db));
	      
	     call_value.reason = XmCR_ARM;
	     call_value.event = event;
	     XtCallCallbackList ((Widget) db,
				 db->drawnbutton.arm_callback, &call_value);
	   }
       }
   }
   else {
     _XmPrimitiveEnter (wid, event, params, num_params);

     if (db -> drawnbutton.pushbutton_enabled &&
	 db -> drawnbutton.armed == TRUE)
       DrawPushButton(db, TRUE);
   }
}


/************************************************************************
 *
 *  Leave
 *
 ************************************************************************/
static void 
Leave(
      Widget wid,
      XEvent *event,
      String *params,
      Cardinal *num_params )
{
  XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
  XmDrawnButtonCallbackStruct call_value;

  if (Lab_IsMenupane(db)) {
    if (_XmGetInDragMode((Widget)db) && db->drawnbutton.armed &&
	(/* !ActiveTearOff || */ event->xcrossing.mode == NotifyNormal))
      {
	XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid));

	db->drawnbutton.armed = FALSE;
  
	((XmManagerWidget) XtParent(wid))->manager.active_child = NULL;

	if (db->drawnbutton.pushbutton_enabled) {
	  XmeClearBorder
	    (XtDisplay (db), XtWindow (db),
	     db->primitive.highlight_thickness,
	     db->primitive.highlight_thickness,
	     db->core.width - 2 * db->primitive.highlight_thickness,
	     db->core.height - 2 * db->primitive.highlight_thickness,
	     db->primitive.shadow_thickness);
	}

	if (db->drawnbutton.disarm_callback)
	  {
	    XFlush (XtDisplay (db));
	      
	    call_value.reason = XmCR_DISARM;
	    call_value.event = event;
	    XtCallCallbackList ((Widget) db, 
				db->drawnbutton.disarm_callback, &call_value);
	  }
      }
  }
  else {
    _XmPrimitiveLeave (wid, event, params, num_params);

    if (db -> drawnbutton.pushbutton_enabled &&
	db -> drawnbutton.armed == TRUE)
      DrawPushButton(db, FALSE);
  }
}

/*************************************<->*************************************
 *
 *  BorderHighlight 
 *
 *************************************<->***********************************/

static void 
BorderHighlight(
        Widget wid )
{
  XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
  XmDrawnButtonCallbackStruct call_value;
  XEvent * event = NULL;
  
  if (Lab_IsMenupane(db)) {
    XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid));
    Boolean already_armed = db->drawnbutton.armed;

    db->drawnbutton.armed = TRUE;

    if (db->drawnbutton.pushbutton_enabled)
      DrawPushButton(db, db->drawnbutton.armed);
      
    if (!already_armed && db->drawnbutton.arm_callback) 
      {
	XFlush (XtDisplay (db));
	  
	call_value.reason = XmCR_ARM;
	call_value.event = event;
	XtCallCallbackList ((Widget) db, db->drawnbutton.arm_callback, 
			    &call_value);
      }
  }
  else {
    XtWidgetProc border_highlight;

    _XmProcessLock();
    border_highlight = xmLabelClassRec.primitive_class.border_highlight;
    _XmProcessUnlock();
    (*border_highlight)(wid);
  }

}

/*************************************<->*************************************
 *
 *  BorderUnhighlight
 *
 *************************************<->***********************************/

static void 
BorderUnhighlight(
		  Widget wid )
{
  XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
  XmDrawnButtonCallbackStruct call_value;
  XEvent * event = NULL;

  if (Lab_IsMenupane(db))
    {
      XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid));
      Boolean already_armed = db->drawnbutton.armed;

      db->drawnbutton.armed = FALSE;

      if (db->drawnbutton.pushbutton_enabled) {
	XmeClearBorder
	  (XtDisplay (db), XtWindow (db),
	   db->primitive.highlight_thickness,
	   db->primitive.highlight_thickness,
	   db->core.width - 2 * db->primitive.highlight_thickness,
	   db->core.height - 2 * db->primitive.highlight_thickness,
	   db->primitive.shadow_thickness);
      }

      if (already_armed && db->drawnbutton.disarm_callback)
	{
	  XFlush (XtDisplay (db));
	  
	  call_value.reason = XmCR_DISARM;
	  call_value.event = event;
	  XtCallCallbackList ((Widget) db, db->drawnbutton.disarm_callback, 
			      &call_value);
	}
    }
  else {
    XtWidgetProc border_unhighlight;

    _XmProcessLock();
    border_unhighlight = xmLabelClassRec.primitive_class.border_unhighlight;
    _XmProcessUnlock();
    (*border_unhighlight)(wid);
  }
}



/************************************************************************
 *
 *  ClassInitialize
 *     Set up the base class extension record.
 *
 ************************************************************************/
static void 
ClassInitialize( void )
{
  /* parse the various translation tables */
  menu_parsed    = XtParseTranslationTable(menuTranslations);
  default_parsed = XtParseTranslationTable(defaultTranslations);
  
   /* set up base class extension quark */
   drawnBBaseClassExtRec.record_type = XmQmotif;
}

/************************************************************************
 *
 *  ClassPartInitialize
 *     Set up the fast subclassing for the widget
 *
 ************************************************************************/
static void 
ClassPartInitialize(
        WidgetClass wc )
{
  _XmFastSubclassInit (wc, XmDRAWN_BUTTON_BIT);

  /* Install the menu savvy trait record,  copying fields from XmLabel */
  _XmLabelCloneMenuSavvy (wc, &MenuSavvyRecord);

  /* Install the activatable trait for all subclasses */
  XmeTraitSet((XtPointer)wc, XmQTactivatable, (XtPointer) &drawnButtonAT);
}
     
/************************************************************
 *
 * InitializePrehook
 *
 * Put the proper translations in core_class tm_table so that
 * the data is massaged correctly
 *
 ************************************************************/

/*ARGSUSED*/
static void
InitializePrehook(
        Widget rw,		/* unused */
        Widget nw,
        ArgList args,		/* unused */
        Cardinal *num_args )	/* unused */
{
  XmDrawnButtonWidget bw = (XmDrawnButtonWidget) nw ;
  unsigned char type;
  XmMenuSystemTrait menuSTrait;
  
  menuSTrait = (XmMenuSystemTrait) 
    XmeTraitGet((XtPointer) XtClass(XtParent(nw)), XmQTmenuSystem);
  
  _XmSaveCoreClassTranslations (nw);
  
  if (menuSTrait != NULL)
    type = menuSTrait->type(XtParent(nw));
  else 
    type = XmWORK_AREA;
  
  _XmProcessLock();
  if (type == XmMENU_PULLDOWN ||
      type == XmMENU_POPUP)
    nw->core.widget_class->core_class.tm_table = (String) menu_parsed;
  else 
    nw->core.widget_class->core_class.tm_table = (String) default_parsed;
  
  /* CR 2990: Use XmNbuttonFontList as the default font. */
  if (bw->label.font == NULL)
    bw->label.font = XmeGetDefaultRenderTable (nw, XmBUTTON_FONTLIST);
  _XmProcessUnlock();
}

/************************************************************
 *
 * InitializePosthook
 *
 * restore core class translations
 *
 ************************************************************/

/*ARGSUSED*/
static void
InitializePosthook(
        Widget rw,		/* unused */
        Widget nw,
        ArgList args,		/* unused */
        Cardinal *num_args )	/* unused */
{
  _XmRestoreCoreClassTranslations (nw);
}

/*************************************<->*************************************
 *
 *  Initialize 
 *
 *************************************<->***********************************/
/*ARGSUSED*/
static void 
Initialize(
        Widget rw,
        Widget nw,
        ArgList args,
        Cardinal *num_args )
{
   XmDrawnButtonWidget new_w = (XmDrawnButtonWidget) nw ;
   XmDrawnButtonWidget req_w = (XmDrawnButtonWidget) rw ;

   /* CR 2990:  Use XmNbuttonFontList as the default font. */
   if (req_w->label.font == NULL)
     {
       XmFontListFree (new_w->label.font);
       new_w->label.font =
	 XmFontListCopy (XmeGetDefaultRenderTable (nw, XmBUTTON_FONTLIST));
     }

   new_w->drawnbutton.armed = FALSE;
   new_w->drawnbutton.timer = 0;

   /* if menuProcs is not set up yet, try again */
   if (xmLabelClassRec.label_class.menuProcs == (XmMenuProc)NULL)
      xmLabelClassRec.label_class.menuProcs =
	 (XmMenuProc) _XmGetMenuProcContext();

   if(    !XmRepTypeValidValue( XmRID_SHADOW_TYPE,
                               new_w->drawnbutton.shadow_type, (Widget) new_w)    )
   {
      new_w -> drawnbutton.shadow_type = XmSHADOW_ETCHED_IN;
   }

}

/*************************************<->*************************************
 *
 *  Resize (db)
 *
 *************************************<->***********************************/
static void 
Resize(
        Widget wid )
{
   XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
   XmDrawnButtonCallbackStruct call_value;
   XtWidgetProc resize;

   _XmProcessLock();
   resize = xmLabelClassRec.core_class.resize;
   _XmProcessUnlock();

  (* resize) ((Widget) db);
 
   /* CR 5419: Suppress redundant calls to the resize callbacks. */
   if (db->drawnbutton.resize_callback &&
       !Lab_ComputingSize(db))
   {
      XFlush(XtDisplay (db));
      call_value.reason = XmCR_RESIZE;
      call_value.event = NULL;
      call_value.window = XtWindow (db);
      XtCallCallbackList ((Widget) db, db->drawnbutton.resize_callback, &call_value);
   }
}


/*************************************<->*************************************
 *
 *  Redisplay (db, event, region)
 *
 *************************************<->***********************************/
/*ARGSUSED*/
static void 
Redisplay(
        Widget wid,
        XEvent *event,
        Region region )
{
   XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
   XmDrawnButtonCallbackStruct call_value;

   if (XtIsRealized((Widget)db)) 
   {
        if (event) {
	 XtExposeProc expose;

	 _XmProcessLock();
	 expose = xmLabelClassRec.core_class.expose;
	 _XmProcessUnlock();

         (* expose) ((Widget) db, event, region);
        }

 	if (db->drawnbutton.pushbutton_enabled)
 	    DrawPushButton(db, db->drawnbutton.armed);
  
 	else
 	    XmeDrawShadows(XtDisplay((Widget) db),
 			    XtWindow((Widget) db),
 			    db -> primitive.top_shadow_GC,
 			    db -> primitive.bottom_shadow_GC,
 			    db -> primitive.highlight_thickness,
 			    db -> primitive.highlight_thickness,
 			    db -> core.width - 2 *
 			       db -> primitive.highlight_thickness,
 			    db -> core.height - 2 *
 			       db -> primitive.highlight_thickness,	
			    db -> primitive.shadow_thickness,
 			    db->drawnbutton.shadow_type);
 			   
      if (db->drawnbutton.expose_callback)
      {
         XFlush(XtDisplay (db));

	 call_value.reason = XmCR_EXPOSE;
	 call_value.event = event;
	 call_value.window = XtWindow (db);
	 XtCallCallbackList ((Widget) db, db->drawnbutton.expose_callback, &call_value);
      }

   }
}


static void 
DrawPushButton(
        XmDrawnButtonWidget db,
#if NeedWidePrototypes
        int armed )
#else
        Boolean armed )
#endif /* NeedWidePrototypes */
{
  XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay((Widget) db));
  Boolean etched_in = dpy -> display.enable_etched_in_menu;
  Boolean in_menu = Lab_IsMenupane((Widget) db);
  Boolean do_draw;
  unsigned int type;

  do_draw = (! in_menu) || (in_menu && armed);

  if (in_menu)
    type = etched_in ? XmSHADOW_IN : XmSHADOW_OUT;
  else
    type = armed ? XmSHADOW_IN : XmSHADOW_OUT;

  if (do_draw)
    XmeDrawShadows (XtDisplay (db), XtWindow (db), 
		    db -> primitive.top_shadow_GC,
		    db -> primitive.bottom_shadow_GC, 
		    db -> primitive.highlight_thickness,
		    db -> primitive.highlight_thickness,
		    db -> core.width - 2 * 
		    db->primitive.highlight_thickness,
		    db -> core.height - 2 * 
		    db->primitive.highlight_thickness,
		    db -> primitive.shadow_thickness,
		    type);
}


/************************************************************************
 *
 *  SetValuesPrehook
 *
 ************************************************************************/

/*ARGSUSED*/
static Boolean 
SetValuesPrehook(
        Widget cw,		/* unused */
        Widget rw,		/* unused */
        Widget nw,
        ArgList args,		/* unused */
        Cardinal *num_args )	/* unused */
{
  XmDrawnButtonWidget bw = (XmDrawnButtonWidget) nw ;

  /* CR 2990: Use XmNbuttonFontList as the default font. */
  if (bw->label.font == NULL)
    bw->label.font = XmeGetDefaultRenderTable (nw, XmBUTTON_FONTLIST);

  return False;
}

/*************************************<->*************************************
 *
 *  SetValues(current, request, new_w)
 *
 *   Description:
 *   -----------
 *     This is the set values procedure for the drawnbutton class.  It is
 *     called last (the set values rtnes for its superclasses are called
 *     first).
 *
 *
 *   Inputs:
 *   ------
 *    current = original widget;
 *    request = original copy of request;
 *    new_w = copy of request which reflects changes made to it by
 *          set values procedures of its superclasses;
 *    last = TRUE if this is the last set values procedure to be called.
 * 
 *   Outputs:
 *   -------
 *
 *   Procedures Called
 *   -----------------
 *
 *************************************<->***********************************/
/*ARGSUSED*/
static Boolean 
SetValues(
        Widget cw,
        Widget rw,
        Widget nw,
        ArgList args,
        Cardinal *num_args )
{
   XmDrawnButtonWidget current = (XmDrawnButtonWidget) cw ;
   XmDrawnButtonWidget new_w = (XmDrawnButtonWidget) nw ;
   Boolean  flag = FALSE;    /* our return value */

    /*  Check the data put into the new widget.  */

   if(    !XmRepTypeValidValue( XmRID_SHADOW_TYPE,
                               new_w->drawnbutton.shadow_type, (Widget) new_w)    )
   {
      new_w->drawnbutton.shadow_type = current->drawnbutton.shadow_type ;
   }

   if (new_w -> drawnbutton.shadow_type != current-> drawnbutton.shadow_type ||
       new_w -> primitive.foreground != current -> primitive.foreground    ||
       new_w -> core.background_pixel != current -> core.background_pixel  ||
       new_w -> primitive.highlight_thickness != 
       current -> primitive.highlight_thickness                          ||
       new_w -> primitive.shadow_thickness !=
       current -> primitive.shadow_thickness)
   {
      flag = TRUE;
   }

   return(flag);
}




/*************************************************************************
 *
 *  Realize
 *	This function sets the bit gravity to forget.
 *
 *************************************************************************/
static void 
Realize(
        Widget w,
        XtValueMask *p_valueMask,
        XSetWindowAttributes *attributes )
{
   Mask valueMask = *p_valueMask;

   valueMask |= CWBitGravity | CWDontPropagate;
   attributes->bit_gravity = ForgetGravity;
   attributes->do_not_propagate_mask =
      ButtonPressMask | ButtonReleaseMask |
      KeyPressMask | KeyReleaseMask | PointerMotionMask;

   XtCreateWindow (w, InputOutput, CopyFromParent, valueMask, attributes);
}



/************************************************************************
 *
 *  Destroy
 *	Clean up allocated resources when the widget is destroyed.
 *
 ************************************************************************/
static void 
Destroy(
        Widget wid )
{
        XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
   if (db->drawnbutton.timer)
       XtRemoveTimeOut (db->drawnbutton.timer);
}

/************************************************************************
 *
 *  ChangeCB
 *	add or remove the activate callback list.
 *      
 ************************************************************************/
static void 
ChangeCB(
	 Widget w, 
	 XtCallbackProc activCB,
	 XtPointer closure,
	 Boolean setunset)
{
    if (setunset) {
	XtAddCallback (w, XmNactivateCallback, activCB, closure);
    } else {
	XtRemoveCallback (w, XmNactivateCallback, activCB, closure);
    }
}


/************************************************************************
 *
 *		Application Accessible External Functions
 *
 ************************************************************************/


/************************************************************************
 *
 *  XmCreateDrawnButton
 *	Create an instance of a drawnbutton and return the widget id.
 *
 ************************************************************************/
Widget 
XmCreateDrawnButton(
        Widget parent,
        char *name,
        ArgList arglist,
        Cardinal argcount )
{
   return (XtCreateWidget (name, xmDrawnButtonWidgetClass, 
                           parent, arglist, argcount));
}
