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