/* 
 * Motif
 *
 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
 *
 * These libraries and programs are free software; you can
 * redistribute them and/or modify them under the terms of the GNU
 * Lesser General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * These libraries and programs are distributed in the hope that
 * they will be useful, but WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with these librararies and programs; if not, write
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA 02110-1301 USA
*/ 
#ifdef REV_INFO
#ifndef lint
static char rcsid[] = "$TOG: LabelG.c /main/24 1999/01/26 15:31:18 mgreess $"
#endif
#endif

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define FIX_1517
#define FIX_1654

#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <X11/IntrinsicP.h>
#include <X11/ShellP.h>
#include <X11/Xatom.h>
#include <X11/keysymdef.h>
#include <Xm/AccColorT.h>
#include <Xm/AccTextT.h>
#include <Xm/AtomMgr.h>
#include <Xm/BaseClassP.h>
#include <Xm/CacheP.h>
#include <Xm/CareVisualT.h>
#include <Xm/CascadeBGP.h>
#include <Xm/DisplayP.h>
#include <Xm/DragC.h>
#include <Xm/DragIcon.h>
#include <Xm/DragIconP.h>
#include <Xm/DrawP.h>
#include <Xm/ManagerP.h>
#include <Xm/MenuT.h>
#include <Xm/RowColumnP.h>
#include <Xm/ScreenP.h>
#include <Xm/TraitP.h>
#include <Xm/TransferT.h>
#include <Xm/VaSimpleP.h>
#include "BaseClassI.h"
#include "CacheI.h"
#include "ColorI.h"
#include "ExtObjectI.h"
#include "GadgetUtiI.h"
#include "LabelGI.h"
#include "MessagesI.h"
#include "MenuProcI.h"
#include "PixConvI.h"
#include "RepTypeI.h"
#include "ScreenI.h"
#include "SyntheticI.h"
#include "TravActI.h"
#include "XmI.h"
#include "XmosI.h"
#include "XmStringI.h"
#include <Xm/XpmP.h>
#include <string.h>
#include <Xm/XmP.h>
#ifdef FIX_1381
#include <Xm/ColorI.h>
#endif
#ifdef FIX_1521
#ifdef USE_XFT
#include "XmRenderTI.h"
#include <X11/Xft/Xft.h>
#endif
#endif

#define Pix(w)      LabG_Pixmap(w)
#define Pix_insen(w)    LabG_PixmapInsensitive(w)

/* Warning Messages */

#define CS_STRING_MESSAGE   _XmMMsgLabel_0003
#define ACC_MESSAGE     _XmMMsgLabel_0004

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

static Pixmap GetTopShadowPixmapDefault(Widget);
static Pixmap GetLabelHighlightPixmapDefault(Widget);
static void ClassInitialize(void);
static void ClassPartInitialize(WidgetClass cl);
static void SecondaryObjectCreate(Widget req, Widget new_w,
ArgList args, Cardinal *num_args);
static void InitializePosthook(Widget req, Widget new_w,
ArgList args, Cardinal *num_args);
static Boolean SetValuesPrehook(Widget oldParent,
Widget refParent,
Widget newParent,
ArgList args,
Cardinal *num_args);
static void GetValuesPrehook(Widget newParent,
ArgList args,
Cardinal *num_args);
static void GetValuesPosthook(Widget new_w,
ArgList args,
Cardinal *num_args);
static Boolean SetValuesPosthook(Widget current,
Widget req,
Widget new_w,
ArgList args,
Cardinal *num_args);
static void BorderHighlight(Widget w);
static void SetNormalGC(XmLabelGadget lw);
static void Resize(Widget wid);
static void Initialize(Widget req, Widget new_w,
ArgList args, Cardinal *num_args);
static XtGeometryResult QueryGeometry(Widget wid,
XtWidgetGeometry *intended,
XtWidgetGeometry *reply);
static void Destroy(Widget w);
static void Redisplay(Widget wid, XEvent *event, Region region);
static Boolean SetValues(Widget cw, Widget rw, Widget nw,
ArgList args, Cardinal *num_args);
static void InputDispatch(Widget wid, XEvent *event, Mask event_mask);
static void Help(Widget w, XEvent *event);
static void GetLabelString(Widget wid, int offset, XtArgVal *value);
static void GetAccelerator(Widget wid, int offset, XtArgVal *value);
static void GetAcceleratorText(Widget wid, int offset, XtArgVal *value);
static XmStringCharSet _XmStringCharsetCreate(XmStringCharSet stringcharset);
static void GetMnemonicCharset(Widget wid, int resource, XtArgVal *value);
static void QualifyLabelLocalCache(XmLabelGadget w);
static void SetOverrideCallback(Widget w);
static Cardinal GetLabelBGClassSecResData(WidgetClass w_class,
XmSecondaryResourceData **data_rtn);
static XtPointer GetLabelClassResBase(Widget widget, XtPointer client_data);
static void SetValuesAlmost(Widget cw, Widget nw,
XtWidgetGeometry *request, XtWidgetGeometry *reply);
static Boolean XmLabelGadgetGetBaselines(Widget wid,
Dimension **baselines,
int *line_count);
static Boolean XmLabelGadgetGetDisplayRect(Widget w,
XRectangle *displayrect);
static void XmLabelGadgetMarginsProc(Widget w,
XmBaselineMargins *margins_rec);
static Widget GetPixmapDragIcon(Widget w);
static void SetGadgetActivateCallbackState(Widget w, XmActivateState state);
static void CheckSetRenderTable(Widget wid, int offset, XrmValue *value);
static void FromPaddingPixels(Widget, int, XtArgVal *);
static XmImportOperator ToPaddingPixels(Widget, int, XtArgVal*);
static Boolean HandleRedraw(Widget kid,
Widget cur_parent,
Widget new_parent,
Mask visual_flag);
static void InitNewColorBehavior(XmLabelGadget lw);
static void DealWithColors(XmLabelGadget lw);
static void DealWithPixmaps(XmLabelGadget lw);
static void InitNewPixmapBehavior(XmLabelGadget lw);
static char* GetLabelGadgetAccelerator(Widget);
static KeySym GetLabelGadgetMnemonic(Widget);
static void GetColors(Widget widget, XmAccessColorData color_data);
/********    End Static Function Declarations    ********/

void _XmLabelConvert(Widget w, XtPointer ignore, XmConvertCallbackStruct*);

/* Transfer trait record */
static XmConst XmTransferTraitRec LabelGTransfer =
{
    0,                                            /* version		  */
    (XmConvertCallbackProc) _XmLabelConvert,      /* convertProc		  */
    NULL,                                         /* destinationProc	  */
    NULL                                          /* destinationPreHookProc */
};

/* Menu Savvy trait record */
static XmConst XmMenuSavvyTraitRec MenuSavvyGadgetRecord =
{
    0,                                            /* version	       */
    SetGadgetActivateCallbackState,               /* disableCallback   */
    GetLabelGadgetAccelerator,                    /* getAccelerator    */
    GetLabelGadgetMnemonic,                       /* getMnemonic       */
    NULL                                          /* getActivateCBName */
};

/* Used to be:
      extern XmConst XmAccessTextualTraitRec _XmLabel_AccessTextualRecord;
   but that was giving a linkage undefined with g++.
   It looks like a G++ bug. */
extern XmAccessTextualTraitRec _XmLabel_AccessTextualRecord;

static XmConst XmCareVisualTraitRec LabelGCVT =
{
    0,                                            /* version */
    HandleRedraw                                  /* redraw */
};

/* Access Colors Trait record for label gadget */
static XmConst XmAccessColorsTraitRec labACT =
{
    0,                                            /* version */
    GetColors,                                    /* getColors */
    NULL                                          /* setColors */
};

/*
 * Uncached resources for Label Gadget
 */

static XtResource resources[] =
{
    /* The following hackery is a way in Xt to see if a widget has been
     * initialized.  We need to know whether or not the gadget cache is
     * valid.  We use "." in the name so that an end user cannot access
     * it from a resource file.  With that in place, we just need to
     * check label.cache != NULL to see if the gadget has been
     * initialized and that we can access the colors for instance. */
    {
        XmNdotCache, XmCDotCache, XmRPointer,
        sizeof(XtPointer), XtOffsetOf(XmLabelGadgetRec, label.cache),
        XtRImmediate, (XtPointer) NULL
    },

    {
        XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension,
        sizeof(Dimension), XtOffsetOf(XmLabelGadgetRec, gadget.shadow_thickness),
        XmRImmediate, (XtPointer) 0
    },

    {
        XmNlabelPixmap, XmCLabelPixmap, XmRDynamicPixmap,
        sizeof(Pixmap), XtOffsetOf(XmLabelGadgetRec, label.pixmap),
        XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP
    },

    {
        XmNlabelInsensitivePixmap, XmCLabelInsensitivePixmap, XmRDynamicPixmap,
        sizeof(Pixmap), XtOffsetOf(XmLabelGadgetRec, label.pixmap_insen),
        XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP
    },

    {
        XmNlabelString, XmCXmString, XmRXmString,
        sizeof(XmString), XtOffsetOf(XmLabelGadgetRec, label._label),
        XmRImmediate, (XtPointer) NULL
    },

    {
        "pri.vate","Pri.vate", XmRBoolean,
        sizeof(Boolean), XtOffsetOf(XmLabelGadgetRec,
        label.check_set_render_table),
        XmRImmediate, (XtPointer) False
    },

    {
        XmNfontList, XmCFontList, XmRFontList,
        sizeof(XmFontList), XtOffsetOf(XmLabelGadgetRec, label.font),
        XmRCallProc, (XtPointer)CheckSetRenderTable
    },

    {
        XmNrenderTable, XmCRenderTable, XmRRenderTable,
        sizeof(XmRenderTable), XtOffsetOf(XmLabelGadgetRec, label.font),
        XmRCallProc, (XtPointer)CheckSetRenderTable
    },

    {
        XmNmnemonic, XmCMnemonic, XmRKeySym,
        sizeof(KeySym), XtOffsetOf(XmLabelGadgetRec, label.mnemonic),
        XmRImmediate, (XtPointer) XK_VoidSymbol
    },

    {
        XmNmnemonicCharSet, XmCMnemonicCharSet, XmRString,
        sizeof(XmStringCharSet), XtOffsetOf(XmLabelGadgetRec,label.mnemonicCharset),
        XmRImmediate, (XtPointer)  XmFONTLIST_DEFAULT_TAG
    },

    {
        XmNaccelerator, XmCAccelerator, XmRString,
        sizeof(char *), XtOffsetOf(XmLabelGadgetRec, label.accelerator),
        XmRImmediate, (XtPointer) NULL
    },

    {
        XmNacceleratorText, XmCAcceleratorText, XmRXmString,
        sizeof(XmString), XtOffsetOf(XmLabelGadgetRec, label._acc_text),
        XmRImmediate, (XtPointer) NULL
    },

    {
        XmNtraversalOn, XmCTraversalOn, XmRBoolean,
        sizeof(Boolean), XtOffsetOf(XmGadgetRec, gadget.traversal_on),
        XmRImmediate, (XtPointer) False
    },

    {
        XmNhighlightThickness, XmCHighlightThickness, XmRHorizontalDimension,
        sizeof(Dimension), XtOffsetOf(XmGadgetRec, gadget.highlight_thickness),
        XmRImmediate, (XtPointer) 0
    },
    
    {
        XmNpixmapPlacement, XmCPixmapPlacement, XmRPixmapPlacement,
        sizeof(XmPixmapPlacement), XtOffsetOf(XmLabelGadgetRec, label.pixmap_placement),
        XmRImmediate, (XtPointer) XmPIXMAP_LEFT
    },
    
    {
        XmNpixmapTextPadding, XmCSpace, XmRVerticalDimension,
        sizeof(Dimension), XtOffsetOf(XmLabelGadgetRec, label.pixmap_text_padding),
        XmRImmediate, (XtPointer) 2
    }
};

/* These 2 slots are needed for the delayed conversion. */
static XtResource label_pixmap_resource[] =
{
    {
        XmNlabelPixmap, XmCLabelPixmap, XmRDynamicPixmap,
        sizeof(Pixmap), XtOffsetOf(XmLabelGadgetRec, label.pixmap),
        XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP
    }
};

static XtResource label_pixmap_insen_resource[] =
{
    {
        XmNlabelInsensitivePixmap, XmCLabelInsensitivePixmap, XmRDynamicPixmap,
        sizeof(Pixmap), XtOffsetOf(XmLabelGadgetRec, label.pixmap_insen),
        XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP
    }
};

/*
 * Cached resources for Label Gadget
 */
static XtResource cache_resources[] =
{
    {
        XmNlabelType, XmCLabelType, XmRLabelType,
        sizeof(unsigned char),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.label_type),
        XmRImmediate, (XtPointer) XmSTRING
    },

    {
        XmNalignment, XmCAlignment, XmRAlignment,
        sizeof(unsigned char),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.alignment),
        XmRImmediate, (XtPointer) XmALIGNMENT_CENTER
    },

    {
        XmNmarginWidth, XmCMarginWidth, XmRHorizontalDimension,
        sizeof(Dimension),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.margin_width),
        XmRImmediate, (XtPointer) 2
    },

    {
        XmNmarginHeight, XmCMarginHeight, XmRVerticalDimension,
        sizeof(Dimension),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.margin_height),
        XmRImmediate, (XtPointer) 2
    },

    {
        XmNmarginLeft, XmCMarginLeft, XmRHorizontalDimension,
        sizeof(Dimension),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.margin_left),
        XmRImmediate, (XtPointer) 0
    },

    {
        XmNmarginRight, XmCMarginRight, XmRHorizontalDimension,
        sizeof(Dimension),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.margin_right),
        XmRImmediate, (XtPointer) 0
    },

    {
        XmNmarginTop, XmCMarginTop, XmRVerticalDimension,
        sizeof(Dimension),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.margin_top),
        XmRImmediate, (XtPointer) 0
    },

    {
        XmNmarginBottom, XmCMarginBottom, XmRVerticalDimension,
        sizeof(Dimension),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.margin_bottom),
        XmRImmediate, (XtPointer) 0
    },

    {
        XmNrecomputeSize, XmCRecomputeSize, XmRBoolean,
        sizeof(Boolean),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.recompute_size),
        XmRImmediate, (XtPointer) True
    },

    {
        XmNstringDirection, XmCStringDirection, XmRStringDirection,
        sizeof(unsigned char),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.string_direction),
        XmRImmediate, (XtPointer) XmDEFAULT_DIRECTION
    },

    {
        XmNlayoutDirection, XmCLayoutDirection, XmRDirection,
        sizeof(XmDirection),
        XtOffsetOf(XmGadgetRec, gadget.layout_direction),
        XmRImmediate, (XtPointer) XmDEFAULT_DIRECTION
    },

    {
        XmNbackground, XmCBackground, XmRPixel,
        sizeof(Pixel),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.background),
        XmRImmediate, (XtPointer) INVALID_PIXEL
    },

    {
        XmNforeground, XmCForeground, XmRPixel,
        sizeof(Pixel),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.foreground),
        XmRImmediate, (XtPointer) INVALID_PIXEL
    },

    {
        XmNtopShadowColor, XmCTopShadowColor, XmRPixel,
        sizeof(Pixel),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.top_shadow_color),
        XmRImmediate, (XtPointer) INVALID_PIXEL
    },

    {
        XmNtopShadowPixmap, XmCTopShadowPixmap, XmRNoScalingDynamicPixmap,
        sizeof(Pixmap),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.top_shadow_pixmap),
        XmRImmediate, (XtPointer) INVALID_PIXMAP
    },

    {
        XmNbottomShadowColor, XmCBottomShadowColor, XmRPixel,
        sizeof(Pixel),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.bottom_shadow_color),
        XmRImmediate, (XtPointer) INVALID_PIXEL
    },

    {
        XmNbottomShadowPixmap, XmCBottomShadowPixmap, XmRNoScalingDynamicPixmap,
        sizeof(Pixmap),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.bottom_shadow_pixmap),
        XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP
    },

    {
        XmNhighlightColor, XmCHighlightColor, XmRPixel,
        sizeof(Pixel),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.highlight_color),
        XmRImmediate, (XtPointer) INVALID_PIXEL
    },

    {
        XmNhighlightPixmap, XmCHighlightPixmap, XmRNoScalingDynamicPixmap,
        sizeof(Pixmap),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.highlight_pixmap),
        XmRImmediate, (XtPointer) INVALID_PIXMAP
    }
};

/*  Definition for resources that need special processing in get values  */

static XmSyntheticResource syn_resources[] =
{
    {
        XmNlabelString,
        sizeof(XmString), XtOffsetOf(XmLabelGadgetRec, label._label),
        GetLabelString, NULL
    },

    {
        XmNaccelerator,
        sizeof(String), XtOffsetOf(XmLabelGadgetRec, label.accelerator),
        GetAccelerator, NULL
    },

    {
        XmNacceleratorText,
        sizeof(XmString), XtOffsetOf(XmLabelGadgetRec, label._acc_text),
        GetAcceleratorText, NULL
    },

    {
        XmNmnemonicCharSet,
        sizeof(XmStringCharSet), XtOffsetOf(XmLabelGadgetRec,label.mnemonicCharset),
        GetMnemonicCharset, NULL
    },
    
    {
        XmNpixmapTextPadding,
	sizeof(Dimension), XtOffsetOf(XmLabelGadgetRec, label.pixmap_text_padding),
        FromPaddingPixels, (XmImportProc) ToPaddingPixels
    }
};

