diff options
Diffstat (limited to 'libXaw/src/Command.c')
-rw-r--r-- | libXaw/src/Command.c | 1317 |
1 files changed, 657 insertions, 660 deletions
diff --git a/libXaw/src/Command.c b/libXaw/src/Command.c index 845ffb8b6..268fc19a7 100644 --- a/libXaw/src/Command.c +++ b/libXaw/src/Command.c @@ -1,660 +1,657 @@ -/* $Xorg: Command.c,v 1.5 2001/02/09 02:03:43 xorgcvs Exp $ */ - -/*********************************************************** - -Copyright 1987, 1988, 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. - - -Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ -/* $XFree86: xc/lib/Xaw/Command.c,v 1.15tsi Exp $ */ - -/* - * Command.c - Command button widget - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <stdio.h> -#include <X11/IntrinsicP.h> -#include <X11/StringDefs.h> -#include <X11/extensions/shape.h> -#include <X11/Xmu/Converters.h> -#include <X11/Xmu/Drawing.h> -#include <X11/Xmu/Misc.h> -#include <X11/Xaw/CommandP.h> -#include <X11/Xaw/XawInit.h> -#include "Private.h" - -#define DEFAULT_HIGHLIGHT_THICKNESS 2 -#define DEFAULT_SHAPE_HIGHLIGHT 32767 -#define STR_EQUAL(str1, str2) (str1 == str2 || strcmp(str1, str2) == 0) - -/* - * Class Methods - */ -static void XawCommandClassInitialize(void); -static void XawCommandDestroy(Widget); -static void XawCommandInitialize(Widget, Widget, ArgList, Cardinal*); -static void XawCommandRealize(Widget, Mask*, XSetWindowAttributes*); -static void XawCommandResize(Widget); -static void XawCommandRedisplay(Widget, XEvent*, Region); -static Boolean XawCommandSetValues(Widget, Widget, Widget, ArgList, Cardinal*); -static void XawCommandGetValuesHook(Widget, ArgList, Cardinal*); -static Bool ChangeSensitive(Widget); - -/* - * Prototypes - */ -static GC Get_GC(CommandWidget, Pixel, Pixel); -static void PaintCommandWidget(Widget, XEvent*, Region, Bool); -static Region HighlightRegion(CommandWidget); -static Bool ShapeButton(CommandWidget, Bool); -static void XawCommandToggle(Widget); - -/* - * Actions - */ -static void Highlight(Widget, XEvent*, String*, Cardinal*); -static void Notify(Widget, XEvent*, String*, Cardinal*); -static void Reset(Widget, XEvent*, String*, Cardinal*); -static void Set(Widget, XEvent*, String*, Cardinal*); -static void Unhighlight(Widget, XEvent*, String*, Cardinal*); -static void Unset(Widget, XEvent*, String*, Cardinal*); - -/* - * Initialization - */ -static char defaultTranslations[] = -"<Enter>:" "highlight()\n" -"<Leave>:" "reset()\n" -"<Btn1Down>:" "set()\n" -"<Btn1Up>:" "notify() unset()\n" -; - -#define offset(field) XtOffsetOf(CommandRec, field) -static XtResource resources[] = { - { - XtNcallback, - XtCCallback, - XtRCallback, - sizeof(XtPointer), - offset(command.callbacks), - XtRCallback, - NULL - }, - { - XtNhighlightThickness, - XtCThickness, - XtRDimension, - sizeof(Dimension), - offset(command.highlight_thickness), - XtRImmediate, - (XtPointer)DEFAULT_SHAPE_HIGHLIGHT - }, - { - XtNshapeStyle, - XtCShapeStyle, - XtRShapeStyle, - sizeof(int), - offset(command.shape_style), - XtRImmediate, - (XtPointer)XawShapeRectangle - }, - { - XtNcornerRoundPercent, - XtCCornerRoundPercent, - XtRDimension, - sizeof(Dimension), - offset(command.corner_round), - XtRImmediate, - (XtPointer)25 - }, -}; -#undef offset - -static XtActionsRec actionsList[] = { - {"set", Set}, - {"notify", Notify}, - {"highlight", Highlight}, - {"reset", Reset}, - {"unset", Unset}, - {"unhighlight", Unhighlight} -}; - -#define SuperClass ((LabelWidgetClass)&labelClassRec) - -CommandClassRec commandClassRec = { - /* core */ - { - (WidgetClass)SuperClass, /* superclass */ - "Command", /* class_name */ - sizeof(CommandRec), /* size */ - XawCommandClassInitialize, /* class_initialize */ - NULL, /* class_part_initialize */ - False, /* class_inited */ - XawCommandInitialize, /* initialize */ - NULL, /* initialize_hook */ - XawCommandRealize, /* realize */ - actionsList, /* actions */ - XtNumber(actionsList), /* num_actions */ - resources, /* resources */ - XtNumber(resources), /* num_resources */ - NULLQUARK, /* xrm_class */ - False, /* compress_motion */ - True, /* compress_exposure */ - True, /* compress_enterleave */ - False, /* visible_interest */ - XawCommandDestroy, /* destroy */ - XawCommandResize, /* resize */ - XawCommandRedisplay, /* expose */ - XawCommandSetValues, /* set_values */ - NULL, /* set_values_hook */ - XtInheritSetValuesAlmost, /* set_values_almost */ - XawCommandGetValuesHook, /* get_values_hook */ - NULL, /* accept_focus */ - XtVersion, /* version */ - NULL, /* callback_private */ - defaultTranslations, /* tm_table */ - XtInheritQueryGeometry, /* query_geometry */ - XtInheritDisplayAccelerator, /* display_accelerator */ - NULL, /* extension */ - }, - /* simple */ - { - ChangeSensitive, /* change_sensitive */ - }, - /* label */ - { - NULL, /* not used */ - }, - /* command */ - { - NULL, /* not used */ - }, -}; - -WidgetClass commandWidgetClass = (WidgetClass)&commandClassRec; - -/* - * Implementation - */ -static GC -Get_GC(CommandWidget cbw, Pixel fg, Pixel bg) -{ - XGCValues values; - - values.foreground = fg; - values.background = bg; - values.font = cbw->label.font->fid; - values.cap_style = CapProjecting; - - if (cbw->command.highlight_thickness > 1) - values.line_width = cbw->command.highlight_thickness; - else - values.line_width = 0; - - if (cbw->simple.international == True) - return (XtAllocateGC((Widget)cbw, 0, - GCForeground | GCBackground | GCLineWidth | - GCCapStyle, &values, GCFont, 0)); - else - return (XtGetGC((Widget)cbw, - GCForeground | GCBackground | GCFont | GCLineWidth | - GCCapStyle, &values)); -} - -/*ARGSUSED*/ -static void -XawCommandInitialize(Widget request, Widget cnew, - ArgList args, Cardinal *num_args) -{ - CommandWidget cbw = (CommandWidget)cnew; - int shape_event_base, shape_error_base; - - if (!cbw->label.font) XtError("Aborting: no font found\n"); - - if (cbw->command.shape_style != XawShapeRectangle && - !XShapeQueryExtension(XtDisplay(cnew), &shape_event_base, - &shape_error_base)) - cbw->command.shape_style = XawShapeRectangle; - - if (cbw->command.highlight_thickness == DEFAULT_SHAPE_HIGHLIGHT) { - if (cbw->command.shape_style != XawShapeRectangle) - cbw->command.highlight_thickness = 0; - else - cbw->command.highlight_thickness = DEFAULT_HIGHLIGHT_THICKNESS; - } - - cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground, - cbw->core.background_pixel); - cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel, - cbw->label.foreground); - XtReleaseGC(cnew, cbw->label.normal_GC); - cbw->label.normal_GC = cbw->command.normal_GC; - - cbw->command.set = False; - cbw->command.highlighted = HighlightNone; -} - -static Region -HighlightRegion(CommandWidget cbw) -{ - static Region outerRegion = NULL, innerRegion, emptyRegion; - XRectangle rect; - - if (cbw->command.highlight_thickness == 0 || - cbw->command.highlight_thickness > Min(XtWidth(cbw), XtHeight(cbw)) / 2) - return (NULL); - - if (outerRegion == NULL) { - /* save time by allocating scratch regions only once. */ - outerRegion = XCreateRegion(); - innerRegion = XCreateRegion(); - emptyRegion = XCreateRegion(); - } - - rect.x = rect.y = 0; - rect.width = XtWidth(cbw); - rect.height = XtHeight(cbw); - XUnionRectWithRegion(&rect, emptyRegion, outerRegion); - rect.x = rect.y = cbw->command.highlight_thickness; - rect.width -= cbw->command.highlight_thickness * 2; - rect.height -= cbw->command.highlight_thickness * 2; - XUnionRectWithRegion(&rect, emptyRegion, innerRegion); - XSubtractRegion(outerRegion, innerRegion, outerRegion); - - return (outerRegion); -} - -/*************************** -* Action Procedures -***************************/ -static void -XawCommandToggle(Widget w) -{ - CommandWidget xaw = (CommandWidget)w; - Arg args[2]; - Cardinal num_args; - - num_args = 0; - XtSetArg(args[num_args], XtNbackground, - xaw->label.foreground); ++num_args; - XtSetArg(args[num_args], XtNforeground, - xaw->core.background_pixel); ++num_args; - XtSetValues(w, args, num_args); -} - -/*ARGSUSED*/ -static void -Set(Widget w, XEvent *event, String *params, Cardinal *num_params) -{ - CommandWidget cbw = (CommandWidget)w; - - if (cbw->command.set) - return; - - XawCommandToggle(w); - cbw->command.set= True; -} - -/*ARGSUSED*/ -static void -Unset(Widget w, XEvent *event, String *params, Cardinal *num_params) -{ - CommandWidget cbw = (CommandWidget)w; - - if (!cbw->command.set) - return; - - cbw->command.set = False; - XawCommandToggle(w); -} - -/*ARGSUSED*/ -static void -Reset(Widget w, XEvent *event, String *params, Cardinal *num_params) -{ - CommandWidget cbw = (CommandWidget)w; - - if (cbw->command.set) { - cbw->command.highlighted = HighlightNone; - Unset(w, event, params, num_params); - } - else - Unhighlight(w, event, params, num_params); -} - -/*ARGSUSED*/ -static void -Highlight(Widget w, XEvent *event, String *params, Cardinal *num_params) -{ - CommandWidget cbw = (CommandWidget)w; - - if (*num_params == (Cardinal)0) - cbw->command.highlighted = HighlightWhenUnset; - else { - if (*num_params != (Cardinal)1) - XtWarning("Too many parameters passed to highlight action table."); - switch (params[0][0]) { - case 'A': - case 'a': - cbw->command.highlighted = HighlightAlways; - break; - default: - cbw->command.highlighted = HighlightWhenUnset; - break; - } - } - - if (XtIsRealized(w)) - PaintCommandWidget(w, event, HighlightRegion(cbw), True); -} - -/*ARGSUSED*/ -static void -Unhighlight(Widget w, XEvent *event, String *params, Cardinal *num_params) -{ - CommandWidget cbw = (CommandWidget)w; - - cbw->command.highlighted = HighlightNone; - if (XtIsRealized(w)) - PaintCommandWidget(w, event, HighlightRegion(cbw), True); -} - -/*ARGSUSED*/ -static void -Notify(Widget w, XEvent *event, String *params, Cardinal *num_params) -{ - CommandWidget cbw = (CommandWidget)w; - - /* check to be sure state is still Set so that user can cancel - the action (e.g. by moving outside the window, in the default - bindings. - */ - if (cbw->command.set) - XtCallCallbackList(w, cbw->command.callbacks, (XtPointer) NULL); -} - -static void -XawCommandRedisplay(Widget w, XEvent *event, Region region) -{ - PaintCommandWidget(w, event, region, False); -} - -/* - * Function: - * PaintCommandWidget - * Parameters: - * w - command widget - * region - region to paint (passed to the superclass) - * change - did it change either set or highlight state? - */ -static void -PaintCommandWidget(Widget w, XEvent *event, Region region, Bool change) -{ - CommandWidget cbw = (CommandWidget)w; - Bool very_thick; - GC rev_gc; - - very_thick = cbw->command.highlight_thickness - > Min(XtWidth(cbw), XtHeight(cbw)) / 2; - - if (cbw->command.highlight_thickness == 0) { - (*SuperClass->core_class.expose) (w, event, region); - return; - } - - /* - * If we are set then use the same colors as if we are not highlighted - */ - - if (cbw->command.highlighted != HighlightNone) { - rev_gc = cbw->command.normal_GC; - } - else { - rev_gc = cbw->command.inverse_GC; - } - - if (!((!change && cbw->command.highlighted == HighlightNone) - || (cbw->command.highlighted == HighlightWhenUnset - && cbw->command.set))) { - if (very_thick) - XFillRectangle(XtDisplay(w),XtWindow(w), rev_gc, - 0, 0, XtWidth(cbw), XtHeight(cbw)); - else { - /* wide lines are centered on the path, so indent it */ - if (cbw->core.background_pixmap != XtUnspecifiedPixmap && - rev_gc == cbw->command.inverse_GC) { - XClearArea(XtDisplay(w), XtWindow(w), - 0, 0, XtWidth(cbw), cbw->command.highlight_thickness, - False); - XClearArea(XtDisplay(w), XtWindow(w), - 0, cbw->command.highlight_thickness, - cbw->command.highlight_thickness, - XtHeight(cbw) - (cbw->command.highlight_thickness<<1), - False); - XClearArea(XtDisplay(w), XtWindow(w), - XtWidth(cbw) - cbw->command.highlight_thickness, - cbw->command.highlight_thickness, - cbw->command.highlight_thickness, - XtHeight(cbw) - (cbw->command.highlight_thickness<<1), - False); - XClearArea(XtDisplay(w), XtWindow(w), - 0, XtHeight(cbw) - cbw->command.highlight_thickness, - XtWidth(cbw), cbw->command.highlight_thickness, - False); - } - else { - int offset = cbw->command.highlight_thickness / 2; - - XDrawRectangle(XtDisplay(w),XtWindow(w), rev_gc, offset, offset, - XtWidth(cbw) - cbw->command.highlight_thickness, - XtHeight(cbw) - cbw->command.highlight_thickness); - } - } - } - - (*SuperClass->core_class.expose)(w, event, region); -} - -static void -XawCommandDestroy(Widget w) -{ - CommandWidget cbw = (CommandWidget)w; - - /* Label will release cbw->command.normal_GC */ - XtReleaseGC(w, cbw->command.inverse_GC); -} - -/*ARGSUSED*/ -static Boolean -XawCommandSetValues(Widget current, Widget request, Widget cnew, - ArgList args, Cardinal *num_args) -{ - CommandWidget oldcbw = (CommandWidget)current; - CommandWidget cbw = (CommandWidget)cnew; - Boolean redisplay = False; - - if (oldcbw->core.sensitive != cbw->core.sensitive && !cbw->core.sensitive) { - cbw->command.highlighted = HighlightNone; - redisplay = True; - } - - if (cbw->command.set) { - unsigned int i; - Pixel foreground, background; - - foreground = oldcbw->label.foreground; - background = oldcbw->core.background_pixel; - for (i = 0; i < *num_args; i++) { - if (STR_EQUAL(args[i].name, XtNforeground)) - background = cbw->label.foreground; - else if (STR_EQUAL(args[i].name, XtNbackground)) - foreground = cbw->core.background_pixel; - } - cbw->label.foreground = foreground; - cbw->core.background_pixel = background; - } - - if (oldcbw->label.foreground != cbw->label.foreground - || oldcbw->core.background_pixel != cbw->core.background_pixel - || oldcbw->command.highlight_thickness - != cbw->command.highlight_thickness - || oldcbw->label.font != cbw->label.font) { - XtReleaseGC(cnew, cbw->command.inverse_GC); - - cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground, - cbw->core.background_pixel); - cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel, - cbw->label.foreground); - XtReleaseGC(cnew, cbw->label.normal_GC); - cbw->label.normal_GC = cbw->command.normal_GC; - - redisplay = True; - } - - if (XtIsRealized(cnew) - && oldcbw->command.shape_style != cbw->command.shape_style - && !ShapeButton(cbw, True)) - cbw->command.shape_style = oldcbw->command.shape_style; - - return (redisplay); -} - -static void -XawCommandGetValuesHook(Widget w, ArgList args, Cardinal *num_args) -{ - CommandWidget cbw = (CommandWidget)w; - unsigned int i; - - for (i = 0; i < *num_args; i++) { - if (STR_EQUAL(args[i].name, XtNforeground)) - *((String*)args[i].value) = cbw->command.set ? - (String)cbw->core.background_pixel : (String)cbw->label.foreground; - else if (STR_EQUAL(args[i].name, XtNbackground)) - *((String*)args[i].value) = cbw->command.set ? - (String)cbw->label.foreground : (String)cbw->core.background_pixel; - } -} - -static void -XawCommandClassInitialize(void) -{ - XawInitializeWidgetSet(); - XtSetTypeConverter(XtRString, XtRShapeStyle, XmuCvtStringToShapeStyle, - NULL, 0, XtCacheNone, NULL); - XtSetTypeConverter(XtRShapeStyle, XtRString, XmuCvtShapeStyleToString, - NULL, 0, XtCacheNone, NULL); -} - -static Bool -ShapeButton(CommandWidget cbw, Bool checkRectangular) -{ - Dimension corner_size = 0; - - if (cbw->command.shape_style == XawShapeRoundedRectangle) { - corner_size = XtWidth(cbw) < XtHeight(cbw) ? - XtWidth(cbw) : XtHeight(cbw); - corner_size = (corner_size * cbw->command.corner_round) / 100; - } - - if (checkRectangular || cbw->command.shape_style != XawShapeRectangle) { - if (!XmuReshapeWidget((Widget)cbw, cbw->command.shape_style, - corner_size, corner_size)) { - cbw->command.shape_style = XawShapeRectangle; - return (False); - } - } - - return (True); -} - -static void -XawCommandRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes) -{ - (*commandWidgetClass->core_class.superclass->core_class.realize) - (w, valueMask, attributes); - - ShapeButton((CommandWidget)w, False); -} - -static void -XawCommandResize(Widget w) -{ - if (XtIsRealized(w)) - ShapeButton((CommandWidget)w, False); - - (*commandWidgetClass->core_class.superclass->core_class.resize)(w); -} - -static Bool -ChangeSensitive(Widget w) -{ - CommandWidget cbw = (CommandWidget)w; - - if (XtIsRealized(w)) { - if (XtIsSensitive(w)) { - if (w->core.border_pixmap != XtUnspecifiedPixmap) - XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w), - w->core.border_pixmap); - else - XSetWindowBorder(XtDisplay(w), XtWindow(w), - w->core.border_pixel); - } - else { - if (cbw->simple.insensitive_border == None) - cbw->simple.insensitive_border = - XmuCreateStippledPixmap(XtScreen(w), - w->core.border_pixel, - cbw->command.set ? - cbw->label.foreground : - w->core.background_pixel, - w->core.depth); - XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w), - cbw->simple.insensitive_border); - } - } - - return (False); -} +/***********************************************************
+
+Copyright 1987, 1988, 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.
+
+
+Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*
+ * Command.c - Command button widget
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/extensions/shape.h>
+#include <X11/Xmu/Converters.h>
+#include <X11/Xmu/Drawing.h>
+#include <X11/Xmu/Misc.h>
+#include <X11/Xaw/CommandP.h>
+#include <X11/Xaw/XawInit.h>
+#include "Private.h"
+
+#define DEFAULT_HIGHLIGHT_THICKNESS 2
+#define DEFAULT_SHAPE_HIGHLIGHT 32767
+#define STR_EQUAL(str1, str2) (str1 == str2 || strcmp(str1, str2) == 0)
+
+/*
+ * Class Methods
+ */
+static void XawCommandClassInitialize(void);
+static void XawCommandDestroy(Widget);
+static void XawCommandInitialize(Widget, Widget, ArgList, Cardinal*);
+static void XawCommandRealize(Widget, Mask*, XSetWindowAttributes*);
+static void XawCommandResize(Widget);
+static void XawCommandRedisplay(Widget, XEvent*, Region);
+static Boolean XawCommandSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
+static void XawCommandGetValuesHook(Widget, ArgList, Cardinal*);
+static Bool ChangeSensitive(Widget);
+
+/*
+ * Prototypes
+ */
+static GC Get_GC(CommandWidget, Pixel, Pixel);
+static void PaintCommandWidget(Widget, XEvent*, Region, Bool);
+static Region HighlightRegion(CommandWidget);
+static Bool ShapeButton(CommandWidget, Bool);
+static void XawCommandToggle(Widget);
+
+/*
+ * Actions
+ */
+static void Highlight(Widget, XEvent*, String*, Cardinal*);
+static void Notify(Widget, XEvent*, String*, Cardinal*);
+static void Reset(Widget, XEvent*, String*, Cardinal*);
+static void Set(Widget, XEvent*, String*, Cardinal*);
+static void Unhighlight(Widget, XEvent*, String*, Cardinal*);
+static void Unset(Widget, XEvent*, String*, Cardinal*);
+
+/*
+ * Initialization
+ */
+static char defaultTranslations[] =
+"<Enter>:" "highlight()\n"
+"<Leave>:" "reset()\n"
+"<Btn1Down>:" "set()\n"
+"<Btn1Up>:" "notify() unset()\n"
+;
+
+#define offset(field) XtOffsetOf(CommandRec, field)
+static XtResource resources[] = {
+ {
+ XtNcallback,
+ XtCCallback,
+ XtRCallback,
+ sizeof(XtPointer),
+ offset(command.callbacks),
+ XtRCallback,
+ NULL
+ },
+ {
+ XtNhighlightThickness,
+ XtCThickness,
+ XtRDimension,
+ sizeof(Dimension),
+ offset(command.highlight_thickness),
+ XtRImmediate,
+ (XtPointer)DEFAULT_SHAPE_HIGHLIGHT
+ },
+ {
+ XtNshapeStyle,
+ XtCShapeStyle,
+ XtRShapeStyle,
+ sizeof(int),
+ offset(command.shape_style),
+ XtRImmediate,
+ (XtPointer)XawShapeRectangle
+ },
+ {
+ XtNcornerRoundPercent,
+ XtCCornerRoundPercent,
+ XtRDimension,
+ sizeof(Dimension),
+ offset(command.corner_round),
+ XtRImmediate,
+ (XtPointer)25
+ },
+};
+#undef offset
+
+static XtActionsRec actionsList[] = {
+ {"set", Set},
+ {"notify", Notify},
+ {"highlight", Highlight},
+ {"reset", Reset},
+ {"unset", Unset},
+ {"unhighlight", Unhighlight}
+};
+
+#define SuperClass ((LabelWidgetClass)&labelClassRec)
+
+CommandClassRec commandClassRec = {
+ /* core */
+ {
+ (WidgetClass)SuperClass, /* superclass */
+ "Command", /* class_name */
+ sizeof(CommandRec), /* size */
+ XawCommandClassInitialize, /* class_initialize */
+ NULL, /* class_part_initialize */
+ False, /* class_inited */
+ XawCommandInitialize, /* initialize */
+ NULL, /* initialize_hook */
+ XawCommandRealize, /* realize */
+ actionsList, /* actions */
+ XtNumber(actionsList), /* num_actions */
+ resources, /* resources */
+ XtNumber(resources), /* num_resources */
+ NULLQUARK, /* xrm_class */
+ False, /* compress_motion */
+ True, /* compress_exposure */
+ True, /* compress_enterleave */
+ False, /* visible_interest */
+ XawCommandDestroy, /* destroy */
+ XawCommandResize, /* resize */
+ XawCommandRedisplay, /* expose */
+ XawCommandSetValues, /* set_values */
+ NULL, /* set_values_hook */
+ XtInheritSetValuesAlmost, /* set_values_almost */
+ XawCommandGetValuesHook, /* get_values_hook */
+ NULL, /* accept_focus */
+ XtVersion, /* version */
+ NULL, /* callback_private */
+ defaultTranslations, /* tm_table */
+ XtInheritQueryGeometry, /* query_geometry */
+ XtInheritDisplayAccelerator, /* display_accelerator */
+ NULL, /* extension */
+ },
+ /* simple */
+ {
+ ChangeSensitive, /* change_sensitive */
+ },
+ /* label */
+ {
+ NULL, /* not used */
+ },
+ /* command */
+ {
+ NULL, /* not used */
+ },
+};
+
+WidgetClass commandWidgetClass = (WidgetClass)&commandClassRec;
+
+/*
+ * Implementation
+ */
+static GC
+Get_GC(CommandWidget cbw, Pixel fg, Pixel bg)
+{
+ XGCValues values;
+
+ values.foreground = fg;
+ values.background = bg;
+ values.font = cbw->label.font->fid;
+ values.cap_style = CapProjecting;
+
+ if (cbw->command.highlight_thickness > 1)
+ values.line_width = cbw->command.highlight_thickness;
+ else
+ values.line_width = 0;
+
+ if (cbw->simple.international == True)
+ return (XtAllocateGC((Widget)cbw, 0,
+ GCForeground | GCBackground | GCLineWidth |
+ GCCapStyle, &values, GCFont, 0));
+ else
+ return (XtGetGC((Widget)cbw,
+ GCForeground | GCBackground | GCFont | GCLineWidth |
+ GCCapStyle, &values));
+}
+
+/*ARGSUSED*/
+static void
+XawCommandInitialize(Widget request, Widget cnew,
+ ArgList args, Cardinal *num_args)
+{
+ CommandWidget cbw = (CommandWidget)cnew;
+ int shape_event_base, shape_error_base;
+
+ if (!cbw->label.font) XtError("Aborting: no font found\n");
+
+ if (cbw->command.shape_style != XawShapeRectangle &&
+ !XShapeQueryExtension(XtDisplay(cnew), &shape_event_base,
+ &shape_error_base))
+ cbw->command.shape_style = XawShapeRectangle;
+
+ if (cbw->command.highlight_thickness == DEFAULT_SHAPE_HIGHLIGHT) {
+ if (cbw->command.shape_style != XawShapeRectangle)
+ cbw->command.highlight_thickness = 0;
+ else
+ cbw->command.highlight_thickness = DEFAULT_HIGHLIGHT_THICKNESS;
+ }
+
+ cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground,
+ cbw->core.background_pixel);
+ cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel,
+ cbw->label.foreground);
+ XtReleaseGC(cnew, cbw->label.normal_GC);
+ cbw->label.normal_GC = cbw->command.normal_GC;
+
+ cbw->command.set = False;
+ cbw->command.highlighted = HighlightNone;
+}
+
+static Region
+HighlightRegion(CommandWidget cbw)
+{
+ static Region outerRegion = NULL, innerRegion, emptyRegion;
+ XRectangle rect;
+
+ if (cbw->command.highlight_thickness == 0 ||
+ cbw->command.highlight_thickness > Min(XtWidth(cbw), XtHeight(cbw)) / 2)
+ return (NULL);
+
+ if (outerRegion == NULL) {
+ /* save time by allocating scratch regions only once. */
+ outerRegion = XCreateRegion();
+ innerRegion = XCreateRegion();
+ emptyRegion = XCreateRegion();
+ }
+
+ rect.x = rect.y = 0;
+ rect.width = XtWidth(cbw);
+ rect.height = XtHeight(cbw);
+ XUnionRectWithRegion(&rect, emptyRegion, outerRegion);
+ rect.x = rect.y = cbw->command.highlight_thickness;
+ rect.width -= cbw->command.highlight_thickness * 2;
+ rect.height -= cbw->command.highlight_thickness * 2;
+ XUnionRectWithRegion(&rect, emptyRegion, innerRegion);
+ XSubtractRegion(outerRegion, innerRegion, outerRegion);
+
+ return (outerRegion);
+}
+
+/***************************
+* Action Procedures
+***************************/
+static void
+XawCommandToggle(Widget w)
+{
+ CommandWidget xaw = (CommandWidget)w;
+ Arg args[2];
+ Cardinal num_args;
+
+ num_args = 0;
+ XtSetArg(args[num_args], XtNbackground,
+ xaw->label.foreground); ++num_args;
+ XtSetArg(args[num_args], XtNforeground,
+ xaw->core.background_pixel); ++num_args;
+ XtSetValues(w, args, num_args);
+}
+
+/*ARGSUSED*/
+static void
+Set(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ CommandWidget cbw = (CommandWidget)w;
+
+ if (cbw->command.set)
+ return;
+
+ XawCommandToggle(w);
+ cbw->command.set= True;
+}
+
+/*ARGSUSED*/
+static void
+Unset(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ CommandWidget cbw = (CommandWidget)w;
+
+ if (!cbw->command.set)
+ return;
+
+ cbw->command.set = False;
+ XawCommandToggle(w);
+}
+
+/*ARGSUSED*/
+static void
+Reset(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ CommandWidget cbw = (CommandWidget)w;
+
+ if (cbw->command.set) {
+ cbw->command.highlighted = HighlightNone;
+ Unset(w, event, params, num_params);
+ }
+ else
+ Unhighlight(w, event, params, num_params);
+}
+
+/*ARGSUSED*/
+static void
+Highlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ CommandWidget cbw = (CommandWidget)w;
+
+ if (*num_params == (Cardinal)0)
+ cbw->command.highlighted = HighlightWhenUnset;
+ else {
+ if (*num_params != (Cardinal)1)
+ XtWarning("Too many parameters passed to highlight action table.");
+ switch (params[0][0]) {
+ case 'A':
+ case 'a':
+ cbw->command.highlighted = HighlightAlways;
+ break;
+ default:
+ cbw->command.highlighted = HighlightWhenUnset;
+ break;
+ }
+ }
+
+ if (XtIsRealized(w))
+ PaintCommandWidget(w, event, HighlightRegion(cbw), True);
+}
+
+/*ARGSUSED*/
+static void
+Unhighlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ CommandWidget cbw = (CommandWidget)w;
+
+ cbw->command.highlighted = HighlightNone;
+ if (XtIsRealized(w))
+ PaintCommandWidget(w, event, HighlightRegion(cbw), True);
+}
+
+/*ARGSUSED*/
+static void
+Notify(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ CommandWidget cbw = (CommandWidget)w;
+
+ /* check to be sure state is still Set so that user can cancel
+ the action (e.g. by moving outside the window, in the default
+ bindings.
+ */
+ if (cbw->command.set)
+ XtCallCallbackList(w, cbw->command.callbacks, (XtPointer) NULL);
+}
+
+static void
+XawCommandRedisplay(Widget w, XEvent *event, Region region)
+{
+ PaintCommandWidget(w, event, region, False);
+}
+
+/*
+ * Function:
+ * PaintCommandWidget
+ * Parameters:
+ * w - command widget
+ * region - region to paint (passed to the superclass)
+ * change - did it change either set or highlight state?
+ */
+static void
+PaintCommandWidget(Widget w, XEvent *event, Region region, Bool change)
+{
+ CommandWidget cbw = (CommandWidget)w;
+ Bool very_thick;
+ GC rev_gc;
+
+ very_thick = cbw->command.highlight_thickness
+ > Min(XtWidth(cbw), XtHeight(cbw)) / 2;
+
+ if (cbw->command.highlight_thickness == 0) {
+ (*SuperClass->core_class.expose) (w, event, region);
+ return;
+ }
+
+ /*
+ * If we are set then use the same colors as if we are not highlighted
+ */
+
+ if (cbw->command.highlighted != HighlightNone) {
+ rev_gc = cbw->command.normal_GC;
+ }
+ else {
+ rev_gc = cbw->command.inverse_GC;
+ }
+
+ if (!((!change && cbw->command.highlighted == HighlightNone)
+ || (cbw->command.highlighted == HighlightWhenUnset
+ && cbw->command.set))) {
+ if (very_thick)
+ XFillRectangle(XtDisplay(w),XtWindow(w), rev_gc,
+ 0, 0, XtWidth(cbw), XtHeight(cbw));
+ else {
+ /* wide lines are centered on the path, so indent it */
+ if (cbw->core.background_pixmap != XtUnspecifiedPixmap &&
+ rev_gc == cbw->command.inverse_GC) {
+ XClearArea(XtDisplay(w), XtWindow(w),
+ 0, 0, XtWidth(cbw), cbw->command.highlight_thickness,
+ False);
+ XClearArea(XtDisplay(w), XtWindow(w),
+ 0, cbw->command.highlight_thickness,
+ cbw->command.highlight_thickness,
+ XtHeight(cbw) - (cbw->command.highlight_thickness<<1),
+ False);
+ XClearArea(XtDisplay(w), XtWindow(w),
+ XtWidth(cbw) - cbw->command.highlight_thickness,
+ cbw->command.highlight_thickness,
+ cbw->command.highlight_thickness,
+ XtHeight(cbw) - (cbw->command.highlight_thickness<<1),
+ False);
+ XClearArea(XtDisplay(w), XtWindow(w),
+ 0, XtHeight(cbw) - cbw->command.highlight_thickness,
+ XtWidth(cbw), cbw->command.highlight_thickness,
+ False);
+ }
+ else {
+ int offset = cbw->command.highlight_thickness / 2;
+
+ XDrawRectangle(XtDisplay(w),XtWindow(w), rev_gc, offset, offset,
+ XtWidth(cbw) - cbw->command.highlight_thickness,
+ XtHeight(cbw) - cbw->command.highlight_thickness);
+ }
+ }
+ }
+
+ (*SuperClass->core_class.expose)(w, event, region);
+}
+
+static void
+XawCommandDestroy(Widget w)
+{
+ CommandWidget cbw = (CommandWidget)w;
+
+ /* Label will release cbw->command.normal_GC */
+ XtReleaseGC(w, cbw->command.inverse_GC);
+}
+
+/*ARGSUSED*/
+static Boolean
+XawCommandSetValues(Widget current, Widget request, Widget cnew,
+ ArgList args, Cardinal *num_args)
+{
+ CommandWidget oldcbw = (CommandWidget)current;
+ CommandWidget cbw = (CommandWidget)cnew;
+ Boolean redisplay = False;
+
+ if (oldcbw->core.sensitive != cbw->core.sensitive && !cbw->core.sensitive) {
+ cbw->command.highlighted = HighlightNone;
+ redisplay = True;
+ }
+
+ if (cbw->command.set) {
+ unsigned int i;
+ Pixel foreground, background;
+
+ foreground = oldcbw->label.foreground;
+ background = oldcbw->core.background_pixel;
+ for (i = 0; i < *num_args; i++) {
+ if (STR_EQUAL(args[i].name, XtNforeground))
+ background = cbw->label.foreground;
+ else if (STR_EQUAL(args[i].name, XtNbackground))
+ foreground = cbw->core.background_pixel;
+ }
+ cbw->label.foreground = foreground;
+ cbw->core.background_pixel = background;
+ }
+
+ if (oldcbw->label.foreground != cbw->label.foreground
+ || oldcbw->core.background_pixel != cbw->core.background_pixel
+ || oldcbw->command.highlight_thickness
+ != cbw->command.highlight_thickness
+ || oldcbw->label.font != cbw->label.font) {
+ XtReleaseGC(cnew, cbw->command.inverse_GC);
+
+ cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground,
+ cbw->core.background_pixel);
+ cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel,
+ cbw->label.foreground);
+ XtReleaseGC(cnew, cbw->label.normal_GC);
+ cbw->label.normal_GC = cbw->command.normal_GC;
+
+ redisplay = True;
+ }
+
+ if (XtIsRealized(cnew)
+ && oldcbw->command.shape_style != cbw->command.shape_style
+ && !ShapeButton(cbw, True))
+ cbw->command.shape_style = oldcbw->command.shape_style;
+
+ return (redisplay);
+}
+
+static void
+XawCommandGetValuesHook(Widget w, ArgList args, Cardinal *num_args)
+{
+ CommandWidget cbw = (CommandWidget)w;
+ unsigned int i;
+
+ for (i = 0; i < *num_args; i++) {
+ if (STR_EQUAL(args[i].name, XtNforeground))
+ *((String*)args[i].value) = cbw->command.set ?
+ (String)cbw->core.background_pixel : (String)cbw->label.foreground;
+ else if (STR_EQUAL(args[i].name, XtNbackground))
+ *((String*)args[i].value) = cbw->command.set ?
+ (String)cbw->label.foreground : (String)cbw->core.background_pixel;
+ }
+}
+
+static void
+XawCommandClassInitialize(void)
+{
+ XawInitializeWidgetSet();
+ XtSetTypeConverter(XtRString, XtRShapeStyle, XmuCvtStringToShapeStyle,
+ NULL, 0, XtCacheNone, NULL);
+ XtSetTypeConverter(XtRShapeStyle, XtRString, XmuCvtShapeStyleToString,
+ NULL, 0, XtCacheNone, NULL);
+}
+
+static Bool
+ShapeButton(CommandWidget cbw, Bool checkRectangular)
+{
+ Dimension corner_size = 0;
+
+ if (cbw->command.shape_style == XawShapeRoundedRectangle) {
+ corner_size = XtWidth(cbw) < XtHeight(cbw) ?
+ XtWidth(cbw) : XtHeight(cbw);
+ corner_size = (corner_size * cbw->command.corner_round) / 100;
+ }
+
+ if (checkRectangular || cbw->command.shape_style != XawShapeRectangle) {
+ if (!XmuReshapeWidget((Widget)cbw, cbw->command.shape_style,
+ corner_size, corner_size)) {
+ cbw->command.shape_style = XawShapeRectangle;
+ return (False);
+ }
+ }
+
+ return (True);
+}
+
+static void
+XawCommandRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
+{
+ (*commandWidgetClass->core_class.superclass->core_class.realize)
+ (w, valueMask, attributes);
+
+ ShapeButton((CommandWidget)w, False);
+}
+
+static void
+XawCommandResize(Widget w)
+{
+ if (XtIsRealized(w))
+ ShapeButton((CommandWidget)w, False);
+
+ (*commandWidgetClass->core_class.superclass->core_class.resize)(w);
+}
+
+static Bool
+ChangeSensitive(Widget w)
+{
+ CommandWidget cbw = (CommandWidget)w;
+
+ if (XtIsRealized(w)) {
+ if (XtIsSensitive(w)) {
+ if (w->core.border_pixmap != XtUnspecifiedPixmap)
+ XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w),
+ w->core.border_pixmap);
+ else
+ XSetWindowBorder(XtDisplay(w), XtWindow(w),
+ w->core.border_pixel);
+ }
+ else {
+ if (cbw->simple.insensitive_border == None)
+ cbw->simple.insensitive_border =
+ XmuCreateStippledPixmap(XtScreen(w),
+ w->core.border_pixel,
+ cbw->command.set ?
+ cbw->label.foreground :
+ w->core.background_pixel,
+ w->core.depth);
+ XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w),
+ cbw->simple.insensitive_border);
+ }
+ }
+
+ return (False);
+}
|