/* * Motif * * Copyright (c) 1987-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these librararies and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* * HISTORY */ #ifdef REV_INFO #ifndef lint static char rcsid[] = "$TOG: Label.c /main/26 1997/06/18 17:40:00 samborn $" #endif #endif /* (c) Copyright 1989, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */ /* (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "GadgetUtiI.h" #include "GMUtilsI.h" #include "LabelGI.h" #include "LabelI.h" #include "MessagesI.h" #include "MenuProcI.h" #include "PrimitiveI.h" #include "RepTypeI.h" #include "ScreenI.h" #include "TransferI.h" #include "TravActI.h" #include "XmI.h" #include "XmosI.h" #include "XmStringI.h" #include #include #include #ifdef FIX_1381 #include #endif #ifdef FIX_1521 #ifdef USE_XFT #include "XmRenderTI.h" #include #endif #endif #define FIX_1442 #define FIX_1484 #define FIX_1504 #define Pix(w) ((w)->label.pixmap) #define Pix_insen(w) ((w)->label.pixmap_insen) /* Warning Messages */ #define CS_STRING_MESSAGE _XmMMsgLabel_0003 #define ACC_MESSAGE _XmMMsgLabel_0004 /******** Static Function Declarations ********/ static void ClassInitialize(void); static void ClassPartInitialize(WidgetClass c); 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); static void SetNormalGC(XmLabelWidget lw); static void Resize(Widget wid); static void Initialize(Widget req, Widget new_w, ArgList args, Cardinal *num_args); static XtGeometryResult QueryGeometry(Widget wid, XtWidgetGeometry *intended, XtWidgetGeometry *reply); static void Destroy(Widget w); static void Redisplay(Widget wid, XEvent *event, Region region); static void Enter(Widget wid, XEvent *event, String *params, Cardinal *num_params); static void Leave(Widget wid, XEvent *event, String *params, Cardinal *num_params); static Boolean SetValues(Widget cw, Widget rw, Widget nw, ArgList args, Cardinal *num_args); static void SetOverrideCallback(Widget wid); static void Help(Widget w, XEvent *event, String *params, Cardinal *num_params); static void GetLabelString(Widget wid, int resource, XtArgVal *value); static void GetAccelerator(Widget wid, int resource, XtArgVal *value); static void GetAcceleratorText(Widget wid, int resource, XtArgVal *value); static XmStringCharSet _XmStringCharSetCreate(XmStringCharSet stringcharset); static void GetMnemonicCharSet(Widget wid, int resource, XtArgVal *value); static void SetValuesAlmost(Widget cw, Widget nw, XtWidgetGeometry *request, XtWidgetGeometry *reply); static Boolean XmLabelGetDisplayRect(Widget w, XRectangle *displayrect); static Boolean XmLabelGetBaselines(Widget wid, Dimension **baselines, int *line_count); static void XmLabelMarginsProc(Widget w, XmBaselineMargins *margins_rec); static Widget GetPixmapDragIcon(Widget w); static void ProcessDrag(Widget w, XEvent *event, String *params, Cardinal *num_params); static void SetActivateCallbackState(Widget w, XmActivateState state); static void CheckSetRenderTable(Widget wid, int offset, XrmValue *value); static void FromPaddingPixels(Widget, int, XtArgVal *); static XmImportOperator ToPaddingPixels(Widget, int, XtArgVal*); static XtPointer LabelGetValue(Widget, int); static void LabelSetValue(Widget, XtPointer, int); static int LabelPreferredValue(Widget); static char* GetLabelAccelerator(Widget); static KeySym GetLabelMnemonic(Widget); static XtPointer ConvertToEncoding(Widget, char*, Atom, unsigned long *, Boolean *); /******** End Static Function Declarations ********/ void _XmLabelConvert(Widget w, XtPointer ignore, XmConvertCallbackStruct*); /* Transfer trait record */ static XmConst XmTransferTraitRec LabelTransfer = { 0, /* version */ (XmConvertCallbackProc) _XmLabelConvert, /* convertProc */ NULL, /* destinationProc */ NULL /* destinationPreHookProc */ }; /* Menu Savvy trait record */ static XmConst XmMenuSavvyTraitRec MenuSavvyRecord = { 0, /* version */ (XmMenuSavvyDisableProc) SetActivateCallbackState, /* disableCallback */ GetLabelAccelerator, /* getAccelerator */ GetLabelMnemonic, /* getMnemonic */ (XmMenuSavvyGetActivateCBNameProc) NULL, /* getActivateCBName */ }; /* Access Textual trait record */ XmAccessTextualTraitRec _XmLabel_AccessTextualRecord = { 0, /* version */ LabelGetValue, /* getValueMethod */ LabelSetValue, /* setValuesMethod */ LabelPreferredValue, /* preferredFormat */ }; /* Default translations and action recs */ static XtTranslations default_parsed; #define defaultTranslations _XmLabel_defaultTranslations static XtTranslations menu_parsed; #define menuTranslations _XmLabel_menuTranslations static XtActionsRec ActionsList[] = { { "Enter", Enter }, { "Leave", Leave }, { "Help", Help }, { "ProcessDrag", ProcessDrag } }; /* Here are the translations used by the subclasses for menu traversal */ /* The matching actions are defined in RowColumn.c */ #define menu_traversal_events _XmLabel_menu_traversal_events static XtResource resources[] = { { XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf(XmLabelRec, primitive.shadow_thickness), XmRImmediate, (XtPointer) 0 }, { XmNalignment, XmCAlignment, XmRAlignment, sizeof(unsigned char), XtOffsetOf(XmLabelRec, label.alignment), XmRImmediate, (XtPointer) XmALIGNMENT_CENTER }, { XmNlabelType, XmCLabelType, XmRLabelType, sizeof(unsigned char), XtOffsetOf(XmLabelRec, label.label_type), XmRImmediate, (XtPointer) XmSTRING }, { XmNmarginWidth, XmCMarginWidth, XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf(XmLabelRec, label.margin_width), XmRImmediate, (XtPointer) 2 }, { XmNmarginHeight, XmCMarginHeight, XmRVerticalDimension, sizeof(Dimension), XtOffsetOf(XmLabelRec, label.margin_height), XmRImmediate, (XtPointer) 2 }, { XmNmarginLeft, XmCMarginLeft, XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf(XmLabelRec, label.margin_left), XmRImmediate, (XtPointer) 0 }, { XmNmarginRight, XmCMarginRight, XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf(XmLabelRec, label.margin_right), XmRImmediate, (XtPointer) 0 }, { XmNmarginTop, XmCMarginTop, XmRVerticalDimension, sizeof(Dimension), XtOffsetOf(XmLabelRec, label.margin_top), XmRImmediate, (XtPointer) 0 }, { XmNmarginBottom, XmCMarginBottom, XmRVerticalDimension, sizeof(Dimension), XtOffsetOf(XmLabelRec, label.margin_bottom), XmRImmediate, (XtPointer) 0 }, { "pri.vate","Pri.vate",XmRBoolean, sizeof(Boolean), XtOffsetOf(XmLabelRec, label.check_set_render_table), XmRImmediate, (XtPointer) False }, { XmNfontList, XmCFontList, XmRFontList, sizeof(XmFontList), XtOffsetOf(XmLabelRec, label.font), XmRCallProc, (XtPointer)CheckSetRenderTable }, { XmNrenderTable, XmCRenderTable, XmRRenderTable, sizeof(XmRenderTable), XtOffsetOf(XmLabelRec, label.font), XmRCallProc, (XtPointer)CheckSetRenderTable }, { XmNlabelPixmap, XmCLabelPixmap, XmRDynamicPixmap, sizeof(Pixmap), XtOffsetOf(XmLabelRec, label.pixmap), XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP }, { XmNlabelInsensitivePixmap, XmCLabelInsensitivePixmap, XmRDynamicPixmap, sizeof(Pixmap), XtOffsetOf(XmLabelRec, label.pixmap_insen), XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP }, { XmNlabelString, XmCXmString, XmRXmString, sizeof(XmString), XtOffsetOf(XmLabelRec, label._label), XmRImmediate, (XtPointer) NULL }, { XmNmnemonic, XmCMnemonic, XmRKeySym, sizeof(KeySym), XtOffsetOf(XmLabelRec, label.mnemonic), XmRImmediate, (XtPointer) XK_VoidSymbol }, { XmNmnemonicCharSet, XmCMnemonicCharSet, XmRString, sizeof(XmStringCharSet), XtOffsetOf(XmLabelRec, label.mnemonicCharset), XmRImmediate, (XtPointer) XmFONTLIST_DEFAULT_TAG }, { XmNaccelerator, XmCAccelerator, XmRString, sizeof(char *), XtOffsetOf(XmLabelRec, label.accelerator), XmRImmediate, (XtPointer) NULL }, { XmNacceleratorText, XmCAcceleratorText, XmRXmString, sizeof(XmString), XtOffsetOf(XmLabelRec, label._acc_text), XmRImmediate, (XtPointer) NULL }, { XmNrecomputeSize, XmCRecomputeSize, XmRBoolean, sizeof(Boolean), XtOffsetOf(XmLabelRec, label.recompute_size), XmRImmediate, (XtPointer) True }, { XmNstringDirection, XmCStringDirection, XmRStringDirection, sizeof(unsigned char), XtOffsetOf(XmLabelRec, label.string_direction), XmRImmediate, (XtPointer) XmDEFAULT_DIRECTION }, { XmNtraversalOn, XmCTraversalOn, XmRBoolean, sizeof(Boolean), XtOffsetOf(XmPrimitiveRec, primitive.traversal_on), XmRImmediate, (XtPointer) False }, { XmNhighlightThickness, XmCHighlightThickness, XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf(XmPrimitiveRec, primitive.highlight_thickness), XmRImmediate, (XtPointer) 0 }, #ifndef XM_PART_BC { XmNlayoutDirection, XmCLayoutDirection, XmRDirection, sizeof(XmDirection), XtOffsetOf(XmPrimitiveRec, primitive.layout_direction), XmRImmediate, (XtPointer) XmDEFAULT_DIRECTION }, #endif { XmNpixmapPlacement, XmCPixmapPlacement, XmRPixmapPlacement, sizeof(XmPixmapPlacement), XtOffsetOf(XmLabelRec, label.pixmap_placement), XmRImmediate, (XtPointer) XmPIXMAP_LEFT }, { XmNpixmapTextPadding, XmCSpace, XmRVerticalDimension, sizeof(Dimension), XtOffsetOf(XmLabelRec, label.pixmap_text_padding), XmRImmediate, (XtPointer) 2 } }; /* Definition for resources that need special processing in get values. */ static XmSyntheticResource syn_resources[] = { { XmNmarginWidth, sizeof(Dimension), XtOffsetOf(XmLabelRec, label.margin_width), XmeFromHorizontalPixels, XmeToHorizontalPixels }, { XmNmarginHeight, sizeof(Dimension), XtOffsetOf(XmLabelRec, label.margin_height), XmeFromVerticalPixels, XmeToVerticalPixels }, { XmNmarginLeft, sizeof(Dimension), XtOffsetOf(XmLabelRec, label.margin_left), XmeFromHorizontalPixels, XmeToHorizontalPixels }, { XmNmarginRight, sizeof(Dimension), XtOffsetOf(XmLabelRec, label.margin_right), XmeFromHorizontalPixels, XmeToHorizontalPixels }, { XmNmarginTop, sizeof(Dimension), XtOffsetOf(XmLabelRec, label.margin_top), XmeFromVerticalPixels, XmeToVerticalPixels }, { XmNmarginBottom, sizeof(Dimension), XtOffsetOf(XmLabelRec, label.margin_bottom), XmeFromVerticalPixels, XmeToVerticalPixels }, { XmNlabelString, sizeof(XmString), XtOffsetOf(XmLabelRec, label._label), GetLabelString, NULL }, { XmNmnemonicCharSet, sizeof(XmStringCharSet), XtOffsetOf(XmLabelRec, label.mnemonicCharset), GetMnemonicCharSet, NULL }, { XmNaccelerator, sizeof(String), XtOffsetOf(XmLabelRec, label.accelerator), GetAccelerator, NULL }, { XmNacceleratorText, sizeof(XmString), XtOffsetOf(XmLabelRec, label._acc_text), GetAcceleratorText, NULL }, { XmNpixmapTextPadding, sizeof(Dimension), XtOffsetOf(XmLabelRec, label.pixmap_text_padding), FromPaddingPixels, (XmImportProc) ToPaddingPixels } }; static XmBaseClassExtRec labelBaseClassExtRec = { NULL, /* Next extension */ NULLQUARK, /* record type XmQmotif */ XmBaseClassExtVersion, /* version */ sizeof(XmBaseClassExtRec), /* size */ InitializePrehook, /* initialize prehook */ XmInheritSetValuesPrehook, /* set_values prehook */ InitializePosthook, /* initialize posthook */ XmInheritSetValuesPosthook, /* set_values posthook */ XmInheritClass, /* secondary class */ XmInheritSecObjectCreate, /* creation proc */ XmInheritGetSecResData, /* getSecResData */ { 0 }, /* fast subclass */ XmInheritGetValuesPrehook, /* get_values prehook */ XmInheritGetValuesPosthook, /* get_values posthook */ NULL, /* classPartInitPrehook */ NULL, /* classPartInitPosthook */ NULL, /* ext_resources */ NULL, /* compiled_ext_resources */ 0, /* num_ext_resources */ FALSE, /* use_sub_resources */ XmInheritWidgetNavigable, /* widgetNavigable */ XmInheritFocusChange /* focusChange */ }; static XmPrimitiveClassExtRec _XmLabelPrimClassExtRec = { NULL, /* next_extension */ NULLQUARK, /* record_type */ XmPrimitiveClassExtVersion, /* version */ sizeof(XmPrimitiveClassExtRec), /* record_size */ XmLabelGetBaselines, /* widget_baseline */ XmLabelGetDisplayRect, /* widget_display_rect */ XmLabelMarginsProc, /* widget_margins */ }; externaldef (xmlabelclassrec) XmLabelClassRec xmLabelClassRec = { { (WidgetClass) &xmPrimitiveClassRec, /* superclass */ "XmLabel", /* class_name */ sizeof(XmLabelRec), /* widget_size */ ClassInitialize, /* class_initialize */ ClassPartInitialize, /* chained class init */ FALSE, /* class_inited */ Initialize, /* initialize */ NULL, /* initialize hook */ XtInheritRealize, /* realize */ ActionsList, /* actions */ XtNumber(ActionsList), /* num_actions */ resources, /* resources */ XtNumber(resources), /* num_resources */ NULLQUARK, /* xrm_class */ TRUE, /* compress_motion */ XtExposeCompressMaximal, /* compress_exposure */ TRUE, /* compress enter/exit */ FALSE, /* visible_interest */ Destroy, /* destroy */ Resize, /* resize */ Redisplay, /* expose */ SetValues, /* set_values */ NULL, /* set values hook */ SetValuesAlmost, /* set values almost */ NULL, /* get values hook */ NULL, /* accept_focus */ XtVersion, /* version */ NULL, /* callback offsetlst */ NULL, /* default trans */ QueryGeometry, /* query geo proc */ NULL, /* display accelerator */ (XtPointer)&labelBaseClassExtRec /* extension record */ }, { /* XmPrimitiveClassPart */ XmInheritBorderHighlight, /* border_highlight */ XmInheritBorderUnhighlight, /* border_unhighlight */ XtInheritTranslations, /* translations */ NULL, /* arm_and_activate */ syn_resources, /* syn resources */ XtNumber(syn_resources), /* num syn_resources */ (XtPointer)&_XmLabelPrimClassExtRec, /* extension */ }, { /* XmLabelClassPart */ SetOverrideCallback, /* override_callback */ NULL, /* menu procedure interface */ NULL, /* translations */ NULL /* extension record */ } }; externaldef(xmlabelwidgetclass) WidgetClass xmLabelWidgetClass = (WidgetClass) &xmLabelClassRec; /********************************************************************* * * ClassInitialize * This is the class initialization routine. It is called only * the first time a widget of this class is initialized. * ********************************************************************/ /*ARGSUSED*/ static void ClassInitialize(void) { /* Parse the various translation tables */ menu_parsed = XtParseTranslationTable(menuTranslations); default_parsed = XtParseTranslationTable(defaultTranslations); /* Set up base class extension quark */ labelBaseClassExtRec.record_type = XmQmotif; xmLabelClassRec.label_class.translations = (String) (XtParseTranslationTable(menu_traversal_events)); /* Install menu savvy on just this class */ XmeTraitSet((XtPointer) &xmLabelClassRec, XmQTmenuSavvy, (XtPointer) &MenuSavvyRecord); } void _XmLabelCloneMenuSavvy(WidgetClass wc, XmMenuSavvyTrait mst) { /* Modify and reinstall menu savvy trait */ if (mst->version == -1) { mst->version = MenuSavvyRecord.version; mst->disableCallback = MenuSavvyRecord.disableCallback; mst->getAccelerator = MenuSavvyRecord.getAccelerator; mst->getMnemonic = MenuSavvyRecord.getMnemonic; } /* Install the new record */ XmeTraitSet((XtPointer) wc, XmQTmenuSavvy, (XtPointer) mst); } char* _XmCBNameActivate() { return XmNactivateCallback; } char* _XmCBNameValueChanged() { return XmNvalueChangedCallback; } /************************************************************ * * InitializePosthook * Restore core class translations. * ************************************************************/ /*ARGSUSED*/ static void InitializePosthook(Widget req, /* unused */ Widget new_w, ArgList args, /* unused */ Cardinal *num_args) /* unused */ { _XmRestoreCoreClassTranslations (new_w); } /********************************************************************* * * ClassPartInitialize * Processes the class fields which need to be inherited. * ************************************************************************/ static void ClassPartInitialize(WidgetClass c) { register XmLabelWidgetClass wc = (XmLabelWidgetClass) c; XmLabelWidgetClass super = (XmLabelWidgetClass)wc->core_class.superclass; if (wc->label_class.setOverrideCallback == XmInheritSetOverrideCallback) wc->label_class.setOverrideCallback = super->label_class.setOverrideCallback; if (wc->label_class.translations == XtInheritTranslations) wc->label_class.translations = super->label_class.translations; _XmFastSubclassInit (c, XmLABEL_BIT); /* Install traits */ XmeTraitSet((XtPointer) c, XmQTtransfer, (XtPointer) &LabelTransfer); XmeTraitSet((XtPointer) c, XmQTaccessTextual, (XtPointer) &_XmLabel_AccessTextualRecord); } /************************************************************ * * InitializePrehook * Put the proper translations in core_class tm_table so * that the data is massaged correctly. * ************************************************************/ /*ARGSUSED*/ static void InitializePrehook(Widget req, /* unused */ Widget new_w, ArgList args, /* unused */ Cardinal *num_args) /* unused */ { unsigned char type; XmMenuSystemTrait menuSTrait; _XmProcessLock(); if (new_w->core.widget_class->core_class.tm_table != NULL) { _XmProcessUnlock(); return; } _XmSaveCoreClassTranslations (new_w); menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass((Widget) XtParent(new_w)), XmQTmenuSystem); if (menuSTrait != (XmMenuSystemTrait) NULL) type = menuSTrait->type(XtParent(new_w)); else type = XmWORK_AREA; if (type == XmWORK_AREA) new_w->core.widget_class->core_class.tm_table = (String) default_parsed; else new_w->core.widget_class->core_class.tm_table = (String) menu_parsed; _XmProcessUnlock(); } /************************************************************************ * * SetNormalGC * Create the normal and insensitive GC's for the gadget. * ************************************************************************/ static void SetNormalGC(XmLabelWidget lw) { XGCValues values; XtGCMask valueMask, dynamicMask; XFontStruct *fs = (XFontStruct *) NULL; valueMask = GCForeground | GCBackground | GCGraphicsExposures; dynamicMask = GCClipMask | GCClipXOrigin | GCClipYOrigin; values.foreground = lw->primitive.foreground; values.background = lw->core.background_pixel; values.graphics_exposures = False; if (XmeRenderTableGetDefaultFont(lw->label.font, &fs)) values.font = fs->fid, valueMask |= GCFont; lw->label.normal_GC = XtAllocateGC((Widget) lw, 0, valueMask, &values, dynamicMask, 0); #ifdef FIX_1381 /*generally gray insensitive foreground (instead stipple)*/ values.foreground = _XmAssignInsensitiveColor((Widget)lw); values.background = lw->core.background_pixel; #else valueMask |= GCFillStyle | GCStipple; values.foreground = lw->core.background_pixel; values.background = lw->primitive.foreground; values.fill_style = FillOpaqueStippled; values.stipple = _XmGetInsensitiveStippleBitmap((Widget) lw); #endif lw->label.insensitive_GC = XtAllocateGC((Widget) lw, 0, valueMask, &values, dynamicMask, 0); #ifdef FIX_1381 /*light shadow for insensitive text (instead stipple)*/ values.foreground = lw->primitive.top_shadow_color; lw->label.shadow_GC = XtAllocateGC((Widget) lw, 0, valueMask, &values, dynamicMask, 0); #endif } /************************************************************************ * * _XmCalcLabelDimensions() * Calculates the dimensions of the label text and pixmap, and updates * the TextRect fields appropriately. Called at Initialize and SetValues. * Also called by subclasses to recalculate label dimensions. * ************************************************************************/ void _XmCalcLabelDimensions(Widget wid) { XmLabelWidget newlw = (XmLabelWidget) wid; XmLabelPart *lp = &(newlw->label); unsigned int w = 0, h = 0; /* Initialize TextRect width and height to 0, change later if needed */ lp->acc_TextRect.width = 0; lp->acc_TextRect.height = 0; lp->StringRect.x = 0; lp->StringRect.y = 0; lp->StringRect.width = 0; lp->StringRect.height = 0; lp->PixmapRect.x = 0; lp->PixmapRect.y = 0; lp->PixmapRect.width = 0; lp->PixmapRect.height = 0; if (Lab_IsPixmap(newlw) || Lab_IsPixmapAndText(newlw)) { /* change NULL pixmap to refer to XmUNSPECIFIED_PIXMAP */ if (Pix(newlw) == (Pixmap)None) Pix(newlw) = XmUNSPECIFIED_PIXMAP; if (Pix_insen(newlw) == (Pixmap)None) Pix_insen(newlw) = XmUNSPECIFIED_PIXMAP; /* Is a pixmap so find out how big it is. */ if (XtIsSensitive(wid)) { if (Pix(newlw) != XmUNSPECIFIED_PIXMAP) { XmeGetPixmapData(XtScreen(newlw), Pix(newlw), NULL, NULL, NULL, NULL, NULL, NULL, &w, &h); lp->PixmapRect.width = (unsigned short) w; lp->PixmapRect.height = (unsigned short) h; } } else { Pixmap pix_use = Pix_insen (newlw) ; if (pix_use == XmUNSPECIFIED_PIXMAP) pix_use = Pix(newlw); if (pix_use != XmUNSPECIFIED_PIXMAP) { XmeGetPixmapData(XtScreen(newlw), pix_use, NULL, NULL, NULL, NULL, NULL, NULL, &w, &h); lp->PixmapRect.width = (unsigned short) w; lp->PixmapRect.height = (unsigned short) h; } } } if (Lab_IsText(newlw) || Lab_IsPixmapAndText(newlw)) { Dimension w, h; if (!XmStringEmpty (lp->_label)) { /* If we have a string then size it. */ XmStringExtent(lp->font, lp->_label, &w, &h); lp->StringRect.width = (unsigned short)w; lp->StringRect.height = (unsigned short)h; } } _XmLabelCalcTextRect(wid); if (lp->_acc_text != NULL) { Dimension w, h; /* If we have a string then size it. */ if (!XmStringEmpty (lp->_acc_text)) { XmStringExtent(lp->font, lp->_acc_text, &w, &h); lp->acc_TextRect.width = (unsigned short)w; lp->acc_TextRect.height = (unsigned short)h; } } } void _XmLabelCalcTextRect(Widget wid) { XmLabelWidget newlw = (XmLabelWidget) wid; XmLabelPart *lp = &(newlw->label); lp->TextRect.width = 0; lp->TextRect.height = 0; if (Lab_IsPixmap(newlw)) { lp->TextRect.width = lp->PixmapRect.width; lp->TextRect.height = lp->PixmapRect.height; } else if (Lab_IsText(newlw)) { lp->TextRect.width = lp->StringRect.width; lp->TextRect.height = lp->StringRect.height; } else if (Lab_IsPixmapAndText(newlw)) { if (lp->pixmap_placement == XmPIXMAP_TOP || lp->pixmap_placement == XmPIXMAP_BOTTOM) { lp->TextRect.height = lp->PixmapRect.height + lp->StringRect.height + lp->pixmap_text_padding; lp->TextRect.width = MAX(lp->StringRect.width, lp->PixmapRect.width); } else if (lp->pixmap_placement == XmPIXMAP_LEFT || lp->pixmap_placement == XmPIXMAP_RIGHT) { lp->TextRect.width = lp->PixmapRect.width + lp->StringRect.width + lp->pixmap_text_padding; lp->TextRect.height = MAX(lp->StringRect.height, lp->PixmapRect.height); } if (lp->pixmap_placement == XmPIXMAP_TOP) { lp->PixmapRect.y = 0; lp->StringRect.y = lp->PixmapRect.height + lp->pixmap_text_padding; } else if (lp->pixmap_placement == XmPIXMAP_BOTTOM) { lp->StringRect.y = 0; lp->PixmapRect.y = lp->StringRect.height + lp->pixmap_text_padding; } else if ((lp->pixmap_placement == XmPIXMAP_RIGHT && LayoutIsRtoLP(wid)) || (lp->pixmap_placement == XmPIXMAP_LEFT && !LayoutIsRtoLP(wid))) { lp->PixmapRect.x = 0; lp->StringRect.x = lp->PixmapRect.width + lp->pixmap_text_padding; } else if ((lp->pixmap_placement == XmPIXMAP_LEFT && LayoutIsRtoLP(wid)) || (lp->pixmap_placement == XmPIXMAP_RIGHT && !LayoutIsRtoLP(wid))) { lp->StringRect.x = 0; lp->PixmapRect.x = lp->StringRect.width + lp->pixmap_text_padding; } if (lp->pixmap_placement == XmPIXMAP_RIGHT || lp->pixmap_placement == XmPIXMAP_LEFT) { lp->PixmapRect.y = (lp->TextRect.height - lp->PixmapRect.height) / 2; lp->StringRect.y = (lp->TextRect.height - lp->StringRect.height) / 2; } else { if (lp->alignment == XmALIGNMENT_CENTER) { lp->PixmapRect.x = (lp->TextRect.width - lp->PixmapRect.width) / 2; lp->StringRect.x = (lp->TextRect.width - lp->StringRect.width) / 2; } else if ((lp->alignment == XmALIGNMENT_END && !LayoutIsRtoLP(wid)) || (lp->alignment == XmALIGNMENT_BEGINNING && LayoutIsRtoLP(wid))) { lp->PixmapRect.x = lp->TextRect.width - lp->PixmapRect.width; lp->StringRect.x = lp->TextRect.width - lp->StringRect.width; } } } } /************************************************************************ * * Resize * Sets new width, new height, and new label.TextRect * appropriately. This routine is called by Initialize and * SetValues. * ************************************************************************/ static void Resize(Widget wid) { XmLabelWidget newlw = (XmLabelWidget) wid; XmLabelPart *lp = &(newlw->label); int leftx, rightx; /* Increase margin width if necessary to accomodate accelerator text. */ if (lp->_acc_text != NULL) { if (LayoutIsRtoLP(newlw)) { if (lp->margin_left < (Dimension) (lp->acc_TextRect.width + LABEL_ACC_PAD) ) { int delta = lp->acc_TextRect.width + LABEL_ACC_PAD - lp->margin_left; lp->acc_left_delta += delta; lp->margin_left += delta; } } else { if (lp->margin_right < (Dimension) (lp->acc_TextRect.width + LABEL_ACC_PAD) ) { int delta = lp->acc_TextRect.width + LABEL_ACC_PAD - lp->margin_right; lp->acc_right_delta += delta; lp->margin_right += delta; } } } /* Has a width been specified? */ if (newlw->core.width == 0) newlw->core.width = (Dimension) lp->TextRect.width + lp->margin_left + lp->margin_right + (2 * (lp->margin_width + newlw->primitive.highlight_thickness + newlw->primitive.shadow_thickness)); leftx = (newlw->primitive.highlight_thickness + newlw->primitive.shadow_thickness + lp->margin_width + lp->margin_left); rightx = (newlw->core.width - (newlw->primitive.highlight_thickness + newlw->primitive.shadow_thickness + lp->margin_width + lp->margin_right)); switch (lp->alignment) { case XmALIGNMENT_BEGINNING: if (LayoutIsRtoLP(newlw)) lp->TextRect.x = rightx - lp->TextRect.width; else lp->TextRect.x = leftx; break; case XmALIGNMENT_END: if (LayoutIsRtoLP(newlw)) lp->TextRect.x = leftx; else lp->TextRect.x = rightx - lp->TextRect.width; break; default: /* CR 9737: Be careful about casting here, since rounding during */ /* division on Suns depends on the sign. */ lp->TextRect.x = leftx + (rightx - leftx - (int)lp->TextRect.width) / 2; break; } /* Has a height been specified? */ if (newlw->core.height == 0) newlw->core.height = (Dimension) MAX(lp->TextRect.height, lp->acc_TextRect.height) + lp->margin_top + lp->margin_bottom + (2 * (lp->margin_height + newlw->primitive.highlight_thickness + newlw->primitive.shadow_thickness)); lp->TextRect.y = (short) (newlw->primitive.highlight_thickness + newlw->primitive.shadow_thickness + lp->margin_height + lp->margin_top + ((int) (newlw->core.height - lp->margin_top - lp->margin_bottom - (2 * (lp->margin_height + newlw->primitive.highlight_thickness + newlw->primitive.shadow_thickness)) - lp->TextRect.height) / 2)); if (lp->_acc_text != NULL) { Dimension base_label, base_accText, diff; if (LayoutIsRtoLP(newlw)) lp->acc_TextRect.x = newlw->primitive.highlight_thickness + newlw->primitive.shadow_thickness + newlw->label.margin_width; else lp->acc_TextRect.x = (short) newlw->core.width - newlw->primitive.highlight_thickness - newlw->primitive.shadow_thickness - newlw->label.margin_width - newlw->label.margin_right + LABEL_ACC_PAD; lp->acc_TextRect.y = (short) (newlw->primitive.highlight_thickness + newlw->primitive.shadow_thickness + lp->margin_height + lp->margin_top + ((int) (newlw->core.height - lp->margin_top - lp->margin_bottom - (2 * (lp->margin_height + newlw->primitive.highlight_thickness + newlw->primitive.shadow_thickness)) - lp->acc_TextRect.height) / 2)); /* make sure the label and accelerator text line up */ /* when the fonts are different */ if (Lab_IsText(newlw) || Lab_IsPixmapAndText(newlw)) { base_label = XmStringBaseline (lp->font, lp->_label); base_accText = XmStringBaseline (lp->font, lp->_acc_text); if (base_label > base_accText) { diff = base_label - base_accText; lp->acc_TextRect.y = (short) lp->TextRect.y + diff - 1; } else if (base_label < base_accText) { diff = base_accText - base_label; lp->TextRect.y = (short) lp->acc_TextRect.y + diff - 1; } } } if (newlw->core.width == 0) /* set core width and height to a */ newlw->core.width = 1; /* default value so that it doesn't */ if (newlw->core.height == 0) /* generate a Toolkit Error */ newlw->core.height = 1; } /************************************************************ * * Initialize * This is the widget's instance initialize routine. It is * called once for each widget * ************************************************************/ /*ARGSUSED*/ static void Initialize( Widget req, Widget new_w, ArgList args, /* unused */ Cardinal *num_args) /* unused */ { XmLabelWidget lw = (XmLabelWidget) new_w; XmMenuSystemTrait menuSTrait; XtTranslations trans; lw->label.baselines = NULL; lw->label.computing_size = FALSE; /* if menuProcs is not set up yet, try again */ if (xmLabelClassRec.label_class.menuProcs == NULL) xmLabelClassRec.label_class.menuProcs = (XmMenuProc) _XmGetMenuProcContext(); /* Check for Invalid enumerated types */ if (!XmRepTypeValidValue(XmRID_LABEL_TYPE, lw->label.label_type, (Widget) lw)) { lw->label.label_type = XmSTRING; } if (!XmRepTypeValidValue(XmRID_ALIGNMENT, lw->label.alignment, (Widget) lw)) { lw->label.alignment = XmALIGNMENT_CENTER; } if (!XmRepTypeValidValue(XmRID_PIXMAP_PLACEMENT, lw->label.pixmap_placement, (Widget) lw)) { lw->label.pixmap_placement = XmPIXMAP_LEFT; } #ifndef NO_XM_1_2_BC /* * Some pre-Motif 2.0 XmManager subclasses may be bypassing the * synthetic resouce GetValues hook and passing us the manager's raw * string_direction field (which is now a layout_direction). Fixup * the common/simple cases. */ switch (lw->label.string_direction) { case XmLEFT_TO_RIGHT: case XmRIGHT_TO_LEFT: /* These string directions are erroneous uses of layout directions. */ lw->label.string_direction = XmDirectionToStringDirection(lw->label.string_direction); break; default: /* Other unknown layout directions will still get a warning. */ break; } #endif /* If layout_direction is set, it overrides string_direction. * If string_direction is set, but not layout_direction, use * string_direction value. * If neither is set, get from parent */ if (XmPrim_layout_direction(lw) != XmDEFAULT_DIRECTION) { if (lw->label.string_direction == XmDEFAULT_DIRECTION) lw->label.string_direction = XmDirectionToStringDirection(XmPrim_layout_direction(lw)); } else if (lw->label.string_direction != XmDEFAULT_DIRECTION) { XmPrim_layout_direction(lw) = XmStringDirectionToDirection(lw->label.string_direction); } else { XmPrim_layout_direction(lw) = _XmGetLayoutDirection(XtParent(new_w)); lw->label.string_direction = XmDirectionToStringDirection(XmPrim_layout_direction(lw)); } if (!XmRepTypeValidValue(XmRID_STRING_DIRECTION, lw->label.string_direction, (Widget) lw)) { lw->label.string_direction = XmSTRING_DIRECTION_L_TO_R; } /* Make a local copy of the font list */ if (lw->label.font == NULL) { /* CR 2990: Let subclasses choose their own default font. */ lw->label.font = XmeGetDefaultRenderTable (new_w, XmLABEL_FONTLIST); } lw->label.font = XmFontListCopy(lw->label.font); menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(new_w)), XmQTmenuSystem); /* get menu type and which button */ if (menuSTrait != (XmMenuSystemTrait) NULL) lw->label.menu_type = menuSTrait->type(XtParent(new_w)); else lw->label.menu_type = XmWORK_AREA; /* Handle the label string : * If label is the constant XmUNSPECIFIED, creates a empty XmString. * (this is used by DrawnB instead of a default conversion that leads * to a leak when someone provides a real label) * If no label string is given accept widget's name as default. * convert the widgets name to an XmString before storing; * else * save a copy of the given string. * If the given string is not an XmString issue an warning. */ if (lw->label._label == (XmString) XmUNSPECIFIED) { lw->label._label = XmeGetLocalizedString ((char *) NULL, /* reserved */ (Widget) lw, XmNlabelString, ""); } else if (lw->label._label == NULL) { lw->label._label = XmeGetLocalizedString ((char *) NULL, /* reserved */ (Widget) lw, XmNlabelString, lw->core.name); } else if (XmeStringIsValid(lw->label._label)) { lw->label._label= XmStringCopy(lw->label._label); } else { XmeWarning((Widget) lw, CS_STRING_MESSAGE); lw->label._label = XmStringCreateLocalized(lw->core.name); } /* * Convert the given mnemonicCharset to the internal Xm-form. */ if (lw->label.mnemonicCharset != NULL) lw->label.mnemonicCharset = _XmStringCharSetCreate (lw->label.mnemonicCharset); else lw->label.mnemonicCharset = _XmStringCharSetCreate (XmFONTLIST_DEFAULT_TAG); /* Accelerators are currently only supported in menus */ if ((lw->label._acc_text != NULL) && Lab_IsMenupane(lw)) { if (XmeStringIsValid((XmString) lw->label._acc_text)) { /* * Copy the input string into local space, if * not a Cascade Button */ if (XmIsCascadeButton(lw)) lw->label._acc_text = NULL; else lw->label._acc_text = XmStringCopy((XmString) lw->label._acc_text); } else { XmeWarning((Widget) lw, ACC_MESSAGE); lw->label._acc_text = NULL; } } else lw->label._acc_text = NULL; if ((lw->label.accelerator != NULL) && Lab_IsMenupane(lw)) { /* Copy the accelerator into local space */ lw->label.accelerator = XtNewString(lw->label.accelerator); } else lw->label.accelerator = NULL; lw->label.skipCallback = FALSE; lw->label.acc_right_delta = 0; lw->label.acc_left_delta = 0; /* If zero width and height was requested by the application, */ /* reset new_w's width and height to zero to allow Resize() */ /* to operate properly. */ if (req->core.width == 0) lw->core.width = 0; if (req->core.height == 0) lw->core.height = 0; /* CR 6267: Suppress highlight thickness before sizing also. */ if ((lw->label.menu_type == XmMENU_POPUP) || (lw->label.menu_type == XmMENU_PULLDOWN) || (lw->label.menu_type == XmMENU_BAR)) lw->primitive.highlight_thickness = 0; _XmCalcLabelDimensions(new_w); /* CR 7283: We can't use the resize method pointer, because */ /* subclasses haven't been initialized yet. */ Resize((Widget) lw); SetNormalGC(lw); /* Force the label traversal flag when in a menu. */ if ((XtClass(lw) == xmLabelWidgetClass) && ((lw->label.menu_type == XmMENU_POPUP) || (lw->label.menu_type == XmMENU_PULLDOWN) || (lw->label.menu_type == XmMENU_OPTION))) { lw->primitive.traversal_on = FALSE; lw->primitive.highlight_on_enter = FALSE; } /* if in menu, override with menu traversal translations */ if ((lw->label.menu_type == XmMENU_POPUP) || (lw->label.menu_type == XmMENU_PULLDOWN) || (lw->label.menu_type == XmMENU_BAR) || (lw->label.menu_type == XmMENU_OPTION)) { _XmProcessLock(); trans = (XtTranslations) ((XmLabelClassRec *)XtClass(lw))->label_class.translations; _XmProcessUnlock(); XtOverrideTranslations((Widget) lw, trans); } else { _XmProcessLock(); trans = (XtTranslations) ((XmPrimitiveClassRec *) XtClass(lw))->primitive_class.translations; _XmProcessUnlock(); /* Otherwise override with primitive traversal translations */ XtOverrideTranslations((Widget) lw, trans); } } /************************************************************************ * * QueryGeometry * ************************************************************************/ static XtGeometryResult QueryGeometry( Widget widget, XtWidgetGeometry *intended, XtWidgetGeometry *desired) { XmLabelWidget lw = (XmLabelWidget) widget; if (lw->label.recompute_size == FALSE) { desired->width = XtWidth(widget); desired->height = XtHeight(widget); } else { desired->width = (Dimension) lw->label.TextRect.width + (2 * (lw->label.margin_width + lw->primitive.highlight_thickness + lw->primitive.shadow_thickness)) + lw->label.margin_left + lw->label.margin_right; if (desired->width == 0) desired->width = 1; desired->height = (Dimension) MAX(lw->label.TextRect.height, lw->label.acc_TextRect.height) + (2 * (lw->label.margin_height + lw->primitive.highlight_thickness + lw->primitive.shadow_thickness)) + lw->label.margin_top + lw->label.margin_bottom; if (desired->height == 0) desired->height = 1; } return XmeReplyToQueryGeometry(widget, intended, desired); } /************************************************************************ * * Destroy * Free up the label gadget allocated space. This includes * the label, and GC's. * ************************************************************************/ static void Destroy( Widget w) { XmLabelWidget lw = (XmLabelWidget) w; if (lw->label._label != NULL) XmStringFree (lw->label._label); if (lw->label._acc_text != NULL) XmStringFree (lw->label._acc_text); if (lw->label.accelerator != NULL) XtFree (lw->label.accelerator); if (lw->label.font != NULL) XmFontListFree (lw->label.font); if (lw->label.mnemonicCharset != NULL) XtFree (lw->label.mnemonicCharset); if (lw->label.baselines != NULL) XtFree ((char*) lw->label.baselines); XtReleaseGC ((Widget) lw, lw->label.normal_GC); XtReleaseGC ((Widget) lw, lw->label.insensitive_GC); #ifdef FIX_1381 XtReleaseGC ((Widget) lw, lw->label.shadow_GC); #endif } /************************************************************************ * * Redisplay * ***********************************************************************/ static void Redisplay( Widget wid, XEvent *event, Region region) { XmLabelWidget lw = (XmLabelWidget) wid; GC gc; GC clipgc = NULL; XRectangle clip_rect; XmLabelPart *lp; Dimension availW, availH, marginal_width, marginal_height, max_text_height; int depth; lp = &(lw->label); /* * Set a clipping area if the label will overwrite critical margins. * A critical margin is defined to be "margin_{left,right, * top,bottom} margin" because it used for other things * such as default_button_shadows and accelerators. Note that * overwriting the "margin_{width,height}" margins is allowed. */ availH = lw->core.height; availW = lw->core.width; /* Adjust definitions of temporary variables */ marginal_width = lp->margin_left + lp->margin_right + (2 * (lw->primitive.highlight_thickness + lw->primitive.shadow_thickness)); marginal_height = lp->margin_top + lp->margin_bottom + (2 * (lw->primitive.highlight_thickness + lw->primitive.shadow_thickness)); max_text_height = MAX(lp->TextRect.height, lp->acc_TextRect.height); if (XtIsSensitive(wid)) clipgc = lp->normal_GC; else clipgc = lp->insensitive_GC; if ((availH < (Dimension)(marginal_height + max_text_height)) || (availW < (Dimension)(marginal_width + lp->TextRect.width))) { clip_rect.x = lw->primitive.highlight_thickness + lw->primitive.shadow_thickness + lp->margin_left; clip_rect.y = lw->primitive.highlight_thickness + lw->primitive.shadow_thickness + lp->margin_top; /* Don't allow negative dimensions. */ if (availW > marginal_width) clip_rect.width = availW - marginal_width; else clip_rect.width = 0; if (availH > marginal_height) clip_rect.height = availH - marginal_height; else clip_rect.height = 0; XSetClipRectangles(XtDisplay(lw), clipgc, 0,0, &clip_rect, 1, Unsorted); #ifdef FIX_1521 #ifdef USE_XFT _XmXftSetClipRectangles(XtDisplay(lw), XtWindow(lw), 0, 0, &clip_rect, 1); #endif #endif } else { XSetClipMask (XtDisplay (lw), clipgc, None); #ifdef FIX_1521 #ifdef USE_XFT XftDraw* draw = _XmXftDrawCreate(XtDisplay(lw), XtWindow(lw)); XftDrawSetClip(draw, NULL); #endif #endif } #ifdef USE_XFT /* it is needed to clear anti-aliased text before draw it again */ if ((Lab_IsText (lw) || Lab_IsPixmapAndText(lw)) && (lp->_label != NULL) && lp->TextRect.width > 0 && lp->TextRect.height > 0) { XClearArea(XtDisplay(lw), XtWindow(lw), lp->TextRect.x, lp->TextRect.y, lp->TextRect.width, lp->TextRect.height, False); } #endif if (Lab_IsPixmap(lw) || Lab_IsPixmapAndText(lw)) { if (XtIsSensitive(wid)) { if (Pix (lw) != XmUNSPECIFIED_PIXMAP) { gc = lp->normal_GC; XmeGetPixmapData(XtScreen(lw), Pix(lw), NULL, &depth, NULL, NULL, NULL, NULL, NULL, NULL); if (depth == lw->core.depth) XCopyArea (XtDisplay(lw), Pix(lw), XtWindow(lw), gc, 0, 0, lp->PixmapRect.width, lp->PixmapRect.height, lp->TextRect.x + lp->PixmapRect.x, lp->TextRect.y + lp->PixmapRect.y); else if (depth == 1) XCopyPlane (XtDisplay(lw), Pix(lw), XtWindow(lw), gc, 0, 0, lp->PixmapRect.width, lp->PixmapRect.height, lp->TextRect.x + lp->PixmapRect.x, lp->TextRect.y + lp->PixmapRect.y, 1); } } else { Pixmap pix_use = Pix_insen (lw) ; if (pix_use == XmUNSPECIFIED_PIXMAP) #ifdef FIX_1381 Pix_insen(lw) = pix_use = _XmConvertToBW(wid, Pix(lw)); #else pix_use = Pix(lw); #endif if (pix_use != XmUNSPECIFIED_PIXMAP) { gc = lp->insensitive_GC; XmeGetPixmapData(XtScreen(lw), pix_use, NULL, &depth, NULL, NULL, NULL, NULL, NULL, NULL); if (depth == lw->core.depth) XCopyArea (XtDisplay(lw), pix_use, XtWindow(lw), gc, 0, 0, lp->PixmapRect.width, lp->PixmapRect.height, lp->TextRect.x + lp->PixmapRect.x, lp->TextRect.y + lp->PixmapRect.y); else if (depth == 1) XCopyPlane (XtDisplay(lw), pix_use, XtWindow(lw), gc, 0, 0, lp->PixmapRect.width, lp->PixmapRect.height, lp->TextRect.x + lp->PixmapRect.x, lp->TextRect.y + lp->PixmapRect.y, 1); #ifndef FIX_1381 /* if no insensitive pixmap but a regular one, we need to do the stipple manually, since copyarea doesn't */ if (pix_use == Pix(lw)) { /* need fill stipple, not opaque */ XSetFillStyle(XtDisplay(lw), gc, FillStippled); XFillRectangle(XtDisplay(lw), XtWindow(lw), gc, lp->TextRect.x + lp->PixmapRect.x, lp->TextRect.y + lp->PixmapRect.y, lp->PixmapRect.width, lp->PixmapRect.height); XSetFillStyle(XtDisplay(lw), gc, FillOpaqueStippled); } #endif #ifdef FIX_1505 if (pix_use == Pix(lw)) { XSetFillStyle(XtDisplay(lw), gc, FillStippled); XSetStipple(XtDisplay(lw), gc, _XmGetInsensitiveStippleBitmap(lw)); XFillRectangle(XtDisplay(lw), XtWindow(lw), gc, lp->TextRect.x + lp->PixmapRect.x, lp->TextRect.y + lp->PixmapRect.y, lp->PixmapRect.width, lp->PixmapRect.height); XSetFillStyle(XtDisplay(lw), gc, FillSolid); } #endif } } } if ((Lab_IsText (lw) || Lab_IsPixmapAndText(lw)) && (lp->_label != NULL)) { if (lp->mnemonic != XK_VoidSymbol) { /* CR 5181: Convert the mnemonic keysym to a character string. */ char tmp[MB_LEN_MAX * 2]; XmString underline; tmp[_XmOSKeySymToCharacter(lp->mnemonic, NULL, tmp)] = '\0'; underline = XmStringCreate(tmp, lp->mnemonicCharset); #ifdef FIX_1381 if (XtIsSensitive(wid) ) { /*Draw normal text*/ XmStringDrawUnderline(XtDisplay(lw), XtWindow(lw), lp->font, lp->_label, lp->normal_GC, lp->TextRect.x + lp->StringRect.x, lp->TextRect.y + lp->StringRect.y, lp->StringRect.width, lp->alignment, XmPrim_layout_direction(lw), NULL, underline); } else { /*Draw shadow for insensitive text*/ XmStringDrawUnderline(XtDisplay(lw), XtWindow(lw), lp->font, lp->_label, lp->shadow_GC, lp->TextRect.x+1 + lp->StringRect.x, lp->TextRect.y+1 + lp->StringRect.y, lp->StringRect.width, lp->alignment, XmPrim_layout_direction(lw), NULL, underline); /*Draw insensitive text*/ XmStringDrawUnderline(XtDisplay(lw), XtWindow(lw), lp->font, lp->_label, lp->insensitive_GC, lp->TextRect.x + lp->StringRect.x, lp->TextRect.y + lp->StringRect.y, lp->StringRect.width, lp->alignment, XmPrim_layout_direction(lw), NULL, underline); } #else XmStringDrawUnderline(XtDisplay(lw), XtWindow(lw), lp->font, lp->_label, (XtIsSensitive(wid) ? lp->normal_GC : lp->insensitive_GC), lp->TextRect.x + lp->StringRect.x, lp->TextRect.y + lp->StringRect.y, lp->StringRect.width, lp->alignment, XmPrim_layout_direction(lw), NULL, underline); #endif XmStringFree(underline); } else #ifdef FIX_1381 { if (XtIsSensitive(wid) ) { /*Draw normal text*/ XmStringDraw (XtDisplay(lw), XtWindow(lw), lp->font, lp->_label, lp->normal_GC, lp->TextRect.x + lp->StringRect.x, lp->TextRect.y + lp->StringRect.y, lp->StringRect.width, lp->alignment, XmPrim_layout_direction(lw), NULL); } else { /*Draw shadow for insensitive text*/ XmStringDraw (XtDisplay(lw), XtWindow(lw), lp->font, lp->_label, lp->shadow_GC, lp->TextRect.x+1 + lp->StringRect.x, lp->TextRect.y+1 + lp->StringRect.y, lp->StringRect.width, lp->alignment, XmPrim_layout_direction(lw), NULL); /*Draw insensitive text*/ XmStringDraw (XtDisplay(lw), XtWindow(lw), lp->font, lp->_label, lp->insensitive_GC, lp->TextRect.x + lp->StringRect.x, lp->TextRect.y + lp->StringRect.y, lp->StringRect.width, lp->alignment, XmPrim_layout_direction(lw), NULL); } } #else XmStringDraw (XtDisplay(lw), XtWindow(lw), lp->font, lp->_label, (XtIsSensitive(wid) ? lp->normal_GC : lp->insensitive_GC), lp->TextRect.x + lp->StringRect.x, lp->TextRect.y + lp->StringRect.y, lp->StringRect.width, lp->alignment, XmPrim_layout_direction(lw), NULL); #endif #ifndef FIX_1381 #ifdef USE_XFT if (!XtIsSensitive(wid)) { XSetFillStyle(XtDisplay(lw), lp->insensitive_GC, FillStippled); XFillRectangle(XtDisplay(lw), XtWindow(lw), lp->insensitive_GC, lp->TextRect.x + lp->StringRect.x, lp->TextRect.y + lp->StringRect.y, lp->StringRect.width, lp->StringRect.height); XSetFillStyle(XtDisplay(lw), lp->insensitive_GC, FillOpaqueStippled); } #endif #endif } if (lp->_acc_text != NULL) { /* Since accelerator text is drawn by moving in from the right, * it is possible to overwrite label text when there is clipping, * Therefore draw accelerator text only if there is enough * room for everything */ if (lw->core.width >= (Dimension) (2 * (lw->primitive.highlight_thickness + lw->primitive.shadow_thickness + lp->margin_width) + lp->margin_left + lp->TextRect.width + lp->margin_right)) #ifdef FIX_1381 if (XtIsSensitive(wid) ) { /*Draw normal text*/ XmStringDraw (XtDisplay(lw), XtWindow(lw), lp->font, lp->_acc_text, lp->normal_GC, lp->acc_TextRect.x, lp->acc_TextRect.y, lp->acc_TextRect.width, XmALIGNMENT_END, XmPrim_layout_direction(lw), NULL); } else { /*Draw shadow for insensitive text*/ XmStringDraw (XtDisplay(lw), XtWindow(lw), lp->font, lp->_acc_text, lp->shadow_GC, lp->acc_TextRect.x+1, lp->acc_TextRect.y+1, lp->acc_TextRect.width, XmALIGNMENT_END, XmPrim_layout_direction(lw), NULL); /*Draw insensitive text*/ XmStringDraw (XtDisplay(lw), XtWindow(lw), lp->font, lp->_acc_text, lp->insensitive_GC, lp->acc_TextRect.x, lp->acc_TextRect.y, lp->acc_TextRect.width, XmALIGNMENT_END, XmPrim_layout_direction(lw), NULL); } #else XmStringDraw (XtDisplay(lw), XtWindow(lw), lp->font, lp->_acc_text, (XtIsSensitive(wid) ? lp->normal_GC : lp->insensitive_GC), lp->acc_TextRect.x, lp->acc_TextRect.y, lp->acc_TextRect.width, XmALIGNMENT_END, XmPrim_layout_direction(lw), NULL); #endif } /* Redraw the proper highlight */ if (! Lab_IsMenupane(lw) && Lab_MenuType(lw) != XmMENU_BAR) { XtExposeProc expose; _XmProcessLock(); expose = (xmPrimitiveClassRec.core_class.expose); _XmProcessUnlock(); /* Envelop our superclass expose method */ (*(expose))((Widget) lw, event, region); } } /********************************************************************** * * Enter * *********************************************************************/ static void Enter(Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmLabelWidget w = (XmLabelWidget) wid; if (w->primitive.highlight_on_enter) _XmPrimitiveEnter (wid, event, params, num_params); } /********************************************************************** * * Leave * *********************************************************************/ static void Leave(Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmLabelWidget w = (XmLabelWidget) wid; if (w->primitive.highlight_on_enter) _XmPrimitiveLeave ((Widget) w, event, params, num_params); } /************************************************************************ * * SetValues * This routine will take care of any changes that have been made. * ************************************************************************/ /*ARGSUSED*/ static Boolean SetValues(Widget cw, Widget rw, Widget nw, ArgList args, /* unused */ Cardinal *num_args) /* unused */ { XmLabelWidget current = (XmLabelWidget) cw; XmLabelWidget req = (XmLabelWidget) rw; XmLabelWidget new_w = (XmLabelWidget) nw; Boolean flag = FALSE; Boolean newstring = FALSE; XmLabelPart *newlp, *curlp, *reqlp; Boolean ProcessFlag = FALSE; Boolean CleanupFontFlag = FALSE; Boolean Call_Resize = False; XmMenuSystemTrait menuSTrait; /* Get pointers to the label parts */ newlp = &(new_w->label); curlp = &(current->label); reqlp = &(req->label); /* Discard the baseline cache if it is no longer valid. */ if ((newlp->_label != curlp->_label) || (newlp->font != curlp->font)) { if (newlp->baselines) { XtFree ((char*) newlp->baselines); newlp->baselines = NULL; } } /* If the label has changed, make a copy of the new label */ /* and free the old label. */ if (newlp->_label != curlp->_label) { newstring = TRUE; if (newlp->_label == NULL) { newlp->_label = XmStringCreateLocalized(new_w->core.name); } else { if (XmeStringIsValid((XmString) newlp->_label)) newlp->_label = XmStringCopy((XmString) newlp->_label); else { XmeWarning((Widget) new_w, CS_STRING_MESSAGE); newlp->_label = XmStringCreateLocalized(new_w->core.name); } } XmStringFree(curlp->_label); curlp->_label= NULL; reqlp->_label= NULL; } if (newlp->margin_right != curlp->margin_right) newlp->acc_right_delta = 0; if (newlp->margin_left != curlp->margin_left) newlp->acc_left_delta = 0; if ((newlp->_acc_text != curlp->_acc_text) && Lab_IsMenupane(new_w)) { /* BEGIN OSF Fix pir 1098 */ newstring = TRUE; /* END OSF Fix pir 1098 */ if (newlp->_acc_text != NULL) { if (XmeStringIsValid((XmString) newlp->_acc_text)) { if ((XmIsCascadeButton (new_w)) && (newlp->_acc_text != NULL)) newlp->_acc_text = NULL; else newlp->_acc_text = XmStringCopy((XmString) newlp->_acc_text); XmStringFree(curlp->_acc_text); curlp->_acc_text= NULL; reqlp->_acc_text= NULL; } else { XmeWarning((Widget) new_w, ACC_MESSAGE); newlp->_acc_text = NULL; curlp->_acc_text= NULL; reqlp->_acc_text= NULL; } } /* BEGIN OSF Fix pir 1098 */ else if (curlp->_acc_text) { /* CR 3481: Don't blindly force the margin back to 0; */ /* try to preserve the user specified value. */ if (LayoutIsRtoLP(new_w)) { newlp->margin_left -= newlp->acc_left_delta; newlp->acc_left_delta = 0; } else { newlp->margin_right -= newlp->acc_right_delta; newlp->acc_right_delta = 0; } } /* END OSF Fix pir 1098 */ } else newlp->_acc_text = curlp->_acc_text; if (newlp->font != curlp->font) { CleanupFontFlag = True; if (newlp->font == NULL) { /* CR 2990: Let subclasses determine default fonts. */ newlp->font = XmeGetDefaultRenderTable((Widget) new_w, XmLABEL_FONTLIST); } newlp->font = XmFontListCopy (newlp->font); } if ((new_w->label.menu_type == XmMENU_POPUP) || (new_w->label.menu_type == XmMENU_PULLDOWN) || (new_w->label.menu_type == XmMENU_BAR)) new_w->primitive.highlight_thickness = 0; if (!XmRepTypeValidValue(XmRID_LABEL_TYPE, new_w->label.label_type, (Widget) new_w)) { new_w->label.label_type = current->label.label_type; } #ifdef FIX_1484 if (!XmRepTypeValidValue(XmRID_PIXMAP_PLACEMENT, new_w->label.pixmap_placement, #else if (!XmRepTypeValidValue(XmRID_LABEL_TYPE, new_w->label.pixmap_placement, #endif (Widget) new_w)) { new_w->label.pixmap_placement = current->label.pixmap_placement; } if (LayoutP(new_w) != LayoutP(current)) { /* if no new margins specified swap them */ if ((LayoutIsRtoLP(current) != LayoutIsRtoLP(new_w)) && (Lab_MarginLeft(current) == Lab_MarginLeft(new_w)) && (Lab_MarginRight(current) == Lab_MarginRight(new_w))) { Lab_MarginLeft(new_w) = Lab_MarginRight(current); Lab_MarginRight(new_w) = Lab_MarginLeft(current); } flag = TRUE; } /* ValidateInputs(new_w); */ #ifdef FIX_1504 _XmCalcLabelDimensions((Widget) new_w); Boolean pixmap_size_changed = ((newlp->PixmapRect.width != curlp->PixmapRect.width) || (newlp->PixmapRect.height != curlp->PixmapRect.height)); #endif if (((Lab_IsText(new_w) || Lab_IsPixmapAndText(new_w)) && ((newstring) || (newlp->font != curlp->font))) || ((Lab_IsPixmap(new_w) || Lab_IsPixmapAndText(new_w)) && ((newlp->pixmap != curlp->pixmap) || (newlp->pixmap_insen != curlp->pixmap_insen) || /* When you have different sized pixmaps for sensitive and */ /* insensitive states and sensitivity changes, */ /* the right size is chosen. (osfP2560) */ #ifdef FIX_1504 (XtIsSensitive(nw) != XtIsSensitive(cw))) && pixmap_size_changed) || #else (XtIsSensitive(nw) != XtIsSensitive(cw)))) || #endif (Lab_IsPixmapAndText(new_w) && (newlp->pixmap_placement != curlp->pixmap_placement)) || (newlp->label_type != curlp->label_type)) { /* CR 9179: Redo CR 5419 changes. */ if (newlp->recompute_size) { if (req->core.width == current->core.width) new_w->core.width = 0; if (req->core.height == current->core.height) new_w->core.height = 0; } #ifndef FIX_1504 _XmCalcLabelDimensions((Widget) new_w); #endif Call_Resize = True; flag = True; } if ((newlp->alignment != curlp->alignment) || (XmPrim_layout_direction(new_w) != XmPrim_layout_direction(current))) { if (!XmRepTypeValidValue(XmRID_ALIGNMENT, new_w->label.alignment, (Widget) new_w)) { new_w->label.alignment = current->label.alignment; } Call_Resize = True; flag = True; } if ((newlp->margin_height != curlp->margin_height) || (newlp->margin_width != curlp->margin_width) || (newlp->margin_left != curlp->margin_left) || (newlp->margin_right != curlp->margin_right) || (newlp->margin_top != curlp->margin_top) || (newlp->margin_bottom != curlp->margin_bottom) || (new_w->primitive.shadow_thickness != current->primitive.shadow_thickness) || (new_w->primitive.highlight_thickness != current->primitive.highlight_thickness) || ((new_w->core.width <= 0) || (new_w->core.height <= 0)) || (newlp->pixmap_text_padding != curlp->pixmap_text_padding)) { if (!XmRepTypeValidValue(XmRID_ALIGNMENT, new_w->label.alignment, (Widget) new_w)) { new_w->label.alignment = current->label.alignment; } if (!XmRepTypeValidValue(XmRID_STRING_DIRECTION, new_w->label.string_direction, (Widget) new_w)) { new_w->label.string_direction = current->label.string_direction; } if (newlp->recompute_size) { if (req->core.width == current->core.width) new_w->core.width = 0; if (req->core.height == current->core.height) new_w->core.height = 0; } Call_Resize = True; flag = True; } /* Resize is called only if we need to calculate the dimensions or */ /* coordinates for the string. */ if (Call_Resize) { XtWidgetProc resize; /* CR 5419: Suppress redundant calls to DrawnB's resize callbacks. */ Boolean was_computing = newlp->computing_size; newlp->computing_size = TRUE; _XmProcessLock(); resize = new_w->core.widget_class->core_class.resize; _XmProcessUnlock(); (* (resize)) ((Widget) new_w); newlp->computing_size = was_computing; } /* * If sensitivity of the label has changed then we must redisplay * the label. */ if (XtIsSensitive(nw) != XtIsSensitive(cw)) { flag = TRUE; } if ((new_w->primitive.foreground != current->primitive.foreground) || (new_w->core.background_pixel != current->core.background_pixel) || (newlp->font != curlp->font)) { XtReleaseGC((Widget) current, current->label.normal_GC); XtReleaseGC((Widget) current, current->label.insensitive_GC); SetNormalGC(new_w); flag = TRUE; } /* Force the traversal flag when in a menu. */ if ((XtClass(new_w) == xmLabelWidgetClass) && ((new_w->label.menu_type == XmMENU_POPUP) || (new_w->label.menu_type == XmMENU_PULLDOWN) || (new_w->label.menu_type == XmMENU_OPTION))) { new_w->primitive.traversal_on = FALSE; new_w->primitive.highlight_on_enter = FALSE; } if (new_w->primitive.traversal_on && (new_w->primitive.traversal_on != current->primitive.traversal_on) && new_w->core.tm.translations) { XtTranslations trans; if ((new_w->label.menu_type == XmMENU_POPUP) || (new_w->label.menu_type == XmMENU_PULLDOWN) || (new_w->label.menu_type == XmMENU_BAR) || (new_w->label.menu_type == XmMENU_OPTION)) { _XmProcessLock(); trans = (XtTranslations) ((XmLabelClassRec *)XtClass(new_w))->label_class.translations; _XmProcessUnlock(); if (trans) XtOverrideTranslations((Widget)new_w, trans); } else { _XmProcessLock(); trans = (XtTranslations) ((XmLabelClassRec*) XtClass(new_w))->primitive_class.translations; _XmProcessUnlock(); if (trans) XtOverrideTranslations ((Widget)new_w, trans); } } if ((new_w->label.menu_type != XmWORK_AREA) && (new_w->label.mnemonic != current->label.mnemonic)) { /* New grabs only required if mnemonic changes */ ProcessFlag = TRUE; if (new_w->label.label_type == XmSTRING || new_w->label.label_type == XmPIXMAP_AND_STRING) flag = TRUE; } if (new_w->label.mnemonicCharset != current->label.mnemonicCharset) { if (new_w->label.mnemonicCharset) new_w->label.mnemonicCharset = _XmStringCharSetCreate(new_w->label.mnemonicCharset); else new_w->label.mnemonicCharset = _XmStringCharSetCreate(XmFONTLIST_DEFAULT_TAG); if (current->label.mnemonicCharset != NULL) XtFree (current->label.mnemonicCharset); if (new_w->label.label_type == XmSTRING || new_w->label.label_type == XmPIXMAP_AND_STRING) flag = TRUE; } if (Lab_IsMenupane(new_w) && (new_w->label.accelerator != current->label.accelerator)) { if (newlp->accelerator != NULL) { /* Copy the accelerator into local space */ newlp->accelerator = XtNewString(newlp->accelerator); } XtFree(curlp->accelerator); curlp->accelerator = NULL; reqlp->accelerator = NULL; ProcessFlag = TRUE; } else newlp->accelerator = curlp->accelerator; menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(current)), XmQTmenuSystem); if (ProcessFlag && menuSTrait != NULL) menuSTrait->updateBindings((Widget)new_w, XmREPLACE); if (flag && (new_w->label.menu_type == XmMENU_PULLDOWN) && menuSTrait != NULL) menuSTrait->updateHistory(XtParent(new_w), (Widget) new_w, True); if (CleanupFontFlag) if (curlp->font) XmFontListFree(curlp->font); return flag; } /************************************************************************ * * SetActivateCallbackState * * This function is used as the method of the menuSavvy trait. It is * used by menu savvy parents to set whether or not the child will * invoke its own activate callback or whether it will defer to the * entryCallback of the parent. * ************************************************************************/ static void SetActivateCallbackState(Widget wid, XmActivateState state) { XmLabelWidget w = (XmLabelWidget) wid; switch (state) { case XmDISABLE_ACTIVATE: w->label.skipCallback = True; break; case XmENABLE_ACTIVATE: w->label.skipCallback = False; break; } } /************************************************************************ * * SetOverrideCallback * Used by subclasses. If this is set true, then there is a RowColumn * parent with the entryCallback resource set. The subclasses do not * do their activate callbacks, instead the RowColumn callbacks are called * by RowColumn. ************************************************************************/ static void SetOverrideCallback(Widget wid) { XmLabelWidget w = (XmLabelWidget) wid; w->label.skipCallback = True; } /************************************************************************ * * Help * This routine is called if the user made a help selection * on the widget. * ************************************************************************/ static void Help(Widget w, XEvent *event, String *params, Cardinal *num_params) { XmLabelWidget lw = (XmLabelWidget) w; Widget parent = XtParent(lw); XmMenuSystemTrait menuSTrait; menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(lw)), XmQTmenuSystem); if (Lab_IsMenupane(lw) && menuSTrait != NULL) menuSTrait->popdown((Widget) parent, event); _XmPrimitiveHelp((Widget) w, event, params, num_params); } /************************************************************************ * * GetLabelString * This is a get values hook function that returns the external * form of the label string from the internal form. * ***********************************************************************/ /*ARGSUSED*/ static void GetLabelString(Widget wid, int resource, /* unused */ XtArgVal *value) { XmLabelWidget lw = (XmLabelWidget) wid; XmString string; string = XmStringCopy(lw->label._label); *value = (XtArgVal) string; } /************************************************************************ * * GetAccelerator * This is a get values hook function that returns a copy * of the accelerator string. * ***********************************************************************/ /*ARGSUSED*/ static void GetAccelerator(Widget wid, int resource, /* unused */ XtArgVal *value) { XmLabelWidget lw = (XmLabelWidget) wid; String string; string = XtNewString(Lab_Accelerator(lw)); *value = (XtArgVal) string; } /************************************************************************ * * GetAcceleratorText * This is a get values hook function that returns the external * form of the accelerator text from the internal form. * ***********************************************************************/ /*ARGSUSED*/ static void GetAcceleratorText(Widget wid, int resource, /* unused */ XtArgVal *value) { XmLabelWidget lw = (XmLabelWidget) wid; XmString string; string = XmStringCopy(lw->label._acc_text); *value = (XtArgVal) string; } /************************************************************************ * * XmCreateLabel() * XmVaCreateLabel() * XmVaCreateManagedLabel() * Externally accessable function for creating a label gadget. * ************************************************************************/ Widget XmCreateLabel(Widget parent, char *name, Arg *arglist, Cardinal argCount) { return XtCreateWidget(name,xmLabelWidgetClass,parent,arglist,argCount); } Widget XmVaCreateLabel( Widget parent, char *name, ...) { register Widget w; va_list var; int count; Va_start(var,name); count = XmeCountVaListSimple(var); va_end(var); Va_start(var, name); w = XmeVLCreateWidget(name, xmLabelWidgetClass, parent, False, var, count); va_end(var); return w; } Widget XmVaCreateManagedLabel( Widget parent, char *name, ...) { Widget w = NULL; va_list var; int count; Va_start(var, name); count = XmeCountVaListSimple(var); va_end(var); Va_start(var, name); w = XmeVLCreateWidget(name, xmLabelWidgetClass, parent, True, var, count); va_end(var); return w; } static XmStringCharSet _XmStringCharSetCreate(XmStringCharSet stringcharset) { return (XmStringCharSet) XtNewString((char*) stringcharset); } /************************************************************************ * * GetMnemonicCharSet * This is a get values hook function that returns the external * form of the mnemonicCharSet from the internal form. Returns a * string containg the mnemonicCharSet. Caller must free the string. ***********************************************************************/ /*ARGSUSED*/ static void GetMnemonicCharSet(Widget wid, int resource, /* unused */ XtArgVal *value) { XmLabelWidget lw = (XmLabelWidget) wid; char *cset; int size; cset = NULL; if (lw->label.mnemonicCharset) { size = strlen (lw->label.mnemonicCharset); if (size > 0) cset = (char *) (_XmStringCharSetCreate(lw->label.mnemonicCharset)); } *value = (XtArgVal) cset; } /*ARGSUSED*/ static void SetValuesAlmost(Widget cw, /* unused */ Widget nw, XtWidgetGeometry *request, XtWidgetGeometry *reply) { XmLabelWidget new_w = (XmLabelWidget) nw; XtWidgetProc resize; _XmProcessLock(); resize = new_w->core.widget_class->core_class.resize; _XmProcessUnlock(); (* (resize)) ((Widget) new_w); *request = *reply; } /************************************************************************ * * XmLabelGetDisplayRect * A Class function which returns True if the widget being passed in * has a display rectangle associated with it. It also determines the * x,y coordinates of the character cell or pixmap relative to the origin, * and the width and height in pixels of the smallest rectangle that encloses * the text or pixmap. This is assigned to the variable being passed in * ***********************************************************************/ static Boolean XmLabelGetDisplayRect(Widget w, XRectangle *displayrect) { XmLabelWidget wid = (XmLabelWidget) w; (*displayrect).x = wid->label.TextRect.x; (*displayrect).y = wid->label.TextRect.y; (*displayrect).width = wid->label.TextRect.width; (*displayrect).height = wid->label.TextRect.height; return TRUE; } /************************************************************************ * * XmLabelGetBaselines * A Class function which when called returns True, if the widget * has a baseline and also determines the number of pixels from the y * origin to the first line of text and assigns it to the variable * being passed in. * ************************************************************************/ static Boolean XmLabelGetBaselines(Widget wid, Dimension **baselines, int *line_count) { XmLabelWidget lw = (XmLabelWidget)wid; Cardinal count; int delta; if (Lab_IsPixmap(wid)) return False; /* Compute raw baselines if unavailable. */ if (lw->label.baselines == NULL) { _XmStringGetBaselines(lw->label.font, lw->label._label, &(lw->label.baselines), &count); assert(lw->label.baselines != NULL); /* Store the current offset in an extra location. */ lw->label.baselines = (Dimension*) XtRealloc((char*) lw->label.baselines, (count+1) * sizeof(Dimension)); lw->label.baselines[count] = 0; } else { count = XmStringLineCount(lw->label._label); } /* Readjust offsets if necessary. */ delta = Lab_TextRect_y(lw) - lw->label.baselines[count]; if (delta) { int tmp; for (tmp = 0; tmp <= count; tmp++) lw->label.baselines[tmp] += delta; } /* Copy the cached data. */ *line_count = count; *baselines = (Dimension*) XtMalloc(*line_count * sizeof(Dimension)); memcpy((char*) *baselines, (char*) lw->label.baselines, *line_count * sizeof(Dimension)); return True; } /************************************************************************ * * XmLabelMarginsProc * ***********************************************************************/ /* ARGSUSED */ static void XmLabelMarginsProc(Widget w, XmBaselineMargins *margins_rec) { if (margins_rec->get_or_set == XmBASELINE_SET) { Lab_MarginTop(w) = margins_rec->margin_top; Lab_MarginBottom(w) = margins_rec->margin_bottom; } else { margins_rec->margin_top = Lab_MarginTop(w); margins_rec->margin_bottom = Lab_MarginBottom(w); margins_rec->shadow = Lab_Shadow(w); margins_rec->highlight = Lab_Highlight(w); margins_rec->text_height = Lab_TextRect_height(w); margins_rec->margin_height = Lab_MarginHeight(w); } } static Widget GetPixmapDragIcon(Widget w) { XmLabelWidget lw = (XmLabelWidget) w; Arg args[10]; int n; Widget drag_icon; Widget screen_object = XmGetXmScreen(XtScreen(w)); unsigned int width, height; int depth; /* It's a labelPixmap, use directly the pixmap */ XmeGetPixmapData(XtScreen(lw), Pix(lw), NULL, &depth, NULL, NULL, NULL, NULL, &width, &height); n = 0; XtSetArg(args[n], XmNhotX, 0), n++; XtSetArg(args[n], XmNhotY, 0), n++; XtSetArg(args[n], XmNwidth, width), n++; XtSetArg(args[n], XmNheight, height), n++; XtSetArg(args[n], XmNmaxWidth, width), n++; XtSetArg(args[n], XmNmaxHeight, height), n++; XtSetArg(args[n], XmNdepth, depth), n++; XtSetArg(args[n], XmNpixmap, Pix(lw)), n++; XtSetArg(args[n], XmNforeground, lw->core.background_pixel), n++; XtSetArg(args[n], XmNbackground, lw->primitive.foreground), n++; assert(n <= XtNumber(args)); drag_icon = XtCreateWidget("drag_icon", xmDragIconObjectClass, screen_object, args, n); return drag_icon; } /*ARGSUSED*/ static void ProcessDrag(Widget w, XEvent *event, String *params, Cardinal *num_params) { XmLabelWidget lw = (XmLabelWidget) w; Widget drag_icon; Arg args[10]; int n; Time _time = _XmGetDefaultTime(w, event); XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(w)); if (Lab_IsMenupane(w)) XAllowEvents(XtDisplay(w), SyncPointer, _time); /* Disallow drag if this is a cascade button and armed - Hack alert */ if (XmIsCascadeButton(w) && CB_IsArmed(w)) return; /* CDE - allow user to not drag labels and label subclasses also, disable drag if enable_btn1_transfer is set to BUTTON2_ADJUST and the trigger was button2 */ if (! dpy -> display.enable_unselectable_drag || (dpy -> display.enable_btn1_transfer == XmBUTTON2_ADJUST && event && event -> xany.type == ButtonPress && event -> xbutton.button == 2)) return; /* CR 5141: Don't allow multi-button drags; they just cause confusion. */ if (event && ! (event->xbutton.state & ~((Button1Mask >> 1) << event->xbutton.button) & (Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask))) { n = 0; XtSetArg(args[n], XmNcursorBackground, lw->core.background_pixel), n++; XtSetArg(args[n], XmNcursorForeground, lw->primitive.foreground), n++; /* If it's a labelPixmap, only specify the pixmap icon */ if (Lab_IsPixmap(lw) && (Pix(lw) != XmUNSPECIFIED_PIXMAP)) { drag_icon = GetPixmapDragIcon(w); XtSetArg(args[n], XmNsourcePixmapIcon, drag_icon), n++; } else { drag_icon = XmeGetTextualDragIcon(w); XtSetArg(args[n], XmNsourceCursorIcon, drag_icon), n++; } XtSetArg(args[n], XmNdragOperations, XmDROP_COPY), n++; (void) XmeDragSource(w, NULL, event, args, n); } } /*ARGSUSED*/ void _XmLabelConvert(Widget w, XtPointer ignore, XmConvertCallbackStruct *cs) { enum { XmA_MOTIF_COMPOUND_STRING, XmACOMPOUND_TEXT, XmATEXT, XmATARGETS, XmA_MOTIF_DROP, XmABACKGROUND, XmAFOREGROUND, XmAPIXEL, XmA_MOTIF_EXPORT_TARGETS, XmA_MOTIF_CLIPBOARD_TARGETS, #ifdef UTF8_SUPPORTED XmAUTF8_STRING, #endif NUM_ATOMS }; static char *atom_names[] = { XmS_MOTIF_COMPOUND_STRING, XmSCOMPOUND_TEXT, XmSTEXT, XmSTARGETS, XmS_MOTIF_DROP, XmIBACKGROUND, XmIFOREGROUND, XmIPIXEL, XmS_MOTIF_EXPORT_TARGETS, XmS_MOTIF_CLIPBOARD_TARGETS, #ifdef UTF8_SUPPORTED XmSUTF8_STRING #endif }; Atom atoms[XtNumber(atom_names)]; Atom C_ENCODING; int target_count = 0; Atom type = None; XtPointer value = NULL; unsigned long size = 0; int format = 8; XmString label_string; Pixmap label_pixmap; Boolean is_pixmap, is_text; if (w == (Widget) NULL) { cs->status = XmCONVERT_REFUSE; return; } C_ENCODING = XmeGetEncodingAtom(w); assert(XtNumber(atom_names) == NUM_ATOMS); XInternAtoms(XtDisplayOfObject(w), atom_names, XtNumber(atom_names), False, atoms); if (cs->selection != atoms[XmA_MOTIF_DROP]) { cs->status = XmCONVERT_REFUSE; return; } if (XtIsWidget(w)) { label_string = ((XmLabelWidget) w)->label._label; label_pixmap = ((XmLabelWidget) w)->label.pixmap; is_pixmap = Lab_IsPixmap(w) || Lab_IsPixmapAndText(w); is_text = Lab_IsText(w) || Lab_IsPixmapAndText(w); } else { label_string = ((XmLabelGadget) w)->label._label; label_pixmap = ((XmLabelGadget) w)->label.pixmap; is_pixmap = LabG_IsPixmap(w) || LabG_IsPixmapAndText(w);; is_text = LabG_IsText(w) || LabG_IsPixmapAndText(w); } if (cs->target == atoms[XmATARGETS] || cs->target == atoms[XmA_MOTIF_EXPORT_TARGETS] || cs->target == atoms[XmA_MOTIF_CLIPBOARD_TARGETS]) { Atom *targs; if (cs->target == atoms[XmATARGETS]) { targs = XmeStandardTargets(w, 7, &target_count); } else { target_count = 0; targs = (Atom *) XtMalloc(sizeof(Atom) * 7); } value = (XtPointer) targs; if (is_pixmap) { targs[target_count] = XA_PIXMAP; target_count++; } if (is_text) { XtPointer temp; unsigned long length; char* ctext; Boolean success; ctext = XmCvtXmStringToCT(label_string); targs[target_count] = atoms[XmA_MOTIF_COMPOUND_STRING]; target_count++; targs[target_count] = atoms[XmACOMPOUND_TEXT]; target_count++; targs[target_count] = atoms[XmATEXT]; target_count++; #ifdef UTF8_SUPPORTED if (C_ENCODING != XA_STRING && C_ENCODING != atoms[XmAUTF8_STRING]) { temp = ConvertToEncoding(w, ctext, C_ENCODING, &length, &success); if (success) { targs[target_count] = C_ENCODING; target_count++; } XtFree((char*) temp); } #endif temp = ConvertToEncoding(w, ctext, XA_STRING, &length, &success); if (success) { targs[target_count] = XA_STRING; target_count++; } XtFree((char*) temp); XtFree((char*) ctext); #ifdef UTF8_SUPPORTED ctext = XmCvtXmStringToUTF8String(label_string); if (ctext) { targs[target_count] = atoms[XmAUTF8_STRING]; target_count++; } XtFree((char*) ctext); #endif } type = XA_ATOM; size = target_count; format = 32; } if (cs->target == atoms[XmA_MOTIF_COMPOUND_STRING]) { type = atoms[XmA_MOTIF_COMPOUND_STRING]; format = 8; size = XmCvtXmStringToByteStream(label_string, (unsigned char **) &value); } else if (cs->target == atoms[XmACOMPOUND_TEXT] || cs->target == atoms[XmATEXT] || cs->target == XA_STRING || cs->target == C_ENCODING) { type = atoms[XmACOMPOUND_TEXT]; format = 8; value = XmCvtXmStringToCT(label_string); if (value != NULL) size = strlen((char*) value); else size = 0; if (cs->target == XA_STRING) { Boolean success; value = ConvertToEncoding(w, (char*) value, XA_STRING, &size, &success); if (value != NULL && success == False) cs->flags |= XmCONVERTING_PARTIAL; type = XA_STRING; } else if ((cs->target == atoms[XmATEXT] || cs->target == C_ENCODING) && value != NULL) { char *cvt; Boolean success; cvt = (char*) ConvertToEncoding(w, (char*) value, C_ENCODING, &size, &success); if (cvt != NULL && success == False) cs->flags |= XmCONVERTING_PARTIAL; if (cvt != NULL && success) { /* 100% ok */ XtFree((char*) value); value = cvt; type = C_ENCODING; } else { /* If the request was C_ENCODING, then return only C_ENCODING, * not atoms[XmACOMPOUND_TEXT] */ if (cs->target == C_ENCODING) { XtFree((char*) value); value = cvt; type = C_ENCODING; } else if (cvt != NULL) XtFree(cvt); type = atoms[XmACOMPOUND_TEXT]; } } #ifdef UTF8_SUPPORTED } else if (cs->target == atoms[XmAUTF8_STRING]) { type = atoms[XmAUTF8_STRING]; format = 8; value = XmCvtXmStringToUTF8String(label_string); if (value != NULL) size = strlen((char*) value); else size = 0; #endif } if (cs->target == XA_PIXMAP) { /* Get widget's pixmap */ Pixmap *pix; pix = (Pixmap *) XtMalloc(sizeof(Pixmap)); *pix = label_pixmap; /* value, type, size, and format must be set */ value = (XtPointer) pix; type = XA_DRAWABLE; size = 1; format = 32; } if (cs->target == atoms[XmABACKGROUND]) { /* Get widget's background */ Pixel *background; background = (Pixel *) XtMalloc(sizeof(Pixel)); if (XtIsWidget(w)) *background = ((XmLabelWidget) w)->core.background_pixel; else *background = LabG_Background(w); /* value, type, size, and format must be set */ value = (XtPointer) background; type = atoms[XmAPIXEL]; size = 1; format = 32; } if (cs->target == atoms[XmAFOREGROUND]) { /* Get widget's foreground */ Pixel *foreground; foreground = (Pixel *) XtMalloc(sizeof(Pixel)); if (XtIsWidget(w)) *foreground = ((XmLabelWidget) w)->primitive.foreground; else *foreground = LabG_Foreground(w); /* value, type, size, and format must be set */ value = (XtPointer) foreground; type = atoms[XmAPIXEL]; size = 1; format = 32; } if (cs->target == XA_COLORMAP) { /* Get widget's colormap */ Colormap *colormap; colormap = (Colormap *) XtMalloc(sizeof(Colormap)); if (XtIsWidget(w)) *colormap = w->core.colormap; else *colormap = XtParent(w)->core.colormap; /* value, type, size, and format must be set */ value = (XtPointer) colormap; type = XA_COLORMAP; size = 1; format = 32; } _XmConvertComplete(w, value, size, format, type, cs); } /************************************************************************** * ConvertToEncoding * * This contains conversion code which is needed more than once in * _XmLabelConvert. The first calls are to check for 100% conversion * in _MOTIF_EXPORT_TARGETS and _MOTIF_CLIPBOARD_TARGETS. * The second are for the real conversion **************************************************************************/ static XtPointer ConvertToEncoding(Widget w, char* str, Atom encoding, unsigned long *length, Boolean *flag) { XtPointer rval = NULL; XTextProperty tmp_prop; Atom COMPOUND_TEXT = XInternAtom(XtDisplay(w), XmSCOMPOUND_TEXT, False); #ifdef UTF8_SUPPORTED Atom UTF8_STRING = XInternAtom(XtDisplay(w), XmSUTF8_STRING, False); #endif int ret_status; if (encoding == XA_STRING) { /* convert value to 8859.1 */ ret_status = XmbTextListToTextProperty(XtDisplay(w), (char**) &str, 1, (XICCEncodingStyle)XStringStyle, &tmp_prop); if (ret_status == Success || ret_status > 0) { rval = (XtPointer) tmp_prop.value; *length = tmp_prop.nitems; } else { rval = NULL; *length = 0; } *flag = (ret_status == Success); #ifdef UTF8_SUPPORTED } else if (encoding == UTF8_STRING) { /* convert value to UTF8 */ ret_status = Xutf8TextListToTextProperty(XtDisplay(w), (char**) &str, 1, (XICCEncodingStyle)XUTF8StringStyle, &tmp_prop); if (ret_status == Success || ret_status > 0) { rval = (XtPointer) tmp_prop.value; *length = tmp_prop.nitems; } else { rval = NULL; *length = 0; } *flag = (ret_status >= Success); #endif } else { /* Locale encoding */ /* Fix for Bug 1117 - if str is null then a SEGVIOLATION occures * in strlen. */ #ifdef FIX_1442 *length = str ? strlen(str) : 0; #else *length = str ? strlen(rval) : 0; #endif rval = _XmTextToLocaleText(w, (XtPointer) str, COMPOUND_TEXT, 8, *length, flag); } return(rval); } /************************************************************************** * FromPaddingPixels * * Converts from pixels to current unit type does either horiz or vert * depending on icon placement. * widget - the icon button widget. * offset, value - passed to correct function based on orientation. **************************************************************************/ static void FromPaddingPixels(Widget widget, int offset, XtArgVal *value) { XmLabelWidget iw = (XmLabelWidget) widget; switch(iw->label.pixmap_placement) { case XmPIXMAP_TOP: case XmPIXMAP_BOTTOM: XmeFromVerticalPixels(widget, offset, value); break; default: /* everything else is horiz. */ XmeFromHorizontalPixels(widget, offset, value); break; } } /************************************************************************** * ToPaddingPixels * * Converts from pixels to current unit type does either horiz or vert * depending on icon placement. * widget - the icon button widget. * offset, value - passed to correct function based on orientation. * Returns the import order from _XmTo{Horizontal, Vertical}Pixels. **************************************************************************/ static XmImportOperator ToPaddingPixels(Widget widget, int offset, XtArgVal *value) { XmLabelWidget iw = (XmLabelWidget) widget; switch(iw->label.pixmap_placement) { case XmPIXMAP_TOP: case XmPIXMAP_BOTTOM: return(XmeToVerticalPixels(widget, offset, value)); default: return(XmeToHorizontalPixels(widget, offset, value)); } } /* * XmRCallProc routine for checking label.font before setting it to NULL * If "check_set_render_table" is True, then function has * been called twice on same widget, thus resource needs to be set NULL, * otherwise leave it alone. */ /*ARGSUSED*/ static void CheckSetRenderTable(Widget wid, int offset, XrmValue *value) { XmLabelWidget lw = (XmLabelWidget)wid; /* Check if been here before */ if (lw->label.check_set_render_table) value->addr = NULL; else { lw->label.check_set_render_table = True; value->addr = (char*)&(lw->label.font); } } static XtPointer LabelGetValue(Widget w, int type) { XmString value; XtVaGetValues(w, XmNlabelString, &value, NULL); if (type == XmFORMAT_XmSTRING) { return (XtPointer) value; } else if (type == XmFORMAT_MBYTE || type == XmFORMAT_WCS) { XtPointer temp; temp = (type == XmFORMAT_MBYTE) ? _XmStringUngenerate(value, NULL, XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT) : _XmStringUngenerate(value, NULL, XmWIDECHAR_TEXT, XmWIDECHAR_TEXT); XmStringFree(value); return temp; } else return NULL; } static void LabelSetValue(Widget w, XtPointer value, int type) { Arg args[1]; Cardinal nargs; XmString temp; Boolean freetemp = True; if (type == XmFORMAT_XmSTRING) { temp = (XmString) value; freetemp = False; } else { if (type == XmFORMAT_WCS) { int length; char *str; wchar_t *str2; str2 = (wchar_t *) value; /* Get length of wchar string */ length = 0; while (str2[length] != 0) length++; str = (char*) XtMalloc(MB_CUR_MAX * length); wcstombs(str, str2, length * MB_CUR_MAX); XtFree((char*) value); value = str; } temp = XmStringCreateLocalized((char*) value); } nargs = 0; XtSetArg(args[nargs], XmNlabelString, temp), nargs++; assert(nargs <= XtNumber(args)); XtSetValues(w, args, nargs); if (freetemp) XmStringFree(temp); } /*ARGSUSED*/ static int LabelPreferredValue(Widget w) /* unused */ { return XmFORMAT_XmSTRING; } static char* GetLabelAccelerator(Widget w) { if (XtClass(w) == xmLabelWidgetClass) return NULL; else return Lab_Accelerator(w); } static KeySym GetLabelMnemonic(Widget w) { if (XtClass(w) == xmLabelWidgetClass) return XK_VoidSymbol; else return Lab_Mnemonic(w); }