static XmSyntheticResource cache_syn_resources[] =
{
    {
        XmNmarginWidth,
        sizeof(Dimension),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.margin_width),
        XmeFromHorizontalPixels, XmeToHorizontalPixels
    },

    {
        XmNmarginHeight,
        sizeof(Dimension),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.margin_height),
        XmeFromVerticalPixels, XmeToVerticalPixels
    },

    {
        XmNmarginLeft,
        sizeof(Dimension),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.margin_left),
        XmeFromHorizontalPixels, XmeToHorizontalPixels
    },

    {
        XmNmarginRight,
        sizeof(Dimension),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.margin_right),
        XmeFromHorizontalPixels, XmeToHorizontalPixels
    },

    {
        XmNmarginTop,
        sizeof(Dimension),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.margin_top),
        XmeFromVerticalPixels, XmeToVerticalPixels
    },

    {
        XmNmarginBottom,
        sizeof(Dimension),
        XtOffsetOf(XmLabelGCacheObjRec, label_cache.margin_bottom),
        XmeFromVerticalPixels, XmeToVerticalPixels
    }
};

static XmCacheClassPart LabelClassCachePart =
{
    {                                             /* head of class cache list */
        NULL, 0, 0
    },
    _XmCacheCopy,                                 /* Copy routine		*/
    _XmCacheDelete,                               /* Delete routine	*/
    _XmLabelCacheCompare                          /* Comparison routine 	*/
};

static XmBaseClassExtRec labelBaseClassExtRec =
{
    NULL,                                         /* Next extension         */
    NULLQUARK,                                    /* record type XmQmotif   */
    XmBaseClassExtVersion,                        /* version                */
    sizeof(XmBaseClassExtRec),                    /* size                   */
    XmInheritInitializePrehook,                   /* initialize prehook     */
    SetValuesPrehook,                             /* set_values prehook     */
    InitializePosthook,                           /* initialize posthook    */
    SetValuesPosthook,                            /* set_values posthook    */
    (WidgetClass)&xmLabelGCacheObjClassRec,       /* secondary class        */
    SecondaryObjectCreate,                        /* creation proc          */
    GetLabelBGClassSecResData,                    /* getSecResData          */
    {                                             /* fast subclass          */
        0
    },
    GetValuesPrehook,                             /* get_values prehook     */
    GetValuesPosthook,                            /* get_values posthook    */
    NULL,                                         /* classPartInitPrehook   */
    NULL,                                         /* classPartInitPosthook  */
    NULL,                                         /* ext_resources          */
    NULL,                                         /* compiled_ext_resources */
    0,                                            /* num_ext_resources      */
    FALSE,                                        /* use_sub_resources      */
    XmInheritWidgetNavigable,                     /* widgetNavigable        */
    XmInheritFocusChange                          /* focusChange            */
};

externaldef (xmlabelgcacheobjclassrec)
XmLabelGCacheObjClassRec xmLabelGCacheObjClassRec =
{
    {
        (WidgetClass) &xmExtClassRec,             /* superclass          */
        "XmLabelGadget",                          /* class_name          */
        sizeof(XmLabelGCacheObjRec),              /* widget_size         */
        NULL,                                     /* class_initialize    */
        NULL,                                     /* chained class init  */
        False,                                    /* class_inited        */
        NULL,                                     /* initialize          */
        NULL,                                     /* initialize hook     */
        NULL,                                     /* realize             */
        NULL,                                     /* actions             */
        0,                                        /* num_actions         */
        cache_resources,                          /* resources           */
        XtNumber(cache_resources),                /* num_resources       */
        NULLQUARK,                                /* xrm_class           */
        False,                                    /* compress_motion     */
        False,                                    /* compress_exposure   */
        False,                                    /* compress enter/exit */
        False,                                    /* visible_interest    */
        NULL,                                     /* destroy             */
        NULL,                                     /* resize              */
        NULL,                                     /* expose              */
        NULL,                                     /* set_values          */
        NULL,                                     /* set values hook     */
        NULL,                                     /* set values almost   */
        NULL,                                     /* get values hook     */
        NULL,                                     /* accept_focus        */
        XtVersion,                                /* version             */
        NULL,                                     /* callback offsetlst  */
        NULL,                                     /* default trans       */
        NULL,                                     /* query geo proc      */
        NULL,                                     /* display accelerator */
        NULL                                      /* extension record    */
    },

    {
        cache_syn_resources,                      /* synthetic resources */
        XtNumber(cache_syn_resources),            /* num_syn_resources   */
        NULL                                      /* extension           */
    }
};

/* This is the class record that gets set at compile/link time  */
/* this is what is passed to the widget create routine as the   */
/* the class.  All fields must be inited at compile time.       */

static XmGadgetClassExtRec _XmLabelGadClassExtRec =
{
    NULL,                                         /* next_extension	*/
    NULLQUARK,                                    /* record_type		*/
    XmGadgetClassExtVersion,                      /* version		*/
    sizeof(XmGadgetClassExtRec),                  /* record_size		*/
    XmLabelGadgetGetBaselines,                    /* widget_baseline	*/
    XmLabelGadgetGetDisplayRect,                  /* widget_display_rect	*/
    XmLabelGadgetMarginsProc,                     /* widget_margins */
};

externaldef (xmlabelgadgetclassrec)
XmLabelGadgetClassRec xmLabelGadgetClassRec =
{
    {
        (WidgetClass) &xmGadgetClassRec,          /* superclass	     */
        "XmLabelGadget",                          /* class_name	     */
        sizeof(XmLabelGadgetRec),                 /* widget_size	     */
        ClassInitialize,                          /* class_initialize    */
        ClassPartInitialize,                      /* chained class init  */
        False,                                    /* class_inited	     */
        Initialize,                               /* initialize	     */
        NULL,                                     /* initialize hook     */
        NULL,                                     /* realize	     */
        NULL,                                     /* actions	     */
        0,                                        /* num_actions	     */
        resources,                                /* resources	     */
        XtNumber(resources),                      /* num_resources	     */
        NULLQUARK,                                /* xrm_class	     */
        True,                                     /* compress_motion     */
        XtExposeCompressMaximal,                  /* compress_exposure   */
        True,                                     /* compress enter/exit */
        False,                                    /* visible_interest    */
        Destroy,                                  /* destroy	     */
        Resize,                                   /* resize		     */
        Redisplay,                                /* expose		     */
        SetValues,                                /* set_values	     */
        NULL,                                     /* set values hook     */
        SetValuesAlmost,                          /* set values almost   */
        NULL,                                     /* get values hook     */
        NULL,                                     /* accept_focus	     */
        XtVersion,                                /* version	     */
        NULL,                                     /* callback offsetlst  */
        NULL,                                     /* default trans	     */
        QueryGeometry,                            /* query geo proc	     */
        NULL,                                     /* display accelerator */
        (XtPointer)&labelBaseClassExtRec          /* extension record    */
    },

    {                                             /* XmGadgetClassPart  */
        BorderHighlight,                          /* border_highlight   */
        XmInheritBorderUnhighlight,               /* border_unhighlight */
        NULL,                                     /* arm_and_activate   */
        InputDispatch,                            /* input dispatch     */
        XmInheritVisualChange,                    /* visual_change      */
        syn_resources,                            /* syn resources      */
        XtNumber(syn_resources),                  /* num syn_resources  */
        &LabelClassCachePart,                     /* class cache part   */
        (XtPointer)&_XmLabelGadClassExtRec        /* extension          */
    },

    {                                             /* XmLabelGadgetClassPart   */
        SetOverrideCallback,                      /* override_callback        */
        NULL,                                     /* menu procedure interface */
        NULL                                      /* extension record         */
    }
};

externaldef(xmlabelgadgetclass) WidgetClass xmLabelGadgetClass =
(WidgetClass) &xmLabelGadgetClassRec;

/*ARGSUSED*/
static Pixmap
GetTopShadowPixmapDefault(Widget widget)
{
    XmLabelGadget lg = (XmLabelGadget) widget;
    XmManagerWidget mw = (XmManagerWidget)XtParent(lg);
    Pixmap result = XmUNSPECIFIED_PIXMAP;

    if (LabG_TopShadowColor(lg) == LabG_Background(lg))
        result = XmGetPixmapByDepth (XtScreen (lg), XmS50_foreground,
            LabG_TopShadowColor(lg),
            LabG_Foreground(lg),
            mw->core.depth);

    else if (DefaultDepthOfScreen (XtScreen (widget)) == 1)
        result = XmGetPixmapByDepth (XtScreen (lg), XmS50_foreground,
                LabG_TopShadowColor(lg),
                LabG_Background(lg),
                mw->core.depth);

    return result;
}


/*ARGSUSED*/
static Pixmap
GetLabelHighlightPixmapDefault(Widget widget)
{
    XmLabelGadget lg = (XmLabelGadget) widget;
    XmManagerWidget mw = (XmManagerWidget)XtParent(lg);
    Pixmap result = XmUNSPECIFIED_PIXMAP;

    if (LabG_HighlightColor(lg) == LabG_Background(lg))
        result = XmGetPixmapByDepth (XtScreen (lg), XmS50_foreground,
            LabG_HighlightColor(lg),
            LabG_Foreground(lg),
            mw->core.depth);

    return result;
}


/*******************************************************************
 *
 *  _XmLabelCacheCompare
 *
 *******************************************************************/

int
_XmLabelCacheCompare(
XtPointer A,
XtPointer B)
{
    XmLabelGCacheObjPart *label_inst = (XmLabelGCacheObjPart *) A;
    XmLabelGCacheObjPart *label_cache_inst = (XmLabelGCacheObjPart *) B;

    if ((label_inst->label_type == label_cache_inst->label_type) &&
        (label_inst->alignment == label_cache_inst->alignment) &&
        (label_inst->string_direction == label_cache_inst->string_direction) &&
        (label_inst->margin_height == label_cache_inst->margin_height) &&
        (label_inst->margin_width == label_cache_inst->margin_width) &&
        (label_inst->margin_left == label_cache_inst->margin_left) &&
        (label_inst->margin_right == label_cache_inst->margin_right) &&
        (label_inst->margin_top == label_cache_inst->margin_top) &&
        (label_inst->margin_bottom == label_cache_inst->margin_bottom) &&
        (label_inst->recompute_size == label_cache_inst->recompute_size) &&
        (label_inst->skipCallback == label_cache_inst->skipCallback) &&
        (label_inst->menu_type == label_cache_inst->menu_type) &&
        (label_inst->background_GC == label_cache_inst->background_GC) &&
        (label_inst->top_shadow_GC == label_cache_inst->top_shadow_GC) &&
        (label_inst->bottom_shadow_GC == label_cache_inst->bottom_shadow_GC) &&
        (label_inst->highlight_GC == label_cache_inst->highlight_GC) &&
        (label_inst->foreground == label_cache_inst->foreground) &&
        (label_inst->background == label_cache_inst->background) &&
        (label_inst->top_shadow_color == label_cache_inst->top_shadow_color) &&
        (label_inst->top_shadow_pixmap == label_cache_inst->top_shadow_pixmap) &&
        (label_inst->bottom_shadow_color ==
        label_cache_inst->bottom_shadow_color) &&
        (label_inst->bottom_shadow_pixmap ==
        label_cache_inst->bottom_shadow_pixmap) &&
        (label_inst->highlight_color == label_cache_inst->highlight_color) &&
        (label_inst->highlight_pixmap == label_cache_inst->highlight_pixmap))
        return 1;
    else
        return 0;
}


/***********************************************************
 *
 *  ClassInitialize
 *
 ************************************************************/

static void
ClassInitialize(void)
{
    labelBaseClassExtRec.record_type = XmQmotif;

    /* Install menu savvy on just this class */
    XmeTraitSet((XtPointer) &xmLabelGadgetClassRec,
        XmQTmenuSavvy, (XtPointer) &MenuSavvyGadgetRecord);

}


void
_XmLabelGCloneMenuSavvy(WidgetClass wc,
XmMenuSavvyTrait mst)
{
    /* Modify and reinstall menu savvy trait */
    if (mst->version == -1)
    {
        mst->version = MenuSavvyGadgetRecord.version;
        mst->disableCallback = MenuSavvyGadgetRecord.disableCallback;
        mst->getAccelerator = MenuSavvyGadgetRecord.getAccelerator;
        mst->getMnemonic = MenuSavvyGadgetRecord.getMnemonic;
    }

    /* Install the new record */
    XmeTraitSet((XtPointer) wc, XmQTmenuSavvy, (XtPointer) mst);
}


/************************************************************************
 *
 *  ClassPartInitialize
 *	Processes the class fields which need to be inherited.
 *
 ************************************************************************/

static void
ClassPartInitialize(WidgetClass cl)
{
    register XmLabelGadgetClass wc = (XmLabelGadgetClass) cl;
    XmLabelGadgetClass super = (XmLabelGadgetClass)wc->rect_class.superclass;
    XmGadgetClassExt *wcePtr, *scePtr;

    if (wc->label_class.setOverrideCallback == XmInheritSetOverrideCallback)
        wc->label_class.setOverrideCallback =
            super->label_class.setOverrideCallback;

    if (wc->rect_class.resize == XmInheritResize)
        wc->rect_class.resize = super->rect_class.resize;

    wcePtr = _XmGetGadgetClassExtPtr(wc, NULLQUARK);
    scePtr = _XmGetGadgetClassExtPtr(super, NULLQUARK);

    if ((*wcePtr)->widget_baseline == XmInheritBaselineProc)
        (*wcePtr)->widget_baseline = (*scePtr)->widget_baseline;

    if ((*wcePtr)->widget_display_rect == XmInheritDisplayRectProc)
        (*wcePtr)->widget_display_rect  = (*scePtr)->widget_display_rect;

    _XmFastSubclassInit (((WidgetClass)wc), XmLABEL_GADGET_BIT);

    /* Install transfer trait */
    XmeTraitSet((XtPointer)cl, XmQTtransfer, (XtPointer) &LabelGTransfer);
    XmeTraitSet((XtPointer) cl, XmQTaccessTextual, (XtPointer)
        &_XmLabel_AccessTextualRecord);

    /* Install the careParentVisual trait for all subclasses as well. */
    XmeTraitSet((XtPointer)cl, XmQTcareParentVisual, (XtPointer)&LabelGCVT);

    /* Install the accessColors trait for all subclasses as well. */
    XmeTraitSet((XtPointer)cl, XmQTaccessColors, (XtPointer)&labACT);
}


/************************************************************************
 *
 *  SecondaryObjectCreate
 *
 ************************************************************************/

/*ARGSUSED*/
static void
SecondaryObjectCreate(Widget req,
Widget new_w,
ArgList args,
Cardinal *num_args)
{
    XmBaseClassExt *cePtr;
    XmWidgetExtData extData;
    WidgetClass   wc;
    Cardinal  size;
    XtPointer newSec, reqSec;

    _XmProcessLock();
    cePtr = _XmGetBaseClassExtPtr(XtClass(new_w), XmQmotif);

    wc = (*cePtr)->secondaryObjectClass;
    size = wc->core_class.widget_size;

    newSec = _XmExtObjAlloc(size);
    reqSec = _XmExtObjAlloc(size);
    _XmProcessUnlock();

    /*
     * Update pointers in instance records now so references to resources
     * in the cache record will be valid for use in CallProcs.
     * CallProcs are invoked by XtGetSubresources().
     */
    LabG_Cache(new_w) = &(((XmLabelGCacheObject)newSec)->label_cache);
    LabG_Cache(req) = &(((XmLabelGCacheObject)reqSec)->label_cache);

    /*
     * Fetch the resources in superclass to subclass order
     */

    XtGetSubresources(new_w, newSec, NULL, NULL,
        wc->core_class.resources,
        wc->core_class.num_resources,
        args, *num_args);

    extData = (XmWidgetExtData) XtCalloc(1, sizeof(XmWidgetExtDataRec));
    extData->widget = (Widget)newSec;
    extData->reqWidget = (Widget)reqSec;

    ((XmLabelGCacheObject)newSec)->ext.extensionType = XmCACHE_EXTENSION;
    ((XmLabelGCacheObject)newSec)->ext.logicalParent = new_w;

    _XmPushWidgetExtData((Widget) new_w, extData,
        ((XmLabelGCacheObject)newSec)->ext.extensionType);
    memcpy(reqSec, newSec, size);
}


/************************************************************************
 *
 *  InitializePosthook
 *
 ************************************************************************/

/*ARGSUSED*/
static void
InitializePosthook(Widget req,
Widget new_w,
ArgList args,
Cardinal *num_args)
{
    XmWidgetExtData     ext;
    XmLabelGadget lw = (XmLabelGadget)new_w;

    /*
     * - register parts in cache.
     * - update cache pointers
     * - and free req
     */

    _XmProcessLock();
    LabG_Cache(lw) = (XmLabelGCacheObjPart *)
        _XmCachePart(LabG_ClassCachePart(lw),
        (XtPointer) LabG_Cache(lw),
        sizeof(XmLabelGCacheObjPart));

    /*
     * Might want to break up into per-class work that gets explicitly
     * chained.  For right now, each class has to replicate all
     * superclass logic in hook routine.
     */

    /*
     * free the req subobject used for comparisons
     */
    _XmPopWidgetExtData((Widget) lw, &ext, XmCACHE_EXTENSION);
    _XmExtObjFree((XtPointer)ext->widget);
    _XmExtObjFree((XtPointer)ext->reqWidget);
    _XmProcessUnlock();
    XtFree((char *) ext);
}


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

