diff options
Diffstat (limited to 'libXaw/src/SmeBSB.c')
-rw-r--r-- | libXaw/src/SmeBSB.c | 774 |
1 files changed, 774 insertions, 0 deletions
diff --git a/libXaw/src/SmeBSB.c b/libXaw/src/SmeBSB.c new file mode 100644 index 000000000..0d77278ab --- /dev/null +++ b/libXaw/src/SmeBSB.c @@ -0,0 +1,774 @@ +/* $Xorg: SmeBSB.c,v 1.5 2001/02/09 02:03:45 xorgcvs Exp $ */ + +/* +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + */ + +/* $XFree86: xc/lib/Xaw/SmeBSB.c,v 1.11 2001/01/17 19:42:31 dawes Exp $ */ + +/* + * SmeBSB.c - Source code file for BSB Menu Entry object. + * + * Date: September 26, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xos.h> +#include <X11/Xmu/Drawing.h> +#include <X11/Xmu/SysUtil.h> +#include <X11/Xaw/Cardinals.h> +#include <X11/Xaw/SimpleMenu.h> +#include <X11/Xaw/SmeBSBP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +#define ONE_HUNDRED 100 + +/* + * Class Methods + */ +static void FlipColors(Widget); +static void XawSmeBSBClassInitialize(void); +static void XawSmeBSBInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawSmeBSBDestroy(Widget); +static XtGeometryResult XawSmeBSBQueryGeometry(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawSmeBSBRedisplay(Widget, XEvent*, Region); +static Boolean XawSmeBSBSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); + +/* + * Prototypes + */ +static void CreateGCs(Widget); +static void GetBitmapInfo(Widget, Bool); +static void GetDefaultSize(Widget, Dimension*, Dimension*); +static void DestroyGCs(Widget); +static void DrawBitmaps(Widget, GC); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(SmeBSBRec, sme_bsb.field) +static XtResource resources[] = { + { + XtNlabel, + XtCLabel, + XtRString, + sizeof(String), + offset(label), + XtRString, + NULL + }, + { + XtNvertSpace, + XtCVertSpace, + XtRInt, + sizeof(int), + offset(vert_space), + XtRImmediate, + (XtPointer)25 + }, + { + XtNleftBitmap, + XtCLeftBitmap, + XtRBitmap, + sizeof(Pixmap), + offset(left_bitmap), + XtRImmediate, + (XtPointer)None + }, + { + XtNjustify, + XtCJustify, + XtRJustify, + sizeof(XtJustify), + offset(justify), + XtRImmediate, + (XtPointer)XtJustifyLeft + }, + { + XtNrightBitmap, + XtCRightBitmap, + XtRBitmap, + sizeof(Pixmap), + offset(right_bitmap), + XtRImmediate, + (XtPointer)None + }, + { + XtNleftMargin, + XtCHorizontalMargins, + XtRDimension, + sizeof(Dimension), + offset(left_margin), + XtRImmediate, + (XtPointer)4 + }, + { + XtNrightMargin, + XtCHorizontalMargins, + XtRDimension, + sizeof(Dimension), + offset(right_margin), + XtRImmediate, + (XtPointer)4 + }, + { + XtNforeground, + XtCForeground, + XtRPixel, + sizeof(Pixel), + offset(foreground), + XtRString, + XtDefaultForeground + }, + { + XtNfont, + XtCFont, + XtRFontStruct, + sizeof(XFontStruct*), + offset(font), + XtRString, + XtDefaultFont + }, + { + XtNfontSet, + XtCFontSet, + XtRFontSet, + sizeof(XFontSet), + offset(fontset), + XtRString, + XtDefaultFontSet + }, +#ifndef OLDXAW + { + XtNmenuName, + XtCMenuName, + XtRString, + sizeof(String), + offset(menu_name), + XtRImmediate, + (XtPointer)NULL + }, +#endif +}; +#undef offset + +#define superclass (&smeClassRec) +SmeBSBClassRec smeBSBClassRec = { + /* rectangle */ + { + (WidgetClass)superclass, /* superclass */ + "SmeBSB", /* class_name */ + sizeof(SmeBSBRec), /* size */ + XawSmeBSBClassInitialize, /* class_init */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawSmeBSBInitialize, /* initialize */ + NULL, /* initialize_hook */ + NULL, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + False, /* compress_motion */ + False, /* compress_exposure */ + False, /* compress_enterleave */ + False, /* visible_interest */ + XawSmeBSBDestroy, /* destroy */ + NULL, /* resize */ + XawSmeBSBRedisplay, /* expose */ + XawSmeBSBSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* intrinsics version */ + NULL, /* callback offsets */ + NULL, /* tm_table */ + XawSmeBSBQueryGeometry, /* query_geometry */ + NULL, /* display_accelerator */ + NULL, /* extension */ + }, + /* sme */ + { + FlipColors, /* highlight */ + FlipColors, /* unhighlight */ + XtInheritNotify, /* notify */ + NULL, /* extension */ + }, + /* sme_bsb */ + { + NULL, /* extension */ + }, +}; +WidgetClass smeBSBObjectClass = (WidgetClass)&smeBSBClassRec; + +/* + * Function: + * XawSmeBSBClassInitialize + * + * Description: + * Initializes the SmeBSBObject. + */ +static void +XawSmeBSBClassInitialize(void) +{ + XawInitializeWidgetSet(); + XtAddConverter(XtRString, XtRJustify, XmuCvtStringToJustify, NULL, 0); + XtSetTypeConverter(XtRJustify, XtRString, XmuCvtJustifyToString, + NULL, 0, XtCacheNone, NULL); +} + +/* + * Function: + * XawSmeBSBInitialize + * + * Parameters: + * request - widget requested by the argument list + * cnew - new widget with both resource and non resource values + * + * Description: + * Initializes the simple menu widget entry. + */ +/*ARGSUSED*/ +static void +XawSmeBSBInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + SmeBSBObject entry = (SmeBSBObject)cnew; + + if (!entry->sme_bsb.font) XtError("Aborting: no font found\n"); + + if (entry->sme_bsb.label == NULL) + entry->sme_bsb.label = XtName(cnew); + else + entry->sme_bsb.label = XtNewString(entry->sme_bsb.label); + + GetDefaultSize(cnew, &entry->rectangle.width, &entry->rectangle.height); + CreateGCs(cnew); + + entry->sme_bsb.left_bitmap_width = entry->sme_bsb.left_bitmap_height = 0; + entry->sme_bsb.right_bitmap_width = entry->sme_bsb.right_bitmap_height = 0; + + GetBitmapInfo(cnew, True); /* Left Bitmap Info */ + GetBitmapInfo(cnew, False); /* Right Bitmap Info */ +} + +/* + * Function: + * XawSmeBSBDestroy + * + * Parameters: + * w - simple menu widget entry + */ +static void +XawSmeBSBDestroy(Widget w) +{ + SmeBSBObject entry = (SmeBSBObject)w; + + DestroyGCs(w); + if (entry->sme_bsb.label != XtName(w)) + XtFree(entry->sme_bsb.label); +} + +/* + * Function: + * XawSmeBSBRedisplay + * + * Parameters: + * w - simple menu widget entry + * event - X event that caused this redisplay + * region - region the needs to be repainted + * + * Description: + * Redisplays the contents of the widget. + */ +/* ARGSUSED */ +static void +XawSmeBSBRedisplay(Widget w, XEvent *event, Region region) +{ + GC gc; + SmeBSBObject entry = (SmeBSBObject)w; + int font_ascent, font_descent, y_loc; + int fontset_ascent, fontset_descent; + XFontSetExtents *ext = XExtentsOfFontSet(entry->sme_bsb.fontset); + + font_ascent = font_descent = fontset_ascent = fontset_descent = 0; + entry->sme_bsb.set_values_area_cleared = False; + + if (entry->sme.international == True) { + fontset_ascent = XawAbs(ext->max_ink_extent.y); + fontset_descent = ext->max_ink_extent.height - fontset_ascent; + } + else { + font_ascent = entry->sme_bsb.font->max_bounds.ascent; + font_descent = entry->sme_bsb.font->max_bounds.descent; + } + y_loc = XtY(entry); + + if (XtIsSensitive(w) && XtIsSensitive(XtParent(w))) { + if (w == XawSimpleMenuGetActiveEntry(XtParent(w))) { + XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), + entry->sme_bsb.norm_gc, XtX(w), y_loc, + XtWidth(entry), XtHeight(entry)); + gc = entry->sme_bsb.rev_gc; + } + else + gc = entry->sme_bsb.norm_gc; + } + else + gc = entry->sme_bsb.norm_gray_gc; + + if (entry->sme_bsb.label != NULL) { + int x_loc = entry->sme_bsb.left_margin; + int len = strlen(entry->sme_bsb.label); + char *label = entry->sme_bsb.label; + int width, t_width; + + switch(entry->sme_bsb.justify) { + case XtJustifyCenter: + if (entry->sme.international == True) { + t_width = XmbTextEscapement(entry->sme_bsb.fontset,label, + len); + width = XtWidth(entry) - (entry->sme_bsb.left_margin + + entry->sme_bsb.right_margin); + } + else { + t_width = XTextWidth(entry->sme_bsb.font, label, len); + width = XtWidth(entry) - (entry->sme_bsb.left_margin + + entry->sme_bsb.right_margin); + } + x_loc += (width - t_width) >> 1; + break; + case XtJustifyRight: + if (entry->sme.international == True) { + t_width = XmbTextEscapement(entry->sme_bsb.fontset,label, + len); + x_loc = XtWidth(entry) - (entry->sme_bsb.right_margin + + t_width); + } + else { + t_width = XTextWidth(entry->sme_bsb.font, label, len); + x_loc = XtWidth(entry) - (entry->sme_bsb.right_margin + + t_width); + } + break; + case XtJustifyLeft: + /*FALLTHROUGH*/ + default: + break; + } + + /* this will center the text in the gadget top-to-bottom */ + if (entry->sme.international == True) { + y_loc += ((XtHeight(entry) - + (fontset_ascent + fontset_descent)) >> 1) + + fontset_ascent; + + XmbDrawString(XtDisplayOfObject(w), XtWindowOfObject(w), + entry->sme_bsb.fontset, gc, + XtX(w) + x_loc, y_loc, label, len); + } + else { + y_loc += ((XtHeight(entry) - + (font_ascent + font_descent)) >> 1) + font_ascent; + + XDrawString(XtDisplayOfObject(w), XtWindowOfObject(w), gc, + XtX(w) + x_loc, y_loc, label, len); + } + } + + DrawBitmaps(w, gc); +} + + +/* + * Function: + * XawSmeBSBSetValues + * + * Parameters: + * current - current state of the widget + * request - what was requested + * cnew - what the widget will become + * + * Description: + * Relayout the menu when one of the resources is changed. + */ + +/*ARGSUSED*/ +static Boolean +XawSmeBSBSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + SmeBSBObject entry = (SmeBSBObject)cnew; + SmeBSBObject old_entry = (SmeBSBObject)current; + Boolean ret_val = False; + + if (old_entry->sme_bsb.label != entry->sme_bsb.label) { + if (old_entry->sme_bsb.label != XtName(cnew)) + XtFree((char *)old_entry->sme_bsb.label); + + if (entry->sme_bsb.label != XtName(cnew)) + entry->sme_bsb.label = XtNewString(entry->sme_bsb.label); + + ret_val = True; + } + + if (entry->rectangle.sensitive != old_entry->rectangle.sensitive) + ret_val = True; + + if (entry->sme_bsb.left_bitmap != old_entry->sme_bsb.left_bitmap) { + GetBitmapInfo(cnew, True); + ret_val = True; + } + + if (entry->sme_bsb.right_bitmap != old_entry->sme_bsb.right_bitmap) { + GetBitmapInfo(cnew, False); + ret_val = True; + } + + if ((old_entry->sme_bsb.font != entry->sme_bsb.font + && old_entry->sme.international == False) + || old_entry->sme_bsb.foreground != entry->sme_bsb.foreground) { + DestroyGCs(current); + CreateGCs(cnew); + ret_val = True; + } + + if (old_entry->sme_bsb.fontset != entry->sme_bsb.fontset && + old_entry->sme.international == True) + /* DONT changes the GCs, because the fontset is not in them */ + ret_val = True; + + if (ret_val) { + Dimension width, height; + + GetDefaultSize(cnew, &width, &height); + entry->sme_bsb.set_values_area_cleared = True; + XtMakeResizeRequest(cnew, width, height, NULL, NULL); + } + + return (ret_val); +} + +/* + * Function: + * XawSmeBSBQueryGeometry + * + * Parameters: + * w - menu entry object + * itended - intended and return geometry info + * return_val - "" + * + * Returns: + * Geometry Result + * + * Description: + * Returns the preferred geometry for this widget. + * See the Intrinsics manual for details on what this function is for. + */ +static XtGeometryResult +XawSmeBSBQueryGeometry(Widget w, XtWidgetGeometry *intended, + XtWidgetGeometry *return_val) +{ + SmeBSBObject entry = (SmeBSBObject)w; + Dimension width, height; + XtGeometryResult ret_val = XtGeometryYes; + XtGeometryMask mode = intended->request_mode; + + GetDefaultSize(w, &width, &height); + + if (((mode & CWWidth) && intended->width != width) || !(mode & CWWidth)) { + return_val->request_mode |= CWWidth; + return_val->width = width; + ret_val = XtGeometryAlmost; + } + + if (((mode & CWHeight) && intended->height != height) || !(mode & CWHeight)) { + return_val->request_mode |= CWHeight; + return_val->height = height; + ret_val = XtGeometryAlmost; + } + + if (ret_val == XtGeometryAlmost) { + mode = return_val->request_mode; + if (((mode & CWWidth) && width == XtWidth(entry)) && + ((mode & CWHeight) && height == XtHeight(entry))) + return (XtGeometryNo); + } + + return (ret_val); +} + +/* + * Function: + * FlipColors + * + * Parameters: + * w - bsb menu entry widget + * + * Description: + * Invert the colors of the current entry. + */ +static void +FlipColors(Widget w) +{ + SmeBSBObject entry = (SmeBSBObject)w; + + if (entry->sme_bsb.set_values_area_cleared) + return; + + XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), + entry->sme_bsb.invert_gc, + XtX(w), XtY(entry), XtWidth(entry), XtHeight(entry)); +} + +/* + * Function: + * GetDefaultSize + * + * Parameters: + * w - menu entry widget. + * width - default width (return) + * height - default height (return) + * + * Description: + * Calculates the Default (preferred) size of this menu entry. + */ +static void +GetDefaultSize(Widget w, Dimension *width, Dimension *height) +{ + SmeBSBObject entry = (SmeBSBObject)w; + + if (entry->sme.international == True) { + XFontSetExtents *ext = XExtentsOfFontSet(entry->sme_bsb.fontset); + + if (entry->sme_bsb.label == NULL) + *width = 0; + else + *width = XmbTextEscapement(entry->sme_bsb.fontset, + entry->sme_bsb.label, + strlen(entry->sme_bsb.label)); + *width += entry->sme_bsb.left_margin + entry->sme_bsb.right_margin; + *height = ext->max_ink_extent.height; + *height = ((int)*height * (ONE_HUNDRED + + entry->sme_bsb.vert_space)) / ONE_HUNDRED; + } + else { + if (entry->sme_bsb.label == NULL) + *width = 0; + else + *width = XTextWidth(entry->sme_bsb.font, entry->sme_bsb.label, + strlen(entry->sme_bsb.label)); + + *width += entry->sme_bsb.left_margin + entry->sme_bsb.right_margin; + + *height = entry->sme_bsb.font->max_bounds.ascent + + entry->sme_bsb.font->max_bounds.descent; + + *height = ((int)*height * (ONE_HUNDRED + + entry->sme_bsb.vert_space)) / ONE_HUNDRED; + } +} + +/* + * Function: + * DrawBitmaps + * + * Parameters: + * w - simple menu widget entry + * gc - graphics context to use for drawing + * + * Description: + * Draws left and right bitmaps. + */ +static void +DrawBitmaps(Widget w, GC gc) +{ + int x_loc, y_loc; + SmeBSBObject entry = (SmeBSBObject)w; + + if (entry->sme_bsb.left_bitmap == None && + entry->sme_bsb.right_bitmap == None) + return; + + /* + * Draw Left Bitmap + */ + if (entry->sme_bsb.left_bitmap != None) { + x_loc = ((entry->sme_bsb.left_margin - + entry->sme_bsb.left_bitmap_width) >> 1) + XtX(w); + + y_loc = XtY(entry) + ((XtHeight(entry) - + entry->sme_bsb.left_bitmap_height) >> 1); + + XCopyPlane(XtDisplayOfObject(w), entry->sme_bsb.left_bitmap, + XtWindowOfObject(w), gc, 0, 0, + entry->sme_bsb.left_bitmap_width, + entry->sme_bsb.left_bitmap_height, x_loc, y_loc, 1); + } + + /* + * Draw Right Bitmap + */ + if (entry->sme_bsb.right_bitmap != None) { + x_loc = XtWidth(entry) - ((entry->sme_bsb.right_margin + + entry->sme_bsb.right_bitmap_width) >> 1) + + XtX(w); + y_loc = XtY(entry) + ((XtHeight(entry) - + entry->sme_bsb.right_bitmap_height) >> 1); + + XCopyPlane(XtDisplayOfObject(w), entry->sme_bsb.right_bitmap, + XtWindowOfObject(w), gc, 0, 0, + entry->sme_bsb.right_bitmap_width, + entry->sme_bsb.right_bitmap_height, x_loc, y_loc, 1); + } +} + +/* + * Function: + * GetBitmapInfo + * + * Parameters: + * w - bsb menu entry object + * is_left - True: if we are testing left bitmap + * False: if we are testing the right bitmap + * + * Description: + * Gets the bitmap information from either of the bitmaps. + */ +static void +GetBitmapInfo(Widget w, Bool is_left) +{ + SmeBSBObject entry = (SmeBSBObject)w; + unsigned int depth, bw; + Window root; + int x, y; + unsigned int width, height; + + if (is_left) { + if (entry->sme_bsb.left_bitmap != None && + XGetGeometry(XtDisplayOfObject(w), + entry->sme_bsb.left_bitmap, &root, + &x, &y, &width, &height, &bw, &depth)) { + entry->sme_bsb.left_bitmap_width = width; + entry->sme_bsb.left_bitmap_height = height; + } + } + else if (entry->sme_bsb.right_bitmap != None && + XGetGeometry(XtDisplayOfObject(w), + entry->sme_bsb.right_bitmap, &root, + &x, &y, &width, &height, &bw, &depth)) { + entry->sme_bsb.right_bitmap_width = width; + entry->sme_bsb.right_bitmap_height = height; + } +} + +/* + * Function: + * CreateGCs + * + * Parameters: + * w - simple menu widget entry + * + * Description: + * Creates all gc's for the simple menu widget. + */ +static void +CreateGCs(Widget w) +{ + SmeBSBObject entry = (SmeBSBObject)w; + XGCValues values; + XtGCMask mask, mask_i18n; + + values.foreground = XtParent(w)->core.background_pixel; + values.background = entry->sme_bsb.foreground; + values.font = entry->sme_bsb.font->fid; + values.graphics_exposures = False; + mask = GCForeground | GCBackground | GCGraphicsExposures | GCFont; + mask_i18n = GCForeground | GCBackground | GCGraphicsExposures; + if (entry->sme.international == True) + entry->sme_bsb.rev_gc = XtAllocateGC(w, 0, mask_i18n, &values, GCFont, 0); + else + entry->sme_bsb.rev_gc = XtGetGC(w, mask, &values); + + values.foreground = entry->sme_bsb.foreground; + values.background = XtParent(w)->core.background_pixel; + if (entry->sme.international == True) + entry->sme_bsb.norm_gc = XtAllocateGC(w, 0, mask_i18n, &values, GCFont, 0); + else + entry->sme_bsb.norm_gc = XtGetGC(w, mask, &values); + + values.fill_style = FillTiled; + values.tile = XmuCreateStippledPixmap(XtScreenOfObject(w), + entry->sme_bsb.foreground, + XtParent(w)->core.background_pixel, + XtParent(w)->core.depth); + values.graphics_exposures = False; + mask |= GCTile | GCFillStyle; + mask_i18n |= GCTile | GCFillStyle; + if (entry->sme.international == True) + entry->sme_bsb.norm_gray_gc = XtAllocateGC(w, 0, mask_i18n, &values, + GCFont, 0); + else + entry->sme_bsb.norm_gray_gc = XtGetGC(w, mask, &values); + + values.foreground ^= values.background; + values.background = 0; + values.function = GXxor; + mask = GCForeground | GCBackground | GCGraphicsExposures | GCFunction; + entry->sme_bsb.invert_gc = XtGetGC(w, mask, &values); +} + +/* + * Function: + * DestroyGCs + * + * Parameters: + * w - simple menu widget entry + * + * Description: + * Removes all gc's for the simple menu widget. + */ +static void +DestroyGCs(Widget w) +{ + SmeBSBObject entry = (SmeBSBObject)w; + + XtReleaseGC(w, entry->sme_bsb.norm_gc); + XtReleaseGC(w, entry->sme_bsb.norm_gray_gc); + XtReleaseGC(w, entry->sme_bsb.rev_gc); + XtReleaseGC(w, entry->sme_bsb.invert_gc); +} |