/* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */ /* * HISTORY */ #ifdef REV_INFO #ifndef lint static char rcsid[] = "$TOG: ToggleBG.c /main/46 1999/12/06 18:10:15 samborn $" #endif #endif /* (c) Copyright 1989, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */ /* (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */ #include #include "XmI.h" #include #include #include #include #include #include #include #include #include #include "BaseClassI.h" #include "CacheI.h" #include "ColorI.h" #include "ExtObjectI.h" #include "LabelGI.h" #include "LabelI.h" #include "MenuProcI.h" #include "MenuStateI.h" #include "RepTypeI.h" #include "SyntheticI.h" #include "ToggleBGI.h" #include "TravActI.h" #include "TraversalI.h" #include "UniqueEvnI.h" #define XmINVALID_TYPE 255 /* special flag for IndicatorType */ #define XmINVALID_BOOLEAN 85 /* special flag for VisibleWhenOff */ #define MIN_GLYPH_SIZE 5 /* Threshold for rendering glyphs. */ #define PixmapOn(w) (TBG_OnPixmap(w)) #define PixmapOff(w) (LabG_Pixmap(w)) #define PixmapInd(w) (TBG_IndeterminatePixmap(w)) #define PixmapInsenOn(w) (TBG_InsenPixmap(w)) #define PixmapInsenOff(w) (LabG_PixmapInsensitive(w)) #define PixmapInsenInd(w) (TBG_IndeterminateInsensitivePixmap(w)) #define IsNull(p) ((p) == XmUNSPECIFIED_PIXMAP) #define IsOn(w) (TBG_VisualSet(w)) #define IsOneOfMany(ind_type) (((ind_type) == XmONE_OF_MANY) || \ ((ind_type) == XmONE_OF_MANY_ROUND) || \ ((ind_type) == XmONE_OF_MANY_DIAMOND)) /* Constants used to decompose XmNindicatorOn values. */ #define XmINDICATOR_BOX_MASK 0x0f #define XmINDICATOR_GLYPH_MASK 0xf0 /* The indicator value should already have been normalized! */ #define DRAW3DBOX(ind_on) ((ind_on) & XmINDICATOR_3D_BOX) #define DRAWFLATBOX(ind_on) ((ind_on) & XmINDICATOR_FLAT_BOX) #define DRAWBOX(ind_on) ((ind_on) & XmINDICATOR_BOX_MASK) #define DRAWCHECK(ind_on) ((ind_on) & XmINDICATOR_CHECK_GLYPH) #define DRAWCROSS(ind_on) ((ind_on) & XmINDICATOR_CROSS_GLYPH) #define DRAWGLYPH(ind_on) ((ind_on) & XmINDICATOR_GLYPH_MASK) /******** Static Function Declarations ********/ static void ClassInitialize( void ) ; static void ClassPartInitialize( WidgetClass wc) ; static void SecondaryObjectCreate( Widget req, Widget new_w, ArgList args, Cardinal *num_args) ; static void InitializePrehook( Widget req, Widget new_w, ArgList args, Cardinal *num_args) ; static void InitializePosthook( Widget req, Widget new_w, ArgList args, Cardinal *num_args) ; int _XmToggleBCacheCompare( XtPointer A, XtPointer B ); static void InputDispatch( Widget wid, XEvent *event, Mask event_mask) ; static void SetAndDisplayPixmap( XmToggleButtonGadget w, XEvent *event, Region region) ; static void Help( XmToggleButtonGadget tb, XEvent *event) ; static void ToggleButtonCallback( XmToggleButtonGadget data, unsigned int reason, unsigned int value, XEvent *event) ; static void Leave( XmToggleButtonGadget w, XEvent *event) ; static void Enter( XmToggleButtonGadget w, XEvent *event) ; static void Arm( Widget w, XEvent *event) ; static void Select( XmToggleButtonGadget tb, XEvent *event) ; static void Disarm( XmToggleButtonGadget tb, XEvent *event) ; static void ArmAndActivate( Widget wid, XEvent *event, String *params, Cardinal *num_params) ; static void BtnDown( XmToggleButtonGadget tb, XEvent *event) ; static void BtnUp( XmToggleButtonGadget tb, XEvent *event) ; static void GetGC( XmToggleButtonGadget tw) ; static void GetUnselectGC( XmToggleButtonGadget tw) ; static void Initialize( Widget rw, Widget nw, ArgList args, Cardinal *num_args) ; static void Destroy( Widget w) ; static void DrawToggle( XmToggleButtonGadget w) ; static void BorderHighlight( Widget wid) ; static void BorderUnhighlight( Widget wid) ; static void KeySelect( XmToggleButtonGadget tb, XEvent *event) ; static void ComputeSpace( XmToggleButtonGadget tb) ; static void Redisplay( Widget w, XEvent *event, Region region) ; static void Resize( Widget w) ; 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 Boolean SetValues( Widget current, Widget request, Widget new_w, ArgList args, Cardinal *num_args) ; static Cardinal GetToggleBGClassSecResData( WidgetClass w_class, XmSecondaryResourceData **data_rtn) ; static XtPointer GetToggleBGClassSecResBase( Widget widget, XtPointer client_data) ; static void DrawToggleLabel( XmToggleButtonGadget tb) ; static void DrawEtchedInMenu( XmToggleButtonGadget tb) ; static void DrawToggleShadow( XmToggleButtonGadget tb) ; static void SetToggleSize( XmToggleButtonGadget newtbg) ; static void NextState(unsigned char *state); static void DrawBox( XmToggleButtonGadget w, GC top_gc, GC bot_gc, GC fillgc, int x, int y, int edge, Dimension margin); static Boolean HandleRedraw (Widget kid, Widget cur_parent, Widget new_parent, Mask visual_flag); static Boolean ToggleBGCVTRedraw (Widget kid, Widget cur_parent, Widget new_parent, Mask visual_flag); static void DefaultSelectColor(Widget widget, int offset, XrmValue *value); static void TBG_FixTearoff( XmToggleButtonGadget tb); static unsigned char NormalizeIndOn(XmToggleButtonGadget tb); static unsigned char NormalizeIndType(XmToggleButtonGadget tb); /******** End Static Function Declarations ********/ /*************************************<->************************************* * * * Description: resource list for class: ToggleButton * ----------- * * Provides default resource settings for instances of this class. * To get full set of default settings, examine resouce list of super * classes of this class. * *************************************<->***********************************/ #define Offset(field) XtOffsetOf(XmToggleButtonGadgetRec, field) #define CacheOffset(field) XtOffsetOf(XmToggleButtonGCacheObjRec, field) static XtResource cache_resources[] = { { XmNindicatorSize, XmCIndicatorSize, XmRVerticalDimension, sizeof(Dimension), CacheOffset(toggle_cache.indicator_dim), XmRImmediate, (XtPointer) XmINVALID_DIMENSION }, { XmNindicatorType, XmCIndicatorType, XmRIndicatorType, sizeof(unsigned char), CacheOffset(toggle_cache.ind_type), XmRImmediate, (XtPointer) XmINVALID_TYPE }, { XmNvisibleWhenOff, XmCVisibleWhenOff, XmRBoolean, sizeof(Boolean), CacheOffset(toggle_cache.visible), XmRImmediate, (XtPointer) XmINVALID_BOOLEAN }, { XmNspacing, XmCSpacing, XmRHorizontalDimension, sizeof(Dimension), CacheOffset(toggle_cache.spacing), XmRImmediate, (XtPointer) 4 }, { XmNselectPixmap, XmCSelectPixmap, XmRDynamicPixmap, sizeof(Pixmap), CacheOffset(toggle_cache.on_pixmap), XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP }, { XmNselectInsensitivePixmap, XmCSelectInsensitivePixmap, XmRDynamicPixmap, sizeof(Pixmap), CacheOffset(toggle_cache.insen_pixmap), XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP }, { XmNindicatorOn, XmCIndicatorOn, XmRIndicatorOn, sizeof(unsigned char), CacheOffset(toggle_cache.ind_on), XmRImmediate, (XtPointer) XmINDICATOR_FILL }, { XmNfillOnSelect, XmCFillOnSelect, XmRBoolean, sizeof(Boolean), CacheOffset(toggle_cache.fill_on_select), XmRImmediate, (XtPointer) XmINVALID_BOOLEAN }, { XmNselectColor, XmCSelectColor, XmRSelectColor, sizeof(Pixel), CacheOffset(toggle_cache.select_color), XmRImmediate, (XtPointer) INVALID_PIXEL }, { XmNtoggleMode, XmCToggleMode, XmRToggleMode, sizeof(unsigned char), CacheOffset(toggle_cache.toggle_mode), XmRImmediate, (XtPointer) XmTOGGLE_BOOLEAN }, { XmNindeterminatePixmap, XmCIndeterminatePixmap, XmRDynamicPixmap, sizeof(Pixmap), CacheOffset(toggle_cache.indeterminate_pixmap), XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP }, { XmNindeterminateInsensitivePixmap, XmCIndeterminateInsensitivePixmap, XmRDynamicPixmap, sizeof(Pixmap), CacheOffset(toggle_cache.indeterminate_insensitive_pixmap), XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP }, { XmNunselectColor, XmCUnselectColor, XmRPixel, sizeof(Pixel), CacheOffset(toggle_cache.unselect_color), XmRImmediate, (XtPointer) INVALID_PIXEL } }; /************************************************ * The uncached resources for ToggleButton ************************************************/ static XtResource resources[] = { { XmNset, XmCSet, XmRSet, sizeof(unsigned char), Offset(toggle.set), XmRImmediate, (XtPointer) XmUNSET }, { XmNvalueChangedCallback, XmCValueChangedCallback, XmRCallback, sizeof(XtCallbackList), Offset(toggle.value_changed_CB), XmRPointer, (XtPointer)NULL }, { XmNarmCallback, XmCArmCallback, XmRCallback, sizeof(XtCallbackList), Offset(toggle.arm_CB), XmRPointer, (XtPointer)NULL }, { XmNdisarmCallback, XmCDisarmCallback, XmRCallback, sizeof(XtCallbackList), Offset(toggle.disarm_CB), XmRPointer, (XtPointer)NULL }, { XmNtraversalOn, XmCTraversalOn, XmRBoolean, sizeof(Boolean), XtOffsetOf(struct _XmGadgetRec, gadget.traversal_on), XmRImmediate, (XtPointer) True }, { XmNhighlightThickness, XmCHighlightThickness, XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf(struct _XmGadgetRec, gadget.highlight_thickness), XmRCallProc, (XtPointer) _XmSetThickness }, { XmNdetailShadowThickness, XmCShadowThickness, XmRHorizontalDimension, sizeof (Dimension), Offset(toggle.detail_shadow_thickness), XmRCallProc, (XtPointer) _XmSetThickness } }; /* Resources that need special processing in get/set values. */ static XmSyntheticResource cache_syn_resources[] = { { XmNspacing, sizeof(Dimension), CacheOffset(toggle_cache.spacing), XmeFromHorizontalPixels, XmeToHorizontalPixels }, { XmNindicatorSize, sizeof(Dimension), CacheOffset(toggle_cache.indicator_dim), XmeFromVerticalPixels, XmeToVerticalPixels } }; static XmSyntheticResource syn_resources[] = { { XmNdetailShadowThickness, sizeof(Dimension), XtOffsetOf(XmToggleButtonGadgetRec, toggle.detail_shadow_thickness), XmeFromHorizontalPixels,XmeToHorizontalPixels } }; #undef CacheOffset #undef Offset /***************************************************************** * * Class Record definitions * ****************************************************************/ static XmCacheClassPart ToggleButtonClassCachePart = { { NULL, 0, 0 }, /* head of class cache list */ _XmCacheCopy, /* Copy routine */ _XmCacheDelete, /* Delete routine */ _XmToggleBCacheCompare, /* Comparison routine */ }; static XmBaseClassExtRec ToggleBGClassExtensionRec = { NULL, /* next_extension */ NULLQUARK, /* record_type */ XmBaseClassExtVersion, /* version */ sizeof(XmBaseClassExtRec), /* record_size */ InitializePrehook, /* initializePrehook */ SetValuesPrehook, /* setValuesPrehook */ InitializePosthook, /* initializePosthook */ SetValuesPosthook, /* setValuesPosthook */ (WidgetClass)&xmToggleButtonGCacheObjClassRec, /* secondaryObjectClass */ SecondaryObjectCreate, /* secondaryObjectCreate */ GetToggleBGClassSecResData, /* getSecResData */ { 0 }, /* Other Flags */ GetValuesPrehook, /* getValuesPrehook */ GetValuesPosthook, /* getValuesPosthook */ (XtWidgetClassProc)NULL, /* classPartInitPrehook */ (XtWidgetClassProc)NULL, /* classPartInitPosthook */ NULL, /* ext_resources */ NULL, /* compiled_ext_resources */ 0, /* num_ext_resources */ FALSE, /* use_sub_resources */ XmInheritWidgetNavigable, /* widgetNavigable */ XmInheritFocusChange, /* focusChange */ (XmWrapperData)NULL, /* wrapperData */ }; /* ext rec static initialization */ externaldef(xmtogglebuttongcacheobjclassrec) XmToggleButtonGCacheObjClassRec xmToggleButtonGCacheObjClassRec = { { /* superclass */ (WidgetClass) &xmLabelGCacheObjClassRec, /* class_name */ "XmToggleButtonGadget", /* widget_size */ sizeof(XmToggleButtonGCacheObjRec), /* class_initialize */ (XtProc)NULL, /* chained class init */ (XtWidgetClassProc)NULL, /* class_inited */ False, /* initialize */ (XtInitProc)NULL, /* initialize hook */ (XtArgsProc)NULL, /* realize */ NULL, /* actions */ NULL, /* num_actions */ 0, /* resources */ cache_resources, /* num_resources */ XtNumber(cache_resources), /* xrm_class */ NULLQUARK, /* compress_motion */ False, /* compress_exposure */ False, /* compress enter/exit*/ False, /* visible_interest */ False, /* destroy */ (XtWidgetProc)NULL, /* resize */ NULL, /* expose */ NULL, /* set_values */ (XtSetValuesFunc)NULL, /* set values hook */ (XtArgsFunc)NULL, /* set values almost */ NULL, /* get values hook */ (XtArgsProc)NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback offsetlst */ NULL, /* default trans */ NULL, /* query geo proc */ NULL, /* display accelerator*/ NULL, /* extension record */ NULL, }, { /* synthetic resources */ cache_syn_resources, /* num_syn_resources */ XtNumber(cache_syn_resources), /* extension */ NULL, } }; /*************************************<->************************************* * * * Description: global class record for instances of class: ToggleButton * ----------- * * Defines default field settings for this class record. * *************************************<->***********************************/ static XmGadgetClassExtRec _XmToggleBGadClassExtRec = { NULL, /* next_extension */ NULLQUARK, /* record_type */ XmGadgetClassExtVersion, /* version */ sizeof(XmGadgetClassExtRec), /* record_size */ XmInheritBaselineProc, /* widget_baseline */ XmInheritDisplayRectProc, /* widget_display_rect */ XmInheritMarginsProc, /* widget_margins */ }; externaldef(xmtogglebuttongadgetclassrec) XmToggleButtonGadgetClassRec xmToggleButtonGadgetClassRec = { { /* superclass */ (WidgetClass) &xmLabelGadgetClassRec, /* class_name */ "XmToggleButtonGadget", /* widget_size */ sizeof(XmToggleButtonGadgetRec), /* class_initialize */ ClassInitialize, /* class_part_init */ ClassPartInitialize, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ (XtArgsProc)NULL, /* realize */ NULL, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ XtExposeCompressMaximal, /* compress_enterlv */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ Resize, /* expose */ Redisplay, /* set_values */ SetValues, /* set_values_hook */ (XtArgsFunc)NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ (XtArgsProc)NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ NULL, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator */ NULL, /* extension */ (XtPointer)&ToggleBGClassExtensionRec }, { /* gadget class record */ /* border_highlight */ BorderHighlight, /* border_unhighlight */ BorderUnhighlight, /* arm_and_activate */ ArmAndActivate, /* input_dispatch */ InputDispatch, /* visual_change */ XmInheritVisualChange, /* syn resources */ syn_resources, /* num_syn_resources */ XtNumber(syn_resources), /* extension */ &ToggleButtonClassCachePart, /* extension */ (XtPointer)&_XmToggleBGadClassExtRec }, { /* label class record */ /* SetOverrideCallback */ XmInheritWidgetProc, /* menu proc entry */ XmInheritMenuProc, /* extension */ NULL }, { /* toggle class record */ /* extension */ NULL } }; externaldef(xmtogglebuttongadgetclass) WidgetClass xmToggleButtonGadgetClass = (WidgetClass)&xmToggleButtonGadgetClassRec; /* Menu Savvy trait record */ static XmMenuSavvyTraitRec MenuSavvyRecord = { -1, /* version */ NULL, /* disableCallback */ NULL, /* getAccelerator */ NULL, /* getMnemonic */ _XmCBNameValueChanged /* getActivateCBName */ }; /* Care about parent Visual trait record. */ static XmConst XmCareVisualTraitRec ToggleBGCVT = { 0, /* version */ HandleRedraw /* redraw */ }; /*********************************************************** * * ClassInitialize * ************************************************************/ static void ClassInitialize( void ) { Cardinal wc_num_res, sc_num_res; XtResource *merged_list; int i, j; XtResourceList uncompiled; Cardinal num; /* * Label's and Togglebutton's resource lists are being merged into one * and assigned to xmToggleButtonGCacheObjClassRec. This is for performance * reasons, since, instead of two calls to XtGetSubResources XtGetSubvaluse * and XtSetSubvalues for both the superclass and the widget class, now * we have just one call with a merged resource list. * NOTE: At this point the resource lists for Label and Togglebutton do * have unique entries, but if there are resources in the superclass * that are being overwritten by the subclass then the merged_lists * need to be created differently. */ wc_num_res = xmToggleButtonGCacheObjClassRec.object_class.num_resources; sc_num_res = xmLabelGCacheObjClassRec.object_class.num_resources; merged_list = (XtResource *) XtMalloc((sizeof(XtResource) * (wc_num_res + sc_num_res))); _XmTransformSubResources(xmLabelGCacheObjClassRec.object_class.resources, sc_num_res, &uncompiled, &num); for (i = 0; i < num; i++) merged_list[i] = uncompiled[i]; XtFree((char *)uncompiled); for (i = 0, j = num; i < wc_num_res; i++, j++) merged_list[j] = xmToggleButtonGCacheObjClassRec.object_class.resources[i]; xmToggleButtonGCacheObjClassRec.object_class.resources = merged_list; xmToggleButtonGCacheObjClassRec.object_class.num_resources = wc_num_res + sc_num_res ; ToggleBGClassExtensionRec.record_type = XmQmotif; } /************************************************************************ * * ClassPartInitialize * Set up fast subclassing for the gadget. * ***********************************************************************/ static void ClassPartInitialize( WidgetClass wc ) { _XmFastSubclassInit (wc, XmTOGGLE_BUTTON_GADGET_BIT); /* Install the menu savvy trait record, copying fields from XmLabelG */ _XmLabelGCloneMenuSavvy (wc, &MenuSavvyRecord); /* Install the careParentVisual trait for all subclasses as well. */ XmeTraitSet((XtPointer)(WidgetClass) wc, XmQTcareParentVisual, (XtPointer)&ToggleBGCVT); } /******************************************************************* * * _XmToggleBCacheCompare * *******************************************************************/ int _XmToggleBCacheCompare( XtPointer A, XtPointer B ) { XmToggleButtonGCacheObjPart *toggleB_inst = (XmToggleButtonGCacheObjPart *) A ; XmToggleButtonGCacheObjPart *toggleB_cache_inst = (XmToggleButtonGCacheObjPart *) B ; if ((toggleB_inst->ind_type == toggleB_cache_inst->ind_type) && (toggleB_inst->visible == toggleB_cache_inst->visible) && (toggleB_inst->spacing == toggleB_cache_inst->spacing) && (toggleB_inst->indicator_dim == toggleB_cache_inst->indicator_dim) && (toggleB_inst->on_pixmap == toggleB_cache_inst->on_pixmap) && (toggleB_inst->insen_pixmap == toggleB_cache_inst->insen_pixmap) && (toggleB_inst->ind_on == toggleB_cache_inst->ind_on) && (toggleB_inst->fill_on_select == toggleB_cache_inst->fill_on_select) && (toggleB_inst->select_color == toggleB_cache_inst->select_color) && (toggleB_inst->select_GC == toggleB_cache_inst->select_GC) && (toggleB_inst->unselect_GC == toggleB_cache_inst->unselect_GC) && (toggleB_inst->unselect_color == toggleB_cache_inst->unselect_color) && (toggleB_inst->indeterminate_pixmap == toggleB_cache_inst->indeterminate_pixmap) && (toggleB_inst->indeterminate_insensitive_pixmap == toggleB_cache_inst->indeterminate_insensitive_pixmap) && (toggleB_inst->indeterminate_GC == toggleB_cache_inst->indeterminate_GC) && (toggleB_inst->indeterminate_box_GC == toggleB_cache_inst->indeterminate_box_GC) && (toggleB_inst->toggle_mode == toggleB_cache_inst->toggle_mode) && (toggleB_inst->reversed_select == toggleB_cache_inst->reversed_select) && (toggleB_inst->background_gc == toggleB_cache_inst->background_gc) && (toggleB_inst->ind_left_delta == toggleB_cache_inst->ind_left_delta) && (toggleB_inst->ind_right_delta == toggleB_cache_inst->ind_right_delta) && (toggleB_inst->ind_top_delta == toggleB_cache_inst->ind_top_delta) && (toggleB_inst->ind_bottom_delta == toggleB_cache_inst->ind_bottom_delta)) return 1; else return 0; } /************************************************************************ * * 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); TBG_Cache(new_w) = &(((XmToggleButtonGCacheObject)newSec)->toggle_cache); TBG_Cache(req) = &(((XmToggleButtonGCacheObject)reqSec)->toggle_cache); /* * Since the resource lists for label and togglebutton were merged at * ClassInitialize time we need to make only one call to * XtGetSubresources() */ 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; ((XmToggleButtonGCacheObject)newSec)->ext.extensionType = XmCACHE_EXTENSION; ((XmToggleButtonGCacheObject)newSec)->ext.logicalParent = new_w; _XmPushWidgetExtData(new_w, extData, ((XmToggleButtonGCacheObject)newSec)->ext.extensionType); memcpy(reqSec, newSec, size); } /************************************************************************ * * InitializePosthook * ************************************************************************/ /* ARGSUSED */ static void InitializePrehook( Widget req, Widget new_w, ArgList args, Cardinal *num_args ) { /* CR 2990: Use XmNbuttonFontList as the default. */ if (LabG_Font(new_w) == NULL) LabG_Font(new_w) = XmeGetDefaultRenderTable (new_w, XmBUTTON_FONTLIST); } /************************************************************************ * * InitializePosthook * ************************************************************************/ /* ARGSUSED */ static void InitializePosthook( Widget req, Widget new_w, ArgList args, Cardinal *num_args ) { XmWidgetExtData ext; XmToggleButtonGadget tbw = (XmToggleButtonGadget)new_w; /* * - register parts in cache. * - update cache pointers * - and free req */ _XmProcessLock(); LabG_Cache(tbw) = (XmLabelGCacheObjPart *) _XmCachePart( LabG_ClassCachePart(tbw), (XtPointer) LabG_Cache(tbw), sizeof(XmLabelGCacheObjPart)); TBG_Cache(tbw) = (XmToggleButtonGCacheObjPart *) _XmCachePart( TBG_ClassCachePart(tbw), (XtPointer) TBG_Cache(tbw), sizeof(XmToggleButtonGCacheObjPart)); /* * 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) tbw, &ext, XmCACHE_EXTENSION); _XmExtObjFree((XtPointer) ext->widget); _XmExtObjFree((XtPointer) ext->reqWidget); _XmProcessUnlock(); XtFree( (char *) ext); } static Boolean HandleRedraw ( Widget kid, Widget cur_parent, Widget new_parent, Mask visual_flag) { Boolean redraw = False; redraw = _XmLabelGCVTRedraw (kid, cur_parent, new_parent, visual_flag); redraw = ToggleBGCVTRedraw (kid, cur_parent, new_parent, visual_flag) || redraw; if (redraw) { XtExposeProc expose; _XmProcessLock(); expose = ((XmToggleButtonGadgetClassRec *) (XtClass(kid)))->rect_class.expose; _XmProcessUnlock(); if (! XtIsRealized(kid)) return redraw; else (* (expose)) ((Widget)kid, NULL, (Region) NULL); } return False; } static Boolean ToggleBGCVTRedraw ( Widget kid, Widget cur_parent, Widget new_parent, Mask visual_flag) { XmToggleButtonGadget tw = (XmToggleButtonGadget) kid ; XmManagerWidget mw = (XmManagerWidget) new_parent; XmManagerWidget curmw = (XmManagerWidget) cur_parent; Boolean redraw = False; XmToggleButtonGCacheObjPart oldCopy; /* * For the purposes of backward compatibility the existance of * UnselectColor is obscured here. That is it is made to follow * background. * * Unless of course someone sets it. */ /* Deal with the Evil gadget cache */ _XmProcessLock(); _XmCacheCopy((XtPointer) TBG_Cache(tw), (XtPointer) &oldCopy, sizeof(XmToggleButtonGCacheObjPart)); _XmCacheDelete ((XtPointer) TBG_Cache(tw)); _XmProcessUnlock(); TBG_Cache(tw) = &oldCopy; if ((visual_flag & VisualBackgroundPixel) && (TBG_UnselectColor(tw) == curmw->core.background_pixel)) { XtReleaseGC (XtParent(tw), TBG_UnselectGC(tw)); TBG_UnselectColor(tw) = mw->core.background_pixel; GetUnselectGC(tw); redraw = True; } _XmProcessLock(); TBG_Cache(tw) = (XmToggleButtonGCacheObjPart *) _XmCachePart(TBG_ClassCachePart(tw), (XtPointer) TBG_Cache(tw), sizeof(XmToggleButtonGCacheObjPart)); _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 ) { XmToggleButtonGadget tb = (XmToggleButtonGadget) wid ; if (event_mask & XmARM_EVENT) { if (LabG_IsMenupane(tb)) BtnDown(tb, event); else Arm ((Widget) tb, event); } /* BEGIN OSF Fix pir 2097 */ else if (event_mask & XmMULTI_ARM_EVENT) { if (! LabG_IsMenupane(tb)) { Arm ((Widget) tb, event); } } /* END OSF Fix pir 2097 */ else if (event_mask & XmACTIVATE_EVENT) { if (LabG_IsMenupane(tb)) { if (event->type == ButtonRelease) BtnUp(tb, event); else /* Assume KeyPress or KeyRelease */ KeySelect (tb, event); } else { Select(tb, event); Disarm (tb, event); } } /* BEGIN OSF Fix pir 2097 */ else if (event_mask & XmMULTI_ACTIVATE_EVENT) { if (! LabG_IsMenupane(tb)) { Select(tb, event); Disarm (tb, event); } } /* END OSF Fix pir 2097 */ else if (event_mask & XmHELP_EVENT) Help (tb, event); else if (event_mask & XmENTER_EVENT) Enter (tb, event); else if (event_mask & XmLEAVE_EVENT) Leave (tb, event); else if (event_mask & XmFOCUS_IN_EVENT) (*(((XmToggleButtonGadgetClass) XtClass( tb)) ->gadget_class.border_highlight))( (Widget) tb) ; else if (event_mask & XmFOCUS_OUT_EVENT) (*(((XmToggleButtonGadgetClass) XtClass( tb)) ->gadget_class.border_unhighlight)) ( (Widget) tb) ; else if (event_mask & XmBDRAG_EVENT) _XmProcessDrag ((Widget) tb, event, NULL, NULL); } /********************************************************************* * * redisplayPixmap * does the apropriate calculations based on the toggle button's * current pixmap and calls label's Redisplay routine. * * This routine was added to fix CR 4839 and CR 4838 * D. Rand 7/6/92 * ***********************************************************************/ static void redisplayPixmap(XmToggleButtonGadget tb, XEvent *event, Region region) { Pixmap todo; unsigned int onH = 0, onW = 0; int w, h; int x, y, offset; XRectangle saved_Text; LRectangle background_box; memcpy(&saved_Text, &LabG_TextRect(tb), sizeof(XRectangle)); offset = tb->gadget.highlight_thickness + tb->gadget.shadow_thickness; x = offset + LabG_MarginWidth(tb) + LabG_MarginLeft(tb); y = offset + LabG_MarginHeight(tb) + LabG_MarginTop(tb); w = tb->rectangle.width - x - offset - LabG_MarginRight(tb) - LabG_MarginWidth(tb); ASSIGN_MAX(w, 0); h = tb->rectangle.height - y - offset - LabG_MarginBottom(tb) - LabG_MarginHeight(tb); ASSIGN_MAX(h, 0); x += tb->rectangle.x; y += tb->rectangle.y; /* CR 6023: As of release 2.0 the LabelG will clear it's own background. */ background_box.x = x; background_box.y = y; background_box.width = w; background_box.height = h; /* CR 7041: ... but not when label.fill_bg_box is False! */ if (!tb->label.fill_bg_box) XClearArea(XtDisplay(tb), XtWindow(tb), x, y, w, h, False); todo = tb->label.pixmap; if ((! XtIsSensitive((Widget) tb)) && tb->label.pixmap_insen) todo = tb->label.pixmap_insen; if (! IsNull(todo)) XmeGetPixmapData(XtScreen(tb), todo, NULL, NULL, NULL, NULL, NULL, NULL, &onW, &onH); h = (tb->rectangle.height - onH) / 2 ; LabG_TextRect_y(tb) = MAX(h, 0); LabG_TextRect_height(tb) = onH; LabG_TextRect_width(tb) = onW; _XmRedisplayLabG ((Widget) tb, event, region, &background_box); memcpy(&LabG_TextRect(tb), &saved_Text, sizeof(XRectangle)); } static void HandlePixmap(XmToggleButtonGadget tb, Pixmap pix, Pixmap insen_pix, XEvent * event, Region region) { if (XtIsSensitive((Widget) tb)) { if (! IsNull (pix)) { Pixmap tempPix = LabG_Pixmap(tb); LabG_Pixmap(tb) = pix; redisplayPixmap(tb, event, region); LabG_Pixmap(tb) = tempPix; } else redisplayPixmap(tb, event, region); } else { if (! IsNull (insen_pix)) { Pixmap tempPix = LabG_PixmapInsensitive(tb); LabG_PixmapInsensitive(tb) = insen_pix; redisplayPixmap(tb, event, region); LabG_PixmapInsensitive(tb) = tempPix; } else redisplayPixmap(tb, event, region); } } /*********************************************************************** * * SetAndDisplayPixmap * Sets the appropriate on, off pixmap in label's pixmap field and * calls label's Redisplay routine. * ***********************************************************************/ static void SetAndDisplayPixmap( XmToggleButtonGadget w, XEvent *event, Region region ) { XmToggleButtonGadget tb = (XmToggleButtonGadget) w ; if (TBG_ToggleMode(tb) == XmTOGGLE_INDETERMINATE) { if (TBG_VisualSet(tb) == XmUNSET) HandlePixmap(tb, PixmapOff(tb), PixmapInsenOff(tb), event, region); else if (TBG_VisualSet(tb) == XmSET) HandlePixmap(tb, PixmapOn(tb), PixmapInsenOn(tb), event, region); else if (TBG_VisualSet(tb) == XmINDETERMINATE) HandlePixmap(tb, PixmapInd(tb), PixmapInsenInd(tb), event, region); } else { if (IsOn (tb) == XmSET) HandlePixmap(tb, PixmapOn(tb), PixmapInsenOn(tb), event, region); else redisplayPixmap(tb, event, region); } } /************************************************************************* * * Help * This routine is called if the user has made a help selection * on the gadget. * ************************************************************************/ static void Help( XmToggleButtonGadget tb, XEvent *event ) { Boolean is_menupane = LabG_IsMenupane(tb); XmMenuSystemTrait menuSTrait; menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(tb)), XmQTmenuSystem); if (is_menupane && menuSTrait != NULL) menuSTrait->buttonPopdown(XtParent(tb), event); ToggleButtonCallback(tb, XmCR_HELP, TBG_Set(tb), event); if (is_menupane && menuSTrait != NULL) menuSTrait->reparentToTearOffShell(XtParent(tb), event); } /************************************************************************* * * ToggleButtonCallback * This is the widget's application callback routine * *************************************************************************/ static void ToggleButtonCallback( XmToggleButtonGadget data, unsigned int reason, unsigned int value, XEvent *event ) { XmToggleButtonCallbackStruct temp; temp.reason = reason; temp.set = value; temp.event = event; switch (reason) { case XmCR_VALUE_CHANGED: XtCallCallbackList ((Widget) data, TBG_ValueChangedCB(data), &temp); break; case XmCR_ARM: XtCallCallbackList ((Widget) data, TBG_ArmCB(data), &temp); break; case XmCR_DISARM: XtCallCallbackList ((Widget) data, TBG_DisarmCB(data), &temp); break; case XmCR_HELP: _XmSocorro( (Widget) data, event, NULL, NULL); break; } } static void NextState( unsigned char *state) { switch(*state) { case XmUNSET: *state = XmSET; break; case XmSET: *state = XmINDETERMINATE; break; case XmINDETERMINATE: *state = XmUNSET; break; } } /* Update the toggle after an Enter or Leave action. */ static void ActionDraw(XmToggleButtonGadget w, XEvent *event, Boolean leave) { if (TBG_Armed(w)) { /* CR 7301: We may have armed while outside the toggle. */ if (leave) TBG_VisualSet(w) = TBG_Set(w); else if (TBG_ToggleMode(w) == XmTOGGLE_INDETERMINATE) NextState(&TBG_VisualSet(w)); else IsOn(w) = !TBG_Set(w); if (TBG_IndOn(w)) DrawToggle(w); else { if (w->gadget.shadow_thickness > 0) DrawToggleShadow(w); if (TBG_FillOnSelect(w) && !LabG_IsPixmap(w)) DrawToggleLabel(w); } if (LabG_IsPixmap(w)) SetAndDisplayPixmap(w, event, NULL); } } /************************************************************************** * * Leave * This procedure is called when the mouse button is pressed and the * cursor moves out of the widget's window. This procedure is used * to change the visuals. * *************************************************************************/ static void Leave( XmToggleButtonGadget w, XEvent *event ) { if (LabG_IsMenupane(w)) { if (_XmGetInDragMode((Widget)w) && TBG_Armed(w)) { XmDisplay dpy; Boolean etched_in; dpy = (XmDisplay) XmGetXmDisplay(XtDisplayOfObject((Widget) w)); etched_in = dpy->display.enable_etched_in_menu; ((XmManagerWidget) XtParent(w))->manager.active_child = NULL; TBG_Armed(w) = FALSE; if ((etched_in) && (TBG_IndOn(w) || (!(TBG_IndOn(w)) && !(TBG_FillOnSelect(w))))) { DrawEtchedInMenu(w); if (TBG_IndOn(w)) DrawToggle(w); } XmeDrawHighlight(XtDisplay(w), XtWindow(w), LabG_BackgroundGC(w), w->rectangle.x + w->gadget.highlight_thickness, w->rectangle .y + w->gadget.highlight_thickness, w->rectangle.width - 2 * w->gadget.highlight_thickness, w->rectangle.height - 2 * w->gadget.highlight_thickness, w->gadget.shadow_thickness); if (TBG_DisarmCB(w)) { XFlush (XtDisplay (w)); ToggleButtonCallback(w, XmCR_DISARM, TBG_Set(w), event); } } } else { _XmLeaveGadget( (Widget) w, event, NULL, NULL); ActionDraw(w, event, TRUE); } } /************************************************************************** * * Enter * This procedure is called when the mouse button is pressed and the * cursor reenters the widget's window. This procedure changes the visuals * accordingly. * **************************************************************************/ static void Enter( XmToggleButtonGadget w, XEvent *event ) { XmDisplay xm_dpy = (XmDisplay) XmGetXmDisplay(XtDisplay((Widget) w)); Boolean etched_in = xm_dpy->display.enable_etched_in_menu; if (LabG_IsMenupane(w)) { if ((((ShellWidget) XtParent(XtParent(w)))->shell.popped_up) && _XmGetInDragMode((Widget)w)) { XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay((Widget) w)); Boolean etched_in = dpy->display.enable_etched_in_menu; if (TBG_Armed(w)) return; /* So KHelp event is delivered correctly */ _XmSetFocusFlag( XtParent(XtParent(w)), XmFOCUS_IGNORE, TRUE); XtSetKeyboardFocus(XtParent(XtParent(w)), (Widget)w); _XmSetFocusFlag( XtParent(XtParent(w)), XmFOCUS_IGNORE, FALSE); ((XmManagerWidget) XtParent(w))->manager.active_child = (Widget) w; TBG_Armed(w) = TRUE; if ((etched_in) && (TBG_IndOn(w) || (!(TBG_IndOn(w)) && !(TBG_FillOnSelect(w))))) { DrawEtchedInMenu(w); if (TBG_IndOn(w)) DrawToggle(w); } XmeDrawShadows (XtDisplay (w), XtWindow (w), LabG_TopShadowGC(w), LabG_BottomShadowGC(w), w->rectangle.x + w->gadget.highlight_thickness, w->rectangle.y + w->gadget.highlight_thickness, w->rectangle.width - 2 * w->gadget.highlight_thickness, w->rectangle.height - 2 * w->gadget.highlight_thickness, w->gadget.shadow_thickness, etched_in ? XmSHADOW_IN : XmSHADOW_OUT); if (TBG_ArmCB(w)) { XFlush (XtDisplay (w)); ToggleButtonCallback(w, XmCR_ARM, TBG_Set(w), event); } } } else { _XmEnterGadget( (Widget) w, event, NULL, NULL); ActionDraw(w, event, FALSE); } } /************************************************************************ * * Arm * This function processes button 1 down occuring on the togglebutton. * Mark the togglebutton as armed and display it armed. * The callbacks for XmNarmCallback are called. * ************************************************************************/ static void Arm( Widget w, XEvent *event ) { XmToggleButtonGadget tb = (XmToggleButtonGadget)w; if (TBG_ToggleMode(tb) == XmTOGGLE_INDETERMINATE) { NextState(&TBG_VisualSet(tb)); TBG_Armed(tb) = TRUE; } else { IsOn(tb) = (TBG_Set(tb) == XmSET) ? XmUNSET : XmSET; TBG_Armed(tb) = TRUE; } if (TBG_IndOn(tb)) DrawToggle((XmToggleButtonGadget) w); else { if (tb->gadget.shadow_thickness> 0) DrawToggleShadow (tb); if (TBG_FillOnSelect(w) && !LabG_IsPixmap(w)) DrawToggleLabel (tb); } if (LabG_IsPixmap(tb)) SetAndDisplayPixmap(tb, event, NULL); if (TBG_ArmCB(tb)) { XFlush(XtDisplay(tb)); ToggleButtonCallback(tb, XmCR_ARM, TBG_Set(tb), event); } } /************************************************************************ * * Select * Mark the togglebutton as unarmed (i.e. inactive). * If the button release occurs inside of the ToggleButton, the * callbacks for XmNvalueChangedCallback are called. * ************************************************************************/ static void Select( XmToggleButtonGadget tb, XEvent *event ) { static XmToggleButtonGadget prev = NULL; XmToggleButtonCallbackStruct call_value; Boolean hit; XmMenuSystemTrait menuSTrait; if ( TBG_Armed(tb) == FALSE) return; TBG_Armed(tb) = FALSE; if ((prev == tb) && (( TBG_IndType(tb) == XmONE_OF_MANY_ROUND) || ( TBG_IndType(tb) == XmONE_OF_MANY_DIAMOND) || ( TBG_IndType(tb) == XmONE_OF_MANY))) return; /* CR 8068: Verify that this is in fact a button event. */ /* CR 9181: Consider clipping when testing visibility. */ hit = (((event->xany.type == ButtonPress) || (event->xany.type == ButtonRelease)) && _XmGetPointVisibility((Widget) tb, event->xbutton.x_root, event->xbutton.y_root)); if (hit) { if (TBG_ToggleMode(tb) == XmTOGGLE_INDETERMINATE) NextState(&TBG_Set(tb)); else TBG_Set(tb) = !TBG_Set(tb); } /* CR 7803: Suppress redundant redraws. */ if (tb->toggle.set != tb->toggle.visual_set) { XtExposeProc expose; _XmProcessLock(); expose = ((XmToggleButtonGadgetClassRec *)(tb->object.widget_class))-> rect_class.expose; _XmProcessUnlock(); /* Redisplay after changing state. */ (* (expose)) ((Widget) tb, event, (Region) NULL); } if (hit) { /* UNDOING this fix ... */ /* CR 8904: Notify value_changed before entry so that state is */ /* reported correctly even if the entry callback resets it. */ menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(tb)), XmQTmenuSystem); if (menuSTrait != NULL) { call_value.reason = XmCR_VALUE_CHANGED; call_value.event = event; call_value.set = TBG_Set(tb); menuSTrait->entryCallback(XtParent(tb), (Widget) tb, &call_value); } if ((! LabG_SkipCallback(tb)) && (TBG_ValueChangedCB(tb))) { XFlush(XtDisplay(tb)); ToggleButtonCallback(tb, XmCR_VALUE_CHANGED, TBG_Set(tb), event); } } prev = tb; } /********************************************************************** * * Disarm * The callbacks for XmNdisarmCallback are called.. * ************************************************************************/ static void Disarm( XmToggleButtonGadget tb, XEvent *event ) { if (TBG_DisarmCB(tb)) ToggleButtonCallback(tb, XmCR_DISARM, TBG_Set(tb), event); if (tb->toggle.set != tb->toggle.visual_set) Redisplay((Widget) tb, event, (Region) NULL); } static void TBG_FixTearoff( XmToggleButtonGadget tb) { if (XmMENU_PULLDOWN == LabG_MenuType(tb)) { Widget mwid = XmGetPostedFromWidget(XtParent(tb)); if (mwid && XmIsRowColumn(mwid) && (XmMENU_OPTION == RC_Type(mwid)) && _XmIsActiveTearOff(XtParent(tb))) XmProcessTraversal((Widget) tb, XmTRAVERSE_CURRENT); } } /************************************************************************ * * ArmAndActivate * This routine arms and activates a ToggleButton. It is called on * Return and a Space, as well as when a mnemonic or * button accelerator has been activated. * Modify: Current implementation does care to draw shadows if indicator * is set to false; This is being modified. ************************************************************************/ /*ARGSUSED*/ static void ArmAndActivate( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params ) /* unused */ { XmToggleButtonGadget tb = (XmToggleButtonGadget) wid ; XmToggleButtonCallbackStruct call_value; Boolean already_armed = TBG_Armed(tb); Boolean is_menupane = LabG_IsMenupane(tb); Boolean torn_has_focus = FALSE; XmMenuSystemTrait menuSTrait; menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(wid)), XmQTmenuSystem); if (is_menupane && !XmIsMenuShell(XtParent(XtParent(tb))) && menuSTrait != NULL) { if (XmeFocusIsInShell((Widget)tb)) { /* In case allowAcceleratedInsensitiveUnmanagedMenuItems is True */ if (!XtIsSensitive((Widget)tb) || (!XtIsManaged((Widget)tb))) return; torn_has_focus = TRUE; } } TBG_Armed(tb) = FALSE; if (TBG_ToggleMode(tb) == XmTOGGLE_INDETERMINATE) { NextState(&TBG_VisualSet(tb)); NextState(&TBG_Set(tb)); } else { TBG_Set(tb) = (TBG_Set(tb) == TRUE) ? FALSE : TRUE; IsOn(tb) = TBG_Set(tb); } if (is_menupane && menuSTrait != NULL) { /* CR 7799: Torn off menus shouldn't be shared, so don't reparent. */ if (torn_has_focus) menuSTrait->popdown(XtParent(tb), event); else menuSTrait->buttonPopdown(XtParent(tb), event); if (torn_has_focus) XmProcessTraversal((Widget) tb, XmTRAVERSE_CURRENT); /* Draw the toggle indicator in case of tear off */ if (TBG_IndOn(tb)) DrawToggle(tb); else if (TBG_FillOnSelect(tb) && !LabG_IsPixmap(tb)) DrawToggleLabel (tb); if (LabG_IsPixmap(tb)) SetAndDisplayPixmap(tb, NULL, NULL); } else { if (TBG_IndOn(tb)) DrawToggle(tb); else { if (tb->gadget.shadow_thickness> 0) DrawToggleShadow (tb); if (TBG_FillOnSelect(tb) && !LabG_IsPixmap(tb)) DrawToggleLabel (tb); } if (LabG_IsPixmap(tb)) SetAndDisplayPixmap(tb, event, NULL); } /* If the parent is menu system able, set the lastSelectToplevel before * the arm. It's ok if this is recalled later. */ if (menuSTrait != NULL) menuSTrait->getLastSelectToplevel(XtParent(tb)); if (TBG_ArmCB(tb) && !already_armed) ToggleButtonCallback(tb, XmCR_ARM, TBG_Set(tb), event); /* UNDOING this fix ... */ /* CR 8904: Notify value_changed before entry so that state is */ /* reported correctly even if the entry callback resets it. */ /* if the parent is menu system able, notify it about the select */ if (menuSTrait != NULL) { call_value.reason = XmCR_VALUE_CHANGED; call_value.event = event; call_value.set = TBG_Set(tb); menuSTrait->entryCallback(XtParent(tb), (Widget) tb, &call_value); } if ((! LabG_SkipCallback(tb)) && (TBG_ValueChangedCB(tb))) { XFlush(XtDisplay(tb)); ToggleButtonCallback(tb, XmCR_VALUE_CHANGED, TBG_Set(tb), event); } if (TBG_DisarmCB(tb)) { XFlush(XtDisplay(tb)); ToggleButtonCallback(tb, XmCR_DISARM, TBG_Set(tb), event); } if (is_menupane && menuSTrait != NULL) { if (torn_has_focus && XtIsSensitive(wid)) { TBG_Armed(tb) = TRUE; if (TBG_ArmCB(tb)) { XFlush(XtDisplay(tb)); ToggleButtonCallback(tb, XmCR_ARM, TBG_Set(tb), event); } } else { menuSTrait->reparentToTearOffShell(XtParent(tb), event); TBG_FixTearoff(tb); } } } /************************************************************************ * * BtnDown * This function processes a button down occuring on the togglebutton * when it is in a popup, pulldown, or option menu. * Popdown the posted menu. * Turn parent's traversal off. * Mark the togglebutton as armed (i.e. active). * The callbacks for XmNarmCallback are called. * ************************************************************************/ static void BtnDown( XmToggleButtonGadget tb, XEvent *event ) { Boolean already_armed; ShellWidget popup; XmMenuSystemTrait menuSTrait; XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(tb)); Boolean etched_in = dpy->display.enable_etched_in_menu; menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(tb)), XmQTmenuSystem); if (menuSTrait == NULL) return; _XmSetInDragMode((Widget)tb, True); /* Popdown other popups that may be up */ if (!(popup = (ShellWidget)_XmGetRC_PopupPosted(XtParent(tb)))) { if (!XmIsMenuShell(XtParent(XtParent(tb)))) { /* In case tear off not armed and no grabs in place, do it now. * Ok if already armed and grabbed - nothing done. */ menuSTrait->tearOffArm(XtParent(tb)); } } if (popup) { if (popup->shell.popped_up) menuSTrait->popdownEveryone((Widget) popup, event); } /* Set focus to this button. This must follow the possible * unhighlighting of the CascadeButton else it'll screw up active_child. */ (void)XmProcessTraversal( (Widget) tb, XmTRAVERSE_CURRENT); /* get the location cursor - get consistent with Gadgets */ already_armed = TBG_Armed(tb); TBG_Armed(tb) = TRUE; if ((etched_in) && (TBG_IndOn(tb) || (!(TBG_IndOn(tb)) && !(TBG_FillOnSelect(tb))))) { DrawEtchedInMenu(tb); if (TBG_IndOn(tb)) DrawToggle(tb); } XmeDrawShadows (XtDisplay (tb), XtWindow (tb), LabG_TopShadowGC(tb), LabG_BottomShadowGC(tb), tb->rectangle.x + tb->gadget.highlight_thickness, tb->rectangle.y + tb->gadget.highlight_thickness, tb->rectangle.width - 2 * tb->gadget.highlight_thickness, tb->rectangle.height - 2 * tb->gadget.highlight_thickness, tb->gadget.shadow_thickness, etched_in ? XmSHADOW_IN : XmSHADOW_OUT); if (TBG_ArmCB(tb) && !already_armed) { XFlush (XtDisplay (tb)); ToggleButtonCallback(tb, XmCR_ARM, TBG_Set(tb), event); } _XmRecordEvent (event); } /************************************************************************ * * BtnUp * This function processes a button up occuring on the togglebutton * when it is in a popup, pulldown, or option menu. * Mark the togglebutton as unarmed (i.e. inactive). * The callbacks for XmNvalueChangedCallback are called. * The callbacks for XmNdisarmCallback are called. * ************************************************************************/ static void BtnUp( XmToggleButtonGadget tb, XEvent *event ) { XmToggleButtonCallbackStruct call_value; Boolean popped_up; Boolean valid_event; Boolean is_menupane = LabG_IsMenupane(tb); Widget shell = XtParent(XtParent(tb)); XmMenuSystemTrait menuSTrait; menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(tb)), XmQTmenuSystem); if (menuSTrait == NULL) return; TBG_Armed(tb) = FALSE; /* We need to validate the event in case the XmMENU_POPDOWN restores the * submenu to the transient shell. The tear off control becomes unmanaged * and the submenu's (and menu item children) layout/geometry changes. */ /* CR 9181: Consider clipping when testing visibility. */ valid_event = (((event->xany.type == ButtonPress) || (event->xany.type == ButtonRelease)) && _XmGetPointVisibility((Widget)tb, event->xbutton.x_root, event->xbutton.y_root)); if (is_menupane && !XmIsMenuShell(shell)) popped_up = menuSTrait->popdown((Widget) tb, event); else popped_up = menuSTrait->buttonPopdown((Widget) tb, event); _XmRecordEvent(event); if (popped_up) return; if (valid_event) { if (TBG_ToggleMode(tb) == XmTOGGLE_INDETERMINATE) { NextState(&TBG_VisualSet(tb)); NextState(&TBG_Set(tb)); } else { TBG_Set(tb) = (TBG_Set(tb) == TRUE) ? FALSE : TRUE; IsOn(tb) = TBG_Set(tb); } /* UNDOING this fix ... */ /* CR 8904: Notify value_changed before entry so that state is */ /* reported correctly even if the entry callback resets it. */ /* notify the parent about the select */ call_value.reason = XmCR_VALUE_CHANGED; call_value.event = event; call_value.set = TBG_Set(tb); menuSTrait->entryCallback(XtParent(tb), (Widget) tb, &call_value); if ((! LabG_SkipCallback(tb)) && (TBG_ValueChangedCB(tb))) { XFlush(XtDisplay(tb)); ToggleButtonCallback(tb, XmCR_VALUE_CHANGED, TBG_Set(tb), event); } if (TBG_DisarmCB(tb)) ToggleButtonCallback(tb, XmCR_DISARM, TBG_Set(tb), event); /* If the original shell does not indicate an active menu, but rather a * tear off pane, leave the button in an armed state. */ if (!XmIsMenuShell(shell)) { if (XtIsSensitive((Widget)tb)) { TBG_Armed(tb) = TRUE; if (TBG_IndOn(tb)) DrawToggle(tb); else if (TBG_FillOnSelect(tb) && !LabG_IsPixmap(tb)) DrawToggleLabel (tb); if (LabG_IsPixmap(tb)) SetAndDisplayPixmap( tb, event, NULL); if (TBG_ArmCB(tb)) { XFlush(XtDisplay(tb)); ToggleButtonCallback(tb, XmCR_ARM, TBG_Set(tb), event); } } } else menuSTrait->reparentToTearOffShell(XtParent(tb), event); } _XmSetInDragMode((Widget)tb, False); /* For the benefit of tear off menus, we must set the focus item * to this button. In normal menus, this would not be a problem * because the focus is cleared when the menu is unposted. */ if (!XmIsMenuShell(shell)) XmProcessTraversal((Widget) tb, XmTRAVERSE_CURRENT); TBG_FixTearoff(tb); } /************************************************************************ * * GetUnselectGC * Get the graphics context to be used to fill the interior of * a square or diamond when unselected. * ************************************************************************/ static void GetUnselectGC( XmToggleButtonGadget tw ) { XGCValues values; XtGCMask valueMask; valueMask = GCForeground | GCBackground | GCFillStyle | GCGraphicsExposures; values.foreground = TBG_UnselectColor(tw); values.background = LabG_Background(tw); values.fill_style = FillSolid; values.graphics_exposures = FALSE; TBG_UnselectGC(tw) = XtGetGC((Widget) tw, valueMask, &values); } /************************************************************************ * * GetGC * Get the graphics context to be used to fill the interior of * a square or diamond when selected, and the arm GC used in a * menu if enableEtchedInMenu is True. * ************************************************************************/ static void GetGC( XmToggleButtonGadget tw ) { XmManagerWidget mw = (XmManagerWidget) XtParent(tw); XGCValues values; XtGCMask valueMask; XFontStruct *fs = (XFontStruct *) NULL; Pixel sel_color, select_pixel; XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay((Widget) tw)); Boolean etched_in = dpy->display.enable_etched_in_menu; /* Differentiate background and select colors on monochrome displays or ** others on which we have indistinguishable colors. */ if ((DefaultDepthOfScreen (XtScreen (tw)) == 1) || (LabG_Background(tw) == TBG_SelectColor(tw))) sel_color = LabG_Foreground(tw); else sel_color = TBG_SelectColor(tw); valueMask = 0; valueMask |= GCForeground, values.foreground = sel_color; valueMask |= GCBackground, values.background = LabG_Background(tw); valueMask |= GCFillStyle, values.fill_style = FillSolid; valueMask |= GCGraphicsExposures, values.graphics_exposures = FALSE; TBG_SelectGC(tw) = XtAllocateGC((Widget) mw, 0, valueMask, &values, 0, 0); /* When foreground and select colors coincide, this GC is used * by XmLabel to draw the text. It requires a font to pacify * the XmString draw functions. */ valueMask = 0; if (XmeRenderTableGetDefaultFont(LabG_Font(tw), &fs)) valueMask |= GCFont, values.font = fs->fid; valueMask |= GCForeground, values.foreground = LabG_Background(tw); valueMask |= GCBackground, values.background = LabG_Foreground(tw); valueMask |= GCFillStyle, values.fill_style = FillSolid; valueMask |= GCGraphicsExposures, values.graphics_exposures = FALSE; valueMask |= GCLineWidth, values.line_width = 1; TBG_BackgroundGC(tw) = XtGetGC((Widget) mw, valueMask, &values); valueMask = 0; valueMask |= GCFillStyle, values.fill_style = FillOpaqueStippled; valueMask |= GCGraphicsExposures, values.graphics_exposures = FALSE; valueMask |= GCStipple, values.stipple = XmGetPixmapByDepth(XtScreen((Widget)(tw)), XmS50_foreground, 1, 0, 1); valueMask |= GCLineWidth, values.line_width = 1; TBG_IndeterminateGC(tw) = XtAllocateGC((Widget) tw, 0, valueMask, &values, GCForeground | GCBackground, 0); /* The valueMask and values are inherited from above. */ valueMask &= ~GCLineWidth; valueMask |= GCForeground, values.foreground = LabG_Background(tw); valueMask |= GCBackground, values.background = LabG_Foreground(tw); TBG_IndeterminateBoxGC(tw) = XtGetGC((Widget) tw, valueMask, &values); /* Create the ArmGC for filling in background if we are in a menu and enableEtchedInMenu is True. */ if ((LabG_IsMenupane(tw)) && etched_in) { Widget wid = (Widget) XtParent(tw); XmGetColors(XtScreen(wid), wid->core.colormap, wid->core.background_pixel, NULL, NULL, NULL, &select_pixel); valueMask = 0; valueMask |= GCForeground, values.foreground = select_pixel; valueMask |= GCBackground, values.background = LabG_Foreground(tw); if (fs != NULL) valueMask |= GCFont, values.font = fs->fid; valueMask |= GCGraphicsExposures, values.graphics_exposures = FALSE; TBG_ArmGC(tw) = XtGetGC((Widget) tw, valueMask, &values); } } /*************************************<->************************************* * * Initialize * If the rectangle height and width fields are set to 0, treat that as a * flag, and compute the optimum size for this button. Then using what ever * the rectangle fields are set to, compute the text placement fields. *************************************<->***********************************/ /*ARGSUSED*/ static void Initialize( Widget rw, Widget nw, ArgList args, /* unused */ Cardinal *num_args ) /* unused */ { XmToggleButtonGadget request = (XmToggleButtonGadget) rw ; XmToggleButtonGadget new_w = (XmToggleButtonGadget) nw ; XtWidgetProc resize; TBG_Armed(new_w) = FALSE; /* if menuProcs is not set up yet, try again */ _XmProcessLock(); resize = xmLabelGadgetClassRec.rect_class.resize; if (xmLabelGadgetClassRec.label_class.menuProcs == (XmMenuProc)NULL) xmLabelGadgetClassRec.label_class.menuProcs = (XmMenuProc) _XmGetMenuProcContext(); _XmProcessUnlock(); if (LabG_IsMenupane(new_w)) { /* If the shadow thickness hasn't been set yet, inherit it from the menu parent, instead of a hard-coded 2, as before. The only draw back is that is the parent has also 0, then the toggle shadow is 0, which is not very good in a menu, but at least consistent with the other buttons */ if (new_w->gadget.shadow_thickness <= 0) { Dimension parent_st ; XtVaGetValues(XtParent(nw), XmNshadowThickness, &parent_st, NULL); new_w->gadget.shadow_thickness = parent_st; } if (TBG_Visible(new_w) == XmINVALID_BOOLEAN) TBG_Visible(new_w) = FALSE; new_w->gadget.traversal_on = TRUE; } else { if (TBG_Visible(new_w) == XmINVALID_BOOLEAN) TBG_Visible(new_w) = TRUE; } /* * if the indicatorType has not been set, then * find out if radio behavior is set for RowColumn parents and * then set indicatorType. If radio behavior is true, default to * one of many, else default to n of many. */ if ((TBG_IndType( new_w) == XmINVALID_TYPE) || !XmRepTypeValidValue(XmRID_INDICATOR_TYPE, TBG_IndType( new_w), (Widget) new_w)) { Boolean radio = FALSE; if (XmIsRowColumn(XtParent(new_w))) { XtVaGetValues(XtParent(new_w), XmNradioBehavior, &radio, NULL); } if (radio) TBG_IndType(new_w) = XmONE_OF_MANY; else TBG_IndType(new_w) = XmN_OF_MANY; } /* * This resource defaults to true if an indicator box is drawn. */ if (TBG_FillOnSelect(new_w) == XmINVALID_BOOLEAN) { if (DRAWBOX(NormalizeIndOn(new_w))) TBG_FillOnSelect(new_w) = True; else if (IsOneOfMany(TBG_IndType(new_w)) && TBG_IndOn(new_w)) TBG_FillOnSelect(new_w) = True; else TBG_FillOnSelect(new_w) = False; } /* Tristate buttons ain't allowed in one-of-many land. */ if (IsOneOfMany(TBG_IndType(new_w))) TBG_ToggleMode(new_w) = XmTOGGLE_BOOLEAN; /* Use the On pixmaps if there are no indeterminate pixmaps. */ if (IsNull(PixmapInd(new_w)) && !IsNull(PixmapOn(new_w))) PixmapInd(new_w) = PixmapOn(new_w); if (IsNull(PixmapInsenInd(new_w)) && !IsNull(PixmapInsenOn(new_w))) PixmapInsenInd(new_w) = PixmapInsenOn(new_w); /* Use the On pixmap if no Off pixmap is available. */ if (IsNull(PixmapOff(new_w)) && !IsNull(PixmapOn(new_w))) { PixmapOff(new_w) = PixmapOn(new_w); if (request->rectangle.width == 0) new_w->rectangle.width = 0; if (request->rectangle.height == 0) new_w->rectangle.height = 0; _XmCalcLabelGDimensions(nw); (* resize)( (Widget) new_w); } /* Use the insensitive On pixmap if there is no insensitive Off pixmap. */ if (IsNull(PixmapInsenOff(new_w)) && !IsNull(PixmapInsenOn(new_w))) { PixmapInsenOff(new_w) = PixmapInsenOn(new_w); if (request->rectangle.width == 0) new_w->rectangle.width = 0; if (request->rectangle.height == 0) new_w->rectangle.height = 0; _XmCalcLabelGDimensions(nw); (* resize)( (Widget) new_w); } /* BEGIN OSF Fix pir 1778 */ if (LabG_IsPixmap(new_w) && (!IsNull(PixmapOff(new_w)) || !IsNull(PixmapInsenOff(new_w)) || !IsNull(PixmapOn(new_w)) || !IsNull(PixmapInsenOn(new_w)) || !IsNull(PixmapInd(new_w)) || !IsNull(PixmapInsenInd(new_w)))) { if (request->rectangle.width == 0) new_w->rectangle.width = 0; if (request->rectangle.height == 0) new_w->rectangle.height = 0; SetToggleSize(new_w); } /* END OSF Fix pir 1778 */ if (TBG_IndicatorDim(new_w) == XmINVALID_DIMENSION) { if (TBG_IndOn(new_w)) { /* Determine how high the toggle indicator should be. */ if LabG_IsPixmap(new_w) { /* Set indicatorSize proportional to size of pixmap. */ if (!IsNull(PixmapOff(new_w)) || !IsNull(PixmapInsenOff(new_w)) || !IsNull(PixmapOn(new_w)) || !IsNull(PixmapInsenOn(new_w)) || !IsNull(PixmapInd(new_w)) || !IsNull(PixmapInsenInd(new_w))) if (LabG_TextRect(new_w).height < 13) TBG_IndicatorDim(new_w) = LabG_TextRect(new_w).height; else TBG_IndicatorDim(new_w) = 13 + (LabG_TextRect(new_w).height/13); else TBG_IndicatorDim(new_w) = XmDEFAULT_INDICATOR_DIM; } else /* Set indicatorSize proportional to size of font. */ { Dimension height; int line_count; height = XmStringHeight (LabG_Font(new_w), LabG__label(new_w)); if ((line_count = XmStringLineCount (LabG__label(new_w))) < 1) line_count = 1; /* Shiz recommends toggles in menus have smaller indicators */ if (LabG_IsMenupane(new_w)) TBG_IndicatorDim(new_w) = MAX(XmDEFAULT_INDICATOR_DIM, (height / ((Dimension)line_count)) * 2/3); else TBG_IndicatorDim(new_w) = MAX(XmDEFAULT_INDICATOR_DIM, height / ((Dimension)line_count)); } } else { TBG_IndicatorDim(new_w) = 0; } TBG_IndicatorSet(new_w) = FALSE; } else { TBG_IndicatorSet(new_w) = TRUE; } /* CR 2337: Maintain original margin values. */ TBG_IndLeftDelta(new_w) = 0; TBG_IndRightDelta(new_w) = 0; TBG_IndTopDelta(new_w) = 0; TBG_IndBottomDelta(new_w) = 0; if (TBG_IndOn(new_w)) { /* * Enlarge the text rectangle if needed to accomodate the size of * indicator button. Adjust the dimensions of superclass Label-Gadget * so that the toggle-button may be accommodated in it. */ int maxIndicatorSize; /* Max Indicator size permissible */ int delta; int boxSize; /* BEGIN OSF Fix pir 2480 */ if (! LabG_IsMenupane(new_w)) maxIndicatorSize = TBG_IndicatorDim(new_w) + 2 * Xm3D_ENHANCE_PIXEL; else maxIndicatorSize = TBG_IndicatorDim(new_w); /* END OSF Fix pir 2480 */ boxSize = ((int) LabG_TextRect(new_w).height + (int) LabG_MarginTop (new_w) + (int) LabG_MarginBottom (new_w)); if (maxIndicatorSize > boxSize) { delta = (maxIndicatorSize - boxSize) / 2; TBG_IndTopDelta(new_w) = delta; LabG_MarginTop(new_w) += delta; TBG_IndBottomDelta(new_w) = delta; LabG_MarginBottom(new_w) += delta; } /* CR 2337: Make room for toggle indicator and spacing */ if (LayoutIsRtoLG(new_w)) { delta = (TBG_IndicatorDim(new_w) + TBG_Spacing(new_w) - LabG_MarginRight(new_w)); if (delta > 0) { TBG_IndRightDelta(new_w) = delta; LabG_MarginRight(new_w) += delta; } } else { delta = (TBG_IndicatorDim(new_w) + TBG_Spacing(new_w) - LabG_MarginLeft(new_w)); if (delta > 0) { TBG_IndLeftDelta(new_w) = delta; LabG_MarginLeft(new_w) += delta; } } } if (request->rectangle.width == 0) { new_w->rectangle.width = LabG_TextRect(new_w).width + 2 * LabG_MarginHeight(new_w) + LabG_MarginRight(new_w) + LabG_MarginLeft(new_w) + 2 * (new_w->gadget.highlight_thickness + new_w->gadget.shadow_thickness); if (new_w->rectangle.width == 0) new_w->rectangle.width = 1; if ((LabG__acceleratorText(new_w) != NULL) && (TBG_IndOn(new_w))) if (LayoutIsRtoLG(new_w)) LabG_AccTextRect(new_w).x = new_w->gadget.highlight_thickness + new_w->gadget.shadow_thickness + LabG_MarginHeight(new_w); else LabG_AccTextRect(new_w).x = new_w->rectangle.width - new_w->gadget.highlight_thickness - new_w->gadget.shadow_thickness - LabG_MarginHeight(new_w) - LabG_MarginRight(new_w) + LABELG_ACC_PAD; } if (request->rectangle.height == 0) new_w->rectangle.height = MAX(TBG_IndicatorDim(new_w), LabG_TextRect(new_w).height + 2 * LabG_MarginHeight(new_w) + LabG_MarginTop(new_w) + LabG_MarginBottom(new_w)) + 2 * (new_w->gadget.highlight_thickness + new_w->gadget.shadow_thickness); LabG_TextRect(new_w).y = new_w->gadget.highlight_thickness + new_w->gadget.shadow_thickness + LabG_MarginHeight(new_w) + LabG_MarginTop(new_w) + ((new_w->rectangle.height - LabG_MarginTop(new_w) - LabG_MarginBottom(new_w) - (2 * (LabG_MarginHeight(new_w) + new_w->gadget.highlight_thickness + new_w->gadget.shadow_thickness)) - LabG_TextRect(new_w).height) / 2); if (new_w->rectangle.height == 0) new_w->rectangle.height = 1; /* Display toggles as set if XmNset is True initially. */ IsOn(new_w) = TBG_Set(new_w); /* BEGIN OSF Fix pir 2097 */ new_w->gadget.event_mask = XmARM_EVENT | XmACTIVATE_EVENT | XmMULTI_ARM_EVENT | XmMULTI_ACTIVATE_EVENT | XmHELP_EVENT | XmFOCUS_IN_EVENT | XmFOCUS_OUT_EVENT | XmENTER_EVENT | XmLEAVE_EVENT | XmBDRAG_EVENT; /* END OSF Fix pir 2097 */ (* (resize)) ((Widget) new_w); /* Unselect same as background unless set. */ if (TBG_UnselectColor(new_w) == INVALID_PIXEL) TBG_UnselectColor(new_w) = LabG_Background(new_w); TBG_ReversedSelect(new_w) = (TBG_SelectColor(new_w) == XmREVERSED_GROUND_COLORS); if ((TBG_SelectColor(new_w) == INVALID_PIXEL) || (TBG_SelectColor(new_w) == XmDEFAULT_SELECT_COLOR)) { XrmValue value; value.size = sizeof(Pixel); DefaultSelectColor((Widget) new_w, XtOffsetOf(XmToggleButtonGCacheObjRec, toggle_cache.select_color), &value); memcpy((char*) &TBG_SelectColor(new_w), value.addr, value.size); } else if (TBG_SelectColor(new_w) == XmREVERSED_GROUND_COLORS) { TBG_SelectColor(new_w) = LabG_Foreground(new_w); } else if (TBG_SelectColor(new_w) == XmHIGHLIGHT_COLOR) { TBG_SelectColor(new_w) = LabG_HighlightColor(new_w); } GetGC (new_w); GetUnselectGC(new_w); } /************************************************************************ * * Destroy * Free toggleButton's graphic context. * ************************************************************************/ static void Destroy( Widget w ) { XmToggleButtonGadget tw = (XmToggleButtonGadget) w; XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(w)); Boolean etched_in = dpy->display.enable_etched_in_menu; XtReleaseGC (XtParent(tw), TBG_SelectGC(tw)); XtReleaseGC (XtParent(tw), TBG_BackgroundGC(tw)); XtReleaseGC (XtParent(tw), TBG_UnselectGC(tw)); XtReleaseGC (XtParent(tw), TBG_IndeterminateGC(tw)); XtReleaseGC (XtParent(tw), TBG_IndeterminateBoxGC(tw)); if (LabG_IsMenupane(tw) && etched_in) XtReleaseGC ((Widget) tw, TBG_ArmGC(tw)); _XmProcessLock(); _XmCacheDelete( (XtPointer) TBG_Cache(tw)); _XmProcessUnlock(); } static void DrawBox(XmToggleButtonGadget w, GC top_gc, GC bot_gc, GC fillgc, int x, int y, int edge, Dimension margin) { int shadow = w->toggle.detail_shadow_thickness; XmeDrawShadows(XtDisplay ((Widget) w), XtWindow ((Widget) w), top_gc, bot_gc, x, y, edge, edge, shadow, XmSHADOW_OUT); /* Don't fill the background on mono screens if we're going to */ /* draw a glyph */ if (DefaultDepthOfScreen(XtScreen(w)) == 1 && DRAWGLYPH(NormalizeIndOn(w))) return; shadow += margin; if (edge > (shadow * 2)) XFillRectangle (XtDisplay ((Widget) w), XtWindow ((Widget) w), fillgc, x + shadow, y + shadow, edge - (shadow * 2), edge - (shadow * 2)); } /*************************************<->************************************* * * DrawToggle * Depending on the state of this widget, draw the ToggleButton. * *************************************<->***********************************/ static void DrawToggle( XmToggleButtonGadget w ) { int x, y, edge; Dimension margin; XGCValues values; Display *dpy = XtDisplay((Widget) w); Drawable drawable = XtWindow(XtParent((Widget) w)); XmDisplay dpyxm = (XmDisplay) XmGetXmDisplay(XtDisplay(w)); Boolean etched_in = dpyxm->display.enable_etched_in_menu; if (LabG_IsPixmap(w) || XmStringEmpty(LabG__label(w))) edge = TBG_IndicatorDim(w); else edge = MIN((int)TBG_IndicatorDim(w), MAX(0, (int)w->rectangle.height - 2 * (w->gadget.highlight_thickness + w->gadget.shadow_thickness + (int)LabG_MarginHeight(w)) + LabG_MarginTop(w) + LabG_MarginBottom(w))); if ((DefaultDepthOfScreen(XtScreen(w)) > 1) && (LabG_TopShadowColor(w) != TBG_SelectColor(w)) && (LabG_BottomShadowColor (w)!= TBG_SelectColor(w))) margin = 0; else margin = 1; if (LayoutIsRtoLG(w)) x = w->rectangle.x + w->rectangle.width - w->gadget.highlight_thickness - w->gadget.shadow_thickness - LabG_MarginHeight(w) - TBG_IndicatorDim(w); else x = w->rectangle.x + w->gadget.highlight_thickness + w->gadget.shadow_thickness + LabG_MarginHeight(w); if (LabG_IsPixmap(w) || XmStringEmpty(LabG__label(w))) y = w->rectangle.y + (int)((w->rectangle.height - TBG_IndicatorDim(w)))/2; else { int fudge = Xm3D_ENHANCE_PIXEL; y = w->rectangle.y + LabG_TextRect(w).y; if (LabG_IsMenupane(w)) y += (TBG_IndicatorDim(w) + 2) / 4; /* adjust in menu */ /* CR 2337: Keep large indicators inside the toggle. */ /* Is this definition of fudge right??? */ if (TBG_IndTopDelta(w) > fudge) y -= (TBG_IndTopDelta(w) - fudge); } if (TBG_Visible(w) || (IsOn(w) == XmSET)) { /* The toggle indicator should be visible. */ GC top_gc, bot_gc, fill_gc, glyph_gc; unsigned char normal_ind_on = NormalizeIndOn(w); switch (TBG_VisualSet(w)) { case XmUNSET: top_gc = LabG_TopShadowGC(w); bot_gc = LabG_BottomShadowGC(w); /* use the arm GC in a menu if armed and enableEtchedInMenu is set */ if (LabG_IsMenupane(w) && etched_in && TBG_Armed(w)) fill_gc = (TBG_FillOnSelect(w) ? TBG_UnselectGC(w) : TBG_ArmGC(w)); else fill_gc = (TBG_FillOnSelect(w) ? TBG_UnselectGC(w) : LabG_BackgroundGC(w)); glyph_gc = None; break; case XmSET: top_gc = LabG_BottomShadowGC(w); bot_gc = LabG_TopShadowGC(w); /* use the arm GC in a menu if armed and enableEtchedInMenu is set */ if (LabG_IsMenupane(w) && etched_in && TBG_Armed(w)) fill_gc = (TBG_FillOnSelect(w) ? TBG_SelectGC(w) : TBG_ArmGC(w)); else fill_gc = (TBG_FillOnSelect(w) ? TBG_SelectGC(w) : LabG_BackgroundGC(w)); glyph_gc = ((TBG_ReversedSelect(w) && DRAWBOX(normal_ind_on)) ? LabG_BackgroundGC(w) : LabG_NormalGC(w)); /* CR 9791: Label's normal_gc has a dynamic clip_mask. */ if (glyph_gc == LabG_NormalGC(w)) XSetClipMask(dpy, glyph_gc, None); break; case XmINDETERMINATE: top_gc = bot_gc = TBG_IndeterminateBoxGC(w); /* use the arm GC in a menu if armed and enableEtchedInMenu is set */ if (LabG_IsMenupane(w) && etched_in && TBG_Armed(w)) fill_gc = (TBG_FillOnSelect(w) ? TBG_IndeterminateGC(w) : TBG_ArmGC(w)); else fill_gc = (TBG_FillOnSelect(w) ? TBG_IndeterminateGC(w) : LabG_BackgroundGC(w)); glyph_gc = TBG_IndeterminateGC(w); break; default: assert(False); return; } switch (NormalizeIndType(w)) { case XmN_OF_MANY: { /* If the toggle indicator is square shaped then adjust the * indicator width and height, so that it looks proportional * to a diamond shaped indicator of the same width and height */ int new_edge; Dimension box_margin = (DRAWBOX(normal_ind_on) ? w->toggle.detail_shadow_thickness : 0); /* Subtract 3 pixels + 10% from the width and height. */ new_edge = edge - 3 - ((edge - 10)/10); /* Adjust x,y to center the indicator relative to the label. */ y = y + ((edge - new_edge) / 2); x = x + ((edge - new_edge) / 2); edge = new_edge; switch(TBG_VisualSet(w)) { case XmUNSET: if (edge > 0) { if (w->label.fill_bg_box || TBG_FillOnSelect(w)) XFillRectangle(dpy, drawable, fill_gc, x, y, edge, edge); else XClearArea(dpy, drawable, x, y, edge, edge, False); } if (DRAW3DBOX(normal_ind_on)) DrawBox(w, top_gc, bot_gc, fill_gc, x, y, edge, margin); else if (DRAWFLATBOX(normal_ind_on)) DrawBox(w, bot_gc, bot_gc, fill_gc, x, y, edge, margin); break; case XmSET: if (DRAW3DBOX(normal_ind_on)) DrawBox(w, top_gc, bot_gc, fill_gc, x, y, edge, margin); else if (DRAWFLATBOX(normal_ind_on)) DrawBox(w, top_gc, top_gc, fill_gc, x, y, edge, margin); else if (edge > 0) { if (w->label.fill_bg_box || TBG_FillOnSelect(w)) XFillRectangle(dpy, drawable, fill_gc, x, y, edge, edge); else XClearArea(dpy, drawable, x, y, edge, edge, False); } if (!DRAWBOX(normal_ind_on) || ((edge - 2 * box_margin) >= MIN_GLYPH_SIZE)) { if (DRAWCHECK(normal_ind_on)) XmeDrawIndicator(dpy, drawable, glyph_gc, x, y, edge, edge, box_margin, normal_ind_on); else if (DRAWCROSS(normal_ind_on)) XmeDrawIndicator(dpy, drawable, glyph_gc, x, y, edge, edge, box_margin, normal_ind_on); } break; case XmINDETERMINATE: if (TBG_FillOnSelect(w)) { /* Fetch the select_color GetGC() actually used. */ XGetGCValues(dpy, TBG_SelectGC(w), GCForeground, &values); values.background = values.foreground; values.foreground = TBG_UnselectColor(w); XChangeGC(dpy, fill_gc, GCForeground|GCBackground, &values); } else { /* This GC should have the right values already. */ fill_gc = TBG_IndeterminateBoxGC(w); } if (DRAWBOX(normal_ind_on)) DrawBox(w, bot_gc, bot_gc, fill_gc, x, y, edge, margin); else if (edge > 0) { if (w->label.fill_bg_box || TBG_FillOnSelect(w)) XFillRectangle(dpy, drawable, fill_gc, x, y, edge, edge); else XClearArea(dpy, drawable, x, y, edge, edge, False); } if (TBG_ReversedSelect(w)) { values.foreground = LabG_Background(w); values.background = LabG_Foreground(w); } else { values.foreground = LabG_Foreground(w); values.background = LabG_Background(w); } if (!DRAWBOX(normal_ind_on) || ((edge - 2 * box_margin) >= MIN_GLYPH_SIZE)) { if (DRAWCHECK(normal_ind_on)) { XChangeGC(dpy, glyph_gc, GCForeground|GCBackground, &values); XmeDrawIndicator(dpy, drawable, glyph_gc, x, y, edge, edge, box_margin, normal_ind_on); } else if (DRAWCROSS(normal_ind_on)) { XChangeGC(dpy, glyph_gc, GCForeground|GCBackground, &values); XmeDrawIndicator(dpy, drawable, glyph_gc, x, y, edge, edge, box_margin, normal_ind_on); } } break; } break; } case XmONE_OF_MANY: /* This value should have been normalized away! */ assert(FALSE); case XmONE_OF_MANY_DIAMOND: XmeDrawDiamond(dpy, drawable, top_gc, bot_gc, fill_gc, x, y, edge, edge, w->toggle.detail_shadow_thickness,margin); break; case XmONE_OF_MANY_ROUND: XmeDrawCircle(dpy, drawable, top_gc, bot_gc, fill_gc, x, y, edge, edge, w->toggle.detail_shadow_thickness, 1); break; } } else { /* The toggle indicator should be invisibile. */ if (edge > 0) { if (LabG_IsMenupane(w) && etched_in) { if (w->toggle.Armed) /* use the arm GC in a menu if armed and enableEtchedInMenu is set */ XFillRectangle(dpy, drawable, TBG_ArmGC(w), x, y, edge, edge); else XFillRectangle(dpy, drawable, TBG_BackgroundGC(w), x, y, edge, edge); } else if (w->label.fill_bg_box) XFillRectangle(dpy, drawable, TBG_BackgroundGC(w), x, y, edge, edge); else XClearArea(dpy, drawable, x, y, edge, edge, False); } } } /*************************************<->************************************* * * BorderHighlight * *************************************<->***********************************/ static void BorderHighlight( Widget wid ) { XmToggleButtonGadget tb = (XmToggleButtonGadget) wid ; XEvent * event = NULL; if (LabG_IsMenupane(tb)) { XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); Boolean etched_in = dpy->display.enable_etched_in_menu; TBG_Armed(tb) = TRUE; if ((etched_in) && (TBG_IndOn(tb) || (!(TBG_IndOn(tb)) && !(TBG_FillOnSelect(tb))))) { DrawEtchedInMenu(tb); if (TBG_IndOn(tb)) DrawToggle(tb); } XmeDrawShadows (XtDisplay (tb), XtWindow (tb), LabG_TopShadowGC(tb), LabG_BottomShadowGC(tb), tb->rectangle.x + tb->gadget.highlight_thickness, tb->rectangle.y + tb->gadget.highlight_thickness, tb->rectangle.width - 2 * tb->gadget.highlight_thickness, tb->rectangle.height - 2 * tb->gadget.highlight_thickness, tb->gadget.shadow_thickness, etched_in ? XmSHADOW_IN : XmSHADOW_OUT); if (TBG_ArmCB(tb)) { XFlush (XtDisplay (tb)); ToggleButtonCallback(tb, XmCR_ARM, TBG_Set(tb), event); } } else { (*(xmLabelGadgetClassRec.gadget_class.border_highlight))((Widget) tb) ; } } /*************************************<->************************************* * * BorderUnhighlight * *************************************<->***********************************/ static void BorderUnhighlight( Widget wid ) { XmToggleButtonGadget tb = (XmToggleButtonGadget) wid ; XEvent * event = NULL; if (LabG_IsMenupane(tb)) { XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); Boolean etched_in = dpy->display.enable_etched_in_menu; if (!TBG_Armed(tb)) return; TBG_Armed(tb) = FALSE; if ((etched_in) && (TBG_IndOn(tb) || (!(TBG_IndOn(tb)) && !(TBG_FillOnSelect(tb))))) { DrawEtchedInMenu(tb); if (TBG_IndOn(tb)) DrawToggle(tb); } XmeClearBorder (XtDisplay (tb), XtWindow (tb), tb->rectangle.x + tb->gadget.highlight_thickness, tb->rectangle.y + tb->gadget.highlight_thickness, tb->rectangle.width - 2 * tb->gadget.highlight_thickness, tb->rectangle.height - 2 * tb->gadget.highlight_thickness, tb->gadget.shadow_thickness); if (TBG_DisarmCB(tb)) { XFlush (XtDisplay (tb)); ToggleButtonCallback(tb, XmCR_DISARM, TBG_Set(tb), event); } } else { (*(xmLabelGadgetClassRec.gadget_class.border_unhighlight)) ((Widget) tb) ; } } /*************************************<->************************************* * * KeySelect * If the menu system traversal is enabled, do an activate and disarm * *************************************<->***********************************/ static void KeySelect( XmToggleButtonGadget tb, XEvent *event ) { XmToggleButtonCallbackStruct call_value; XmMenuSystemTrait menuSTrait; menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(tb)), XmQTmenuSystem); if (menuSTrait == NULL) return; if (!_XmIsEventUnique(event)) return; if (!_XmGetInDragMode((Widget)tb)) { if (TBG_IndOn(tb)) DrawToggle(tb); else if (TBG_FillOnSelect(tb) && !LabG_IsPixmap(tb)) DrawToggleLabel (tb); if (LabG_IsPixmap(tb)) SetAndDisplayPixmap( tb, NULL, NULL); TBG_Armed(tb) = FALSE; TBG_Set(tb) = (TBG_Set(tb) == TRUE) ? FALSE : TRUE; menuSTrait->buttonPopdown(XtParent(tb), event); _XmRecordEvent(event); /* UNDOING this fix ... */ /* CR 8904: Notify value_changed before entry so that state is */ /* reported correctly even if the entry callback resets it. */ /* Notify parent about the select. */ call_value.reason = XmCR_VALUE_CHANGED; call_value.event = event; call_value.set = TBG_Set(tb); menuSTrait->entryCallback(XtParent(tb), (Widget) tb, &call_value); menuSTrait->reparentToTearOffShell(XtParent(tb), event); if ((! LabG_SkipCallback(tb)) && (TBG_ValueChangedCB(tb))) { XFlush(XtDisplay(tb)); ToggleButtonCallback(tb, XmCR_VALUE_CHANGED, TBG_Set(tb), event); } } } /************************************************************************ * * Compute Space * ***********************************************************************/ static void ComputeSpace( XmToggleButtonGadget tb ) { int needed_width; int needed_height; /* Compute space for drawing toggle. */ needed_width = LabG_TextRect(tb).width + LabG_MarginLeft(tb) + LabG_MarginRight(tb) + (2 * (tb->gadget.shadow_thickness + tb->gadget.highlight_thickness + LabG_MarginWidth(tb))); needed_height = LabG_TextRect(tb).height + LabG_MarginTop(tb) + LabG_MarginBottom(tb) + (2 * (tb->gadget.shadow_thickness + tb->gadget.highlight_thickness + LabG_MarginHeight(tb))); if (needed_height > tb->rectangle.height) if (TBG_IndOn(tb)) LabG_TextRect(tb).y = tb->gadget.shadow_thickness + tb->gadget.highlight_thickness + LabG_MarginHeight(tb) + LabG_MarginTop(tb) + ((tb->rectangle.height - LabG_MarginTop(tb) - LabG_MarginBottom(tb) - (2 * (LabG_MarginHeight(tb) + tb->gadget.highlight_thickness + tb->gadget.shadow_thickness)) - LabG_TextRect(tb).height) / 2); if (LayoutIsRtoLG(tb)) { if ((needed_width > tb->rectangle.width) || ((LabG_Alignment(tb) == XmALIGNMENT_BEGINNING) && (needed_width < tb->rectangle.width)) || ((LabG_Alignment(tb) == XmALIGNMENT_CENTER) && (needed_width < tb->rectangle.width) && (tb->rectangle.width - needed_width < LabG_MarginRight(tb))) || (needed_width == tb->rectangle.width)) { if (TBG_IndOn(tb)) LabG_TextRect(tb).x = tb->rectangle.x + tb->rectangle.width - (tb->gadget.shadow_thickness + tb->gadget.highlight_thickness + LabG_MarginHeight(tb) + LabG_MarginRight(tb) + LabG_TextRect(tb).width); } } else { if ((needed_width > tb->rectangle.width) || ((LabG_Alignment(tb) == XmALIGNMENT_BEGINNING) && (needed_width < tb->rectangle.width)) || ((LabG_Alignment(tb) == XmALIGNMENT_CENTER) && (needed_width < tb->rectangle.width) && (tb->rectangle.width - needed_width < LabG_MarginLeft(tb))) || (needed_width == tb->rectangle.width)) { if (TBG_IndOn(tb)) LabG_TextRect(tb).x = tb->gadget.shadow_thickness + tb->gadget.highlight_thickness + LabG_MarginHeight(tb) + LabG_MarginLeft(tb); } } } /*************************************<->************************************* * * Redisplay(w, event, region) * Cause the widget, identified by w, to be redisplayed. * *************************************<->***********************************/ static void Redisplay( Widget w, XEvent *event, Region region ) { register XmToggleButtonGadget tb = (XmToggleButtonGadget) w; /* Fix CR #4884, D. Rand 6/4/92 */ if (! XtIsRealized(w) ) return; /* End Fix */ if (LabG_IsMenupane(tb)) { ShellWidget mshell = (ShellWidget) XtParent(XtParent(tb)); if (! mshell->shell.popped_up) return; } ComputeSpace(tb); if (LabG_IsPixmap (tb)) SetAndDisplayPixmap(tb, event, region); else { if (!TBG_IndOn(tb) && TBG_FillOnSelect(tb)) DrawToggleLabel (tb); else { XtExposeProc expose; _XmProcessLock(); expose = xmLabelGadgetClassRec.rect_class.expose; _XmProcessUnlock(); (* expose) ((Widget)tb, event, region); } } if (TBG_IndOn(tb)) { if (! TBG_Armed(tb)) IsOn(tb) = TBG_Set(tb); DrawToggle(tb); } if (LabG_IsMenupane(tb)) { XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(w)); Boolean etched_in = dpy -> display.enable_etched_in_menu; if (TBG_Armed(tb)) XmeDrawShadows(XtDisplay (tb), XtWindow (tb), LabG_TopShadowGC(tb), LabG_BottomShadowGC(tb), tb->rectangle.x + tb->gadget.highlight_thickness, tb->rectangle.y + tb->gadget.highlight_thickness, tb->rectangle.width - 2*tb->gadget.highlight_thickness, tb->rectangle.height - 2*tb->gadget.highlight_thickness, tb->gadget.shadow_thickness, etched_in ? XmSHADOW_IN : XmSHADOW_OUT); } else { DrawToggleShadow (tb); } } /************************************************************************** * Resize(w, event) **************************************************************************/ static void Resize( Widget w ) { register XmToggleButtonGadget tb = (XmToggleButtonGadget) w; if (LabG_IsPixmap(w)) SetToggleSize(tb); else { XtWidgetProc resize; _XmProcessLock(); resize = xmLabelGadgetClassRec.rect_class.resize; _XmProcessUnlock(); (* resize)( (Widget) tb); } } /************************************************************************ * * SetValuesPrehook * ************************************************************************/ /* ARGSUSED */ static Boolean SetValuesPrehook( Widget oldParent, Widget refParent, Widget newParent, ArgList args, Cardinal *num_args ) { XmWidgetExtData extData; XmBaseClassExt *cePtr; WidgetClass ec; Cardinal size; XmToggleButtonGCacheObject newSec, reqSec; _XmProcessLock(); cePtr = _XmGetBaseClassExtPtr(XtClass(newParent), XmQmotif); ec = (*cePtr)->secondaryObjectClass; size = ec->core_class.widget_size; newSec = (XmToggleButtonGCacheObject)_XmExtObjAlloc(size); reqSec = (XmToggleButtonGCacheObject)_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)); memcpy(&(newSec->toggle_cache), TBG_Cache(newParent), sizeof(XmToggleButtonGCacheObjPart)); extData = (XmWidgetExtData) XtCalloc(1, sizeof(XmWidgetExtDataRec)); extData->widget = (Widget)newSec; extData->reqWidget = (Widget)reqSec; _XmPushWidgetExtData(newParent, extData, XmCACHE_EXTENSION); /* * Since the resource lists for label and togglebutton were merged at * ClassInitialize time we need to make only one call to * XtSetSubvalues() */ XtSetSubvalues((XtPointer)newSec, ec->core_class.resources, ec->core_class.num_resources, args, *num_args); memcpy((XtPointer)reqSec, (XtPointer)newSec, size); LabG_Cache(newParent) = &(((XmLabelGCacheObject)newSec)->label_cache); LabG_Cache(refParent) = &(((XmLabelGCacheObject) extData->reqWidget)->label_cache); TBG_Cache(newParent) = &(((XmToggleButtonGCacheObject)newSec)->toggle_cache); TBG_Cache(refParent) = &(((XmToggleButtonGCacheObject)extData->reqWidget)->toggle_cache); _XmExtImportArgs((Widget)newSec, args, num_args); /* CR 2990: Use XmNbuttonFontList as the default font. */ if (LabG_Font(newParent) == NULL) LabG_Font(newParent) = XmeGetDefaultRenderTable (newParent, XmBUTTON_FONTLIST); return FALSE; } /************************************************************************ * * GetValuesPrehook * ************************************************************************/ /* ARGSUSED */ static void GetValuesPrehook( Widget newParent, ArgList args, Cardinal *num_args ) { XmWidgetExtData extData; XmBaseClassExt *cePtr; WidgetClass ec; Cardinal size; XmToggleButtonGCacheObject newSec; _XmProcessLock(); cePtr = _XmGetBaseClassExtPtr(XtClass(newParent), XmQmotif); ec = (*cePtr)->secondaryObjectClass; size = ec->core_class.widget_size; newSec = (XmToggleButtonGCacheObject)_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)); memcpy (&(newSec->toggle_cache), TBG_Cache(newParent), sizeof(XmToggleButtonGCacheObjPart)); extData = (XmWidgetExtData) XtCalloc(1, sizeof(XmWidgetExtDataRec)); extData->widget = (Widget)newSec; _XmPushWidgetExtData(newParent, extData, XmCACHE_EXTENSION); /* * Note that if a resource is defined in the superclass's as well as a * subclass's resource list and if a NULL is passed in as the third * argument to XtSetArg, then when a GetSubValues() is done by the * superclass the NULL is replaced by a value. Now when the subclass * gets the arglist it doesn't see a NULL and thinks it's an address * it needs to stuff a value into and sure enough it breaks. * This means that we have to pass the same arglist with the NULL to * both the superclass and subclass and propagate the values up once * the XtGetSubValues() are done. */ /* * Since the resource lists for label and togglebutton were merged at * ClassInitialize time we need to make only one call to * XtGetSubvalues() */ 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, /* unused */ Cardinal *num_args ) /* unused */ { 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, /* unused */ Widget new_w, ArgList args, /* unused */ Cardinal *num_args ) /* unused */ { 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); /* assign if changed! */ if (!_XmToggleBCacheCompare((XtPointer)TBG_Cache(new_w), (XtPointer)TBG_Cache(current))) { /* delete the old one */ _XmCacheDelete( (XtPointer) TBG_Cache(current)); TBG_Cache(new_w) = (XmToggleButtonGCacheObjPart *) _XmCachePart(TBG_ClassCachePart(new_w), (XtPointer) TBG_Cache(new_w), sizeof(XmToggleButtonGCacheObjPart)); } else TBG_Cache(new_w) = TBG_Cache(current); _XmPopWidgetExtData(new_w, &ext, XmCACHE_EXTENSION); _XmExtObjFree((XtPointer) ext->widget); _XmExtObjFree((XtPointer) ext->reqWidget); _XmProcessUnlock(); XtFree( (char *) ext); return FALSE; } /*************************************************************************** * * SetValues(current, request, new_w) * This is the set values procedure for the ToggleButton class. It is * called last (the set values rtnes for its superclasses are called * first). * *************************************<->***********************************/ /*ARGSUSED*/ static Boolean SetValues( Widget current, Widget request, Widget new_w, ArgList args, /* unused */ Cardinal *num_args ) /* unused */ { XmToggleButtonGadget curcbox = (XmToggleButtonGadget) current; XmToggleButtonGadget reqcbox = (XmToggleButtonGadget) request; XmToggleButtonGadget newcbox = (XmToggleButtonGadget) new_w; Boolean flag = FALSE; /* our return value */ XtWidgetProc resize; /* CR 2337: Preserve the user's margins. */ if (LabG_MarginRight(curcbox) != LabG_MarginRight(reqcbox)) TBG_IndRightDelta(newcbox) = 0; if (LabG_MarginLeft(curcbox) != LabG_MarginLeft(reqcbox)) TBG_IndLeftDelta(newcbox) = 0; if (LabG_MarginTop(curcbox) != LabG_MarginTop(reqcbox)) TBG_IndTopDelta(newcbox) = 0; if (LabG_MarginBottom(curcbox) != LabG_MarginBottom(reqcbox)) TBG_IndBottomDelta(newcbox) = 0; /********************************************************************** * Calculate the window size: The assumption here is that if * the width and height are the same in the new and current instance * record that those fields were not changed with set values. Therefore * its okay to recompute the necessary width and height. However, if * the new and current do have different width/heights then leave them * alone because that's what the user wants. *********************************************************************/ _XmProcessLock(); resize = xmLabelGadgetClassRec.rect_class.resize; _XmProcessUnlock(); /* Use the On pixmaps if no Indeterminate pixmaps are found. */ if (IsNull(PixmapInd(newcbox)) && !IsNull(PixmapOn(newcbox))) PixmapInd(newcbox) = PixmapOn(newcbox); if (IsNull(PixmapInsenInd(newcbox)) && !IsNull(PixmapInsenOn(newcbox))) PixmapInsenInd(newcbox) = PixmapInsenOn(newcbox); /* Use the On pixmap if no Off pixmap is found. */ if (IsNull(PixmapOff(newcbox)) && !IsNull(PixmapOn(newcbox))) { PixmapOff(newcbox) = PixmapOn(newcbox); if ((LabG_RecomputeSize(newcbox)) && (request->core.width == current->core.width)) new_w->core.width = 0; if ((LabG_RecomputeSize(newcbox)) && (request->core.height == current->core.height)) new_w->core.height = 0; _XmCalcLabelGDimensions(new_w); (* resize)( (Widget) newcbox); } /* Use the insensitive On pixmap if no insensitive Off pixmap is found. */ if (IsNull(PixmapInsenOff(newcbox)) && !IsNull(PixmapInsenOn(newcbox))) { PixmapInsenOff(newcbox) = PixmapInsenOn(newcbox); if ((LabG_RecomputeSize(newcbox)) && (request->core.width == current->core.width)) new_w->core.width = 0; if ((LabG_RecomputeSize(newcbox)) && (request->core.height == current->core.height)) new_w->core.height = 0; _XmCalcLabelGDimensions(new_w); (* resize)( (Widget) newcbox); } /* BEGIN OSF Fix pir 1778 */ /* Have to reset the TextRect width because label's resize will have mucked with it. */ if (LabG_IsPixmap(newcbox) && (!IsNull(PixmapOff(newcbox)) || !IsNull(PixmapInsenOff(newcbox)) || !IsNull(PixmapOn(newcbox)) || !IsNull(PixmapInsenOn(newcbox)) || !IsNull(PixmapInd(newcbox)) || !IsNull(PixmapInsenInd(newcbox)))) { if (LabG_RecomputeSize(newcbox)) { if (request->core.width == current->core.width) new_w->core.width = 0; if (request->core.height == current->core.height) new_w->core.height = 0; } SetToggleSize(newcbox); } /* END OSF Fix pir 1778 */ /* CR 9922: Changing fillOnSelect requires a redraw. */ if (TBG_FillOnSelect(newcbox) != TBG_FillOnSelect(curcbox)) { flag = TRUE; } if ((LabG__label(newcbox) != LabG__label(curcbox)) || (PixmapOff(newcbox) != PixmapOff(curcbox)) || (LabG_Font(newcbox) != LabG_Font(curcbox)) || (TBG_Spacing(newcbox) != TBG_Spacing(curcbox)) || (PixmapOn(newcbox) != PixmapOn(curcbox)) || (PixmapInsenOn(newcbox) != PixmapInsenOn(curcbox)) || (PixmapInd(newcbox) != PixmapInd(curcbox)) || (PixmapInsenInd(newcbox) != PixmapInsenInd(curcbox)) || (TBG_IndOn(newcbox) != TBG_IndOn(curcbox)) || (TBG_IndicatorDim(newcbox) != TBG_IndicatorDim(curcbox)) || (LabG_IsPixmap(newcbox) != LabG_IsPixmap(curcbox))) { int right_delta = 0; /* Our desired margin adjustments. */ int left_delta = 0; int top_delta = 0; int bottom_delta = 0; if (LabG_RecomputeSize(newcbox)) { if (reqcbox->rectangle.width == curcbox->rectangle.width) newcbox->rectangle.width = 0; if (reqcbox->rectangle.height == curcbox->rectangle.height) newcbox->rectangle.height = 0; } if (LabG_IsPixmap(newcbox) && ((PixmapOn(newcbox) != PixmapOn(curcbox)) || (PixmapInsenOn(newcbox) != PixmapInsenOn(curcbox)) || (PixmapInd(newcbox) != PixmapInd(curcbox)) || (PixmapInsenInd(newcbox) != PixmapInsenInd(curcbox))) ) { _XmCalcLabelGDimensions(new_w); /* OSF Fix 1778 */ SetToggleSize(newcbox); } TBG_IndicatorSet(newcbox) = TBG_IndicatorSet(curcbox); if ( TBG_IndicatorDim(newcbox) != TBG_IndicatorDim(curcbox)) TBG_IndicatorSet(newcbox) = TRUE; /* CR 8415: Honor explicit requests for XmNindicatorSize. */ if (!TBG_IndicatorSet(newcbox) && (TBG_IndicatorDim(newcbox) == TBG_IndicatorDim(curcbox))) { if ((LabG_IsPixmap(newcbox) != LabG_IsPixmap(curcbox)) || (LabG__label(newcbox) != LabG__label(curcbox)) || (PixmapOff(newcbox) != PixmapOff(curcbox)) || (LabG_Font(newcbox) != LabG_Font(curcbox)) || (TBG_IndOn(newcbox) != TBG_IndOn(curcbox))) { if LabG_IsPixmap(newcbox) { if (!IsNull(PixmapOff(newcbox)) || !IsNull(PixmapInsenOff(newcbox)) || !IsNull(PixmapOn(newcbox)) || !IsNull(PixmapInsenOn(newcbox)) || !IsNull(PixmapInd(newcbox)) || !IsNull(PixmapInsenInd(newcbox))) if (LabG_TextRect(newcbox).height < 13) TBG_IndicatorDim(newcbox) = LabG_TextRect(newcbox).height; else TBG_IndicatorDim(newcbox) = 13 + (LabG_TextRect(newcbox).height/13); else TBG_IndicatorDim(newcbox) = XmDEFAULT_INDICATOR_DIM; } else { Dimension height; int line_count; height = XmStringHeight(LabG_Font(newcbox), LabG__label(newcbox)); line_count = XmStringLineCount (LabG__label(newcbox)); if (line_count < 1) line_count = 1; /* * CR 5203 - Make the calculation for the * indicator_dim be the same as in the Initialize * procedure, i.e. Popup and Pulldown menus should * have smaller indicators */ if (LabG_IsMenupane(new_w)) TBG_IndicatorDim(newcbox) = MAX(XmDEFAULT_INDICATOR_DIM, (height / ((Dimension)line_count))*2/3); else TBG_IndicatorDim(newcbox) = MAX(XmDEFAULT_INDICATOR_DIM, height / ((Dimension)line_count)); } /* End 5203 Fix */ } } if (TBG_IndOn(newcbox)) { /* * Fix CR 5568 - If the indicator is on and the user has changed the * indicator dimension, calculate the new top and bottom * margins in a place where they can effect the core width * and height. */ /* Recompute the Top and bottom margins and the height of the text * rectangle to accommodate the size of toggle indicator. * if (we are given a new toggleIndicator size) * { if (user has given new top or bottom margin) * { compute to accomodate new toggle button size; } * else (user has set new top/bottom margin) * { Recompute margin to accommodate new IndicatorSize } * } */ if (TBG_IndicatorDim(newcbox) != TBG_IndicatorDim(curcbox)) { int maxIndicatorSize = (int) (TBG_IndicatorDim(newcbox)) + 2*Xm3D_ENHANCE_PIXEL; int boxSize = ((int) LabG_TextRect(newcbox).height + (int) LabG_MarginTop(newcbox) + (int) LabG_MarginBottom(newcbox)); top_delta = bottom_delta = (maxIndicatorSize - boxSize) / 2; } if (LayoutIsRtoLG(newcbox)) right_delta = (TBG_IndicatorDim(newcbox) + TBG_Spacing(newcbox) - LabG_MarginRight(newcbox)); else left_delta = (TBG_IndicatorDim(newcbox) + TBG_Spacing(newcbox) - LabG_MarginLeft(newcbox)); } else if (TBG_IndOn(curcbox)) { /* CR 2337: Redisplay when the indicator is turned off. */ flag = TRUE; top_delta = -TBG_IndTopDelta(newcbox); bottom_delta = -TBG_IndBottomDelta(newcbox); if (LayoutIsRtoLG(newcbox)) right_delta = -TBG_IndRightDelta(newcbox); else left_delta = -TBG_IndLeftDelta(newcbox); } /* CR 2337: Let the toggle button shrink if necessary. */ if (right_delta || left_delta || top_delta || bottom_delta) { flag = TRUE; /* Adjust vertical margins based on the indicator. */ if ((int)TBG_IndTopDelta(newcbox) + top_delta > 0) { LabG_MarginTop(newcbox) += top_delta; TBG_IndTopDelta(newcbox) += top_delta; } else { LabG_MarginTop(newcbox) -= TBG_IndTopDelta(newcbox); TBG_IndTopDelta(newcbox) = 0; } if ((int)TBG_IndBottomDelta(newcbox) + bottom_delta > 0) { LabG_MarginBottom(newcbox) += bottom_delta; TBG_IndBottomDelta(newcbox) += bottom_delta; } else { LabG_MarginBottom(newcbox) -= TBG_IndBottomDelta(newcbox); TBG_IndBottomDelta(newcbox) = 0; } /* Adjust horizontal margins based on the indicator. */ if (LayoutIsRtoLG(newcbox)) { if ((int)TBG_IndRightDelta(newcbox) + right_delta > 0) { LabG_MarginRight(newcbox) += right_delta; TBG_IndRightDelta(newcbox) += right_delta; } else { LabG_MarginRight(newcbox) -= TBG_IndRightDelta(newcbox); TBG_IndRightDelta(newcbox) = 0; } } else { if ((int)TBG_IndLeftDelta(newcbox) + left_delta > 0) { LabG_MarginLeft(newcbox) += left_delta; TBG_IndLeftDelta(newcbox) += left_delta; } else { LabG_MarginLeft(newcbox) -= TBG_IndLeftDelta(newcbox); TBG_IndLeftDelta(newcbox) = 0; } } /* Realign the label. */ if (! LabG_RecomputeSize(newcbox)) (* resize) ((Widget) new_w); } if (LabG_RecomputeSize(newcbox)) { if (reqcbox->rectangle.width == curcbox->rectangle.width) newcbox->rectangle.width = 0; if (reqcbox->rectangle.height == curcbox->rectangle.height) newcbox->rectangle.height = 0; } if (newcbox->rectangle.width == 0) { newcbox->rectangle.width = LabG_TextRect(newcbox).width + LabG_MarginLeft(newcbox) + LabG_MarginRight(newcbox) + 2 * (newcbox->gadget.highlight_thickness + newcbox->gadget.shadow_thickness + LabG_MarginHeight(newcbox)); if (newcbox->rectangle.width == 0) newcbox->rectangle.width = 1; flag = TRUE; } if (newcbox->rectangle.height == 0) { newcbox->rectangle.height = MAX(TBG_IndicatorDim(newcbox), LabG_TextRect(newcbox).height + 2*LabG_MarginHeight(newcbox) + LabG_MarginTop(newcbox) + LabG_MarginBottom(newcbox)) + 2 * (newcbox->gadget.highlight_thickness + newcbox->gadget.shadow_thickness); if (newcbox->rectangle.height == 0) newcbox->rectangle.height = 1; flag = TRUE; } } if ((TBG_IndType(curcbox) != TBG_IndType(newcbox)) && (!XmRepTypeValidValue(XmRID_INDICATOR_TYPE, TBG_IndType( newcbox), (Widget) newcbox))) { TBG_IndType(newcbox) = TBG_IndType(curcbox); } if ((LabG_Foreground(newcbox) != LabG_Foreground(curcbox)) || (LabG_Background(newcbox) != LabG_Background(curcbox)) || (TBG_SelectColor(newcbox) != TBG_SelectColor(curcbox))) { XtReleaseGC (XtParent(newcbox), TBG_SelectGC(newcbox)); XtReleaseGC (XtParent(newcbox), TBG_BackgroundGC(newcbox)); XtReleaseGC (XtParent(newcbox), TBG_IndeterminateGC(newcbox)); XtReleaseGC (XtParent(newcbox), TBG_IndeterminateBoxGC(newcbox)); TBG_ReversedSelect(newcbox) = (TBG_SelectColor(newcbox) == XmREVERSED_GROUND_COLORS); if ((TBG_SelectColor(newcbox) == INVALID_PIXEL) || (TBG_SelectColor(newcbox) == XmDEFAULT_SELECT_COLOR)) { XrmValue value; value.size = sizeof(Pixel); DefaultSelectColor((Widget) newcbox, XtOffsetOf(XmToggleButtonGCacheObjRec, toggle_cache.select_color), &value); memcpy((char*) &TBG_SelectColor(newcbox), value.addr, value.size); } else if (TBG_SelectColor(newcbox) == XmREVERSED_GROUND_COLORS) { TBG_SelectColor(newcbox) = LabG_Foreground(newcbox); } else if (TBG_SelectColor(newcbox) == XmHIGHLIGHT_COLOR) { TBG_SelectColor(newcbox) = LabG_HighlightColor(newcbox); } GetGC(newcbox); flag = TRUE; } if (TBG_UnselectColor(newcbox) != TBG_UnselectColor(curcbox)) { XtReleaseGC (XtParent(curcbox), TBG_UnselectGC(curcbox)); GetUnselectGC(newcbox); flag = TRUE; } if (TBG_Set(curcbox) != TBG_Set(newcbox)) { if (TBG_ToggleMode(newcbox) == XmTOGGLE_BOOLEAN && TBG_Set(newcbox) == XmINDETERMINATE) TBG_Set(newcbox) = TBG_Set(curcbox); else { IsOn(newcbox) = TBG_Set(newcbox); if (flag == False && XtIsRealized((Widget)newcbox)) { if (TBG_IndOn(newcbox)) DrawToggle (newcbox); else { if (newcbox->gadget.shadow_thickness > 0) DrawToggleShadow (newcbox); if (TBG_FillOnSelect(newcbox)&& !LabG_IsPixmap(newcbox)) DrawToggleLabel (newcbox); if (LabG_IsPixmap(newcbox)) { SetAndDisplayPixmap(newcbox, NULL, NULL); flag = True; } } } } } if ((TBG_IndType(curcbox) != TBG_IndType(newcbox)) || ( (TBG_Visible(curcbox) != TBG_Visible(newcbox)) && (XmUNSET == TBG_Set(newcbox)))) { flag = True; } /* One-of-many forces boolean mode. */ if (IsOneOfMany(TBG_IndType(newcbox)) && (TBG_ToggleMode(newcbox) == XmTOGGLE_INDETERMINATE)) { TBG_ToggleMode(newcbox) = XmTOGGLE_BOOLEAN; } if (TBG_ToggleMode(curcbox) != TBG_ToggleMode(newcbox)) { if ((TBG_ToggleMode(newcbox) == XmTOGGLE_BOOLEAN) && (TBG_Set(newcbox) == XmINDETERMINATE)) { TBG_VisualSet(newcbox) = TBG_Set(newcbox) = False; flag = True; } } /* BEGIN OSF Fix pir 2097 */ newcbox->gadget.event_mask = XmARM_EVENT | XmACTIVATE_EVENT | XmMULTI_ARM_EVENT | XmMULTI_ACTIVATE_EVENT | XmHELP_EVENT | XmFOCUS_IN_EVENT | XmFOCUS_OUT_EVENT | XmENTER_EVENT | XmLEAVE_EVENT | XmBDRAG_EVENT; /* END OSF Fix pir 2097 */ return(flag); } /*************************************************************** * * XmToggleButtonGadgetGetState * This function gets the state of the toggle gadget. * ***************************************************************/ Boolean XmToggleButtonGadgetGetState( Widget w ) { XmToggleButtonGadget tg = (XmToggleButtonGadget) w; Boolean ret_val; XtAppContext app = XtWidgetToApplicationContext(w); _XmAppLock(app); ret_val = TBG_Set(tg); _XmAppUnlock(app); return (ret_val); } /**************************************************************** * * XmToggleButtonGadgetSetState * This function sets the state of the toggle gadget. * ****************************************************************/ void XmToggleButtonGadgetSetState( Widget w, #if NeedWidePrototypes int bnewstate, int notify ) #else Boolean bnewstate, Boolean notify ) #endif /* NeedWidePrototypes */ { XmToggleButtonGadget tg = (XmToggleButtonGadget) w; XmMenuSystemTrait menuSTrait; XmToggleButtonState newstate; XtAppContext app = XtWidgetToApplicationContext(w); _XmAppLock(app); newstate = (bnewstate == XmSET)? XmSET : XmUNSET; if (TBG_Set(tg) != newstate) { TBG_Set(tg) = newstate; IsOn(tg) = newstate; if (XtIsRealized ((Widget)tg)) { if (TBG_IndOn(tg)) DrawToggle(tg); else { if (tg->gadget.shadow_thickness> 0) DrawToggleShadow (tg); if (TBG_FillOnSelect(tg) && !LabG_IsPixmap(tg)) DrawToggleLabel (tg); } if (LabG_IsPixmap(tg)) SetAndDisplayPixmap(tg, NULL, NULL); } if (notify) { /* UNDOING this fix ... */ /* CR 8904: Notify value_changed before entry so that state is */ /* reported correctly even if the entry callback resets it. */ menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(tg)), XmQTmenuSystem); if (menuSTrait != NULL) { XmToggleButtonCallbackStruct call_value; call_value.reason = XmCR_VALUE_CHANGED; call_value.event = NULL; call_value.set = TBG_Set(tg); menuSTrait->entryCallback(XtParent(tg), (Widget)tg, &call_value); } if ((! LabG_SkipCallback(tg)) && (TBG_ValueChangedCB(tg))) { if (XtIsRealized ((Widget)tg)) XFlush (XtDisplay (tg)); ToggleButtonCallback(tg, XmCR_VALUE_CHANGED, TBG_Set(tg), NULL); } } } _XmAppUnlock(app); } /**************************************************************** * * XmToggleButtonGadgetSetValue * This function sets the state of the toggle gadget. * ****************************************************************/ Boolean XmToggleButtonGadgetSetValue( Widget w, #if NeedWidePrototypes int newstate, int notify ) #else XmToggleButtonState newstate, Boolean notify ) #endif /* NeedWidePrototypes */ { XmToggleButtonGadget tg = (XmToggleButtonGadget) w; XmMenuSystemTrait menuSTrait; XtAppContext app = XtWidgetToApplicationContext(w); _XmAppLock(app); /* Can't set third state if we aren't in three state mode */ if ((newstate == XmINDETERMINATE) && (TBG_ToggleMode(tg) != XmTOGGLE_INDETERMINATE)) { _XmAppUnlock(app); return False; } if (TBG_Set(tg) != newstate) { TBG_Set(tg) = newstate; IsOn(tg) = newstate; if (XtIsRealized ((Widget)tg)) { if (TBG_IndOn(tg)) DrawToggle(tg); else { if (tg->gadget.shadow_thickness> 0) DrawToggleShadow (tg); if (TBG_FillOnSelect(tg) && !LabG_IsPixmap(tg)) DrawToggleLabel (tg); } if (LabG_IsPixmap(tg)) SetAndDisplayPixmap(tg, NULL, NULL); } if (notify) { /* UNDOING this fix ... */ /* CR 8904: Notify value_changed before entry so that state is */ /* reported correctly even if the entry callback resets it. */ menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(tg)), XmQTmenuSystem); if (menuSTrait != NULL) { XmToggleButtonCallbackStruct call_value; call_value.reason = XmCR_VALUE_CHANGED; call_value.event = NULL; call_value.set = TBG_Set(tg); menuSTrait->entryCallback(XtParent(tg), (Widget)tg, &call_value); } if ((! LabG_SkipCallback(tg)) && (TBG_ValueChangedCB(tg))) { if (XtIsRealized ((Widget)tg)) XFlush (XtDisplay (tg)); ToggleButtonCallback(tg, XmCR_VALUE_CHANGED, TBG_Set(tg), NULL); } } } _XmAppUnlock(app); return True; } /*********************************************************************** * * XmCreateToggleButtonGadget * Creates an instance of a togglebutton and returns the widget id. * ***********************************************************************/ Widget XmCreateToggleButtonGadget( Widget parent, char *name, Arg *arglist, Cardinal argCount ) { return XtCreateWidget(name,xmToggleButtonGadgetClass,parent,arglist,argCount); } /********************************************************* * Functions for manipulating Secondary Resources. *********************************************************/ /* * GetPushBGSecResData() * Create a XmSecondaryResourceDataRec for each secondary resource; * Put the pointers to these records in an array of pointers; * Return the pointer to the array of pointers. */ /*ARGSUSED*/ static Cardinal GetToggleBGClassSecResData( WidgetClass w_class, /* unused */ XmSecondaryResourceData **data_rtn ) { int arrayCount = 0; XmBaseClassExt bcePtr; String resource_class, resource_name; XtPointer client_data; _XmProcessLock(); bcePtr = &( ToggleBGClassExtensionRec ); client_data = NULL; resource_class = NULL; resource_name = NULL; arrayCount = _XmSecondaryResourceData ( bcePtr, data_rtn, client_data, resource_name, resource_class, GetToggleBGClassSecResBase) ; _XmProcessUnlock(); return (arrayCount); } /* * GetToggleBGClassResBase () * return the address of the base of resources. */ /*ARGSUSED*/ static XtPointer GetToggleBGClassSecResBase( Widget widget, XtPointer client_data ) /* unused */ { XtPointer widgetSecdataPtr; int labg_cache_size = sizeof (XmLabelGCacheObjPart); int togglebg_cache_size = sizeof (XmToggleButtonGCacheObjPart); char *cp; widgetSecdataPtr = (XtPointer) (XtMalloc ( labg_cache_size + togglebg_cache_size + 1)); _XmProcessLock(); if (widgetSecdataPtr) { cp = (char *) widgetSecdataPtr; memcpy (cp, LabG_Cache(widget), labg_cache_size); cp += labg_cache_size; memcpy (cp, TBG_Cache(widget), togglebg_cache_size); } /* else Warning: error cannot allocate Memory */ _XmProcessUnlock(); return ( widgetSecdataPtr); } /* * DrawToggleLabel (tb) * Called when XmNindicatorOn is TRUE and XmNfillOnSelect is FALSE. * Fill toggle with selectColor or background depending on toggle * value, and draw label. */ static void DrawToggleLabel( XmToggleButtonGadget tb ) { Dimension margin = tb->gadget.highlight_thickness + tb->gadget.shadow_thickness; Position fx = tb->rectangle.x + margin; Position fy = tb->rectangle.y + margin; int fw = tb->rectangle.width - 2 * margin; int fh = tb->rectangle.height - 2 * margin; Boolean restore_gc = False; GC tmp_gc = NULL, fill_gc; if ((LabG_TopShadowColor(tb) == TBG_SelectColor(tb)) || (LabG_BottomShadowColor(tb) == TBG_SelectColor(tb))) { fx += 1; fy += 1; fw -= 2; fh -= 2; } if (fw < 0 || fh < 0) return; switch (tb->toggle.visual_set) { case XmUNSET: fill_gc = TBG_UnselectGC(tb); break; case XmSET: fill_gc = TBG_SelectGC(tb); break; case XmINDETERMINATE: { XGCValues values; /* Fetch the select_color GetGC() actually used. */ XGetGCValues(XtDisplay(tb), TBG_SelectGC(tb), GCForeground, &values); values.background = TBG_UnselectColor(tb); XChangeGC(XtDisplay((Widget)tb), TBG_IndeterminateGC(tb), GCForeground|GCBackground, &values); fill_gc = TBG_IndeterminateGC(tb); break; } default: assert(False); return; } XFillRectangle (XtDisplay(tb), XtWindow(tb), fill_gc, fx, fy, fw, fh); if (LabG_Foreground(tb) == TBG_SelectColor(tb) && (IsOn(tb) == XmSET)) { tmp_gc = LabG_NormalGC(tb); LabG_NormalGC(tb) = TBG_BackgroundGC(tb); restore_gc = True; } { XtExposeProc expose; _XmProcessLock(); expose = xmLabelGadgetClassRec.rect_class.expose; _XmProcessUnlock(); (* expose) ((Widget)tb, NULL, NULL); } if (restore_gc) { /* CR 9791: Label's normal_gc has a dynamic clip_mask. */ XSetClipMask(XtDisplay(tb), TBG_BackgroundGC(tb), None); LabG_NormalGC(tb) = tmp_gc; } } /* * DrawEtchedInMenu (tb) * Called when in a Menu and EtchedInMenu is TRUE. * And when XmNindicatorOn is FALSE and XmNfillOnSelect is FALSE; * or when XmNindicatorOn is TRUE. * Fill background with the arm_gc and draw label. */ static void DrawEtchedInMenu( XmToggleButtonGadget tb ) { Dimension margin = tb->gadget.highlight_thickness + tb->gadget.shadow_thickness; Position fx = tb->rectangle.x + margin; Position fy = tb->rectangle.y + margin; int fw = tb->rectangle.width - 2 * margin; int fh = tb->rectangle.height - 2 * margin; Boolean restore_gc = False; GC tmp_gc = NULL; XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay((Widget) tb)); Boolean etched_in = dpy->display.enable_etched_in_menu; if ((LabG_TopShadowColor(tb) == TBG_SelectColor(tb)) || (LabG_BottomShadowColor(tb) == TBG_SelectColor(tb))) { fx += 1; fy += 1; fw -= 2; fh -= 2; } if (fw < 0 || fh < 0) return; XFillRectangle (XtDisplay(tb), XtWindow(tb), TBG_Armed(tb) ? TBG_ArmGC(tb) : TBG_BackgroundGC(tb), fx, fy, fw, fh); if (TBG_Armed(tb)) { Pixel select_pix; Widget wid = XtParent(tb); XmGetColors(XtScreen(wid), wid->core.colormap, wid->core.background_pixel, NULL, NULL, NULL, &select_pix); if (LabG_Foreground(tb) == select_pix) { tmp_gc = LabG_NormalGC(tb); LabG_NormalGC(tb) = TBG_BackgroundGC(tb); restore_gc = True; } } { XtExposeProc expose; _XmProcessLock(); expose = xmLabelGadgetClassRec.rect_class.expose; _XmProcessUnlock(); (* expose) ((Widget)tb, NULL, NULL); } if (restore_gc) { /* CR 9791: Label's normal_gc has a dynamic clip_mask. */ XSetClipMask(XtDisplay(tb), TBG_BackgroundGC(tb), None); LabG_NormalGC(tb) = tmp_gc; } } /* * DrawToggleShadow (tb) * - Should be called only if ToggleShadow are to be drawn ; * if the IndicatorOn resource is set to false top and bottom shadows * will be switched depending on whether the Toggle is selected or * unselected. */ static void DrawToggleShadow( XmToggleButtonGadget tb ) { GC top_gc, bot_gc; int dx, dy, width, height; int hilite_thickness; if (TBG_IndOn(tb) || (IsOn(tb) == XmUNSET)) { top_gc = LabG_TopShadowGC(tb); bot_gc = LabG_BottomShadowGC(tb); } else if (IsOn(tb) == XmINDETERMINATE) { top_gc = bot_gc = TBG_IndeterminateBoxGC(tb); } else { top_gc = LabG_BottomShadowGC(tb); bot_gc = LabG_TopShadowGC(tb); } hilite_thickness = tb->gadget.highlight_thickness; dx = (int)(tb->rectangle.x + hilite_thickness); dy = (int)(tb->rectangle.y + hilite_thickness); width = (int) ( tb->rectangle.width - (hilite_thickness << 1)); height = (int) ( tb->rectangle.height - (hilite_thickness << 1)); XmeDrawShadows (XtDisplay (tb), XtWindow (tb), top_gc, bot_gc, dx, dy, width, height, tb->gadget.shadow_thickness, XmSHADOW_OUT); } /* BEGIN OSF Fix pir 1778 */ /************************************************************************ * * SetToggleSize(newtbg) * Set size properly when XmNselectPixmap or XmNselectInsensitivePixmaps * are set in addition to the corresponding labelPixmaps. Have to pick * the largest dimensions. * ************************************************************************/ static void SetToggleSize( XmToggleButtonGadget newtbg) { unsigned int maxW, maxH, tmpW, tmpH; maxW = maxH = tmpW = tmpH = 0; /* We know it's a pixmap so find out how how big it is */ if (XtIsSensitive ((Widget) newtbg)) { if (!IsNull(PixmapOn(newtbg))) { XmeGetPixmapData(XtScreen(newtbg), PixmapOn(newtbg), NULL, NULL, NULL, NULL, NULL, NULL, &tmpW, &tmpH); ASSIGN_MAX(maxW, tmpW); ASSIGN_MAX(maxH, tmpH); } if (!IsNull(PixmapOff(newtbg))) { XmeGetPixmapData(XtScreen(newtbg), PixmapOff(newtbg), NULL, NULL, NULL, NULL, NULL, NULL, &tmpW, &tmpH); ASSIGN_MAX(maxW, tmpW); ASSIGN_MAX(maxH, tmpH); } if (!IsNull(PixmapInd(newtbg))) { XmeGetPixmapData(XtScreen(newtbg), PixmapInd(newtbg), NULL, NULL, NULL, NULL, NULL, NULL, &tmpW, &tmpH); ASSIGN_MAX(maxW, tmpW); ASSIGN_MAX(maxH, tmpH); } } else { if (!IsNull(PixmapInsenOn(newtbg))) { XmeGetPixmapData(XtScreen(newtbg), PixmapInsenOn(newtbg), NULL, NULL, NULL, NULL, NULL, NULL, &tmpW, &tmpH); ASSIGN_MAX(maxW, tmpW); ASSIGN_MAX(maxH, tmpH); } if (!IsNull(PixmapInsenOff(newtbg))) { XmeGetPixmapData(XtScreen(newtbg), PixmapInsenOff(newtbg), NULL, NULL, NULL, NULL, NULL, NULL, &tmpW, &tmpH); ASSIGN_MAX(maxW, tmpW); ASSIGN_MAX(maxH, tmpH); } if (!IsNull(PixmapInsenInd(newtbg))) { XmeGetPixmapData(XtScreen(newtbg), PixmapInsenInd(newtbg), NULL, NULL, NULL, NULL, NULL, NULL, &tmpW, &tmpH); ASSIGN_MAX(maxW, tmpW); ASSIGN_MAX(maxH, tmpH); } } LabG_TextRect(newtbg).width = (unsigned short) maxW; LabG_TextRect(newtbg).height = (unsigned short) maxH; /* Invoke Label's SetSize procedure. */ { XtWidgetProc resize; _XmProcessLock(); resize = xmLabelGadgetClassRec.rect_class.resize; _XmProcessUnlock(); (* resize) ((Widget) newtbg); } } /* END OSF Fix pir 1778 */ /* * DefaultSelectColor - an XtResourceDefaultProc for generating the * default select color. This may require examining the * XmNindicatorType and XmNhighlightColor resources, which will * happen to have real values only because they appear before * XmNselectColor in the resource list. */ static void DefaultSelectColor(Widget widget, int offset, XrmValue *value) { XmToggleButtonGadget tb = (XmToggleButtonGadget) widget; Boolean force_highlight = FALSE; XmDisplay xm_dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(widget)); Boolean enable_toggle_color = xm_dpy->display.enable_toggle_color; if (enable_toggle_color) { /* This code may misbehave for erroneous ind_type values. */ if (IsOneOfMany(TBG_IndType(tb))) { force_highlight = TRUE; } else if ((TBG_IndType(tb) == XmINVALID_TYPE) && XmIsRowColumn(XtParent(widget))) { XtVaGetValues(XtParent(widget), XmNradioBehavior, &force_highlight, NULL); } } if (force_highlight) { value->size = sizeof(LabG_HighlightColor(tb)); value->addr = (char *) &LabG_HighlightColor(tb); } else _XmSelectColorDefault(widget, offset, value); } /* * NormalizeIndOn - return the normalized value of XmNindicatorOn, * replacing XmINDICATOR_FILL and XmINDICATOR_BOX with the proper * absolute values. */ static unsigned char NormalizeIndOn(XmToggleButtonGadget tb) { unsigned char value = TBG_IndOn(tb); /* Convert XmINDICATOR_FILL to XmINDICATOR_CHECK_BOX? */ if (value == XmINDICATOR_FILL) { /* This routine may be called frequently, so reach directly into */ /* the XmDisplay rather than calling XtGetValues. */ XmDisplay xm_dpy = (XmDisplay) XmGetXmDisplay(XtDisplay((Widget) tb)); if (xm_dpy->display.enable_toggle_visual) value = XmINDICATOR_CHECK_BOX; } /* Convert XmINDICATOR_BOX to XmINDICATOR_3D_BOX (XmINDICATOR_FILL). */ else if (value == XmINDICATOR_BOX) { value = XmINDICATOR_3D_BOX; } return value; } /* * NormalizeIndType - return the normalized value of XmNindicatorType, * replacing XmONE_OF_MANY with the proper absolute value. */ static unsigned char NormalizeIndType(XmToggleButtonGadget tb) { unsigned char value = TBG_IndType(tb); if (value == XmONE_OF_MANY) { /* This routine may be called frequently, so reach directly into */ /* the XmDisplay rather than calling XtGetValues. */ XmDisplay xm_dpy = (XmDisplay) XmGetXmDisplay(XtDisplay((Widget) tb)); if (xm_dpy->display.enable_toggle_visual) value = XmONE_OF_MANY_ROUND; else value = XmONE_OF_MANY_DIAMOND; } return value; }