/*ARGSUSED*/
static Boolean
SetValuesPrehook(Widget oldParent,
Widget refParent,
Widget newParent,
ArgList args,
Cardinal *num_args)
{
    XmWidgetExtData     extData;
    XmBaseClassExt      *cePtr;
    WidgetClass         ec;
    XmLabelGCacheObject newSec, reqSec;
    Cardinal        size;

    _XmProcessLock();
    cePtr = _XmGetBaseClassExtPtr(XtClass(newParent), XmQmotif);
    ec = (*cePtr)->secondaryObjectClass;
    size = ec->core_class.widget_size;

    newSec = (XmLabelGCacheObject)_XmExtObjAlloc(size);
    reqSec = (XmLabelGCacheObject)_XmExtObjAlloc(size);
    _XmProcessUnlock();

    newSec->object.self = (Widget)newSec;
    newSec->object.widget_class = ec;
    newSec->object.parent = XtParent(newParent);
    newSec->object.xrm_name = newParent->core.xrm_name;
    newSec->object.being_destroyed = False;
    newSec->object.destroy_callbacks = NULL;
    newSec->object.constraints = NULL;

    newSec->ext.logicalParent = newParent;
    newSec->ext.extensionType = XmCACHE_EXTENSION;

    memcpy(&(newSec->label_cache),
        LabG_Cache(newParent),
        sizeof(XmLabelGCacheObjPart));

    extData = (XmWidgetExtData) XtCalloc(1, sizeof(XmWidgetExtDataRec));
    extData->widget = (Widget)newSec;
    extData->reqWidget = (Widget)reqSec;
    _XmPushWidgetExtData(newParent, extData, XmCACHE_EXTENSION);

    XtSetSubvalues((XtPointer)newSec,
        ec->core_class.resources,
        ec->core_class.num_resources,
        args, *num_args);

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

    memcpy((XtPointer)reqSec, (XtPointer)newSec, size);

    LabG_Cache(newParent) = &((newSec)->label_cache);
    LabG_Cache(refParent) = &((reqSec)->label_cache);

    return FALSE;
}


/************************************************************************
 *
 *  GetValuesPrehook
 *
 ************************************************************************/

/*ARGSUSED*/
static void
GetValuesPrehook(Widget newParent,
ArgList args,
Cardinal *num_args)
{
    XmWidgetExtData     extData;
    XmBaseClassExt      *cePtr;
    WidgetClass         ec;
    XmLabelGCacheObject newSec;
    Cardinal            size;

    _XmProcessLock();
    cePtr = _XmGetBaseClassExtPtr(XtClass(newParent), XmQmotif);
    ec = (*cePtr)->secondaryObjectClass;
    size = ec->core_class.widget_size;

    newSec = (XmLabelGCacheObject)_XmExtObjAlloc(size);
    _XmProcessUnlock();

    newSec->object.self = (Widget)newSec;
    newSec->object.widget_class = ec;
    newSec->object.parent = XtParent(newParent);
    newSec->object.xrm_name = newParent->core.xrm_name;
    newSec->object.being_destroyed = False;
    newSec->object.destroy_callbacks = NULL;
    newSec->object.constraints = NULL;

    newSec->ext.logicalParent = newParent;
    newSec->ext.extensionType = XmCACHE_EXTENSION;

    memcpy(&(newSec->label_cache),
        LabG_Cache(newParent),
        sizeof(XmLabelGCacheObjPart));

    extData = (XmWidgetExtData) XtCalloc(1, sizeof(XmWidgetExtDataRec));
    extData->widget = (Widget)newSec;
    _XmPushWidgetExtData(newParent, extData, XmCACHE_EXTENSION);

    XtGetSubvalues((XtPointer)newSec,
        ec->core_class.resources,
        ec->core_class.num_resources,
        args, *num_args);

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


/************************************************************************
 *
 *  GetValuesPosthook
 *
 ************************************************************************/

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

    _XmPopWidgetExtData(new_w, &ext, XmCACHE_EXTENSION);

    _XmProcessLock();
    _XmExtObjFree((XtPointer)ext->widget);
    _XmProcessUnlock();

    XtFree((char *) ext);
}


/************************************************************************
 *
 *  SetValuesPosthook
 *
 ************************************************************************/

/*ARGSUSED*/
static Boolean
SetValuesPosthook(Widget current,
Widget req,
Widget new_w,
ArgList args,
Cardinal *num_args)
{
    XmWidgetExtData ext;

    /*
     * - register parts in cache.
     * - update cache pointers
     * - and free req
     */

    /* assign if changed! */
    _XmProcessLock();
    if (!_XmLabelCacheCompare((XtPointer)LabG_Cache(new_w),
        (XtPointer)LabG_Cache(current)))

    {
        /* delete the old one */
        _XmCacheDelete((XtPointer) LabG_Cache(current));
        LabG_Cache(new_w) = (XmLabelGCacheObjPart *)
            _XmCachePart(LabG_ClassCachePart(new_w),
            (XtPointer) LabG_Cache(new_w),
            sizeof(XmLabelGCacheObjPart));
    }
    else
        LabG_Cache(new_w) = LabG_Cache(current);

    _XmPopWidgetExtData(new_w, &ext, XmCACHE_EXTENSION);

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

    XtFree((char *) ext);
    _XmProcessUnlock();

    return FALSE;
}


static void
BorderHighlight(Widget w)
{
    XmLabelGadget lg = (XmLabelGadget) w;

    if (lg->rectangle.width == 0 ||
        lg->rectangle.height == 0 ||
        lg->gadget.highlight_thickness == 0)
    {
        return;
    }

    lg->gadget.highlighted = True;
    lg->gadget.highlight_drawn = True;

    /* CR 7330: Use XmeDrawHighlight, not _XmDrawHighlight. */
    XmeDrawHighlight(XtDisplay((Widget) lg), XtWindow((Widget) lg),
        LabG_HighlightGC(lg),
        lg->rectangle.x, lg->rectangle.y,
        lg->rectangle.width, lg->rectangle.height,
        lg->gadget.highlight_thickness);
}


/************************************************************************
 *
 *  SetNormalGC
 *	Create the normal and insensitive GC's for the gadget.
 *
 ************************************************************************/

static void
SetNormalGC(XmLabelGadget lw)
{
    XGCValues       values;
    XtGCMask        valueMask, dynamicMask;
    XmManagerWidget mw;
    XFontStruct     *fs = (XFontStruct *) NULL;

    mw = (XmManagerWidget) XtParent(lw);

    valueMask = GCForeground | GCBackground | GCGraphicsExposures;
    dynamicMask = GCClipXOrigin | GCClipYOrigin | GCClipMask;

    values.foreground = LabG_Foreground(lw);
    values.background = LabG_Background(lw);
    values.graphics_exposures = FALSE;

    if (XmeRenderTableGetDefaultFont(LabG_Font(lw), &fs))
    {
        valueMask |= GCFont;
        values.font = fs->fid;
    }

    LabG_NormalGC(lw) = XtAllocateGC((Widget) mw, 0, valueMask, &values,
        dynamicMask, 0);

#ifdef FIX_1381
    /*generally gray insensitive foreground (instead stipple)*/
    values.foreground = _XmAssignInsensitiveColor((Widget)lw);
    values.background = LabG_Background(lw);
#else
    valueMask |= GCFillStyle | GCStipple;
    values.foreground = LabG_Background(lw); 
    values.background = LabG_Foreground(lw);
    values.fill_style = FillOpaqueStippled;
    values.stipple = _XmGetInsensitiveStippleBitmap((Widget) lw);
#endif

    LabG_InsensitiveGC(lw) = XtAllocateGC((Widget) mw, 0, valueMask, &values,
        dynamicMask, 0);
#ifdef FIX_1381
    /*light shadow for insensitive text (instead stipple)*/
    values.foreground = LabG_TopShadowColor(lw);
    LabG_ShadowGC(lw)  = XtAllocateGC((Widget) mw, 0, valueMask, &values,
	dynamicMask, 0);
#endif

}


/************************************************************************
 *
 *  _XmLabelSetBackgroundGC
 *     Get the graphics context used for drawing the shadows.
 *
 ************************************************************************/

void
_XmLabelSetBackgroundGC(XmLabelGadget lw)
{
    XGCValues   values;
    XtGCMask    valueMask;
    XmManagerWidget mw;
    XFontStruct     *fs = (XFontStruct *) NULL;

    mw = (XmManagerWidget) XtParent(lw);

    if (lw->label.fill_bg_box != _XmALWAYS_FILL_BG_BOX)
    {
        if ((mw->core.background_pixel != LabG_Background(lw)) &&
            (mw->core.background_pixmap == XmUNSPECIFIED_PIXMAP))
            lw->label.fill_bg_box = _XmFILL_BG_BOX;
        else
            lw->label.fill_bg_box = _XmPLAIN_BG_BOX;
    }

    valueMask = GCForeground | GCBackground | GCGraphicsExposures | GCClipMask;
    values.foreground = LabG_Background(lw);
    values.background = LabG_Foreground(lw);
    values.graphics_exposures = FALSE;
    values.clip_mask = None;

    /* CR 8980: Use parent's background_pixmap if possible. */
    if (mw->core.background_pixmap != XmUNSPECIFIED_PIXMAP)
    {
        int depth;

        XmeGetPixmapData(XtScreen((Widget)lw), mw->core.background_pixmap,
            NULL, &depth, NULL, NULL, NULL, NULL, NULL, NULL);

        if (depth == 1)
        {
            valueMask |= GCFillStyle | GCStipple ;
            values.fill_style = FillOpaqueStippled;
            values.stipple = mw->core.background_pixmap;
        }
        else
        {
            valueMask |= GCFillStyle | GCTile ;
            values.fill_style = FillTiled;
            values.tile = mw->core.background_pixmap;
        }
    }

    if (XmeRenderTableGetDefaultFont(LabG_Font(lw), &fs))
    {
        valueMask |= GCFont;
        values.font = fs->fid;
    }

    LabG_BackgroundGC(lw) = XtGetGC ((Widget) mw, valueMask, &values);
}


/************************************************************************
 *
 * _XmCalcLabelGDimensions()
 *   Calculates the dimensionsof the label text and pixmap, and updates
 *   the TextRect fields appropriately. Called at Initialize and SetValues.
 *   This is also called by the subclasses to recalculate label dimensions.
 *
 *************************************************************************/

void
_XmCalcLabelGDimensions(Widget wid)
{
    XmLabelGadget newlw = (XmLabelGadget) wid;
    unsigned int  w = 0 , h = 0;

    /* initialize TextRect width and height to 0, reset if needed */

    LabG_AccTextRect(newlw).width = 0;
    LabG_AccTextRect(newlw).height = 0;
    LabG_StringRect(newlw).x = 0;
    LabG_StringRect(newlw).y = 0;
    LabG_StringRect(newlw).width = 0;
    LabG_StringRect(newlw).height = 0;
    LabG_PixmapRect(newlw).x = 0;
    LabG_PixmapRect(newlw).y = 0;
    LabG_PixmapRect(newlw).width = 0;
    LabG_PixmapRect(newlw).height = 0;

    if (LabG_IsPixmap(newlw) || LabG_IsPixmapAndText(newlw))
    {
        if (XtIsSensitive(wid))
        {
            if (Pix (newlw) != XmUNSPECIFIED_PIXMAP)
            {
                XmeGetPixmapData(XtScreen(newlw), Pix(newlw),
                    NULL, NULL, NULL, NULL, NULL, NULL,
                    &w, &h);

                LabG_PixmapRect(newlw).width = (unsigned short) w;
                LabG_PixmapRect(newlw).height = (unsigned short) h;
            }
        }
        else
        {
            Pixmap pix_use = Pix_insen (newlw) ;

            if (pix_use == XmUNSPECIFIED_PIXMAP)
                pix_use = Pix(newlw);

            if (pix_use != XmUNSPECIFIED_PIXMAP)
            {
                XmeGetPixmapData(XtScreen(newlw), pix_use,
                    NULL, NULL, NULL, NULL, NULL, NULL,
                    &w, &h);

                LabG_PixmapRect(newlw).width = (unsigned short) w;
                LabG_PixmapRect(newlw).height = (unsigned short) h;
            }
        }
    }
	
    if (LabG_IsText (newlw) || LabG_IsPixmapAndText(newlw))
    {
        Dimension w, h;

        /* If we have a string then size it.  */
        if (!XmStringEmpty (LabG__label(newlw)))
        {
            XmStringExtent (LabG_Font(newlw), LabG__label(newlw), &w, &h);
            LabG_StringRect(newlw).width = (unsigned short)w;
            LabG_StringRect(newlw).height = (unsigned short)h;
        }
    }
    
    _XmLabelGCalcTextRect(wid);
    
    if (LabG__acceleratorText(newlw) != NULL)
    {
        /* If we have a string then size it. */
        Dimension w,h;

        if (!XmStringEmpty (LabG__acceleratorText(newlw)))
        {
            XmStringExtent(LabG_Font(newlw),
                    LabG__acceleratorText(newlw), &w, &h);
            LabG_AccTextRect(newlw).width = (unsigned short)w;
            LabG_AccTextRect(newlw).height = (unsigned short)h;
        }
    }
}

void 
_XmLabelGCalcTextRect(Widget wid)
{
  LabG_TextRect(wid).width = 0;
  LabG_TextRect(wid).height = 0;
  
  if (LabG_IsPixmap(wid))
    {
      LabG_TextRect(wid).width = LabG_PixmapRect(wid).width;
      LabG_TextRect(wid).height = LabG_PixmapRect(wid).height;
    }
  else if (LabG_IsText(wid))
    {
      LabG_TextRect(wid).width = LabG_StringRect(wid).width;
      LabG_TextRect(wid).height = LabG_StringRect(wid).height;
    }
  else if (LabG_IsPixmapAndText(wid))
    {
      if (LabG_PixmapPlacement(wid) == XmPIXMAP_TOP ||
          LabG_PixmapPlacement(wid) == XmPIXMAP_BOTTOM)
	{
          LabG_TextRect(wid).height = LabG_PixmapRect(wid).height +
          	LabG_StringRect(wid).height + LabG_PixmapTextPadding(wid);
          LabG_TextRect(wid).width =
          	MAX(LabG_StringRect(wid).width, LabG_PixmapRect(wid).width);
	}
      else if (LabG_PixmapPlacement(wid) == XmPIXMAP_LEFT ||
	       LabG_PixmapPlacement(wid) == XmPIXMAP_RIGHT)
        {
          LabG_TextRect(wid).width = LabG_PixmapRect(wid).width +
          	LabG_StringRect(wid).width + LabG_PixmapTextPadding(wid);
          LabG_TextRect(wid).height =
          	MAX(LabG_StringRect(wid).height, LabG_PixmapRect(wid).height);
        }
	  
      if (LabG_PixmapPlacement(wid) == XmPIXMAP_TOP)
        {
	  LabG_PixmapRect(wid).y = 0;
	  LabG_StringRect(wid).y =
          	LabG_PixmapRect(wid).height + LabG_PixmapTextPadding(wid);
        }
      else if (LabG_PixmapPlacement(wid) == XmPIXMAP_BOTTOM)
        {
          LabG_StringRect(wid).y = 0;
          LabG_PixmapRect(wid).y =
          	LabG_StringRect(wid).height + LabG_PixmapTextPadding(wid);
        }
      else if ((LabG_PixmapPlacement(wid) == XmPIXMAP_RIGHT &&
	        LayoutIsRtoLG(wid)) ||
               (LabG_PixmapPlacement(wid) == XmPIXMAP_LEFT &&
                !LayoutIsRtoLG(wid)))
	{
          LabG_PixmapRect(wid).x = 0;
          LabG_StringRect(wid).x =
          	LabG_PixmapRect(wid).width + LabG_PixmapTextPadding(wid);
	}
      else if ((LabG_PixmapPlacement(wid) == XmPIXMAP_LEFT &&
                LayoutIsRtoLG(wid)) ||
               (LabG_PixmapPlacement(wid) == XmPIXMAP_RIGHT &&
                !LayoutIsRtoLG(wid)))
	{
	   LabG_StringRect(wid).x = 0;
	   LabG_PixmapRect(wid).x =
           	LabG_StringRect(wid).width + LabG_PixmapTextPadding(wid);
	}
	    
      if (LabG_PixmapPlacement(wid) == XmPIXMAP_RIGHT ||
	  LabG_PixmapPlacement(wid) == XmPIXMAP_LEFT)
        {
          LabG_PixmapRect(wid).y =
          	(LabG_TextRect(wid).height - LabG_PixmapRect(wid).height) / 2;
          LabG_StringRect(wid).y =
          	(LabG_TextRect(wid).height - LabG_StringRect(wid).height) / 2;
        }
      else
        {
          if (LabG_Alignment(wid) == XmALIGNMENT_CENTER)
            {
              LabG_PixmapRect(wid).x =
	        (LabG_TextRect(wid).width - LabG_PixmapRect(wid).width) / 2;
              LabG_StringRect(wid).x =
              	(LabG_TextRect(wid).width - LabG_StringRect(wid).width) / 2;
            }
          else if ((LabG_Alignment(wid) == XmALIGNMENT_END &&
                     !LayoutIsRtoLG(wid)) ||
                    (LabG_Alignment(wid) == XmALIGNMENT_BEGINNING &&
                     LayoutIsRtoLG(wid)))
            {
              LabG_PixmapRect(wid).x =
              	LabG_TextRect(wid).width - LabG_PixmapRect(wid).width;
              LabG_StringRect(wid).x =
              	LabG_TextRect(wid).width - LabG_StringRect(wid).width;
            }
        }
    }
}


