Release 0.3.0
[wine/multimedia.git] / controls / WinCommand.c
blobe05da8eeff641159857adffaf1846a024f3c8d9d
1 /***********************************************************
2 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
3 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
5 All Rights Reserved
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
21 SOFTWARE.
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
36 #include <stdio.h>
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 ****************************************************************/
53 /* Private Data */
55 static char defaultTranslations[] =
56 "<EnterWindow>: highlight() \n\
57 <LeaveWindow>: reset() \n\
58 <Btn1Down>: set() \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},
75 #undef offset
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[] = {
85 {"set", Set},
86 {"notify", Notify},
87 {"highlight", Highlight},
88 {"reset", Reset},
89 {"unset", Unset},
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 */
116 Resize, /* resize */
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 */
128 NULL /* extension */
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 /****************************************************************
146 * Private Procedures
148 ****************************************************************/
150 static GC
151 Get_GC(cbw, fg, bg)
152 WinCommandWidget cbw;
153 Pixel fg, bg;
155 XGCValues values;
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;
164 else
165 values.line_width = 0;
167 return XtGetGC((Widget)cbw,
168 (GCForeground|GCBackground|GCFont|GCLineWidth|GCCapStyle),
169 &values);
173 /* ARGSUSED */
174 static void
175 Initialize(request, new, args, num_args)
176 Widget request, new;
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,
185 &shape_error_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;
190 else
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;
205 static Region
206 HighlightRegion(cbw)
207 WinCommandWidget cbw;
209 static Region outerRegion = NULL, innerRegion, emptyRegion;
210 XRectangle rect;
212 if (cbw->wincommand.highlight_thickness == 0 ||
213 cbw->wincommand.highlight_thickness >
214 (Dimension) ((Dimension) Min(cbw->core.width, cbw->core.height)/2))
215 return(NULL);
217 if (outerRegion == NULL) {
218 /* save time by allocating scratch regions only once. */
219 outerRegion = XCreateRegion();
220 innerRegion = XCreateRegion();
221 emptyRegion = XCreateRegion();
224 rect.x = rect.y = 0;
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 );
233 return outerRegion;
236 /***************************
238 * Action Procedures
240 ***************************/
242 /* ARGSUSED */
243 static void
244 Set(w,event,params,num_params)
245 Widget w;
246 XEvent *event;
247 String *params; /* unused */
248 Cardinal *num_params; /* unused */
250 WinCommandWidget cbw = (WinCommandWidget)w;
252 if (cbw->wincommand.set)
253 return;
255 cbw->wincommand.set= TRUE;
256 if (XtIsRealized(w))
257 PaintWinCommandWidget(w, (Region) NULL, TRUE);
260 /* ARGSUSED */
261 static void
262 Unset(w,event,params,num_params)
263 Widget w;
264 XEvent *event;
265 String *params; /* unused */
266 Cardinal *num_params;
268 WinCommandWidget cbw = (WinCommandWidget)w;
270 if (!cbw->wincommand.set)
271 return;
273 cbw->wincommand.set = FALSE;
274 if (XtIsRealized(w)) {
275 XClearWindow(XtDisplay(w), XtWindow(w));
276 PaintWinCommandWidget(w, (Region) NULL, TRUE);
280 /* ARGSUSED */
281 static void
282 Reset(w,event,params,num_params)
283 Widget w;
284 XEvent *event;
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);
294 else
295 Unhighlight(w, event, params, num_params);
298 /* ARGSUSED */
299 static void
300 Highlight(w,event,params,num_params)
301 Widget w;
302 XEvent *event;
303 String *params;
304 Cardinal *num_params;
306 WinCommandWidget cbw = (WinCommandWidget)w;
308 if ( *num_params == (Cardinal) 0)
309 cbw->wincommand.highlighted = HighlightWhenUnset;
310 else {
311 if ( *num_params != (Cardinal) 1)
312 XtWarning("Too many parameters passed to highlight action table.");
313 switch (params[0][0]) {
314 case 'A':
315 case 'a':
316 cbw->wincommand.highlighted = HighlightAlways;
317 break;
318 default:
319 cbw->wincommand.highlighted = HighlightWhenUnset;
320 break;
324 if (XtIsRealized(w))
325 PaintWinCommandWidget(w, HighlightRegion(cbw), TRUE);
328 /* ARGSUSED */
329 static void
330 Unhighlight(w,event,params,num_params)
331 Widget w;
332 XEvent *event;
333 String *params; /* unused */
334 Cardinal *num_params; /* unused */
336 WinCommandWidget cbw = (WinCommandWidget)w;
338 cbw->wincommand.highlighted = HighlightNone;
339 if (XtIsRealized(w))
340 PaintWinCommandWidget(w, HighlightRegion(cbw), TRUE);
343 /* ARGSUSED */
344 static void
345 Notify(w,event,params,num_params)
346 Widget w;
347 XEvent *event;
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
355 bindings.
357 if (cbw->wincommand.set)
358 XtCallCallbackList(w, cbw->wincommand.callbacks, NULL);
362 * Repaint the widget window
365 /************************
367 * REDISPLAY (DRAW)
369 ************************/
371 /* ARGSUSED */
372 static void
373 Redisplay(w, event, region)
374 Widget w;
375 XEvent *event;
376 Region 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?
386 * Returns: none
389 static void
390 PaintWinCommandWidget(w, region, change)
391 Widget w;
392 Region region;
393 Boolean change;
395 WinCommandWidget cbw = (WinCommandWidget) w;
396 Boolean very_thick;
397 GC norm_gc, rev_gc;
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. */
409 else
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);
415 return;
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;
426 else {
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))) ) {
434 if (very_thick) {
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);
439 else {
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);
450 static void
451 Destroy(w)
452 Widget w;
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 );
459 else
460 XtReleaseGC( w, cbw->wincommand.normal_GC );
464 * Set specified arguments into widget
467 /* ARGSUSED */
468 static Boolean
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;
480 redisplay = TRUE;
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);
492 else
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);
504 redisplay = True;
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;
514 return (redisplay);
517 static void ClassInitialize()
519 XawInitializeWidgetSet();
520 XtSetTypeConverter( XtRString, XtRShapeStyle, XmuCvtStringToShapeStyle,
521 NULL, 0, XtCacheNone, NULL );
525 static Boolean
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
534 : cbw->core.height;
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;
542 return(False);
545 return(TRUE);
548 static void Realize(w, valueMask, attributes)
549 Widget w;
550 Mask *valueMask;
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)
560 Widget w;
562 if (XtIsRealized(w))
563 ShapeButton( (WinCommandWidget) w, FALSE);
565 (*winCommandWidgetClass->core_class.superclass->core_class.resize)(w);