1 /**
2 *
3 * $Header: /cvsroot/lesstif/lesstif/lib/Xm-2.1/ToggleBG.c,v 1.2 2004/10/21 18:53:59 dannybackx Exp $
4 *
5 * Copyright (C) 1995 Free Software Foundation, Inc.
6 * Copyright � 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004 LessTif Development Team
7 *
8 * This file is part of the GNU LessTif Library.
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 **/
25
26 static const char rcsid[] = "$Header: /cvsroot/lesstif/lesstif/lib/Xm-2.1/ToggleBG.c,v 1.2 2004/10/21 18:53:59 dannybackx Exp $";
27
28 #include <LTconfig.h>
29
30 #include <stdarg.h>
31 #include <string.h>
32
33 #include <XmI/XmI.h>
34
35 #include <Xm/XmP.h>
36 #include <Xm/ToggleBGP.h>
37 #include <Xm/CascadeB.h>
38 #include <Xm/CascadeBG.h>
39 #include <Xm/RepType.h>
40 #include <Xm/RowColumnP.h>
41 #include <Xm/MenuShell.h>
42 #include <Xm/MenuUtilP.h>
43 #include <Xm/CacheP.h>
44 #include <X11/ShellP.h>
45 #include <Xm/ToggleBP.h>
46
47 #include <XmI/DebugUtil.h>
48
49
50 /* Some M*tif versions (e.g. 1.2.6 on Solaris 2.6) leave less room above and
51 * below the indicator than others (e.g. 1.2.5 on HP-UX 10, my reference).
52 */
53 #undef LESS_VERTICAL_PADDING
54
55 #define UNSPECIFIED_TBG_BOOLEAN ((Boolean)85)
56 #define SQUARE_INDICATOR_DEC 3
57 #define SQUARE_INDICATOR_ELBOW 10
58 #define PIXMAP_INDICATOR_ELBOW 13
59
60 #define DETAIL_SHADOW_THICKNESS(w) TBG_DetailShadowThickness(w)
61 #define INDICATOR_BOX_MASK 0x03
62 #define NEXT_TOGGLE(w) (TBG_ToggleMode(w) == XmTOGGLE_BOOLEAN\
63 || TBG_IndType(w) != XmN_OF_MANY \
64 ? !TBG_Set(w) : (TBG_Set(w) + 1) % 3)
65
66 /* Forward Declarations */
67
68 static void class_initialize(void);
69
70 static void class_part_initialize(WidgetClass w_class);
71
72 static void initialize(Widget request, Widget new_w,
73 ArgList args, Cardinal *num_args);
74
75 static void destroy(Widget w);
76
77 static void resize(Widget w);
78
79 static void expose(Widget w, XEvent *event, Region region);
80
81 static Boolean set_values(Widget current, Widget request, Widget new_w,
82 ArgList args, Cardinal *num_args);
83
84 static void input_dispatch(Widget gadget, XEvent *event, Mask event_mask);
85
86 static void secondary_object_create(Widget request, Widget new_w,
87 ArgList args, Cardinal *num_args);
88
89 static void initialize_posthook(Widget request, Widget new_w,
90 ArgList args, Cardinal *num_args);
91
92 static Boolean set_values_prehook(Widget old, Widget request, Widget new_w,
93 ArgList args, Cardinal *num_args);
94
95 static Boolean set_values_posthook(Widget old, Widget request, Widget new_w,
96 ArgList args, Cardinal *num_args);
97
98 static void get_values_prehook(Widget new_w, ArgList args, Cardinal *num_args);
99
100 static void get_values_posthook(Widget new_w, ArgList args, Cardinal *num_args);
101
102 static Cardinal get_sec_res_data(WidgetClass wc,
103 XmSecondaryResourceData **data);
104
105
106 static void Arm(Widget w, XEvent *event,
107 String *params, Cardinal *num_params);
108
109 static void Select(Widget w, XEvent *event,
110 String *params, Cardinal *num_params);
111
112 static void Disarm(Widget w, XEvent *event,
113 String *params, Cardinal *num_params);
114
115 static void ArmAndActivate(Widget w, XEvent *event,
116 String *params, Cardinal *num_params);
117
118 static void Help(Widget w, XEvent *event,
119 String *params, Cardinal *num_params);
120
121 static void EnterWindow(Widget w, XEvent *event,
122 String *params, Cardinal *num_params);
123
124 static void LeaveWindow(Widget w, XEvent *event,
125 String *params, Cardinal *num_params);
126
127 static void ButtonDown(Widget w, XEvent *event,
128 String *params, Cardinal *num_params);
129
130 static void ButtonUp(Widget w, XEvent *event,
131 String *params, Cardinal *num_params);
132
133 static void MenuProcEntry(int proc, Widget rc,...);
134
135 static void draw_toggle(Widget w, XEvent *event, Region region,
136 int is_expose, int visual_set);
137
138 static int implicit_indicator(Widget w);
139 static void _XmUnselectColorDefault(Widget, int, XrmValue *);
140
141 /*
142 * resources
143 */
144 #define Offset(field) XtOffsetOf(XmToggleButtonGCacheObjRec, toggle_cache.field)
145 static XtResource cache_resources[] =
146 {
147 {
148 XmNindicatorSize, XmCIndicatorSize, XmRVerticalDimension,
149 sizeof(Dimension), Offset(indicator_dim),
150 XmRImmediate, (XtPointer)XmINVALID_DIMENSION
151 },
152 {
153 XmNindicatorType, XmCIndicatorType, XmRIndicatorType,
154 sizeof(unsigned char), Offset(ind_type),
155 XmRImmediate, (XtPointer)((unsigned char)XmUNSPECIFIED)
156 },
157 {
158 XmNvisibleWhenOff, XmCVisibleWhenOff, XmRBoolean,
159 sizeof(Boolean), Offset(visible),
160 XmRImmediate, (XtPointer)UNSPECIFIED_TBG_BOOLEAN
161 },
162 {
163 XmNspacing, XmCSpacing, XmRHorizontalDimension,
164 sizeof(Dimension), Offset(spacing),
165 XmRImmediate, (XtPointer)4
166 },
167 {
168 XmNselectPixmap, XmCSelectPixmap, XmRGadgetPixmap,
169 sizeof(Pixmap), Offset(on_pixmap),
170 XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP
171 },
172 {
173 XmNselectInsensitivePixmap, XmCSelectInsensitivePixmap, XmRGadgetPixmap,
174 sizeof(Pixmap), Offset(insen_pixmap),
175 XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP
176 },
177 {
178 /* The type changed to an unsigned char in 2.0..oh just lovely. */
179 XmNindicatorOn, XmCIndicatorOn, XmRIndicatorOn,
180 sizeof(unsigned char), Offset(ind_on),
181 XmRImmediate, (XtPointer)True
182 },
183 {
184 XmNfillOnSelect, XmCFillOnSelect, XmRBoolean,
185 sizeof(Boolean), Offset(fill_on_select),
186 XmRImmediate, (XtPointer)UNSPECIFIED_TBG_BOOLEAN
187 },
188 {
189 XmNselectColor, XmCSelectColor, XmRPixel,
190 sizeof(Pixel), Offset(select_color),
191 XmRCallProc, (XtPointer)_XmSelectColorDefault
192 },
193 {
194 XmNunselectColor, XmCUnselectColor, XmRPixel,
195 sizeof(Pixel), Offset(unselect_color),
196 XmRCallProc, (XtPointer)_XmUnselectColorDefault
197 }
198 };
199
200 static XmSyntheticResource cache_syn_resources[] =
201 {
202 {
203 XmNspacing,
204 sizeof(Dimension), Offset(spacing),
205 _XmFromHorizontalPixels, _XmToHorizontalPixels
206 },
207 {
208 XmNindicatorSize,
209 sizeof(Dimension), Offset(indicator_dim),
210 _XmFromVerticalPixels, _XmToVerticalPixels
211 }
212 };
213
214 XmToggleButtonGCacheObjClassRec xmToggleButtonGCacheObjClassRec = {
215 /* Object class part */
216 {
217 /* superclass */ (WidgetClass) &xmLabelGCacheObjClassRec,
218 /* class_name */ "XmToggleButtonGCacheObjClass",
219 /* widget_size */ sizeof(XmToggleButtonGCacheObjRec),
220 /* class_initialize */ NULL,
221 /* class_part_initialize */ NULL,
222 /* class_inited */ False,
223 /* initialize */ NULL,
224 /* initialize_hook */ NULL,
225 /* realize */ NULL,
226 /* actions */ NULL,
227 /* num_actions */ 0,
228 /* resources */ cache_resources,
229 /* num_resources */ XtNumber(cache_resources),
230 /* xrm_class */ NULLQUARK,
231 /* compress_motion */ 0,
232 /* compress_exposure */ 0,
233 /* compress_enterleave */ 0,
234 /* visible_interest */ 0,
235 /* destroy */ NULL,
236 /* resize */ NULL,
237 /* expose */ NULL,
238 /* set_values */ NULL,
239 /* set_values_hook */ NULL,
240 /* set_values_almost */ NULL,
241 /* get_values_hook */ NULL,
242 /* accept_focus */ NULL,
243 /* version */ XtVersion,
244 /* callback offsets */ NULL,
245 /* tm_table */ NULL,
246 /* query_geometry */ NULL,
247 /* display_accelerator */ NULL,
248 /* extension */ NULL
249 },
250 /* XmExtObject part */
251 {
252 /* syn_resources */ cache_syn_resources,
253 /* num_syn_resources */ XtNumber(cache_syn_resources),
254 /* extension */ NULL
255 },
256 /* LabelGCacheObj part */
257 {
258 /* foo */ 0
259 },
260 /* ToggleButtonGCacheObj part */
261 {
262 /* foo */ 0
263 }
264 };
265
266 #undef Offset
267 #define Offset(field) XtOffsetOf(XmToggleButtonGadgetRec, toggle.field)
268
269 /* Resources for the togglebutton class */
270 static XtResource resources[] = {
271 {
272 XmNset, XmCSet, XmRBoolean,
273 sizeof(Boolean), Offset(set),
274 XmRImmediate,(XtPointer)False
275 },
276 {
277 XmNvalueChangedCallback, XmCValueChangedCallback, XmRCallback,
278 sizeof(XtCallbackList), Offset(value_changed_CB),
279 XmRPointer, (XtPointer)NULL
280 },
281 {
282 XmNarmCallback, XmCArmCallback, XmRCallback,
283 sizeof(XtCallbackList), Offset(arm_CB),
284 XmRPointer, (XtPointer)NULL
285 },
286 {
287 XmNdisarmCallback, XmCDisarmCallback, XmRCallback,
288 sizeof(XtCallbackList), Offset(disarm_CB),
289 XmRPointer, (XtPointer)NULL
290 },
291 {
292 XmNtraversalOn, XmCTraversalOn, XmRBoolean,
293 sizeof(Boolean), XtOffsetOf(XmToggleButtonGadgetRec, gadget.traversal_on),
294 XmRImmediate, (XtPointer)True
295 },
296 {
297 XmNhighlightThickness, XmCHighlightThickness, XmRHorizontalDimension,
298 sizeof(Dimension),
299 XtOffsetOf(XmToggleButtonGadgetRec,gadget.highlight_thickness),
300 XmRImmediate, (XtPointer)2
301 },
302 /* New for 2.0 : */
303 {
304 XmNdetailShadowThickness, XmCDetailShadowThickness,
305 XmRDimension, sizeof(Dimension),
306 Offset(detail_shadow_thickness),
307 XmRImmediate, (XtPointer)2
308 },
309 {
310 XmNindeterminatePixmap, XmCIndeterminatePixmap,
311 XmRGadgetPixmap, sizeof(Pixmap),
312 Offset(indeterminate_pixmap),
313 XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP
314 },
315 {
316 XmNtoggleMode, XmCToggleMode,
317 XmRToggleMode, sizeof(unsigned char),
318 Offset(toggle_mode),
319 XmRImmediate, (XtPointer)XmTOGGLE_BOOLEAN
320 }
321 };
322
323 static XmSyntheticResource syn_resources[] =
324 {
325 {
326 XmNdetailShadowThickness,
327 sizeof(Dimension), Offset(detail_shadow_thickness),
328 _XmFromHorizontalPixels, _XmToHorizontalPixels
329 }
330 };
331
332 static XmBaseClassExtRec _XmToggleBGRectClassExtRec = {
333 /* next_extension */ NULL,
334 /* record_type */ NULLQUARK,
335 /* version */ XmBaseClassExtVersion,
336 /* size */ sizeof(XmBaseClassExtRec),
337 /* initialize_prehook */ XmInheritInitializePrehook,
338 /* set_values_prehook */ set_values_prehook,
339 /* initialize_posthook */ initialize_posthook,
340 /* set_values_posthook */ set_values_posthook,
341 /* secondary_object_class */ (WidgetClass)&xmToggleButtonGCacheObjClassRec,
342 /* secondary_object_create */ secondary_object_create,
343 /* get_secondary_resources */ get_sec_res_data,
344 /* fast_subclass */ { 0 },
345 /* get_values_prehook */ get_values_prehook,
346 /* get_values_posthook */ get_values_posthook,
347 /* class_part_init_prehook */ NULL,
348 /* class_part_init_posthook */ NULL,
349 /* ext_resources */ NULL,
350 /* compiled_ext_resources */ NULL,
351 /* num_ext_resources */ 0,
352 /* use_sub_resources */ False,
353 /* widget_navigable */ XmInheritWidgetNavigable,
354 /* focus_change */ XmInheritFocusChange,
355 /* wrapper_data */ NULL
356 };
357
358 static XmCacheClassPart cache_part = {
359 /* cache head part */
360 {
361 /* next */ NULL,
362 /* prev */ NULL,
363 /* ref_count */ 0
364 },
365 _XmCacheCopy,
366 _XmCacheDelete,
367 _XmToggleBCacheCompare
368 };
369
370 static XmGadgetClassExtRec _XmToggleBGadgetClassExtRec = {
371 /* next_extension */ NULL,
372 /* record_type */ NULLQUARK,
373 /* version */ XmGadgetClassExtVersion,
374 /* size */ sizeof(XmGadgetClassExtRec),
375 /* widget_baseline_proc */ XmInheritBaselineProc,
376 /* display_rect_proc */ XmInheritDisplayRectProc,
377 /* margins_proc */ XmInheritMarginsProc,
378 };
379
380 XmToggleButtonGadgetClassRec xmToggleButtonGadgetClassRec = {
381 /* RectObj class part */
382 {
383 /* superclass */ (WidgetClass) &xmLabelGadgetClassRec,
384 /* class_name */ "XmToggleButtonGadget",
385 /* widget_size */ sizeof(XmToggleButtonGadgetRec),
386 /* class_initialize */ class_initialize,
387 /* class_part_initialize */ class_part_initialize,
388 /* class_inited */ False,
389 /* initialize */ initialize,
390 /* initialize_hook */ NULL,
391 /* realize */ NULL, /* FIX ME */
392 /* actions */ NULL,
393 /* num_actions */ 0,
394 /* resources */ resources,
395 /* num_resources */ XtNumber(resources),
396 /* xrm_class */ NULLQUARK,
397 /* compress_motion */ True /*False*/,
398 /* compress_exposure */ XtExposeCompressMaximal /*XtExposeNoCompress*/,
399 /* compress_enterleave */ True /*False*/,
400 /* visible_interest */ False,
401 /* destroy */ destroy,
402 /* resize */ resize,
403 /* expose */ expose,
404 /* set_values */ set_values,
405 /* set_values_hook */ NULL,
406 /* set_values_almost */ XtInheritSetValuesAlmost,
407 /* get_values_hook */ NULL,
408 /* accept_focus */ NULL,
409 /* version */ XtVersionDontCheck,
410 /* callback offsets */ NULL,
411 /* tm_table */ NULL,
412 /* query_geometry */ XtInheritQueryGeometry,
413 /* display_accelerator */ NULL,
414 /* extension */ (XtPointer)&_XmToggleBGRectClassExtRec
415 },
416 /* XmGadget part */
417 {
418 /* border_highlight */ XmInheritBorderHighlight, /* FIX ME */
419 /* border_unhighlight */ XmInheritBorderUnhighlight, /* FIX ME */
420 /* arm_and_activate */ ArmAndActivate,
421 /* input_dispatch */ input_dispatch,
422 /* visual_change */ NULL, /* FIX ME */
423 /* syn_resources */ syn_resources,
424 /* num_syn_resources */ 0,
425 /* cache_part */ &cache_part,
426 /* extension */ (XtPointer)&_XmToggleBGadgetClassExtRec
427 },
428 /* XmLabelGadget part */
429 {
430 /* setOverrideCallback */ XmInheritSetOverrideCallback,
431 /* menuProcs */ XmInheritMenuProc,
432 /* extension */ NULL
433 },
434 /* XmToggleButtonGadget part */
435 {
436 /* extension */ NULL
437 },
438 };
439
440
441 WidgetClass xmToggleButtonGadgetClass = (WidgetClass)&xmToggleButtonGadgetClassRec;
442
443 /*
444 * Some #defines to make the code below more readable
445 */
446
447 #define IN_MENU(w) (LabG_MenuType(w) == XmMENU_POPUP || \
448 LabG_MenuType(w) == XmMENU_PULLDOWN)
449
450 /******************************* CACHE PART *********************************/
451 static void
secondary_object_create(Widget request,Widget new_w,ArgList args,Cardinal * num_args)452 secondary_object_create(Widget request,
453 Widget new_w,
454 ArgList args,
455 Cardinal *num_args)
456 {
457 XmBaseClassExt *bce;
458 XtPointer nsec, rsec;
459 XmWidgetExtData ed;
460 Cardinal size;
461
462 DEBUGOUT(_LtDebug(__FILE__, new_w,
463 "ToggleButtonGCacheRec %s being initialized.\n",
464 XtName(new_w)));
465
466 bce = _XmGetBaseClassExtPtr(XtClass(new_w), XmQmotif);
467
468 size = (*bce)->secondaryObjectClass->core_class.widget_size;
469 nsec = _XmExtObjAlloc(size);
470 rsec = _XmExtObjAlloc(size);
471
472 ((XmExtRec *)nsec)->object.self = (Widget)nsec;
473 ((XmExtRec *)nsec)->object.widget_class = (*bce)->secondaryObjectClass;
474 ((XmExtRec *)nsec)->object.parent = XtParent(new_w);
475 ((XmExtRec *)nsec)->object.xrm_name = new_w->core.xrm_name;
476 ((XmExtRec *)nsec)->object.being_destroyed = False;
477 ((XmExtRec *)nsec)->object.destroy_callbacks = NULL;
478 ((XmExtRec *)nsec)->object.constraints = NULL;
479
480 ExtObj_LogicalParent(nsec) = new_w;
481 ExtObj_ExtensionType(nsec) = XmCACHE_EXTENSION;
482
483 XtGetSubresources(new_w, nsec, NULL, NULL,
484 (*bce)->secondaryObjectClass->core_class.resources,
485 (*bce)->secondaryObjectClass->core_class.num_resources,
486 args, *num_args);
487
488 ed = (XmWidgetExtData)XtMalloc(sizeof(XmWidgetExtDataRec));
489 ed->widget = (Widget)nsec;
490 ed->reqWidget = (Widget)rsec;
491
492 memcpy(rsec, nsec, size);
493 ((XmExtRec *)rsec)->object.self = (Widget)rsec;
494
495 _XmPushWidgetExtData(new_w, ed, XmCACHE_EXTENSION);
496
497 LabG_Cache(new_w) = &(((XmLabelGCacheObject)nsec)->label_cache);
498 LabG_Cache(request) = &(((XmLabelGCacheObject)rsec)->label_cache);
499
500 TBG_Cache(new_w) = &(((XmToggleButtonGCacheObject)nsec)->toggle_cache);
501 TBG_Cache(request) = &(((XmToggleButtonGCacheObject)rsec)->toggle_cache);
502 }
503
504 int
_XmToggleBCacheCompare(XtPointer A,XtPointer B)505 _XmToggleBCacheCompare(XtPointer A, XtPointer B)
506 {
507 return !memcmp(((XmToggleButtonGCacheObjPart *)A),
508 ((XmToggleButtonGCacheObjPart *)B),
509 sizeof(XmToggleButtonGCacheObjPart));
510 }
511
512 /******************************* CACHE PART *********************************/
513 static void
class_initialize(void)514 class_initialize(void)
515 {
516 XtResourceList combined, labels;
517 int ncom;
518 Cardinal nlabels;
519
520 /* don't let the nulls fool you. look at the header file -- the arg
521 * isn't used. */
522 ClassCacheHead(TBG_ClassCachePart(NULL)).prev =
523 &ClassCacheHead(TBG_ClassCachePart(NULL));
524 ClassCacheHead(TBG_ClassCachePart(NULL)).next =
525 &ClassCacheHead(TBG_ClassCachePart(NULL));
526
527 _XmToggleBGRectClassExtRec.record_type = XmQmotif;
528
529 /*
530 * Label subclasses (ToggleBG, PushBG, CascadeBG) have a problem. Since
531 * we do all the subpart manipulation in the pre- and post- hooks, and
532 * since those hooks aren't chained, we have to either make multiple
533 * calls to XtGetSubresources/Xt[Get|Set]Subvalues, or merge the resource
534 * lists. Since I just wrote _XmTransformSubresources, seems like a
535 * waste not to use it.
536 */
537 ncom = XtNumber(cache_resources) +
538 xmLabelGCacheObjClassRec.object_class.num_resources;
539
540 _XmTransformSubResources(xmLabelGCacheObjClassRec.object_class.resources,
541 xmLabelGCacheObjClassRec.object_class.num_resources,
542 &labels, &nlabels);
543
544 combined = (XtResourceList)XtMalloc(sizeof(XtResource) * ncom);
545 memcpy(combined, labels, nlabels * sizeof(XtResource));
546 memcpy(&combined[nlabels],
547 cache_resources,
548 XtNumber(cache_resources) * sizeof(XtResource));
549 XtFree((char *)labels);
550
551 xmToggleButtonGCacheObjClassRec.object_class.resources = combined;
552 xmToggleButtonGCacheObjClassRec.object_class.num_resources = ncom;
553 }
554
555 static void
class_part_initialize(WidgetClass widget_class)556 class_part_initialize(WidgetClass widget_class)
557 {
558 _XmFastSubclassInit(widget_class, XmTOGGLE_BUTTON_GADGET_BIT);
559 }
560
561 static void
CreateSelectGC(Widget w)562 CreateSelectGC(Widget w)
563 {
564 XGCValues values;
565 XtGCMask mask;
566
567 mask = GCForeground | GCBackground | GCFillStyle | GCFunction |
568 GCSubwindowMode | GCGraphicsExposures | GCPlaneMask;
569
570 if (TBG_VisualSet(w) == XmINDETERMINATE)
571 {
572 mask |= GCStipple | GCTileStipXOrigin | GCTileStipYOrigin;
573 values.fill_style = FillOpaqueStippled;
574 values.ts_x_origin = values.ts_y_origin = 0;
575 values.stipple =
576 XmGetPixmapByDepth(XtScreen(w), "50_foreground", 1, 0, 1);
577 } else {
578 values.fill_style = FillSolid;
579 }
580 values.function = GXcopy;
581 values.plane_mask = -1;
582 values.subwindow_mode = ClipByChildren;
583 values.graphics_exposures = False;
584 values.foreground = TBG_SelectColor(w);
585 values.background = XmParentBackground(w);
586
587 TBG_SelectGC(w) = XtGetGC(w, mask, &values);
588
589 values.foreground = TBG_UnselectColor(w);
590
591 DEBUGOUT(_LtDebug(__FILE__, w, "CreateSelectGC: unselect color %p\n",
592 TBG_UnselectColor(w)));
593
594 TBG_UnselectGC(w) = XtGetGC(w, mask, &values);
595 }
596
597 static void
CreateBackgroundGC(Widget w)598 CreateBackgroundGC(Widget w)
599 {
600 XGCValues values;
601 XtGCMask mask;
602
603 mask = GCForeground | GCBackground | GCFillStyle | GCFunction |
604 GCSubwindowMode | GCGraphicsExposures | GCPlaneMask;
605
606 values.fill_style = FillSolid;
607 values.function = GXcopy;
608 values.plane_mask = -1;
609 values.subwindow_mode = ClipByChildren;
610 values.graphics_exposures = False;
611 values.foreground = XmParentBackground(w);
612 values.background = XmParentForeground(w);
613
614 TBG_BackgroundGC(w) = XtGetGC(w, mask, &values);
615 }
616
617 static void
initialize_posthook(Widget request,Widget new_w,ArgList args,Cardinal * num_args)618 initialize_posthook(Widget request, Widget new_w,
619 ArgList args, Cardinal *num_args)
620 {
621 XmWidgetExtData ext;
622
623 DEBUGOUT(_LtDebug(__FILE__, new_w, "ToggleBG InitializePosthook\n"));
624
625 /* don't let the null fool you */
626 LabG_Cache(new_w) = (XmLabelGCacheObjPart *)
627 _XmCachePart(LabG_ClassCachePart(NULL),
628 (XtPointer)LabG_Cache(new_w),
629 sizeof(XmLabelGCacheObjPart));
630 TBG_Cache(new_w) = (XmToggleButtonGCacheObjPart *)
631 _XmCachePart(TBG_ClassCachePart(NULL),
632 (XtPointer)TBG_Cache(new_w),
633 sizeof(XmToggleButtonGCacheObjPart));
634
635 _XmPopWidgetExtData(new_w, &ext, XmCACHE_EXTENSION);
636 _XmExtObjFree((XtPointer)ext->widget);
637 _XmExtObjFree((XtPointer)ext->reqWidget);
638 XtFree((char *)ext);
639 }
640
641 static void
initialize(Widget request,Widget new_w,ArgList args,Cardinal * num_args)642 initialize(Widget request, Widget new_w,
643 ArgList args, Cardinal *num_args)
644 {
645 if (!XtIsSubclass(XtParent(new_w), xmManagerWidgetClass))
646 {
647 _XmError(new_w, "parent should be manager.");
648 }
649
650 TBG_Armed(new_w) = False;
651
652 TBG_VisualSet(new_w) = TBG_Set(new_w);
653
654 /* Fix up the pixmaps */
655 if (LabG_Pixmap(new_w) == XmUNSPECIFIED_PIXMAP &&
656 TBG_OnPixmap(new_w) != XmUNSPECIFIED_PIXMAP)
657 LabG_Pixmap(new_w) = TBG_OnPixmap(new_w);
658
659 if (LabG_PixmapInsensitive(new_w) == XmUNSPECIFIED_PIXMAP &&
660 TBG_InsenPixmap(new_w) != XmUNSPECIFIED_PIXMAP)
661 LabG_PixmapInsensitive(new_w) = TBG_InsenPixmap(new_w);
662
663 if (LabG_IsPixmap(new_w) &&
664 (TBG_IndeterminatePixmap(new_w) != XmUNSPECIFIED_PIXMAP ||
665 ((XtSensitive(new_w)
666 ? TBG_OnPixmap(new_w)
667 : TBG_InsenPixmap(new_w))
668 != XmUNSPECIFIED_PIXMAP)))
669 {
670 Dimension width, height;
671 Dimension iwidth, iheight;
672
673 _XmLabelGetPixmapSize(new_w,
674 (XtSensitive(new_w)
675 ? TBG_OnPixmap(new_w)
676 : TBG_InsenPixmap(new_w)),
677 &width, &height);
678
679 _XmLabelGetPixmapSize(new_w, TBG_IndeterminatePixmap(new_w),
680 &iwidth, &iheight);
681 if (width < iwidth)
682 width = iwidth;
683 if (height < iheight)
684 height = iheight;
685
686 if (LabG_TextRect_width(new_w) < width ||
687 LabG_TextRect_height(new_w) < height)
688 {
689 if (LabG_TextRect_width(new_w) < width)
690 LabG_TextRect_width(new_w) = width;
691 if (LabG_TextRect_height(new_w) < height)
692 LabG_TextRect_height(new_w) = height;
693 if (!XtWidth(request) || !XtHeight(request))
694 {
695 if (!XtWidth(request))
696 XtWidth(new_w) = 0;
697 if (!XtHeight(request))
698 XtHeight(new_w) = 0;
699 xmToggleButtonGadgetClassRec.rect_class.resize(new_w);
700 }
701 }
702 }
703
704 if (TBG_IndicatorDim(new_w) == XmINVALID_DIMENSION)
705 {
706 TBG_IndicatorSet(new_w) = LabG_IsPixmap(new_w);
707 TBG_IndicatorDim(new_w) = implicit_indicator(new_w);
708 }
709 else
710 {
711 TBG_IndicatorSet(new_w) = True;
712 }
713
714 CreateSelectGC(new_w);
715 CreateBackgroundGC(new_w);
716
717 if (!XmRepTypeValidValue(XmRepTypeGetId(XmRToggleMode),
718 TBG_ToggleMode(new_w), new_w))
719 TBG_ToggleMode(new_w) = XmTOGGLE_BOOLEAN;
720
721 if (TBG_IndType(new_w) == (unsigned char)XmUNSPECIFIED ||
722 !XmRepTypeValidValue(XmRepTypeGetId(XmRIndicatorType),
723 TBG_IndType(new_w), new_w))
724 {
725 TBG_IndType(new_w) =
726 XmIsRowColumn(XtParent(new_w)) && RC_RadioBehavior(XtParent(new_w))
727 ? XmONE_OF_MANY
728 : XmN_OF_MANY;
729 }
730
731 if (TBG_Visible(new_w) == UNSPECIFIED_TBG_BOOLEAN)
732 TBG_Visible(new_w) = !IN_MENU(new_w);
733
734 if (TBG_FillOnSelect(new_w) == UNSPECIFIED_TBG_BOOLEAN)
735 TBG_FillOnSelect(new_w) = (TBG_IndType(new_w) == XmN_OF_MANY
736 ? TBG_IndOn(new_w) & INDICATOR_BOX_MASK
737 : TBG_IndOn(new_w)) != 0;
738
739 if (TBG_IndOn(new_w))
740 {
741 int margin;
742
743 /* Make sure there's enough room on the side for the indicator */
744 margin = (TBG_IndicatorDim(new_w) + TBG_Spacing(new_w))
745 - (LabG_StringDirection(new_w) == XmSTRING_DIRECTION_L_TO_R
746 ? LabG_MarginLeft(new_w) : LabG_MarginRight(new_w));
747 if (margin > 0)
748 {
749 if (LabG_StringDirection(new_w) == XmSTRING_DIRECTION_L_TO_R)
750 {
751 LabG_MarginLeft(new_w) += margin;
752 LabG_TextRect_x(new_w) += margin;
753 LabG_AccTextRect(new_w).x += margin;
754 }
755 else
756 LabG_MarginRight(new_w) += margin;
757 if (!XtWidth(request))
758 XtWidth(new_w) += margin;
759 }
760
761 /* Make sure there's enough room vertically.
762 * Non-menu toggles want some padding space.
763 */
764 margin = TBG_IndicatorDim(new_w) - (LabG_TextRect_height(new_w)
765 + LabG_MarginTop(new_w)
766 + LabG_MarginBottom(new_w));
767 #ifdef LESS_VERTICAL_PADDING
768 margin -= LabG_MarginHeight(new_w) << 1;
769 #else
770 if (!IN_MENU(new_w))
771 margin += (LabG_Shadow(new_w) + Xm3D_ENHANCE_PIXEL) << 1;
772 #endif
773 if (margin > 0)
774 {
775 LabG_MarginTop(new_w) += margin >> 1;
776 LabG_MarginBottom(new_w) += margin >> 1;
777 if (!XtHeight(request))
778 {
779 LabG_TextRect_y(new_w) += margin >> 1;
780 LabG_AccTextRect(new_w).y += margin >> 1;
781 XtHeight(new_w) += margin;
782 }
783 }
784 }
785
786 if (IN_MENU(new_w))
787 {
788 LabG_Highlight(new_w) = 0;
789 if (LabG_Shadow(new_w) == 0)
790 LabG_Shadow(new_w) = 2;
791 LabGClass_MenuProcs(XtClass(new_w)) = MenuProcEntry;
792 }
793
794 G_EventMask(new_w) = XmARM_EVENT | XmACTIVATE_EVENT | XmENTER_EVENT |
795 XmLEAVE_EVENT | XmMOTION_EVENT | XmFOCUS_IN_EVENT |
796 XmFOCUS_OUT_EVENT | XmMULTI_ARM_EVENT | XmMULTI_ACTIVATE_EVENT |
797 XmHELP_EVENT | XmBDRAG_EVENT;
798 }
799
800 static void
destroy(Widget w)801 destroy(Widget w)
802 {
803 XtReleaseGC(w, TBG_SelectGC(w));
804 XtReleaseGC(w, TBG_BackgroundGC(w));
805 XtReleaseGC(w, TBG_UnselectGC(w));
806
807 _XmCacheDelete((XtPointer)TBG_Cache(w));
808 }
809
810 static Boolean
set_values_prehook(Widget old,Widget request,Widget new_w,ArgList args,Cardinal * num_args)811 set_values_prehook(Widget old, Widget request, Widget new_w,
812 ArgList args, Cardinal *num_args)
813 {
814 XmBaseClassExt *bce;
815 XmWidgetExtData ed;
816 Cardinal size;
817 XtPointer nsec, rsec;
818
819 bce = _XmGetBaseClassExtPtr(XtClass(new_w), XmQmotif);
820 size = (*bce)->secondaryObjectClass->core_class.widget_size;
821
822 nsec = _XmExtObjAlloc(size);
823 rsec = _XmExtObjAlloc(size);
824
825 ((XmExtRec *)nsec)->object.self = (Widget)nsec;
826 ((XmExtRec *)nsec)->object.widget_class = (*bce)->secondaryObjectClass;
827 ((XmExtRec *)nsec)->object.parent = XtParent(new_w);
828 ((XmExtRec *)nsec)->object.xrm_name = new_w->core.xrm_name;
829 ((XmExtRec *)nsec)->object.being_destroyed = False;
830 ((XmExtRec *)nsec)->object.constraints = NULL;
831
832 ExtObj_LogicalParent(nsec) = new_w;
833 ExtObj_ExtensionType(nsec) = XmCACHE_EXTENSION;
834
835 memcpy(&((XmLabelGCacheObject)nsec)->label_cache,
836 LabG_Cache(new_w),
837 sizeof(XmLabelGCacheObjPart));
838 memcpy(&((XmToggleButtonGCacheObject)nsec)->toggle_cache,
839 TBG_Cache(new_w),
840 sizeof(XmToggleButtonGCacheObjPart));
841
842 ed = (XmWidgetExtData)XtMalloc(sizeof(XmWidgetExtDataRec));
843 ed->widget = (Widget)nsec;
844 ed->reqWidget = (Widget)rsec;
845
846 _XmPushWidgetExtData(new_w, ed, XmCACHE_EXTENSION);
847
848 _XmGadgetImportSecondaryArgs(new_w, args, num_args);
849
850 XtSetSubvalues((XtPointer)nsec,
851 (*bce)->secondaryObjectClass->core_class.resources,
852 (*bce)->secondaryObjectClass->core_class.num_resources,
853 args, *num_args);
854
855 memcpy(rsec, nsec, size);
856
857 LabG_Cache(new_w) = &(((XmToggleButtonGCacheObject)nsec)->label_cache);
858 LabG_Cache(request) = &(((XmToggleButtonGCacheObject)rsec)->label_cache);
859 TBG_Cache(new_w) = &(((XmToggleButtonGCacheObject)nsec)->toggle_cache);
860 TBG_Cache(request) = &(((XmToggleButtonGCacheObject)rsec)->toggle_cache);
861
862 _XmExtImportArgs((Widget)nsec, args, num_args);
863
864 return False;
865 }
866
867 static Boolean
set_values_posthook(Widget old,Widget request,Widget new_w,ArgList args,Cardinal * num_args)868 set_values_posthook(Widget old, Widget request, Widget new_w,
869 ArgList args, Cardinal *num_args)
870 {
871 XmWidgetExtData ext;
872
873 if (!_XmLabelCacheCompare((XtPointer)LabG_Cache(new_w),
874 (XtPointer)LabG_Cache(old)))
875 {
876
877 _XmCacheDelete((XtPointer)LabG_Cache(old));
878
879 LabG_Cache(new_w) = (XmLabelGCacheObjPart *)
880 _XmCachePart(LabG_ClassCachePart(NULL),
881 (XtPointer)LabG_Cache(new_w),
882 sizeof(XmLabelGCacheObjPart));
883 }
884 else
885 {
886 LabG_Cache(new_w) = LabG_Cache(old);
887 }
888
889 if (!_XmToggleBCacheCompare((XtPointer)TBG_Cache(new_w),
890 (XtPointer)TBG_Cache(old)))
891 {
892
893 _XmCacheDelete((XtPointer)TBG_Cache(old));
894
895 TBG_Cache(new_w) = (XmToggleButtonGCacheObjPart *)
896 _XmCachePart(TBG_ClassCachePart(NULL),
897 (XtPointer)TBG_Cache(new_w),
898 sizeof(XmToggleButtonGCacheObjPart));
899 }
900 else
901 {
902 TBG_Cache(new_w) = TBG_Cache(old);
903 }
904
905 _XmPopWidgetExtData(new_w, &ext, XmCACHE_EXTENSION);
906
907 _XmExtObjFree((XtPointer)ext->widget);
908 _XmExtObjFree((XtPointer)ext->reqWidget);
909
910 XtFree((char *)ext);
911
912 return False;
913 }
914
915 static Boolean
set_values(Widget old,Widget request,Widget new_w,ArgList args,Cardinal * num_args)916 set_values(Widget old, Widget request, Widget new_w,
917 ArgList args, Cardinal *num_args)
918 {
919 Boolean refresh_needed = False;
920 XGCValues gcv;
921
922 DEBUGOUT(_LtDebug(__FILE__, new_w, "ToggleBG set_values\n"));
923
924 if (TBG_IndType(old) != TBG_IndType(new_w) &&
925 !XmRepTypeValidValue(XmRepTypeGetId(XmRIndicatorType),
926 TBG_IndType(new_w), new_w))
927 TBG_IndType(new_w) = TBG_IndType(old);
928
929 if (TBG_ToggleMode(old) != TBG_ToggleMode(new_w) &&
930 !XmRepTypeValidValue(XmRepTypeGetId(XmRIndicatorType),
931 TBG_ToggleMode(new_w), new_w))
932 TBG_ToggleMode(new_w) = TBG_ToggleMode(old);
933
934
935 if (TBG_SelectColor(new_w) != TBG_SelectColor(old))
936 {
937 XtReleaseGC(new_w, TBG_SelectGC(new_w));
938 CreateSelectGC(new_w);
939 refresh_needed = True;
940 }
941 /* See bug #772755 : need to query the old widget's values */
942 XGetGCValues(XtDisplayOfObject(old), LabG_NormalGC(old), GCBackground, &gcv);
943 /*
944 if (XmParentBackground(new_w) != XmParentBackground(old))
945 */
946 if (XmParentBackground(new_w) != gcv.background) {
947 XtReleaseGC(new_w, TBG_BackgroundGC(new_w));
948 CreateBackgroundGC(new_w);
949 refresh_needed = True;
950 }
951
952 /* Changes to the on or off pixmap */
953 if (LabG_Pixmap(new_w) == XmUNSPECIFIED_PIXMAP &&
954 TBG_OnPixmap(new_w) != XmUNSPECIFIED_PIXMAP)
955 {
956 LabG_Pixmap(new_w) = TBG_OnPixmap(new_w);
957
958 if (LabG_IsPixmap(new_w) && XtSensitive(new_w))
959 refresh_needed = True;
960 }
961
962 if (LabG_PixmapInsensitive(new_w) == XmUNSPECIFIED_PIXMAP &&
963 TBG_InsenPixmap(new_w) != XmUNSPECIFIED_PIXMAP)
964 {
965 LabG_PixmapInsensitive(new_w) = TBG_InsenPixmap(new_w);
966
967 if (LabG_IsPixmap(new_w) && !XtSensitive(new_w))
968 refresh_needed = True;
969 }
970
971 if (LabG_IsPixmap(new_w) && (LabG_RecomputeSize(new_w) ||
972 TBG_IndeterminatePixmap(new_w) != XmUNSPECIFIED_PIXMAP ||
973 (XtSensitive(new_w)
974 ? LabG_Pixmap(request) != LabG_Pixmap(old) ||
975 TBG_OnPixmap(new_w) != TBG_OnPixmap(old)
976 : LabG_PixmapInsensitive(request) != LabG_PixmapInsensitive(old) ||
977 TBG_InsenPixmap(new_w) != TBG_InsenPixmap(old))))
978 {
979 Dimension width, height;
980 Dimension iwidth, iheight;
981
982 _XmLabelGetPixmapSize(new_w,
983 (XtSensitive(new_w)
984 ? TBG_OnPixmap(new_w)
985 : TBG_InsenPixmap(new_w)),
986 &width, &height);
987 _XmLabelGetPixmapSize(new_w, TBG_IndeterminatePixmap(new_w),
988 &iwidth, &iheight);
989 if (width < iwidth)
990 width = iwidth;
991 if (height < iheight)
992 height = iheight;
993
994 if (LabG_TextRect_width(new_w) < width ||
995 LabG_TextRect_height(new_w) < height)
996 {
997 if (LabG_TextRect_width(new_w) < width)
998 LabG_TextRect_width(new_w) = width;
999 if (LabG_TextRect_height(new_w) < height)
1000 LabG_TextRect_height(new_w) = height;
1001
1002 if (LabG_RecomputeSize(new_w))
1003 {
1004 if (XtWidth(request) == XtWidth(old))
1005 XtWidth(new_w) = 0;
1006 if (XtHeight(request) == XtHeight(old))
1007 XtHeight(new_w) = 0;
1008 }
1009 if (!XtWidth(request) || !XtWidth(new_w) ||
1010 !XtHeight(request) || !XtHeight(new_w))
1011 {
1012 if (!XtWidth(request))
1013 XtWidth(new_w) = 0;
1014 if (!XtHeight(request))
1015 XtHeight(new_w) = 0;
1016 xmToggleButtonGadgetClassRec.rect_class.resize(new_w);
1017 }
1018
1019 width = XtWidth(new_w);
1020 height = XtHeight(new_w);
1021 XtWidth(new_w) = XtWidth(old);
1022 XtHeight(new_w) = XtHeight(old);
1023 xmToggleButtonGadgetClassRec.rect_class.resize(new_w);
1024 XtWidth(new_w) = width;
1025 XtHeight(new_w) = height;
1026 }
1027 }
1028
1029 if (TBG_IndicatorDim(new_w) == XmINVALID_DIMENSION)
1030 TBG_IndicatorSet(new_w) = False;
1031
1032 if ((!TBG_IndicatorSet(new_w) &&
1033 (TBG_IndicatorDim(new_w) == XmINVALID_DIMENSION ||
1034 TBG_IndOn(new_w) != TBG_IndOn(old) ||
1035 LabG_Label(new_w) != LabG_Label(old) ||
1036 LabG_Font(new_w) != LabG_Font(old))) ||
1037 (TBG_IndicatorDim(new_w) == TBG_IndicatorDim(old)
1038 && LabG_IsPixmap(new_w)
1039 && LabG_TextRect_height(new_w) != LabG_TextRect_height(old)))
1040 {
1041 TBG_IndicatorDim(new_w) = implicit_indicator(new_w);
1042 }
1043
1044 if (LabG_IsPixmap(new_w))
1045 TBG_IndicatorSet(new_w) = True;
1046
1047 /* Adjust margins for the indicator size if necessary.
1048 * Margins be increased or decreased; if the margin was explicitly set
1049 * in this call, don't decrease it past that (though it can get bigger).
1050 */
1051 if (TBG_IndOn(new_w) &&
1052 (TBG_IndicatorDim(new_w) != TBG_IndicatorDim(old)
1053 || TBG_Spacing(new_w) != TBG_Spacing(old)
1054 || (!IN_MENU(new_w) && LabG_Shadow(new_w) != LabG_Shadow(old))
1055 || LabG_StringDirection(new_w) != LabG_StringDirection(old)
1056 || (LabG_StringDirection(new_w) == XmSTRING_DIRECTION_L_TO_R
1057 ? LabG_MarginLeft(new_w) != LabG_MarginLeft(old)
1058 : LabG_MarginRight(new_w) != LabG_MarginRight(old))
1059 || LabG_MarginTop(new_w) != LabG_MarginTop(old)
1060 || LabG_MarginBottom(new_w) != LabG_MarginBottom(old)))
1061 {
1062 int margin, tm;
1063
1064 margin = TBG_IndicatorDim(new_w) + TBG_Spacing(new_w)
1065 - (LabG_StringDirection(new_w) == XmSTRING_DIRECTION_L_TO_R
1066 ? LabG_MarginLeft(new_w) : LabG_MarginRight(new_w));
1067 if (margin && (margin > 0 ||
1068 (LabG_StringDirection(new_w) == XmSTRING_DIRECTION_L_TO_R
1069 ? LabG_MarginLeft(new_w) == LabG_MarginLeft(old)
1070 : LabG_MarginRight(new_w) == LabG_MarginRight(old))))
1071 {
1072 if (LabG_StringDirection(new_w) == XmSTRING_DIRECTION_L_TO_R)
1073 {
1074 LabG_MarginLeft(new_w) += margin;
1075 LabG_TextRect_x(new_w) += margin;
1076 LabG_AccTextRect(new_w).x += margin;
1077 }
1078 else
1079 LabG_MarginRight(new_w) += margin;
1080 if (LabG_RecomputeSize(new_w) || !XtWidth(request))
1081 XtWidth(new_w) += margin;
1082 }
1083
1084 margin = TBG_IndicatorDim(new_w) - (LabG_TextRect_height(new_w)
1085 + LabG_MarginTop(new_w)
1086 + LabG_MarginBottom(new_w));
1087 #ifdef LESS_VERTICAL_PADDING
1088 margin -= LabG_MarginHeight(new_w) << 1;
1089 #else
1090 if (!IN_MENU(new_w))
1091 margin += (LabG_Shadow(new_w) + Xm3D_ENHANCE_PIXEL) << 1;
1092 #endif
1093 if (margin)
1094 {
1095 margin /= 2;
1096 tm = margin;
1097 if (tm < (LabG_MarginTop(new_w) == LabG_MarginTop(old)
1098 ? XmDEFAULT_TOP_MARGIN - (int)LabG_MarginTop(new_w)
1099 : 0))
1100 tm = (LabG_MarginTop(new_w) == LabG_MarginTop(old)
1101 ? XmDEFAULT_TOP_MARGIN - (int)LabG_MarginTop(new_w)
1102 : 0);
1103 LabG_MarginTop(new_w) += tm;
1104 if (LabG_RecomputeSize(new_w) || !XtHeight(request))
1105 XtHeight(new_w) += tm;
1106
1107 if (margin < (LabG_MarginBottom(new_w) == LabG_MarginBottom(old)
1108 ? XmDEFAULT_BOTTOM_MARGIN - (int)LabG_MarginBottom(new_w)
1109 : 0))
1110 margin = (LabG_MarginBottom(new_w) == LabG_MarginBottom(old)
1111 ? XmDEFAULT_BOTTOM_MARGIN - (int)LabG_MarginBottom(new_w)
1112 : 0);
1113 LabG_MarginBottom(new_w) += margin;
1114 if (LabG_RecomputeSize(new_w) || !XtHeight(request))
1115 XtHeight(new_w) += margin;
1116
1117 if (tm != margin)
1118 {
1119 LabG_TextRect_y(new_w) += (tm - margin) / 2;
1120 LabG_AccTextRect(new_w).y += (tm - margin) / 2;
1121 }
1122 }
1123
1124 refresh_needed = True;
1125 }
1126
1127 if (TBG_IndType(new_w) != TBG_IndType(old)
1128 || TBG_DetailShadowThickness(new_w) != TBG_DetailShadowThickness(old)
1129 || ((TBG_IndOn(new_w) || TBG_IndOn(old))
1130 && (TBG_Visible(new_w) != TBG_Visible(old)
1131 || TBG_FillOnSelect(new_w) != TBG_FillOnSelect(old))))
1132 {
1133 refresh_needed = True;
1134 }
1135
1136 if (TBG_Set(old) != TBG_Set(new_w))
1137 {
1138 if (!refresh_needed)
1139 draw_toggle(new_w, NULL, NULL, False, TBG_Set(new_w));
1140 else if ((TBG_Set(old) == XmINDETERMINATE ||
1141 TBG_Set(new_w) == XmINDETERMINATE)
1142 && TBG_SelectColor(new_w) == TBG_SelectColor(old))
1143 {
1144 XtReleaseGC(new_w, TBG_SelectGC(new_w));
1145 CreateSelectGC(new_w);
1146 }
1147 TBG_VisualSet(new_w) = TBG_Set(new_w);
1148 }
1149
1150 return refresh_needed;
1151 }
1152
1153 static void
get_values_prehook(Widget new_w,ArgList args,Cardinal * num_args)1154 get_values_prehook(Widget new_w, ArgList args, Cardinal *num_args)
1155 {
1156 XmBaseClassExt *bce;
1157 XmWidgetExtData ed;
1158 Cardinal size;
1159 XtPointer nsec;
1160
1161 bce = _XmGetBaseClassExtPtr(XtClass(new_w), XmQmotif);
1162 size = (*bce)->secondaryObjectClass->core_class.widget_size;
1163
1164 nsec = _XmExtObjAlloc(size);
1165
1166 memcpy(&((XmLabelGCacheObject)nsec)->label_cache,
1167 LabG_Cache(new_w),
1168 sizeof(XmLabelGCacheObjPart));
1169 memcpy(&((XmToggleButtonGCacheObject)nsec)->toggle_cache,
1170 TBG_Cache(new_w),
1171 sizeof(XmToggleButtonGCacheObjPart));
1172
1173 /*
1174 * don't do this and ResInd will blow up.
1175 */
1176 ((XmExtRec *)nsec)->object.self = (Widget)nsec;
1177 ((XmExtRec *)nsec)->object.widget_class = (*bce)->secondaryObjectClass;
1178 ((XmExtRec *)nsec)->object.parent = XtParent(new_w);
1179 ((XmExtRec *)nsec)->object.xrm_name = new_w->core.xrm_name;
1180 ((XmExtRec *)nsec)->object.being_destroyed = False;
1181 ((XmExtRec *)nsec)->object.destroy_callbacks = NULL;
1182 ((XmExtRec *)nsec)->object.constraints = NULL;
1183
1184 ExtObj_LogicalParent(nsec) = new_w;
1185 ExtObj_ExtensionType(nsec) = XmCACHE_EXTENSION;
1186
1187 ed = (XmWidgetExtData)XtMalloc(sizeof(XmWidgetExtDataRec));
1188 ed->widget = (Widget)nsec;
1189
1190 _XmPushWidgetExtData(new_w, ed, XmCACHE_EXTENSION);
1191
1192 XtGetSubvalues((XtPointer)nsec,
1193 (*bce)->secondaryObjectClass->core_class.resources,
1194 (*bce)->secondaryObjectClass->core_class.num_resources,
1195 args, *num_args);
1196
1197 _XmExtGetValuesHook((Widget)nsec, args, num_args);
1198 }
1199
1200 static void
get_values_posthook(Widget new_w,ArgList args,Cardinal * num_args)1201 get_values_posthook(Widget new_w, ArgList args, Cardinal *num_args)
1202 {
1203 XmWidgetExtData ext;
1204
1205 _XmPopWidgetExtData(new_w, &ext, XmCACHE_EXTENSION);
1206
1207 _XmExtObjFree((XtPointer)ext->widget);
1208
1209 XtFree((char *)ext);
1210 }
1211
1212 static void
resize(Widget w)1213 resize(Widget w)
1214 {
1215 Position x;
1216
1217 xmLabelGadgetClassRec.rect_class.resize(w);
1218
1219 /* Make sure the label and toggle don't overlap */
1220
1221 if (TBG_IndOn(w))
1222 {
1223 if (LabG_StringDirection(w) == XmSTRING_DIRECTION_L_TO_R)
1224 {
1225 x = LabG_Highlight(w) + LabG_Shadow(w) + LabG_MarginWidth(w)
1226 + TBG_IndicatorDim(w) + TBG_Spacing(w);
1227 if (LabG_TextRect_x(w) < x)
1228 {
1229 LabG_AccTextRect(w).x += x - LabG_TextRect_x(w);
1230 LabG_TextRect_x(w) = x;
1231 }
1232 }
1233 else
1234 {
1235 x = XtWidth(w) - LabG_Highlight(w) - LabG_Shadow(w)
1236 - LabG_MarginWidth(w) - TBG_IndicatorDim(w) - TBG_Spacing(w)
1237 - LabG_TextRect_width(w);
1238 if (LabG_TextRect_x(w) > x)
1239 {
1240 LabG_AccTextRect(w).x -= LabG_TextRect_x(w) - x;
1241 LabG_TextRect_x(w) = x;
1242 }
1243 }
1244 }
1245 }
1246
1247 static void
expose(Widget w,XEvent * event,Region region)1248 expose(Widget w, XEvent *event, Region region)
1249 {
1250 DEBUGOUT(_LtDebug(__FILE__, w, "ToggleBG Expose\n"));
1251 draw_toggle(w, event, region, True, 0);
1252 }
1253
1254 static Cardinal
get_sec_res_data(WidgetClass wc,XmSecondaryResourceData ** data)1255 get_sec_res_data(WidgetClass wc, XmSecondaryResourceData **data)
1256 {
1257 /* FIX ME */
1258
1259 return _XmSecondaryResourceData(&_XmToggleBGRectClassExtRec,
1260 data, NULL, NULL, NULL, NULL);
1261 }
1262
1263 static void
Arm(Widget w,XEvent * event,String * params,Cardinal * num_params)1264 Arm(Widget w, XEvent *event, String *params, Cardinal *num_params)
1265 {
1266 XmToggleButtonCallbackStruct cbs;
1267
1268 if (!TBG_Armed(w))
1269 {
1270 TBG_Armed(w) = True;
1271 MGR_ActiveChild(XtParent(w)) = w;
1272
1273 if (TBG_ArmCallback(w))
1274 {
1275 cbs.reason = XmCR_ARM;
1276 cbs.event = event;
1277 cbs.set = TBG_Set(w);
1278
1279 XFlush(XtDisplay(w));
1280 XtCallCallbackList(w, TBG_ArmCallback(w), (XtPointer)&cbs);
1281 }
1282 }
1283 draw_toggle(w, NULL, NULL, False, NEXT_TOGGLE(w));
1284 }
1285
1286 static void
Select(Widget w,XEvent * event,String * params,Cardinal * num_params)1287 Select(Widget w, XEvent *event, String *params, Cardinal *num_params)
1288 {
1289 XmToggleButtonCallbackStruct cbs;
1290 XButtonEvent *ev = (XButtonEvent *)event;
1291
1292 if (TBG_Armed(w) &&
1293 (ev->type == KeyPress || ev->type == KeyRelease ||
1294 ((ev->x >= XtX(w) && ev->x < XtX(w) + XtWidth(w)) &&
1295 (ev->y >= XtY(w) && ev->y < XtY(w) + XtHeight(w)))))
1296 {
1297 TBG_Armed(w) = False;
1298
1299 TBG_Set(w) = TBG_VisualSet(w);
1300
1301 if (XtIsRealized(w))
1302 XtClass(w)->core_class.expose(w, event, NULL);
1303
1304 cbs.reason = XmCR_VALUE_CHANGED;
1305 cbs.event = event;
1306 cbs.set = TBG_Set(w);
1307 if (XmIsRowColumn(XtParent(w)))
1308 {
1309 RC_MenuMenuCallback(w, &cbs);
1310 }
1311 /* Menu callback might cancel the set (radioAlwaysOne). */
1312 cbs.set = TBG_Set(w);
1313 if (!LabG_SkipCallback(w) && TBG_ValueChangedCallback(w))
1314 {
1315 XFlush(XtDisplay(w));
1316 XtCallCallbackList(w,
1317 TBG_ValueChangedCallback(w),
1318 (XtPointer)&cbs);
1319 }
1320 }
1321 }
1322
1323
1324 static void
Disarm(Widget w,XEvent * event,String * params,Cardinal * num_params)1325 Disarm(Widget w, XEvent *event, String *params, Cardinal *num_params)
1326 {
1327 XmToggleButtonCallbackStruct cbs;
1328
1329 if (XtIsRealized(w))
1330 _XmClearBorder(XtDisplay(w), XtWindow(w),
1331 XtX(w), XtY(w), XtWidth(w), XtHeight(w),
1332 LabG_Shadow(w));
1333
1334 if (TBG_Armed(w))
1335 TBG_Armed(w) = False;
1336
1337 if (TBG_DisarmCallback(w))
1338 {
1339 cbs.reason = XmCR_DISARM;
1340 cbs.event = event;
1341 cbs.set = TBG_Set(w);
1342
1343 XFlush(XtDisplay(w));
1344 XtCallCallbackList(w, TBG_DisarmCallback(w), (XtPointer)&cbs);
1345 }
1346
1347 draw_toggle(w, NULL, NULL, False, TBG_Set(w));
1348 }
1349
1350 static void
ArmAndActivate(Widget w,XEvent * event,String * params,Cardinal * num_params)1351 ArmAndActivate(Widget w, XEvent *event, String *params, Cardinal *num_params)
1352 {
1353 Boolean poppedUp;
1354
1355 Arm(w, event, params, num_params);
1356
1357 if (IN_MENU(w))
1358 {
1359 RC_MenuButtonPopdown(w, event, &poppedUp);
1360 }
1361
1362 Select(w, event, params, num_params);
1363 Disarm(w, event, params, num_params);
1364 }
1365
1366 static void
ButtonUp(Widget w,XEvent * event,String * params,Cardinal * num_params)1367 ButtonUp(Widget w, XEvent *event, String *params, Cardinal *num_params)
1368 {
1369 Boolean validButton, poppedUp;
1370 XmToggleButtonCallbackStruct cbs;
1371
1372 XAllowEvents(XtDisplayOfObject(w), SyncPointer, CurrentTime);
1373
1374 if (event && (event->type == ButtonRelease))
1375 {
1376 RC_MenuButton(w, event, &validButton);
1377 }
1378 else
1379 {
1380 validButton = False;
1381 }
1382
1383 if (!validButton)
1384 {
1385 return;
1386 }
1387
1388 if (!TBG_Armed(w))
1389 {
1390 return;
1391 }
1392
1393 RC_MenuButtonPopdown(w, event, &poppedUp);
1394
1395 _XmRecordEvent(event);
1396
1397 TBG_Armed(w) = False;
1398
1399 if (XtIsRealized(w))
1400 _XmClearBorder(XtDisplay(w), XtWindow(w),
1401 XtX(w), XtY(w), XtWidth(w), XtHeight(w),
1402 LabG_Shadow(w));
1403
1404 TBG_Set(w) = NEXT_TOGGLE(w);
1405 draw_toggle(w, NULL, NULL, False, TBG_Set(w));
1406
1407 cbs.reason = XmCR_VALUE_CHANGED;
1408 cbs.event = event;
1409 cbs.set = TBG_Set(w);
1410 if (XmIsRowColumn(XtParent(w)))
1411 {
1412 RC_MenuMenuCallback(w, &cbs);
1413 }
1414 if (!LabG_SkipCallback(w) && TBG_ValueChangedCallback(w))
1415 {
1416 XFlush(XtDisplay(w));
1417 XtCallCallbackList(w, TBG_ValueChangedCallback(w), (XtPointer)&cbs);
1418 }
1419 if (TBG_DisarmCallback(w))
1420 {
1421 cbs.reason = XmCR_DISARM;
1422 cbs.event = event;
1423 cbs.set = TBG_Set(w);
1424
1425 XFlush(XtDisplay(w));
1426 XtCallCallbackList(w, TBG_DisarmCallback(w), (XtPointer)&cbs);
1427 }
1428
1429 _XmSetInDragMode(w, False);
1430 }
1431
1432
1433 static void
ButtonDown(Widget w,XEvent * event,String * params,Cardinal * num_params)1434 ButtonDown(Widget w, XEvent *event, String *params, Cardinal *num_params)
1435 {
1436 int validButton;
1437 XmToggleButtonCallbackStruct cbs;
1438
1439 XAllowEvents(XtDisplayOfObject(w), SyncPointer, CurrentTime);
1440
1441 if (event && (event->type == ButtonPress))
1442 {
1443 RC_MenuButton(w, event, &validButton);
1444 if (!validButton)
1445 return;
1446 }
1447
1448 _XmSetInDragMode(w, True);
1449
1450 {
1451 Boolean poppedUp;
1452
1453 RC_MenuShellPopdown(w, event, &poppedUp);
1454 }
1455 {
1456 Cardinal i;
1457 Widget menu = XtParent(w);
1458
1459 for (i = 0; i < MGR_NumChildren(menu); i++)
1460 {
1461 Widget w1 = MGR_Children(menu)[i];
1462
1463 if (w1 && (w1 != w))
1464 {
1465 _XmMenuDisarmItem(w1);
1466 }
1467 }
1468 }
1469
1470 if (!TBG_Armed(w))
1471 {
1472 TBG_Armed(w) = True;
1473
1474 if (XtIsRealized(w))
1475 _XmDrawShadows(XtDisplay(w), XtWindow(w),
1476 XmParentTopShadowGC(w), XmParentBottomShadowGC(w),
1477 XtX(w), XtY(w), XtWidth(w), XtHeight(w),
1478 LabG_Shadow(w), XmSHADOW_OUT);
1479
1480 if (TBG_ArmCallback(w))
1481 {
1482 cbs.reason = XmCR_ARM;
1483 cbs.event = event;
1484 cbs.set = TBG_Set(w);
1485
1486 XFlush(XtDisplay(w));
1487 XtCallCallbackList(w, TBG_ArmCallback(w), (XtPointer)&cbs);
1488 }
1489 }
1490
1491 _XmRecordEvent(event);
1492 }
1493
1494 static void
Help(Widget w,XEvent * event,String * params,Cardinal * num_params)1495 Help(Widget w, XEvent *event, String *params, Cardinal *num_params)
1496 {
1497 Widget cur = w;
1498 XmAnyCallbackStruct cbs;
1499
1500 cbs.reason = XmCR_HELP;
1501 cbs.event = event;
1502
1503 while (cur != NULL)
1504 {
1505 if (XtHasCallbacks(w, XmNhelpCallback) == XtCallbackHasSome)
1506 {
1507 XtCallCallbacks(w, XmNhelpCallback, (XtPointer)&cbs);
1508 return;
1509 }
1510 cur = XtParent(cur);
1511 }
1512 }
1513
1514 static void
EnterWindow(Widget w,XEvent * event,String * params,Cardinal * num_params)1515 EnterWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
1516 {
1517 XmToggleButtonCallbackStruct cbs;
1518
1519 if (!IN_MENU(w))
1520 {
1521 _XmEnterGadget(w, event, NULL, NULL);
1522 if (TBG_Armed(w))
1523 draw_toggle(w, NULL, NULL, False, NEXT_TOGGLE(w));
1524 }
1525 else
1526 {
1527 if (_XmGetInDragMode(w))
1528 {
1529 Boolean poppedUp;
1530
1531 RC_MenuShellPopdown(w, event, &poppedUp);
1532
1533 TBG_Armed(w) = True;
1534
1535 if (XtIsRealized(w))
1536 _XmDrawShadows(XtDisplay(w), XtWindow(w),
1537 XmParentTopShadowGC(w),
1538 XmParentBottomShadowGC(w),
1539 XtX(w), XtY(w), XtWidth(w), XtHeight(w),
1540 LabG_Shadow(w), XmSHADOW_OUT);
1541
1542 if (TBG_ArmCallback(w))
1543 {
1544 cbs.reason = XmCR_ARM;
1545 cbs.event = event;
1546 cbs.set = TBG_Set(w);
1547
1548 XFlush(XtDisplay(w));
1549 XtCallCallbackList(w, TBG_ArmCallback(w), (XtPointer)&cbs);
1550 }
1551 }
1552 }
1553 }
1554
1555 static void
LeaveWindow(Widget w,XEvent * event,String * params,Cardinal * num_params)1556 LeaveWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
1557 {
1558 XmToggleButtonCallbackStruct cbs;
1559
1560 if (!IN_MENU(w))
1561 {
1562 _XmLeaveGadget(w, event, NULL, NULL);
1563 if (TBG_Armed(w))
1564 draw_toggle(w, NULL, NULL, False, TBG_Set(w));
1565 }
1566 else
1567 {
1568 if (_XmGetInDragMode(w))
1569 {
1570 TBG_Armed(w) = False;
1571
1572 if (XtIsRealized(w))
1573 _XmClearBorder(XtDisplay(w), XtWindow(w),
1574 XtX(w), XtY(w), XtWidth(w), XtHeight(w),
1575 LabG_Shadow(w));
1576
1577 if (TBG_DisarmCallback(w))
1578 {
1579 cbs.reason = XmCR_DISARM;
1580 cbs.event = event;
1581 cbs.set = TBG_Set(w);
1582
1583 XFlush(XtDisplay(w));
1584 XtCallCallbackList(w, TBG_DisarmCallback(w), (XtPointer)&cbs);
1585 }
1586 }
1587 }
1588 }
1589
1590 static void
input_dispatch(Widget gadget,XEvent * event,Mask event_mask)1591 input_dispatch(Widget gadget, XEvent *event, Mask event_mask)
1592 {
1593 Cardinal num_params = 0;
1594
1595 switch (event_mask)
1596 {
1597 case XmARM_EVENT:
1598 case XmMULTI_ARM_EVENT:
1599 DEBUGOUT(_LtDebug(__FILE__, gadget,
1600 "ToggleButtonGadget got arm event\n"));
1601 if (IN_MENU(gadget))
1602 {
1603 ButtonDown(gadget, event, NULL, &num_params);
1604 }
1605 else
1606 {
1607 Arm(gadget, event, NULL, &num_params);
1608 }
1609 break;
1610
1611 case XmACTIVATE_EVENT:
1612 case XmMULTI_ACTIVATE_EVENT:
1613 DEBUGOUT(_LtDebug(__FILE__, gadget,
1614 "ToggleButtonGadget got activate event\n"));
1615 if (IN_MENU(gadget))
1616 {
1617 ButtonUp(gadget, event, NULL, &num_params);
1618 }
1619 else
1620 {
1621 Select(gadget, event, NULL, &num_params);
1622 Disarm(gadget, event, NULL, &num_params);
1623 }
1624 break;
1625
1626 case XmENTER_EVENT:
1627 DEBUGOUT(_LtDebug(__FILE__, gadget,
1628 "ToggleButtonGadget enter window\n"));
1629 EnterWindow(gadget, event, NULL, &num_params);
1630 break;
1631
1632 case XmLEAVE_EVENT:
1633 DEBUGOUT(_LtDebug(__FILE__, gadget,
1634 "ToggleButtonGadget leave window\n"));
1635 LeaveWindow(gadget, event, NULL, &num_params);
1636 break;
1637
1638 case XmMOTION_EVENT:
1639 DEBUGOUT(_LtDebug(__FILE__, gadget,
1640 "ToggleButtonGadget motion event\n"));
1641 break;
1642
1643 case XmFOCUS_IN_EVENT:
1644 _XmFocusInGadget(gadget, event, NULL, &num_params);
1645 break;
1646
1647 case XmFOCUS_OUT_EVENT:
1648 _XmFocusOutGadget(gadget, event, NULL, &num_params);
1649 break;
1650
1651 case XmHELP_EVENT:
1652 Help(gadget, event, NULL, &num_params);
1653 break;
1654
1655 case XmBDRAG_EVENT:
1656 _XmProcessDrag(gadget, event, NULL, NULL);
1657 break;
1658
1659 default:
1660 _XmWarning(gadget, "ToggleButtonGadget got unknown event\n");
1661 }
1662 }
1663
1664 static void
MenuProcEntry(int proc,Widget w,...)1665 MenuProcEntry(int proc, Widget w,...)
1666 {
1667 va_list arg_list;
1668 /*
1669 Cardinal num_params = 0;
1670 */
1671
1672 va_start(arg_list, w);
1673
1674 switch (proc)
1675 {
1676 case XmMENU_ARM:
1677 {
1678 Boolean poppedUp;
1679
1680 if (!TBG_Armed(w))
1681 {
1682 RC_MenuShellPopdown(w, NULL, &poppedUp);
1683
1684 TBG_Armed(w) = True;
1685
1686 if (XtIsRealized(w))
1687 _XmDrawShadows(XtDisplay(w), XtWindow(w),
1688 XmParentTopShadowGC(w),
1689 XmParentBottomShadowGC(w),
1690 XtX(w), XtY(w), XtWidth(w), XtHeight(w),
1691 LabG_Shadow(w), XmSHADOW_OUT);
1692
1693 MGR_ActiveChild(XtParent(w)) = w;
1694 if (TBG_ArmCallback(w))
1695 {
1696 XmToggleButtonCallbackStruct cbs;
1697
1698 cbs.reason = XmCR_ARM;
1699 cbs.event = NULL;
1700 cbs.set = TBG_Set(w);
1701
1702 XFlush(XtDisplay(w));
1703 XtCallCallbackList(w, TBG_ArmCallback(w), (XtPointer)&cbs);
1704 }
1705 }
1706 }
1707 break;
1708 case XmMENU_DISARM:
1709 {
1710 if (TBG_Armed(w))
1711 {
1712 TBG_Armed(w) = False;
1713
1714 if (XtIsRealized(w))
1715 _XmClearBorder(XtDisplay(w), XtWindow(w),
1716 XtX(w), XtY(w), XtWidth(w), XtHeight(w),
1717 LabG_Shadow(w));
1718
1719 MGR_ActiveChild(XtParent(w)) = w;
1720 if (TBG_DisarmCallback(w))
1721 {
1722 XmToggleButtonCallbackStruct cbs;
1723
1724 cbs.reason = XmCR_DISARM;
1725 cbs.event = NULL;
1726 cbs.set = TBG_Set(w);
1727
1728 XFlush(XtDisplay(w));
1729 XtCallCallbackList(w, TBG_DisarmCallback(w), (XtPointer)&cbs);
1730 }
1731 }
1732 }
1733 break;
1734 default:
1735 _XmWarning(w, "%s(%d) - Invalid menuProc function", __FILE__, __LINE__);
1736 break;
1737 }
1738
1739 va_end(arg_list);
1740 }
1741
1742 /* This may be called from expose, in which case everything is drawn,
1743 * but there's generally no reason to erase anything;
1744 * or it could be called by an action or such, in which case the only
1745 * things drawn are what got changed by toggling, but things may be
1746 * erased as well.
1747 */
1748
1749 static void
draw_toggle(Widget w,XEvent * event,Region region,int is_expose,int visual_set)1750 draw_toggle(Widget w, XEvent *event, Region region, int is_expose,
1751 int visual_set)
1752 {
1753 Dimension dim, delta, fill;
1754 Position x, y;
1755 Pixmap tmp_pix = XmUNSPECIFIED_PIXMAP;
1756
1757 if (is_expose)
1758 {
1759 /* Called from expose: get visual_set and draw everything */
1760 visual_set = TBG_VisualSet(w);
1761 }
1762 else
1763 {
1764 /* Called from an action: set visual_set and draw some stuff */
1765 if (TBG_VisualSet(w) == visual_set)
1766 return;
1767 if (TBG_VisualSet(w) == XmINDETERMINATE ||
1768 visual_set == XmINDETERMINATE)
1769 {
1770 /* FIX ME: Change the GC for a toggle? That's ridiculous!
1771 * Yet it seems necessary - there's no field available
1772 * for an indeterminateGC. - JHG
1773 */
1774 XtReleaseGC(w, TBG_SelectGC(w));
1775 TBG_VisualSet(w) = visual_set;
1776 CreateSelectGC(w);
1777 } else {
1778 TBG_VisualSet(w) = visual_set;
1779 }
1780 if (!XtIsRealized(w))
1781 return;
1782 }
1783
1784 /* Fill in the widget only if toggling the background */
1785 if (LabG_IsText(w) && !TBG_IndOn(w) && TBG_FillOnSelect(w))
1786 {
1787 XFillRectangle(XtDisplay(w), XtWindow(w),
1788 visual_set ? TBG_SelectGC(w) : TBG_BackgroundGC(w),
1789 XtX(w) + LabG_Highlight(w) + LabG_Shadow(w),
1790 XtY(w) + LabG_Highlight(w) + LabG_Shadow(w),
1791 XtWidth(w) - ((LabG_Highlight(w) + LabG_Shadow(w)) << 1),
1792 XtHeight(w) - ((LabG_Highlight(w) + LabG_Shadow(w)) << 1));
1793 }
1794
1795 if (is_expose || (!TBG_IndOn(w) && TBG_FillOnSelect(w)) ||
1796 (LabG_IsPixmap(w) && (
1797 TBG_IndeterminatePixmap(w) != XmUNSPECIFIED_PIXMAP ||
1798 (XtSensitive(w) ? TBG_OnPixmap(w) :
1799 TBG_InsenPixmap(w)) != XmUNSPECIFIED_PIXMAP)))
1800 {
1801 if (LabG_IsPixmap(w))
1802 {
1803 if (visual_set)
1804 {
1805 /* Switch pixmaps before drawing label */
1806 if (XtSensitive(w))
1807 {
1808 if (visual_set == XmINDETERMINATE &&
1809 TBG_IndeterminatePixmap(w) != XmUNSPECIFIED_PIXMAP) {
1810 tmp_pix = LabG_Pixmap(w);
1811 LabG_Pixmap(w) = TBG_IndeterminatePixmap(w);
1812 } else if (TBG_OnPixmap(w) != XmUNSPECIFIED_PIXMAP) {
1813 tmp_pix = LabG_Pixmap(w);
1814 LabG_Pixmap(w) = TBG_OnPixmap(w);
1815 }
1816 } else {
1817 if (visual_set == XmINDETERMINATE &&
1818 TBG_IndeterminatePixmap(w) != XmUNSPECIFIED_PIXMAP) {
1819 tmp_pix = LabG_Pixmap(w);
1820 LabG_Pixmap(w) = TBG_IndeterminatePixmap(w);
1821 } else if (TBG_InsenPixmap(w) != XmUNSPECIFIED_PIXMAP)
1822 {
1823 tmp_pix = LabG_PixmapInsensitive(w);
1824 LabG_PixmapInsensitive(w) = TBG_InsenPixmap(w);
1825 }
1826 }
1827 }
1828 if (!is_expose && (TBG_IndOn(w) || !TBG_FillOnSelect(w))) {
1829 XRectangle cliprect;
1830
1831 /* Changing pixmaps: erase the TextRect just in case
1832 * they're different sizes. Take a bit of trouble here
1833 * to avoid excess drawing, which causes more work later.
1834 * Based on similar work in Label's expose.
1835 */
1836 cliprect.x =
1837 LabG_Highlight(w) + LabG_Shadow(w) + LabG_MarginLeft(w);
1838 cliprect.y =
1839 LabG_Highlight(w) + LabG_Shadow(w) + LabG_MarginTop(w);
1840 cliprect.width = XtWidth(w)
1841 - ((LabG_Shadow(w) + LabG_Highlight(w)) << 1)
1842 - LabG_MarginLeft(w) - LabG_MarginRight(w);
1843 cliprect.height = XtHeight(w)
1844 - ((LabG_Shadow(w) + LabG_Highlight(w)) << 1)
1845 - LabG_MarginTop(w) - LabG_MarginBottom(w);
1846 if (cliprect.x + cliprect.width > LabG_TextRect_x(w) &&
1847 cliprect.x < LabG_TextRect_x(w) + LabG_TextRect_width(w) &&
1848 cliprect.y + cliprect.height > LabG_TextRect_y(w) &&
1849 cliprect.y < LabG_TextRect_y(w) + LabG_TextRect_height(w))
1850 {
1851 if (cliprect.x < LabG_TextRect_x(w))
1852 {
1853 cliprect.width -= LabG_TextRect_x(w) - cliprect.x;
1854 cliprect.x = LabG_TextRect_x(w);
1855 }
1856 if (cliprect.x + cliprect.width >
1857 LabG_TextRect_x(w) + LabG_TextRect_width(w))
1858 {
1859 cliprect.width = (LabG_TextRect_x(w)
1860 + LabG_TextRect_width(w)) - cliprect.x;
1861 }
1862 if (cliprect.y < LabG_TextRect_y(w))
1863 {
1864 cliprect.height -= LabG_TextRect_y(w) - cliprect.y;
1865 cliprect.y = LabG_TextRect_y(w);
1866 }
1867 if (cliprect.y + cliprect.height >
1868 LabG_TextRect_y(w) + LabG_TextRect_height(w))
1869 {
1870 cliprect.height = (LabG_TextRect_y(w)
1871 + LabG_TextRect_height(w)) - cliprect.y;
1872 }
1873 XFillRectangle(XtDisplay(w), XtWindow(w),
1874 TBG_BackgroundGC(w),
1875 XtX(w) + cliprect.x,
1876 XtY(w) + cliprect.y,
1877 cliprect.width, cliprect.height);
1878 }
1879 }
1880 }
1881 #define superclass (&xmLabelGadgetClassRec)
1882 (*superclass->rect_class.expose) (w, event, region);
1883 #undef superclass
1884 if (LabG_IsPixmap(w) && visual_set)
1885 {
1886 /* Switch pixmaps back after drawing label */
1887 if (tmp_pix != XmUNSPECIFIED_PIXMAP)
1888 {
1889 if (XtSensitive(w))
1890 {
1891 LabG_Pixmap(w) = tmp_pix;
1892 }
1893 else
1894 {
1895 LabG_PixmapInsensitive(w) = tmp_pix;
1896 }
1897 }
1898 }
1899 }
1900
1901 if (IN_MENU(w))
1902 {
1903 if (is_expose)
1904 {
1905 /* Exposing in a menu: draw or erase shadows */
1906 if (TBG_Armed(w))
1907 {
1908 _XmDrawShadows(XtDisplay(w), XtWindow(w),
1909 XmParentTopShadowGC(w),
1910 XmParentBottomShadowGC(w),
1911 XtX(w), XtY(w), XtWidth(w), XtHeight(w),
1912 LabG_Shadow(w), XmSHADOW_OUT);
1913 }
1914 else
1915 {
1916 _XmClearBorder(XtDisplay(w), XtWindow(w),
1917 XtX(w), XtY(w), XtWidth(w), XtHeight(w),
1918 LabG_Shadow(w));
1919 }
1920 }
1921 }
1922 else
1923 {
1924 if (is_expose || !TBG_IndOn(w))
1925 {
1926 /* Non-menu: draw shadows in or out */
1927 _XmDrawShadows(XtDisplay(w), XtWindow(w),
1928 visual_set == XmINDETERMINATE
1929 ? LabG_InsensitiveGC(w)
1930 : XmParentTopShadowGC(w),
1931 visual_set == XmINDETERMINATE
1932 ? LabG_InsensitiveGC(w)
1933 : XmParentBottomShadowGC(w),
1934 XtX(w) + LabG_Highlight(w),
1935 XtY(w) + LabG_Highlight(w),
1936 XtWidth(w) - (LabG_Highlight(w) << 1),
1937 XtHeight(w) - (LabG_Highlight(w) << 1),
1938 LabG_Shadow(w), visual_set && !TBG_IndOn(w)
1939 ? XmSHADOW_IN : XmSHADOW_OUT);
1940 }
1941 }
1942
1943 if (TBG_IndOn(w) && (visual_set || !is_expose || TBG_Visible(w)))
1944 {
1945 /* Draw (or erase) the indicator */
1946
1947 x = XtX(w) + LabG_Highlight(w) + LabG_Shadow(w) + LabG_MarginWidth(w);
1948 dim = TBG_IndicatorDim(w);
1949
1950 if (TBG_IndicatorSet(w) || !LabG_TextRect_height(w))
1951 {
1952 /* Center indicator on label */
1953 y = (LabG_MarginTop(w) << 1) + XtHeight(w)
1954 - LabG_MarginTop(w) - LabG_MarginBottom(w) - dim;
1955 }
1956 else
1957 {
1958 /* Make sure implicit indicator isn't too big to fit.
1959 * Align it with top line of text.
1960 */
1961 y = LabG_TextRect_y(w) << 1;
1962 if (IN_MENU(w))
1963 {
1964 /* For the smaller menu indicators.
1965 * The "true" formula is (fullsize - smaller) / 2,
1966 * but that would require the _XmString calls every time.
1967 * This formula is much quicker and usually correct,
1968 * with only 1 pixel rounded up 1/6 of the time.
1969 * You see, I couldn't sleep, and had nothing better to do...
1970 */
1971 y += (dim + 1) >> 1;
1972 }
1973 if (dim > XtHeight(w) -
1974 ((LabG_Highlight(w) + LabG_Shadow(w) + LabG_MarginHeight(w))
1975 >> 1) - LabG_MarginTop(w) - LabG_MarginBottom(w))
1976 dim = XtHeight(w) - ((LabG_Highlight(w) + LabG_Shadow(w)
1977 + LabG_MarginHeight(w)) >> 1)
1978 - LabG_MarginTop(w) - LabG_MarginBottom(w);
1979 }
1980
1981 /* Monochrome displays (or anything with the select color the same
1982 * as a shadow) get inset by one pixel to make things easier to see.
1983 */
1984 fill = XmParentTopShadowColor(w) != TBG_SelectColor(w) &&
1985 XmParentBottomShadowColor(w) != TBG_SelectColor(w);
1986
1987 if (TBG_IndType(w) == XmN_OF_MANY)
1988 {
1989 /* Make square indicators a bit smaller then they really are */
1990 delta = dim <= SQUARE_INDICATOR_DEC + Xm3D_ENHANCE_PIXEL
1991 ? dim >> 1
1992 : SQUARE_INDICATOR_DEC +
1993 (dim >= SQUARE_INDICATOR_ELBOW << 1
1994 ? (dim - SQUARE_INDICATOR_ELBOW) / SQUARE_INDICATOR_ELBOW
1995 : 0);
1996 x += delta >> 1;
1997 y += delta;
1998 dim -= delta;
1999 }
2000 y = XtY(w) + (y >> 1);
2001
2002 if (LabG_StringDirection(w) == XmSTRING_DIRECTION_R_TO_L)
2003 x = XtWidth(w) - x - dim;
2004
2005 switch (TBG_IndType(w))
2006 {
2007 case XmN_OF_MANY:
2008 if (visual_set || TBG_Visible(w))
2009 {
2010 if (TBG_IndOn(w) & INDICATOR_BOX_MASK)
2011 {
2012 _XmDrawShadows(XtDisplay(w), XtWindow(w),
2013 visual_set == XmINDETERMINATE
2014 ? LabG_InsensitiveGC(w)
2015 : (TBG_IndOn(w) & INDICATOR_BOX_MASK)
2016 == XmINDICATOR_FLAT_BOX
2017 ? XmParentBottomShadowGC(w)
2018 : XmParentTopShadowGC(w),
2019 visual_set == XmINDETERMINATE
2020 ? LabG_InsensitiveGC(w)
2021 : XmParentBottomShadowGC(w),
2022 x, y, dim, dim, DETAIL_SHADOW_THICKNESS(w),
2023 visual_set ? XmSHADOW_IN : XmSHADOW_OUT);
2024 delta = DETAIL_SHADOW_THICKNESS(w) + (1 - fill);
2025 } else {
2026 delta = 0;
2027 }
2028 if (dim > delta << 1) {
2029 if (is_expose || TBG_FillOnSelect(w)) {
2030 XFillRectangle(XtDisplay(w), XtWindow(w),
2031 visual_set && TBG_FillOnSelect(w)
2032 ? TBG_SelectGC(w) : TBG_BackgroundGC(w),
2033 x + delta, y + delta,
2034 dim - (delta << 1), dim - (delta << 1));
2035 }
2036 if (visual_set == XmUNSET) {
2037 XFillRectangle(XtDisplayOfObject(w),
2038 XtWindowOfObject(w),
2039 TBG_UnselectGC(w),
2040 x, y, dim, dim);
2041
2042 _XmDrawShadows(XtDisplay(w), XtWindow(w),
2043 visual_set == XmINDETERMINATE
2044 ? LabG_InsensitiveGC(w)
2045 : (TBG_IndOn(w) & INDICATOR_BOX_MASK)
2046 == XmINDICATOR_FLAT_BOX
2047 ? XmParentBottomShadowGC(w)
2048 : XmParentTopShadowGC(w),
2049 visual_set == XmINDETERMINATE
2050 ? LabG_InsensitiveGC(w)
2051 : XmParentBottomShadowGC(w),
2052 x, y, dim, dim, DETAIL_SHADOW_THICKNESS(w),
2053 visual_set ? XmSHADOW_IN : XmSHADOW_OUT);
2054 }
2055 }
2056 } else {
2057 XFillRectangle(XtDisplay(w), XtWindow(w),
2058 TBG_BackgroundGC(w), x, y, dim, dim);
2059 }
2060 break;
2061
2062 case XmONE_OF_MANY_ROUND:
2063 XmeDrawCircle(XtDisplay(w), XtWindow(w),
2064 visual_set ? XmParentBottomShadowGC(w) : TBG_Visible(w)
2065 ? XmParentTopShadowGC(w) : TBG_BackgroundGC(w),
2066 visual_set ? XmParentTopShadowGC(w) : TBG_Visible(w)
2067 ? XmParentBottomShadowGC(w) : TBG_BackgroundGC(w),
2068 (is_expose || TBG_FillOnSelect(w))
2069 ? visual_set && TBG_FillOnSelect(w)
2070 ? TBG_SelectGC(w) : TBG_BackgroundGC(w) : NULL,
2071 x, y, dim, dim, TBG_DetailShadowThickness(w), 1);
2072 break;
2073
2074 default: /* XmONE_OF_MANY[_DIAMOND] */
2075 _XmDrawDiamond(XtDisplay(w), XtWindow(w),
2076 visual_set ? XmParentBottomShadowGC(w) :
2077 TBG_Visible(w) ? XmParentTopShadowGC(w) : TBG_BackgroundGC(w),
2078 visual_set ? XmParentTopShadowGC(w) :
2079 TBG_Visible(w) ? XmParentBottomShadowGC(w) : TBG_BackgroundGC(w),
2080 (is_expose || TBG_FillOnSelect(w))
2081 ? (visual_set && TBG_FillOnSelect(w))
2082 ? TBG_SelectGC(w)
2083 : TBG_UnselectGC(w)
2084 : NULL,
2085 x, y, dim, dim, DETAIL_SHADOW_THICKNESS(w),
2086 !fill);
2087 }
2088 }
2089 }
2090
2091 static int
implicit_indicator(Widget w)2092 implicit_indicator(Widget w)
2093 {
2094 int dim;
2095
2096 /* For a text button, the default indicator size is the height of
2097 * the first line of text. For a pixmap, it's related to the pixmap
2098 * height. For small pixmaps, just make it the same size.
2099 * Why 13 for size & slope? You got me. -- JHG
2100 */
2101
2102 if (LabG_IsText(w))
2103 {
2104 dim = _XmStringHeight(LabG_Font(w), LabG_Label(w))
2105 / _XmStringLineCount(LabG_Label(w));
2106 if (IN_MENU(w))
2107 {
2108 /* Menu indicators are a bit smaller */
2109 dim = (dim << 1) / 3;
2110 }
2111 if (dim < XmDEFAULT_INDICATOR_DIM)
2112 dim = XmDEFAULT_INDICATOR_DIM;
2113 return dim;
2114 }
2115 else
2116 {
2117 return LabG_TextRect_height(w) < PIXMAP_INDICATOR_ELBOW
2118 ? LabG_TextRect_height(w)
2119 : PIXMAP_INDICATOR_ELBOW +
2120 LabG_TextRect_height(w) / PIXMAP_INDICATOR_ELBOW;
2121 }
2122 }
2123
2124 Widget
XmCreateToggleButtonGadget(Widget parent,char * name,Arg * arglist,Cardinal argcount)2125 XmCreateToggleButtonGadget(Widget parent, char *name,
2126 Arg *arglist, Cardinal argcount)
2127 {
2128 Widget w;
2129
2130 _XmObjectLock(parent);
2131 w = XtCreateWidget(name, xmToggleButtonGadgetClass, parent,
2132 arglist, argcount);
2133
2134 _XmObjectUnlock(parent);
2135 return w;
2136 }
2137
2138 Boolean
XmToggleButtonGadgetGetState(Widget w)2139 XmToggleButtonGadgetGetState(Widget w)
2140 {
2141 Boolean r;
2142
2143 _XmObjectLock(w);
2144 r = XmIsToggleButtonGadget(w)
2145 ? TBG_Set(w)
2146 : XmIsToggleButton(w)
2147 ? XmToggleButtonGetState(w)
2148 : False;
2149
2150 _XmObjectUnlock(w);
2151 return r;
2152 }
2153
2154 void
XmToggleButtonGadgetSetState(Widget w,Boolean state,Boolean notify)2155 XmToggleButtonGadgetSetState(Widget w, Boolean state, Boolean notify)
2156 {
2157 XmToggleButtonCallbackStruct cbs;
2158
2159 _XmObjectLock(w);
2160 if (XtIsWidget(w))
2161 {
2162 XmToggleButtonSetState(w, state, notify);
2163 _XmObjectUnlock(w);
2164 return;
2165 }
2166 if (XmIsToggleButtonGadget(w) && TBG_Set(w) != state)
2167 {
2168 TBG_Set(w) = state;
2169 draw_toggle(w, NULL, NULL, False, state);
2170 if (notify)
2171 {
2172 cbs.reason = XmCR_VALUE_CHANGED;
2173 cbs.event = NULL;
2174 cbs.set = TBG_Set(w);
2175 if (XmIsRowColumn(XtParent(w)))
2176 {
2177 RC_MenuMenuCallback(w, &cbs);
2178 }
2179 /* Menu callback might cancel the set (radioAlwaysOne). */
2180 cbs.set = TBG_Set(w);
2181 if (!LabG_SkipCallback(w) && TBG_ValueChangedCallback(w))
2182 {
2183 XFlush(XtDisplay(w));
2184 XtCallCallbackList(w, TBG_ValueChangedCallback(w),
2185 (XtPointer)&cbs);
2186 }
2187 }
2188 }
2189 _XmObjectUnlock(w);
2190 }
2191
2192 static void
_XmUnselectColorDefault(Widget w,int offset,XrmValue * val)2193 _XmUnselectColorDefault(Widget w, int offset, XrmValue *val)
2194 {
2195 /*
2196 * XmNunselectColor
2197 * This resource's default for a color display is XmNbackground.
2198 * For a monochrome display, the default is set to the background color.
2199 * To set the background of the button to XmNunselectColor when
2200 * XmNindicatorOn is XmINDICATOR_NONE, the value of XmNfillOnSelect must
2201 * be explicitly set to True.
2202 */
2203 val->size = sizeof(Pixel);
2204 val->addr = (XtPointer)&CoreBackground(w);
2205
2206 #define XmParentBackgroundPixel(w) (((XmManagerWidget) \
2207 (((XmGadget)(w))->object.parent))->core.background_pixel)
2208
2209 val->addr = (XtPointer)&XmParentBackgroundPixel(w);
2210 #if 0
2211 if (DefaultDepth(XtDisplay(w), 0) == 1) { /* Mono */
2212 } else { /* Colour */
2213 }
2214 #endif
2215
2216 DEBUGOUT(_LtDebug(__FILE__, w, "_XmUnselectColorDefault(%p)\n",
2217 *(Pixel *)(val->addr)));
2218 }
2219