/************************************************************************
 *
 *  Resize
 *	Sets new width, new height, and new label.TextRect
 *	appropriately. It is called by Initialize and SetValues.
 *
 ************************************************************************/

static void
Resize(Widget wid)
{
    XmLabelGadget newlw = (XmLabelGadget) wid;
    int leftx, rightx;

    /* increase margin width if necessary to accomodate accelerator text */
    if (LabG__acceleratorText(newlw) != NULL)
    {
        if (LayoutIsRtoLG(newlw))
        {
            if (LabG_MarginLeft(newlw) <
                LabG_AccTextRect(newlw).width + LABELG_ACC_PAD)
            {
                int delta = LabG_AccTextRect(newlw).width + LABELG_ACC_PAD -
                    LabG_MarginLeft(newlw);
                newlw->label.acc_left_delta += delta;
                LabG_MarginLeft(newlw) += delta;
            }
        }
        else
        {
            if (LabG_MarginRight(newlw) <
                LabG_AccTextRect(newlw).width + LABELG_ACC_PAD)
            {
                int delta = LabG_AccTextRect(newlw).width + LABELG_ACC_PAD -
                    LabG_MarginRight(newlw);
                newlw->label.acc_right_delta += delta;
                LabG_MarginRight(newlw) += delta;
            }
        }
    }
    /* Has a width been specified?  */
    if (newlw->rectangle.width == 0)
        newlw->rectangle.width =
            LabG_TextRect(newlw).width +
            LabG_MarginLeft(newlw) + LabG_MarginRight(newlw) +
            (2 * (LabG_MarginWidth(newlw) +
            newlw->gadget.highlight_thickness
            + newlw->gadget.shadow_thickness));

    leftx = newlw->gadget.highlight_thickness +
        newlw->gadget.shadow_thickness + LabG_MarginWidth(newlw) +
        LabG_MarginLeft(newlw);

    rightx = newlw->rectangle.width - newlw->gadget.highlight_thickness -
        newlw->gadget.shadow_thickness - LabG_MarginWidth(newlw) -
        LabG_MarginRight(newlw);

    switch (LabG_Alignment(newlw))
    {
        case XmALIGNMENT_BEGINNING:
            if (LayoutIsRtoLG(newlw))
                LabG_TextRect(newlw).x = rightx - LabG_TextRect(newlw).width;
            else
                LabG_TextRect(newlw).x = leftx;
            break;

        case XmALIGNMENT_END:
            if (LayoutIsRtoLG(newlw))
                LabG_TextRect(newlw).x = leftx;
            else
                LabG_TextRect(newlw).x = rightx - LabG_TextRect(newlw).width;
            break;

        default:
            /* XmALIGNMENT_CENTER */
            LabG_TextRect(newlw).x = leftx +
                (rightx - leftx - (int)LabG_TextRect(newlw).width) / 2;
            break;
    }

    /*  Has a height been specified?  */
    if (newlw->rectangle.height == 0)
        newlw->rectangle.height = MAX(LabG_TextRect(newlw).height,
            LabG_AccTextRect(newlw).height)
            + LabG_MarginTop(newlw)
            + LabG_MarginBottom(newlw)
            + (2 * (LabG_MarginHeight(newlw)
            + newlw->gadget.highlight_thickness
            + newlw->gadget.shadow_thickness));

    LabG_TextRect(newlw).y =
        (short) (newlw->gadget.highlight_thickness
        + newlw->gadget.shadow_thickness
        + LabG_MarginHeight(newlw) + LabG_MarginTop(newlw) +
        ((int) (newlw->rectangle.height - LabG_MarginTop(newlw)
        - LabG_MarginBottom(newlw)
        - (2 * (LabG_MarginHeight(newlw)
        + newlw->gadget.highlight_thickness
        + newlw->gadget.shadow_thickness))
        - LabG_TextRect(newlw).height) / 2));

    if (LabG__acceleratorText(newlw) != NULL)
    {
        Dimension  base_label, base_accText, diff;

        if (LayoutIsRtoLG(newlw))
            LabG_AccTextRect(newlw).x =  newlw->rectangle .x +
                (newlw->gadget.highlight_thickness +
                newlw->gadget.shadow_thickness +
                LabG_MarginWidth(newlw));
        else
            LabG_AccTextRect(newlw).x = (newlw->rectangle.width -
                newlw->gadget.highlight_thickness -
                newlw->gadget.shadow_thickness -
                LabG_MarginWidth(newlw) -
                LabG_MarginRight(newlw) +
                LABELG_ACC_PAD);

        LabG_AccTextRect(newlw).y = newlw->gadget.highlight_thickness
            + newlw->gadget.shadow_thickness
            + LabG_MarginHeight(newlw) + LabG_MarginTop(newlw) +
            ((int) (newlw->rectangle.height - LabG_MarginTop(newlw)
            - LabG_MarginBottom(newlw)
            - (2 * (LabG_MarginHeight(newlw)
            + newlw->gadget.highlight_thickness
            + newlw->gadget.shadow_thickness))
            - LabG_AccTextRect(newlw).height) / 2);

        /* make sure the label and accelerator text line up */
        /* when the fonts are different */

        if (LabG_IsText (newlw))
        {
            base_label =
                XmStringBaseline (LabG_Font(newlw), LabG__label(newlw));
            base_accText =
                XmStringBaseline (LabG_Font(newlw),
                LabG__acceleratorText(newlw));

            if (base_label > base_accText)
            {
                diff = base_label - base_accText;
                LabG_AccTextRect(newlw).y = LabG_TextRect(newlw).y + diff - 1;
            }
            else if (base_label < base_accText)
            {
                diff = base_accText - base_label;
                LabG_TextRect(newlw).y = LabG_AccTextRect(newlw).y + diff - 1;
            }
        }
    }

    /* Set core dimensions so we don't get a Toolkit error. */
    if (newlw->rectangle.width == 0)
        newlw->rectangle.width = 1;
    if (newlw->rectangle.height == 0)
        newlw->rectangle.height = 1;
}


/************************************************************************
 *
 *  Initialize
 *	This is the widget's instance initialize routine.  It is
 *	called once for each widget.
 *  Changes: Treat label, pixmap, labeltype, mnemoniccharset as independently
 *	setable resource.
 ************************************************************************/

/*ARGSUSED*/
static void
Initialize(Widget req,
Widget new_w,
ArgList args,
Cardinal *num_args)
{
    XmMenuSystemTrait menuSTrait;

    XmLabelGadget lw = (XmLabelGadget) new_w;
    XmLabelGadget rw = (XmLabelGadget) req;

    lw->label.baselines = NULL;

    /* Before doing anything with the pixmap, check if we have to
     * re-ask for a conversion */
    if (Pix  (new_w) == XmDELAYED_PIXMAP)
    {
        /* This test means that a conversion was asked for
         * but failed because the colors were not accessible
         * prior to Initialize, because the cache wasn't there yet.
         * We have to try again from here. */

        XtGetSubresources(new_w, new_w,
            NULL, NULL,
            label_pixmap_resource, 1,
            args, *num_args);
    }

    if (Pix_insen (new_w) == XmDELAYED_PIXMAP)
    {
        XtGetSubresources(new_w, new_w,
            NULL, NULL,
            label_pixmap_insen_resource, 1,
            args, *num_args);
    }

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

    LabG_SkipCallback(new_w) = FALSE;

    /* Check for Invalid enumerated types */

    if (!XmRepTypeValidValue(XmRID_LABEL_TYPE, LabG_LabelType(new_w), new_w))
        LabG_LabelType(new_w) = XmSTRING;

    if (!XmRepTypeValidValue(XmRID_ALIGNMENT, LabG_Alignment(new_w), new_w))
        LabG_Alignment(new_w) = XmALIGNMENT_CENTER;

    if (!XmRepTypeValidValue(XmRID_PIXMAP_PLACEMENT, LabG_PixmapPlacement(new_w), new_w))
        LabG_PixmapPlacement(new_w) = XmPIXMAP_LEFT;
	
    #ifndef NO_XM_1_2_BC
    /*
     * Some pre-Motif 2.0 XmManager subclasses may be bypassing the
     * synthetic resouce GetValues hook and passing us the manager's raw
     * string_direction field (which is now a layout_direction).  Fixup
     * the common/simple cases.
     */
    switch (LabG_StringDirection(lw))
    {
        case XmLEFT_TO_RIGHT:
        case XmRIGHT_TO_LEFT:
            /* These string directions are erroneous uses of layout directions. */
            LabG_StringDirection(lw) =
                XmDirectionToStringDirection(LabG_StringDirection(lw));
            break;
        default:
            /* Other unknown layout directions will still get a warning. */
            break;
    }
    #endif

    /* If layout_direction is set, it overrides string_direction.
     * If string_direction is set, but not layout_direction, use
     *	string_direction value.
     * If neither is set, get from parent.
     */
    if (lw->gadget.layout_direction != XmDEFAULT_DIRECTION)
    {
        if (LabG_StringDirection(lw) == XmDEFAULT_DIRECTION)
            LabG_StringDirection(lw) =
                XmDirectionToStringDirection(lw->gadget.layout_direction);
    }
    else if (LabG_StringDirection(lw) != XmDEFAULT_DIRECTION)
    {
        lw->gadget.layout_direction =
            XmStringDirectionToDirection(LabG_StringDirection(lw));
    }
    else
    {
        lw->gadget.layout_direction = _XmGetLayoutDirection(XtParent(new_w));
        LabG_StringDirection(lw) =
            XmDirectionToStringDirection(lw->gadget.layout_direction);
    }

    if (!XmRepTypeValidValue(XmRID_STRING_DIRECTION,
        LabG_StringDirection(new_w), new_w))
        LabG_StringDirection(new_w) = XmSTRING_DIRECTION_L_TO_R;

    /* Make a local copy of the font list */
    if (LabG_Font(new_w) == NULL)
    {
        /* CR 2990:  Let subclasses choose their own default font. */
        LabG_Font(new_w) = XmeGetDefaultRenderTable (new_w, XmLABEL_FONTLIST);
    }
    LabG_Font(new_w) = XmFontListCopy(LabG_Font(new_w));

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

    if (menuSTrait != (XmMenuSystemTrait) NULL)
        LabG_MenuType(new_w) = menuSTrait->type(XtParent(new_w));
    else
        LabG_MenuType(new_w) = XmWORK_AREA;

    /*  Handle the label string :
     *   If no label string is given accept widget's name as default.
     *     convert the widgets name to an XmString before storing;
     *   else
     *     save a copy of the given string.
     *     If the given string is not an XmString issue an warning.
     */

    if (LabG__label(new_w) == NULL)
    {
                                                  /* reserved */
        LabG__label(new_w) = XmeGetLocalizedString ((char *) NULL,
            (Widget) lw,
            XmNlabelString,
            XrmQuarkToString(lw->object.xrm_name));
    }
    else if (XmeStringIsValid((XmString) LabG__label(new_w)))
    {
        LabG__label(new_w) = XmStringCopy((XmString) LabG__label(new_w));
    }
    else
    {
        XmeWarning((Widget) lw, CS_STRING_MESSAGE);
        LabG__label(new_w) =
            XmStringCreateLocalized(XrmQuarkToString(lw->object.xrm_name));
    }

    /*
     * Convert the given mnemonicCharset to the internal Xm-form.
     */
    if (LabG_MnemonicCharset(new_w) != NULL)
    {
        LabG_MnemonicCharset (new_w) =
            _XmStringCharsetCreate (LabG_MnemonicCharset (new_w));
    }
    else
        LabG_MnemonicCharset (new_w) =
            _XmStringCharsetCreate (XmFONTLIST_DEFAULT_TAG);

    /* Accelerators are currently only supported in menus */
    if ((LabG__acceleratorText(new_w) != NULL) && LabG_IsMenupane(new_w))
    {
        if (XmeStringIsValid((XmString) LabG__acceleratorText(new_w)))
        {
            /* Copy the input string into local space if not a Cascade Button. */
            if (XmIsCascadeButtonGadget(new_w))
                LabG__acceleratorText(new_w) = NULL;
            else
                LabG__acceleratorText(new_w)=
                    XmStringCopy((XmString) LabG__acceleratorText(new_w));
        }
        else
        {
            XmeWarning((Widget) lw, ACC_MESSAGE);
            LabG__acceleratorText(new_w) = NULL;
        }
    }
    else
        LabG__acceleratorText(new_w) = NULL;

    if ((LabG_Accelerator(new_w) != NULL) && LabG_IsMenupane(new_w))
    {
        /* Copy the accelerator into local space */
        LabG_Accelerator(lw) = XtNewString(LabG_Accelerator(new_w));
    }
    else
        LabG_Accelerator(lw) = NULL;

    LabG_SkipCallback(lw) = FALSE;

    lw->label.acc_left_delta = 0;
    lw->label.acc_right_delta = 0;

    /*  If zero width and height was requested by the application,  */
    /*  reset new's width and height to zero to allow Resize()     */
    /*  to operate properly.                                        */

    if (rw->rectangle.width == 0)
        lw->rectangle.width = 0;

    if (rw->rectangle.height == 0)
        lw->rectangle.height = 0;

    /* CR 6267:  Suppress highlight thickness before sizing also. */
    if ((LabG_MenuType(new_w) == XmMENU_POPUP) ||
        (LabG_MenuType(new_w) == XmMENU_PULLDOWN) ||
        (LabG_MenuType(new_w) == XmMENU_BAR))
        lw->gadget.highlight_thickness = 0;

    _XmCalcLabelGDimensions(new_w);

    /* CR 7283: Can't use the resize method pointer here because */
    /* 	subclasses haven't been initialized.		       */
    Resize((Widget) lw);

    DealWithColors(lw);
    DealWithPixmaps(lw);

    /* Initialize only; set properly in _XmLabelSetBackgroundGC(). */
    lw->label.fill_bg_box = _XmPLAIN_BG_BOX;

    SetNormalGC(lw);
    _XmLabelSetBackgroundGC (lw);
    LabG_HighlightGC(lw) =
        _XmGetPixmapBasedGC (XtParent(new_w),
        LabG_HighlightColor(lw),
        LabG_Background(lw),
        LabG_HighlightPixmap(lw));
    LabG_TopShadowGC(lw) =
        _XmGetPixmapBasedGC (XtParent(new_w),
        LabG_TopShadowColor(lw),
        LabG_Background(lw),
        LabG_TopShadowPixmap(lw));
    LabG_BottomShadowGC(lw) =
        _XmGetPixmapBasedGC (XtParent(new_w),
        LabG_BottomShadowColor(lw),
        LabG_Background(lw),
        LabG_BottomShadowPixmap(lw));

    /*  Force the label traversal flag when in a menu  */
    if ((XtClass(lw) == xmLabelGadgetClass) &&
        ((LabG_MenuType(new_w) == XmMENU_POPUP) ||
        (LabG_MenuType(new_w) == XmMENU_PULLDOWN) ||
        (LabG_MenuType(new_w) == XmMENU_OPTION)))
    {
        lw->gadget.traversal_on = False;
        lw->gadget.highlight_on_enter = False;
    }

    /*  Initialize the interesting input types.  */
    lw->gadget.event_mask = XmHELP_EVENT | XmFOCUS_IN_EVENT | XmFOCUS_OUT_EVENT
        | XmENTER_EVENT | XmLEAVE_EVENT | XmBDRAG_EVENT;
}


/*
 * DealWithColors
 *	Deal with compatibility.
 */

static void
DealWithColors(XmLabelGadget lw)
{
    XmManagerWidget mw = (XmManagerWidget) XtParent(lw);

    /*
     * If the gadget color is set to the tag value or it is the
     * same as the manager color; bc mode is enabled otherwise
     * initialize like a widget.
     */
    if ((LabG_Background(lw) == INVALID_PIXEL ||
        LabG_Background(lw) == mw->core.background_pixel) &&
        (LabG_Foreground(lw) == INVALID_PIXEL ||
        LabG_Foreground(lw) == mw->manager.foreground) &&
        (LabG_TopShadowColor(lw) == INVALID_PIXEL ||
        LabG_TopShadowColor(lw) == mw->manager.top_shadow_color) &&
        (LabG_BottomShadowColor(lw) == INVALID_PIXEL ||
        LabG_BottomShadowColor(lw) == mw->manager.bottom_shadow_color) &&
        (LabG_HighlightColor(lw) == INVALID_PIXEL ||
        LabG_HighlightColor(lw) == mw->manager.highlight_color))
    {
        LabG_Background(lw) = mw->core.background_pixel;
        LabG_Foreground(lw) = mw->manager.foreground;
        LabG_TopShadowColor(lw) = mw->manager.top_shadow_color;
        LabG_BottomShadowColor(lw) = mw->manager.bottom_shadow_color;
        LabG_HighlightColor(lw) = mw->manager.highlight_color;
    }
    else
    {
        InitNewColorBehavior(lw);
    }
}


/*
 * InitNewColorBehavior
 *	Initialize colors like a widget.  These are CallProcs so
 * they should be called with a correct offset. However offset
 * isn't used by these functions.  Even so I supply offset.
 * You make the call.
 */

