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 REV_INFO
24 #ifndef lint
25 static char rcsid[] = "$TOG: DrawnB.c /main/20 1999/04/29 13:05:14 samborn $"
26 #endif
27 #endif
28 /*
29  * Include files & Static Routine Definitions
30  */
31 
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35 
36 
37 #include <stdio.h>
38 #include <X11/X.h>
39 #include <Xm/ActivatableT.h>
40 #include <Xm/DisplayP.h>
41 #include <Xm/DrawP.h>
42 #include <Xm/DrawnBP.h>
43 #include <Xm/LabelP.h>
44 #include <Xm/ManagerP.h>
45 #include <Xm/MenuT.h>
46 #include <Xm/RowColumnP.h>
47 #include <Xm/VaSimpleP.h>
48 #include <Xm/TraitP.h>
49 #include <Xm/TransltnsP.h>
50 #include "XmI.h"
51 #include "RepTypeI.h"
52 #include "LabelI.h"
53 #include "MenuUtilI.h"
54 #include "MenuProcI.h"
55 #include "MenuStateI.h"
56 #include "PrimitiveI.h"
57 #include "TravActI.h"
58 #include "TraversalI.h"
59 #include "UniqueEvnI.h"
60 
61 
62 #define DELAY_DEFAULT 100
63 
64 /********    Static Function Declarations    ********/
65 
66 static void Arm(
67                         Widget wid,
68                         XEvent *event,
69                         String *params,
70                         Cardinal *num_params) ;
71 static void MultiArm(
72                         Widget wid,
73                         XEvent *event,
74                         String *params,
75                         Cardinal *num_params) ;
76 static void Activate(
77                         Widget wid,
78                         XEvent *buttonEvent,
79                         String *params,
80                         Cardinal *num_params) ;
81 static void MultiActivate(
82                         Widget wid,
83                         XEvent *buttonEvent,
84                         String *params,
85                         Cardinal *num_params) ;
86 static void ActivateCommon(
87                         Widget wid,
88                         XEvent *event,
89                         String *params,
90                         Cardinal *num_params) ;
91 static void ArmAndActivate(
92                         Widget wid,
93                         XEvent *event,
94                         String *params,
95                         Cardinal *num_params) ;
96 static void ArmTimeout (
97         		XtPointer closure,
98         		XtIntervalId *id ) ;
99 static void Disarm(
100                         Widget wid,
101                         XEvent *event,
102                         String *params,
103                         Cardinal *num_params) ;
104 static void BtnDown(
105                         Widget wid,
106                         XEvent *event,
107                         String *params,
108                         Cardinal *num_params) ;
109 static void BtnUp(
110                         Widget wid,
111                         XEvent *event,
112                         String *params,
113                         Cardinal *num_params) ;
114 static void Enter(
115                         Widget wid,
116                         XEvent *event,
117                         String *params,
118                         Cardinal *num_params) ;
119 static void Leave(
120                         Widget wid,
121                         XEvent *event,
122                         String *params,
123                         Cardinal *num_params) ;
124 static void BorderHighlight(
125                         Widget wid) ;
126 static void BorderUnhighlight(
127                         Widget wid) ;
128 static void ClassInitialize( void ) ;
129 static void ClassPartInitialize(
130                         WidgetClass wc) ;
131 static void InitializePrehook(
132                         Widget rw,
133                         Widget nw,
134                         ArgList args,
135                         Cardinal *num_args) ;
136 static void InitializePosthook(
137                         Widget rw,
138                         Widget nw,
139                         ArgList args,
140                         Cardinal *num_args) ;
141 static void Initialize(
142                         Widget rw,
143                         Widget nw,
144                         ArgList args,
145                         Cardinal *num_args) ;
146 static void Resize(
147                         Widget wid) ;
148 static void Redisplay(
149                         Widget wid,
150                         XEvent *event,
151                         Region region) ;
152 static void DrawPushButton(
153                         XmDrawnButtonWidget db,
154 #if NeedWidePrototypes
155                         int armed) ;
156 #else
157                         Boolean armed) ;
158 #endif /* NeedWidePrototypes */
159 static Boolean SetValuesPrehook(
160 			Widget cw,
161                         Widget rw,
162                         Widget nw,
163                         ArgList args,
164                         Cardinal *num_args) ;
165 static Boolean SetValues(
166                         Widget cw,
167                         Widget rw,
168                         Widget nw,
169                         ArgList args,
170                         Cardinal *num_args) ;
171 static void Realize(
172                         Widget w,
173                         XtValueMask *p_valueMask,
174                         XSetWindowAttributes *attributes) ;
175 static void Destroy(
176                         Widget wid) ;
177 
178 static void ChangeCB(Widget w,
179 		     XtCallbackProc activCB,
180 		     XtPointer closure,
181 		     Boolean setunset) ;
182 
183 static void DB_FixTearoff(XmDrawnButtonWidget db);
184 
185 /********    End Static Function Declarations    ********/
186 
187 /*************************************<->*************************************
188  *
189  *
190  *   Description:   translation tables for class: DrawnButton
191  *   -----------
192  *
193  *   Matches events with string descriptors for internal routines.
194  *
195  *************************************<->***********************************/
196 
197 static XtTranslations default_parsed;
198 
199 #define defaultTranslations	_XmDrawnB_defaultTranslations
200 
201 static XtTranslations menu_parsed;
202 
203 #define menuTranslations	_XmDrawnB_menuTranslations
204 
205 
206 /*************************************<->*************************************
207  *
208  *
209  *   Description:  action list for class: DrawnButton
210  *   -----------
211  *
212  *   Matches string descriptors with internal routines.
213  *   Note that Primitive will register additional event handlers
214  *   for traversal.
215  *
216  *************************************<->***********************************/
217 
218 static XtActionsRec actionsList[] =
219 {
220   {"Arm", 	Arm		 },
221   {"Activate", 	Activate		 },
222   {"MultiActivate", MultiActivate		 },
223   {"MultiArm",	MultiArm },
224   {"ArmAndActivate", ArmAndActivate },
225   {"Disarm", 	Disarm		 },
226   {"BtnDown", 	BtnDown		 },
227   {"BtnUp", 	BtnUp		 },
228   {"Enter", 	Enter		 },
229   {"Leave",	Leave		 },
230   {"ButtonTakeFocus", _XmButtonTakeFocus },
231   {"MenuButtonTakeFocus", _XmMenuButtonTakeFocus	 },
232   {"MenuButtonTakeFocusUp", _XmMenuButtonTakeFocusUp }
233 };
234 
235 
236 /*  The resource list for Drawn Button  */
237 
238 static XtResource resources[] =
239 {
240    {
241      XmNmultiClick, XmCMultiClick, XmRMultiClick, sizeof (unsigned char),
242      XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.multiClick),
243      XmRImmediate, (XtPointer) XmMULTICLICK_KEEP
244    },
245 
246    {
247      XmNpushButtonEnabled, XmCPushButtonEnabled, XmRBoolean, sizeof (Boolean),
248      XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.pushbutton_enabled),
249      XmRImmediate, (XtPointer) False
250    },
251 
252    {
253      XmNshadowType, XmCShadowType, XmRShadowType, sizeof(unsigned char),
254      XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.shadow_type),
255      XmRImmediate, (XtPointer) XmSHADOW_ETCHED_IN
256    },
257 
258    {
259      XmNactivateCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
260      XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.activate_callback),
261      XmRPointer, (XtPointer) NULL
262    },
263 
264    {
265      XmNarmCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
266      XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.arm_callback),
267      XmRPointer, (XtPointer) NULL
268    },
269 
270    {
271      XmNdisarmCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
272      XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.disarm_callback),
273      XmRPointer, (XtPointer) NULL
274    },
275 
276    {
277      XmNexposeCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
278      XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.expose_callback),
279      XmRPointer, (XtPointer) NULL
280    },
281 
282    {
283      XmNresizeCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
284      XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.resize_callback),
285      XmRPointer, (XtPointer) NULL
286    },
287 
288    {
289      XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension,
290      sizeof(Dimension),
291      XtOffsetOf( struct _XmDrawnButtonRec, primitive.shadow_thickness),
292      XmRCallProc, (XtPointer) _XmSetThickness
293    },
294 
295    {
296      XmNlabelString, XmCXmString, XmRXmString, sizeof(XmString),
297      XtOffsetOf( struct _XmDrawnButtonRec, label._label),
298      XmRImmediate, (XtPointer) XmUNSPECIFIED
299    },
300    {
301 	XmNtraversalOn,
302 	XmCTraversalOn,
303 	XmRBoolean,
304 	sizeof(Boolean),
305 	XtOffsetOf( struct _XmPrimitiveRec, primitive.traversal_on),
306 	XmRImmediate,
307 	(XtPointer) True
308    },
309 
310    {
311 	XmNhighlightThickness,
312 	XmCHighlightThickness,
313 	XmRHorizontalDimension,
314 	sizeof (Dimension),
315 	XtOffsetOf( struct _XmPrimitiveRec, primitive.highlight_thickness),
316 	XmRCallProc,
317 	(XtPointer) _XmSetThickness
318    }
319 };
320 
321 static XmBaseClassExtRec       drawnBBaseClassExtRec = {
322     NULL,                                     /* Next extension       */
323     NULLQUARK,                                /* record type XmQmotif */
324     XmBaseClassExtVersion,                    /* version              */
325     sizeof(XmBaseClassExtRec),                /* size                 */
326     InitializePrehook,                        /* initialize prehook   */
327     SetValuesPrehook,			      /* set_values prehook   */
328     InitializePosthook,                       /* initialize posthook  */
329     XmInheritSetValuesPosthook,               /* set_values posthook  */
330     XmInheritClass,                           /* secondary class      */
331     XmInheritSecObjectCreate,                 /* creation proc        */
332     XmInheritGetSecResData,                   /* getSecResData        */
333     {0},                                      /* fast subclass        */
334     XmInheritGetValuesPrehook,                /* get_values prehook   */
335     XmInheritGetValuesPosthook,               /* get_values posthook  */
336     XmInheritClassPartInitPrehook,            /* classPartInitPrehook */
337     XmInheritClassPartInitPosthook,           /* classPartInitPosthook*/
338     NULL,                                     /* ext_resources        */
339     NULL,                                     /* compiled_ext_resources*/
340     0,                                        /* num_ext_resources    */
341     FALSE,                                    /* use_sub_resources    */
342     XmInheritWidgetNavigable,                 /* widgetNavigable      */
343     XmInheritFocusChange,                     /* focusChange          */
344 };
345 
346 
347 
348 /*************************************<->*************************************
349  *
350  *
351  *   Description:  global class record for instances of class: DrawnButton
352  *   -----------
353  *
354  *   Defines default field settings for this class record.
355  *
356  *************************************<->***********************************/
357 
358 externaldef(xmdrawnbuttonclassrec) XmDrawnButtonClassRec xmDrawnButtonClassRec ={
359   {
360 /* core_class record */
361     /* superclass	  */	(WidgetClass) &xmLabelClassRec,
362     /* class_name	  */	"XmDrawnButton",
363     /* widget_size	  */	sizeof(XmDrawnButtonRec),
364     /* class_initialize   */    ClassInitialize,
365     /* class_part_init    */    ClassPartInitialize,
366     /* class_inited       */	FALSE,
367     /* initialize	  */	Initialize,
368     /* initialize_hook    */    NULL,
369     /* realize		  */	Realize,
370     /* actions		  */	actionsList,
371     /* num_actions	  */	XtNumber(actionsList),
372     /* resources	  */	resources,
373     /* num_resources	  */	XtNumber(resources),
374     /* xrm_class	  */	NULLQUARK,
375     /* compress_motion	  */	TRUE,
376     /* compress_exposure  */	XtExposeNoCompress,
377     /* compress_enterlv   */    TRUE,
378     /* visible_interest	  */	FALSE,
379     /* destroy		  */	Destroy,
380     /* resize		  */	Resize,
381     /* expose		  */	Redisplay,
382     /* set_values	  */	SetValues,
383     /* set_values_hook    */    NULL,
384     /* set_values_almost  */    XtInheritSetValuesAlmost,
385     /* get_values_hook    */	NULL,
386     /* accept_focus	  */	NULL,
387     /* version            */	XtVersion,
388     /* callback_private   */    NULL,
389     /* tm_table           */    defaultTranslations,
390     /* query_geometry     */	NULL,
391     /* display_accelerator */   NULL,
392     /* extension          */    (XtPointer) &drawnBBaseClassExtRec,
393   },
394 
395   { /* primitive_class record       */
396 
397    /* Primitive border_highlight   */	BorderHighlight,
398     /* Primitive border_unhighlight */	BorderUnhighlight,
399     /* translations		    */  XtInheritTranslations,
400     /* arm_and_activate		    */  ArmAndActivate,
401     /* get resources		    */  NULL,
402     /* num get_resources	    */  0,
403     /* extension		    */  NULL,
404   },
405 
406   { /* label_class record */
407 
408     /* setOverrideCallback*/    XmInheritWidgetProc,
409     /* Menu procedures    */    XmInheritMenuProc,
410     /* menu trav xlations */	XtInheritTranslations,
411     /* extension	  */	NULL,
412   },
413 
414   { /* drawnbutton_class record */
415 
416     /* extension	  */    NULL,
417   }
418 
419 };
420 externaldef(xmdrawnbuttonwidgetclass) WidgetClass xmDrawnButtonWidgetClass =
421 			     (WidgetClass)&xmDrawnButtonClassRec;
422 
423 /* Trait record for drawnButton */
424 
425 static XmConst XmActivatableTraitRec drawnButtonAT = {
426   0,		/* version */
427   ChangeCB,
428 };
429 
430 /* Menu Savvy trait record */
431 static XmMenuSavvyTraitRec MenuSavvyRecord = {
432     /* version: */
433     -1,
434     NULL,
435     NULL,
436     NULL,
437     _XmCBNameActivate,
438 };
439 
440 
441 /************************************************************************
442  *
443  *     Arm
444  *
445  *     This function processes button 1 down occuring on the drawnbutton.
446  *     Mark the drawnbutton as armed if XmNpushButtonEnabled is TRUE.
447  *     The callbacks for XmNarmCallback are called.
448  *
449  ************************************************************************/
450 /*ARGSUSED*/
451 static void
Arm(Widget wid,XEvent * event,String * params,Cardinal * num_params)452 Arm(
453         Widget wid,
454         XEvent *event,
455         String *params,		/* unused */
456         Cardinal *num_params )	/* unused */
457 {
458     XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
459     XButtonEvent *buttonEvent = (XButtonEvent *) event;
460     XmDrawnButtonCallbackStruct call_value;
461 
462     (void) XmProcessTraversal((Widget) db, XmTRAVERSE_CURRENT);
463 
464     db -> drawnbutton.armed = TRUE;
465     if (event && (event->type == ButtonPress))
466 	db -> drawnbutton.armTimeStamp = buttonEvent->time;
467 
468     if (db->drawnbutton.pushbutton_enabled)
469 	DrawPushButton(db, db->drawnbutton.armed);
470 
471     if (db->drawnbutton.arm_callback) {
472 	XFlush(XtDisplay (db));
473 
474 	call_value.reason = XmCR_ARM;
475 	call_value.event = event;
476 	call_value.window = XtWindow (db);
477 	XtCallCallbackList ((Widget) db, db->drawnbutton.arm_callback,
478 			    &call_value);
479     }
480 }
481 
482 
483 /*ARGSUSED*/
484 static void
MultiArm(Widget wid,XEvent * event,String * params,Cardinal * num_params)485 MultiArm(
486         Widget wid,
487         XEvent *event,
488         String *params,		/* unused */
489         Cardinal *num_params )	/* unused */
490 {
491     if (((XmDrawnButtonWidget) wid)->drawnbutton.multiClick == XmMULTICLICK_KEEP)
492 			Arm (wid, event, NULL, NULL);
493 }
494 
495 /************************************************************************
496  *
497  *     Activate
498  *
499  *     Mark the drawnbutton as unarmed (i.e. inactive).
500  *     The foreground and background colors will revert to the
501  *     unarmed state if XmNinvertOnArm is set to TRUE.
502  *     If the button release occurs inside of the DrawnButton, the
503  *     callbacks for XmNactivateCallback are called.
504  *
505  ************************************************************************/
506 static void
Activate(Widget wid,XEvent * buttonEvent,String * params,Cardinal * num_params)507 Activate(
508         Widget wid,
509         XEvent *buttonEvent,
510         String *params,
511         Cardinal *num_params )
512 {
513         XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
514    if (db -> drawnbutton.armed == FALSE)
515       return;
516 
517    db->drawnbutton.click_count = 1;
518    ActivateCommon ((Widget) db, buttonEvent, params, num_params);
519 
520 }
521 
522 static void
MultiActivate(Widget wid,XEvent * buttonEvent,String * params,Cardinal * num_params)523 MultiActivate(
524         Widget wid,
525         XEvent *buttonEvent,
526         String *params,
527         Cardinal *num_params )
528 {
529         XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
530    /* When a multi click sequence occurs and the user Button Presses and
531     * holds for a length of time, the final release should look like a
532     * new/separate activate.
533     */
534   if (db->drawnbutton.multiClick == XmMULTICLICK_KEEP)
535   { if ((buttonEvent->xbutton.time - db->drawnbutton.armTimeStamp) >
536 	   XtGetMultiClickTime(XtDisplay(db)))
537      db->drawnbutton.click_count = 1;
538    else
539      db->drawnbutton.click_count++;
540    ActivateCommon ((Widget) db, buttonEvent, params, num_params) ;
541    Disarm ((Widget) db, buttonEvent, params, num_params) ;
542  }
543 }
544 
545 /*ARGSUSED*/
546 static void
ActivateCommon(Widget wid,XEvent * event,String * params,Cardinal * num_params)547 ActivateCommon(
548         Widget wid,
549         XEvent *event,
550         String *params,		/* unused */
551         Cardinal *num_params )	/* unused */
552 {
553    XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
554    XmDrawnButtonCallbackStruct call_value;
555    XmMenuSystemTrait menuSTrait;
556 
557    menuSTrait = (XmMenuSystemTrait)
558      XmeTraitGet((XtPointer) XtClass(XtParent(wid)), XmQTmenuSystem);
559 
560    if (event && (event->xbutton.type != ButtonRelease))
561        return;
562 
563    db -> drawnbutton.armed = FALSE;
564    if (db->drawnbutton.pushbutton_enabled)
565 	DrawPushButton(db, db->drawnbutton.armed);
566 
567 
568   /* CR 9181: Consider clipping when testing visibility. */
569   if ((db->drawnbutton.activate_callback) &&
570       ((event->xany.type == ButtonPress) ||
571        (event->xany.type == ButtonRelease)) &&
572       _XmGetPointVisibility(wid, event->xbutton.x_root, event->xbutton.y_root))
573    {
574       XFlush(XtDisplay (db));
575 
576       call_value.reason = XmCR_ACTIVATE;
577       call_value.event = event;
578       call_value.window = XtWindow (db);
579       call_value.click_count = db->drawnbutton.click_count;
580 
581       if ((db->drawnbutton.multiClick == XmMULTICLICK_DISCARD) &&
582 	  (call_value.click_count > 1))
583       {
584 	  return;
585       }
586 
587       if (menuSTrait != NULL)
588       {
589 	menuSTrait->entryCallback(XtParent(db), (Widget) db,
590 					   &call_value);
591       }
592 
593       if ((! db->label.skipCallback) &&
594 	  (db->drawnbutton.activate_callback))
595       {
596 	 XtCallCallbackList ((Widget) db, db->drawnbutton.activate_callback,
597 				&call_value);
598       }
599    }
600 }
601 
602 
603 
604 static void
DB_FixTearoff(XmDrawnButtonWidget db)605 DB_FixTearoff( XmDrawnButtonWidget db)
606 {
607 	 if  (XmMENU_PULLDOWN == db->label.menu_type)
608 	 {
609 		Widget mwid = XmGetPostedFromWidget(XtParent(db));
610 		if (mwid && XmIsRowColumn(mwid)
611 			&& (XmMENU_OPTION == RC_Type(mwid))
612 			&& _XmIsActiveTearOff(XtParent(db)))
613 			XmProcessTraversal((Widget) db, XmTRAVERSE_CURRENT);
614 	 }
615 }
616 /************************************************************************
617  *
618  *     ArmAndActivate
619  *
620  ************************************************************************/
621 /*ARGSUSED*/
622 static void
ArmAndActivate(Widget wid,XEvent * event,String * params,Cardinal * num_params)623 ArmAndActivate(
624         Widget wid,
625         XEvent *event,
626         String *params,		/* unused */
627         Cardinal *num_params )	/* unused */
628 {
629    XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
630    XmDrawnButtonCallbackStruct call_value;
631    XmMenuSystemTrait menuSTrait;
632 
633    menuSTrait = (XmMenuSystemTrait)
634      XmeTraitGet((XtPointer) XtClass(XtParent(wid)), XmQTmenuSystem);
635 
636    db -> drawnbutton.armed = TRUE;
637    if (db->drawnbutton.pushbutton_enabled)
638 	DrawPushButton(db, db->drawnbutton.armed);
639 
640    XFlush(XtDisplay (db));
641 
642    if (db->drawnbutton.arm_callback)
643    {
644       call_value.reason = XmCR_ARM;
645       call_value.event = event;
646       call_value.window = XtWindow (db);
647       XtCallCallbackList ((Widget) db, db->drawnbutton.arm_callback, &call_value);
648    }
649 
650    call_value.reason = XmCR_ACTIVATE;
651    call_value.event = event;
652    call_value.window = XtWindow (db);
653    call_value.click_count = 1;		/* always 1 in kselect */
654 
655    if (menuSTrait != NULL)
656    {
657      menuSTrait->entryCallback(XtParent(db), (Widget) db,
658 					&call_value);
659    }
660 
661    if ((! db->label.skipCallback) &&
662        (db->drawnbutton.activate_callback))
663    {
664       XtCallCallbackList ((Widget) db, db->drawnbutton.activate_callback,
665 			  &call_value);
666    }
667 
668    db->drawnbutton.armed = FALSE;
669 
670    if (db->drawnbutton.disarm_callback)
671    {
672       call_value.reason = XmCR_DISARM;
673       XtCallCallbackList ((Widget) db, db->drawnbutton.disarm_callback,
674                              &call_value);
675    }
676 
677    /* If the button is still around, show it released, after a short delay */
678    if (!db->core.being_destroyed && db->drawnbutton.pushbutton_enabled)
679    {
680        db->drawnbutton.timer = XtAppAddTimeOut(
681 				       XtWidgetToApplicationContext((Widget)db),
682                                        (unsigned long) DELAY_DEFAULT,
683                                        ArmTimeout,
684                                        (XtPointer)db);
685    }
686 }
687 
688 /*ARGSUSED*/
689 static void
ArmTimeout(XtPointer closure,XtIntervalId * id)690 ArmTimeout (
691 	XtPointer closure,
692 	XtIntervalId *id )
693 {
694   XmDrawnButtonWidget db = (XmDrawnButtonWidget) closure ;
695 
696   db -> drawnbutton.timer = 0;
697 
698   if (db->drawnbutton.pushbutton_enabled &&
699       XtIsRealized((Widget)db) && XtIsManaged((Widget)db))
700    {
701      DrawPushButton(db, db->drawnbutton.armed);
702      XFlush (XtDisplay (db));
703    }
704 }
705 
706 
707 
708 /************************************************************************
709  *
710  *    Disarm
711  *
712  *     Mark the drawnbutton as unarmed (i.e. active).
713  *     The foreground and background colors will revert to the
714  *     unarmed state if XmNinvertOnSelect is set to TRUE and the
715  *     drawnbutton is not in a menu.
716  *     The callbacks for XmNdisarmCallback are called..
717  *
718  ************************************************************************/
719 /*ARGSUSED*/
720 static void
Disarm(Widget wid,XEvent * event,String * params,Cardinal * num_params)721 Disarm(
722         Widget wid,
723         XEvent *event,
724         String *params,		/* unused */
725         Cardinal *num_params )	/* unused */
726 {
727    XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
728    XmDrawnButtonCallbackStruct call_value;
729 
730    db -> drawnbutton.armed = FALSE;
731 
732    if (db->drawnbutton.disarm_callback)
733    {
734       XFlush(XtDisplay (db));
735 
736       call_value.reason = XmCR_DISARM;
737       call_value.event = event;
738       call_value.window = XtWindow (db);
739       XtCallCallbackList ((Widget) db, db->drawnbutton.disarm_callback, &call_value);
740    }
741 }
742 
743 
744 
745 /************************************************************************
746  *
747  *     BtnDown
748  *
749  *     This function processes a button down occuring on the drawnbutton
750  *     when it is in a popup, pulldown, or option menu.
751  *     Popdown the posted menu.
752  *     Turn parent's traversal off.
753  *     Mark the drawnbutton as armed (i.e. active).
754  *     The callbacks for XmNarmCallback are called.
755  *
756  ************************************************************************/
757 
758 /*ARGSUSED*/
759 static void
BtnDown(Widget wid,XEvent * event,String * params,Cardinal * num_params)760 BtnDown(
761         Widget wid,
762         XEvent *event,
763         String *params,		/* unused */
764         Cardinal *num_params )	/* unused */
765 {
766   XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
767   XmDrawnButtonCallbackStruct call_value;
768   Boolean validButton = False;
769   Boolean already_armed;
770   ShellWidget popup;
771   XmMenuSystemTrait menuSTrait;
772 
773   /* Support menu replay, free server input queue until next button event */
774   XAllowEvents(XtDisplay(db), SyncPointer, CurrentTime);
775 
776   /* If no menu system trait then parent isn't a menu as it should be. */
777   menuSTrait = (XmMenuSystemTrait)
778     XmeTraitGet((XtPointer) XtClass(XtParent(db)), XmQTmenuSystem);
779   if (menuSTrait == NULL)
780     return;
781 
782   if (event && (event->type == ButtonPress))
783     validButton = menuSTrait->verifyButton(XtParent(db), event);
784 
785   if (!validButton)
786     return;
787 
788   _XmSetInDragMode((Widget)db, True);
789 
790   /* Popdown other popus that may be up */
791   if (!(popup = (ShellWidget)_XmGetRC_PopupPosted(XtParent(db))))
792     {
793       if (!XmIsMenuShell(XtParent(XtParent(db))))
794 	{
795 	  /* In case tear off not armed and no grabs in place, do it now.
796 	   * Ok if already armed and grabbed - nothing done.
797 	   */
798 	  menuSTrait->tearOffArm(XtParent(db));
799 	}
800     }
801 
802   if (popup)
803     {
804       if (popup->shell.popped_up)
805 	menuSTrait->popdownEveryone((Widget) popup, event);
806     }
807 
808   /* Set focus to this drawnbutton.  This must follow the possible
809    * unhighlighting of the CascadeButton else it'll screw up active_child.
810    */
811   (void)XmProcessTraversal ((Widget) db, XmTRAVERSE_CURRENT);
812   /* get the location cursor - get consistent with Gadgets */
813 
814   already_armed = db->drawnbutton.armed;
815   db->drawnbutton.armed = TRUE;
816 
817   if (db->drawnbutton.arm_callback && !already_armed)
818     {
819       XFlush (XtDisplay (db));
820 
821       call_value.reason = XmCR_ARM;
822       call_value.event = event;
823       XtCallCallbackList((Widget) db, db->drawnbutton.arm_callback, &call_value);
824     }
825   _XmRecordEvent (event);
826 }
827 
828 /************************************************************************
829  *
830  *     BtnUp
831  *
832  *     This function processes a button up occuring on the drawnbutton
833  *     when it is in a popup, pulldown, or option menu.
834  *     Mark the drawnbutton as unarmed (i.e. inactive).
835  *     The callbacks for XmNactivateCallback are called.
836  *     The callbacks for XmNdisarmCallback are called.
837  *
838  ************************************************************************/
839 
840 /*ARGSUSED*/
841 static void
BtnUp(Widget wid,XEvent * event,String * params,Cardinal * num_params)842 BtnUp(
843         Widget wid,
844         XEvent *event,
845         String *params,		/* unused */
846         Cardinal *num_params )	/* unused */
847 {
848   XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
849   Widget parent =  XtParent(db);
850   XmDrawnButtonCallbackStruct call_value;
851   Boolean flushDone = False;
852   Boolean validButton = False;
853   Boolean popped_up;
854   Boolean is_menupane = Lab_IsMenupane(db);
855   Widget shell = XtParent(XtParent(db));
856   XmMenuSystemTrait menuSTrait;
857 
858   /* If no menu system trait then parent isn't a menu as it should be. */
859   menuSTrait = (XmMenuSystemTrait)
860     XmeTraitGet((XtPointer) XtClass(XtParent(db)), XmQTmenuSystem);
861   if (menuSTrait == NULL)
862     return;
863 
864   if (event && (event->type == ButtonRelease))
865     validButton = menuSTrait->verifyButton(parent, event);
866 
867   if (!validButton || (db->drawnbutton.armed == FALSE))
868     return;
869 
870   db->drawnbutton.armed = FALSE;
871 
872   if (is_menupane && !XmIsMenuShell(shell))
873     popped_up = menuSTrait->popdown((Widget) db, event);
874   else
875     popped_up = menuSTrait->buttonPopdown((Widget) db, event);
876 
877   _XmRecordEvent(event);
878 
879   /* XmMENU_POPDOWN left the menu posted on button click - don't activate! */
880   if (popped_up)
881     return;
882 
883   call_value.reason = XmCR_ACTIVATE;
884   call_value.event = event;
885   call_value.click_count = 1;
886 
887   /* if the parent is menu system able, notify it about the select */
888   if (menuSTrait != NULL)
889     {
890       menuSTrait->entryCallback(parent, (Widget) db, &call_value);
891       flushDone = True;
892     }
893 
894   if ((! db->label.skipCallback) &&
895       (db->drawnbutton.activate_callback))
896     {
897       XFlush (XtDisplay (db));
898       flushDone = True;
899       XtCallCallbackList ((Widget) db, db->drawnbutton.activate_callback,
900 			  &call_value);
901     }
902   if (db->drawnbutton.disarm_callback)
903     {
904       if (!flushDone)
905 	XFlush (XtDisplay (db));
906       call_value.reason = XmCR_DISARM;
907       call_value.event = event;
908       XtCallCallbackList ((Widget) db, db->drawnbutton.disarm_callback,
909 			  &call_value);
910     }
911 
912   /* If the original shell does not indicate an active menu, but rather a
913    * tear off pane, leave the button in an armed state.  Also, briefly
914    * display the button as depressed to give the user some feedback of
915    * the selection.
916    */
917 
918   if (is_menupane) /* necessary check? */
919     {
920       if (!XmIsMenuShell(shell))
921 	{
922 	  if (XtIsSensitive((Widget)db))
923 	    {
924 	      XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(db));
925 	      Boolean etched_in = dpy->display.enable_etched_in_menu;
926 
927 	      if ((db->core.width > 2 * db->primitive.highlight_thickness) &&
928 		  (db->core.height > 2 * db->primitive.highlight_thickness))
929 		XmeDrawShadows
930 		  (XtDisplay (db), XtWindow (db),
931 		   db->primitive.bottom_shadow_GC,
932 		   db->primitive.top_shadow_GC,
933 		   db->primitive.highlight_thickness,
934 		   db->primitive.highlight_thickness,
935 		   db->core.width - 2 * db->primitive.highlight_thickness,
936 		   db->core.height - 2 * db->primitive.highlight_thickness,
937 		   db->primitive.shadow_thickness,
938 		   etched_in ? XmSHADOW_IN : XmSHADOW_OUT);
939 
940 	      XFlush (XtDisplay (db));
941 	      flushDone = True;
942 
943 	      if (db->core.being_destroyed == False)
944 		{
945 		  if (!db->drawnbutton.timer)
946 		    db->drawnbutton.timer =
947 		      XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)db),
948 				      (unsigned long) DELAY_DEFAULT,
949 				      ArmTimeout,
950 				      (XtPointer)(db));
951 		}
952 
953 	      db->drawnbutton.armed = TRUE;
954 	      if (db->drawnbutton.arm_callback)
955 		{
956 		  if (!flushDone)
957 		    XFlush (XtDisplay (db));
958 		  call_value.reason = XmCR_ARM;
959 		  call_value.event = event;
960 		  XtCallCallbackList ((Widget) db, db->drawnbutton.arm_callback,
961 				      &call_value);
962 		}
963 	    }
964 	}
965       else
966 	menuSTrait->reparentToTearOffShell(XtParent(db), event);
967     }
968 
969   _XmSetInDragMode((Widget)db, False);
970 
971   /* For the benefit of tear off menus, we must set the focus item
972    * to this button.  In normal menus, this would not be a problem
973    * because the focus is cleared when the menu is unposted.
974    */
975   if (!XmIsMenuShell(shell))
976     XmProcessTraversal((Widget) db, XmTRAVERSE_CURRENT);
977   DB_FixTearoff(db);
978 }
979 
980 /************************************************************************
981  *
982  *  Enter
983  *
984  ************************************************************************/
985 static void
Enter(Widget wid,XEvent * event,String * params,Cardinal * num_params)986 Enter(
987         Widget wid,
988         XEvent *event,
989         String *params,
990         Cardinal *num_params )
991 {
992    XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
993    XmDrawnButtonCallbackStruct call_value;
994 
995    if (Lab_IsMenupane(db)) {
996      if ((((ShellWidget) XtParent(XtParent(db)))->shell.popped_up) &&
997 	 _XmGetInDragMode((Widget)db))
998        {
999 	 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid));
1000 
1001 	 if (db->drawnbutton.armed)
1002 	   return;
1003 
1004 	 /* So KHelp event is delivered correctly */
1005 	 _XmSetFocusFlag (XtParent(XtParent(db)), XmFOCUS_IGNORE, TRUE);
1006 	 XtSetKeyboardFocus(XtParent(XtParent(db)), (Widget)db);
1007 	 _XmSetFocusFlag (XtParent(XtParent(db)), XmFOCUS_IGNORE, FALSE);
1008 
1009 	 db -> drawnbutton.armed = TRUE;
1010 
1011 	 ((XmManagerWidget) XtParent(wid))->manager.active_child = wid;
1012 
1013 	 if (db->drawnbutton.pushbutton_enabled)
1014 	   DrawPushButton(db, db->drawnbutton.armed);
1015 
1016 	 if (db->drawnbutton.arm_callback)
1017 	   {
1018 	     XFlush (XtDisplay (db));
1019 
1020 	     call_value.reason = XmCR_ARM;
1021 	     call_value.event = event;
1022 	     XtCallCallbackList ((Widget) db,
1023 				 db->drawnbutton.arm_callback, &call_value);
1024 	   }
1025        }
1026    }
1027    else {
1028      _XmPrimitiveEnter (wid, event, params, num_params);
1029 
1030      if (db -> drawnbutton.pushbutton_enabled &&
1031 	 db -> drawnbutton.armed == TRUE)
1032        DrawPushButton(db, TRUE);
1033    }
1034 }
1035 
1036 
1037 /************************************************************************
1038  *
1039  *  Leave
1040  *
1041  ************************************************************************/
1042 static void
Leave(Widget wid,XEvent * event,String * params,Cardinal * num_params)1043 Leave(
1044       Widget wid,
1045       XEvent *event,
1046       String *params,
1047       Cardinal *num_params )
1048 {
1049   XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
1050   XmDrawnButtonCallbackStruct call_value;
1051 
1052   if (Lab_IsMenupane(db)) {
1053     if (_XmGetInDragMode((Widget)db) && db->drawnbutton.armed &&
1054 	(/* !ActiveTearOff || */ event->xcrossing.mode == NotifyNormal))
1055       {
1056 	XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid));
1057 
1058 	db->drawnbutton.armed = FALSE;
1059 
1060 	((XmManagerWidget) XtParent(wid))->manager.active_child = NULL;
1061 
1062 	if (db->drawnbutton.pushbutton_enabled) {
1063 	  XmeClearBorder
1064 	    (XtDisplay (db), XtWindow (db),
1065 	     db->primitive.highlight_thickness,
1066 	     db->primitive.highlight_thickness,
1067 	     db->core.width - 2 * db->primitive.highlight_thickness,
1068 	     db->core.height - 2 * db->primitive.highlight_thickness,
1069 	     db->primitive.shadow_thickness);
1070 	}
1071 
1072 	if (db->drawnbutton.disarm_callback)
1073 	  {
1074 	    XFlush (XtDisplay (db));
1075 
1076 	    call_value.reason = XmCR_DISARM;
1077 	    call_value.event = event;
1078 	    XtCallCallbackList ((Widget) db,
1079 				db->drawnbutton.disarm_callback, &call_value);
1080 	  }
1081       }
1082   }
1083   else {
1084     _XmPrimitiveLeave (wid, event, params, num_params);
1085 
1086     if (db -> drawnbutton.pushbutton_enabled &&
1087 	db -> drawnbutton.armed == TRUE)
1088       DrawPushButton(db, FALSE);
1089   }
1090 }
1091 
1092 /*************************************<->*************************************
1093  *
1094  *  BorderHighlight
1095  *
1096  *************************************<->***********************************/
1097 
1098 static void
BorderHighlight(Widget wid)1099 BorderHighlight(
1100         Widget wid )
1101 {
1102   XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
1103   XmDrawnButtonCallbackStruct call_value;
1104   XEvent * event = NULL;
1105 
1106   if (Lab_IsMenupane(db)) {
1107     XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid));
1108     Boolean already_armed = db->drawnbutton.armed;
1109 
1110     db->drawnbutton.armed = TRUE;
1111 
1112     if (db->drawnbutton.pushbutton_enabled)
1113       DrawPushButton(db, db->drawnbutton.armed);
1114 
1115     if (!already_armed && db->drawnbutton.arm_callback)
1116       {
1117 	XFlush (XtDisplay (db));
1118 
1119 	call_value.reason = XmCR_ARM;
1120 	call_value.event = event;
1121 	XtCallCallbackList ((Widget) db, db->drawnbutton.arm_callback,
1122 			    &call_value);
1123       }
1124   }
1125   else {
1126     XtWidgetProc border_highlight;
1127 
1128     _XmProcessLock();
1129     border_highlight = xmLabelClassRec.primitive_class.border_highlight;
1130     _XmProcessUnlock();
1131     (*border_highlight)(wid);
1132   }
1133 
1134 }
1135 
1136 /*************************************<->*************************************
1137  *
1138  *  BorderUnhighlight
1139  *
1140  *************************************<->***********************************/
1141 
1142 static void
BorderUnhighlight(Widget wid)1143 BorderUnhighlight(
1144 		  Widget wid )
1145 {
1146   XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
1147   XmDrawnButtonCallbackStruct call_value;
1148   XEvent * event = NULL;
1149 
1150   if (Lab_IsMenupane(db))
1151     {
1152       XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid));
1153       Boolean already_armed = db->drawnbutton.armed;
1154 
1155       db->drawnbutton.armed = FALSE;
1156 
1157       if (db->drawnbutton.pushbutton_enabled) {
1158 	XmeClearBorder
1159 	  (XtDisplay (db), XtWindow (db),
1160 	   db->primitive.highlight_thickness,
1161 	   db->primitive.highlight_thickness,
1162 	   db->core.width - 2 * db->primitive.highlight_thickness,
1163 	   db->core.height - 2 * db->primitive.highlight_thickness,
1164 	   db->primitive.shadow_thickness);
1165       }
1166 
1167       if (already_armed && db->drawnbutton.disarm_callback)
1168 	{
1169 	  XFlush (XtDisplay (db));
1170 
1171 	  call_value.reason = XmCR_DISARM;
1172 	  call_value.event = event;
1173 	  XtCallCallbackList ((Widget) db, db->drawnbutton.disarm_callback,
1174 			      &call_value);
1175 	}
1176     }
1177   else {
1178     XtWidgetProc border_unhighlight;
1179 
1180     _XmProcessLock();
1181     border_unhighlight = xmLabelClassRec.primitive_class.border_unhighlight;
1182     _XmProcessUnlock();
1183     (*border_unhighlight)(wid);
1184   }
1185 }
1186 
1187 
1188 
1189 /************************************************************************
1190  *
1191  *  ClassInitialize
1192  *     Set up the base class extension record.
1193  *
1194  ************************************************************************/
1195 static void
ClassInitialize(void)1196 ClassInitialize( void )
1197 {
1198   /* parse the various translation tables */
1199   menu_parsed    = XtParseTranslationTable(menuTranslations);
1200   default_parsed = XtParseTranslationTable(defaultTranslations);
1201 
1202    /* set up base class extension quark */
1203    drawnBBaseClassExtRec.record_type = XmQmotif;
1204 }
1205 
1206 /************************************************************************
1207  *
1208  *  ClassPartInitialize
1209  *     Set up the fast subclassing for the widget
1210  *
1211  ************************************************************************/
1212 static void
ClassPartInitialize(WidgetClass wc)1213 ClassPartInitialize(
1214         WidgetClass wc )
1215 {
1216   _XmFastSubclassInit (wc, XmDRAWN_BUTTON_BIT);
1217 
1218   /* Install the menu savvy trait record,  copying fields from XmLabel */
1219   _XmLabelCloneMenuSavvy (wc, &MenuSavvyRecord);
1220 
1221   /* Install the activatable trait for all subclasses */
1222   XmeTraitSet((XtPointer)wc, XmQTactivatable, (XtPointer) &drawnButtonAT);
1223 }
1224 
1225 /************************************************************
1226  *
1227  * InitializePrehook
1228  *
1229  * Put the proper translations in core_class tm_table so that
1230  * the data is massaged correctly
1231  *
1232  ************************************************************/
1233 
1234 /*ARGSUSED*/
1235 static void
InitializePrehook(Widget rw,Widget nw,ArgList args,Cardinal * num_args)1236 InitializePrehook(
1237         Widget rw,		/* unused */
1238         Widget nw,
1239         ArgList args,		/* unused */
1240         Cardinal *num_args )	/* unused */
1241 {
1242   XmDrawnButtonWidget bw = (XmDrawnButtonWidget) nw ;
1243   unsigned char type;
1244   XmMenuSystemTrait menuSTrait;
1245 
1246   menuSTrait = (XmMenuSystemTrait)
1247     XmeTraitGet((XtPointer) XtClass(XtParent(nw)), XmQTmenuSystem);
1248 
1249   _XmSaveCoreClassTranslations (nw);
1250 
1251   if (menuSTrait != NULL)
1252     type = menuSTrait->type(XtParent(nw));
1253   else
1254     type = XmWORK_AREA;
1255 
1256   _XmProcessLock();
1257   if (type == XmMENU_PULLDOWN ||
1258       type == XmMENU_POPUP)
1259     nw->core.widget_class->core_class.tm_table = (String) menu_parsed;
1260   else
1261     nw->core.widget_class->core_class.tm_table = (String) default_parsed;
1262 
1263   /* CR 2990: Use XmNbuttonFontList as the default font. */
1264   if (bw->label.font == NULL)
1265     bw->label.font = XmeGetDefaultRenderTable (nw, XmBUTTON_FONTLIST);
1266   _XmProcessUnlock();
1267 }
1268 
1269 /************************************************************
1270  *
1271  * InitializePosthook
1272  *
1273  * restore core class translations
1274  *
1275  ************************************************************/
1276 
1277 /*ARGSUSED*/
1278 static void
InitializePosthook(Widget rw,Widget nw,ArgList args,Cardinal * num_args)1279 InitializePosthook(
1280         Widget rw,		/* unused */
1281         Widget nw,
1282         ArgList args,		/* unused */
1283         Cardinal *num_args )	/* unused */
1284 {
1285   _XmRestoreCoreClassTranslations (nw);
1286 }
1287 
1288 /*************************************<->*************************************
1289  *
1290  *  Initialize
1291  *
1292  *************************************<->***********************************/
1293 /*ARGSUSED*/
1294 static void
Initialize(Widget rw,Widget nw,ArgList args,Cardinal * num_args)1295 Initialize(
1296         Widget rw,
1297         Widget nw,
1298         ArgList args,
1299         Cardinal *num_args )
1300 {
1301    XmDrawnButtonWidget new_w = (XmDrawnButtonWidget) nw ;
1302    XmDrawnButtonWidget req_w = (XmDrawnButtonWidget) rw ;
1303 
1304    /* CR 2990:  Use XmNbuttonFontList as the default font. */
1305    if (req_w->label.font == NULL)
1306      {
1307        XmFontListFree (new_w->label.font);
1308        new_w->label.font =
1309 	 XmFontListCopy (XmeGetDefaultRenderTable (nw, XmBUTTON_FONTLIST));
1310      }
1311 
1312    new_w->drawnbutton.armed = FALSE;
1313    new_w->drawnbutton.timer = 0;
1314 
1315    /* if menuProcs is not set up yet, try again */
1316    if (xmLabelClassRec.label_class.menuProcs == (XmMenuProc)NULL)
1317       xmLabelClassRec.label_class.menuProcs =
1318 	 (XmMenuProc) _XmGetMenuProcContext();
1319 
1320    if(    !XmRepTypeValidValue( XmRID_SHADOW_TYPE,
1321                                new_w->drawnbutton.shadow_type, (Widget) new_w)    )
1322    {
1323       new_w -> drawnbutton.shadow_type = XmSHADOW_ETCHED_IN;
1324    }
1325 
1326 }
1327 
1328 /*************************************<->*************************************
1329  *
1330  *  Resize (db)
1331  *
1332  *************************************<->***********************************/
1333 static void
Resize(Widget wid)1334 Resize(
1335         Widget wid )
1336 {
1337    XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
1338    XmDrawnButtonCallbackStruct call_value;
1339    XtWidgetProc resize;
1340 
1341    _XmProcessLock();
1342    resize = xmLabelClassRec.core_class.resize;
1343    _XmProcessUnlock();
1344 
1345   (* resize) ((Widget) db);
1346 
1347    /* CR 5419: Suppress redundant calls to the resize callbacks. */
1348    if (db->drawnbutton.resize_callback &&
1349        !Lab_ComputingSize(db))
1350    {
1351       XFlush(XtDisplay (db));
1352       call_value.reason = XmCR_RESIZE;
1353       call_value.event = NULL;
1354       call_value.window = XtWindow (db);
1355       XtCallCallbackList ((Widget) db, db->drawnbutton.resize_callback, &call_value);
1356    }
1357 }
1358 
1359 
1360 /*************************************<->*************************************
1361  *
1362  *  Redisplay (db, event, region)
1363  *
1364  *************************************<->***********************************/
1365 /*ARGSUSED*/
1366 static void
Redisplay(Widget wid,XEvent * event,Region region)1367 Redisplay(
1368         Widget wid,
1369         XEvent *event,
1370         Region region )
1371 {
1372    XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
1373    XmDrawnButtonCallbackStruct call_value;
1374 
1375    if (XtIsRealized((Widget)db))
1376    {
1377         if (event) {
1378 	 XtExposeProc expose;
1379 
1380 	 _XmProcessLock();
1381 	 expose = xmLabelClassRec.core_class.expose;
1382 	 _XmProcessUnlock();
1383 
1384          (* expose) ((Widget) db, event, region);
1385         }
1386 
1387  	if (db->drawnbutton.pushbutton_enabled)
1388  	    DrawPushButton(db, db->drawnbutton.armed);
1389 
1390  	else
1391  	    XmeDrawShadows(XtDisplay((Widget) db),
1392  			    XtWindow((Widget) db),
1393  			    db -> primitive.top_shadow_GC,
1394  			    db -> primitive.bottom_shadow_GC,
1395  			    db -> primitive.highlight_thickness,
1396  			    db -> primitive.highlight_thickness,
1397  			    db -> core.width - 2 *
1398  			       db -> primitive.highlight_thickness,
1399  			    db -> core.height - 2 *
1400  			       db -> primitive.highlight_thickness,
1401 			    db -> primitive.shadow_thickness,
1402  			    db->drawnbutton.shadow_type);
1403 
1404       if (db->drawnbutton.expose_callback)
1405       {
1406          XFlush(XtDisplay (db));
1407 
1408 	 call_value.reason = XmCR_EXPOSE;
1409 	 call_value.event = event;
1410 	 call_value.window = XtWindow (db);
1411 	 XtCallCallbackList ((Widget) db, db->drawnbutton.expose_callback, &call_value);
1412       }
1413 
1414    }
1415 }
1416 
1417 
1418 static void
DrawPushButton(XmDrawnButtonWidget db,int armed)1419 DrawPushButton(
1420         XmDrawnButtonWidget db,
1421 #if NeedWidePrototypes
1422         int armed )
1423 #else
1424         Boolean armed )
1425 #endif /* NeedWidePrototypes */
1426 {
1427   XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay((Widget) db));
1428   Boolean etched_in = dpy -> display.enable_etched_in_menu;
1429   Boolean in_menu = Lab_IsMenupane((Widget) db);
1430   Boolean do_draw;
1431   unsigned int type;
1432 
1433   do_draw = (! in_menu) || (in_menu && armed);
1434 
1435   if (in_menu)
1436     type = etched_in ? XmSHADOW_IN : XmSHADOW_OUT;
1437   else
1438     type = armed ? XmSHADOW_IN : XmSHADOW_OUT;
1439 
1440   if (do_draw)
1441     XmeDrawShadows (XtDisplay (db), XtWindow (db),
1442 		    db -> primitive.top_shadow_GC,
1443 		    db -> primitive.bottom_shadow_GC,
1444 		    db -> primitive.highlight_thickness,
1445 		    db -> primitive.highlight_thickness,
1446 		    db -> core.width - 2 *
1447 		    db->primitive.highlight_thickness,
1448 		    db -> core.height - 2 *
1449 		    db->primitive.highlight_thickness,
1450 		    db -> primitive.shadow_thickness,
1451 		    type);
1452 }
1453 
1454 
1455 /************************************************************************
1456  *
1457  *  SetValuesPrehook
1458  *
1459  ************************************************************************/
1460 
1461 /*ARGSUSED*/
1462 static Boolean
SetValuesPrehook(Widget cw,Widget rw,Widget nw,ArgList args,Cardinal * num_args)1463 SetValuesPrehook(
1464         Widget cw,		/* unused */
1465         Widget rw,		/* unused */
1466         Widget nw,
1467         ArgList args,		/* unused */
1468         Cardinal *num_args )	/* unused */
1469 {
1470   XmDrawnButtonWidget bw = (XmDrawnButtonWidget) nw ;
1471 
1472   /* CR 2990: Use XmNbuttonFontList as the default font. */
1473   if (bw->label.font == NULL)
1474     bw->label.font = XmeGetDefaultRenderTable (nw, XmBUTTON_FONTLIST);
1475 
1476   return False;
1477 }
1478 
1479 /*************************************<->*************************************
1480  *
1481  *  SetValues(current, request, new_w)
1482  *
1483  *   Description:
1484  *   -----------
1485  *     This is the set values procedure for the drawnbutton class.  It is
1486  *     called last (the set values rtnes for its superclasses are called
1487  *     first).
1488  *
1489  *
1490  *   Inputs:
1491  *   ------
1492  *    current = original widget;
1493  *    request = original copy of request;
1494  *    new_w = copy of request which reflects changes made to it by
1495  *          set values procedures of its superclasses;
1496  *    last = TRUE if this is the last set values procedure to be called.
1497  *
1498  *   Outputs:
1499  *   -------
1500  *
1501  *   Procedures Called
1502  *   -----------------
1503  *
1504  *************************************<->***********************************/
1505 /*ARGSUSED*/
1506 static Boolean
SetValues(Widget cw,Widget rw,Widget nw,ArgList args,Cardinal * num_args)1507 SetValues(
1508         Widget cw,
1509         Widget rw,
1510         Widget nw,
1511         ArgList args,
1512         Cardinal *num_args )
1513 {
1514    XmDrawnButtonWidget current = (XmDrawnButtonWidget) cw ;
1515    XmDrawnButtonWidget new_w = (XmDrawnButtonWidget) nw ;
1516    Boolean  flag = FALSE;    /* our return value */
1517 
1518     /*  Check the data put into the new widget.  */
1519 
1520    if(    !XmRepTypeValidValue( XmRID_SHADOW_TYPE,
1521                                new_w->drawnbutton.shadow_type, (Widget) new_w)    )
1522    {
1523       new_w->drawnbutton.shadow_type = current->drawnbutton.shadow_type ;
1524    }
1525 
1526    if (new_w -> drawnbutton.shadow_type != current-> drawnbutton.shadow_type ||
1527        new_w -> primitive.foreground != current -> primitive.foreground    ||
1528        new_w -> core.background_pixel != current -> core.background_pixel  ||
1529        new_w -> primitive.highlight_thickness !=
1530        current -> primitive.highlight_thickness                          ||
1531        new_w -> primitive.shadow_thickness !=
1532        current -> primitive.shadow_thickness)
1533    {
1534       flag = TRUE;
1535    }
1536 
1537    return(flag);
1538 }
1539 
1540 
1541 
1542 
1543 /*************************************************************************
1544  *
1545  *  Realize
1546  *	This function sets the bit gravity to forget.
1547  *
1548  *************************************************************************/
1549 static void
Realize(Widget w,XtValueMask * p_valueMask,XSetWindowAttributes * attributes)1550 Realize(
1551         Widget w,
1552         XtValueMask *p_valueMask,
1553         XSetWindowAttributes *attributes )
1554 {
1555    Mask valueMask = *p_valueMask;
1556 
1557    valueMask |= CWBitGravity | CWDontPropagate;
1558    attributes->bit_gravity = ForgetGravity;
1559    attributes->do_not_propagate_mask =
1560       ButtonPressMask | ButtonReleaseMask |
1561       KeyPressMask | KeyReleaseMask | PointerMotionMask;
1562 
1563    XtCreateWindow (w, InputOutput, CopyFromParent, valueMask, attributes);
1564 }
1565 
1566 
1567 
1568 /************************************************************************
1569  *
1570  *  Destroy
1571  *	Clean up allocated resources when the widget is destroyed.
1572  *
1573  ************************************************************************/
1574 static void
Destroy(Widget wid)1575 Destroy(
1576         Widget wid )
1577 {
1578         XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ;
1579    if (db->drawnbutton.timer)
1580        XtRemoveTimeOut (db->drawnbutton.timer);
1581 }
1582 
1583 /************************************************************************
1584  *
1585  *  ChangeCB
1586  *	add or remove the activate callback list.
1587  *
1588  ************************************************************************/
1589 static void
ChangeCB(Widget w,XtCallbackProc activCB,XtPointer closure,Boolean setunset)1590 ChangeCB(
1591 	 Widget w,
1592 	 XtCallbackProc activCB,
1593 	 XtPointer closure,
1594 	 Boolean setunset)
1595 {
1596     if (setunset) {
1597 	XtAddCallback (w, XmNactivateCallback, activCB, closure);
1598     } else {
1599 	XtRemoveCallback (w, XmNactivateCallback, activCB, closure);
1600     }
1601 }
1602 
1603 
1604 /************************************************************************
1605  *
1606  *		Application Accessible External Functions
1607  *
1608  ************************************************************************/
1609 
1610 
1611 /************************************************************************
1612  *
1613  *  XmCreateDrawnButton
1614  *	Create an instance of a drawnbutton and return the widget id.
1615  *
1616  ************************************************************************/
1617 Widget
XmCreateDrawnButton(Widget parent,char * name,ArgList arglist,Cardinal argcount)1618 XmCreateDrawnButton(
1619         Widget parent,
1620         char *name,
1621         ArgList arglist,
1622         Cardinal argcount )
1623 {
1624    return (XtCreateWidget (name, xmDrawnButtonWidgetClass,
1625                            parent, arglist, argcount));
1626 }
1627 
1628 Widget
XmVaCreateDrawnButton(Widget parent,char * name,...)1629 XmVaCreateDrawnButton(
1630         Widget parent,
1631         char *name,
1632         ...)
1633 {
1634     register Widget w;
1635     va_list var;
1636     int count;
1637 
1638     Va_start(var,name);
1639     count = XmeCountVaListSimple(var);
1640     va_end(var);
1641 
1642 
1643     Va_start(var, name);
1644     w = XmeVLCreateWidget(name,
1645                          xmDrawnButtonWidgetClass,
1646                          parent, False,
1647                          var, count);
1648     va_end(var);
1649     return w;
1650 }
1651 
1652 Widget
XmVaCreateManagedDrawnButton(Widget parent,char * name,...)1653 XmVaCreateManagedDrawnButton(
1654         Widget parent,
1655         char *name,
1656         ...)
1657 {
1658     Widget w = NULL;
1659     va_list var;
1660     int count;
1661 
1662     Va_start(var, name);
1663     count = XmeCountVaListSimple(var);
1664     va_end(var);
1665 
1666     Va_start(var, name);
1667     w = XmeVLCreateWidget(name,
1668                          xmDrawnButtonWidgetClass,
1669                          parent, True,
1670                          var, count);
1671     va_end(var);
1672     return w;
1673 }
1674