1 /***********************************************************
2 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
3 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Digital or MIT not be
12 used in advertising or publicity pertaining to distribution of the
13 software without specific, written prior permission.
15 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23 ******************************************************************/
26 * Modifications for Wine
28 * 8/27/93 David Metcalfe (david@prism.demon.co.uk)
29 * Converted to WinCommand
33 * WinCommand.c - WinCommand button widget
37 #include <X11/IntrinsicP.h>
38 #include <X11/StringDefs.h>
39 #include <X11/Xmu/Misc.h>
40 #include <X11/Xaw/XawInit.h>
41 #include "WinCommandP.h"
42 #include <X11/Xmu/Converters.h>
44 #define DEFAULT_HIGHLIGHT_THICKNESS 2
45 #define DEFAULT_SHAPE_HIGHLIGHT 32767
47 /****************************************************************
49 * Full class record constant
51 ****************************************************************/
55 static char defaultTranslations[] =
56 "<EnterWindow>: highlight() \n\
57 <LeaveWindow>: reset() \n\
59 <Btn1Up>: notify() unset() ";
61 #define offset(field) XtOffsetOf(WinCommandRec, field)
62 static XtResource resources[] = {
63 {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer),
64 offset(wincommand.callbacks), XtRCallback, (XtPointer)NULL},
65 {XtNhighlightThickness, XtCThickness, XtRDimension, sizeof(Dimension),
66 offset(wincommand.highlight_thickness), XtRImmediate,
67 (XtPointer) DEFAULT_SHAPE_HIGHLIGHT},
68 {XtNshapeStyle, XtCShapeStyle, XtRShapeStyle, sizeof(int),
69 offset(wincommand.shape_style), XtRImmediate,
70 (XtPointer)XawShapeRectangle},
71 {XtNcornerRoundPercent, XtCCornerRoundPercent,
72 XtRDimension, sizeof(Dimension),
73 offset(wincommand.corner_round), XtRImmediate, (XtPointer) 25},
77 static Boolean SetValues();
78 static void Initialize(), Redisplay(), Set(), Reset(), Notify(), Unset();
79 static void Highlight(), Unhighlight(), Destroy(), PaintWinCommandWidget();
80 static void ClassInitialize();
81 static Boolean ShapeButton();
82 static void Realize(), Resize();
84 static XtActionsRec actionsList[] = {
87 {"highlight", Highlight},
90 {"unhighlight", Unhighlight}
93 #define SuperClass ((WinLabelWidgetClass)&winLabelClassRec)
95 WinCommandClassRec winCommandClassRec = {
97 (WidgetClass) SuperClass, /* superclass */
98 "WinCommand", /* class_name */
99 sizeof(WinCommandRec), /* size */
100 ClassInitialize, /* class_initialize */
101 NULL, /* class_part_initialize */
102 FALSE, /* class_inited */
103 Initialize, /* initialize */
104 NULL, /* initialize_hook */
105 Realize, /* realize */
106 actionsList, /* actions */
107 XtNumber(actionsList), /* num_actions */
108 resources, /* resources */
109 XtNumber(resources), /* resource_count */
110 NULLQUARK, /* xrm_class */
111 FALSE, /* compress_motion */
112 TRUE, /* compress_exposure */
113 TRUE, /* compress_enterleave */
114 FALSE, /* visible_interest */
115 Destroy, /* destroy */
117 Redisplay, /* expose */
118 SetValues, /* set_values */
119 NULL, /* set_values_hook */
120 XtInheritSetValuesAlmost, /* set_values_almost */
121 NULL, /* get_values_hook */
122 NULL, /* accept_focus */
123 XtVersion, /* version */
124 NULL, /* callback_private */
125 defaultTranslations, /* tm_table */
126 XtInheritQueryGeometry, /* query_geometry */
127 XtInheritDisplayAccelerator, /* display_accelerator */
129 }, /* CoreClass fields initialization */
131 XtInheritChangeSensitive /* change_sensitive */
132 }, /* SimpleClass fields initialization */
134 0, /* field not used */
135 }, /* WinLabelClass fields initialization */
137 0, /* field not used */
138 }, /* WinCommandClass fields initialization */
141 /* for public consumption */
142 WidgetClass winCommandWidgetClass = (WidgetClass) &winCommandClassRec;
144 /****************************************************************
148 ****************************************************************/
152 WinCommandWidget cbw;
157 values.foreground = fg;
158 values.background = bg;
159 values.font = cbw->winlabel.font->fid;
160 values.cap_style = CapProjecting;
162 if (cbw->wincommand.highlight_thickness > 1 )
163 values.line_width = cbw->wincommand.highlight_thickness;
165 values.line_width = 0;
167 return XtGetGC((Widget)cbw,
168 (GCForeground|GCBackground|GCFont|GCLineWidth|GCCapStyle),
175 Initialize(request, new, args, num_args)
177 ArgList args; /* unused */
178 Cardinal *num_args; /* unused */
180 WinCommandWidget cbw = (WinCommandWidget) new;
181 int shape_event_base, shape_error_base;
183 if (cbw->wincommand.shape_style != XawShapeRectangle
184 && !XShapeQueryExtension(XtDisplay(new), &shape_event_base,
186 cbw->wincommand.shape_style = XawShapeRectangle;
187 if (cbw->wincommand.highlight_thickness == DEFAULT_SHAPE_HIGHLIGHT) {
188 if (cbw->wincommand.shape_style != XawShapeRectangle)
189 cbw->wincommand.highlight_thickness = 0;
191 cbw->wincommand.highlight_thickness = DEFAULT_HIGHLIGHT_THICKNESS;
194 cbw->wincommand.normal_GC = Get_GC(cbw, cbw->winlabel.foreground,
195 cbw->core.background_pixel);
196 cbw->wincommand.inverse_GC = Get_GC(cbw, cbw->core.background_pixel,
197 cbw->winlabel.foreground);
198 XtReleaseGC(new, cbw->winlabel.normal_GC);
199 cbw->winlabel.normal_GC = cbw->wincommand.normal_GC;
201 cbw->wincommand.set = FALSE;
202 cbw->wincommand.highlighted = HighlightNone;
207 WinCommandWidget cbw;
209 static Region outerRegion = NULL, innerRegion, emptyRegion;
212 if (cbw->wincommand.highlight_thickness == 0 ||
213 cbw->wincommand.highlight_thickness >
214 (Dimension) ((Dimension) Min(cbw->core.width, cbw->core.height)/2))
217 if (outerRegion == NULL) {
218 /* save time by allocating scratch regions only once. */
219 outerRegion = XCreateRegion();
220 innerRegion = XCreateRegion();
221 emptyRegion = XCreateRegion();
225 rect.width = cbw->core.width;
226 rect.height = cbw->core.height;
227 XUnionRectWithRegion( &rect, emptyRegion, outerRegion );
228 rect.x = rect.y = cbw->wincommand.highlight_thickness;
229 rect.width -= cbw->wincommand.highlight_thickness * 2;
230 rect.height -= cbw->wincommand.highlight_thickness * 2;
231 XUnionRectWithRegion( &rect, emptyRegion, innerRegion );
232 XSubtractRegion( outerRegion, innerRegion, outerRegion );
236 /***************************
240 ***************************/
244 Set(w,event,params,num_params)
247 String *params; /* unused */
248 Cardinal *num_params; /* unused */
250 WinCommandWidget cbw = (WinCommandWidget)w;
252 if (cbw->wincommand.set)
255 cbw->wincommand.set= TRUE;
257 PaintWinCommandWidget(w, (Region) NULL, TRUE);
262 Unset(w,event,params,num_params)
265 String *params; /* unused */
266 Cardinal *num_params;
268 WinCommandWidget cbw = (WinCommandWidget)w;
270 if (!cbw->wincommand.set)
273 cbw->wincommand.set = FALSE;
274 if (XtIsRealized(w)) {
275 XClearWindow(XtDisplay(w), XtWindow(w));
276 PaintWinCommandWidget(w, (Region) NULL, TRUE);
282 Reset(w,event,params,num_params)
285 String *params; /* unused */
286 Cardinal *num_params; /* unused */
288 WinCommandWidget cbw = (WinCommandWidget)w;
290 if (cbw->wincommand.set) {
291 cbw->wincommand.highlighted = HighlightNone;
292 Unset(w, event, params, num_params);
295 Unhighlight(w, event, params, num_params);
300 Highlight(w,event,params,num_params)
304 Cardinal *num_params;
306 WinCommandWidget cbw = (WinCommandWidget)w;
308 if ( *num_params == (Cardinal) 0)
309 cbw->wincommand.highlighted = HighlightWhenUnset;
311 if ( *num_params != (Cardinal) 1)
312 XtWarning("Too many parameters passed to highlight action table.");
313 switch (params[0][0]) {
316 cbw->wincommand.highlighted = HighlightAlways;
319 cbw->wincommand.highlighted = HighlightWhenUnset;
325 PaintWinCommandWidget(w, HighlightRegion(cbw), TRUE);
330 Unhighlight(w,event,params,num_params)
333 String *params; /* unused */
334 Cardinal *num_params; /* unused */
336 WinCommandWidget cbw = (WinCommandWidget)w;
338 cbw->wincommand.highlighted = HighlightNone;
340 PaintWinCommandWidget(w, HighlightRegion(cbw), TRUE);
345 Notify(w,event,params,num_params)
348 String *params; /* unused */
349 Cardinal *num_params; /* unused */
351 WinCommandWidget cbw = (WinCommandWidget)w;
353 /* check to be sure state is still Set so that user can cancel
354 the action (e.g. by moving outside the window, in the default
357 if (cbw->wincommand.set)
358 XtCallCallbackList(w, cbw->wincommand.callbacks, NULL);
362 * Repaint the widget window
365 /************************
369 ************************/
373 Redisplay(w, event, region)
378 PaintWinCommandWidget(w, region, FALSE);
381 /* Function Name: PaintWinCommandWidget
382 * Description: Paints the wincommand widget.
383 * Arguments: w - the wincommand widget.
384 * region - region to paint (passed to the superclass).
385 * change - did it change either set or highlight state?
390 PaintWinCommandWidget(w, region, change)
395 WinCommandWidget cbw = (WinCommandWidget) w;
399 very_thick = cbw->wincommand.highlight_thickness >
400 (Dimension)((Dimension) Min(cbw->core.width,
401 cbw->core.height)/2);
403 if (cbw->wincommand.set) {
404 cbw->winlabel.normal_GC = cbw->wincommand.inverse_GC;
405 XFillRectangle(XtDisplay(w), XtWindow(w), cbw->wincommand.normal_GC,
406 0, 0, cbw->core.width, cbw->core.height);
407 region = NULL; /* Force label to repaint text. */
410 cbw->winlabel.normal_GC = cbw->wincommand.normal_GC;
412 if (cbw->wincommand.highlight_thickness <= 0)
414 (*SuperClass->core_class.expose) (w, (XEvent *) NULL, region);
419 * If we are set then use the same colors as if we are not highlighted.
422 if (cbw->wincommand.set == (cbw->wincommand.highlighted == HighlightNone)) {
423 norm_gc = cbw->wincommand.inverse_GC;
424 rev_gc = cbw->wincommand.normal_GC;
427 norm_gc = cbw->wincommand.normal_GC;
428 rev_gc = cbw->wincommand.inverse_GC;
431 if ( !( (!change && (cbw->wincommand.highlighted == HighlightNone)) ||
432 ((cbw->wincommand.highlighted == HighlightWhenUnset) &&
433 (cbw->wincommand.set))) ) {
435 cbw->winlabel.normal_GC = norm_gc; /* Give the label the right GC. */
436 XFillRectangle(XtDisplay(w),XtWindow(w), rev_gc,
437 0, 0, cbw->core.width, cbw->core.height);
440 /* wide lines are centered on the path, so indent it */
441 int offset = cbw->wincommand.highlight_thickness/2;
442 XDrawRectangle(XtDisplay(w),XtWindow(w), rev_gc, offset, offset,
443 cbw->core.width - cbw->wincommand.highlight_thickness,
444 cbw->core.height - cbw->wincommand.highlight_thickness);
447 (*SuperClass->core_class.expose) (w, (XEvent *) NULL, region);
454 WinCommandWidget cbw = (WinCommandWidget) w;
456 /* so WinLabel can release it */
457 if (cbw->winlabel.normal_GC == cbw->wincommand.normal_GC)
458 XtReleaseGC( w, cbw->wincommand.inverse_GC );
460 XtReleaseGC( w, cbw->wincommand.normal_GC );
464 * Set specified arguments into widget
469 SetValues (current, request, new)
470 Widget current, request, new;
472 WinCommandWidget oldcbw = (WinCommandWidget) current;
473 WinCommandWidget cbw = (WinCommandWidget) new;
474 Boolean redisplay = False;
476 if ( oldcbw->core.sensitive != cbw->core.sensitive && !cbw->core.sensitive) {
477 /* about to become insensitive */
478 cbw->wincommand.set = FALSE;
479 cbw->wincommand.highlighted = HighlightNone;
483 if ( (oldcbw->winlabel.foreground != cbw->winlabel.foreground) ||
484 (oldcbw->core.background_pixel != cbw->core.background_pixel) ||
485 (oldcbw->wincommand.highlight_thickness !=
486 cbw->wincommand.highlight_thickness) ||
487 (oldcbw->winlabel.font != cbw->winlabel.font) )
489 if (oldcbw->winlabel.normal_GC == oldcbw->wincommand.normal_GC)
490 /* WinLabel has release one of these */
491 XtReleaseGC(new, cbw->wincommand.inverse_GC);
493 XtReleaseGC(new, cbw->wincommand.normal_GC);
495 cbw->wincommand.normal_GC = Get_GC(cbw, cbw->winlabel.foreground,
496 cbw->core.background_pixel);
497 cbw->wincommand.inverse_GC = Get_GC(cbw, cbw->core.background_pixel,
498 cbw->winlabel.foreground);
499 XtReleaseGC(new, cbw->winlabel.normal_GC);
500 cbw->winlabel.normal_GC = (cbw->wincommand.set
501 ? cbw->wincommand.inverse_GC
502 : cbw->wincommand.normal_GC);
507 if ( XtIsRealized(new)
508 && oldcbw->wincommand.shape_style != cbw->wincommand.shape_style
509 && !ShapeButton(cbw, TRUE))
511 cbw->wincommand.shape_style = oldcbw->wincommand.shape_style;
517 static void ClassInitialize()
519 XawInitializeWidgetSet();
520 XtSetTypeConverter( XtRString, XtRShapeStyle, XmuCvtStringToShapeStyle,
521 NULL, 0, XtCacheNone, NULL );
526 ShapeButton(cbw, checkRectangular)
527 WinCommandWidget cbw;
528 Boolean checkRectangular;
530 Dimension corner_size;
532 if ( (cbw->wincommand.shape_style == XawShapeRoundedRectangle) ) {
533 corner_size = (cbw->core.width < cbw->core.height) ? cbw->core.width
535 corner_size = (int) (corner_size * cbw->wincommand.corner_round) / 100;
538 if (checkRectangular || cbw->wincommand.shape_style != XawShapeRectangle) {
539 if (!XmuReshapeWidget((Widget) cbw, cbw->wincommand.shape_style,
540 corner_size, corner_size)) {
541 cbw->wincommand.shape_style = XawShapeRectangle;
548 static void Realize(w, valueMask, attributes)
551 XSetWindowAttributes *attributes;
553 (*winCommandWidgetClass->core_class.superclass->core_class.realize)
554 (w, valueMask, attributes);
556 ShapeButton( (WinCommandWidget) w, FALSE);
559 static void Resize(w)
563 ShapeButton( (WinCommandWidget) w, FALSE);
565 (*winCommandWidgetClass->core_class.superclass->core_class.resize)(w);