static void
InitNewColorBehavior(XmLabelGadget lw)
{
    XrmValue value;

    value.size = sizeof(Pixel);

    if (LabG_Background(lw) == INVALID_PIXEL)
    {
        _XmBackgroundColorDefault
            ((Widget) lw,
            XtOffsetOf(struct _XmLabelGCacheObjRec, label_cache.background),
            &value);
        memcpy((char*) &LabG_Background(lw), value.addr, value.size);
    }

    if (LabG_Foreground(lw) == INVALID_PIXEL)
    {
        _XmForegroundColorDefault
            ((Widget) lw,
            XtOffsetOf(struct _XmLabelGCacheObjRec, label_cache.foreground),
            &value);
        memcpy((char*) &LabG_Foreground(lw), value.addr, value.size);
    }

    if (LabG_TopShadowColor(lw) == INVALID_PIXEL)
    {
        _XmTopShadowColorDefault
            ((Widget) lw,
            XtOffsetOf(struct _XmLabelGCacheObjRec, label_cache.top_shadow_color),
            &value);
        memcpy((char*) &LabG_TopShadowColor(lw), value.addr, value.size);
    }

    if (LabG_BottomShadowColor(lw) == INVALID_PIXEL)
    {
        _XmBottomShadowColorDefault
            ((Widget) lw,
            XtOffsetOf(struct _XmLabelGCacheObjRec,
            label_cache.bottom_shadow_color),
            &value);
        memcpy((char*) &LabG_BottomShadowColor(lw), value.addr, value.size);
    }

    if (LabG_HighlightColor(lw) == INVALID_PIXEL)
    {
        _XmHighlightColorDefault
            ((Widget) lw,
            XtOffsetOf(struct _XmLabelGCacheObjRec, label_cache.highlight_color),
            &value);
        memcpy((char*) &LabG_HighlightColor(lw), value.addr, value.size);
    }
}


/*
 * DealWithPixmaps
 *	Deal with compatibility.  If any resource is set initialize
 * like a widget otherwise get everything from the parent.
 */

static void
DealWithPixmaps(XmLabelGadget lw)
{
    XmManagerWidget mw = (XmManagerWidget) XtParent(lw);

    if ((LabG_TopShadowPixmap(lw) == INVALID_PIXMAP ||
        LabG_TopShadowPixmap(lw) == mw->manager.top_shadow_pixmap) &&
        (LabG_HighlightPixmap(lw) == INVALID_PIXMAP ||
        LabG_HighlightPixmap(lw) == mw->manager.highlight_pixmap))
    {
        LabG_TopShadowPixmap(lw) = mw->manager.top_shadow_pixmap;
        LabG_HighlightPixmap(lw) = mw->manager.highlight_pixmap;
    }
    else
    {
        InitNewPixmapBehavior(lw);
    }
}


/*
 * InitNewPixmapBehavior
 *	Initialize colors like a widget.
 */

static void
InitNewPixmapBehavior(XmLabelGadget lw)
{
    if (LabG_TopShadowPixmap(lw) == INVALID_PIXMAP)
        LabG_TopShadowColor(lw) = GetTopShadowPixmapDefault((Widget)lw);

    if (LabG_HighlightPixmap(lw) == INVALID_PIXMAP)
        LabG_HighlightPixmap(lw) = GetLabelHighlightPixmapDefault((Widget)lw);
}


/************************************************************************
 *
 *  QueryGeometry
 *
 ************************************************************************/

static XtGeometryResult
QueryGeometry(Widget wid,
XtWidgetGeometry *intended,
XtWidgetGeometry *reply)
{
    XmLabelGadget lg = (XmLabelGadget) wid;
    reply->request_mode = 0;

    /* Don't really know what to do with queries about x,y,border,stacking.
     * Since we are interpreting unset bits as a request for information
     * (asking about neither height or width does the old 0-0 request)
     * a caller asking about x,y should not get back width and height,
     * especially since it is an expensive operation.  So x, y, border, stack
     * all return No, this indicates we'd prefer to remain as is.  Parent
     * is free to change it anyway...
     */

    if (GMode(intended) & ~(CWWidth | CWHeight))
        return XtGeometryNo;

    if (LabG_RecomputeSize(lg) == FALSE)
        return XtGeometryNo;

    /* pre-load the reply with input values */

    reply->request_mode = (CWWidth | CWHeight);

    reply->width = LabG_TextRect(lg).width +
        (2 * (LabG_MarginWidth(lg) +
        lg->gadget.highlight_thickness +
        lg->gadget.shadow_thickness)) +
        LabG_MarginLeft(lg) +
        LabG_MarginRight(lg);

    if (reply->width == 0)
        reply->width = 1;

    reply->height = MAX(LabG_TextRect(lg).height,
        LabG_AccTextRect(lg).height) +
        (2 * (LabG_MarginHeight(lg) +
        lg->gadget.highlight_thickness +
        lg->gadget.shadow_thickness)) +
        LabG_MarginTop(lg) +
        LabG_MarginBottom(lg);

    if (reply->height == 0)
        reply->height = 1;

    if ((IsWidth(intended) && (reply->width != intended->width)) ||
        (IsHeight(intended) && (reply->height != intended->height)) ||
        (GMode(intended) != GMode(reply)))
    {
        return XtGeometryAlmost;
    }
    else
    {
        reply->request_mode = 0;
        return XtGeometryYes;
    }
}


/************************************************************************
 *
 *  Destroy
 *	Free up the label gadget allocated space.  This includes
 *	the label, and GC's.
 *
 ************************************************************************/

static void
Destroy(Widget w)
{
    if (LabG__label(w) != NULL)
        XmStringFree (LabG__label(w));
    if (LabG__acceleratorText(w) != NULL)
        XmStringFree (LabG__acceleratorText(w));
    XtFree (LabG_Accelerator(w));
    if (LabG_Font(w)  != NULL)
        XmFontListFree (LabG_Font(w));
    XtFree (LabG_MnemonicCharset (w));

    XtFree ((char*) ((XmLabelGadget)w)->label.baselines);

    XtReleaseGC (XtParent(w), LabG_NormalGC(w));
    XtReleaseGC (XtParent(w), LabG_InsensitiveGC(w));
#ifdef FIX_1381
	XtReleaseGC (XtParent(w), LabG_ShadowGC(w));
#endif
    XtReleaseGC (XtParent(w), LabG_BackgroundGC(w));
    XtReleaseGC (XtParent(w), LabG_HighlightGC(w));
    XtReleaseGC (XtParent(w), LabG_TopShadowGC(w));
    XtReleaseGC (XtParent(w), LabG_BottomShadowGC(w));

    /* CR 6571: Free cache *after* making all references. */
    _XmProcessLock();
    _XmCacheDelete((XtPointer) LabG_Cache(w));
    _XmProcessUnlock();
}


/*ARGSUSED*/
static void
LabelDrawBackground(Widget wid,
XEvent *event,                                    /* unused */
Region region,                                    /* unused */
LRectangle *background_box)
{
    XmLabelGadget lw = (XmLabelGadget) wid;

    switch (lw->label.fill_bg_box)
    {
        case _XmPLAIN_BG_BOX:
            return;

        case _XmFILL_BG_BOX:
        case _XmALWAYS_FILL_BG_BOX:
        default:
            break;
    }

    /*
     * Background_box is a parameter because subclasses like
     * PushBG and ToggleBG need to be able to adjust this rectangle.
     */

    if (background_box->width < 0)
        background_box->width = 0;

    if (background_box->height < 0)
        background_box->height = 0;

    XFillRectangle(XtDisplay(lw),
        XtWindow((Widget) lw),
        LabG_BackgroundGC(lw),
        background_box->x,
        background_box->y,
        background_box->width,
        background_box->height);
}


/************************************************************************
 *
 *  Redisplay
 *
 ************************************************************************/

static void
Redisplay(Widget wid,
XEvent *event,
Region region)
{
    XmLabelGadget lw = (XmLabelGadget) wid;
    LRectangle background_box;

    background_box.x = lw->rectangle.x + LabG_Highlight(lw);
    background_box.y = lw->rectangle.y + LabG_Highlight(lw);
    background_box.width = lw->rectangle.width - (2 * LabG_Highlight(lw));
    background_box.height = lw->rectangle.height - (2 * LabG_Highlight(lw));

    _XmRedisplayLabG(wid, event, region, &background_box);
}

void
_XmRedisplayLabG(Widget wid,
XEvent *event,
Region region,
LRectangle *background_box)
{
    XmLabelGadget lw = (XmLabelGadget) wid;
    GC gc;
    GC clipgc = NULL;
    XRectangle clip_rect;
    Dimension availW, availH, marginal_width, marginal_height, max_text_height;

    if (!XtIsRealized(wid)) return ;

    if (LabG_IsMenupane(lw))
    {
        ShellWidget mshell = (ShellWidget) XtParent(XtParent(lw));
        if (! mshell->shell.popped_up)
            return;
    }

    availH = lw->rectangle.height;
    availW = lw->rectangle.width;

    /*
     * Don't count MarginWidth to be consistent with Label Widget.
     *
     * Adjust definitions of temporary variables
     */
    marginal_width = LabG_MarginLeft(lw) + LabG_MarginRight(lw) +
        (2 * (lw->gadget.highlight_thickness + lw->gadget.shadow_thickness));

    marginal_height = LabG_MarginTop(lw) + LabG_MarginBottom(lw) +
        (2 * (lw->gadget.highlight_thickness + lw->gadget.shadow_thickness));

    max_text_height = MAX(LabG_TextRect(lw).height, LabG_AccTextRect(lw).height);

    if (XtIsSensitive(wid))
        clipgc = LabG_NormalGC(lw);
    else
        clipgc = LabG_InsensitiveGC(lw);

    /* Clip should include critical margins (see Label.c) */
    if (availH < (marginal_height + max_text_height) ||
        availW < (marginal_width + LabG_TextRect(lw).width))
    {
        clip_rect.x = lw->rectangle.x + lw->gadget.highlight_thickness +
            lw->gadget.shadow_thickness + LabG_MarginLeft(lw);
        clip_rect.y = lw->rectangle.y + lw->gadget.highlight_thickness +
            lw->gadget.shadow_thickness + LabG_MarginTop(lw);

        /* Don't allow negative dimensions */
        if (availW > marginal_width)
            clip_rect.width = availW - marginal_width;
        else
            clip_rect.width = 0;

        if (availH > marginal_height)
            clip_rect.height = availH - marginal_height;
        else
            clip_rect.height = 0;

        XSetClipRectangles(XtDisplay(lw), clipgc, 0,0, &clip_rect, 1, Unsorted);
#ifdef FIX_1521
#ifdef USE_XFT
        _XmXftSetClipRectangles(XtDisplay(lw), XtWindow(lw), 0, 0, &clip_rect, 1);
#endif
#endif
    } else
    {
    XSetClipMask (XtDisplay (lw), clipgc, None);
#ifdef FIX_1521    
#ifdef USE_XFT
	XftDraw	*draw = _XmXftDrawCreate(XtDisplay(lw), XtWindow(lw));
	XftDrawSetClip(draw, NULL);
#endif
#endif
    }

#ifdef FIX_1517
#ifdef USE_XFT
    {
    int width, height;
    
    int x = lw->rectangle.x + LabG_TextRect(lw).x + LabG_StringRect(lw).x;
    int y = lw->rectangle.y + LabG_TextRect(lw).y + LabG_StringRect(lw).y;
    
    if (LabG_StringRect(lw).width < availW - marginal_width)
    	width = LabG_StringRect(lw).width;
    else
#ifdef FIX_1654
    	width = availW - marginal_width;
#else
    	width = availW - marginal_width - x;
#endif

    if (LabG_StringRect(lw).height < availH - marginal_height)
    	height = LabG_StringRect(lw).height;
    else
#ifdef FIX_1654
    	height = availH - marginal_height;
#else
    	height = availH - marginal_height - y;
#endif
    
    XFillRectangle(XtDisplay(lw), XtWindow(lw), LabG_BackgroundGC(lw),
		x, y, width, height);
    }
#endif
#endif

    /*  Draw the pixmap or text  */
    LabelDrawBackground((Widget)lw, event, region, background_box);

    if (LabG_IsPixmap(lw) || LabG_IsPixmapAndText(lw))
    {
        int depth;

        /* moved before the condition: LabelDrawBackground((Widget)lw, event, region, background_box); */
        if (XtIsSensitive(wid))
        {
            if (Pix (lw) != XmUNSPECIFIED_PIXMAP)
            {
                gc = LabG_NormalGC(lw);

                XmeGetPixmapData(XtScreen(lw), Pix(lw), NULL, &depth,
                    NULL, NULL, NULL, NULL, NULL, NULL);

                if (depth == XtParent(lw)->core.depth)
                    XCopyArea (XtDisplay(lw), Pix(lw), XtWindow(lw), gc, 0, 0,
                        LabG_PixmapRect(lw).width, LabG_PixmapRect(lw).height,
                        lw->rectangle.x + LabG_TextRect(lw).x +
				LabG_PixmapRect(lw).x,
                        lw->rectangle.y + LabG_TextRect(lw).y +
				LabG_PixmapRect(lw).y);
                else if (depth == 1)
                    XCopyPlane (XtDisplay(lw), Pix(lw), XtWindow(lw), gc, 0, 0,
                            LabG_PixmapRect(lw).width,
			    LabG_PixmapRect(lw).height,
                            lw->rectangle.x + LabG_TextRect(lw).x +
				LabG_PixmapRect(lw).x,
                            lw->rectangle.y + LabG_TextRect(lw).y +
				LabG_PixmapRect(lw).y,
			    1);
            }
        }
        else
        {
            Pixmap pix_use = Pix_insen (lw) ;

            if (pix_use == XmUNSPECIFIED_PIXMAP)
#ifdef FIX_1381
		Pix_insen(lw) = pix_use = _XmConvertToBW(wid, Pix(lw));
#else
		pix_use = Pix(lw);				
#endif
            if (pix_use != XmUNSPECIFIED_PIXMAP)
            {
                gc = LabG_InsensitiveGC(lw);

                XmeGetPixmapData(XtScreen(lw), pix_use, NULL, &depth,
                    NULL, NULL, NULL, NULL, NULL, NULL);

                if (depth == XtParent(lw)->core.depth)
                    XCopyArea (XtDisplay(lw), pix_use, XtWindow(lw), gc, 0, 0,
                        LabG_PixmapRect(lw).width, LabG_PixmapRect(lw).height,
                        lw->rectangle.x + LabG_TextRect(lw).x +
				LabG_PixmapRect(lw).x,
                        lw->rectangle.y + LabG_TextRect(lw).y +
				LabG_PixmapRect(lw).y);
                else if (depth == 1)
                    XCopyPlane (XtDisplay(lw), pix_use, XtWindow(lw), gc, 0, 0,
                            LabG_PixmapRect(lw).width,
			    LabG_PixmapRect(lw).height,
                            lw->rectangle.x + LabG_TextRect(lw).x + LabG_PixmapRect(lw).x,
                            lw->rectangle.y + LabG_TextRect(lw).y + LabG_PixmapRect(lw).y,
			    1);

#ifndef FIX_1381
                /* if no insensitive pixmap but a regular one, we need
                to do the stipple manually, since copyarea doesn't */
				if (pix_use == Pix(lw))		{
                    /* need fill stipple, not opaque */
                    XSetFillStyle(XtDisplay(lw), gc, FillStippled);
                    XFillRectangle(XtDisplay(lw), XtWindow(lw),
                        gc,
			lw->rectangle.x + LabG_TextRect(lw).x +
				LabG_PixmapRect(lw).x,
                        lw->rectangle.y + LabG_TextRect(lw).y +
				LabG_PixmapRect(lw).y,
                        LabG_PixmapRect(lw).width,
                        LabG_PixmapRect(lw).height);
                    XSetFillStyle(XtDisplay(lw), gc, FillOpaqueStippled);
                }
#endif
#ifdef FIX_1505
                if (pix_use == Pix(lw)) {
                    XSetFillStyle(XtDisplay(lw), gc, FillStippled);
                    XSetStipple(XtDisplay(lw), gc, _XmGetInsensitiveStippleBitmap((Widget)lw));
                    XFillRectangle(XtDisplay(lw), XtWindow(lw), gc,
                       lw->rectangle.x + LabG_TextRect(lw).x +
                       LabG_PixmapRect(lw).x,
                       lw->rectangle.y + LabG_TextRect(lw).y +
                       LabG_PixmapRect(lw).y,
                       LabG_PixmapRect(lw).width,
                       LabG_PixmapRect(lw).height);
                    XSetFillStyle(XtDisplay(lw), gc, FillSolid);
                }
#endif
            }
        }
    }

    if ((LabG_IsText(lw) || LabG_IsPixmapAndText(lw)) && (LabG__label(lw) != NULL))
    {
        /* TODO this clears the pixmap, but this is needed to draw background */
        /* LabelDrawBackground((Widget)lw, event, region, background_box); */
	
        if (LabG_Mnemonic(lw) != XK_VoidSymbol)
        {
            /* CR 5181: Convert the mnemonic keysym to a character string. */
            char tmp[MB_LEN_MAX * 2];
            XmString underline;

            tmp[_XmOSKeySymToCharacter(LabG_Mnemonic(lw), NULL, tmp)] = '\0';
            underline = XmStringCreate(tmp, LabG_MnemonicCharset(lw));
#ifdef FIX_1381
			if (XtIsSensitive(wid) )
			{
				/*Draw normal text*/
				XmStringDrawUnderline(XtDisplay(lw), XtWindow(lw),
						LabG_Font(lw), LabG__label(lw),
						LabG_NormalGC(lw),
						lw->rectangle.x + LabG_TextRect(lw).x + LabG_StringRect(lw).x,
						lw->rectangle.y + LabG_TextRect(lw).y + LabG_StringRect(lw).y,
						LabG_StringRect(lw).width, LabG_Alignment(lw),
						LayoutG(lw), NULL, underline);
			}
			else
			{
				/*Draw shadow for insensitive text*/
				XmStringDrawUnderline(XtDisplay(lw), XtWindow(lw),
						LabG_Font(lw), LabG__label(lw),
						LabG_ShadowGC(lw),
						lw->rectangle.x+1 + LabG_TextRect(lw).x + LabG_StringRect(lw).x,
						lw->rectangle.y+1 + LabG_TextRect(lw).y + LabG_StringRect(lw).y,
						LabG_StringRect(lw).width, LabG_Alignment(lw),
						LayoutG(lw), NULL, underline);
				/*Draw insensitive text*/
				XmStringDrawUnderline(XtDisplay(lw), XtWindow(lw),
						LabG_Font(lw), LabG__label(lw),
						LabG_InsensitiveGC(lw),
						lw->rectangle.x + LabG_TextRect(lw).x + LabG_StringRect(lw).x,
						lw->rectangle.y + LabG_TextRect(lw).y + LabG_StringRect(lw).y,
						LabG_StringRect(lw).width, LabG_Alignment(lw),
						LayoutG(lw), NULL, underline);
			}
#else
            XmStringDrawUnderline(XtDisplay(lw), XtWindow(lw),
                LabG_Font(lw), LabG__label(lw),
                (XtIsSensitive(wid) ?
                LabG_NormalGC(lw) : LabG_InsensitiveGC(lw)),
                lw->rectangle.x + LabG_TextRect(lw).x + LabG_StringRect(lw).x,
                lw->rectangle.y + LabG_TextRect(lw).y + LabG_StringRect(lw).y,
                LabG_StringRect(lw).width, LabG_Alignment(lw),
                LayoutG(lw), NULL, underline);

#endif
            XmStringFree(underline);
        }
        else
#ifdef FIX_1381
		{
			if (XtIsSensitive(wid) )
			{
				/*Draw normal text*/
				XmStringDraw (XtDisplay(lw), XtWindow(lw),
						LabG_Font(lw), LabG__label(lw),
						LabG_NormalGC(lw),
						lw->rectangle.x + LabG_TextRect(lw).x + LabG_StringRect(lw).x,
						lw->rectangle.y + LabG_TextRect(lw).y + LabG_StringRect(lw).y,
						LabG_StringRect(lw).width,
						LabG_Alignment(lw), LayoutG(lw), NULL);
			}
			else
			{
				/*Draw shadow for insensitive text*/
				XmStringDraw (XtDisplay(lw), XtWindow(lw),
						LabG_Font(lw), LabG__label(lw),
						LabG_ShadowGC(lw),
						lw->rectangle.x + LabG_TextRect(lw).x+1 + LabG_StringRect(lw).x,
						lw->rectangle.y + LabG_TextRect(lw).y+1 + LabG_StringRect(lw).y,
						LabG_StringRect(lw).width,
						LabG_Alignment(lw), LayoutG(lw), NULL);
				/*Draw insensitive text*/
				XmStringDraw (XtDisplay(lw), XtWindow(lw),
						LabG_Font(lw), LabG__label(lw),
						LabG_InsensitiveGC(lw),
						lw->rectangle.x + LabG_TextRect(lw).x + LabG_StringRect(lw).x,
						lw->rectangle.y + LabG_TextRect(lw).y + LabG_StringRect(lw).y,
						LabG_StringRect(lw).width,
						LabG_Alignment(lw), LayoutG(lw), NULL);
			}
		}
#else
            XmStringDraw (XtDisplay(lw), XtWindow(lw),
                LabG_Font(lw), LabG__label(lw),
                (XtIsSensitive(wid) ?
                LabG_NormalGC(lw) : LabG_InsensitiveGC(lw)),
            lw->rectangle.x + LabG_TextRect(lw).x + LabG_StringRect(lw).x,
            lw->rectangle.y + LabG_TextRect(lw).y + LabG_StringRect(lw).y,
            LabG_StringRect(lw).width,
            LabG_Alignment(lw), LayoutG(lw), NULL);
#endif

#ifndef FIX_1381
#ifdef USE_XFT
        if (!XtIsSensitive(wid)) {
          XSetFillStyle(XtDisplay(lw), LabG_InsensitiveGC(lw), FillStippled);
          XFillRectangle(XtDisplay(lw), XtWindow(lw), LabG_InsensitiveGC(lw),
			lw->rectangle.x + LabG_TextRect(lw).x +
				LabG_StringRect(lw).x,
                        lw->rectangle.y + LabG_TextRect(lw).y +
				LabG_StringRect(lw).y,
                        LabG_StringRect(lw).width,
                        LabG_StringRect(lw).height);
          XSetFillStyle(XtDisplay(lw), LabG_InsensitiveGC(lw), FillOpaqueStippled);
        }
#endif
#endif
    }

    if (LabG__acceleratorText(lw) != NULL)
    {
        /* Since accelerator text is drawn by moving in from the right,
         * it is possible to overwrite label text when there is clipping,
         * Therefore draw accelerator text only if there is enough
         * room for everything */

        if ((lw->rectangle.width) >=
            (2 * (lw->gadget.highlight_thickness +
            lw->gadget.shadow_thickness +
            LabG_MarginWidth(lw)) +
            LabG_MarginLeft(lw) + LabG_TextRect(lw).width +
            LabG_MarginRight(lw)))
        {
#ifdef FIX_1381
			if (XtIsSensitive(wid) )
			{
				/*Draw normal text*/
				XmStringDraw (XtDisplay(lw), XtWindow(lw),
						LabG_Font(lw), LabG__acceleratorText(lw),
						LabG_NormalGC(lw),
						lw->rectangle.x + LabG_AccTextRect(lw).x,
						lw->rectangle.y + LabG_AccTextRect(lw).y,
						LabG_AccTextRect(lw).width, XmALIGNMENT_END,
						LayoutG(lw), NULL);
			}
			else
			{
				/*Draw shadow for insensitive text*/
				XmStringDraw (XtDisplay(lw), XtWindow(lw),
						LabG_Font(lw), LabG__acceleratorText(lw),
						LabG_ShadowGC(lw) ,
						lw->rectangle.x + LabG_AccTextRect(lw).x+1,
						lw->rectangle.y + LabG_AccTextRect(lw).y+1,
						LabG_AccTextRect(lw).width, XmALIGNMENT_END,
						LayoutG(lw), NULL);
				/*Draw insensitive text*/
				XmStringDraw (XtDisplay(lw), XtWindow(lw),
						LabG_Font(lw), LabG__acceleratorText(lw),
						LabG_InsensitiveGC(lw),
						lw->rectangle.x + LabG_AccTextRect(lw).x,
						lw->rectangle.y + LabG_AccTextRect(lw).y,
						LabG_AccTextRect(lw).width, XmALIGNMENT_END,
						LayoutG(lw), NULL);
			}
#else
            XmStringDraw (XtDisplay(lw), XtWindow(lw),
                LabG_Font(lw), LabG__acceleratorText(lw),
                (XtIsSensitive(wid) ?
                LabG_NormalGC(lw) : LabG_InsensitiveGC(lw)),
                lw->rectangle.x + LabG_AccTextRect(lw).x,
                lw->rectangle.y + LabG_AccTextRect(lw).y,
                LabG_AccTextRect(lw).width, XmALIGNMENT_END,
                LayoutG(lw), NULL);
#endif
        }
    }

    /* Redraw the proper highlight  */
    if (! LabG_IsMenupane(lw) && LabG_MenuType(lw) != XmMENU_BAR)
    {
        if (lw->gadget.highlighted)
        {
            (*((XmGadgetClass) XtClass(lw))->gadget_class.border_highlight)
                ((Widget) lw);
        }
    }
}


