1 /*
2 * Motif
3 *
4 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5 *
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
16 * details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
22 */
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27
28 #ifdef REV_INFO
29 #ifndef lint
30 static char rcsid[] = "$TOG: ToggleB.c /main/43 1999/12/06 18:09:38 samborn $"
31 #endif
32 #endif
33
34 #include <stdio.h>
35 #include "XmI.h"
36 #include <X11/ShellP.h>
37 #include <Xm/BaseClassP.h>
38 #include <Xm/CascadeB.h>
39 #include <Xm/DisplayP.h>
40 #include <Xm/DrawP.h>
41 #include <Xm/ManagerP.h>
42 #include <Xm/MenuT.h>
43 #include <Xm/ToggleBG.h>
44 #include <Xm/ToggleBP.h>
45 #include <Xm/TraitP.h>
46 #include <Xm/TransltnsP.h>
47 #include <Xm/VaSimpleP.h>
48 #include "ColorI.h"
49 #include "LabelI.h"
50 #include "MenuProcI.h"
51 #include "MenuStateI.h"
52 #include "MenuUtilI.h"
53 #include "PrimitiveI.h"
54 #include "RepTypeI.h"
55 #include "TravActI.h"
56 #include "TraversalI.h"
57 #include "UniqueEvnI.h"
58
59
60 #define XmINVALID_TYPE 255 /* default flag for IndicatorType */
61 #define XmINVALID_BOOLEAN 85 /* default flag for VisibleWhenOff */
62 #define XmINVALID_PIXEL ((Pixel) -1) /* default flag for unselectColor */
63
64 #define MIN_GLYPH_SIZE 5 /* Threshold for rendering glyphs. */
65
66 #define PixmapOn(w) ((w)->toggle.on_pixmap)
67 #define PixmapOff(w) ((w)->label.pixmap)
68 #define PixmapInd(w) ((w)->toggle.indeterminate_pixmap)
69 #define PixmapInsenOn(w) ((w)->toggle.insen_pixmap)
70 #define PixmapInsenOff(w) ((w)->label.pixmap_insen)
71 #define PixmapInsenInd(w) ((w)->toggle.indeterminate_insensitive_pixmap)
72 #define IsNull(p) ((p) == XmUNSPECIFIED_PIXMAP)
73 #define IsOn(w) ((w)->toggle.visual_set)
74
75 #define IsOneOfMany(ind_type) (((ind_type) == XmONE_OF_MANY) || \
76 ((ind_type) == XmONE_OF_MANY_ROUND) || \
77 ((ind_type) == XmONE_OF_MANY_DIAMOND))
78
79 /* Constants used to decompose XmNindicatorOn values. */
80 #define XmINDICATOR_BOX_MASK 0x0f
81 #define XmINDICATOR_GLYPH_MASK 0xf0
82
83 /* The indicator value should already have been normalized! */
84 #define DRAW3DBOX(ind_on) ((ind_on) & XmINDICATOR_3D_BOX)
85 #define DRAWFLATBOX(ind_on) ((ind_on) & XmINDICATOR_FLAT_BOX)
86 #define DRAWBOX(ind_on) ((ind_on) & XmINDICATOR_BOX_MASK)
87 #define DRAWCHECK(ind_on) ((ind_on) & XmINDICATOR_CHECK_GLYPH)
88 #define DRAWCROSS(ind_on) ((ind_on) & XmINDICATOR_CROSS_GLYPH)
89 #define DRAWGLYPH(ind_on) ((ind_on) & XmINDICATOR_GLYPH_MASK)
90
91
92 /******** Static Function Declarations ********/
93
94 static void ClassInitialize( void ) ;
95 static void ClassPartInitialize(
96 WidgetClass wc) ;
97 static void InitializePrehook(
98 Widget req,
99 Widget new_w,
100 ArgList args,
101 Cardinal *num_args) ;
102 static void InitializePosthook(
103 Widget req,
104 Widget new_w,
105 ArgList args,
106 Cardinal *num_args) ;
107 static void SetAndDisplayPixmap(
108 XmToggleButtonWidget tb,
109 XEvent *event,
110 Region region) ;
111 static void Help(
112 Widget wid,
113 XEvent *event,
114 String *params,
115 Cardinal *num_params) ;
116 static void ToggleButtonCallback(
117 XmToggleButtonWidget data,
118 unsigned int reason,
119 unsigned int value,
120 XEvent *event) ;
121 static void Leave(
122 Widget wid,
123 XEvent *event,
124 String *params,
125 Cardinal *num_params) ;
126 static void Enter(
127 Widget wid,
128 XEvent *event,
129 String *params,
130 Cardinal *num_params) ;
131 static void Arm(
132 Widget wid,
133 XEvent *event,
134 String *params,
135 Cardinal *num_params) ;
136 static void Select(
137 Widget wid,
138 XEvent *event,
139 String *params,
140 Cardinal *num_params) ;
141 static void Disarm(
142 Widget wid,
143 XEvent *event,
144 String *params,
145 Cardinal *num_params) ;
146 static void ArmAndActivate(
147 Widget wid,
148 XEvent *event,
149 String *params,
150 Cardinal *num_params) ;
151 static void BtnDown(
152 Widget wid,
153 XEvent *event,
154 String *params,
155 Cardinal *num_params) ;
156 static void BtnUp(
157 Widget wid,
158 XEvent *event,
159 String *params,
160 Cardinal *num_params) ;
161 static void GetGC(
162 XmToggleButtonWidget tw) ;
163 static void Initialize(
164 Widget rw,
165 Widget nw,
166 ArgList args,
167 Cardinal *num_args) ;
168 static void Destroy(
169 Widget wid) ;
170 static void DrawToggle(
171 XmToggleButtonWidget w) ;
172 static void BorderHighlight(
173 Widget wid) ;
174 static void BorderUnhighlight(
175 Widget wid) ;
176 static void KeySelect(
177 Widget wid,
178 XEvent *event,
179 String *param,
180 Cardinal *num_param) ;
181 static void ComputeSpace(
182 XmToggleButtonWidget tb) ;
183 static void Redisplay(
184 Widget w,
185 XEvent *event,
186 Region region) ;
187 static void Resize(
188 Widget w) ;
189 static Boolean SetValuesPrehook(
190 Widget current,
191 Widget request,
192 Widget new_w,
193 ArgList args,
194 Cardinal *num_args) ;
195 static Boolean SetValues(
196 Widget current,
197 Widget request,
198 Widget new_w,
199 ArgList args,
200 Cardinal *num_args) ;
201 static void DrawToggleShadow(
202 XmToggleButtonWidget tb) ;
203 static void DrawToggleLabel(
204 XmToggleButtonWidget tb) ;
205 static void DrawEtchedInMenu(
206 XmToggleButtonWidget tb) ;
207 static void SetToggleSize(
208 XmToggleButtonWidget newtb) ;
209 static void NextState(unsigned char *state);
210 static void DrawBox(
211 XmToggleButtonWidget w,
212 GC top_gc,
213 GC bot_gc,
214 GC fillgc,
215 int x, int y, int edge,
216 Dimension margin
217 );
218
219 static void DefaultSelectColor(Widget widget,
220 int offset,
221 XrmValue *value);
222
223 static unsigned char NormalizeIndOn(XmToggleButtonWidget tb);
224 static unsigned char NormalizeIndType(XmToggleButtonWidget tb);
225 static void TB_FixTearoff( XmToggleButtonWidget tb);
226
227
228 /******** End Static Function Declarations ********/
229
230
231
232 /*************************************<->*************************************
233 *
234 *
235 * Description: default translation table for class: ToggleButton
236 * -----------
237 *
238 * Matches events with string descriptors for internal routines.
239 *
240 *************************************<->***********************************/
241 static XtTranslations default_parsed;
242
243 #define defaultTranslations _XmToggleB_defaultTranslations
244
245 static XtTranslations menu_parsed;
246
247 #define menuTranslations _XmToggleB_menuTranslations
248
249 /*************************************<->*************************************
250 *
251 *
252 * Description: action list for class: ToggleButton
253 * -----------
254 *
255 * Matches string descriptors with internal routines.
256 *
257 *************************************<->***********************************/
258
259 static XtActionsRec actionsList[] =
260 {
261 {"Arm", Arm },
262 {"ArmAndActivate", ArmAndActivate },
263 {"Disarm", Disarm },
264 {"Select", Select },
265 {"Enter", Enter },
266 {"Leave", Leave },
267 {"BtnDown", BtnDown },
268 {"BtnUp", BtnUp },
269 {"ButtonTakeFocus", _XmButtonTakeFocus },
270 {"MenuButtonTakeFocus", _XmMenuButtonTakeFocus },
271 {"MenuButtonTakeFocusUp", _XmMenuButtonTakeFocusUp },
272 {"KeySelect", KeySelect },
273 {"Help", Help},
274 };
275
276
277
278
279 /*************************************<->*************************************
280 *
281 *
282 * Description: resource list for class: ToggleButton
283 * -----------
284 *
285 * Provides default resource settings for instances of this class.
286 * To get full set of default settings, examine resouce list of super
287 * classes of this class.
288 *
289 *************************************<->***********************************/
290
291 #define Offset(field) (XtOffsetOf(XmToggleButtonRec, field))
292
293 static XtResource resources[] = {
294 {
295 XmNindicatorSize, XmCIndicatorSize, XmRVerticalDimension,
296 sizeof(Dimension), Offset(toggle.indicator_dim),
297 XmRImmediate, (XtPointer) XmINVALID_DIMENSION
298 },
299
300 {
301 XmNindicatorType, XmCIndicatorType, XmRIndicatorType,
302 sizeof(unsigned char), Offset(toggle.ind_type),
303 XmRImmediate, (XtPointer) XmINVALID_TYPE
304 },
305
306 {
307 XmNvisibleWhenOff, XmCVisibleWhenOff, XmRBoolean,
308 sizeof(Boolean), Offset(toggle.visible),
309 XmRImmediate, (XtPointer) XmINVALID_BOOLEAN
310 },
311
312 {
313 XmNspacing, XmCSpacing, XmRHorizontalDimension,
314 sizeof(Dimension), Offset(toggle.spacing),
315 XmRImmediate, (XtPointer) 4
316 },
317
318 {
319 XmNselectPixmap, XmCSelectPixmap, XmRDynamicPixmap,
320 sizeof(Pixmap), Offset(toggle.on_pixmap),
321 XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP
322 },
323
324 {
325 XmNselectInsensitivePixmap, XmCSelectInsensitivePixmap, XmRDynamicPixmap,
326 sizeof(Pixmap), Offset(toggle.insen_pixmap),
327 XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP
328 },
329
330 {
331 XmNset, XmCSet, XmRSet,
332 sizeof(unsigned char), Offset(toggle.set),
333 XmRImmediate, (XtPointer) XmUNSET
334 },
335
336 {
337 XmNindicatorOn, XmCIndicatorOn, XmRIndicatorOn,
338 sizeof (unsigned char), Offset(toggle.ind_on),
339 XmRImmediate, (XtPointer) XmINDICATOR_FILL
340 },
341
342 {
343 XmNfillOnSelect, XmCFillOnSelect, XmRBoolean,
344 sizeof(Boolean), Offset(toggle.fill_on_select),
345 XmRImmediate, (XtPointer) XmINVALID_BOOLEAN
346 },
347
348 {
349 XmNselectColor, XmCSelectColor, XmRSelectColor,
350 sizeof(Pixel), Offset(toggle.select_color),
351 XmRCallProc, (XtPointer) DefaultSelectColor
352 },
353
354 {
355 XmNvalueChangedCallback, XmCValueChangedCallback, XmRCallback,
356 sizeof (XtCallbackList), Offset(toggle.value_changed_CB),
357 XmRPointer, (XtPointer)NULL
358 },
359
360 {
361 XmNarmCallback, XmCArmCallback, XmRCallback,
362 sizeof(XtCallbackList), Offset(toggle.arm_CB),
363 XmRPointer, (XtPointer)NULL
364 },
365
366 {
367 XmNdisarmCallback, XmCDisarmCallback, XmRCallback,
368 sizeof (XtCallbackList), Offset(toggle.disarm_CB),
369 XmRPointer, (XtPointer)NULL
370 },
371
372 {
373 XmNtraversalOn, XmCTraversalOn, XmRBoolean,
374 sizeof(Boolean), Offset(primitive.traversal_on),
375 XmRImmediate, (XtPointer) True
376 },
377
378 {
379 XmNhighlightThickness, XmCHighlightThickness, XmRHorizontalDimension,
380 sizeof(Dimension), Offset(primitive.highlight_thickness),
381 XmRCallProc, (XtPointer) _XmSetThickness
382 },
383
384 {
385 XmNtoggleMode, XmCToggleMode, XmRToggleMode,
386 sizeof(unsigned char), Offset(toggle.toggle_mode),
387 XmRImmediate, (XtPointer) XmTOGGLE_BOOLEAN
388 },
389
390 {
391 XmNindeterminatePixmap, XmCIndeterminatePixmap, XmRDynamicPixmap,
392 sizeof(Pixmap), Offset(toggle.indeterminate_pixmap),
393 XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP
394 },
395
396 {
397 XmNindeterminateInsensitivePixmap, XmCIndeterminateInsensitivePixmap,
398 XmRDynamicPixmap,
399 sizeof(Pixmap), Offset(toggle.indeterminate_insensitive_pixmap),
400 XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP
401 },
402
403 {
404 XmNunselectColor, XmCUnselectColor, XmRPixel,
405 sizeof(Pixel), Offset(toggle.unselect_color),
406 XmRImmediate, (XtPointer) XmINVALID_PIXEL
407 },
408
409 {
410 XmNdetailShadowThickness, XmCShadowThickness, XmRHorizontalDimension,
411 sizeof(Dimension), Offset(toggle.detail_shadow_thickness),
412 XmRCallProc, (XtPointer) _XmSetThickness
413 }
414 };
415
416 /* Definition for resources that need special processing in get values */
417
418 static XmSyntheticResource syn_resources[] =
419 {
420 {
421 XmNspacing,
422 sizeof(Dimension), Offset(toggle.spacing),
423 XmeFromHorizontalPixels, XmeToHorizontalPixels
424 },
425
426 {
427 XmNindicatorSize,
428 sizeof(Dimension), Offset(toggle.indicator_dim),
429 XmeFromVerticalPixels, XmeToVerticalPixels
430 },
431
432 {
433 XmNdetailShadowThickness,
434 sizeof(Dimension), Offset(toggle.detail_shadow_thickness),
435 XmeFromHorizontalPixels, XmeToHorizontalPixels
436 }
437 };
438
439 #undef Offset
440
441 /*************************************<->*************************************
442 *
443 *
444 * Description: global class record for instances of class: ToggleButton
445 * -----------
446 *
447 * Defines default field settings for this class record.
448 *
449 *************************************<->***********************************/
450 static XmBaseClassExtRec toggleBBaseClassExtRec = {
451 NULL, /* Next extension */
452 NULLQUARK, /* record type XmQmotif */
453 XmBaseClassExtVersion, /* version */
454 sizeof(XmBaseClassExtRec), /* size */
455 InitializePrehook, /* initialize prehook */
456 SetValuesPrehook, /* set_values prehook */
457 InitializePosthook, /* initialize posthook */
458 XmInheritSetValuesPosthook, /* set_values posthook */
459 XmInheritClass, /* secondary class */
460 XmInheritSecObjectCreate, /* creation proc */
461 XmInheritGetSecResData, /* getSecResData */
462 {0}, /* fast subclass */
463 XmInheritGetValuesPrehook, /* get_values prehook */
464 XmInheritGetValuesPosthook, /* get_values posthook */
465 (XtWidgetClassProc)NULL, /* classPartInitPrehook */
466 (XtWidgetClassProc)NULL, /* classPartInitPosthook*/
467 NULL, /* ext_resources */
468 NULL, /* compiled_ext_resources*/
469 0, /* num_ext_resources */
470 FALSE, /* use_sub_resources */
471 XmInheritWidgetNavigable, /* widgetNavigable */
472 XmInheritFocusChange, /* focusChange */
473 };
474
475
476 externaldef(xmtogglebuttonclassrec)
477 XmToggleButtonClassRec xmToggleButtonClassRec = {
478 {
479 /* superclass */ (WidgetClass) &xmLabelClassRec,
480 /* class_name */ "XmToggleButton",
481 /* widget_size */ sizeof(XmToggleButtonRec),
482 /* class_initialize */ ClassInitialize,
483 /* class_part_init */ ClassPartInitialize,
484 /* class_inited */ FALSE,
485 /* initialize */ Initialize,
486 /* initialize_hook */ (XtArgsProc)NULL,
487 /* realize */ XmInheritRealize,
488 /* actions */ actionsList,
489 /* num_actions */ XtNumber(actionsList),
490 /* resources */ resources,
491 /* num_resources */ XtNumber(resources),
492 /* xrm_class */ NULLQUARK,
493 /* compress_motion */ TRUE,
494 /* compress_exposure */ XtExposeCompressMaximal,
495 /* compress_enterlv */ TRUE,
496 /* visible_interest */ FALSE,
497 /* destroy */ Destroy,
498 /* resize */ Resize,
499 /* expose */ Redisplay,
500 /* set_values */ SetValues,
501 /* set_values_hook */ (XtArgsFunc)NULL,
502 /* set_values_almost */ XtInheritSetValuesAlmost,
503 /* get_values_hook */ (XtArgsProc)NULL,
504 /* accept_focus */ (XtAcceptFocusProc)NULL,
505 /* version */ XtVersion,
506 /* callback_private */ NULL,
507 /* tm_table */ NULL,
508 /* query_geometry */ XtInheritQueryGeometry,
509 /* display_accelerator*/ (XtStringProc)NULL,
510 /* extension record */ (XtPointer)&toggleBBaseClassExtRec,
511 },
512
513 {
514 /* Primitive border_highlight */ BorderHighlight,
515 /* Primitive border_unhighlight */ BorderUnhighlight,
516 /* translations */ XtInheritTranslations,
517 /* arm_and_activate */ ArmAndActivate,
518 /* syn resources */ syn_resources,
519 /* num syn_resources */ XtNumber(syn_resources),
520 /* extension */ NULL,
521 },
522
523 {
524 /* SetOverrideCallback */ XmInheritWidgetProc,
525 /* menu procedures */ XmInheritMenuProc,
526 /* menu traversal xlation */ XtInheritTranslations,
527 /* extension */ NULL,
528 },
529
530 {
531 /* extension */ (XtPointer) NULL,
532 }
533 };
534
535 externaldef(xmtogglebuttonwidgetclass)
536 WidgetClass xmToggleButtonWidgetClass = (WidgetClass)&xmToggleButtonClassRec;
537
538 /* Menu Savvy trait record */
539 static XmMenuSavvyTraitRec MenuSavvyRecord = {
540 /* version: */
541 -1,
542 NULL,
543 NULL,
544 NULL,
545 _XmCBNameValueChanged,
546 };
547
548 /*************************************<->*************************************
549 *
550 * ClassInitialize
551 *
552 *************************************<->***********************************/
553 static void
ClassInitialize(void)554 ClassInitialize( void )
555 {
556 /* Parse the various translation tables. */
557 default_parsed = XtParseTranslationTable(defaultTranslations);
558 menu_parsed = XtParseTranslationTable(menuTranslations);
559
560 /* Set up base class extension quark */
561 toggleBBaseClassExtRec.record_type = XmQmotif;
562 }
563
564 /*****************************************************************************
565 *
566 * ClassPartInitialize
567 * Set up fast subclassing for the widget.
568 *
569 ****************************************************************************/
570 static void
ClassPartInitialize(WidgetClass wc)571 ClassPartInitialize(
572 WidgetClass wc )
573 {
574 _XmFastSubclassInit (wc, XmTOGGLE_BUTTON_BIT);
575
576 /* Install the menu savvy trait record, copying fields from XmLabel */
577 _XmLabelCloneMenuSavvy (wc, &MenuSavvyRecord);
578 }
579
580 /************************************************************
581 *
582 * InitializePrehook
583 *
584 * Put the proper translations in core_class tm_table so that
585 * the data is massaged correctly
586 *
587 ************************************************************/
588 /*ARGSUSED*/
589 static void
InitializePrehook(Widget req,Widget new_w,ArgList args,Cardinal * num_args)590 InitializePrehook(
591 Widget req, /* unused */
592 Widget new_w,
593 ArgList args, /* unused */
594 Cardinal *num_args ) /* unused */
595 {
596 unsigned char type;
597 XmMenuSystemTrait menuSTrait;
598 XmToggleButtonWidget bw = (XmToggleButtonWidget) new_w ;
599
600 menuSTrait = (XmMenuSystemTrait)
601 XmeTraitGet((XtPointer) XtClass(XtParent(new_w)), XmQTmenuSystem);
602
603 _XmSaveCoreClassTranslations (new_w);
604
605 if (menuSTrait != NULL)
606 type = menuSTrait->type(XtParent(new_w));
607 else
608 type = XmWORK_AREA;
609
610 _XmProcessLock();
611 if ((type == XmMENU_PULLDOWN) ||
612 (type == XmMENU_POPUP))
613 new_w->core.widget_class->core_class.tm_table = (String) menu_parsed;
614 else
615 new_w->core.widget_class->core_class.tm_table = (String) default_parsed;
616 _XmProcessUnlock();
617
618 /* CR 2990: Use XmNbuttonFontList as the default font. */
619 if (bw->label.font == NULL)
620 bw->label.font = XmeGetDefaultRenderTable (new_w, XmBUTTON_FONTLIST);
621 }
622
623 /************************************************************
624 *
625 * InitializePosthook
626 *
627 * restore core class translations
628 *
629 ************************************************************/
630 /*ARGSUSED*/
631 static void
InitializePosthook(Widget req,Widget new_w,ArgList args,Cardinal * num_args)632 InitializePosthook(
633 Widget req, /* unused */
634 Widget new_w,
635 ArgList args, /* unused */
636 Cardinal *num_args ) /* unused */
637 {
638 _XmRestoreCoreClassTranslations (new_w);
639 }
640
641 /*********************************************************************
642 *
643 * redisplayPixmap
644 * does the apropriate calculations based on the toggle button's
645 * current pixmap and calls label's Redisplay routine.
646 *
647 * This routine was added to fix CR 4839 and CR 4838
648 * D. Rand 7/6/92
649 *
650 ***********************************************************************/
651
652 static void
redisplayPixmap(XmToggleButtonWidget tb,XEvent * event,Region region)653 redisplayPixmap(XmToggleButtonWidget tb,
654 XEvent *event,
655 Region region)
656 {
657 Pixmap todo;
658 unsigned int onH = 0, onW = 0;
659 int w, h;
660 int x, y, offset;
661 short saveY;
662 unsigned short saveWidth, saveHeight;
663
664 offset = tb->primitive.highlight_thickness + tb->primitive.shadow_thickness;
665
666 x = offset + tb->label.margin_width + tb->label.margin_left;
667
668 y = offset + tb->label.margin_height + tb->label.margin_top;
669
670 w = XtWidth(tb) - x - offset - tb->label.margin_right
671 - tb->label.margin_width;
672
673 ASSIGN_MAX(w, 0);
674
675 h = XtHeight(tb) - y - offset - tb->label.margin_bottom
676 - tb->label.margin_height;
677
678 ASSIGN_MAX(h, 0);
679
680 XClearArea(XtDisplay(tb), XtWindow(tb), x, y, w, h, False);
681
682 todo = tb->label.pixmap;
683
684 if ((! XtIsSensitive((Widget) tb)) && tb->label.pixmap_insen)
685 todo = tb->label.pixmap_insen;
686
687 if (! IsNull(todo))
688 XmeGetPixmapData(XtScreen(tb), todo,
689 NULL, NULL, NULL, NULL, NULL, NULL,
690 &onW, &onH);
691
692 saveY = Lab_TextRect_y(tb);
693 saveWidth = Lab_TextRect_width(tb);
694 saveHeight = Lab_TextRect_height(tb);
695
696 h = (XtHeight(tb) - onH) / 2;
697 Lab_TextRect_y(tb) = MAX(h, 0);
698 Lab_TextRect_height(tb) = onH;
699 Lab_TextRect_width(tb) = onW;
700 {
701 XtExposeProc expose;
702 _XmProcessLock();
703 expose = xmLabelClassRec.core_class.expose;
704 _XmProcessUnlock();
705 (* expose) ((Widget) tb, event, region);
706 }
707
708 Lab_TextRect_y(tb) = saveY;
709 Lab_TextRect_width(tb) = saveWidth;
710 Lab_TextRect_height(tb) = saveHeight;
711 }
712
713 static void
HandlePixmap(XmToggleButtonWidget tb,Pixmap pix,Pixmap insen_pix,XEvent * event,Region region)714 HandlePixmap(XmToggleButtonWidget tb,
715 Pixmap pix,
716 Pixmap insen_pix,
717 XEvent * event,
718 Region region)
719 {
720 if (XtIsSensitive((Widget) tb))
721 {
722 if (! IsNull (pix))
723 {
724 Pixmap tempPix = tb->label.pixmap;
725
726 tb->label.pixmap = pix;
727 redisplayPixmap(tb, event, region);
728 tb->label.pixmap = tempPix;
729 }
730 else
731 redisplayPixmap(tb, event, region);
732 }
733 else
734 {
735 if (! IsNull (insen_pix))
736 {
737 Pixmap tempPix = tb->label.pixmap_insen;
738
739 tb->label.pixmap_insen = insen_pix;
740 redisplayPixmap(tb, event, region);
741 tb->label.pixmap_insen = tempPix;
742 }
743 else
744 redisplayPixmap(tb, event, region);
745 }
746 }
747
748 /***********************************************************************
749 *
750 * SetAndDisplayPixmap
751 * Sets the appropriate on, off pixmap in label's pixmap field and
752 * calls redisplayPixmap
753 *
754 ***********************************************************************/
755 static void
SetAndDisplayPixmap(XmToggleButtonWidget tb,XEvent * event,Region region)756 SetAndDisplayPixmap(
757 XmToggleButtonWidget tb,
758 XEvent *event,
759 Region region )
760 {
761 if (tb->toggle.toggle_mode == XmTOGGLE_INDETERMINATE)
762 {
763 if (tb->toggle.visual_set == XmUNSET)
764 HandlePixmap(tb, PixmapOff(tb), PixmapInsenOff(tb), event, region);
765 else if (tb->toggle.visual_set == XmSET)
766 HandlePixmap(tb, PixmapOn(tb), PixmapInsenOn(tb), event, region);
767 else if (tb->toggle.visual_set == XmINDETERMINATE)
768 HandlePixmap(tb, PixmapInd(tb), PixmapInsenInd(tb), event, region);
769 }
770 else
771 {
772 if (IsOn (tb) == XmSET)
773 HandlePixmap(tb, PixmapOn(tb), PixmapInsenOn(tb), event, region);
774 else
775 redisplayPixmap(tb, event, region);
776 }
777 }
778
779 /*************************************************************************
780 *
781 * Help
782 * This routine is called if the user has made a help selection
783 * on the widget.
784 *
785 ************************************************************************/
786 static void
Help(Widget wid,XEvent * event,String * params,Cardinal * num_params)787 Help(
788 Widget wid,
789 XEvent *event,
790 String *params,
791 Cardinal *num_params )
792 {
793 XmToggleButtonWidget tb = (XmToggleButtonWidget) wid ;
794 Boolean is_menupane = Lab_IsMenupane(tb);
795 XmMenuSystemTrait menuSTrait;
796
797 menuSTrait = (XmMenuSystemTrait)
798 XmeTraitGet((XtPointer) XtClass(XtParent(tb)), XmQTmenuSystem);
799
800 if (is_menupane && menuSTrait != NULL)
801 menuSTrait->buttonPopdown(XtParent(tb), event);
802
803 _XmPrimitiveHelp( (Widget) tb, event, params, num_params);
804
805 if (is_menupane && menuSTrait != NULL)
806 menuSTrait->reparentToTearOffShell(XtParent(tb), event);
807 }
808
809 /*************************************************************************
810 *
811 * ToggleButtonCallback
812 * This is the widget's application callback routine
813 *
814 *************************************************************************/
815 static void
ToggleButtonCallback(XmToggleButtonWidget data,unsigned int reason,unsigned int value,XEvent * event)816 ToggleButtonCallback(
817 XmToggleButtonWidget data,
818 unsigned int reason,
819 unsigned int value,
820 XEvent *event )
821 {
822 XmToggleButtonCallbackStruct temp;
823
824 temp.reason = reason;
825 temp.set = value;
826 temp.event = event;
827
828 switch (reason)
829 {
830 case XmCR_VALUE_CHANGED:
831 XtCallCallbackList ((Widget) data, data->toggle.value_changed_CB, &temp);
832 break;
833
834 case XmCR_ARM:
835 XtCallCallbackList ((Widget) data, data->toggle.arm_CB, &temp);
836 break;
837
838 case XmCR_DISARM:
839 XtCallCallbackList ((Widget) data, data->toggle.disarm_CB, &temp);
840 break;
841 }
842 }
843
844 /* Update the toggle after an Enter or Leave action. */
845 static void
ActionDraw(XmToggleButtonWidget w,XEvent * event,Boolean leave)846 ActionDraw(XmToggleButtonWidget w,
847 XEvent *event,
848 Boolean leave)
849 {
850 if (w->toggle.Armed)
851 {
852 /* CR 7301: We may have armed while outside the toggle. */
853 if (leave)
854 w->toggle.visual_set = w->toggle.set;
855 else if (w->toggle.toggle_mode == XmTOGGLE_INDETERMINATE)
856 NextState(&w->toggle.visual_set);
857 else
858 IsOn(w) = (w->toggle.set == XmSET)? XmUNSET : XmSET;
859
860 if (w->toggle.ind_on)
861 DrawToggle(w);
862 else
863 {
864 if (w->primitive.shadow_thickness > 0)
865 DrawToggleShadow(w);
866 if (w->toggle.fill_on_select && !Lab_IsPixmap(w))
867 DrawToggleLabel(w);
868 }
869
870 if (Lab_IsPixmap(w) || Lab_IsPixmapAndText(w))
871 SetAndDisplayPixmap(w, event, NULL);
872 }
873 }
874
875 /**************************************************************************
876 *
877 * Leave
878 * This procedure is called when the mouse button is pressed and the
879 * cursor moves out of the widget's window. This procedure is used
880 * to change the visuals.
881 *
882 *************************************************************************/
883 static void
Leave(Widget wid,XEvent * event,String * params,Cardinal * num_params)884 Leave(
885 Widget wid,
886 XEvent *event,
887 String *params,
888 Cardinal *num_params )
889 {
890 XmToggleButtonWidget w = (XmToggleButtonWidget) wid;
891
892 if (Lab_IsMenupane(w))
893 {
894 if (_XmGetInDragMode((Widget)w) && w->toggle.Armed &&
895 (/* !ActiveTearOff || */ event->xcrossing.mode == NotifyNormal))
896 {
897 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid));
898 Boolean etched_in = dpy->display.enable_etched_in_menu;
899
900 w->toggle.Armed = FALSE;
901
902 ((XmManagerWidget) XtParent(wid))->manager.active_child = NULL;
903
904 if ((etched_in) &&
905 ((w->toggle.ind_on) ||
906 (!(w->toggle.ind_on) && !(w->toggle.fill_on_select))))
907 {
908 DrawEtchedInMenu(w);
909 if (w->toggle.ind_on)
910 DrawToggle(w);
911 }
912
913 XmeClearBorder(XtDisplay (w), XtWindow (w),
914 w->primitive.highlight_thickness,
915 w->primitive.highlight_thickness,
916 w->core.width - 2 * w->primitive.highlight_thickness,
917 w->core.height - 2 * w->primitive.highlight_thickness,
918 w->primitive.shadow_thickness);
919
920 if (w->toggle.disarm_CB)
921 {
922 XFlush (XtDisplay (w));
923 ToggleButtonCallback(w, XmCR_DISARM, w->toggle.set, event);
924 }
925 }
926 }
927 else
928 {
929 _XmPrimitiveLeave( (Widget) w, event, params, num_params);
930 ActionDraw(w, event, TRUE);
931 }
932 }
933
934 /**************************************************************************
935 *
936 * Enter
937 * This procedure is called when the mouse button is pressed and the
938 * cursor reenters the widget's window. This procedure changes the visuals
939 * accordingly.
940 *
941 **************************************************************************/
942 static void
Enter(Widget wid,XEvent * event,String * params,Cardinal * num_params)943 Enter(
944 Widget wid,
945 XEvent *event,
946 String *params,
947 Cardinal *num_params )
948 {
949 XmToggleButtonWidget w = (XmToggleButtonWidget) wid ;
950
951 if (Lab_IsMenupane(w))
952 {
953 if ((((ShellWidget) XtParent(XtParent(w)))->shell.popped_up) &&
954 _XmGetInDragMode((Widget)w))
955 {
956 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid));
957 Boolean etched_in = dpy->display.enable_etched_in_menu;
958
959 if (w->toggle.Armed)
960 return;
961
962 /* So KHelp event is delivered correctly */
963 _XmSetFocusFlag( XtParent(XtParent(w)), XmFOCUS_IGNORE, TRUE);
964 XtSetKeyboardFocus(XtParent(XtParent(w)), (Widget)w);
965 _XmSetFocusFlag( XtParent(XtParent(w)), XmFOCUS_IGNORE, FALSE);
966
967 ((XmManagerWidget) XtParent(wid))->manager.active_child = wid;
968
969 w->toggle.Armed = TRUE;
970
971 if ((etched_in) &&
972 ((w->toggle.ind_on) ||
973 (!(w->toggle.ind_on) && !(w->toggle.fill_on_select))))
974 {
975 DrawEtchedInMenu(w);
976 if (w->toggle.ind_on)
977 DrawToggle(w);
978 }
979
980 XmeDrawShadows (XtDisplay (w), XtWindow (w),
981 w->primitive.top_shadow_GC,
982 w->primitive.bottom_shadow_GC,
983 w->primitive.highlight_thickness,
984 w->primitive.highlight_thickness,
985 w->core.width - 2 * w->primitive.highlight_thickness,
986 w->core.height - 2 * w->primitive.highlight_thickness,
987 w->primitive.shadow_thickness,
988 etched_in ? XmSHADOW_IN : XmSHADOW_OUT);
989
990 if (w->toggle.arm_CB)
991 {
992 XFlush (XtDisplay (w));
993 ToggleButtonCallback(w, XmCR_ARM, w->toggle.set, event);
994 }
995 }
996 }
997 else
998 {
999 _XmPrimitiveEnter( (Widget) w, event, params, num_params);
1000 ActionDraw(w, event, FALSE);
1001 }
1002 }
1003
1004 static void
NextState(unsigned char * state)1005 NextState(
1006 unsigned char *state)
1007 {
1008 switch(*state)
1009 {
1010 case XmUNSET:
1011 *state = XmSET;
1012 break;
1013 case XmSET:
1014 *state = XmINDETERMINATE;
1015 break;
1016 case XmINDETERMINATE:
1017 *state = XmUNSET;
1018 break;
1019 }
1020 }
1021
1022 /****************************************************************************
1023 *
1024 * Arm
1025 * This function processes button down occuring on the togglebutton.
1026 * Mark the togglebutton as armed and display it armed.
1027 * The callbacks for XmNarmCallback are called.
1028 *
1029 ***************************************************************************/
1030
1031 /* ARGSUSED */
1032 static void
Arm(Widget wid,XEvent * event,String * params,Cardinal * num_params)1033 Arm(
1034 Widget wid,
1035 XEvent *event,
1036 String *params,
1037 Cardinal *num_params )
1038 {
1039 XmToggleButtonWidget tb = (XmToggleButtonWidget) wid ;
1040
1041 (void)XmProcessTraversal( (Widget) tb, XmTRAVERSE_CURRENT);
1042
1043 if (tb->toggle.toggle_mode == XmTOGGLE_INDETERMINATE)
1044 NextState(&tb->toggle.visual_set);
1045 else
1046 IsOn(tb) = (tb->toggle.set == XmSET)? XmUNSET : XmSET;
1047
1048 tb->toggle.Armed = TRUE;
1049
1050 if (tb->toggle.ind_on)
1051 DrawToggle(tb);
1052 else
1053 {
1054 if (tb->primitive.shadow_thickness > 0)
1055 DrawToggleShadow (tb);
1056 if (tb->toggle.fill_on_select && !Lab_IsPixmap(tb))
1057 DrawToggleLabel(tb);
1058 }
1059
1060 if (Lab_IsPixmap(tb) || Lab_IsPixmapAndText(tb))
1061 SetAndDisplayPixmap(tb, event, NULL);
1062
1063 if (tb->toggle.arm_CB)
1064 {
1065 XFlush(XtDisplay(tb));
1066
1067 ToggleButtonCallback(tb, XmCR_ARM, tb->toggle.set, event);
1068 }
1069 }
1070
1071 /************************************************************************
1072 *
1073 * Select
1074 * Mark the togglebutton as unarmed (i.e. inactive).
1075 * If the button release occurs inside of the ToggleButton, the
1076 * callbacks for XmNvalueChangedCallback are called.
1077 *
1078 ************************************************************************/
1079 /* ARGSUSED */
1080 static void
Select(Widget wid,XEvent * event,String * params,Cardinal * num_params)1081 Select(
1082 Widget wid,
1083 XEvent *event,
1084 String *params,
1085 Cardinal *num_params )
1086 {
1087 XmToggleButtonWidget tb = (XmToggleButtonWidget) wid ;
1088 XmToggleButtonCallbackStruct call_value;
1089 Boolean hit;
1090 XmMenuSystemTrait menuSTrait;
1091 Boolean radio = TRUE, always = TRUE;
1092
1093 if (tb->toggle.Armed == FALSE)
1094 return;
1095
1096 tb->toggle.Armed = FALSE;
1097
1098 if (XmIsRowColumn(XtParent(tb))) {
1099 XtVaGetValues(XtParent(tb),
1100 XmNradioBehavior, &radio,
1101 XmNradioAlwaysOne, &always,
1102 NULL);
1103 }
1104
1105 /* CR 8068: Verify that this is in fact a button event. */
1106 /* CR 9181: Consider clipping when testing visibility. */
1107 /* Check to see if BtnUp is inside the widget */
1108 hit = ((event->xany.type == ButtonPress ||
1109 event->xany.type == ButtonRelease) &&
1110 _XmGetPointVisibility(wid,
1111 event->xbutton.x_root,
1112 event->xbutton.y_root));
1113
1114 if (hit)
1115 {
1116 if (tb->toggle.toggle_mode == XmTOGGLE_INDETERMINATE)
1117 NextState(&tb->toggle.set);
1118 else
1119 tb->toggle.set = !tb->toggle.set;
1120 }
1121
1122 /* CR 7803: Suppress redundant redraws. */
1123 if (tb->toggle.set != tb->toggle.visual_set)
1124 {
1125 /* Redisplay after changing state. */
1126 XtExposeProc expose;
1127 _XmProcessLock();
1128 expose = ((WidgetClass)XtClass(tb))->core_class.expose;
1129 _XmProcessUnlock();
1130 (* (expose)) (wid, event, NULL);
1131 }
1132
1133 if (hit)
1134 {
1135 /* UNDOING this fix .... */
1136 /* CR 8904: Notify value_changed before entry so that state is */
1137 /* reported correctly even if the entry callback resets it. */
1138 menuSTrait = (XmMenuSystemTrait)
1139 XmeTraitGet((XtPointer) XtClass(XtParent(tb)), XmQTmenuSystem);
1140
1141 if (menuSTrait != NULL)
1142 {
1143 call_value.reason = XmCR_VALUE_CHANGED;
1144 call_value.event = event;
1145 call_value.set = tb->toggle.set;
1146 menuSTrait->entryCallback(XtParent(tb), (Widget) tb, &call_value);
1147 }
1148
1149 if ((! tb->label.skipCallback) &&
1150 (tb->toggle.value_changed_CB))
1151 {
1152 XFlush(XtDisplay(tb));
1153 ToggleButtonCallback(tb, XmCR_VALUE_CHANGED, tb->toggle.set, event);
1154 }
1155
1156 }
1157 }
1158
1159 /**********************************************************************
1160 *
1161 * Disarm
1162 * The callbacks for XmNdisarmCallback are called..
1163 *
1164 ************************************************************************/
1165 /* ARGSUSED */
1166 static void
Disarm(Widget wid,XEvent * event,String * params,Cardinal * num_params)1167 Disarm(
1168 Widget wid,
1169 XEvent *event,
1170 String *params,
1171 Cardinal *num_params )
1172 {
1173 XmToggleButtonWidget tb = (XmToggleButtonWidget) wid ;
1174
1175 if (tb->toggle.disarm_CB)
1176 ToggleButtonCallback(tb, XmCR_DISARM, tb->toggle.set, event);
1177
1178 /* BEGIN OSF Fix pir 2826 */
1179
1180 /* CR 7803: Suppress redundant redraws. */
1181 if (tb->toggle.set != tb->toggle.visual_set)
1182 Redisplay((Widget) tb, event, (Region) NULL);
1183
1184 /* END OSF Fix pir 2826 */
1185 }
1186
1187 static void
TB_FixTearoff(XmToggleButtonWidget tb)1188 TB_FixTearoff( XmToggleButtonWidget tb)
1189 {
1190 if (XmMENU_PULLDOWN == tb->label.menu_type)
1191 {
1192 Widget mwid = XmGetPostedFromWidget(XtParent(tb));
1193 if (mwid && XmIsRowColumn(mwid)
1194 && (XmMENU_OPTION == RC_Type(mwid))
1195 && _XmIsActiveTearOff(XtParent(tb)))
1196 XmProcessTraversal((Widget) tb, XmTRAVERSE_CURRENT);
1197 }
1198 }
1199
1200 /************************************************************************
1201 *
1202 * ArmAndActivate
1203 * This routine arms and activates a ToggleButton. It is called on
1204 * <Key> Return and a <Key> Space, as well as when a mnemonic or
1205 * button accelerator has been activated.
1206 *
1207 ************************************************************************/
1208 /* ARGSUSED */
1209 static void
ArmAndActivate(Widget wid,XEvent * event,String * params,Cardinal * num_params)1210 ArmAndActivate(
1211 Widget wid,
1212 XEvent *event,
1213 String *params,
1214 Cardinal *num_params )
1215 {
1216 XmToggleButtonWidget tb = (XmToggleButtonWidget) wid ;
1217 XmToggleButtonCallbackStruct call_value;
1218 Boolean already_armed = tb->toggle.Armed;
1219 Boolean is_menupane = Lab_IsMenupane(tb);
1220 Boolean torn_has_focus = FALSE;
1221 XmMenuSystemTrait menuSTrait;
1222 Boolean radio = TRUE, always = TRUE, no_change;
1223
1224 if (XmIsRowColumn(XtParent(tb))) {
1225 XtVaGetValues(XtParent(tb),
1226 XmNradioBehavior, &radio,
1227 XmNradioAlwaysOne, &always,
1228 NULL);
1229 }
1230
1231 no_change = False;
1232
1233 menuSTrait = (XmMenuSystemTrait)
1234 XmeTraitGet((XtPointer) XtClass(XtParent(tb)), XmQTmenuSystem);
1235
1236 if (is_menupane && !XmIsMenuShell(XtParent(XtParent(tb))))
1237 {
1238 if (XmeFocusIsInShell((Widget)tb))
1239 {
1240 /* In case allowAcceleratedInsensitiveUnmanagedMenuItems is True */
1241 if (!XtIsSensitive((Widget)tb) || (!XtIsManaged((Widget)tb)))
1242 return;
1243 torn_has_focus = TRUE;
1244 }
1245 }
1246
1247 tb->toggle.Armed = FALSE;
1248
1249 if (!no_change) /* skip toggle for buttons already turned on */
1250 {
1251 if (tb->toggle.toggle_mode == XmTOGGLE_INDETERMINATE)
1252 {
1253 NextState(&tb->toggle.visual_set);
1254 NextState(&tb->toggle.set);
1255 }
1256 else
1257 {
1258 tb->toggle.set = (tb->toggle.set == XmSET)? XmUNSET : XmSET;
1259 IsOn(tb) = tb->toggle.set;
1260 }
1261 }
1262
1263 if (is_menupane && menuSTrait != NULL)
1264 {
1265 /* CR 7799: Torn off menus shouldn't be shared, so don't reparent. */
1266 if (torn_has_focus)
1267 menuSTrait->popdown(XtParent(tb), event);
1268 else
1269 menuSTrait->buttonPopdown(XtParent(tb), event);
1270
1271 if (torn_has_focus)
1272 XmProcessTraversal((Widget) tb, XmTRAVERSE_CURRENT);
1273
1274 /* Draw the toggle indicator in case of tear off */
1275 if (tb->toggle.ind_on)
1276 DrawToggle(tb);
1277 else if (tb->toggle.fill_on_select && !Lab_IsPixmap(tb))
1278 DrawToggleLabel(tb);
1279
1280 if (Lab_IsPixmap(tb) || Lab_IsPixmapAndText(tb))
1281 SetAndDisplayPixmap( tb, event, NULL);
1282 }
1283 else
1284 {
1285 if (tb->toggle.ind_on)
1286 DrawToggle(tb);
1287 else
1288 {
1289 if (tb->primitive.shadow_thickness > 0)
1290 DrawToggleShadow (tb);
1291 if (tb->toggle.fill_on_select && !Lab_IsPixmap(tb))
1292 DrawToggleLabel (tb);
1293 }
1294 if (Lab_IsPixmap(tb) || Lab_IsPixmapAndText(tb))
1295 SetAndDisplayPixmap( tb, event, NULL);
1296 }
1297
1298 /* If the parent is menu system able, set the lastSelectToplevel before
1299 * the arm. It's ok if this is recalled later.
1300 */
1301 if (menuSTrait != NULL)
1302 menuSTrait->getLastSelectToplevel(XtParent(tb));
1303
1304 if (tb->toggle.arm_CB && !already_armed)
1305 {
1306 XFlush(XtDisplay(tb));
1307 ToggleButtonCallback(tb, XmCR_ARM, tb->toggle.set, event);
1308 }
1309
1310 if (!no_change)
1311 {
1312 /* UNDOING this fix .... */
1313 /* CR 8904: Notify value_changed before entry so that state is */
1314 /* reported correctly even if the entry callback resets it. */
1315 /* if the parent is menu system able, notify it about the select */
1316
1317 if (menuSTrait != NULL)
1318 {
1319 call_value.reason = XmCR_VALUE_CHANGED;
1320 call_value.event = event;
1321 call_value.set = tb->toggle.set;
1322 menuSTrait->entryCallback(XtParent(tb), (Widget) tb, &call_value);
1323 }
1324
1325 if ((! tb->label.skipCallback) &&
1326 (tb->toggle.value_changed_CB))
1327 {
1328 XFlush(XtDisplay(tb));
1329 ToggleButtonCallback(tb, XmCR_VALUE_CHANGED, tb->toggle.set, event);
1330 }
1331 }
1332
1333 if (tb->toggle.disarm_CB)
1334 {
1335 XFlush(XtDisplay(tb));
1336 ToggleButtonCallback(tb, XmCR_DISARM, tb->toggle.set, event);
1337 }
1338
1339 if (is_menupane)
1340 {
1341 if (torn_has_focus && XtIsSensitive(wid))
1342 {
1343 tb->toggle.Armed = TRUE;
1344 if (tb->toggle.arm_CB)
1345 {
1346 XFlush(XtDisplay(tb));
1347 ToggleButtonCallback(tb, XmCR_ARM, tb->toggle.set, event);
1348 }
1349 }
1350 else if (menuSTrait != NULL)
1351 {
1352 menuSTrait->reparentToTearOffShell(XtParent(tb), event);
1353 TB_FixTearoff(tb);
1354 }
1355 }
1356 }
1357
1358 /************************************************************************
1359 *
1360 * BtnDown
1361 * This function processes a button down occuring on the togglebutton
1362 * when it is in a popup, pulldown, or option menu.
1363 * Popdown the posted menu.
1364 * Turn parent's traversal off.
1365 * Mark the togglebutton as armed (i.e. active).
1366 * The callbacks for XmNarmCallback are called.
1367 *
1368 ************************************************************************/
1369 /* ARGSUSED */
1370 static void
BtnDown(Widget wid,XEvent * event,String * params,Cardinal * num_params)1371 BtnDown(
1372 Widget wid,
1373 XEvent *event,
1374 String *params,
1375 Cardinal *num_params )
1376 {
1377 XmToggleButtonWidget tb = (XmToggleButtonWidget) wid ;
1378 Boolean validButton = False;
1379 Boolean already_armed;
1380 ShellWidget popup;
1381 XmMenuSystemTrait menuSTrait;
1382
1383 menuSTrait = (XmMenuSystemTrait)
1384 XmeTraitGet((XtPointer) XtClass(XtParent(tb)), XmQTmenuSystem);
1385
1386 if (menuSTrait == NULL) return;
1387
1388 /* Support menu replay, free server input queue until next button event */
1389 XAllowEvents(XtDisplay(tb), SyncPointer, CurrentTime);
1390
1391 already_armed = tb->toggle.Armed;
1392
1393 tb->toggle.Armed = TRUE;
1394
1395 if (event && (event->type == ButtonPress))
1396 {
1397 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid));
1398 Boolean etched_in = dpy->display.enable_etched_in_menu;
1399
1400 if ((etched_in) &&
1401 ((tb->toggle.ind_on) ||
1402 (!(tb->toggle.ind_on) && !(tb->toggle.fill_on_select))))
1403 {
1404 DrawEtchedInMenu(tb);
1405 if (tb->toggle.ind_on)
1406 DrawToggle(tb);
1407 }
1408
1409 validButton = menuSTrait->verifyButton(XtParent(tb), event);
1410 }
1411
1412 if (!validButton)
1413 return;
1414
1415 _XmSetInDragMode((Widget)tb, True);
1416
1417 /* Popdown other popups that may be up */
1418 if (!(popup = (ShellWidget)_XmGetRC_PopupPosted(XtParent(tb))))
1419 {
1420 if (!XmIsMenuShell(XtParent(XtParent(tb))))
1421 {
1422 /* In case tear off not armed and no grabs in place, do it now.
1423 * Ok if already armed and grabbed - nothing done.
1424 */
1425 menuSTrait->tearOffArm(XtParent(tb));
1426 }
1427 }
1428
1429 if (popup)
1430 {
1431 /* Widget w; */
1432
1433 if (popup->shell.popped_up)
1434 menuSTrait->popdownEveryone((Widget) popup, event);
1435
1436 /* If the active_child is a cascade (highlighted), then unhighlight it.*/
1437 /*
1438 * w = ((XmManagerWidget)XtParent(tb))->manager.active_child;
1439 * if (w && (XmIsCascadeButton(w) || XmIsCascadeButtonGadget(w)))
1440 * XmCascadeButtonHighlight (w, FALSE);
1441 */
1442 }
1443
1444 /* Set focus to this button. This must follow the possible
1445 * unhighlighting of the CascadeButton else it'll screw up active_child.
1446 */
1447 (void)XmProcessTraversal( (Widget) tb, XmTRAVERSE_CURRENT);
1448 /* get the location cursor - get consistent with Gadgets */
1449
1450 if (tb->toggle.arm_CB && !already_armed)
1451 {
1452 XFlush (XtDisplay (tb));
1453
1454 ToggleButtonCallback(tb, XmCR_ARM, tb->toggle.set, event);
1455 }
1456
1457 _XmRecordEvent(event);
1458 }
1459
1460 /************************************************************************
1461 *
1462 * BtnUp
1463 * This function processes a button up occuring on the togglebutton
1464 * when it is in a popup, pulldown, or option menu.
1465 * Mark the togglebutton as unarmed (i.e. inactive).
1466 * The callbacks for XmNvalueChangedCallback are called.
1467 * The callbacks for XmNdisarmCallback are called.
1468 *
1469 ************************************************************************/
1470 /* ARGSUSED */
1471 static void
BtnUp(Widget wid,XEvent * event,String * params,Cardinal * num_params)1472 BtnUp(
1473 Widget wid,
1474 XEvent *event,
1475 String *params,
1476 Cardinal *num_params )
1477 {
1478 XmToggleButtonWidget tb = (XmToggleButtonWidget) wid ;
1479 XmToggleButtonCallbackStruct call_value;
1480 Boolean validButton = False;
1481 Boolean popped_up;
1482 Boolean is_menupane = Lab_IsMenupane(tb);
1483 Widget shell = XtParent(XtParent(tb));
1484 XmMenuSystemTrait menuSTrait;
1485
1486 menuSTrait = (XmMenuSystemTrait)
1487 XmeTraitGet((XtPointer) XtClass(XtParent(tb)), XmQTmenuSystem);
1488
1489 if (menuSTrait == NULL) return;
1490
1491 if (event && (event->type == ButtonRelease))
1492 validButton = menuSTrait->verifyButton(XtParent(tb), event);
1493
1494 if (!validButton || (tb->toggle.Armed == FALSE))
1495 return;
1496
1497 tb->toggle.Armed = FALSE;
1498
1499 if (is_menupane && !XmIsMenuShell(shell))
1500 popped_up = menuSTrait->popdown((Widget) tb, event);
1501 else
1502 popped_up = menuSTrait->buttonPopdown((Widget) tb, event);
1503
1504 _XmRecordEvent(event);
1505
1506 if (popped_up)
1507 return;
1508
1509 /* Check to see if BtnUp is inside the widget */
1510 /* CR 9181: Consider clipping when testing visibility. */
1511 if ((event->xany.type == ButtonPress || event->xany.type == ButtonRelease) &&
1512 _XmGetPointVisibility(wid, event->xbutton.x_root, event->xbutton.y_root))
1513 {
1514 if (tb->toggle.toggle_mode == XmTOGGLE_INDETERMINATE)
1515 {
1516 NextState(&tb->toggle.visual_set);
1517 NextState(&tb->toggle.set);
1518 }
1519 else
1520 {
1521 tb->toggle.set = (tb->toggle.set == XmSET)? XmUNSET : XmSET;
1522 IsOn(tb) = tb->toggle.set;
1523 }
1524
1525 /* UNDOING this fix ... */
1526 /* CR 8904: Notify value_changed before entry so that state is */
1527 /* reported correctly even if the entry callback resets it. */
1528 /* if the parent is menu system able, notify it about the select */
1529 if (menuSTrait != NULL)
1530 {
1531 call_value.reason = XmCR_VALUE_CHANGED;
1532 call_value.event = event;
1533 call_value.set = tb->toggle.set;
1534 menuSTrait->entryCallback(XtParent(tb), (Widget) tb, &call_value);
1535 }
1536
1537 if ((! tb->label.skipCallback) &&
1538 (tb->toggle.value_changed_CB))
1539 {
1540 XFlush(XtDisplay(tb));
1541 ToggleButtonCallback(tb, XmCR_VALUE_CHANGED, tb->toggle.set, event);
1542 }
1543
1544 if (tb->toggle.disarm_CB)
1545 ToggleButtonCallback(tb, XmCR_DISARM, tb->toggle.set, event);
1546
1547 if (is_menupane)
1548 {
1549 if (!XmIsMenuShell(shell))
1550 {
1551 if (XtIsSensitive((Widget)tb))
1552 {
1553 tb->toggle.Armed = TRUE;
1554
1555 if (tb->toggle.ind_on)
1556 DrawToggle(tb);
1557 else if (tb->toggle.fill_on_select && !Lab_IsPixmap(tb))
1558 DrawToggleLabel(tb);
1559
1560 if (Lab_IsPixmap(tb) || Lab_IsPixmapAndText(tb))
1561 SetAndDisplayPixmap( tb, event, NULL);
1562
1563 if (tb->toggle.arm_CB)
1564 {
1565 XFlush(XtDisplay(tb));
1566 ToggleButtonCallback(tb, XmCR_ARM, tb->toggle.set, event);
1567 }
1568 }
1569 }
1570 else
1571 menuSTrait->reparentToTearOffShell(XtParent(tb), event);
1572 }
1573 }
1574
1575 _XmSetInDragMode((Widget)tb, False);
1576
1577 /* For the benefit of tear off menus, we must set the focus item
1578 * to this button. In normal menus, this would not be a problem
1579 * because the focus is cleared when the menu is unposted.
1580 */
1581 if (!XmIsMenuShell(shell))
1582 XmProcessTraversal((Widget) tb, XmTRAVERSE_CURRENT);
1583 TB_FixTearoff(tb);
1584 }
1585
1586 /************************************************************************
1587 *
1588 * GetUnselectGC
1589 * Get the graphics context to be used to fill the interior of
1590 * a square or diamond when unselected.
1591 *
1592 ************************************************************************/
1593 static void
GetUnselectGC(XmToggleButtonWidget tw)1594 GetUnselectGC(
1595 XmToggleButtonWidget tw )
1596 {
1597 XGCValues values;
1598 XtGCMask valueMask;
1599
1600 valueMask = GCForeground | GCBackground | GCFillStyle | GCGraphicsExposures;
1601 values.foreground = tw->toggle.unselect_color;
1602 values.background = tw->core.background_pixel;
1603 values.fill_style = FillSolid;
1604 values.graphics_exposures = FALSE;
1605
1606 tw->toggle.unselect_GC = XtGetGC((Widget) tw, valueMask, &values);
1607 }
1608
1609 /************************************************************************
1610 *
1611 * GetGC
1612 * Get the graphics context to be used to fill the interior of
1613 * a square or diamond when selected, and the arm GC used in a
1614 * menu if enableEtchedInMenu is True.
1615 *
1616 ************************************************************************/
1617
1618 static void
GetGC(XmToggleButtonWidget tw)1619 GetGC(
1620 XmToggleButtonWidget tw )
1621 {
1622 XGCValues values;
1623 XtGCMask valueMask;
1624 XFontStruct *fs = (XFontStruct *) NULL;
1625 Pixel sel_color, select_pixel;
1626 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(tw));
1627 Boolean etched_in = dpy->display.enable_etched_in_menu;
1628
1629 /* Differentiate background and select colors on monochrome displays or
1630 ** others on which we have indistinguishable colors. */
1631 if ((DefaultDepthOfScreen(XtScreen(tw)) == 1) ||
1632 (tw->core.background_pixel == tw->toggle.select_color))
1633 sel_color = tw->primitive.foreground;
1634 else
1635 sel_color = tw->toggle.select_color;
1636
1637 valueMask = 0;
1638 valueMask |= GCForeground, values.foreground = sel_color;
1639 valueMask |= GCBackground, values.background = tw->core.background_pixel;
1640 valueMask |= GCFillStyle, values.fill_style = FillSolid;
1641 valueMask |= GCGraphicsExposures, values.graphics_exposures = FALSE;
1642
1643 tw->toggle.select_GC = XtAllocateGC((Widget)tw, 0, valueMask, &values, 0, 0);
1644
1645 /* When foreground and select colors coincide, this GC is used
1646 * by XmLabel to draw the text. It requires a font to pacify
1647 * the XmString draw functions.
1648 */
1649 valueMask = 0;
1650
1651 if (XmeRenderTableGetDefaultFont(tw->label.font, &fs))
1652 valueMask |= GCFont, values.font = fs->fid;
1653
1654 valueMask |= GCForeground, values.foreground = tw->core.background_pixel;
1655 valueMask |= GCBackground, values.background = tw->primitive.foreground;
1656 valueMask |= GCFillStyle, values.fill_style = FillSolid;
1657 valueMask |= GCGraphicsExposures, values.graphics_exposures = FALSE;
1658 valueMask |= GCLineWidth, values.line_width = 1;
1659
1660 tw->toggle.background_gc = XtGetGC((Widget) tw, valueMask, &values);
1661
1662 valueMask = 0;
1663 valueMask |= GCFillStyle, values.fill_style = FillOpaqueStippled;
1664 valueMask |= GCGraphicsExposures, values.graphics_exposures = FALSE;
1665 valueMask |= GCStipple, values.stipple =
1666 XmGetPixmapByDepth(XtScreen((Widget)(tw)), XmS50_foreground, 1, 0, 1);
1667 valueMask |= GCLineWidth, values.line_width = 1;
1668
1669 tw->toggle.indeterminate_GC = XtAllocateGC((Widget)tw, 0, valueMask, &values,
1670 GCForeground | GCBackground, 0);
1671
1672 /* The valueMask and values are inherited from above. */
1673 valueMask &= ~GCLineWidth;
1674 valueMask |= GCForeground, values.foreground = tw->core.background_pixel;
1675 valueMask |= GCBackground, values.background = tw->primitive.foreground;
1676
1677 tw->toggle.indeterminate_box_GC = XtGetGC((Widget) tw, valueMask, &values);
1678
1679 /* Create the ArmGC for filling in background if we are in a menu
1680 and enableEtchedInMenu is True. */
1681 if ((Lab_IsMenupane(tw)) && etched_in) {
1682 XmGetColors(XtScreen(tw), tw->core.colormap, tw->core.background_pixel,
1683 NULL, NULL, NULL, &select_pixel);
1684
1685 valueMask = 0;
1686 valueMask |= GCForeground, values.foreground = select_pixel;
1687 valueMask |= GCBackground, values.background = tw->primitive.foreground;
1688 if (fs != NULL)
1689 valueMask |= GCFont, values.font = fs->fid;
1690 valueMask |= GCGraphicsExposures, values.graphics_exposures = FALSE;
1691
1692 tw->toggle.arm_GC = XtGetGC((Widget) tw, valueMask, &values);
1693 }
1694 }
1695
1696
1697
1698 /*************************************<->*************************************
1699 *
1700 * Initialize
1701 *
1702 *************************************<->***********************************/
1703
1704 /*ARGSUSED*/
1705 static void
Initialize(Widget rw,Widget nw,ArgList args,Cardinal * num_args)1706 Initialize(
1707 Widget rw,
1708 Widget nw,
1709 ArgList args,
1710 Cardinal *num_args )
1711 {
1712 XmToggleButtonWidget request = (XmToggleButtonWidget) rw ;
1713 XmToggleButtonWidget new_w = (XmToggleButtonWidget) nw ;
1714 XtWidgetProc resize;
1715
1716
1717 new_w->toggle.Armed = FALSE;
1718
1719 /* if menuProcs is not set up yet, try again */
1720 _XmProcessLock();
1721 resize = xmLabelClassRec.core_class.resize;
1722 if (xmLabelClassRec.label_class.menuProcs == (XmMenuProc)NULL)
1723 xmLabelClassRec.label_class.menuProcs = (XmMenuProc)_XmGetMenuProcContext();
1724 _XmProcessUnlock();
1725
1726 if (Lab_IsMenupane(new_w))
1727 {
1728 /* If the shadow thickness hasn't been set yet, inherit it
1729 from the menu parent, instead of a hard-coded 2, as before.
1730 The only draw back is that is the parent has also 0, then
1731 the toggle shadow is 0, which is not very good in a menu,
1732 but at least consistent with the other buttons */
1733 if (new_w->primitive.shadow_thickness <= 0) {
1734 Dimension parent_st ;
1735
1736 XtVaGetValues(XtParent(nw), XmNshadowThickness, &parent_st, NULL);
1737 new_w->primitive.shadow_thickness = parent_st;
1738 }
1739
1740 if (new_w->toggle.visible == XmINVALID_BOOLEAN)
1741 new_w->toggle.visible = FALSE;
1742
1743 new_w->primitive.traversal_on = TRUE;
1744 }
1745 else if (new_w->toggle.visible == XmINVALID_BOOLEAN)
1746 new_w->toggle.visible = TRUE;
1747
1748
1749 /*
1750 * If the indicatorType has not been set, then
1751 * find out if radio behavior is set for RowColumn parents and
1752 * then set indicatorType. If radio behavior is true, default to
1753 * one of many, else default to n of many.
1754 */
1755 if ((new_w->toggle.ind_type == XmINVALID_TYPE) ||
1756 !XmRepTypeValidValue (XmRID_INDICATOR_TYPE,
1757 new_w->toggle.ind_type, (Widget) new_w))
1758 {
1759 Boolean radio = FALSE;
1760
1761 if (XmIsRowColumn(XtParent(new_w)))
1762 {
1763 XtVaGetValues(XtParent(new_w),
1764 XmNradioBehavior, &radio,
1765 NULL);
1766 }
1767
1768 if (radio)
1769 new_w->toggle.ind_type = XmONE_OF_MANY;
1770 else
1771 new_w->toggle.ind_type = XmN_OF_MANY;
1772 }
1773
1774 /*
1775 * This resource defaults to true if an indicator box is drawn.
1776 */
1777 if (new_w->toggle.fill_on_select == XmINVALID_BOOLEAN)
1778 {
1779 if (DRAWBOX(NormalizeIndOn(new_w)))
1780 new_w->toggle.fill_on_select = True;
1781 else if (IsOneOfMany(new_w->toggle.ind_type) &&
1782 new_w->toggle.ind_on)
1783 new_w->toggle.fill_on_select = True;
1784 else
1785 new_w->toggle.fill_on_select = False;
1786 }
1787
1788 /* Tristate buttons ain't allowed in one-of-many land. */
1789 if (IsOneOfMany(new_w->toggle.ind_type))
1790 new_w->toggle.toggle_mode = XmTOGGLE_BOOLEAN;
1791
1792
1793 /* If necessary use the On pixmaps in place of the Indeterminate ones. */
1794 if (IsNull(PixmapInd(new_w)) && !IsNull(PixmapOn(new_w)))
1795 PixmapInd(new_w) = PixmapOn(new_w);
1796 if (IsNull(PixmapInsenInd(new_w)) && !IsNull(PixmapInsenOn(new_w)))
1797 PixmapInsenInd(new_w) = PixmapInsenOn(new_w);
1798
1799 /* If necessary use PixmapOn in place of PixmapOff. */
1800 if (IsNull(PixmapOff(new_w)) && !IsNull(PixmapOn(new_w)))
1801 {
1802 PixmapOff(new_w) = PixmapOn(new_w);
1803 if (request->core.width == 0)
1804 new_w->core.width = 0;
1805 if (request->core.height == 0)
1806 new_w->core.height = 0;
1807
1808 _XmCalcLabelDimensions((Widget) new_w);
1809 (* resize)( (Widget) new_w);
1810 }
1811
1812 /* If necessary use PixmapInsenOn in place of PixmapInsenOff. */
1813 if (IsNull(PixmapInsenOff(new_w)) && !IsNull(PixmapInsenOn(new_w)))
1814 {
1815 PixmapInsenOff(new_w) = PixmapInsenOn(new_w);
1816 if (request->core.width == 0)
1817 new_w->core.width = 0;
1818 if (request->core.height == 0)
1819 new_w->core.height = 0;
1820
1821 _XmCalcLabelDimensions((Widget) new_w);
1822 (* resize)( (Widget) new_w);
1823 }
1824
1825
1826 /* BEGIN OSF Fix pir 1778 */
1827 if (Lab_IsPixmap(new_w) &&
1828 (!IsNull(PixmapOff(new_w)) || !IsNull(PixmapInsenOff(new_w)) ||
1829 !IsNull(PixmapOn(new_w)) || !IsNull(PixmapInsenOn(new_w)) ||
1830 !IsNull(PixmapInd(new_w)) || !IsNull(PixmapInsenInd(new_w))))
1831 {
1832 if (request->core.width == 0)
1833 new_w->core.width = 0;
1834 if (request->core.height == 0)
1835 new_w->core.height = 0;
1836 SetToggleSize(new_w);
1837 }
1838 /* END OSF Fix pir 1778 */
1839
1840 if (new_w->toggle.indicator_dim == XmINVALID_DIMENSION) {
1841 if (new_w->toggle.ind_on)
1842 {
1843 /* Determine how high the toggle indicator should be. */
1844 if (Lab_IsPixmap(new_w) || Lab_IsPixmapAndText(new_w))
1845 {
1846 /* Set indicator size proportional to size of pixmap. */
1847 if ( !IsNull(PixmapOn(new_w)) || !IsNull(PixmapInsenOn(new_w)) ||
1848 !IsNull(PixmapOff(new_w)) || !IsNull(PixmapInsenOff(new_w)) ||
1849 !IsNull(PixmapInd(new_w)) || !IsNull(PixmapInsenInd(new_w)))
1850 if (new_w->label.TextRect.height < 13)
1851 new_w->toggle.indicator_dim = new_w->label.TextRect.height;
1852 else
1853 new_w->toggle.indicator_dim =
1854 13 + (new_w->label.TextRect.height/13);
1855 else
1856 new_w->toggle.indicator_dim = XmDEFAULT_INDICATOR_DIM;
1857 }
1858 else
1859 {
1860 /* Set indicator size proportional to size of font. */
1861 Dimension height;
1862 int line_count;
1863
1864 height = XmStringHeight (new_w->label.font, new_w->label._label);
1865 if ((line_count = XmStringLineCount (new_w->label._label)) < 1)
1866 line_count = 1;
1867
1868 /* Shiz recommends toggles in menus have smaller indicators */
1869 if (Lab_IsMenupane(new_w))
1870 new_w->toggle.indicator_dim =
1871 MAX(XmDEFAULT_INDICATOR_DIM,
1872 (height / ((Dimension)line_count))*2/3);
1873 else
1874 new_w->toggle.indicator_dim =
1875 MAX(XmDEFAULT_INDICATOR_DIM, height / ((Dimension)line_count));
1876 }
1877 } else {
1878 new_w->toggle.indicator_dim = 0;
1879 }
1880
1881 new_w->toggle.indicator_set = FALSE;
1882 } else {
1883 new_w->toggle.indicator_set = TRUE;
1884 }
1885
1886 /* CR 2337: Maintain original margin values. */
1887 new_w->toggle.ind_left_delta = 0;
1888 new_w->toggle.ind_right_delta = 0;
1889 new_w->toggle.ind_top_delta = 0;
1890 new_w->toggle.ind_bottom_delta = 0;
1891
1892 if (new_w->toggle.ind_on)
1893 {
1894 /*
1895 * Enlarge the text rectangle if needed to accomodate the size of
1896 * indicator button. Adjust the dimensions of superclass Label-Gadget
1897 * so that the toggle-button may be accommodated in it.
1898 */
1899 int maxIndicatorSize;
1900 int delta;
1901 int boxSize;
1902
1903 /* BEGIN OSF Fix pir 2480 */
1904 if (! Lab_IsMenupane(new_w))
1905 maxIndicatorSize = new_w->toggle.indicator_dim + 2*Xm3D_ENHANCE_PIXEL;
1906 else
1907 maxIndicatorSize = new_w->toggle.indicator_dim;
1908 /* END OSF Fix pir 2480 */
1909
1910 boxSize = ((int) new_w->label.TextRect.height +
1911 (int) new_w->label.margin_top +
1912 (int) new_w->label.margin_bottom);
1913
1914 if (maxIndicatorSize > boxSize)
1915 {
1916 delta = (maxIndicatorSize - boxSize) / 2;
1917 new_w->toggle.ind_top_delta = delta;
1918 new_w->label.margin_top += new_w->toggle.ind_top_delta;
1919 new_w->toggle.ind_bottom_delta = delta;
1920 new_w->label.margin_bottom += new_w->toggle.ind_bottom_delta;
1921 }
1922
1923 /* CR 2337: Make room for toggle indicator and spacing */
1924 if (LayoutIsRtoLP(new_w))
1925 {
1926 delta = (new_w->toggle.indicator_dim + new_w->toggle.spacing -
1927 new_w->label.margin_right);
1928 if (delta > 0)
1929 {
1930 new_w->toggle.ind_right_delta = delta;
1931 new_w->label.margin_right += delta;
1932 }
1933 }
1934 else
1935 {
1936 delta = (new_w->toggle.indicator_dim + new_w->toggle.spacing -
1937 new_w->label.margin_left);
1938 if (delta > 0)
1939 {
1940 new_w->toggle.ind_left_delta = delta;
1941 new_w->label.margin_left += delta;
1942 }
1943 }
1944 }
1945
1946 if (request->core.width == 0)
1947 {
1948 new_w->core.width = new_w->label.TextRect.width +
1949 2 * new_w->label.margin_width + new_w->label.margin_right +
1950 new_w->label.margin_left +
1951 2 * (new_w->primitive.highlight_thickness +
1952 new_w->primitive.shadow_thickness);
1953
1954 if (new_w->core.width == 0)
1955 new_w->core.width = 1;
1956
1957 if ((new_w->label._acc_text != NULL) && (new_w->toggle.ind_on))
1958 {
1959 if (LayoutIsRtoLP(new_w))
1960 {
1961 new_w->label.acc_TextRect.x = new_w->primitive.highlight_thickness +
1962 new_w->primitive.shadow_thickness + new_w->label.margin_width;
1963 }
1964 else
1965 {
1966 new_w->label.acc_TextRect.x = new_w->core.width -
1967 new_w->primitive.highlight_thickness -
1968 new_w->primitive.shadow_thickness - new_w->label.margin_width -
1969 new_w->label.margin_right + LABEL_ACC_PAD;
1970 }
1971 }
1972 }
1973
1974 if (request->core.height == 0)
1975 new_w->core.height =
1976 MAX(new_w->toggle.indicator_dim,
1977 new_w->label.TextRect.height + 2 * new_w->label.margin_height +
1978 new_w->label.margin_top + new_w->label.margin_bottom) +
1979 2 * (new_w->primitive.highlight_thickness +
1980 new_w->primitive.shadow_thickness);
1981
1982 new_w->label.TextRect.y = (short) new_w->primitive.highlight_thickness
1983 + new_w->primitive.shadow_thickness + new_w->label.margin_height +
1984 new_w->label.margin_top +
1985 ((new_w->core.height - new_w->label.margin_top
1986 - new_w->label.margin_bottom
1987 - (2 * (new_w->label.margin_height
1988 + new_w->primitive.highlight_thickness
1989 + new_w->primitive.shadow_thickness))
1990 - new_w->label.TextRect.height) / 2);
1991
1992 if (new_w->core.height == 0)
1993 new_w->core.height = 1;
1994
1995 new_w->toggle.visual_set = new_w->toggle.set;
1996
1997 /* Display as set if XmNset is TRUE when the toggle first comes up. */
1998 if (XmSET == new_w->toggle.set)
1999 IsOn(new_w) = XmSET;
2000 else
2001 IsOn(new_w) = XmUNSET;
2002
2003 {
2004 XtWidgetProc resize;
2005 _XmProcessLock();
2006 resize = new_w->core.widget_class->core_class.resize;
2007 _XmProcessUnlock();
2008
2009 (* (resize)) ((Widget) new_w);
2010 }
2011
2012 /* unselect same as background unless set. */
2013 if (new_w->toggle.unselect_color == XmINVALID_PIXEL)
2014 new_w->toggle.unselect_color = new_w->core.background_pixel;
2015
2016 /* Deal with selectColor */
2017 new_w->toggle.reversed_select =
2018 (new_w->toggle.select_color == XmREVERSED_GROUND_COLORS);
2019 if (new_w->toggle.select_color == XmDEFAULT_SELECT_COLOR)
2020 {
2021 /* CR 9923: Copy all bytes of the resulting pixel. */
2022 XrmValue value;
2023 _XmSelectColorDefault((Widget)new_w,
2024 XtOffsetOf(XmToggleButtonRec,
2025 toggle.select_color),
2026 &value);
2027 assert(value.size == sizeof(Pixel));
2028 new_w->toggle.select_color = *((Pixel*) value.addr);
2029 }
2030 else if (new_w->toggle.select_color == XmREVERSED_GROUND_COLORS)
2031 {
2032 new_w->toggle.select_color = new_w->primitive.foreground;
2033 }
2034 else if (new_w->toggle.select_color == XmHIGHLIGHT_COLOR)
2035 {
2036 new_w->toggle.select_color = new_w->primitive.highlight_color;
2037 }
2038
2039 GetGC (new_w);
2040 GetUnselectGC(new_w);
2041 }
2042
2043 /************************************************************************
2044 *
2045 * Destroy
2046 * Free toggleButton's graphic context.
2047 *
2048 ************************************************************************/
2049 static void
Destroy(Widget wid)2050 Destroy(
2051 Widget wid )
2052 {
2053 XmToggleButtonWidget tw = (XmToggleButtonWidget) wid ;
2054 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid));
2055 Boolean etched_in = dpy->display.enable_etched_in_menu;
2056
2057 XtReleaseGC ((Widget) tw, tw->toggle.select_GC);
2058 XtReleaseGC ((Widget) tw, tw->toggle.background_gc);
2059 XtReleaseGC ((Widget) tw, tw->toggle.unselect_GC);
2060 XtReleaseGC ((Widget) tw, tw->toggle.indeterminate_GC);
2061 XtReleaseGC ((Widget) tw, tw->toggle.indeterminate_box_GC);
2062 if (Lab_IsMenupane(tw) && etched_in)
2063 XtReleaseGC ((Widget) tw, tw->toggle.arm_GC);
2064 }
2065
2066 static void
DrawBox(XmToggleButtonWidget w,GC top_gc,GC bot_gc,GC fillgc,int x,int y,int edge,Dimension margin)2067 DrawBox(XmToggleButtonWidget w,
2068 GC top_gc, GC bot_gc, GC fillgc, int x, int y, int edge,
2069 Dimension margin)
2070 {
2071 int shadow = w->toggle.detail_shadow_thickness;
2072
2073 XmeDrawShadows(XtDisplay ((Widget) w),
2074 XtWindow ((Widget) w),
2075 top_gc,
2076 bot_gc,
2077 x, y, edge, edge,
2078 shadow, XmSHADOW_OUT);
2079
2080 /* Don't fill the background on mono screens if we're going to */
2081 /* draw a glyph */
2082
2083 if ((DefaultDepthOfScreen(XtScreen(w)) == 1) && DRAWGLYPH(NormalizeIndOn(w)))
2084 return;
2085
2086 shadow += margin;
2087
2088 if (edge > (shadow * 2))
2089 XFillRectangle (XtDisplay ((Widget) w),
2090 XtWindow ((Widget) w),
2091 fillgc,
2092 x + shadow,
2093 y + shadow,
2094 edge - (shadow * 2),
2095 edge - (shadow * 2));
2096 }
2097
2098 /*************************************<->*************************************
2099 *
2100 * DrawToggle(w)
2101 * Depending on the state of this widget, draw the Toggle.
2102 * That is draw the True/False indicator next to the label.
2103 *
2104 *************************************<->***********************************/
2105 static void
DrawToggle(XmToggleButtonWidget w)2106 DrawToggle
2107 (XmToggleButtonWidget w )
2108 {
2109 int x, y, edge;
2110 Dimension margin;
2111 XGCValues values;
2112 Display *dpy = XtDisplay((Widget) w);
2113 Drawable drawable = XtWindow((Widget) w);
2114 XmDisplay dpyxm = (XmDisplay) XmGetXmDisplay(XtDisplay(w));
2115 Boolean etched_in = dpyxm->display.enable_etched_in_menu;
2116
2117 /* Get size of indicator i.e. bounding box */
2118 if (Lab_IsPixmap(w) || XmStringEmpty(w->label._label))
2119 edge = w->toggle.indicator_dim;
2120 else
2121 edge = MIN((int)w->toggle.indicator_dim,
2122 MAX(0,
2123 ((int)w->core.height - 2*(w->primitive.highlight_thickness +
2124 w->primitive.shadow_thickness +
2125 (int)w->label.margin_height) +
2126 w->label.margin_top + w->label.margin_bottom)));
2127
2128 /* Touch up the appearance of filled background. */
2129 if ((DefaultDepthOfScreen(XtScreen(w)) > 1) &&
2130 (w->primitive.top_shadow_color != w->toggle.select_color) &&
2131 (w->primitive.bottom_shadow_color != w->toggle.select_color))
2132 margin = 0;
2133 else
2134 margin = 1;
2135
2136 if (LayoutIsRtoLP(w))
2137 x = (int)w->core.width - w->primitive.highlight_thickness -
2138 w->primitive.shadow_thickness - w->label.margin_width -
2139 w->toggle.indicator_dim;
2140 else
2141 x = w->primitive.highlight_thickness + w->primitive.shadow_thickness +
2142 w->label.margin_width;
2143
2144 if (Lab_IsPixmap(w) || XmStringEmpty(w->label._label))
2145 y = (int)((w->core.height - w->toggle.indicator_dim))/2;
2146 else
2147 {
2148 /* Center indicator vertically next to the first line of text. */
2149 int fudge = Xm3D_ENHANCE_PIXEL;
2150 Dimension text_height;
2151 int line_count, height_diff;
2152
2153 text_height = XmStringHeight(w->label.font, w->label._label);
2154 if ((line_count = XmStringLineCount(w->label._label)) < 1)
2155 line_count = 1;
2156
2157 height_diff = ((int)text_height / line_count) -
2158 (int)w->toggle.indicator_dim;
2159 if (height_diff < 0)
2160 height_diff = 0;
2161
2162 y = w->label.TextRect.y + (height_diff / 2);
2163
2164 /* CR 2337: Keep large indicators inside the toggle. */
2165 /* Is this definition of fudge right??? */
2166 if (w->toggle.ind_top_delta > fudge)
2167 y -= (w->toggle.ind_top_delta - fudge);
2168 }
2169
2170 if (w->toggle.visible || (w->toggle.visual_set != XmUNSET))
2171 {
2172 /* The toggle indicator should be visible. */
2173 GC top_gc, bot_gc, fill_gc, glyph_gc;
2174 unsigned char normal_ind_on = NormalizeIndOn(w);
2175
2176 switch (w->toggle.visual_set)
2177 {
2178 case XmUNSET:
2179 top_gc = w->primitive.top_shadow_GC;
2180 bot_gc = w->primitive.bottom_shadow_GC;
2181 /* use the arm GC in a menu if armed and enableEtchedInMenu is set */
2182 if (Lab_IsMenupane(w) && etched_in && w->toggle.Armed)
2183 fill_gc = (w->toggle.fill_on_select ?
2184 w->toggle.unselect_GC : w->toggle.arm_GC);
2185 else
2186 fill_gc = (w->toggle.fill_on_select ?
2187 w->toggle.unselect_GC : w->toggle.background_gc);
2188 glyph_gc = None;
2189 break;
2190
2191 case XmSET:
2192 top_gc = w->primitive.bottom_shadow_GC;
2193 bot_gc = w->primitive.top_shadow_GC;
2194 /* use the arm GC in a menu if armed and enableEtchedInMenu is set */
2195 if (Lab_IsMenupane(w) && etched_in && w->toggle.Armed)
2196 fill_gc = (w->toggle.fill_on_select ?
2197 w->toggle.select_GC : w->toggle.arm_GC);
2198 else
2199 fill_gc = (w->toggle.fill_on_select ?
2200 w->toggle.select_GC : w->toggle.background_gc);
2201 glyph_gc = ((w->toggle.reversed_select && DRAWBOX(normal_ind_on)) ?
2202 w->toggle.background_gc : w->label.normal_GC);
2203
2204 /* CR 9791: Label's normal_gc has a dynamic clip_mask. */
2205 if (glyph_gc == w->label.normal_GC)
2206 XSetClipMask(dpy, glyph_gc, None);
2207 break;
2208
2209 case XmINDETERMINATE:
2210 top_gc = bot_gc = w->toggle.indeterminate_box_GC;
2211 /* use the arm GC in a menu if armed and enableEtchedInMenu is set */
2212 if (Lab_IsMenupane(w) && etched_in && w->toggle.Armed)
2213 fill_gc = (w->toggle.fill_on_select ?
2214 w->toggle.indeterminate_GC : w->toggle.arm_GC);
2215 else
2216 fill_gc = (w->toggle.fill_on_select ?
2217 w->toggle.indeterminate_GC : w->toggle.background_gc);
2218 glyph_gc = w->toggle.indeterminate_GC;
2219 break;
2220
2221 default:
2222 assert(False);
2223 return;
2224 }
2225
2226 switch (NormalizeIndType(w))
2227 {
2228 case XmN_OF_MANY:
2229 {
2230 /* If the toggle indicator is square shaped then adjust the
2231 * indicator width and height, so that it looks proportional
2232 * to a diamond shaped indicator of the same width and height
2233 */
2234 int new_edge;
2235 Dimension box_margin = (DRAWBOX(normal_ind_on) ?
2236 w->toggle.detail_shadow_thickness : 0);
2237
2238 /* Subtract 3 pixels + 10% from the width and height. */
2239 new_edge = edge - 3 - ((edge - 10)/10);
2240
2241 /* Adjust x,y to center the indicator relative to the label */
2242 y = y + ((edge - new_edge) / 2);
2243 x = x + ((edge - new_edge) / 2);
2244 edge = new_edge;
2245
2246 switch(w->toggle.visual_set)
2247 {
2248 case XmUNSET:
2249 if (DRAW3DBOX(normal_ind_on))
2250 DrawBox(w, top_gc, bot_gc, fill_gc, x, y, edge, margin);
2251 else if (DRAWFLATBOX(normal_ind_on))
2252 DrawBox(w, bot_gc, bot_gc, fill_gc, x, y, edge, margin);
2253 else if (edge > 0)
2254 XFillRectangle(dpy, drawable, fill_gc, x, y, edge, edge);
2255 break;
2256
2257 case XmSET:
2258 if (DRAW3DBOX(normal_ind_on))
2259 DrawBox(w, top_gc, bot_gc, fill_gc, x, y, edge, margin);
2260 else if (DRAWFLATBOX(normal_ind_on))
2261 DrawBox(w, top_gc, top_gc, fill_gc, x, y, edge, margin);
2262 else if (edge > 0)
2263 XFillRectangle(dpy, drawable, fill_gc, x, y, edge, edge);
2264
2265 if (!DRAWBOX(normal_ind_on) ||
2266 ((edge - 2 * box_margin) >= MIN_GLYPH_SIZE))
2267 {
2268 if (DRAWCHECK(normal_ind_on))
2269 XmeDrawIndicator(dpy, drawable, glyph_gc, x, y,
2270 edge, edge, box_margin,
2271 normal_ind_on);
2272 else if (DRAWCROSS(normal_ind_on))
2273 XmeDrawIndicator(dpy, drawable, glyph_gc, x, y,
2274 edge, edge, box_margin,
2275 normal_ind_on);
2276 }
2277 break;
2278
2279 case XmINDETERMINATE:
2280 if (w->toggle.fill_on_select)
2281 {
2282 /* Fetch the select_color GetGC() actually used. */
2283 XGetGCValues(dpy, w->toggle.select_GC,
2284 GCForeground, &values);
2285 values.background = values.foreground;
2286 values.foreground = w->toggle.unselect_color;
2287 XChangeGC(dpy, fill_gc,
2288 GCForeground|GCBackground, &values);
2289 }
2290 else if (DRAWBOX(normal_ind_on))
2291 {
2292 /* This GC should have the right values already. */
2293 fill_gc = w->toggle.indeterminate_box_GC;
2294 }
2295
2296 if (DRAWBOX(normal_ind_on))
2297 DrawBox(w, bot_gc, bot_gc, fill_gc, x, y, edge, margin);
2298 else if (edge > 0)
2299 XFillRectangle(dpy, drawable, fill_gc, x, y, edge, edge);
2300
2301 if (w->toggle.reversed_select)
2302 {
2303 values.foreground = w->core.background_pixel;
2304 values.background = w->primitive.foreground;
2305 }
2306 else
2307 {
2308 values.foreground = w->primitive.foreground;
2309 values.background = w->core.background_pixel;
2310 }
2311
2312 if (!DRAWBOX(normal_ind_on) ||
2313 ((edge - 2 * box_margin) >= MIN_GLYPH_SIZE))
2314 {
2315 if (DRAWCHECK(normal_ind_on))
2316 {
2317 XChangeGC(dpy, glyph_gc,
2318 GCForeground|GCBackground, &values);
2319 XmeDrawIndicator(dpy, drawable, glyph_gc, x, y,
2320 edge, edge, box_margin,
2321 normal_ind_on);
2322 }
2323 else if (DRAWCROSS(normal_ind_on))
2324 {
2325 XChangeGC(dpy, glyph_gc,
2326 GCForeground|GCBackground, &values);
2327 XmeDrawIndicator(dpy, drawable, glyph_gc, x, y,
2328 edge, edge, box_margin,
2329 normal_ind_on);
2330 }
2331 }
2332 break;
2333 }
2334 break;
2335 }
2336
2337 case XmONE_OF_MANY:
2338 /* This value should have been normalized away! */
2339 assert(FALSE);
2340
2341 case XmONE_OF_MANY_DIAMOND:
2342 XmeDrawDiamond(dpy, drawable, top_gc, bot_gc, fill_gc, x, y,
2343 edge,edge, w->toggle.detail_shadow_thickness, margin);
2344 break;
2345
2346 case XmONE_OF_MANY_ROUND:
2347 #ifdef FIX_1402
2348 XmeDrawCircle(dpy, drawable, top_gc, bot_gc, fill_gc, x, y,
2349 edge, edge, w->toggle.detail_shadow_thickness, margin);
2350 #else
2351 XmeDrawCircle(dpy, drawable, top_gc, bot_gc, fill_gc, x, y,
2352 edge, edge, w->toggle.detail_shadow_thickness, 1);
2353 #endif
2354 break;
2355 }
2356 }
2357 else
2358 {
2359 /* The toggle indicator should be invisible. */
2360 if (edge > 0)
2361 {
2362 /* use the arm GC in a menu if armed and enableEtchedInMenu is set */
2363 if (Lab_IsMenupane(w) && etched_in && w->toggle.Armed)
2364 XFillRectangle(dpy, drawable, w->toggle.arm_GC,
2365 x, y, edge + 4, edge + 2);
2366 else
2367 XFillRectangle(dpy, drawable, w->toggle.background_gc,
2368 x, y, edge + 4, edge + 2);
2369 }
2370 }
2371 }
2372
2373 /*************************************<->*************************************
2374 *
2375 * BorderHighlight
2376 *
2377 *************************************<->***********************************/
2378 static void
BorderHighlight(Widget wid)2379 BorderHighlight(
2380 Widget wid )
2381 {
2382 XmToggleButtonWidget tb = (XmToggleButtonWidget) wid ;
2383 XEvent * event = NULL;
2384
2385 if (Lab_IsMenupane(tb))
2386 {
2387 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid));
2388 Boolean etched_in = dpy->display.enable_etched_in_menu;
2389 Boolean already_armed = tb->toggle.Armed;
2390
2391 tb->toggle.Armed = True;
2392
2393 if ((etched_in) &&
2394 ((tb->toggle.ind_on) ||
2395 (!(tb->toggle.ind_on) && !(tb->toggle.fill_on_select))))
2396 {
2397 DrawEtchedInMenu(tb);
2398 if (tb->toggle.ind_on)
2399 DrawToggle(tb);
2400 }
2401
2402 XmeDrawShadows (XtDisplay (tb), XtWindow (tb),
2403 tb->primitive.top_shadow_GC,
2404 tb->primitive.bottom_shadow_GC,
2405 tb->primitive.highlight_thickness,
2406 tb->primitive.highlight_thickness,
2407 tb->core.width - 2 * tb->primitive.highlight_thickness,
2408 tb->core.height - 2 * tb->primitive.highlight_thickness,
2409 tb->primitive.shadow_thickness,
2410 etched_in ? XmSHADOW_IN : XmSHADOW_OUT);
2411
2412 if (!already_armed && tb->toggle.arm_CB)
2413 {
2414 XFlush (XtDisplay (tb));
2415 ToggleButtonCallback(tb, XmCR_ARM, tb->toggle.set, event);
2416 }
2417 }
2418 else
2419 {
2420 (*(xmLabelClassRec.primitive_class.border_highlight))((Widget) tb) ;
2421 }
2422 }
2423
2424 /*************************************<->*************************************
2425 *
2426 * BorderUnhighlight
2427 *
2428 *************************************<->***********************************/
2429 static void
BorderUnhighlight(Widget wid)2430 BorderUnhighlight(
2431 Widget wid )
2432 {
2433 XmToggleButtonWidget tb = (XmToggleButtonWidget) wid ;
2434 XEvent * event = NULL;
2435
2436 if (Lab_IsMenupane(tb))
2437 {
2438 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid));
2439 Boolean etched_in = dpy->display.enable_etched_in_menu;
2440 Boolean already_armed = tb->toggle.Armed;
2441
2442 tb -> toggle.Armed = FALSE;
2443
2444 if ((etched_in) &&
2445 ((tb->toggle.ind_on) ||
2446 (!(tb->toggle.ind_on) && !(tb->toggle.fill_on_select))))
2447 {
2448 DrawEtchedInMenu(tb);
2449 if (tb->toggle.ind_on)
2450 DrawToggle(tb);
2451 }
2452
2453 XmeClearBorder (XtDisplay (tb), XtWindow (tb),
2454 tb->primitive.highlight_thickness,
2455 tb->primitive.highlight_thickness,
2456 tb->core.width - 2 * tb->primitive.highlight_thickness,
2457 tb->core.height - 2 * tb->primitive.highlight_thickness,
2458 tb->primitive.shadow_thickness);
2459
2460 if (tb->toggle.Armed && tb->toggle.disarm_CB)
2461 {
2462 XFlush (XtDisplay (tb));
2463 ToggleButtonCallback(tb, XmCR_DISARM, tb->toggle.set, event);
2464 }
2465 }
2466 else
2467 {
2468 (*(xmLabelClassRec.primitive_class.border_unhighlight))((Widget) tb) ;
2469 }
2470 }
2471
2472 /* spb This action does not seem to be used anywhere */
2473 /* Tue Apr 27 17:31:48 1993 */
2474 /*************************************<->*************************************
2475 *
2476 * KeySelect
2477 * If the menu system traversal is enabled, do an activate and disarm
2478 *
2479 *************************************<->***********************************/
2480 /* ARGSUSED */
2481 static void
KeySelect(Widget wid,XEvent * event,String * param,Cardinal * num_param)2482 KeySelect(
2483 Widget wid,
2484 XEvent *event,
2485 String *param,
2486 Cardinal *num_param )
2487 {
2488 XmToggleButtonWidget tb = (XmToggleButtonWidget) wid ;
2489 XmToggleButtonCallbackStruct call_value;
2490 XmMenuSystemTrait menuSTrait;
2491
2492 menuSTrait = (XmMenuSystemTrait)
2493 XmeTraitGet((XtPointer) XtClass(XtParent(tb)), XmQTmenuSystem);
2494
2495 if (menuSTrait == NULL) return;
2496
2497 if (!_XmIsEventUnique(event))
2498 return;
2499
2500 if (!_XmGetInDragMode((Widget)tb))
2501 {
2502 if (tb->toggle.ind_on)
2503 DrawToggle(tb);
2504 else if (tb->toggle.fill_on_select && !Lab_IsPixmap(tb))
2505 DrawToggleLabel(tb);
2506
2507 if (Lab_IsPixmap(tb) || Lab_IsPixmapAndText(tb))
2508 SetAndDisplayPixmap( tb, event, NULL);
2509
2510 tb->toggle.Armed = FALSE;
2511 tb->toggle.set = (tb->toggle.set == TRUE) ? FALSE : TRUE;
2512
2513 if (menuSTrait != NULL)
2514 menuSTrait->buttonPopdown(XtParent(tb), event);
2515
2516 _XmRecordEvent(event);
2517
2518 /* UNDOING this fix ... */
2519 /* CR 8904: Notify value_changed before entry so that state is */
2520 /* reported correctly even if the entry callback resets it. */
2521
2522 /* If the parent is menu system able, notify it about the select. */
2523 if (menuSTrait != NULL)
2524 {
2525 call_value.reason = XmCR_VALUE_CHANGED;
2526 call_value.event = event;
2527 call_value.set = tb->toggle.set;
2528 menuSTrait->entryCallback(XtParent(tb), (Widget) tb, &call_value);
2529 }
2530
2531 if (menuSTrait != NULL)
2532 menuSTrait->reparentToTearOffShell(XtParent(tb), event);
2533
2534 if ((! tb->label.skipCallback) &&
2535 (tb->toggle.value_changed_CB))
2536 {
2537 XFlush(XtDisplay(tb));
2538 ToggleButtonCallback(tb, XmCR_VALUE_CHANGED, tb->toggle.set, event);
2539 }
2540 }
2541 }
2542
2543 /************************************************************************
2544 *
2545 * Compute Space
2546 *
2547 ***********************************************************************/
2548 static void
ComputeSpace(XmToggleButtonWidget tb)2549 ComputeSpace(
2550 XmToggleButtonWidget tb )
2551 {
2552 int needed_width;
2553 int needed_height;
2554
2555 /* Compute space for drawing toggle. */
2556
2557 needed_width = tb->label.TextRect.width +
2558 tb->label.margin_left + tb->label.margin_right +
2559 (2 * (tb->primitive.shadow_thickness +
2560 tb->primitive.highlight_thickness +
2561 tb->label.margin_width));
2562
2563 needed_height = tb->label.TextRect.height +
2564 tb->label.margin_top + tb->label.margin_bottom +
2565 (2 * (tb->primitive.shadow_thickness +
2566 tb->primitive.highlight_thickness +
2567 tb->label.margin_height));
2568
2569 if (needed_height > tb->core.height)
2570 if (tb->toggle.ind_on)
2571 tb->label.TextRect.y = tb->primitive.shadow_thickness +
2572 tb->primitive.highlight_thickness +
2573 tb->label.margin_height +
2574 tb->label.margin_top +
2575 ((tb->core.height - tb->label.margin_top
2576 - tb->label.margin_bottom
2577 - (2 * (tb->label.margin_height
2578 + tb->primitive.highlight_thickness
2579 + tb->primitive.shadow_thickness))
2580 - tb->label.TextRect.height) / 2);
2581
2582 if (LayoutIsRtoLP(tb))
2583 {
2584 if ((needed_width > tb->core.width) ||
2585 ((tb->label.alignment == XmALIGNMENT_BEGINNING)
2586 && (needed_width < tb->core.width)) ||
2587 ((tb->label.alignment == XmALIGNMENT_CENTER)
2588 && (needed_width < tb->core.width)
2589 && (tb->core.width - needed_width < tb->label.margin_right)) ||
2590 (needed_width == tb->core.width))
2591 {
2592 if (tb->toggle.ind_on)
2593 tb->label.TextRect.x = tb->core.width -
2594 (tb->primitive.shadow_thickness +
2595 tb->primitive.highlight_thickness +
2596 tb->label.margin_width +
2597 tb->label.margin_right +
2598 tb->label.TextRect.width);
2599 }
2600 }
2601 else
2602 {
2603 if ((needed_width > tb->core.width) ||
2604 ((tb->label.alignment == XmALIGNMENT_BEGINNING)
2605 && (needed_width < tb->core.width)) ||
2606 ((tb->label.alignment == XmALIGNMENT_CENTER)
2607 && (needed_width < tb->core.width)
2608 && (tb->core.width - needed_width < tb->label.margin_left)) ||
2609 (needed_width == tb->core.width))
2610 {
2611 if (tb->toggle.ind_on)
2612 tb->label.TextRect.x = tb->primitive.shadow_thickness +
2613 tb->primitive.highlight_thickness +
2614 tb->label.margin_width +
2615 tb->label.margin_left;
2616 }
2617 }
2618 }
2619
2620 /*************************************<->*************************************
2621 *
2622 * Redisplay (w, event, region)
2623 * Cause the widget, identified by w, to be redisplayed.
2624 *
2625 *************************************<->***********************************/
2626 /*ARGUSED*/
2627 static void
Redisplay(Widget w,XEvent * event,Region region)2628 Redisplay(
2629 Widget w,
2630 XEvent *event,
2631 Region region )
2632 {
2633 register XmToggleButtonWidget tb = (XmToggleButtonWidget) w;
2634
2635 if (! XtIsRealized(w) ) return; /* Fix CR #4884, D. Rand 6/4/92 */
2636
2637 ComputeSpace (tb);
2638
2639 if (Lab_IsPixmap(tb) || Lab_IsPixmapAndText(tb))
2640 SetAndDisplayPixmap(tb, event, region);
2641 else
2642 if (!tb->toggle.ind_on && tb->toggle.fill_on_select)
2643 DrawToggleLabel (tb);
2644 else
2645 {
2646 XtExposeProc expose;
2647 _XmProcessLock();
2648 expose = xmLabelClassRec.core_class.expose;
2649 _XmProcessUnlock();
2650 (* expose) (w, event, region);
2651 }
2652
2653 if (tb->toggle.ind_on)
2654 {
2655 if (!(tb->toggle.Armed))
2656 IsOn(tb) = tb->toggle.set;
2657 DrawToggle(tb);
2658 }
2659
2660 if (Lab_IsMenupane(tb))
2661 {
2662 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(w));
2663 Boolean etched_in = dpy -> display.enable_etched_in_menu;
2664
2665 if ((tb->toggle.Armed) &&
2666 (tb->primitive.shadow_thickness > 0))
2667 XmeDrawShadows (XtDisplay (tb), XtWindow (tb),
2668 tb->primitive.top_shadow_GC,
2669 tb->primitive.bottom_shadow_GC,
2670 tb ->primitive.highlight_thickness,
2671 tb ->primitive.highlight_thickness,
2672 (int)tb->core.width-2*tb->primitive.highlight_thickness,
2673 (int)tb->core.height-2*tb->primitive.highlight_thickness,
2674 tb->primitive.shadow_thickness,
2675 etched_in ? XmSHADOW_IN : XmSHADOW_OUT);
2676 }
2677
2678 else
2679 {
2680 DrawToggleShadow (tb);
2681 }
2682 }
2683
2684 /**************************************************************************
2685 *
2686 * Resize(w, event)
2687 *
2688 **************************************************************************/
2689 static void
Resize(Widget w)2690 Resize(
2691 Widget w )
2692 {
2693 register XmToggleButtonWidget tb = (XmToggleButtonWidget) w;
2694
2695 /* BEGIN OSF Fix pir 1778 */
2696 if (Lab_IsPixmap(w))
2697 SetToggleSize(tb);
2698 else {
2699 XtWidgetProc resize;
2700 _XmProcessLock();
2701 resize = xmLabelClassRec.core_class.resize;
2702 _XmProcessUnlock();
2703 (* resize)( (Widget) tb);
2704 }
2705 /* END OSF Fix pir 1778 */
2706 }
2707
2708 /************************************************************************
2709 *
2710 * SetValuesPrehook
2711 *
2712 ************************************************************************/
2713
2714 /*ARGSUSED*/
2715 static Boolean
SetValuesPrehook(Widget cw,Widget rw,Widget nw,ArgList args,Cardinal * num_args)2716 SetValuesPrehook(
2717 Widget cw, /* unused */
2718 Widget rw, /* unused */
2719 Widget nw,
2720 ArgList args, /* unused */
2721 Cardinal *num_args ) /* unused */
2722 {
2723 XmToggleButtonWidget new_w = (XmToggleButtonWidget) nw ;
2724
2725 /* CR 2990: Use XmNbuttonFontList as the default font. */
2726 if (new_w->label.font == NULL)
2727 new_w->label.font = XmeGetDefaultRenderTable (nw, XmBUTTON_FONTLIST);
2728
2729 return False;
2730 }
2731
2732 /***************************************************************************
2733 *
2734 * SetValues(current, request, new_w)
2735 * This is the set values procedure for the ToggleButton class. It is
2736 * called last (the set values rtnes for its superclasses are called
2737 * first).
2738 *
2739 *************************************<->***********************************/
2740 /* ARGSUSED */
2741 static Boolean
SetValues(Widget current,Widget request,Widget new_w,ArgList args,Cardinal * num_args)2742 SetValues(
2743 Widget current,
2744 Widget request,
2745 Widget new_w,
2746 ArgList args,
2747 Cardinal *num_args )
2748 {
2749 XmToggleButtonWidget curcbox = (XmToggleButtonWidget) current;
2750 XmToggleButtonWidget reqcbox = (XmToggleButtonWidget) request;
2751 XmToggleButtonWidget newcbox = (XmToggleButtonWidget) new_w;
2752 Boolean flag = FALSE; /* our return value */
2753 XtWidgetProc resize;
2754
2755 /* CR 2337: Preserve the user's margins. */
2756 if (curcbox->label.margin_right != reqcbox->label.margin_right)
2757 newcbox->toggle.ind_right_delta = 0;
2758 if (curcbox->label.margin_left != reqcbox->label.margin_left)
2759 newcbox->toggle.ind_left_delta = 0;
2760 if (curcbox->label.margin_top != reqcbox->label.margin_top)
2761 newcbox->toggle.ind_top_delta = 0;
2762 if (curcbox->label.margin_bottom != reqcbox->label.margin_bottom)
2763 newcbox->toggle.ind_bottom_delta = 0;
2764
2765
2766 /**********************************************************************
2767 * Calculate the window size: The assumption here is that if
2768 * the width and height are the same in the new and current instance
2769 * record that those fields were not changed with set values. Therefore
2770 * its okay to recompute the necessary width and height. However, if
2771 * the new and current do have different width/heights then leave them
2772 * alone because that's what the user wants.
2773 *********************************************************************/
2774
2775 _XmProcessLock();
2776 resize = xmLabelClassRec.core_class.resize;
2777 _XmProcessUnlock();
2778
2779 /* Use the On pixmaps if no Indeterminate pixmaps are found. */
2780 if (IsNull(PixmapInd(newcbox)) && !IsNull(PixmapOn(newcbox)))
2781 PixmapInd(newcbox) = PixmapOn(newcbox);
2782 if (IsNull(PixmapInsenInd(newcbox)) && !IsNull(PixmapInsenOn(newcbox)))
2783 PixmapInsenInd(newcbox) = PixmapInsenOn(newcbox);
2784
2785 /* Use the On pixmap if no Off pixmap is found. */
2786 if (IsNull(PixmapOff(newcbox)) && !IsNull(PixmapOn(newcbox)))
2787 {
2788 PixmapOff(newcbox) = PixmapOn(newcbox);
2789 if ((newcbox->label.recompute_size) &&
2790 (request->core.width == current->core.width))
2791 new_w->core.width = 0;
2792 if ((newcbox->label.recompute_size) &&
2793 (request->core.height == current->core.height))
2794 new_w->core.height = 0;
2795
2796 _XmCalcLabelDimensions(new_w);
2797 (* resize)( (Widget) new_w);
2798 }
2799
2800 /* Use the insensitive On pixmap if no insensitive Off pixmap is found. */
2801 if (IsNull(PixmapInsenOff(newcbox)) && !IsNull(PixmapInsenOn(newcbox)))
2802 {
2803 PixmapInsenOff(newcbox) = PixmapInsenOn(newcbox);
2804 if ((newcbox->label.recompute_size) &&
2805 (request->core.width == current->core.width))
2806 new_w->core.width = 0;
2807 if ((newcbox->label.recompute_size) &&
2808 (request->core.height == current->core.height))
2809 new_w->core.height = 0;
2810
2811 _XmCalcLabelDimensions(new_w);
2812 (* resize)( (Widget) new_w);
2813 }
2814
2815 /* BEGIN OSF Fix pir 1778 */
2816 /* Have to reset the TextRect width because label's resize will have
2817 * mucked with it. */
2818 if (Lab_IsPixmap(newcbox) &&
2819 (!IsNull(PixmapOff(newcbox)) || !IsNull(PixmapInsenOff(newcbox)) ||
2820 !IsNull(PixmapOn(newcbox)) || !IsNull(PixmapInsenOn(newcbox)) ||
2821 !IsNull(PixmapInd(newcbox)) || !IsNull(PixmapInsenInd(newcbox))))
2822 {
2823 if ((newcbox->label.recompute_size))
2824 {
2825 if (request->core.width == current->core.width)
2826 new_w->core.width = 0;
2827 if (request->core.height == current->core.height)
2828 new_w->core.height = 0;
2829 }
2830
2831 SetToggleSize(newcbox);
2832 }
2833 /* END OSF Fix pir 1778 */
2834
2835 /* CR 9922: Changing fillOnSelect requires a redraw. */
2836 if (newcbox->toggle.fill_on_select != curcbox->toggle.fill_on_select)
2837 {
2838 flag = TRUE;
2839 }
2840
2841 if ((newcbox->label._label != curcbox->label._label) ||
2842 (PixmapOff(newcbox) != PixmapOff(curcbox)) ||
2843 (newcbox->label.font != curcbox->label.font) ||
2844 (newcbox->toggle.spacing != curcbox->toggle.spacing) ||
2845 (PixmapOn(newcbox) != PixmapOn(curcbox)) ||
2846 (PixmapInsenOn(newcbox) != PixmapInsenOn(curcbox)) ||
2847 (PixmapInd(newcbox) != PixmapInd(curcbox)) ||
2848 (PixmapInsenInd(newcbox) != PixmapInsenInd(curcbox)) ||
2849 (newcbox->toggle.ind_on != curcbox->toggle.ind_on) ||
2850 (newcbox->toggle.indicator_dim != curcbox->toggle.indicator_dim) ||
2851 (Lab_IsPixmap(newcbox) != Lab_IsPixmap(curcbox)) ||
2852 (Lab_IsPixmapAndText(newcbox) != Lab_IsPixmapAndText(curcbox)))
2853 {
2854 int right_delta = 0; /* Our desired margin adjustments. */
2855 int left_delta = 0;
2856 int top_delta = 0;
2857 int bottom_delta = 0;
2858
2859 if (newcbox->label.recompute_size)
2860 {
2861 if (request->core.width == current->core.width)
2862 new_w->core.width = 0;
2863 if (request->core.height == current->core.height)
2864 new_w->core.height = 0;
2865 }
2866
2867 if (Lab_IsPixmap(newcbox) &&
2868 ((PixmapOn(newcbox) != PixmapOn(curcbox)) ||
2869 (PixmapInsenOn(newcbox) != PixmapInsenOn(curcbox)) ||
2870 (PixmapInd(newcbox) != PixmapInd(curcbox)) ||
2871 (PixmapInsenInd(newcbox) != PixmapInsenInd(curcbox))) )
2872 {
2873 _XmCalcLabelDimensions(new_w);
2874
2875 /* OSF Fix pir 1778 */
2876 SetToggleSize(newcbox);
2877 }
2878
2879 newcbox->toggle.indicator_set = curcbox->toggle.indicator_set;
2880
2881 if (newcbox->toggle.indicator_dim != curcbox->toggle.indicator_dim)
2882 {
2883 newcbox->toggle.indicator_set = TRUE;
2884 }
2885
2886
2887 /* CR 8415: Honor explicit requests for XmNindicatorSize. */
2888 if (!(newcbox->toggle.indicator_set) &&
2889 (newcbox->toggle.indicator_dim == curcbox->toggle.indicator_dim))
2890 {
2891 if ((Lab_IsPixmap(newcbox) != Lab_IsPixmap(curcbox)) ||
2892 (Lab_IsPixmapAndText(newcbox) != Lab_IsPixmapAndText(curcbox)) ||
2893 (newcbox->label._label != curcbox->label._label) ||
2894 (PixmapOff(newcbox) != PixmapOff(curcbox)) ||
2895 (newcbox->label.font != curcbox->label.font) ||
2896 (newcbox->toggle.ind_on != curcbox->toggle.ind_on))
2897 {
2898 if (Lab_IsPixmap(new_w) || Lab_IsPixmapAndText(new_w))
2899 {
2900 if (!IsNull(PixmapOff(newcbox)) || !IsNull(PixmapInsenOff(newcbox)) ||
2901 !IsNull(PixmapOn(newcbox)) || !IsNull(PixmapInsenOn(newcbox)) ||
2902 !IsNull(PixmapInd(newcbox)) || !IsNull(PixmapInsenInd(newcbox)))
2903 if (newcbox->label.TextRect.height < 13)
2904 newcbox->toggle.indicator_dim =
2905 newcbox->label.TextRect.height;
2906 else
2907 newcbox->toggle.indicator_dim = 13 +
2908 (newcbox->label.TextRect.height/13);
2909 else
2910 newcbox->toggle.indicator_dim = XmDEFAULT_INDICATOR_DIM;
2911 }
2912 else
2913 {
2914 Dimension height;
2915 int line_count;
2916
2917 height = XmStringHeight (newcbox->label.font,
2918 newcbox->label._label);
2919 line_count = XmStringLineCount (newcbox->label._label);
2920
2921 /*
2922 * CR 5203 - Make the calculation for the
2923 * indicator_dim be the same as in the Initialize
2924 * procedure, i.e. Popup and Pulldown menus should
2925 * have smaller indicators.
2926 */
2927 if (line_count < 1)
2928 line_count = 1;
2929 if (Lab_IsMenupane(newcbox))
2930 newcbox->toggle.indicator_dim =
2931 MAX(XmDEFAULT_INDICATOR_DIM,
2932 (height / ((Dimension)line_count)) * 2/3);
2933 else
2934 newcbox->toggle.indicator_dim =
2935 MAX(XmDEFAULT_INDICATOR_DIM,
2936 height / ((Dimension)line_count));
2937 /* End 5203 Fix */
2938 }
2939 }
2940 }
2941
2942 if (newcbox->toggle.ind_on)
2943 {
2944 /*
2945 * Fix CR 5568 - If the indicator is on and the user has changed the
2946 * indicator dimension, calculate the new top and bottom
2947 * margins in a place where they can effect the core width
2948 * and height.
2949 */
2950 /* Recompute the Top and bottom margins and the height of the text
2951 * rectangle to accommodate the size of toggle indicator.
2952 * if (we are given a new toggleIndicator size)
2953 * { if (user has given new top or bottom margin)
2954 * { compute to accomodate new toggle button size; }
2955 * else (user has set new top/bottom margin)
2956 * { Recompute margin to accommodate new IndicatorSize; }
2957 * }
2958 */
2959 if (newcbox->toggle.indicator_dim != curcbox->toggle.indicator_dim)
2960 {
2961 int maxIndicatorSize =
2962 (int) (newcbox->toggle.indicator_dim) + 2*Xm3D_ENHANCE_PIXEL;
2963
2964 int boxSize = ((int) newcbox->label.TextRect.height +
2965 (int) newcbox->label.margin_top +
2966 (int) newcbox->label.margin_bottom);
2967
2968 top_delta = bottom_delta = (maxIndicatorSize - boxSize) / 2;
2969 }
2970 /* End fix CR 5568 */
2971
2972 if (LayoutIsRtoLP(newcbox))
2973 right_delta = (newcbox->toggle.indicator_dim +
2974 newcbox->toggle.spacing -
2975 newcbox->label.margin_right);
2976 else
2977 left_delta = (newcbox->toggle.indicator_dim +
2978 newcbox->toggle.spacing -
2979 newcbox->label.margin_left);
2980 }
2981 else if (curcbox->toggle.ind_on)
2982 {
2983 /* CR 2337: Redisplay when the indicator is turned off. */
2984 flag = TRUE;
2985
2986 top_delta = -newcbox->toggle.ind_top_delta;
2987 bottom_delta = -newcbox->toggle.ind_bottom_delta;
2988
2989 if (LayoutIsRtoLP(newcbox))
2990 right_delta = -newcbox->toggle.ind_right_delta;
2991 else
2992 left_delta = -newcbox->toggle.ind_left_delta;
2993 }
2994
2995 /* CR 2337: Let the toggle button shrink if necessary. */
2996 if (right_delta || left_delta || top_delta || bottom_delta)
2997 {
2998 flag = TRUE;
2999
3000 /* Adjust vertical margins based on the indicator. */
3001 if ((int)newcbox->toggle.ind_top_delta + top_delta > 0)
3002 {
3003 newcbox->label.margin_top += top_delta;
3004 newcbox->toggle.ind_top_delta += top_delta;
3005 }
3006 else
3007 {
3008 newcbox->label.margin_top -= newcbox->toggle.ind_top_delta;
3009 newcbox->toggle.ind_top_delta = 0;
3010 }
3011
3012 if ((int)newcbox->toggle.ind_bottom_delta + bottom_delta > 0)
3013 {
3014 newcbox->label.margin_bottom += bottom_delta;
3015 newcbox->toggle.ind_bottom_delta += bottom_delta;
3016 }
3017 else
3018 {
3019 newcbox->label.margin_bottom -= newcbox->toggle.ind_bottom_delta;
3020 newcbox->toggle.ind_bottom_delta = 0;
3021 }
3022
3023 /* Adjust horizontal margins based on the indicator. */
3024 if (LayoutIsRtoLP(newcbox))
3025 {
3026 if ((int)newcbox->toggle.ind_right_delta + right_delta > 0)
3027 {
3028 newcbox->label.margin_right += right_delta;
3029 newcbox->toggle.ind_right_delta += right_delta;
3030 }
3031 else
3032 {
3033 newcbox->label.margin_right -=
3034 newcbox->toggle.ind_right_delta;
3035 newcbox->toggle.ind_right_delta = 0;
3036 }
3037 }
3038 else
3039 {
3040 if ((int)newcbox->toggle.ind_left_delta + left_delta > 0)
3041 {
3042 newcbox->label.margin_left += left_delta;
3043 newcbox->toggle.ind_left_delta += left_delta;
3044 }
3045 else
3046 {
3047 newcbox->label.margin_left -= newcbox->toggle.ind_left_delta;
3048 newcbox->toggle.ind_left_delta = 0;
3049 }
3050 }
3051
3052 /* Realign the label. */
3053 if (!newcbox->label.recompute_size)
3054 (* resize) ((Widget) new_w);
3055 }
3056
3057 if (newcbox->label.recompute_size)
3058 {
3059 if (request->core.width == current->core.width)
3060 new_w->core.width = 0;
3061 if (request->core.height == current->core.height)
3062 new_w->core.height = 0;
3063 }
3064
3065 if (new_w->core.width == 0)
3066 {
3067 newcbox->core.width =
3068 newcbox->label.TextRect.width +
3069 newcbox->label.margin_left + newcbox->label.margin_right +
3070 2 * (newcbox->primitive.highlight_thickness +
3071 newcbox->primitive.shadow_thickness +
3072 newcbox->label.margin_width);
3073
3074 if (newcbox->core.width == 0)
3075 newcbox->core.width = 1;
3076
3077 flag = TRUE;
3078 }
3079
3080 if (new_w->core.height == 0)
3081 {
3082 newcbox->core.height =
3083 MAX(newcbox->toggle.indicator_dim,
3084 newcbox->label.TextRect.height +
3085 2 * newcbox->label.margin_height +
3086 newcbox->label.margin_top + newcbox->label.margin_bottom) +
3087 2 * (newcbox->primitive.highlight_thickness +
3088 newcbox->primitive.shadow_thickness);
3089
3090 if (newcbox->core.height == 0)
3091 newcbox->core.height = 1;
3092
3093 flag = TRUE;
3094 }
3095 }
3096
3097 if ((newcbox->primitive.foreground != curcbox->primitive.foreground) ||
3098 (newcbox->core.background_pixel != curcbox->core.background_pixel) ||
3099 (newcbox->toggle.select_color != curcbox->toggle.select_color))
3100 {
3101 XtReleaseGC( (Widget) curcbox, curcbox->toggle.select_GC);
3102 XtReleaseGC( (Widget) curcbox, curcbox->toggle.background_gc);
3103 XtReleaseGC( (Widget) curcbox, curcbox->toggle.indeterminate_GC);
3104 XtReleaseGC( (Widget) curcbox, curcbox->toggle.indeterminate_box_GC);
3105
3106 newcbox->toggle.reversed_select =
3107 (newcbox->toggle.select_color == XmREVERSED_GROUND_COLORS);
3108 if (newcbox->toggle.select_color == XmDEFAULT_SELECT_COLOR)
3109 {
3110 /* CR 9923: Copy all bytes of the resulting pixel. */
3111 XrmValue value;
3112 DefaultSelectColor((Widget)newcbox,
3113 XtOffsetOf(XmToggleButtonRec,toggle.select_color),
3114 &value);
3115 assert(value.size == sizeof(Pixel));
3116 newcbox->toggle.select_color = *((Pixel*) value.addr);
3117 }
3118 else if (newcbox->toggle.select_color == XmREVERSED_GROUND_COLORS)
3119 {
3120 newcbox->toggle.select_color = newcbox->primitive.foreground;
3121 }
3122 else if (newcbox->toggle.select_color == XmHIGHLIGHT_COLOR)
3123 {
3124 newcbox->toggle.select_color = newcbox->primitive.highlight_color;
3125 }
3126
3127 GetGC(newcbox);
3128 flag = TRUE;
3129 }
3130
3131 if (newcbox->toggle.unselect_color != curcbox->toggle.unselect_color)
3132 {
3133 XtReleaseGC ((Widget) curcbox, curcbox->toggle.unselect_GC);
3134 GetUnselectGC(newcbox);
3135 flag = TRUE;
3136 }
3137
3138
3139 if ((curcbox->toggle.ind_type != newcbox->toggle.ind_type) &&
3140 (!XmRepTypeValidValue(XmRID_INDICATOR_TYPE,
3141 newcbox->toggle.ind_type, (Widget) newcbox)))
3142 {
3143 newcbox->toggle.ind_type = curcbox->toggle.ind_type;
3144 }
3145
3146 if (curcbox->toggle.set != newcbox->toggle.set)
3147 {
3148 if ((newcbox->toggle.toggle_mode == XmTOGGLE_BOOLEAN) &&
3149 (newcbox->toggle.set == XmINDETERMINATE))
3150 {
3151 newcbox->toggle.set = curcbox->toggle.set;
3152 }
3153 else
3154 {
3155 IsOn(newcbox) = newcbox->toggle.set;
3156 if (flag == False && XtIsRealized((Widget)newcbox))
3157 {
3158 if (newcbox->toggle.ind_on)
3159 {
3160 DrawToggle (newcbox);
3161 if (Lab_IsPixmap(newcbox) || Lab_IsPixmapAndText(newcbox))
3162 SetAndDisplayPixmap(newcbox, NULL, NULL);
3163 }
3164 else
3165 {
3166 /* Begin fixing OSF 5946 */
3167 if (newcbox->primitive.shadow_thickness > 0)
3168 DrawToggleShadow (newcbox);
3169 if (newcbox->toggle.fill_on_select && !Lab_IsPixmap(newcbox))
3170 DrawToggleLabel (newcbox);
3171 if (Lab_IsPixmap(newcbox) || Lab_IsPixmapAndText(newcbox))
3172 {
3173 SetAndDisplayPixmap(newcbox, NULL, NULL);
3174 flag = True;
3175 }
3176 /* End fixing OSF 5946 */
3177 }
3178 }
3179 }
3180 }
3181
3182 if ((curcbox->toggle.ind_type != newcbox->toggle.ind_type) ||
3183 ( (curcbox->toggle.visible != newcbox->toggle.visible) && (XmUNSET == newcbox->toggle.set)) )
3184 {
3185 flag = True;
3186 }
3187
3188 /* One-of-many forces boolean mode. */
3189 if (IsOneOfMany(newcbox->toggle.ind_type) &&
3190 (newcbox->toggle.toggle_mode == XmTOGGLE_INDETERMINATE))
3191 {
3192 newcbox->toggle.toggle_mode = XmTOGGLE_BOOLEAN;
3193 }
3194
3195 /*
3196 * Transition between True/False is easy. Transition from
3197 * indetermine is done by setting the toggle to False.
3198 */
3199 if ((curcbox->toggle.toggle_mode != newcbox->toggle.toggle_mode) &&
3200 (newcbox->toggle.toggle_mode == XmTOGGLE_BOOLEAN) &&
3201 (newcbox->toggle.set == XmINDETERMINATE))
3202 {
3203 newcbox->toggle.visual_set = newcbox->toggle.set = XmUNSET;
3204 flag = True;
3205 }
3206
3207 return(flag);
3208 }
3209
3210 /***************************************************************
3211 *
3212 * XmToggleButtonGetState
3213 * This function gets the state of the toggle widget.
3214 *
3215 ***************************************************************/
3216 Boolean
XmToggleButtonGetState(Widget w)3217 XmToggleButtonGetState(
3218 Widget w )
3219 {
3220 XmToggleButtonWidget tw = (XmToggleButtonWidget) w;
3221 Boolean ret_val;
3222 XtAppContext app = XtWidgetToApplicationContext(w);
3223
3224 if (XmIsGadget(w))
3225 return XmToggleButtonGadgetGetState(w);
3226
3227 _XmAppLock(app);
3228 ret_val = tw->toggle.set;
3229 _XmAppUnlock(app);
3230
3231 return (ret_val);
3232 }
3233
3234 /****************************************************************
3235 *
3236 * XmTogglebuttonSetState
3237 * This function sets the state of the toggle widget.
3238 *
3239 ****************************************************************/
3240 void
XmToggleButtonSetState(Widget w,int bnewstate,int notify)3241 XmToggleButtonSetState(
3242 Widget w,
3243 #if NeedWidePrototypes
3244 int bnewstate,
3245 int notify )
3246 #else
3247 Boolean bnewstate,
3248 Boolean notify )
3249 #endif /* NeedWidePrototypes */
3250 {
3251 XmToggleButtonWidget tw = (XmToggleButtonWidget) w;
3252 XmMenuSystemTrait menuSTrait;
3253 XtAppContext app = XtWidgetToApplicationContext(w);
3254 XmToggleButtonState newstate;
3255
3256 if (XmIsGadget(w)) {
3257 XmToggleButtonGadgetSetState(w, bnewstate, notify);
3258 return;
3259 }
3260
3261 _XmAppLock(app);
3262
3263 /* toggel.set is enum type, not Boolean */
3264 newstate = (bnewstate == XmSET)? XmSET : XmUNSET;
3265
3266 if (tw->toggle.set != newstate)
3267 {
3268 tw->toggle.set = newstate;
3269 IsOn(tw) = newstate;
3270 if (XtIsRealized ((Widget)tw))
3271 {
3272 if (tw->toggle.ind_on)
3273 DrawToggle(tw);
3274 else
3275 {
3276 if (tw->primitive.shadow_thickness > 0)
3277 DrawToggleShadow (tw);
3278 if (tw->toggle.fill_on_select && !Lab_IsPixmap(tw))
3279 DrawToggleLabel (tw);
3280 }
3281
3282 if (Lab_IsPixmap(tw) || Lab_IsPixmapAndText(tw))
3283 SetAndDisplayPixmap( tw, NULL, NULL);
3284 }
3285
3286 if (notify)
3287 {
3288 /* UNDOING this fix ... */
3289 /* CR 8904: Notify value_changed before entry so that state is */
3290 /* reported correctly even if the entry callback resets it. */
3291 menuSTrait = (XmMenuSystemTrait)
3292 XmeTraitGet((XtPointer) XtClass(XtParent(tw)), XmQTmenuSystem);
3293
3294 if (menuSTrait != NULL)
3295 {
3296 XmToggleButtonCallbackStruct call_value;
3297
3298 call_value.reason = XmCR_VALUE_CHANGED;
3299 call_value.event = NULL;
3300 call_value.set = tw->toggle.set;
3301
3302 menuSTrait->entryCallback(XtParent(tw), (Widget)tw, &call_value);
3303 }
3304
3305 if ((! tw->label.skipCallback) &&
3306 (tw->toggle.value_changed_CB))
3307 {
3308 XFlush(XtDisplay(tw));
3309 ToggleButtonCallback(tw, XmCR_VALUE_CHANGED,
3310 tw->toggle.set, NULL);
3311 }
3312
3313 }
3314 }
3315 _XmAppUnlock(app);
3316 }
3317
3318 /****************************************************************
3319 *
3320 * XmToggleButtonSetValue
3321 * This function sets the state of the toggle widget.
3322 *
3323 ****************************************************************/
3324 Boolean
XmToggleButtonSetValue(Widget w,int newstate,int notify)3325 XmToggleButtonSetValue(
3326 Widget w,
3327 #if NeedWidePrototypes
3328 int newstate,
3329 int notify )
3330 #else
3331 XmToggleButtonState newstate,
3332 Boolean notify )
3333 #endif /* NeedWidePrototypes */
3334 {
3335 XmToggleButtonWidget tw = (XmToggleButtonWidget) w;
3336 XtAppContext app = XtWidgetToApplicationContext(w);
3337
3338 if (XmIsGadget(w))
3339 return XmToggleButtonGadgetSetValue(w, newstate, notify);
3340
3341 _XmAppLock(app);
3342
3343 /* Can't set third state if we aren't in three state mode. */
3344 if ((newstate == XmINDETERMINATE) &&
3345 (tw->toggle.toggle_mode != XmTOGGLE_INDETERMINATE)) {
3346 _XmAppUnlock(app);
3347 return False;
3348 }
3349
3350 if (tw->toggle.set != newstate)
3351 {
3352 tw->toggle.set = tw->toggle.visual_set = newstate;
3353 if (XtIsRealized ((Widget)tw))
3354 {
3355 if (tw->toggle.ind_on)
3356 DrawToggle(tw);
3357 else
3358 {
3359 if (tw->primitive.shadow_thickness > 0)
3360 DrawToggleShadow (tw);
3361 if (tw->toggle.fill_on_select && !Lab_IsPixmap(tw))
3362 DrawToggleLabel (tw);
3363 }
3364 if (Lab_IsPixmap(tw) || Lab_IsPixmapAndText(tw))
3365 SetAndDisplayPixmap( tw, NULL, NULL);
3366 }
3367
3368 if (notify)
3369 {
3370 /* If the parent is a RowColumn, notify it about the select. */
3371 if (XmIsRowColumn(XtParent(tw)))
3372 {
3373 XmToggleButtonCallbackStruct call_value;
3374 call_value.reason = XmCR_VALUE_CHANGED;
3375 call_value.event = NULL;
3376 call_value.set = tw->toggle.set;
3377 (* xmLabelClassRec.label_class.menuProcs)
3378 (XmMENU_CALLBACK, XtParent(tw), FALSE, tw, &call_value);
3379 }
3380
3381 if ((! tw->label.skipCallback) &&
3382 (tw->toggle.value_changed_CB))
3383 {
3384 XFlush(XtDisplay(tw));
3385 ToggleButtonCallback(tw, XmCR_VALUE_CHANGED,
3386 tw->toggle.set, NULL);
3387 }
3388 }
3389 }
3390
3391 _XmAppUnlock(app);
3392 return True;
3393 }
3394
3395 /***********************************************************************
3396 *
3397 * XmCreateToggleButton
3398 * Creates an instance of a togglebutton and returns the widget id.
3399 *
3400 ************************************************************************/
3401 Widget
XmCreateToggleButton(Widget parent,char * name,Arg * arglist,Cardinal argCount)3402 XmCreateToggleButton(
3403 Widget parent,
3404 char *name,
3405 Arg *arglist,
3406 Cardinal argCount )
3407 {
3408 return XtCreateWidget(name, xmToggleButtonWidgetClass, parent,
3409 arglist, argCount);
3410 }
3411
3412 Widget
XmVaCreateToggleButton(Widget parent,char * name,...)3413 XmVaCreateToggleButton(
3414 Widget parent,
3415 char *name,
3416 ...)
3417 {
3418 register Widget w;
3419 va_list var;
3420 int count;
3421
3422 Va_start(var,name);
3423 count = XmeCountVaListSimple(var);
3424 va_end(var);
3425
3426
3427 Va_start(var, name);
3428 w = XmeVLCreateWidget(name,
3429 xmToggleButtonWidgetClass,
3430 parent, False,
3431 var, count);
3432 va_end(var);
3433 return w;
3434
3435 }
3436 Widget
XmVaCreateManagedToggleButton(Widget parent,char * name,...)3437 XmVaCreateManagedToggleButton(
3438 Widget parent,
3439 char *name,
3440 ...)
3441 {
3442 Widget w = NULL;
3443 va_list var;
3444 int count;
3445
3446 Va_start(var, name);
3447 count = XmeCountVaListSimple(var);
3448 va_end(var);
3449
3450 Va_start(var, name);
3451 w = XmeVLCreateWidget(name,
3452 xmToggleButtonWidgetClass,
3453 parent, True,
3454 var, count);
3455 va_end(var);
3456 return w;
3457
3458 }
3459
3460 /*
3461 * DrawToggleShadow (tb)
3462 * - Should be called only if ToggleShadow are to be drawn ;
3463 * if the IndicatorOn resource is set to false top and bottom shadows
3464 * will be switched depending on whether the Toggle is selected or
3465 * unselected.
3466 * No need to call the routine if shadow_thickness is 0.
3467 */
3468 static void
DrawToggleShadow(XmToggleButtonWidget tb)3469 DrawToggleShadow(
3470 XmToggleButtonWidget tb )
3471 {
3472 GC top_gc, bot_gc;
3473 int width, height;
3474 int hilite_thickness;
3475
3476 if (tb->toggle.ind_on || (IsOn(tb) == XmUNSET))
3477 {
3478 top_gc = tb->primitive.top_shadow_GC;
3479 bot_gc = tb->primitive.bottom_shadow_GC;
3480 }
3481 else if (IsOn(tb) == XmINDETERMINATE)
3482 {
3483 top_gc = bot_gc = tb->toggle.indeterminate_box_GC;
3484 }
3485 else
3486 {
3487 top_gc = tb->primitive.bottom_shadow_GC;
3488 bot_gc = tb->primitive.top_shadow_GC;
3489 }
3490
3491 hilite_thickness = tb->primitive.highlight_thickness;
3492 width = (int) (tb->core.width - (hilite_thickness << 1));
3493 height = (int) (tb->core.height - (hilite_thickness << 1));
3494
3495 XmeDrawShadows (XtDisplay (tb), XtWindow (tb), top_gc, bot_gc,
3496 hilite_thickness, hilite_thickness, width, height,
3497 tb->primitive.shadow_thickness, XmSHADOW_OUT);
3498 }
3499
3500 /*
3501 * DrawToggleLabel (tb)
3502 * Called when XmNindicatorOn is FALSE and XmNfillOnSelect is TRUE.
3503 * Fill toggle with selectColor or background depending on toggle
3504 * value, and draw label.
3505 */
3506 static void
DrawToggleLabel(XmToggleButtonWidget tb)3507 DrawToggleLabel(
3508 XmToggleButtonWidget tb )
3509 {
3510 Dimension margin = (tb->primitive.highlight_thickness +
3511 tb->primitive.shadow_thickness);
3512 Position fx = margin;
3513 Position fy = margin;
3514 int fw = tb->core.width - 2 * margin;
3515 int fh = tb->core.height - 2 * margin;
3516 Boolean restore_gc = False;
3517 GC tmp_gc = None, fill_gc;
3518
3519 if (tb->primitive.top_shadow_color == tb->toggle.select_color ||
3520 tb->primitive.bottom_shadow_color == tb->toggle.select_color)
3521 {
3522 fx += 1;
3523 fy += 1;
3524 fw -= 2;
3525 fh -= 2;
3526 }
3527
3528 if (fw < 0 || fh < 0)
3529 return;
3530
3531 switch (tb->toggle.visual_set)
3532 {
3533 case XmUNSET:
3534 fill_gc = tb->toggle.unselect_GC;
3535 break;
3536 case XmSET:
3537 fill_gc = tb->toggle.select_GC;
3538 break;
3539 case XmINDETERMINATE:
3540 {
3541 XGCValues values;
3542
3543 /* Fetch the select_color GetGC() actually used. */
3544 XGetGCValues(XtDisplay(tb), tb->toggle.select_GC,
3545 GCForeground, &values);
3546 values.background = tb->toggle.unselect_color;
3547 XChangeGC(XtDisplay((Widget)tb), tb->toggle.indeterminate_GC,
3548 GCForeground|GCBackground, &values);
3549 fill_gc = tb->toggle.indeterminate_GC;
3550 break;
3551 }
3552 default:
3553 assert(False);
3554 return;
3555 }
3556
3557 XFillRectangle (XtDisplay(tb), XtWindow(tb), fill_gc, fx, fy, fw, fh);
3558
3559
3560 if ((tb->primitive.foreground == tb->toggle.select_color) &&
3561 (IsOn(tb) == XmSET))
3562 {
3563 tmp_gc = tb->label.normal_GC;
3564 tb->label.normal_GC = tb->toggle.background_gc;
3565 restore_gc = True;
3566 }
3567
3568 {
3569
3570 XtExposeProc expose;
3571 #ifdef FIX_1395
3572 Pixel tmpc = tb->core.background_pixel; /* Save bg color */
3573
3574 /* Changing label background color if button toggled */
3575 if (tb->toggle.visual_set == XmSET && !Lab_IsMenupane(tb))
3576 XSetWindowBackground(XtDisplay(tb), XtWindow(tb), tb->toggle.select_color);
3577 #endif
3578 _XmProcessLock();
3579 expose = xmLabelClassRec.core_class.expose;
3580 _XmProcessUnlock();
3581 (* expose) ((Widget) tb, NULL, NULL);
3582 #ifdef FIX_1395
3583 /* restore default bg color */
3584 if (tb->toggle.visual_set == XmSET && !Lab_IsMenupane(tb) )
3585 XSetWindowBackground(XtDisplay(tb), XtWindow(tb), tmpc);
3586 #endif
3587 }
3588
3589 if (restore_gc)
3590 {
3591 /* CR 9791: Label's normal_gc has a dynamic clip_mask. */
3592 XSetClipMask(XtDisplay(tb), tb->toggle.background_gc, None);
3593 tb->label.normal_GC = tmp_gc;
3594 }
3595 }
3596
3597 /*
3598 * DrawEtchedInMenu (tb)
3599 * Called when in a Menu and EtchedInMenu is TRUE.
3600 * And when XmNindicatorOn is FALSE and XmNfillOnSelect is FALSE;
3601 * or when XmNindicatorOn is TRUE.
3602 * Fill background with the arm_gc and draw label.
3603 */
3604 static void
DrawEtchedInMenu(XmToggleButtonWidget tb)3605 DrawEtchedInMenu(
3606 XmToggleButtonWidget tb )
3607 {
3608 Dimension margin = (tb->primitive.highlight_thickness +
3609 tb->primitive.shadow_thickness);
3610 Position fx = margin;
3611 Position fy = margin;
3612 int fw = tb->core.width - 2 * margin;
3613 int fh = tb->core.height - 2 * margin;
3614 Boolean restore_gc = False;
3615 GC tmp_gc = None;
3616 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(tb));
3617 Boolean etched_in = dpy->display.enable_etched_in_menu;
3618 Pixel select_pix, tmpc;
3619
3620 if (tb->primitive.top_shadow_color == tb->toggle.select_color ||
3621 tb->primitive.bottom_shadow_color == tb->toggle.select_color)
3622 {
3623 fx += 1;
3624 fy += 1;
3625 fw -= 2;
3626 fh -= 2;
3627 }
3628
3629 if (fw < 0 || fh < 0)
3630 return;
3631
3632 XFillRectangle (XtDisplay(tb), XtWindow(tb),
3633 tb->toggle.Armed ? tb->toggle.arm_GC :
3634 tb->toggle.background_gc,
3635 fx, fy, fw, fh);
3636
3637 if (tb->toggle.Armed)
3638 {
3639 tmpc = tb->core.background_pixel;
3640
3641 XmGetColors(XtScreen(tb), tb->core.colormap,
3642 tb->core.background_pixel,
3643 NULL, NULL, NULL, &select_pix);
3644
3645 if (tb->primitive.foreground == select_pix)
3646 {
3647 tmp_gc = tb->label.normal_GC;
3648 tb->label.normal_GC = tb->toggle.background_gc;
3649 restore_gc = True;
3650 }
3651 }
3652
3653 {
3654 XtExposeProc expose;
3655 #ifdef FIX_1395
3656 if (tb->toggle.Armed)
3657 {
3658 XSetWindowBackground(XtDisplay(tb), XtWindow(tb), select_pix);
3659 }
3660 else
3661 {
3662 XSetWindowBackground(XtDisplay(tb), XtWindow(tb), tb->core.background_pixel);
3663 }
3664 #endif
3665 _XmProcessLock();
3666 expose = xmLabelClassRec.core_class.expose;
3667 _XmProcessUnlock();
3668 (* expose) ((Widget) tb, NULL, NULL);
3669 }
3670
3671 if (restore_gc)
3672 {
3673 XSetClipMask(XtDisplay(tb), tb->toggle.background_gc, None);
3674 tb->label.normal_GC = tmp_gc;
3675 }
3676 }
3677
3678 /* BEGIN OSF Fix pir 1778 */
3679 /*************************************************************************
3680 *
3681 * SetToggleSize(newtb)
3682 * Set size properly when XmNselectPixmap or XmNselectInsensitivePixmaps
3683 * are set in addition to the corresponding labelPixmaps. Have to pick
3684 * the largest dimensions.
3685 *
3686 ************************************************************************/
3687
3688 static void
SetToggleSize(XmToggleButtonWidget newtb)3689 SetToggleSize(
3690 XmToggleButtonWidget newtb)
3691 {
3692 unsigned int maxW, maxH;
3693 unsigned int tmpW, tmpH;
3694
3695 maxW = maxH = tmpW = tmpH = 0;
3696
3697 /* We know it's a pixmap so find out how how big it is */
3698 if (XtIsSensitive((Widget) newtb))
3699 {
3700 if (!IsNull(PixmapOn(newtb)))
3701 {
3702 XmeGetPixmapData(XtScreen(newtb), PixmapOn(newtb),
3703 NULL, NULL, NULL, NULL, NULL, NULL,
3704 &tmpW, &tmpH);
3705 ASSIGN_MAX(maxW, tmpW);
3706 ASSIGN_MAX(maxH, tmpH);
3707 }
3708
3709 if (!IsNull(PixmapOff(newtb)))
3710 {
3711 XmeGetPixmapData(XtScreen(newtb), PixmapOff(newtb),
3712 NULL, NULL, NULL, NULL, NULL, NULL,
3713 &tmpW, &tmpH);
3714 ASSIGN_MAX(maxW, tmpW);
3715 ASSIGN_MAX(maxH, tmpH);
3716 }
3717
3718 if (!IsNull(PixmapInd(newtb)))
3719 {
3720 XmeGetPixmapData(XtScreen(newtb), PixmapInd(newtb),
3721 NULL, NULL, NULL, NULL, NULL, NULL,
3722 &tmpW, &tmpH);
3723 ASSIGN_MAX(maxW, tmpW);
3724 ASSIGN_MAX(maxH, tmpH);
3725 }
3726 }
3727 else
3728 {
3729 if (!IsNull(PixmapInsenOn(newtb)))
3730 {
3731 XmeGetPixmapData(XtScreen(newtb), PixmapInsenOn(newtb),
3732 NULL, NULL, NULL, NULL, NULL, NULL,
3733 &tmpW, &tmpH);
3734 ASSIGN_MAX(maxW, tmpW);
3735 ASSIGN_MAX(maxH, tmpH);
3736 }
3737
3738 if (!IsNull(PixmapInsenOff(newtb)))
3739 {
3740 XmeGetPixmapData(XtScreen(newtb), PixmapInsenOff(newtb),
3741 NULL, NULL, NULL, NULL, NULL, NULL,
3742 &tmpW, &tmpH);
3743 ASSIGN_MAX(maxW, tmpW);
3744 ASSIGN_MAX(maxH, tmpH);
3745 }
3746
3747 if (!IsNull(PixmapInsenInd(newtb)))
3748 {
3749 XmeGetPixmapData(XtScreen(newtb), PixmapInsenInd(newtb),
3750 NULL, NULL, NULL, NULL, NULL, NULL,
3751 &tmpW, &tmpH);
3752 ASSIGN_MAX(maxW, tmpW);
3753 ASSIGN_MAX(maxH, tmpH);
3754 }
3755 }
3756
3757 newtb->label.TextRect.width = (unsigned short) maxW;
3758 newtb->label.TextRect.height = (unsigned short) maxH;
3759
3760 /* Invoke Label's SetSize procedure. */
3761 {
3762 XtWidgetProc resize;
3763 _XmProcessLock();
3764 resize = xmLabelClassRec.core_class.resize;
3765 _XmProcessUnlock();
3766
3767 (* resize) ((Widget) newtb);
3768 }
3769 }
3770 /* END OSF Fix pir 1778 */
3771
3772 /*
3773 * DefaultSelectColor - an XtResourceDefaultProc for generating the
3774 * default select color. This may require examining the
3775 * XmNindicatorType and XmNhighlightColor resources, which will
3776 * happen to have real values only because they appear before
3777 * XmNselectColor in the resource list.
3778 */
3779 static void
DefaultSelectColor(Widget widget,int offset,XrmValue * value)3780 DefaultSelectColor(Widget widget,
3781 int offset,
3782 XrmValue *value)
3783 {
3784 XmToggleButtonWidget tb = (XmToggleButtonWidget) widget;
3785 Boolean force_highlight = FALSE;
3786 XmDisplay xm_dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(widget));
3787 Boolean enable_toggle_color = xm_dpy->display.enable_toggle_color;
3788
3789 if (enable_toggle_color)
3790 {
3791 /* This code may misbehave for erroneous ind_type values. */
3792 if (IsOneOfMany(tb->toggle.ind_type))
3793 {
3794 force_highlight = TRUE;
3795 }
3796 else if ((tb->toggle.ind_type == XmINVALID_TYPE) &&
3797 XmIsRowColumn(XtParent(widget)))
3798 {
3799 XtVaGetValues(XtParent(widget),
3800 XmNradioBehavior, &force_highlight,
3801 NULL);
3802 }
3803 }
3804
3805 if (force_highlight)
3806 {
3807 value->size = sizeof(tb->primitive.highlight_color);
3808 value->addr = (char *) &tb->primitive.highlight_color;
3809 }
3810 else
3811 _XmSelectColorDefault(widget, offset, value);
3812 }
3813
3814 /*
3815 * NormalizeIndOn - return the normalized value of XmNindicatorOn,
3816 * replacing XmINDICATOR_FILL and XmINDICATOR_BOX with the proper
3817 * absolute values.
3818 */
3819 static unsigned char
NormalizeIndOn(XmToggleButtonWidget tb)3820 NormalizeIndOn(XmToggleButtonWidget tb)
3821 {
3822 unsigned char value = tb->toggle.ind_on;
3823
3824 /* Convert XmINDICATOR_FILL to XmINDICATOR_CHECK_BOX? */
3825 if (value == XmINDICATOR_FILL)
3826 {
3827 /* This routine may be called frequently, so reach directly into */
3828 /* the XmDisplay rather than calling XtGetValues. */
3829 XmDisplay xm_dpy = (XmDisplay) XmGetXmDisplay(XtDisplay((Widget) tb));
3830
3831 if (xm_dpy->display.enable_toggle_visual)
3832 value = XmINDICATOR_CHECK_BOX;
3833 }
3834
3835 /* Convert XmINDICATOR_BOX to XmINDICATOR_3D_BOX (XmINDICATOR_FILL). */
3836 else if (value == XmINDICATOR_BOX)
3837 {
3838 value = XmINDICATOR_3D_BOX;
3839 }
3840
3841 return value;
3842 }
3843
3844 /*
3845 * NormalizeIndType - return the normalized value of XmNindicatorType,
3846 * replacing XmONE_OF_MANY with the proper absolute value.
3847 */
3848 static unsigned char
NormalizeIndType(XmToggleButtonWidget tb)3849 NormalizeIndType(XmToggleButtonWidget tb)
3850 {
3851 unsigned char value = tb->toggle.ind_type;
3852
3853 if (value == XmONE_OF_MANY)
3854 {
3855 /* This routine may be called frequently, so reach directly into */
3856 /* the XmDisplay rather than calling XtGetValues. */
3857 XmDisplay xm_dpy = (XmDisplay) XmGetXmDisplay(XtDisplay((Widget) tb));
3858
3859 if (xm_dpy->display.enable_toggle_visual)
3860 value = XmONE_OF_MANY_ROUND;
3861 else
3862 value = XmONE_OF_MANY_DIAMOND;
3863 }
3864
3865 return value;
3866 }
3867