| /*********************************************************** |
| Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts, |
| and the Massachusetts Institute of Technology, Cambridge, 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 names of Digital or MIT 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. |
| |
| ******************************************************************/ |
| |
| /* |
| * Modifications for Wine |
| * |
| * 8/27/93 David Metcalfe (david@prism.demon.co.uk) |
| * Converted to WinCommand |
| */ |
| |
| /* |
| * WinCommand.c - WinCommand button widget |
| */ |
| |
| #include <stdio.h> |
| #include <X11/IntrinsicP.h> |
| #include <X11/StringDefs.h> |
| #include <X11/Xmu/Misc.h> |
| #include <X11/Xaw/XawInit.h> |
| #include "WinCommandP.h" |
| #include <X11/Xmu/Converters.h> |
| |
| #define DEFAULT_HIGHLIGHT_THICKNESS 2 |
| #define DEFAULT_SHAPE_HIGHLIGHT 32767 |
| |
| /**************************************************************** |
| * |
| * Full class record constant |
| * |
| ****************************************************************/ |
| |
| /* Private Data */ |
| |
| static char defaultTranslations[] = |
| "<EnterWindow>: highlight() \n\ |
| <LeaveWindow>: reset() \n\ |
| <Btn1Down>: set() \n\ |
| <Btn1Up>: notify() unset() "; |
| |
| #define offset(field) XtOffsetOf(WinCommandRec, field) |
| static XtResource resources[] = { |
| {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), |
| offset(wincommand.callbacks), XtRCallback, (XtPointer)NULL}, |
| {XtNhighlightThickness, XtCThickness, XtRDimension, sizeof(Dimension), |
| offset(wincommand.highlight_thickness), XtRImmediate, |
| (XtPointer) DEFAULT_SHAPE_HIGHLIGHT}, |
| {XtNshapeStyle, XtCShapeStyle, XtRShapeStyle, sizeof(int), |
| offset(wincommand.shape_style), XtRImmediate, |
| (XtPointer)XawShapeRectangle}, |
| {XtNcornerRoundPercent, XtCCornerRoundPercent, |
| XtRDimension, sizeof(Dimension), |
| offset(wincommand.corner_round), XtRImmediate, (XtPointer) 25}, |
| }; |
| #undef offset |
| |
| static Boolean SetValues(); |
| static void Initialize(), Redisplay(), Set(), Reset(), Notify(), Unset(); |
| static void Highlight(), Unhighlight(), Destroy(), PaintWinCommandWidget(); |
| static void ClassInitialize(); |
| static Boolean ShapeButton(); |
| static void Realize(), Resize(); |
| |
| static XtActionsRec actionsList[] = { |
| {"set", Set}, |
| {"notify", Notify}, |
| {"highlight", Highlight}, |
| {"reset", Reset}, |
| {"unset", Unset}, |
| {"unhighlight", Unhighlight} |
| }; |
| |
| #define SuperClass ((WinLabelWidgetClass)&winLabelClassRec) |
| |
| WinCommandClassRec winCommandClassRec = { |
| { |
| (WidgetClass) SuperClass, /* superclass */ |
| "WinCommand", /* class_name */ |
| sizeof(WinCommandRec), /* size */ |
| ClassInitialize, /* class_initialize */ |
| NULL, /* class_part_initialize */ |
| FALSE, /* class_inited */ |
| Initialize, /* initialize */ |
| NULL, /* initialize_hook */ |
| Realize, /* realize */ |
| actionsList, /* actions */ |
| XtNumber(actionsList), /* num_actions */ |
| resources, /* resources */ |
| XtNumber(resources), /* resource_count */ |
| NULLQUARK, /* xrm_class */ |
| FALSE, /* compress_motion */ |
| TRUE, /* compress_exposure */ |
| TRUE, /* compress_enterleave */ |
| FALSE, /* visible_interest */ |
| Destroy, /* destroy */ |
| Resize, /* resize */ |
| Redisplay, /* expose */ |
| SetValues, /* set_values */ |
| NULL, /* set_values_hook */ |
| XtInheritSetValuesAlmost, /* set_values_almost */ |
| NULL, /* get_values_hook */ |
| NULL, /* accept_focus */ |
| XtVersion, /* version */ |
| NULL, /* callback_private */ |
| defaultTranslations, /* tm_table */ |
| XtInheritQueryGeometry, /* query_geometry */ |
| XtInheritDisplayAccelerator, /* display_accelerator */ |
| NULL /* extension */ |
| }, /* CoreClass fields initialization */ |
| { |
| XtInheritChangeSensitive /* change_sensitive */ |
| }, /* SimpleClass fields initialization */ |
| { |
| 0, /* field not used */ |
| }, /* WinLabelClass fields initialization */ |
| { |
| 0, /* field not used */ |
| }, /* WinCommandClass fields initialization */ |
| }; |
| |
| /* for public consumption */ |
| WidgetClass winCommandWidgetClass = (WidgetClass) &winCommandClassRec; |
| |
| /**************************************************************** |
| * |
| * Private Procedures |
| * |
| ****************************************************************/ |
| |
| static GC |
| Get_GC(cbw, fg, bg) |
| WinCommandWidget cbw; |
| Pixel fg, bg; |
| { |
| XGCValues values; |
| |
| values.foreground = fg; |
| values.background = bg; |
| values.font = cbw->winlabel.font->fid; |
| values.cap_style = CapProjecting; |
| |
| if (cbw->wincommand.highlight_thickness > 1 ) |
| values.line_width = cbw->wincommand.highlight_thickness; |
| else |
| values.line_width = 0; |
| |
| return XtGetGC((Widget)cbw, |
| (GCForeground|GCBackground|GCFont|GCLineWidth|GCCapStyle), |
| &values); |
| } |
| |
| |
| /* ARGSUSED */ |
| static void |
| Initialize(request, new, args, num_args) |
| Widget request, new; |
| ArgList args; /* unused */ |
| Cardinal *num_args; /* unused */ |
| { |
| WinCommandWidget cbw = (WinCommandWidget) new; |
| int shape_event_base, shape_error_base; |
| |
| if (cbw->wincommand.shape_style != XawShapeRectangle |
| && !XShapeQueryExtension(XtDisplay(new), &shape_event_base, |
| &shape_error_base)) |
| cbw->wincommand.shape_style = XawShapeRectangle; |
| if (cbw->wincommand.highlight_thickness == DEFAULT_SHAPE_HIGHLIGHT) { |
| if (cbw->wincommand.shape_style != XawShapeRectangle) |
| cbw->wincommand.highlight_thickness = 0; |
| else |
| cbw->wincommand.highlight_thickness = DEFAULT_HIGHLIGHT_THICKNESS; |
| } |
| |
| cbw->wincommand.normal_GC = Get_GC(cbw, cbw->winlabel.foreground, |
| cbw->core.background_pixel); |
| cbw->wincommand.inverse_GC = Get_GC(cbw, cbw->core.background_pixel, |
| cbw->winlabel.foreground); |
| XtReleaseGC(new, cbw->winlabel.normal_GC); |
| cbw->winlabel.normal_GC = cbw->wincommand.normal_GC; |
| |
| cbw->wincommand.set = FALSE; |
| cbw->wincommand.highlighted = HighlightNone; |
| } |
| |
| static Region |
| HighlightRegion(cbw) |
| WinCommandWidget cbw; |
| { |
| static Region outerRegion = NULL, innerRegion, emptyRegion; |
| XRectangle rect; |
| |
| if (cbw->wincommand.highlight_thickness == 0 || |
| cbw->wincommand.highlight_thickness > |
| (Dimension) ((Dimension) Min(cbw->core.width, cbw->core.height)/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 = cbw->core.width; |
| rect.height = cbw->core.height; |
| XUnionRectWithRegion( &rect, emptyRegion, outerRegion ); |
| rect.x = rect.y = cbw->wincommand.highlight_thickness; |
| rect.width -= cbw->wincommand.highlight_thickness * 2; |
| rect.height -= cbw->wincommand.highlight_thickness * 2; |
| XUnionRectWithRegion( &rect, emptyRegion, innerRegion ); |
| XSubtractRegion( outerRegion, innerRegion, outerRegion ); |
| return outerRegion; |
| } |
| |
| /*************************** |
| * |
| * Action Procedures |
| * |
| ***************************/ |
| |
| /* ARGSUSED */ |
| static void |
| Set(w,event,params,num_params) |
| Widget w; |
| XEvent *event; |
| String *params; /* unused */ |
| Cardinal *num_params; /* unused */ |
| { |
| WinCommandWidget cbw = (WinCommandWidget)w; |
| |
| if (cbw->wincommand.set) |
| return; |
| |
| cbw->wincommand.set= TRUE; |
| if (XtIsRealized(w)) |
| PaintWinCommandWidget(w, (Region) NULL, TRUE); |
| } |
| |
| /* ARGSUSED */ |
| static void |
| Unset(w,event,params,num_params) |
| Widget w; |
| XEvent *event; |
| String *params; /* unused */ |
| Cardinal *num_params; |
| { |
| WinCommandWidget cbw = (WinCommandWidget)w; |
| |
| if (!cbw->wincommand.set) |
| return; |
| |
| cbw->wincommand.set = FALSE; |
| if (XtIsRealized(w)) { |
| XClearWindow(XtDisplay(w), XtWindow(w)); |
| PaintWinCommandWidget(w, (Region) NULL, TRUE); |
| } |
| } |
| |
| /* ARGSUSED */ |
| static void |
| Reset(w,event,params,num_params) |
| Widget w; |
| XEvent *event; |
| String *params; /* unused */ |
| Cardinal *num_params; /* unused */ |
| { |
| WinCommandWidget cbw = (WinCommandWidget)w; |
| |
| if (cbw->wincommand.set) { |
| cbw->wincommand.highlighted = HighlightNone; |
| Unset(w, event, params, num_params); |
| } |
| else |
| Unhighlight(w, event, params, num_params); |
| } |
| |
| /* ARGSUSED */ |
| static void |
| Highlight(w,event,params,num_params) |
| Widget w; |
| XEvent *event; |
| String *params; |
| Cardinal *num_params; |
| { |
| WinCommandWidget cbw = (WinCommandWidget)w; |
| |
| if ( *num_params == (Cardinal) 0) |
| cbw->wincommand.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->wincommand.highlighted = HighlightAlways; |
| break; |
| default: |
| cbw->wincommand.highlighted = HighlightWhenUnset; |
| break; |
| } |
| } |
| |
| if (XtIsRealized(w)) |
| PaintWinCommandWidget(w, HighlightRegion(cbw), TRUE); |
| } |
| |
| /* ARGSUSED */ |
| static void |
| Unhighlight(w,event,params,num_params) |
| Widget w; |
| XEvent *event; |
| String *params; /* unused */ |
| Cardinal *num_params; /* unused */ |
| { |
| WinCommandWidget cbw = (WinCommandWidget)w; |
| |
| cbw->wincommand.highlighted = HighlightNone; |
| if (XtIsRealized(w)) |
| PaintWinCommandWidget(w, HighlightRegion(cbw), TRUE); |
| } |
| |
| /* ARGSUSED */ |
| static void |
| Notify(w,event,params,num_params) |
| Widget w; |
| XEvent *event; |
| String *params; /* unused */ |
| Cardinal *num_params; /* unused */ |
| { |
| WinCommandWidget cbw = (WinCommandWidget)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->wincommand.set) |
| XtCallCallbackList(w, cbw->wincommand.callbacks, NULL); |
| } |
| |
| /* |
| * Repaint the widget window |
| */ |
| |
| /************************ |
| * |
| * REDISPLAY (DRAW) |
| * |
| ************************/ |
| |
| /* ARGSUSED */ |
| static void |
| Redisplay(w, event, region) |
| Widget w; |
| XEvent *event; |
| Region region; |
| { |
| PaintWinCommandWidget(w, region, FALSE); |
| } |
| |
| /* Function Name: PaintWinCommandWidget |
| * Description: Paints the wincommand widget. |
| * Arguments: w - the wincommand widget. |
| * region - region to paint (passed to the superclass). |
| * change - did it change either set or highlight state? |
| * Returns: none |
| */ |
| |
| static void |
| PaintWinCommandWidget(w, region, change) |
| Widget w; |
| Region region; |
| Boolean change; |
| { |
| WinCommandWidget cbw = (WinCommandWidget) w; |
| Boolean very_thick; |
| GC norm_gc, rev_gc; |
| |
| very_thick = cbw->wincommand.highlight_thickness > |
| (Dimension)((Dimension) Min(cbw->core.width, |
| cbw->core.height)/2); |
| |
| if (cbw->wincommand.set) { |
| cbw->winlabel.normal_GC = cbw->wincommand.inverse_GC; |
| XFillRectangle(XtDisplay(w), XtWindow(w), cbw->wincommand.normal_GC, |
| 0, 0, cbw->core.width, cbw->core.height); |
| region = NULL; /* Force label to repaint text. */ |
| } |
| else |
| cbw->winlabel.normal_GC = cbw->wincommand.normal_GC; |
| |
| if (cbw->wincommand.highlight_thickness <= 0) |
| { |
| (*SuperClass->core_class.expose) (w, (XEvent *) NULL, region); |
| return; |
| } |
| |
| /* |
| * If we are set then use the same colors as if we are not highlighted. |
| */ |
| |
| if (cbw->wincommand.set == (cbw->wincommand.highlighted == HighlightNone)) { |
| norm_gc = cbw->wincommand.inverse_GC; |
| rev_gc = cbw->wincommand.normal_GC; |
| } |
| else { |
| norm_gc = cbw->wincommand.normal_GC; |
| rev_gc = cbw->wincommand.inverse_GC; |
| } |
| |
| if ( !( (!change && (cbw->wincommand.highlighted == HighlightNone)) || |
| ((cbw->wincommand.highlighted == HighlightWhenUnset) && |
| (cbw->wincommand.set))) ) { |
| if (very_thick) { |
| cbw->winlabel.normal_GC = norm_gc; /* Give the label the right GC. */ |
| XFillRectangle(XtDisplay(w),XtWindow(w), rev_gc, |
| 0, 0, cbw->core.width, cbw->core.height); |
| } |
| else { |
| /* wide lines are centered on the path, so indent it */ |
| int offset = cbw->wincommand.highlight_thickness/2; |
| XDrawRectangle(XtDisplay(w),XtWindow(w), rev_gc, offset, offset, |
| cbw->core.width - cbw->wincommand.highlight_thickness, |
| cbw->core.height - cbw->wincommand.highlight_thickness); |
| } |
| } |
| (*SuperClass->core_class.expose) (w, (XEvent *) NULL, region); |
| } |
| |
| static void |
| Destroy(w) |
| Widget w; |
| { |
| WinCommandWidget cbw = (WinCommandWidget) w; |
| |
| /* so WinLabel can release it */ |
| if (cbw->winlabel.normal_GC == cbw->wincommand.normal_GC) |
| XtReleaseGC( w, cbw->wincommand.inverse_GC ); |
| else |
| XtReleaseGC( w, cbw->wincommand.normal_GC ); |
| } |
| |
| /* |
| * Set specified arguments into widget |
| */ |
| |
| /* ARGSUSED */ |
| static Boolean |
| SetValues (current, request, new) |
| Widget current, request, new; |
| { |
| WinCommandWidget oldcbw = (WinCommandWidget) current; |
| WinCommandWidget cbw = (WinCommandWidget) new; |
| Boolean redisplay = False; |
| |
| if ( oldcbw->core.sensitive != cbw->core.sensitive && !cbw->core.sensitive) { |
| /* about to become insensitive */ |
| cbw->wincommand.set = FALSE; |
| cbw->wincommand.highlighted = HighlightNone; |
| redisplay = TRUE; |
| } |
| |
| if ( (oldcbw->winlabel.foreground != cbw->winlabel.foreground) || |
| (oldcbw->core.background_pixel != cbw->core.background_pixel) || |
| (oldcbw->wincommand.highlight_thickness != |
| cbw->wincommand.highlight_thickness) || |
| (oldcbw->winlabel.font != cbw->winlabel.font) ) |
| { |
| if (oldcbw->winlabel.normal_GC == oldcbw->wincommand.normal_GC) |
| /* WinLabel has release one of these */ |
| XtReleaseGC(new, cbw->wincommand.inverse_GC); |
| else |
| XtReleaseGC(new, cbw->wincommand.normal_GC); |
| |
| cbw->wincommand.normal_GC = Get_GC(cbw, cbw->winlabel.foreground, |
| cbw->core.background_pixel); |
| cbw->wincommand.inverse_GC = Get_GC(cbw, cbw->core.background_pixel, |
| cbw->winlabel.foreground); |
| XtReleaseGC(new, cbw->winlabel.normal_GC); |
| cbw->winlabel.normal_GC = (cbw->wincommand.set |
| ? cbw->wincommand.inverse_GC |
| : cbw->wincommand.normal_GC); |
| |
| redisplay = True; |
| } |
| |
| if ( XtIsRealized(new) |
| && oldcbw->wincommand.shape_style != cbw->wincommand.shape_style |
| && !ShapeButton(cbw, TRUE)) |
| { |
| cbw->wincommand.shape_style = oldcbw->wincommand.shape_style; |
| } |
| |
| return (redisplay); |
| } |
| |
| static void ClassInitialize() |
| { |
| XawInitializeWidgetSet(); |
| XtSetTypeConverter( XtRString, XtRShapeStyle, XmuCvtStringToShapeStyle, |
| NULL, 0, XtCacheNone, NULL ); |
| } |
| |
| |
| static Boolean |
| ShapeButton(cbw, checkRectangular) |
| WinCommandWidget cbw; |
| Boolean checkRectangular; |
| { |
| Dimension corner_size; |
| |
| if ( (cbw->wincommand.shape_style == XawShapeRoundedRectangle) ) { |
| corner_size = (cbw->core.width < cbw->core.height) ? cbw->core.width |
| : cbw->core.height; |
| corner_size = (int) (corner_size * cbw->wincommand.corner_round) / 100; |
| } |
| |
| if (checkRectangular || cbw->wincommand.shape_style != XawShapeRectangle) { |
| if (!XmuReshapeWidget((Widget) cbw, cbw->wincommand.shape_style, |
| corner_size, corner_size)) { |
| cbw->wincommand.shape_style = XawShapeRectangle; |
| return(False); |
| } |
| } |
| return(TRUE); |
| } |
| |
| static void Realize(w, valueMask, attributes) |
| Widget w; |
| Mask *valueMask; |
| XSetWindowAttributes *attributes; |
| { |
| (*winCommandWidgetClass->core_class.superclass->core_class.realize) |
| (w, valueMask, attributes); |
| |
| ShapeButton( (WinCommandWidget) w, FALSE); |
| } |
| |
| static void Resize(w) |
| Widget w; |
| { |
| if (XtIsRealized(w)) |
| ShapeButton( (WinCommandWidget) w, FALSE); |
| |
| (*winCommandWidgetClass->core_class.superclass->core_class.resize)(w); |
| } |
| |