/************************************************************************
 *
 *  SetValues
 *	This routine will take care of any changes that have been made
 *
 ************************************************************************/

/*ARGSUSED*/
static Boolean
SetValues(Widget cw,
Widget rw,
Widget nw,
ArgList args,                                     /* unused */
Cardinal *num_args)                               /* unused */
{
    XmLabelGadget current = (XmLabelGadget) cw;
    XmLabelGadget req = (XmLabelGadget) rw;
    XmLabelGadget new_w = (XmLabelGadget) nw;
    Boolean flag = False;
    Boolean newstring = False;
    Boolean ProcessFlag = FALSE;
    Boolean CleanupFontFlag = FALSE;
    Boolean Call_Resize = False;
    XmMenuSystemTrait menuSTrait;

    /* Invalidate the basline cache if necessary. */
    if ((LabG__label(new_w) != LabG__label(current)) ||
        (LabG_Font(new_w) != LabG_Font(current)))
    {
        if (new_w->label.baselines)
        {
            XtFree ((char*) new_w->label.baselines);
            new_w->label.baselines = NULL;
        }
    }

    /*  If the label has changed, make a copy of the new label,  */
    /*  and free the old label.                                  */

    if (LabG__label(new_w)!= LabG__label(current))
    {
        newstring = True;
        if (LabG__label(new_w) == NULL)
        {
            LabG__label(new_w) =
                XmStringCreateLocalized(XrmQuarkToString (current->object.xrm_name));
        }
        else
        {
            if (XmeStringIsValid((XmString) LabG__label(new_w)))
            {
                LabG__label(new_w) = XmStringCopy((XmString) LabG__label(new_w));
            }
            else
            {
                XmeWarning((Widget) new_w, CS_STRING_MESSAGE);
                LabG__label(new_w) =
                    XmStringCreateLocalized(XrmQuarkToString(new_w->object.xrm_name));
            }
        }

        XmStringFree(LabG__label(current));
        LabG__label(current)= NULL;
        LabG__label(req)= NULL;
    }

    if (LabG_MarginRight(new_w) != LabG_MarginRight(current))
        new_w->label.acc_right_delta = 0;
    if (LabG_MarginLeft(new_w) != LabG_MarginLeft(current))
        new_w->label.acc_left_delta = 0;

    if ((LabG__acceleratorText(new_w) != LabG__acceleratorText(current)) &&
        LabG_IsMenupane(new_w))
    {
        /* BEGIN OSF Fix pir 1098 */
        newstring = TRUE;
        /* END OSF Fix pir 1098 */
        if (LabG__acceleratorText(new_w) != NULL)
        {
            if (XmeStringIsValid((XmString) LabG__acceleratorText(new_w)))
            {
                if ((XmIsCascadeButtonGadget(new_w)) &&
                    (LabG__acceleratorText(new_w) != NULL))
                    LabG__acceleratorText(new_w) = NULL;
                else
                    LabG__acceleratorText(new_w) =
                        XmStringCopy(LabG__acceleratorText(new_w));
                XmStringFree(LabG__acceleratorText(current));
                LabG__acceleratorText(current)= NULL;
                LabG__acceleratorText(req)= NULL;
            }
            else
            {
                XmeWarning((Widget) new_w, ACC_MESSAGE);
                LabG__acceleratorText(new_w) = NULL;
                XmStringFree(LabG__acceleratorText(current));
                LabG__acceleratorText(current)= NULL;
                LabG__acceleratorText(req)= NULL;
            }
        }
        /* BEGIN OSF Fix pir 1098 */
        else if (LabG__acceleratorText(current))
        {
            /* CR 3481:  Don't blindly force the margin back to 0; */
            /*	try to preserve the user specified value. */
            if (LayoutIsRtoLG(new_w))
            {
                LabG_MarginLeft(new_w) -= new_w->label.acc_left_delta;
                new_w->label.acc_left_delta = 0;
            }
            else
            {
                LabG_MarginRight(new_w) -= new_w->label.acc_right_delta;
                new_w->label.acc_right_delta = 0;
            }
        }
        /* END OSF Fix pir 1098 */
    }
    else
        LabG__acceleratorText(new_w) = LabG__acceleratorText(current);

    if (LabG_Font(new_w) != LabG_Font(current))
    {
        CleanupFontFlag = True;
        if (LabG_Font(new_w) == NULL)
        {
            /* CR 2990: let subclasses pick their own default fonts. */
            LabG_Font(new_w) =
                XmeGetDefaultRenderTable((Widget) new_w, XmLABEL_FONTLIST);
        }
        LabG_Font(new_w) = XmFontListCopy (LabG_Font(new_w));
    }

    /*  Reinitialize the interesting input types.  */

    new_w->gadget.event_mask = XmHELP_EVENT;

    new_w->gadget.event_mask |=
        XmFOCUS_IN_EVENT | XmFOCUS_OUT_EVENT | XmENTER_EVENT | XmLEAVE_EVENT |
        XmBDRAG_EVENT;

    if ((LabG_MenuType(new_w) == XmMENU_POPUP) ||
        (LabG_MenuType(new_w) == XmMENU_PULLDOWN) ||
        (LabG_MenuType(new_w) == XmMENU_BAR))
        new_w->gadget.highlight_thickness = 0;

    if (!XmRepTypeValidValue(XmRID_LABEL_TYPE, LabG_LabelType(new_w),
        (Widget) new_w))
    {
        LabG_LabelType(new_w) = LabG_LabelType(current);
    }

    if (!XmRepTypeValidValue(XmRID_PIXMAP_PLACEMENT, LabG_PixmapPlacement(new_w),
        (Widget) new_w))
    {
        LabG_PixmapPlacement(new_w) = LabG_PixmapPlacement(current);
    }

    if (LayoutG(new_w) != LayoutG(current))
    {
        /* If no new margins specified swap them */
        if ((LayoutIsRtoLG(current) != LayoutIsRtoLG(new_w)) &&
            (LabG_MarginLeft(current)  == LabG_MarginLeft(new_w)) &&
            (LabG_MarginRight(current) == LabG_MarginRight(new_w)))
        {
            LabG_MarginLeft(new_w)  = LabG_MarginRight(current);
            LabG_MarginRight(new_w) = LabG_MarginLeft(current);
        }
        flag = TRUE;
    }

    /* ValidateInputs(new_w); */

    if (((LabG_IsText(new_w) || LabG_IsPixmapAndText(new_w)) &&
        (newstring || (LabG_Font(new_w) != LabG_Font(current)))) ||
        ((LabG_IsPixmap(new_w) || LabG_IsPixmapAndText(new_w)) &&
        ((LabG_Pixmap(new_w) != LabG_Pixmap(current)) ||
        (LabG_PixmapInsensitive(new_w) != LabG_PixmapInsensitive(current)) ||
        /* When you have different sized pixmaps for sensitive and */
        /* insensitive states and sensitivity changes, */
        /* the right size is chosen. (osfP2560) */
        (XtIsSensitive(nw) != XtIsSensitive(cw)))) ||
	(LabG_IsPixmapAndText(new_w) &&
	LabG_PixmapPlacement(new_w) != LabG_PixmapPlacement(current)) ||
        (LabG_LabelType(new_w) != LabG_LabelType(current)))
    {
        /* CR 9179: back out CR 5419 changes. */
        _XmCalcLabelGDimensions((Widget) new_w);

        if (LabG_RecomputeSize(new_w))
        {
            if (req->rectangle.width == current->rectangle.width)
                new_w->rectangle.width = 0;
            if (req->rectangle.height == current->rectangle.height)
                new_w->rectangle.height = 0;
        }

        Call_Resize = True;

        flag = True;
    }

    if ((LabG_Alignment(new_w)!= LabG_Alignment(current)) ||
        (LayoutG(new_w) != LayoutG(current)))
    {
        if (!XmRepTypeValidValue(XmRID_ALIGNMENT, LabG_Alignment(new_w),
            (Widget) new_w))
        {
            LabG_Alignment(new_w) = LabG_Alignment(current);
        }

        Call_Resize = True;

        flag = True;
    }

    if ((LabG_MarginHeight(new_w) != LabG_MarginHeight(current)) ||
        (LabG_MarginWidth(new_w) != LabG_MarginWidth(current)) ||
        (LabG_MarginRight(new_w) != LabG_MarginRight(current)) ||
        (LabG_MarginLeft(new_w)!= LabG_MarginLeft(current)) ||
        (LabG_MarginTop(new_w)!= LabG_MarginTop(current)) ||
        (LabG_MarginBottom(new_w)!= LabG_MarginBottom(current)) ||
        (new_w->gadget.shadow_thickness != current->gadget.shadow_thickness) ||
        (new_w->gadget.highlight_thickness !=
        current->gadget.highlight_thickness) ||
        ((new_w->rectangle.width <= 0) || (new_w->rectangle.height <= 0)) ||
        (LabG_PixmapTextPadding(new_w) != LabG_PixmapTextPadding(current)))
    {
        if (LabG_RecomputeSize(new_w))
        {
            if (req->rectangle.width == current->rectangle.width)
                new_w->rectangle.width = 0;
            if (req->rectangle.height == current->rectangle.height)
                new_w->rectangle.height = 0;
        }

        Call_Resize = True;
        flag = True;
    }

    /* Resize is called only if we need to calculate the dimensions or */
    /* coordinates  for the string.				      */

    if (Call_Resize)
    {

        XtWidgetProc resize;

        _XmProcessLock();
        resize = (((XmLabelGadgetClassRec *)(new_w->object.widget_class))->
            rect_class.resize);
        _XmProcessUnlock();

        (* (resize)) ((Widget) new_w);
    }

    /* If the sensitivity has changed then we must redisplay. */
    if (XtIsSensitive(nw) != XtIsSensitive(cw))
    {
        flag = True;
    }

    /*  Force the traversal flag when in a menu.  */
    if ((XtClass(new_w) == xmLabelGadgetClass) &&
        ((LabG_MenuType(new_w) == XmMENU_POPUP) ||
        (LabG_MenuType(new_w) == XmMENU_PULLDOWN) ||
        (LabG_MenuType(new_w) == XmMENU_OPTION)))
    {
        new_w->gadget.traversal_on = False;
        new_w->gadget.highlight_on_enter = False;
    }

    if (LabG_Font(new_w) != LabG_Font(current) ||
        LabG_Foreground(new_w) != LabG_Foreground(current) ||
        LabG_Background(new_w) != LabG_Background(current))
    {
        /* Recreate the GC's if the font has been changed */
        XtReleaseGC (XtParent (current), LabG_NormalGC(current));
        XtReleaseGC (XtParent (current), LabG_InsensitiveGC(current));
        SetNormalGC(new_w);
        flag = True;
    }

    /*
     * The test for foreground is done here to allow for subclasses
     * to use this gc in a graphix op that may reference the background
     * field of the GC (i.e. in this gc background is set to LabG_Foreground.
     */

    if (LabG_Background(new_w) != LabG_Background(current) ||
        LabG_Foreground(new_w) != LabG_Foreground(current))
    {
        XtReleaseGC (XtParent (current), LabG_BackgroundGC(current));
        _XmLabelSetBackgroundGC(new_w);
        flag = True;
    }

    if (LabG_TopShadowColor(new_w) != LabG_TopShadowColor(current) ||
        LabG_TopShadowPixmap(new_w) != LabG_TopShadowPixmap(current))
    {
        XtReleaseGC (XtParent (current), LabG_TopShadowGC(current));
        LabG_TopShadowGC(new_w) =
            _XmGetPixmapBasedGC (XtParent(nw),
            LabG_TopShadowColor(new_w),
            LabG_Background(new_w),
            LabG_TopShadowPixmap(new_w));
        flag = True;
    }

    if (LabG_BottomShadowColor(new_w) != LabG_BottomShadowColor(current) ||
        LabG_BottomShadowPixmap(new_w) != LabG_BottomShadowPixmap(current))
    {
        XtReleaseGC (XtParent (current), LabG_BottomShadowGC(current));
        LabG_BottomShadowGC(new_w) =
            _XmGetPixmapBasedGC (XtParent(nw),
            LabG_BottomShadowColor(new_w),
            LabG_Background(new_w),
            LabG_BottomShadowPixmap(new_w));
        flag = True;
    }

    if (LabG_HighlightColor(new_w) != LabG_HighlightColor(current) ||
        LabG_HighlightPixmap(new_w) != LabG_HighlightPixmap(current))
    {
        XtReleaseGC (XtParent (current), LabG_HighlightGC(current));
        LabG_HighlightGC(new_w) =
            _XmGetPixmapBasedGC (XtParent(nw),
            LabG_HighlightColor(new_w),
            LabG_Background(new_w),
            LabG_HighlightPixmap(new_w));
        flag = True;
    }

    if ((LabG_MenuType(new_w) != XmWORK_AREA) &&
        (LabG_Mnemonic(new_w) != LabG_Mnemonic(current)))
    {
        /* New grabs only required if mnemonic changes */
        ProcessFlag = TRUE;
        if (LabG_LabelType(new_w) == XmSTRING ||
	   LabG_LabelType(new_w) == XmPIXMAP_AND_STRING)
            flag = TRUE;
    }

    if (LabG_MnemonicCharset(new_w) != LabG_MnemonicCharset(current))
    {
        if (LabG_MnemonicCharset(new_w))
            LabG_MnemonicCharset(new_w) =
                _XmStringCharsetCreate(LabG_MnemonicCharset (new_w));
        else
            LabG_MnemonicCharset(new_w) =
                _XmStringCharsetCreate(XmFONTLIST_DEFAULT_TAG);

        if (LabG_MnemonicCharset (current) != NULL)
            XtFree(LabG_MnemonicCharset(current));

        if (LabG_LabelType(new_w) == XmSTRING ||
	   LabG_LabelType(new_w) == XmPIXMAP_AND_STRING)
            flag = TRUE;
    }

    if (LabG_IsMenupane(new_w) &&
        (LabG_Accelerator(new_w) != LabG_Accelerator(current)))
    {
        if (LabG_Accelerator(new_w) != NULL)
        {
            /* Copy the accelerator into local space */
            LabG_Accelerator(new_w) = XtNewString(LabG_Accelerator(new_w));
        }

        if (LabG_Accelerator(current) != NULL)
            XtFree(LabG_Accelerator(current));

        LabG_Accelerator(current) = NULL;
        LabG_Accelerator(req) = NULL;
        ProcessFlag = TRUE;
    }
    else
        LabG_Accelerator(new_w) = LabG_Accelerator(current);

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

    if (ProcessFlag && menuSTrait != NULL)
        menuSTrait->updateBindings((Widget)new_w, XmREPLACE);

    if (flag && (LabG_MenuType(new_w) == XmMENU_PULLDOWN) &&
        menuSTrait != NULL)
        menuSTrait->updateHistory(XtParent(new_w), (Widget) new_w, True);

    if (CleanupFontFlag)
        if (LabG_Font(current)) XmFontListFree(LabG_Font(current));

    return flag;
}


/*
 * So complications.  HandleRedraw is a wrapper that calls _XmLabelGCVTRedraw
 * which does the work for the trait stuff.
 *
 * _XmLabelGCVTRedraw returns a boolean which determines if the child, not the
 * parent should be redrawn.
 *
 * This is done to serve as a form of inheritance.  ToggleBG needs all the
 * LabelG stuff changed plus some of its own state.  Therefore ToggleBG
 * will call _XmLabelGCVTRedraw.
 */

static Boolean
HandleRedraw (Widget kid,
Widget cur_parent,
Widget new_parent,
Mask visual_flag)
{
    Boolean redraw = False;
    XtExposeProc  expose;

    /* Don't change with parent.  New Gadget behavior has been enabled. */
    redraw = _XmLabelGCVTRedraw (kid,  cur_parent, new_parent, visual_flag);

    _XmProcessLock();
    expose = ((XmLabelGadgetClassRec *)(XtClass(kid)))->rect_class.expose;
    _XmProcessUnlock();

    if (redraw)
    {
        if (! XtIsRealized(kid))
        {
            return redraw;
        }
        else
        {
            (* (expose)) ((Widget)kid, NULL, (Region) NULL);
        }
    }
    return False;
}


Boolean
_XmLabelGCVTRedraw(Widget kid,
Widget cur_parent,
Widget new_parent,
Mask visual_flag)
{
    XmLabelGadget lw = (XmLabelGadget) kid;
    XmManagerWidget mw = (XmManagerWidget) new_parent;
    XmManagerWidget curmw = (XmManagerWidget) cur_parent;
    Boolean redraw = False, do_normal = False, do_background = False;
    XmLabelGCacheObjPart oldCopy;

    /*
     * Since we are here the instance record is going to be changed.
     * So break this out out the cache, make the changes and reinsert
     * below.
     */

    _XmProcessLock();
    _XmCacheCopy((XtPointer) LabG_Cache(lw), (XtPointer) &oldCopy,
        sizeof(XmLabelGCacheObjPart));
    _XmCacheDelete ((XtPointer) LabG_Cache(lw));
    _XmProcessUnlock();
    LabG_Cache(lw) = &oldCopy;

    if ((visual_flag & VisualBackgroundPixel) &&
        (LabG_Background(lw) == curmw->core.background_pixel))
    {
        redraw = do_background = do_normal = True;
        LabG_Background(lw) = mw->core.background_pixel;
    }

    if (visual_flag & VisualBackgroundPixmap)
    {
        redraw = do_background = True;
    }

    if ((visual_flag & VisualForeground) &&
        (LabG_Foreground(lw) == curmw->manager.foreground))
    {
        redraw = do_normal = True;
        LabG_Foreground(lw) = mw->manager.foreground;
    }

    if (do_background)
    {
        XtReleaseGC (XtParent(lw), LabG_BackgroundGC(lw));
        _XmLabelSetBackgroundGC((XmLabelGadget)lw);
    }

    if (do_normal)
    {
        XtReleaseGC (XtParent(lw), LabG_NormalGC(lw));
        XtReleaseGC (XtParent(lw), LabG_InsensitiveGC(lw));
        SetNormalGC((XmLabelGadget)lw);
    }

    if (visual_flag & (VisualTopShadowColor | VisualTopShadowPixmap))
    {
        XtReleaseGC (XtParent(lw), LabG_TopShadowGC(lw));

        if(LabG_TopShadowColor(lw) == curmw->manager.top_shadow_color)
            LabG_TopShadowColor(lw) = mw->manager.top_shadow_color;

        if(LabG_TopShadowPixmap(lw) == curmw->manager.top_shadow_pixmap &&
            (LabG_TopShadowPixmap(lw) != XmUNSPECIFIED_PIXMAP
            || LabG_TopShadowColor(lw) == curmw->manager.top_shadow_color))
            LabG_TopShadowPixmap(lw) = mw->manager.top_shadow_pixmap;

        LabG_TopShadowGC(lw) =
            _XmGetPixmapBasedGC (XtParent(lw),
            LabG_TopShadowColor(lw),
            LabG_Background(lw),
            LabG_TopShadowPixmap(lw));

        redraw = True;
    }

    if (visual_flag & (VisualBottomShadowColor | VisualBottomShadowPixmap))
    {
        XtReleaseGC (XtParent(lw), LabG_BottomShadowGC(lw));

        if(LabG_BottomShadowColor(lw) == curmw->manager.bottom_shadow_color)
            LabG_BottomShadowColor(lw) = mw->manager.bottom_shadow_color;

        if(LabG_BottomShadowPixmap(lw) == curmw->manager.bottom_shadow_pixmap &&
            (LabG_BottomShadowPixmap(lw) != XmUNSPECIFIED_PIXMAP
            || LabG_BottomShadowColor(lw) == curmw->manager.bottom_shadow_color))
            LabG_BottomShadowPixmap(lw) = mw->manager.bottom_shadow_pixmap;

        LabG_BottomShadowGC(lw) =
            _XmGetPixmapBasedGC (XtParent(lw),
            LabG_BottomShadowColor(lw),
            LabG_Background(lw),
            LabG_BottomShadowPixmap(lw));

        redraw = True;
    }

    if (visual_flag & (VisualHighlightColor | VisualHighlightPixmap))
    {
        XtReleaseGC (XtParent(lw), LabG_HighlightGC(lw));

        if(LabG_HighlightColor(lw) == curmw->manager.highlight_color)
            LabG_HighlightColor(lw) = mw->manager.highlight_color;

        if(LabG_HighlightPixmap(lw) == curmw->manager.highlight_pixmap &&
            (LabG_HighlightPixmap(lw) != XmUNSPECIFIED_PIXMAP
            || LabG_HighlightColor(lw) == curmw->manager.highlight_color))
            LabG_HighlightPixmap(lw) = mw->manager.highlight_pixmap;

        LabG_HighlightGC(lw) =
            _XmGetPixmapBasedGC (XtParent(lw),
            LabG_HighlightColor(lw),
            LabG_Background(lw),
            LabG_HighlightPixmap(lw));

        redraw = True;
    }

    _XmProcessLock();
    LabG_Cache(lw) = (XmLabelGCacheObjPart *)
        _XmCachePart(LabG_ClassCachePart(lw), (XtPointer) LabG_Cache(lw),
        sizeof(XmLabelGCacheObjPart));
    _XmProcessUnlock();
    return redraw;
}


/************************************************************************
 *
 *  InputDispatch
 *     This function catches input sent by a manager and dispatches it
 *     to the individual routines.
 *
 ************************************************************************/

static void
InputDispatch(Widget wid,
XEvent *event,
Mask event_mask)
{
    XmLabelGadget lg = (XmLabelGadget) wid;

    if (event_mask & XmHELP_EVENT)
        Help ((Widget) lg, event);
    else if (event_mask & XmENTER_EVENT)
        _XmEnterGadget ((Widget) lg, event, NULL, NULL);
    else if (event_mask & XmLEAVE_EVENT)
        _XmLeaveGadget ((Widget) lg, event, NULL, NULL);
    else if (event_mask & XmFOCUS_IN_EVENT)
        _XmFocusInGadget ((Widget) lg, event, NULL, NULL);
    else if (event_mask & XmFOCUS_OUT_EVENT)
        _XmFocusOutGadget ((Widget) lg, event, NULL, NULL);
    else if (event_mask & XmBDRAG_EVENT)
        _XmProcessDrag ((Widget) lg, event, NULL, NULL);
}


/************************************************************************
 *
 *  Help
 *	This routine is called if the user made a help selection
 *      on the widget.
 *
 ************************************************************************/

static void
Help(Widget w,
XEvent *event)
{
    XmLabelGadget lg = (XmLabelGadget) w;
    XmMenuSystemTrait menuSTrait;

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

    if (LabG_IsMenupane(lg) && (menuSTrait != NULL))
        menuSTrait->popdown(XtParent(lg), event);

    _XmSocorro(w, event, NULL, NULL);
}


/************************************************************************
 *
 *  GetLabelString
 *     This is a get values hook function that returns the external
 *     form of the label string from the internal form.
 *
 ***********************************************************************/

/*ARGSUSED*/
static void
GetLabelString(Widget wid,
int offset,
XtArgVal *value)
{
    XmLabelGadget lw = (XmLabelGadget) wid;
    XmString string;

    string = XmStringCopy(LabG__label(lw));

    *value = (XtArgVal) string;
}


/************************************************************************
 *
 *  GetAccelerator
 *     This is a get values hook function that returns a copy
 *     of the accelerator string.
 *
 ***********************************************************************/

/*ARGSUSED*/
static void
GetAccelerator(Widget wid,
int offset,
XtArgVal *value)
{
    XmLabelGadget lw = (XmLabelGadget) wid;
    String string;

    string = XtNewString(LabG_Accelerator(lw));

    *value = (XtArgVal) string;
}


/************************************************************************
 *
 *  GetAcceleratorText
 *     This is a get values hook function that returns the external
 *     form of the accelerator text from the internal form.
 *
 ***********************************************************************/

/*ARGSUSED*/
static void
GetAcceleratorText(Widget wid,
int offset,
XtArgVal *value)
{
    XmLabelGadget lw = (XmLabelGadget) wid;
    XmString string;

    string = XmStringCopy(LabG__acceleratorText(lw));

    *value = (XtArgVal) string;
}


/************************************************************************
 *
 *  _XmStringCharsetCreate
 *
 ************************************************************************/

static XmStringCharSet
_XmStringCharsetCreate(XmStringCharSet stringcharset)
{
    return (XmStringCharSet) XtNewString((char*) stringcharset);
}


/************************************************************************
 *
 *  GetMnemonicCharset
 *     This is a get values hook function that returns the external
 *     form of the mnemonicCharset from the internal form.
 *  : Returns a string containg the mnemonicCharset.
 *    Caller must free the string .
 *
 ***********************************************************************/

/*ARGSUSED*/
static void
GetMnemonicCharset(Widget wid,
int resource,                                     /* unused */
XtArgVal *value)
{
    XmLabelGadget lw = (XmLabelGadget) wid;
    char *cset;
    int   size;

    cset = NULL;
    if (LabG_MnemonicCharset (lw))
    {
        size = strlen (LabG_MnemonicCharset (lw));
        if (size > 0)
            cset = (char *) (_XmStringCharsetCreate(LabG_MnemonicCharset (lw)));
    }

    *value = (XtArgVal) cset;
}


/************************************************************************
 *
 *  Caching Assignment help
 *     These routines are for manager widgets that go into Label's
 *     fields and set them, instead of doing a SetValues.
 *
 ************************************************************************/

static XmLabelGCacheObjPart local_cache;
static Boolean local_cache_inited = FALSE;

/*
 * QualifyLabelLocalCache
 *  Checks to see if local cache is set up
 */
static void
QualifyLabelLocalCache(XmLabelGadget w)
{
    if (!local_cache_inited)
    {
        local_cache_inited = TRUE;
        ClassCacheCopy(LabG_ClassCachePart(w))
            (LabG_Cache(w), &local_cache, sizeof(local_cache));
    }
}


/************************************************************************
 *
 * _XmReCacheLabG()
 * Check to see if ReCaching is necessary as a result of fields having
 * been set by a mananger widget. This routine is called by the
 * manager widget in their SetValues after a change is made to any
 * of Label's cached fields.
 *
 ************************************************************************/

void
_XmReCacheLabG(Widget wid)
{
    XmLabelGadget lw = (XmLabelGadget) wid;

    _XmProcessLock();
    if (local_cache_inited &&
        (!_XmLabelCacheCompare((XtPointer)&local_cache,
        (XtPointer)LabG_Cache(lw))))
    {
        /* Delete the old one. */
        _XmCacheDelete((XtPointer) LabG_Cache(lw));
        LabG_Cache(lw) = (XmLabelGCacheObjPart *)
            _XmCachePart(LabG_ClassCachePart(lw),
            (XtPointer) &local_cache, sizeof(local_cache));
    }
    local_cache_inited = FALSE;
    _XmProcessUnlock();
}


void
_XmAssignLabG_MarginHeight(XmLabelGadget lw,
#if NeedWidePrototypes
int value)
#else
Dimension value)
#endif                                            /* NeedWidePrototypes */
{
    _XmProcessLock();
        QualifyLabelLocalCache(lw);
        local_cache.margin_height = value;
        _XmProcessUnlock();
}


void
_XmAssignLabG_MarginWidth(XmLabelGadget lw,
#if NeedWidePrototypes
int value)
#else
Dimension value)
#endif                                            /* NeedWidePrototypes */
{
    _XmProcessLock();
        QualifyLabelLocalCache(lw);
        local_cache.margin_width = value;
        _XmProcessUnlock();
}


void
_XmAssignLabG_MarginLeft(XmLabelGadget lw,
#if NeedWidePrototypes
int value)
#else
Dimension value)
#endif                                            /* NeedWidePrototypes */
{
    _XmProcessLock();
        QualifyLabelLocalCache(lw);
        local_cache.margin_left = value;
        _XmProcessUnlock();
}


void
_XmAssignLabG_MarginRight(XmLabelGadget lw,
#if NeedWidePrototypes
int value)
#else
Dimension value)
#endif                                            /* NeedWidePrototypes */
{
    _XmProcessLock();
        QualifyLabelLocalCache(lw);
        local_cache.margin_right = value;
        _XmProcessUnlock();
}


void
_XmAssignLabG_MarginTop(XmLabelGadget lw,
#if NeedWidePrototypes
int value)
#else
Dimension value)
#endif                                            /* NeedWidePrototypes */
{
    _XmProcessLock();
        QualifyLabelLocalCache(lw);
        local_cache.margin_top = value;
        _XmProcessUnlock();
}


void
_XmAssignLabG_MarginBottom(XmLabelGadget lw,
#if NeedWidePrototypes
int value)
#else
Dimension value)
#endif                                            /* NeedWidePrototypes */
{
    _XmProcessLock();
        QualifyLabelLocalCache(lw);
        local_cache.margin_bottom = value;
        _XmProcessUnlock();
}


/************************************************************************
 *
 *  SetGadgetActivateCallbackState
 *
 * This function is used as the method of the menuSavvy trait. It is
 * used by menu savvy parents to set whether or not the child will
 * invoke its own activate callback or whether it will defer to the
 * entryCallback of the parent.
 *
 ************************************************************************/

static void
SetGadgetActivateCallbackState(Widget wid,
XmActivateState state)
{
    XmLabelGCacheObjPart localCache;

        _XmQualifyLabelLocalCache(&localCache, (XmLabelGadget)wid);

        switch (state)
    {
        case XmDISABLE_ACTIVATE:
            localCache.skipCallback = True;
                break;

            case XmENABLE_ACTIVATE:
            localCache.skipCallback = False;
                break;
    }

    _XmReCacheLabG_r(&localCache, (XmLabelGadget)wid);
}


/************************************************************************
 *
 *  SetOverrideCallback
 *
 * Used by subclasses.  If this is set true, then there is a RowColumn
 * parent with the entryCallback resource set.  The subclasses do not
 * do their activate callbacks, instead the RowColumn callbacks are called
 * by RowColumn.
 ************************************************************************/

/*ARGSUSED*/
static void
SetOverrideCallback(
Widget w)
{
    XmLabelGCacheObjPart localCache;

        _XmQualifyLabelLocalCache(&localCache, (XmLabelGadget)w);
        localCache.skipCallback= True;
        _XmReCacheLabG_r(&localCache, (XmLabelGadget)w);
}


/************************************************************************
 *
 *  XmCreateLabelGadget()
 *  XmVaCreateLabelGadget()
 *  XmVaCreateManagedLabelGadget()
 *
 *	Externally accessable function for creating a label gadget.
 *
 ************************************************************************/

Widget
XmCreateLabelGadget(Widget parent,
char *name,
Arg *arglist,
Cardinal argCount)
{
    return XtCreateWidget(name, xmLabelGadgetClass, parent, arglist, argCount);
}
Widget 
XmVaCreateLabelGadget(
        Widget parent,
        char *name,
        ...)
{
    register Widget w;
    va_list var;
    int count;
    
    Va_start(var,name);
    count = XmeCountVaListSimple(var);
    va_end(var);

    
    Va_start(var, name);
    w = XmeVLCreateWidget(name, 
                         xmLabelGadgetClass, 
                         parent, False, 
                         var, count);
    va_end(var);   
    return w;
    
}
Widget 
XmVaCreateManagedLabelGadget(
        Widget parent,
        char *name,
        ...)
{
    Widget w = NULL;
    va_list var;
    int count;
    
    Va_start(var, name);
    count = XmeCountVaListSimple(var);
    va_end(var);
    
    Va_start(var, name);
    w = XmeVLCreateWidget(name, 
                         xmLabelGadgetClass, 
                         parent, True, 
                         var, count);
    va_end(var);   
    return w;
    
}

/*
 *  GetLabelBGClassSecResData ()
 *    Class function to be called to copy secondary resource for external
 *  use.  i.e. copy the cached resources and send it back.
 */

/*ARGSUSED*/
static Cardinal
GetLabelBGClassSecResData(WidgetClass w_class,
XmSecondaryResourceData **data_rtn)
{
    int        arrayCount;
        XmBaseClassExt bcePtr;
        String     resource_class, resource_name;
        XtPointer  client_data;

        _XmProcessLock();
        bcePtr = &(labelBaseClassExtRec);
        client_data = NULL;
        resource_class = NULL;
        resource_name = NULL;
        arrayCount =
        _XmSecondaryResourceData(bcePtr, data_rtn, client_data,
        resource_name, resource_class,
        GetLabelClassResBase);
        _XmProcessUnlock();
        return arrayCount;
}


/*
 * GetLabelClassResBase ()
 *   retrun the address of the base of resources.
 *   - Not yet implemented.
 */

/*ARGSUSED*/
static XtPointer
GetLabelClassResBase(Widget widget,
XtPointer client_data)                            /* unused */
{
    XtPointer widgetSecdataPtr;
        int       labg_cache_size = sizeof(XmLabelGCacheObjPart);
        char     *cp;

        widgetSecdataPtr = (XtPointer) (XtMalloc (labg_cache_size +1));

        _XmProcessLock();
        if (widgetSecdataPtr)
    {
        cp = (char *) widgetSecdataPtr;
            memcpy(cp, LabG_Cache(widget), labg_cache_size);
    }

    _XmProcessUnlock();
        return widgetSecdataPtr;
}


/*ARGSUSED*/
static void
SetValuesAlmost(Widget cw,                        /* unused */
Widget nw,
XtWidgetGeometry *request,
XtWidgetGeometry *reply)
{
    XmLabelGadget new_w = (XmLabelGadget) nw;
        XtWidgetProc resize;

        _XmProcessLock();
        resize = ((XmLabelGadgetClassRec *)(new_w->object.widget_class))->
        rect_class.resize;
        _XmProcessUnlock();

        (* (resize)) ((Widget) new_w);
        *request = *reply;
}


static void
GetColors(Widget w,
XmAccessColorData color_data)
{
    if (LabG_Cache(w))
    {
        color_data->valueMask = AccessForeground | AccessBackgroundPixel |
            AccessHighlightColor | AccessTopShadowColor | AccessBottomShadowColor;
            color_data->background = LabG_Background(w);
            color_data->foreground = LabG_Foreground(w);
            color_data->highlight_color = LabG_HighlightColor(w);
            color_data->top_shadow_color = LabG_TopShadowColor(w);
            color_data->bottom_shadow_color = LabG_BottomShadowColor(w);
    }
    else
    {
        color_data->valueMask = AccessColorInvalid;
    }
}


/************************************************************************
 *
 * XmLabelGadgetGetBaselines
 *
 * A Class function which when called returns True, if the widget has
 * a baseline and also determines the number of pixels from the y
 * origin to the first line of text and assigns it to the variable
 * being passed in.
 *
 ************************************************************************/

static Boolean
XmLabelGadgetGetBaselines(Widget wid,
Dimension **baselines,
int *line_count)
{
    XmLabelGadget lw = (XmLabelGadget)wid;
        Cardinal count;
        int delta;

        if (LabG_IsPixmap(wid))
        return False;

    /* Compute raw baselines if unavailable. */
        if (lw->label.baselines == NULL)
    {
        _XmStringGetBaselines(LabG_Font(lw), LabG__label(lw),
            &(lw->label.baselines), &count);
            assert(lw->label.baselines != NULL);

        /* Store the current offset in an extra location. */
            lw->label.baselines = (Dimension*)
            XtRealloc((char*) lw->label.baselines, (count+1) * sizeof(Dimension));
            lw->label.baselines[count] = 0;
    }
    else
    {
        count = XmStringLineCount(LabG__label(lw));
    }

    /* Readjust offsets if necessary. */
    delta = LabG_TextRect_y(lw) - lw->label.baselines[count];
        if (delta)
    {
        int tmp;
            for (tmp = 0; tmp <= count; tmp++)
            lw->label.baselines[tmp] += delta;
    }

    /* Copy the cached data. */
    *line_count = count;
        *baselines = (Dimension*) XtMalloc(*line_count * sizeof(Dimension));
        memcpy((char*) *baselines, (char*) lw->label.baselines,
        *line_count * sizeof(Dimension));

        return True;
}


/************************************************************************
 *
 * XmLabelGadgetGetDisplayRect
 *
 * A Class function which returns true if the widget being passed in
 * has a display rectangle associated with it. It also determines the
 * x,y coordinates of the character cell or pixmap relative to the origin
 * and the width and height in pixels of the smallest rectangle that encloses
 * the text or pixmap. This is assigned to the variable being passed in
 *
 ***********************************************************************/

static Boolean
XmLabelGadgetGetDisplayRect(Widget w,
XRectangle *displayrect)
{
    XmLabelGadget wid = (XmLabelGadget) w;

        displayrect->x = wid->label.TextRect.x;
        displayrect->y = wid->label.TextRect.y;
        displayrect->width = wid->label.TextRect.width;
        displayrect->height = wid->label.TextRect.height;

        return TRUE;
}


/************************************************************************
 *
 * XmLabelGadgetMarginsProc
 *
 ***********************************************************************/

/* ARGSUSED */
static void
XmLabelGadgetMarginsProc(Widget w,
XmBaselineMargins *margins_rec)
{
    XmLabelGCacheObjPart localCache;

        if (margins_rec->get_or_set == XmBASELINE_SET)
    {
        _XmQualifyLabelLocalCache(&localCache, (XmLabelGadget)w);
            _XmAssignLabG_MarginTop_r((&localCache), margins_rec->margin_top);
            _XmAssignLabG_MarginBottom_r((&localCache), margins_rec->margin_bottom);
            _XmReCacheLabG_r(&localCache, (XmLabelGadget)w);
    }
    else
    {
        margins_rec->margin_top = LabG_MarginTop(w);
            margins_rec->margin_bottom = LabG_MarginBottom(w);
            margins_rec->shadow = LabG_Shadow(w);
            margins_rec->highlight = LabG_Highlight(w);
            margins_rec->text_height = LabG_TextRect_height(w);
            margins_rec->margin_height = LabG_MarginHeight(w);
    }
}


static Widget
GetPixmapDragIcon(Widget w)
{
    XmLabelGadget lw = (XmLabelGadget) w;
        Arg args[10];
        int n = 0;
        Widget drag_icon;
        Widget screen_object = XmGetXmScreen(XtScreen(w));
        unsigned int wid, hei;
        int d;

    /* it's a labelPixmap, use directly the pixmap */

        XmeGetPixmapData(XtScreen(lw), Pix(lw), NULL, &d,
        NULL, NULL, NULL, NULL, &wid, &hei);

        n = 0;
        XtSetArg(args[n], XmNhotX, 0),             n++;
        XtSetArg(args[n], XmNhotY, 0),             n++;
        XtSetArg(args[n], XmNwidth, wid),          n++;
        XtSetArg(args[n], XmNheight, hei),             n++;
        XtSetArg(args[n], XmNmaxWidth, wid),           n++;
        XtSetArg(args[n], XmNmaxHeight, hei),          n++;
        XtSetArg(args[n], XmNdepth, d),            n++;
        XtSetArg(args[n], XmNpixmap, Pix(lw)),         n++;
        XtSetArg(args[n], XmNforeground, LabG_Background(lw)), n++;
        XtSetArg(args[n], XmNbackground, LabG_Foreground(lw)), n++;
        assert(n <= XtNumber(args));
        drag_icon = XtCreateWidget("drag_icon", xmDragIconObjectClass,
        screen_object, args, n);
        return drag_icon;
}


/*ARGSUSED*/
void
_XmProcessDrag(Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
    XmLabelGadget lw = (XmLabelGadget) w;
        Widget drag_icon;
        Arg args[10];
        int n;
        XmManagerWidget mw;
        Time _time = _XmGetDefaultTime(w, event);
        XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(w));

        mw = (XmManagerWidget) XtParent(lw);

        if (LabG_IsMenupane(w))
        XAllowEvents(XtDisplay(mw), SyncPointer, _time);

    /* Disallow drag if this is a cascade button and armed - Hack alert */
        if (XmIsCascadeButtonGadget(w) && CBG_IsArmed(w)) return;

    /* CDE - allow user to not drag labels and label subclasses
       also,  disable drag if enable_btn1_transfer is set to
       BUTTON2_ADJUST and the trigger was button2 */
        if (! dpy -> display.enable_unselectable_drag ||
        (dpy -> display.enable_btn1_transfer == XmBUTTON2_ADJUST &&
        event && event -> xany.type == ButtonPress &&
        event -> xbutton.button == 2)) return;

        n = 0;
        XtSetArg(args[n], XmNcursorBackground, LabG_Background(lw)), n++;
        XtSetArg(args[n], XmNcursorForeground, LabG_Foreground(lw)), n++;

    /* If it's a labelPixmap, only specify the pixmap icon */
        if (LabG_IsPixmap(lw) && (Pix(lw) != XmUNSPECIFIED_PIXMAP))
    {
        drag_icon = GetPixmapDragIcon(w);
            XtSetArg(args[n], XmNsourcePixmapIcon, drag_icon), n++;
    }
    else
    {
        drag_icon = XmeGetTextualDragIcon(w);
            XtSetArg(args[n], XmNsourceCursorIcon, drag_icon), n++;
    }

    XtSetArg(args[n], XmNdragOperations, XmDROP_COPY), n++;
        (void) XmeDragSource(w, NULL, event, args, n);
}


/*
 * XmRCallProc routine for checking label.font before setting it to NULL
 * If "check_set_render_table" is True, then function has
 * been called twice on same widget, thus resource needs to be set NULL,
 * otherwise leave it alone.
 */

/*ARGSUSED*/
static void
CheckSetRenderTable(Widget wid,
int offset,
XrmValue *value)
{
    XmLabelGadget lw = (XmLabelGadget)wid;

    /* Check if been here before */
        if (lw->label.check_set_render_table)
        value->addr = NULL;
        else
    {
        lw->label.check_set_render_table = True;
            value->addr = (char*)&(lw->label.font);
    }
}

/**************************************************************************
 * FromPaddingPixels
 *
 * Converts from pixels to current unit type does either horiz or vert
 * depending on icon placement.
 *  widget - the icon button widget.
 *  offset, value - passed to correct function based on orientation.
 **************************************************************************/
  
static void
FromPaddingPixels(Widget widget, int offset, XtArgVal *value)
{
    switch(LabG_PixmapPlacement(widget)) {
    case XmPIXMAP_TOP:
    case XmPIXMAP_BOTTOM:
	XmeFromVerticalPixels(widget, offset, value);
	break;
    default:			/* everything else is horiz. */
	XmeFromHorizontalPixels(widget, offset, value);
	break;
    }
}
    
/**************************************************************************
 * ToPaddingPixels
 *
 * Converts from pixels to current unit type does either horiz or vert
 * depending on icon placement.
 *  widget - the icon button widget.
 *  offset, value - passed to correct function based on orientation.
 * Returns the import order from _XmTo{Horizontal, Vertical}Pixels.
 **************************************************************************/

static XmImportOperator
ToPaddingPixels(Widget widget, int offset, XtArgVal *value)
{
    switch(LabG_PixmapPlacement(widget)) {
    case XmPIXMAP_TOP:
    case XmPIXMAP_BOTTOM:
	return(XmeToVerticalPixels(widget, offset, value));
    default:
	return(XmeToHorizontalPixels(widget, offset, value));
    }
}
    

static char*
GetLabelGadgetAccelerator(Widget w)
{
    if (XtClass(w) == xmLabelGadgetClass)
        return NULL;
        else
        return LabG_Accelerator(w);
}


static KeySym
GetLabelGadgetMnemonic(Widget w)
{
    if (XtClass(w) == xmLabelGadgetClass)
        return XK_VoidSymbol;
        else
        return LabG_Mnemonic(w);
}


void
_XmQualifyLabelLocalCache(
XmLabelGCacheObjPart *local_cache,
XmLabelGadget w)
{
    _XmProcessLock();
        ClassCacheCopy(LabG_ClassCachePart(w))
        (LabG_Cache(w),
        local_cache,
        sizeof(XmLabelGCacheObjPart)
        );
        _XmProcessUnlock();
}


void
_XmReCacheLabG_r(XmLabelGCacheObjPart *local_cache, XmLabelGadget w)
{
    _XmProcessLock();
        if (!_XmLabelCacheCompare(local_cache, (XtPointer)LabG_Cache(w)))
    {
        _XmCacheDelete((XtPointer)LabG_Cache(w));
            LabG_Cache(w) = (XmLabelGCacheObjPart *)_XmCachePart(
            LabG_ClassCachePart(w),
            local_cache,
            sizeof(XmLabelGCacheObjPart));
    }
    _XmProcessUnlock();
}
