1 /*----------------------------------------------------------------------------
2 --
3 --  Module:           XitRwPixButton
4 --
5 --  Project:          XitRw - Rogge's Motif widgets
6 --  System:           <>
7 --    Subsystem:      <>
8 --    Function block: <>
9 --
10 --  Description:
11 --    This is the implementation file for the widget.
12 --    A Pix button can display both a text and a pixmap.
13 --
14 --  Filename:         xitRwPixB.c
15 --
16 --  Authors:          Roger Larsson, Ulrika Bornetun
17 --  Creation date:    1992-10-17
18 --
19 --
20 --  (C) Copyright Ulrika Bornetun, Roger Larsson (1995)
21 --      All rights reserved
22 --
23 --  Permission to use, copy, modify, and distribute this software and its
24 --  documentation for any purpose and without fee is hereby granted,
25 --  provided that the above copyright notice appear in all copies. Ulrika
26 --  Bornetun and Roger Larsson make no representations about the usability
27 --  of this software for any purpose. It is provided "as is" without express
28 --  or implied warranty.
29 ----------------------------------------------------------------------------*/
30 
31 /* SCCS module identifier. */
32 static char SCCSID[] = "@(#) Module: xitRwPixB.c, Version: 1.1, Date: 95/02/18 15:10:46";
33 
34 
35 /*----------------------------------------------------------------------------
36 --  Include files
37 ----------------------------------------------------------------------------*/
38 
39 #include <stdio.h>
40 
41 #include <X11/IntrinsicP.h>
42 #include <X11/StringDefs.h>
43 
44 #include <Xm/XmP.h>
45 #include <xitTools.h>
46 
47 #if XmVersion > 1001
48 #  include <Xm/PrimitiveP.h>
49 #endif
50 
51 #include "xitRwPixBP.h"
52 
53 
54 /*----------------------------------------------------------------------------
55 --  Macro definitions
56 ----------------------------------------------------------------------------*/
57 
58 #define max( a, b )  ((a) < (b) ? (b) : (a) )
59 
60 #define DEFAULT_MARGIN       2
61 #define DEFAULT_MARGIN_NULL  0
62 #define INSENS_WIDTH         10
63 #define INSENS_HEIGHT        10
64 
65 #define XmRPixmapPosition    "PixmapPosition"
66 
67 
68 /*----------------------------------------------------------------------------
69 --  Type declarations
70 ----------------------------------------------------------------------------*/
71 
72 typedef int pixmapPosition;
73 
74 
75 /*----------------------------------------------------------------------------
76 --  Global definitions
77 ----------------------------------------------------------------------------*/
78 
79 static void
80   Activate( Widget  w,
81             XEvent  *event );
82 
83 static void
84   Arm( Widget  w,
85        XEvent  *event );
86 
87 static void
88   ArmAndActivate( Widget   w,
89 		  XEvent   *event );
90 
91 static void
92   Disarm( Widget   w,
93 	  XEvent   *event,
94 	  String   *params,
95 	  Cardinal num_params );
96 
97 static void
98   Enter( Widget   w,
99 	 XEvent   *event,
100 	 String   *params,
101 	 Cardinal num_params );
102 
103 static void
104   PixButFocusIn( Widget   w,
105                  XEvent   *event,
106                  String   *params,
107                  Cardinal num_params );
108 
109 static void
110   PixButFocusOut( Widget   w,
111                   XEvent   *event,
112                   String   *params,
113                   Cardinal num_params );
114 
115 static void
116   Leave( Widget   w,
117 	 XEvent   *event,
118 	 String   *params,
119 	 Cardinal num_params );
120 
121 static void
122   TraverseNextTabGroup( Widget   w,
123                         XEvent   *event,
124 	                String   *params,
125 	                Cardinal num_params );
126 
127 static void
128   TraversePrevTabGroup( Widget   w,
129                         XEvent   *event,
130 	                String   *params,
131 	                Cardinal num_params );
132 
133 static void
134   TraverseDown( Widget   w,
135                 XEvent   *event,
136 	        String   *params,
137 	        Cardinal num_params );
138 static void
139   TraverseHome( Widget   w,
140                 XEvent   *event,
141 	        String   *params,
142 	        Cardinal num_params );
143 static void
144   TraverseLeft( Widget   w,
145                 XEvent   *event,
146 	        String   *params,
147 	        Cardinal num_params );
148 static void
149   TraverseRight( Widget   w,
150                  XEvent   *event,
151 	         String   *params,
152 	         Cardinal num_params );
153 static void
154   TraverseUp( Widget   w,
155               XEvent   *event,
156 	      String   *params,
157 	      Cardinal num_params );
158 
159 static void
160   Unmap( Widget   w,
161          XEvent   *event,
162          String   *params,
163          Cardinal num_params );
164 
165 
166 /* Resource converters. */
167 static void
168   ConvertToPixmapPosition( XrmValue   *args,
169                            Cardinal   *num_args,
170                            XrmValue   *from,
171                            XrmValue   *to );
172 
173 /* Resource list. */
174 static XtResource resources[] = {
175   {
176     XmNactivateCallback,
177     XmCCallback,
178     XmRCallback, sizeof( XtCallbackList ),
179     XtOffset( XitRwPixButtonWidget, pixBut.activate_callback ),
180     XmRPointer,
181     (XtPointer) NULL
182   },
183   {
184     XmNalignment,
185     XmCAlignment,
186     XmRAlignment, sizeof( unsigned char ),
187     XtOffset( XitRwPixButtonWidget, pixBut.alignment ),
188     XmRImmediate,
189     (XtPointer) XmALIGNMENT_CENTER
190   },
191   {
192     XmNarmCallback,
193     XmCCallback,
194     XmRCallback, sizeof( XtCallbackList ),
195     XtOffset( XitRwPixButtonWidget, pixBut.arm_callback ),
196     XmRPointer,
197     (XtPointer) NULL
198   },
199   {
200     XmNdisarmCallback,
201     XmCCallback,
202     XmRCallback, sizeof( XtCallbackList ),
203     XtOffset( XitRwPixButtonWidget, pixBut.disarm_callback ),
204     XmRPointer,
205     (XtPointer) NULL
206   },
207   {
208     XmNfontList,
209     XmCFontList,
210     XmRFontList, sizeof( XmFontList ),
211     XtOffset( XitRwPixButtonWidget, pixBut.font_list ),
212     XmRString,
213     (XtPointer) "Fixed"
214   },
215   {
216     XmNlabelPixmap,
217     XmCLabelPixmap,
218     XmRInt, sizeof( Pixmap ),
219     XtOffset( XitRwPixButtonWidget, pixBut.pixmap ),
220     XtRImmediate,
221     (XtPointer) XmUNSPECIFIED_PIXMAP
222   },
223   {
224     XmNlabelString,
225     XmCLabelString,
226     XmRString, sizeof( XmString ),
227     XtOffset( XitRwPixButtonWidget, pixBut.label ),
228     XtRImmediate,
229     NULL
230   },
231   {
232     XmNmarginHeight,
233     XmCMarginHeight,
234     XtRInt, sizeof( int ),
235     XtOffset( XitRwPixButtonWidget, pixBut.margin_height ),
236     XtRImmediate,
237     (XtPointer) DEFAULT_MARGIN
238   },
239   {
240     XmNmarginWidth,
241     XmCMarginWidth,
242     XtRInt, sizeof( int ),
243     XtOffset( XitRwPixButtonWidget, pixBut.margin_width ),
244     XtRImmediate,
245     (XtPointer) DEFAULT_MARGIN
246   },
247   {
248     XmNmarginTop,
249     XmCMarginTop,
250     XtRInt, sizeof( int ),
251     XtOffset( XitRwPixButtonWidget, pixBut.top_margin ),
252     XtRImmediate,
253     (XtPointer) DEFAULT_MARGIN_NULL
254   },
255   {
256     XmNmarginLeft,
257     XmCMarginLeft,
258     XtRInt, sizeof( int ),
259     XtOffset( XitRwPixButtonWidget, pixBut.left_margin ),
260     XtRImmediate,
261     (XtPointer) DEFAULT_MARGIN_NULL
262   },
263   {
264     XmNmarginRight,
265     XmCMarginRight,
266     XtRInt, sizeof( int ),
267     XtOffset( XitRwPixButtonWidget, pixBut.right_margin ),
268     XtRImmediate,
269     (XtPointer) DEFAULT_MARGIN_NULL
270   },
271   {
272     XmNmarginBottom,
273     XmCMarginBottom,
274     XtRInt, sizeof( int ),
275     XtOffset( XitRwPixButtonWidget, pixBut.bottom_margin ),
276     XtRImmediate,
277     (XtPointer) DEFAULT_MARGIN_NULL
278   },
279   {
280     XitRwNoppositeAlignment,
281     XmCAlignment,
282     XmRAlignment, sizeof( unsigned char ),
283     XtOffset( XitRwPixButtonWidget, pixBut.opposite_alignment ),
284     XmRImmediate,
285     (XtPointer) XmALIGNMENT_CENTER
286   },
287   {
288     XitRwNpixmapPosition,
289     XitRwCPixmapPosition,
290     XmRPixmapPosition, sizeof( int ),
291     XtOffset( XitRwPixButtonWidget, pixBut.pixmap_position ),
292     XtRImmediate,
293     (XtPointer) XitRwLEFT
294   },
295   {
296     XmNrecomputeSize,
297     XmCRecomputeSize,
298     XtRBoolean, sizeof( Boolean ),
299     XtOffset( XitRwPixButtonWidget, pixBut.recompute_size ),
300     XtRImmediate,
301     (XtPointer) True
302   },
303   {
304     XmNshadowType,
305     XmCShadowType,
306     XmRShadowType, sizeof( unsigned char ),
307     XtOffset( XitRwPixButtonWidget, pixBut.shadow_type ),
308     XmRImmediate,
309     (XtPointer) XmSHADOW_OUT
310   },
311   {
312     XmNspacing,
313     XmCSpacing,
314     XtRInt, sizeof( int ),
315     XtOffset( XitRwPixButtonWidget, pixBut.spacing ),
316     XtRImmediate,
317     (XtPointer) DEFAULT_MARGIN
318   },
319 };
320 
321 
322 /* Pixmap for insensitive pixmap. */
323 static unsigned char insens_bits[] = {
324    0x55, 0x01, 0xaa, 0x02, 0x55, 0x01, 0xaa, 0x02, 0x55, 0x01, 0xaa, 0x02,
325    0x55, 0x01, 0xaa, 0x02, 0x55, 0x01, 0xaa, 0x02};
326 
327 /* Action list. */
328 static XtActionsRec actionsList[] =
329 {
330   { "Activate",              (XtActionProc) Activate },
331   { "Arm",                   (XtActionProc) Arm },
332   { "ArmAndActivate",        (XtActionProc) ArmAndActivate },
333   { "PrimitiveNextTabGroup", (XtActionProc) TraverseNextTabGroup },
334   { "PrimitivePrevTabGroup", (XtActionProc) TraversePrevTabGroup },
335   { "PrimitiveTabDown",      (XtActionProc) TraverseDown },
336   { "PrimitiveTabHome",      (XtActionProc) TraverseHome },
337   { "PrimitiveTabLeft",      (XtActionProc) TraverseLeft },
338   { "PrimitiveTabRight",     (XtActionProc) TraverseRight },
339   { "PrimitiveTabUp",        (XtActionProc) TraverseUp },
340   { "Disarm",                (XtActionProc) Disarm },
341   { "Enter",                 (XtActionProc) Enter },
342   { "FocusIn",               (XtActionProc) PixButFocusIn },
343   { "FocusOut",              (XtActionProc) PixButFocusOut },
344   { "Leave",                 (XtActionProc) Leave },
345   { "Unmap",                 (XtActionProc) Unmap },
346 };
347 
348 
349 /* Default translation list. */
350 static char defaultTranslations[] =
351   "<Btn1Down>:     Arm()                \n\
352    <Btn1Up>:       Activate() Disarm()  \n\
353    <EnterWindow>:  Enter()              \n\
354    <FocusIn>:      FocusIn()            \n\
355    <FocusOut>:     FocusOut()           \n\
356    <LeaveWindow>:  Leave()              \n\
357    <Key>Return:    ArmAndActivate()     \n\
358    <Key>space:     ArmAndActivate()     \n\
359    <Key>Home:      PrimitiveTabHome()   \n\
360    <Key>Down:      PrimitiveTabDown()   \n\
361    <Key>Left:      PrimitiveTabLeft()   \n\
362    <Key>Right:     PrimitiveTabRight()  \n\
363    <Key>Up:        PrimitiveTabUp()     \n\
364    <Key>osfDown:   PrimitiveTabDown()   \n\
365    <Key>osfLeft:   PrimitiveTabLeft()   \n\
366    <Key>osfRight:  PrimitiveTabRight()  \n\
367    <Key>osfUp:     PrimitiveTabUp()     \n\
368    ~Ctrl ~Alt ~Meta ~Shift<Key>Tab:  PrimitiveNextTabGroup() \n\
369    ~Ctrl ~Alt ~Meta  Shift<Key>Tab:  PrimitivePrevTabGroup() \n\
370    <Unmap>:        Unmap()";
371 
372 
373 /* Quarks. */
374 static XrmQuark   quark_bottom;
375 static XrmQuark   quark_left;
376 static XrmQuark   quark_right;
377 static XrmQuark   quark_top;
378 
379 
380 
381 /*----------------------------------------------------------------------------
382 --  Function prototypes
383 ----------------------------------------------------------------------------*/
384 
385 /* Core methods. */
386 static void
387   ClassInitialize();
388 
389 static void
390   Destroy( Widget  widget );
391 
392 static void
393   ExposeIt( Widget  widget,
394             XEvent  *event,
395             Region  region );
396 
397 static void
398   Initialize( Widget    treq,
399               Widget    tnew,
400               ArgList   args,
401               Cardinal  *num_args );
402 
403 static XtGeometryResult
404   QueryGeometry( Widget             widget,
405                  XtWidgetGeometry  *proposed,
406                  XtWidgetGeometry  *answer );
407 
408 static void
409   Resize( Widget  widget );
410 
411 static Boolean
412   SetValues( Widget    current,
413              Widget    request,
414              Widget    new,
415              ArgList   args,
416              Cardinal  *num_args );
417 
418 /* These core methods are not needed.
419 --
420 --  static void Realize();
421 --
422 */
423 
424 /* Local functions. */
425 static void
426   DesiredDimensions( Widget     widget,
427                      Boolean    override_no_recompute,
428                      Dimension  *width,
429                      Dimension  *height );
430 
431 static void
432   DrawButton( Widget   widget,
433               Boolean  draw_as_armed );
434 
435 static void
436   DrawShadow( Widget   widget,
437               Boolean  armed );
438 
439 static void
440   GetDrawingGC( Widget  widget );
441 
442 static void
443   SetComponentDimensions( Widget  widget );
444 
445 static void
446   SetComponentPositions( Widget  widget );
447 
448 
449 /*----------------------------------------------------------------------------
450 --  Initialization of the class record.
451 ----------------------------------------------------------------------------*/
452 
453 /* This initialization has to be done after the methods have been declared. */
454 XitRwPixButtonClassRec xitRwPixButtonClassRec = {
455 
456   { /* Core class fields. */
457     /* superclass */                  (WidgetClass) &xmPrimitiveClassRec,
458     /* class_name */                  "XitRwPixButton",
459     /* widget_size */                 sizeof( XitRwPixButtonRec ),
460     /* class_initialize */            ClassInitialize,
461     /* class_part_initialize */       NULL,
462     /* class_inited */                False,
463     /* initialize */                  Initialize,
464     /* initialize_hook */             NULL,
465     /* realize */                     XtInheritRealize,
466     /* actions */                     actionsList,
467     /* num_actions */                 XtNumber( actionsList ),
468     /* resources */                   resources,
469     /* num_resources */               XtNumber( resources ),
470     /* xrm_class */                   NULLQUARK,
471     /* compress_motion */             True,
472     /* compress_exposure */           True,
473     /* compress_enterleave */         True,
474     /* visible_interest */            False,
475     /* destroy */                     Destroy,
476     /* resize */                      Resize,
477     /* expose */                      ExposeIt,
478     /* set_values */                  SetValues,
479     /* set_values_hook */             NULL,
480     /* set_values_almost */           XtInheritSetValuesAlmost,
481     /* get_values_hook */             NULL,
482     /* accept_focus */                NULL,
483     /* version */                     XtVersion,
484     /* callback_private */            NULL,
485     /* tm_table */                    defaultTranslations,
486     /* query_geometry */              QueryGeometry,
487     /* display_accelerator */         XtInheritDisplayAccelerator,
488     /* extension */                   NULL
489   },
490   { /* Primitive class part. */
491     /* border_highlight */            (XtWidgetProc) _XtInherit,
492     /* border_unhighlight */          (XtWidgetProc) _XtInherit,
493     /* translations */                NULL,
494 #if XmVersion < 1002
495     /* arm_and_activate */            (XmArmAndActivate) ArmAndActivate,
496 #else
497     /* arm_and_activate */            (XtActionProc) ArmAndActivate,
498 #endif
499     /* get_resources */               NULL,
500     /* num_get_resources */           0,
501     /* extension */                   NULL
502   },
503   { /* PixBut button class part. */
504     /* extension */                   NULL
505   },
506 
507 }; /* XitRwPixButtonClassRec */
508 
509 
510 /* Class record pointer. */
511 WidgetClass
512   xitRwPixButtonWidgetClass = (WidgetClass) &xitRwPixButtonClassRec;
513 
514 
515 /*----------------------------------------------------------------------------
516 --  Functions
517 ----------------------------------------------------------------------------*/
518 
519 static void
Activate(Widget w,XEvent * event)520   Activate( Widget  w,
521             XEvent  *event )
522 {
523 
524   /* Variables. */
525   XitRwPixButtonWidget  cb;
526   XmAnyCallbackStruct   callback_info;
527 
528 
529   /* Code. */
530 
531   cb = (XitRwPixButtonWidget) w;
532 
533   /* Event outside window? */
534   if( ((event->type == ButtonPress) ||
535        (event->type == ButtonRelease)) &&
536       ((event->xbutton.x > cb -> core.width) ||
537        (event->xbutton.y > cb -> core.height )) )
538     return;
539 
540 
541   /* Callback. */
542   if( cb -> pixBut.activate_callback != NULL ) {
543 
544     /* Prepare callback data. */
545     callback_info.reason = XmCR_ACTIVATE;
546     callback_info.event  = event;
547 
548     /* Call the activate callback. */
549     XtCallCallbacks( (Widget) cb, XmNactivateCallback,
550                      (XtPointer) &callback_info );
551 
552   }
553 
554   return;
555 
556 } /* Activate */
557 
558 
559 /*---------------------------------------------------------------------------*/
560 
561 static void
Arm(Widget w,XEvent * event)562   Arm( Widget  w,
563        XEvent  *event )
564 {
565 
566   /* Variables. */
567   XitRwPixButtonWidget  cb;
568   XmAnyCallbackStruct   callback_info;
569 
570 
571   /* Code. */
572 
573   cb = (XitRwPixButtonWidget) w;
574 
575   /* Grab traversal. */
576   /* Grab focus. */
577   XmProcessTraversal( w, XmTRAVERSE_CURRENT );
578 
579   cb -> pixBut.armed = True;
580   DrawButton( (Widget) cb, True );
581 
582   if( cb -> pixBut.arm_callback != NULL ) {
583     XFlush( XtDisplay( (Widget) cb ) );
584 
585     /* Prepare callback data. */
586     callback_info.reason = XmCR_ARM;
587     callback_info.event  = event;
588 
589     XtCallCallbacks( (Widget) cb, XmNarmCallback, (XtPointer) &callback_info );
590   }
591 
592 
593   return;
594 
595 } /* Arm */
596 
597 
598 /*---------------------------------------------------------------------------*/
599 
600 static void
ArmAndActivate(Widget w,XEvent * event)601   ArmAndActivate( Widget   w,
602 		  XEvent   *event )
603 {
604 
605   /* Variables. */
606   XitRwPixButtonWidget  cb;
607 
608   /* Code. */
609   cb = (XitRwPixButtonWidget) w;
610 
611   /* Activate called by keyboard event. Arm during callback. */
612   Arm( w, event );
613 
614   Activate( w, event );
615 
616   /* Disarm and draw it. */
617   cb -> pixBut.armed = False;
618   DrawButton( (Widget) cb, False );
619 
620   XFlush( XtDisplay( (Widget) cb ));
621 
622 
623   return;
624 
625 } /* ArmAndActivate */
626 
627 
628 /*---------------------------------------------------------------------------*/
629 
630 static void
ClassInitialize()631   ClassInitialize()
632 {
633 
634   /* Code. */
635 
636   /* Convert quarks for comparison. */
637   quark_bottom = XrmStringToQuark( "BOTTOM" );
638   quark_left   = XrmStringToQuark( "LEFT" );
639   quark_right  = XrmStringToQuark( "RIGHT" );
640   quark_top    = XrmStringToQuark( "TOP" );
641 
642   /* Register type converter for XitRwCPixmapPosition. */
643   XtAddConverter( XmRString, XmRPixmapPosition, ConvertToPixmapPosition,
644                   NULL, 0 );
645 
646 
647   return;
648 
649 } /* ClassInitialize */
650 
651 
652 /*---------------------------------------------------------------------------*/
653 
654 static void
ConvertToPixmapPosition(XrmValue * args,Cardinal * num_args,XrmValue * from,XrmValue * to)655   ConvertToPixmapPosition( XrmValue  *args,
656                            Cardinal  *num_args,
657                            XrmValue  *from,
658                            XrmValue  *to )
659 {
660 
661   /* Variables. */
662   XrmQuark    quark_resource;
663   static int  pixmap_value;
664 
665 
666   /* Code. */
667 
668   if( *num_args != 0 )
669     XtWarningMsg( "wrongParameters", "ConvertToPixmapPosition",
670       "XtToolkitError", "Conversion needs no extra arguments",
671       (String *) NULL, (Cardinal *) NULL );
672 
673   /* Convert argument. */
674   quark_resource = XrmStringToQuark( from -> addr );
675 
676   if( quark_resource == quark_bottom )
677     pixmap_value = XitRwBOTTOM;
678   else if( quark_resource == quark_left )
679     pixmap_value = XitRwLEFT;
680   else if( quark_resource == quark_right )
681     pixmap_value = XitRwRIGHT;
682   else if( quark_resource == quark_top )
683     pixmap_value = XitRwTOP;
684   else {
685     XtWarningMsg( "wrongParameters", "ConvertToPixmapPosition",
686       "XtToolkitError", "Cannot convert to type pixmapPosition",
687       (String *) NULL, (Cardinal *) 0 );
688     pixmap_value = XitRwLEFT;
689   }
690 
691   (*to).size = sizeof( int );
692   (*to).addr = (XtPointer) &pixmap_value;
693 
694 
695   return;
696 
697 } /* ConvertToPixmapPosition */
698 
699 
700 /*---------------------------------------------------------------------------*/
701 
702 static void
DesiredDimensions(Widget widget,Boolean override_no_recompute,Dimension * width,Dimension * height)703   DesiredDimensions( Widget     widget,
704                      Boolean    override_no_recompute,
705                      Dimension  *width,
706                      Dimension  *height )
707 {
708 
709   /* Variables. */
710   XitRwPixButtonWidget  cb;
711 
712 
713   /* Code. */
714 
715   cb = (XitRwPixButtonWidget) widget;
716 
717   if( cb -> pixBut.user_set_width ||
718       ( !cb -> pixBut.recompute_size && !override_no_recompute ) )
719     *width = cb -> core.width;
720 
721   /* Adapt size to contents. */
722   else {
723     /* Basic margins are always counted. */
724     *width  = (Dimension)( 2 * cb -> pixBut.margin_width +
725 			   cb -> pixBut.left_margin +
726 			   cb -> pixBut.right_margin +
727 			   2 * (int) cb -> primitive.shadow_thickness +
728 			   2 * (int) cb -> primitive.highlight_thickness );
729 
730     switch( cb -> pixBut.pixmap_position ) {
731 
732       case XitRwLEFT:
733       case XitRwRIGHT:
734 	/* Horizontal organization. */
735 	*width  += (Dimension) ( cb -> pixBut.spacing +
736 				 cb -> pixBut.pixmap_width +
737 				 cb -> pixBut.string_width );
738 	break;
739 
740       case XitRwTOP:
741       case XitRwBOTTOM:
742 	/* Vertical organization. */
743 	*width  += max( (Dimension) cb -> pixBut.string_width,
744 			(Dimension) cb -> pixBut.pixmap_width );
745 	break;
746 
747     } /* switch */
748   }
749 
750   if( cb -> pixBut.user_set_height ||
751       ( !cb -> pixBut.recompute_size && !override_no_recompute ) )
752     *height = cb -> core.height;
753 
754   /* Adapt size to contents. */
755   else {
756     *height = (Dimension)( 2 * cb -> pixBut.margin_height +
757 			   cb -> pixBut.top_margin +
758 			   cb -> pixBut.bottom_margin +
759 			   2 * (int) cb -> primitive.shadow_thickness +
760 			   2 * (int) cb -> primitive.highlight_thickness );
761 
762     switch( cb -> pixBut.pixmap_position ) {
763 
764       case XitRwLEFT:
765       case XitRwRIGHT:
766 	/* Horizontal organization. */
767 	*height += max( (Dimension) cb -> pixBut.string_height,
768 			(Dimension) cb -> pixBut.pixmap_height );
769 	break;
770 
771       case XitRwTOP:
772       case XitRwBOTTOM:
773 	/* Vertical organization. */
774 	*height += (Dimension) ( cb -> pixBut.spacing +
775 				 cb -> pixBut.pixmap_height +
776 				 cb -> pixBut.string_height );
777 	break;
778 
779     } /* switch */
780 
781   }
782 
783 
784   return;
785 
786 } /* DesiredDimensions */
787 
788 
789 /*---------------------------------------------------------------------------*/
790 
791 static void
Destroy(Widget widget)792   Destroy( Widget  widget )
793 {
794 
795   /* Variables. */
796   XitRwPixButtonWidget  cb;
797 
798 
799   /* Code. */
800 
801   cb = (XitRwPixButtonWidget) widget;
802 
803   /* Free gc's */
804   if( cb -> pixBut.gc != NULL )
805     XtReleaseGC( (Widget) cb, cb -> pixBut.gc );
806 
807   if( cb -> pixBut.clear_gc != NULL )
808     XtReleaseGC( (Widget) cb, cb -> pixBut.clear_gc );
809 
810   if( cb -> pixBut.select_gc != NULL )
811     XtReleaseGC( (Widget) cb, cb -> pixBut.select_gc );
812 
813   if( cb -> pixBut.select_clear_gc != NULL )
814     XtReleaseGC( (Widget) cb, cb -> pixBut.select_clear_gc );
815 
816   if( cb -> pixBut.insensitive_gc != NULL )
817     XtReleaseGC( (Widget) cb, cb -> pixBut.insensitive_gc );
818 
819   /* Free allocated string. */
820   if( cb -> pixBut.label != NULL )
821     XmStringFree( cb -> pixBut.label );
822 
823   /* Free insensitive pixmap. */
824   if( cb -> pixBut.insensitive_pixmap != (XID) NULL )
825     XFreePixmap( XtDisplay( (Widget) cb ), cb -> pixBut.insensitive_pixmap );
826 
827 
828   return;
829 
830 } /* Destroy */
831 
832 
833 /*---------------------------------------------------------------------------*/
834 
835 static void
Disarm(Widget w,XEvent * event,String * params,Cardinal num_params)836   Disarm( Widget    w,
837 	  XEvent    *event,
838 	  String    *params,
839 	  Cardinal  num_params )
840 {
841 
842   /* Variables. */
843   XitRwPixButtonWidget  cb;
844   XmAnyCallbackStruct   callback_info;
845 
846 
847   /* Code. */
848 
849   cb = (XitRwPixButtonWidget) w;
850 
851   if( cb -> pixBut.armed ) {
852     cb -> pixBut.armed = False;
853     DrawButton( (Widget) cb, False );
854   }
855 
856   if( cb -> pixBut.disarm_callback != NULL ) {
857     XFlush( XtDisplay( (Widget) cb ) );
858 
859     /* Prepare callback data. */
860     callback_info.reason = XmCR_DISARM;
861     callback_info.event  = event;
862 
863     XtCallCallbacks( (Widget) cb, XmNdisarmCallback,
864                      (XtPointer) &callback_info );
865   }
866 
867 
868   return;
869 
870 } /* Disarm */
871 
872 
873 /*---------------------------------------------------------------------------*/
874 
875 static void
DrawButton(Widget widget,Boolean draw_as_armed)876   DrawButton( Widget   widget,
877               Boolean  draw_as_armed )
878 {
879 #if XmVERSION > 1
880   /* these Motif 1.1 calls are obsoleted in Motif 2.0 */
881   /* they aren't declared by any Motif 2.0 header file */
882   /* 040597 RXTN */
883   extern void _XmHighlightBorder( Widget );
884   extern void _XmUnhighlightBorder( Widget );
885 #endif
886 
887   /* Variables. */
888   GC                    clear_gc;
889   GC                    normal_gc;
890   XitRwPixButtonWidget  cb;
891 
892 
893   /* Code. */
894 
895   cb = (XitRwPixButtonWidget) widget;
896 
897   clear_gc  = ( draw_as_armed ? cb -> pixBut.select_clear_gc :
898                                 cb -> pixBut.clear_gc );
899   normal_gc = ( draw_as_armed ? cb -> pixBut.select_gc :
900                                 cb -> pixBut.gc );
901 
902 
903   /* Clear the button for redraw. */
904   XFillRectangle( XtDisplay( widget ), cb -> core.window,
905                   clear_gc, 0, 0,
906                   (unsigned int) cb -> core.width,
907                   (unsigned int) cb -> core.height );
908 
909   /* Draw pixmap. */
910   if( cb -> pixBut.pixmap != XmUNSPECIFIED_PIXMAP )
911     XCopyArea( XtDisplay( widget ), cb -> pixBut.pixmap,
912                cb -> core.window, normal_gc, 0, 0,
913                cb -> pixBut.pixmap_width,
914                cb -> pixBut.pixmap_height,
915                cb -> pixBut.x_pixmap,
916                cb -> pixBut.y_pixmap );
917 
918   /* Draw string. */
919   if( cb -> pixBut.label != NULL )
920     XmStringDraw( XtDisplay( widget ),
921                   cb -> core.window, cb -> pixBut.font_list,
922 		  cb -> pixBut.label, normal_gc,
923 		  cb -> pixBut.x_string, cb -> pixBut.y_string,
924 		  (Dimension) cb -> pixBut.string_width,
925                   XmALIGNMENT_BEGINNING,
926 		  XmSTRING_DIRECTION_L_TO_R, NULL );
927 
928   /* Insensitive state. Stipple it. */
929   if( ! cb -> core.sensitive )
930     XFillRectangle( XtDisplay( widget ), cb -> core.window,
931                     cb -> pixBut.insensitive_gc,
932                     0, 0,
933                     (unsigned int) cb -> core.width,
934                     (unsigned int) cb -> core.height );
935 
936   /* Shadows. */
937   DrawShadow( (Widget) cb, draw_as_armed );
938 
939   /* Highlight? */
940   if( cb -> primitive.highlighted )
941     _XmHighlightBorder( (Widget) cb );
942   else
943     _XmUnhighlightBorder( (Widget) cb );
944 
945 
946 } /* DrawButton */
947 
948 
949 /*---------------------------------------------------------------------------*/
950 
951 static void
DrawShadow(Widget widget,Boolean armed)952   DrawShadow( Widget   widget,
953               Boolean  armed )
954 {
955 
956   /* Variables. */
957   Boolean               shadow_in;
958   GC                    bottom_gc;
959   GC                    top_gc;
960   XitRwPixButtonWidget  cb;
961 
962 
963   /* Code. */
964 
965   if( ! xitIsRealized( widget ) )
966     return;
967 
968   cb = (XitRwPixButtonWidget) widget;
969 
970   if( cb -> primitive.shadow_thickness == 0 )
971     return;
972 
973 
974   /* Find out shadow type. */
975   shadow_in = (( cb -> pixBut.shadow_type == XmSHADOW_IN )  && !armed ) ||
976               (( cb -> pixBut.shadow_type == XmSHADOW_OUT ) && armed );
977 
978   if( shadow_in ) {
979     top_gc    = cb -> primitive.bottom_shadow_GC;
980     bottom_gc = cb -> primitive.top_shadow_GC;
981   } else {
982     top_gc    = cb -> primitive.top_shadow_GC;
983     bottom_gc = cb -> primitive.bottom_shadow_GC;
984   }
985 
986   /* _XmDrawShadow is superseded in Motif 2.0 */
987   _XmDrawShadow( XtDisplay( widget ), XtWindow( widget ),
988                  top_gc, bottom_gc,
989                  cb -> primitive.shadow_thickness,
990                  cb -> primitive.highlight_thickness,
991                  cb -> primitive.highlight_thickness,
992                  (int) cb -> core.width -
993                        2 * cb -> primitive.highlight_thickness,
994                  (int) cb -> core.height -
995                        2 * cb -> primitive.highlight_thickness );
996 
997   return;
998 
999 } /* DrawShadow */
1000 
1001 
1002 /*---------------------------------------------------------------------------*/
1003 
1004 static void
Enter(Widget w,XEvent * event,String * params,Cardinal num_params)1005   Enter( Widget    w,
1006 	 XEvent    *event,
1007 	 String    *params,
1008 	 Cardinal  num_params )
1009 {
1010 
1011   /* Variables. */
1012   XitRwPixButtonWidget  cb;
1013 
1014 
1015   /* Code. */
1016 
1017   cb = (XitRwPixButtonWidget) w;
1018 
1019 #if XmVersion > 1001
1020   _XmPrimitiveEnter( (Widget) cb, event, NULL, NULL );
1021 #else
1022   _XmPrimitiveEnter( (XmPrimitiveWidget) cb, event );
1023 #endif
1024 
1025   /* Only bother to redraw if the widget is armed. */
1026   if( cb -> pixBut.armed )
1027     DrawButton( (Widget) cb, True );
1028 
1029 
1030   return;
1031 
1032 } /* Enter */
1033 
1034 
1035 /*---------------------------------------------------------------------------*/
1036 
1037 static void
ExposeIt(Widget widget,XEvent * event,Region region)1038   ExposeIt( Widget  widget,
1039             XEvent  *event,
1040             Region  region )
1041 {
1042 
1043   /* Variables. */
1044   XitRwPixButtonWidget  cb;
1045 
1046 
1047   /* Code. */
1048 
1049   cb = (XitRwPixButtonWidget) widget;
1050 
1051   DrawButton( (Widget) cb, cb -> pixBut.armed );
1052 
1053 
1054   return;
1055 
1056 } /* ExposeIt */
1057 
1058 
1059 /*---------------------------------------------------------------------------*/
1060 
1061 static void
PixButFocusIn(Widget w,XEvent * event,String * params,Cardinal num_params)1062   PixButFocusIn( Widget   w,
1063                  XEvent   *event,
1064                  String   *params,
1065                  Cardinal num_params )
1066 {
1067 
1068   XitRwPixButtonWidget   cb;
1069 
1070   /* Code. */
1071 
1072   cb = (XitRwPixButtonWidget) w;
1073 
1074 #if XmVersion > 1001
1075   _XmPrimitiveFocusIn( (Widget) w, event, NULL, NULL );
1076 #else
1077   _XmPrimitiveFocusIn( (XmPrimitiveWidget) w, event );
1078 #endif
1079 
1080   DrawButton( (Widget) cb, cb -> pixBut.armed );
1081 
1082 
1083   return;
1084 
1085 } /* PixButFocusIn */
1086 
1087 
1088 /*---------------------------------------------------------------------------*/
1089 
1090 static void
PixButFocusOut(Widget w,XEvent * event,String * params,Cardinal num_params)1091   PixButFocusOut( Widget   w,
1092                   XEvent   *event,
1093                   String   *params,
1094                   Cardinal num_params )
1095 {
1096 
1097   XitRwPixButtonWidget   cb;
1098 
1099   /* Code. */
1100 
1101   cb = (XitRwPixButtonWidget) w;
1102 
1103   DrawButton( (Widget) cb, cb -> pixBut.armed );
1104 
1105 #if XmVersion > 1001
1106   _XmPrimitiveFocusOut( (Widget) w, event, NULL, NULL );
1107 #else
1108   _XmPrimitiveFocusOut( (XmPrimitiveWidget) w, event );
1109 #endif
1110 
1111 
1112   return;
1113 
1114 } /* PixButFocusOut */
1115 
1116 
1117 /*---------------------------------------------------------------------------*/
1118 
1119 static void
GetDrawingGC(Widget widget)1120   GetDrawingGC( Widget  widget )
1121 {
1122 
1123   /* Variables. */
1124   XFontStruct           *font;
1125   XGCValues             gc_values;
1126   XitRwPixButtonWidget  cb;
1127   Pixel                 select_color;
1128 
1129 
1130   /* Code. */
1131 
1132   cb = (XitRwPixButtonWidget) widget;
1133 
1134   /* Get font for GC, Take first font in list. */
1135   {
1136     XmFontContext    context;
1137     XmStringCharSet  char_set;
1138 
1139     (void) XmFontListInitFontContext( &context, cb -> pixBut.font_list );
1140     (void) XmFontListGetNextFont( context, &char_set, &font );
1141     XmFontListFreeFontContext( context );
1142     XtFree( char_set );
1143   } /* block */
1144 
1145   /* Get the background color for armed state. */
1146   {
1147     Pixel   dummy;
1148 
1149     XmGetColors( XtScreen( (Widget) cb ),
1150 		 DefaultColormapOfScreen( XtScreen( (Widget) cb )),
1151 		 cb -> core.background_pixel, &dummy, &dummy, &dummy,
1152   		 &select_color );
1153   }
1154 
1155   /* Use a shareable GC. */
1156   if( cb -> pixBut.gc != NULL )
1157     XtReleaseGC( (Widget) cb, cb -> pixBut.gc );
1158 
1159   gc_values.foreground = cb -> primitive.foreground;
1160   gc_values.background = cb -> core.background_pixel;
1161   gc_values.font       = font -> fid;
1162 
1163   cb -> pixBut.gc = XtGetGC( (Widget) cb,
1164                              GCForeground | GCBackground | GCFont,
1165                              &gc_values );
1166 
1167 
1168   /* The clear_gc for clearing the window. */
1169   if( cb -> pixBut.clear_gc != NULL )
1170     XtReleaseGC( (Widget) cb, cb -> pixBut.clear_gc );
1171 
1172   gc_values.foreground = cb -> core.background_pixel;
1173   gc_values.background = cb -> primitive.foreground;
1174   gc_values.fill_style = FillSolid;
1175 
1176   cb -> pixBut.clear_gc = XtGetGC( (Widget) cb,
1177                                    GCForeground | GCBackground | GCFillStyle,
1178                                    &gc_values );
1179 
1180   /* The select_gc for drawing the button in its armed state. */
1181   if( cb -> pixBut.select_gc != NULL )
1182     XtReleaseGC( (Widget) cb, cb -> pixBut.select_gc );
1183 
1184   gc_values.foreground   = cb -> primitive.foreground;
1185   gc_values.background   = select_color;
1186   gc_values.font         = font -> fid;
1187   cb -> pixBut.select_gc = XtGetGC( (Widget) cb,
1188                                   GCForeground | GCBackground | GCFont,
1189                                   &gc_values );
1190 
1191   /* The select_clear_gc for clearing the pixmap when armed. */
1192   if( cb -> pixBut.select_clear_gc != NULL )
1193     XtReleaseGC( (Widget) cb, cb -> pixBut.select_clear_gc );
1194 
1195   gc_values.foreground = select_color;
1196   gc_values.background = cb -> primitive.foreground;
1197   gc_values.fill_style = FillSolid;
1198   cb -> pixBut.select_clear_gc = XtGetGC( (Widget) cb,
1199                                            GCForeground | GCBackground,
1200                                            &gc_values );
1201 
1202   /* The insensitive GC for insensitive state. */
1203   if( cb -> pixBut.insensitive_gc != NULL )
1204     XtReleaseGC( (Widget) cb, cb -> pixBut.insensitive_gc );
1205 
1206   gc_values.foreground = cb -> core.background_pixel;
1207   gc_values.stipple    = cb -> pixBut.insensitive_pixmap;
1208   gc_values.fill_style = FillStippled;
1209 
1210   cb -> pixBut.insensitive_gc =
1211     XtGetGC( (Widget) cb,
1212              GCForeground | GCStipple | GCFillStyle,
1213              &gc_values );
1214 
1215   return;
1216 
1217 } /* GetDrawingGC */
1218 
1219 
1220 /*---------------------------------------------------------------------------*/
1221 
1222 static void
Initialize(Widget treq,Widget tnew,ArgList args,Cardinal * num_args)1223   Initialize( Widget    treq,
1224               Widget    tnew,
1225               ArgList   args,
1226               Cardinal  *num_args )
1227 {
1228 
1229   /* Variables. */
1230   XitRwPixButtonWidget  new;
1231   XmString              tmp_label;
1232 
1233 
1234   /* Code. */
1235 
1236   new = (XitRwPixButtonWidget) tnew;
1237 
1238   /* Reset all private fields. */
1239   new -> pixBut.gc                = NULL;
1240   new -> pixBut.clear_gc          = NULL;
1241   new -> pixBut.select_gc         = NULL;
1242   new -> pixBut.select_clear_gc   = NULL;
1243   new -> pixBut.insensitive_gc    = NULL;
1244   new -> pixBut.pixmap_width      = 0;
1245   new -> pixBut.pixmap_height     = 0;
1246   new -> pixBut.string_width      = 0;
1247   new -> pixBut.string_height     = 0;
1248   new -> pixBut.x_pixmap          = 0;
1249   new -> pixBut.y_pixmap          = 0;
1250   new -> pixBut.x_string          = 0;
1251   new -> pixBut.y_string          = 0;
1252   new -> pixBut.user_set_width    = False;
1253   new -> pixBut.user_set_height   = False;
1254   new -> pixBut.armed             = False;
1255 
1256   /* Copy label string. */
1257   if( new -> pixBut.label != NULL ){
1258 
1259     tmp_label           = XmStringCopy( new -> pixBut.label );
1260     new -> pixBut.label = tmp_label;
1261   }
1262 
1263   /* Check the dimensions of the stuff to be displayed. */
1264   SetComponentDimensions( (Widget) new );
1265 
1266   /* Get our initial size. */
1267   DesiredDimensions( (Widget) new, True, &new -> core.width,
1268                                          &new -> core.height );
1269 
1270   /* Avoid trying to create a widget with zero width and/or height. */
1271   if( new -> core.width <= 0 )
1272     new -> core.width = 10;
1273   if( new -> core.height <= 0 )
1274     new -> core.height = 10;
1275 
1276   /* Lay out components within the window. */
1277   SetComponentPositions( (Widget) new );
1278 
1279   /* Create insensitive pixmap. */
1280   new -> pixBut.insensitive_pixmap =
1281     XCreateBitmapFromData( XtDisplay( (Widget) new ),
1282                            RootWindowOfScreen( XtScreen( (Widget) new )),
1283                            (char *) insens_bits,
1284                            INSENS_WIDTH, INSENS_HEIGHT );
1285 
1286   /* Create GC for drawing. */
1287   GetDrawingGC( (Widget) new );
1288 
1289 
1290   return;
1291 
1292 } /* Initialize */
1293 
1294 
1295 /*---------------------------------------------------------------------------*/
1296 
1297 static void
Leave(Widget w,XEvent * event,String * params,Cardinal num_params)1298   Leave( Widget    w,
1299 	 XEvent    *event,
1300 	 String    *params,
1301 	 Cardinal  num_params )
1302 {
1303 
1304   /* Variables. */
1305   XitRwPixButtonWidget  cb;
1306 
1307 
1308   /* Code. */
1309 
1310   cb = (XitRwPixButtonWidget) w;
1311 
1312 #if XmVersion > 1001
1313   _XmPrimitiveLeave( (Widget) cb, event, NULL, NULL );
1314 #else
1315   _XmPrimitiveLeave( (XmPrimitiveWidget) cb, event );
1316 #endif
1317 
1318   /* Only bother to redraw if the widget is armed. */
1319   if( cb -> pixBut.armed )
1320     DrawButton( (Widget) cb, False );
1321 
1322 
1323   return;
1324 
1325 } /* Leave */
1326 
1327 
1328 /*---------------------------------------------------------------------------*/
1329 
1330 static XtGeometryResult
QueryGeometry(Widget widget,XtWidgetGeometry * proposed,XtWidgetGeometry * answer)1331   QueryGeometry( Widget             widget,
1332                  XtWidgetGeometry  *proposed,
1333                  XtWidgetGeometry  *answer )
1334 {
1335 
1336   /* Variables. */
1337   XitRwPixButtonWidget  cb;
1338 
1339 
1340   /* Code. */
1341 
1342   cb = (XitRwPixButtonWidget) widget;
1343 
1344   /* Suggest the calculated width and height. */
1345   answer -> request_mode = CWWidth | CWHeight;
1346 
1347   DesiredDimensions( (Widget) cb, False, &answer -> width, &answer -> height );
1348 
1349   /* Check if our calculated dimensions correspond to the propsed ones. */
1350   if( (( proposed -> request_mode & ( CWWidth | CWHeight )) ==
1351          ( CWWidth | CWHeight )) &&
1352      ( proposed -> width  == answer -> width ) &&
1353      ( proposed -> height == answer -> height ) )
1354     return( XtGeometryYes );
1355 
1356   else if( ( answer -> width  == cb -> core.width ) &&
1357            ( answer -> height == cb -> core.height ) )
1358     return( XtGeometryNo );
1359 
1360   else
1361     return( XtGeometryAlmost );
1362 
1363 
1364 } /* QueryGeometry */
1365 
1366 
1367 /*---------------------------------------------------------------------------*/
1368 
1369 static void
Resize(Widget widget)1370   Resize( Widget  widget )
1371 {
1372 
1373   /* Variables. */
1374   XitRwPixButtonWidget  cb;
1375 
1376 
1377   /* Code. */
1378 
1379   cb = (XitRwPixButtonWidget) widget;
1380 
1381   /* When this method is called, the parameter widget structure contains the
1382      new values for width, height and border width. We must obey. */
1383 
1384   /* Calculate positions of the components. */
1385   SetComponentPositions( (Widget) cb );
1386 
1387   /* X will generate an expose event and we can draw the button in the
1388      expose method. */
1389 
1390   return;
1391 
1392 
1393 } /* Resize */
1394 
1395 
1396 /*---------------------------------------------------------------------------*/
1397 
1398 static void
SetComponentDimensions(Widget widget)1399   SetComponentDimensions( Widget  widget )
1400 {
1401 
1402   /* Variables. */
1403   int                   x;
1404   int                   y;
1405   unsigned int          border_width;
1406   unsigned int          depth;
1407   unsigned int         pixmap_height;
1408   unsigned int         pixmap_width;
1409   Dimension             string_height;
1410   Dimension             string_width;
1411   Window                root_window;
1412   XitRwPixButtonWidget  cb;
1413 
1414 
1415   /* Code. */
1416 
1417   cb = (XitRwPixButtonWidget) widget;
1418 
1419   /* Get the dimensions of the stuff that shall be displayed. */
1420 
1421   /* Pixmap. */
1422   if( cb -> pixBut.pixmap != XmUNSPECIFIED_PIXMAP )
1423     XGetGeometry( XtDisplay( widget ), cb -> pixBut.pixmap, &root_window,
1424                   &x, &y, &pixmap_width, &pixmap_height, &border_width,
1425                   &depth );
1426   else {
1427     pixmap_height = 0;
1428     pixmap_width  = 0;
1429   }
1430 
1431 
1432   /* String. */
1433   if( cb -> pixBut.label != NULL ){
1434     string_height = XmStringHeight( cb -> pixBut.font_list,
1435                                     cb -> pixBut.label );
1436     string_width  = XmStringWidth(  cb -> pixBut.font_list,
1437                                     cb -> pixBut.label );
1438   } else {
1439     string_height = 0;
1440     string_width  = 0;
1441   }
1442 
1443   cb -> pixBut.pixmap_height = (int) pixmap_height;
1444   cb -> pixBut.pixmap_width  = (int) pixmap_width;
1445   cb -> pixBut.string_height = (int) string_height;
1446   cb -> pixBut.string_width  = (int) string_width;
1447 
1448 
1449   return;
1450 
1451 } /* SetComponentDimensions */
1452 
1453 
1454 /*---------------------------------------------------------------------------*/
1455 
1456 static void
SetComponentPositions(Widget widget)1457   SetComponentPositions( Widget  widget )
1458 {
1459 
1460   /* Variables. */
1461   int                   basic_bottom_offset;
1462   int                   basic_left_offset;
1463   int                   basic_right_offset;
1464   int                   basic_top_offset;
1465   int                   middle_x_pos;
1466   int                   middle_y_pos;
1467   XitRwPixButtonWidget  cb;
1468 
1469 
1470   /* Code. */
1471 
1472   cb = (XitRwPixButtonWidget) widget;
1473 
1474   basic_left_offset   = cb -> primitive.shadow_thickness +
1475                         cb -> primitive.highlight_thickness +
1476                         cb -> pixBut.margin_width +
1477                         cb -> pixBut.left_margin;
1478 
1479   basic_top_offset    = cb -> primitive.shadow_thickness +
1480                         cb -> primitive.highlight_thickness +
1481                         cb -> pixBut.margin_height +
1482                         cb -> pixBut.top_margin;
1483 
1484   basic_right_offset  = cb -> primitive.shadow_thickness +
1485                         cb -> primitive.highlight_thickness +
1486                         cb -> pixBut.margin_width +
1487                         cb -> pixBut.right_margin;
1488 
1489   basic_bottom_offset = cb -> primitive.shadow_thickness +
1490                         cb -> primitive.highlight_thickness +
1491                         cb -> pixBut.margin_height +
1492                         cb -> pixBut.bottom_margin;
1493 
1494   middle_x_pos  = (( cb -> core.width - basic_left_offset -
1495                      basic_right_offset ) / 2 ) + basic_left_offset;
1496 
1497   middle_y_pos  = (( cb -> core.height - basic_top_offset -
1498                      basic_bottom_offset ) / 2 ) + basic_top_offset;
1499 
1500 
1501   /* X position. */
1502   switch( cb -> pixBut.pixmap_position ){
1503 
1504     case XitRwLEFT:
1505       /* Horizontal layout. Pixmap to the left. */
1506 
1507       switch( cb -> pixBut.alignment ){
1508         case XmALIGNMENT_BEGINNING:
1509 	  cb -> pixBut.x_pixmap = basic_left_offset;
1510 	  cb -> pixBut.x_string = cb -> pixBut.x_pixmap +
1511                                   cb -> pixBut.pixmap_width +
1512 			          cb -> pixBut.spacing;
1513           break;
1514 
1515         case XmALIGNMENT_END:
1516           cb -> pixBut.x_string = cb -> core.width - basic_right_offset -
1517                                   cb -> pixBut.string_width;
1518           cb -> pixBut.x_pixmap = cb -> pixBut.x_string -
1519                                   cb -> pixBut.spacing -
1520                                   cb -> pixBut.pixmap_width;
1521           break;
1522 
1523         case XmALIGNMENT_CENTER:
1524           cb -> pixBut.x_pixmap = middle_x_pos - ( cb -> pixBut.pixmap_width +
1525                                   cb -> pixBut.spacing +
1526                                   cb -> pixBut.string_width ) / 2;
1527           cb -> pixBut.x_string = cb -> pixBut.x_pixmap +
1528                                   cb -> pixBut.pixmap_width +
1529                                   cb -> pixBut.spacing;
1530           break;
1531       }
1532 
1533       break;
1534 
1535     case XitRwRIGHT:
1536       /* Horizontal layout. Pixmap to the right. */
1537 
1538       switch( cb -> pixBut.alignment ){
1539         case XmALIGNMENT_BEGINNING:
1540 	  cb -> pixBut.x_string = basic_left_offset;
1541 	  cb -> pixBut.x_pixmap = cb -> pixBut.x_string +
1542                                   cb -> pixBut.string_width +
1543 			          cb -> pixBut.spacing;
1544           break;
1545 
1546         case XmALIGNMENT_END:
1547           cb -> pixBut.x_pixmap = cb -> core.width - basic_right_offset -
1548                                   cb -> pixBut.pixmap_width;
1549           cb -> pixBut.x_string = cb -> pixBut.x_pixmap -
1550                                   cb -> pixBut.spacing -
1551                                   cb -> pixBut.string_width;
1552           break;
1553 
1554         case XmALIGNMENT_CENTER:
1555           /* Center the components. */
1556           cb -> pixBut.x_string = middle_x_pos -
1557                                   (cb -> pixBut.pixmap_width +
1558                                    cb -> pixBut.spacing +
1559                                    cb -> pixBut.string_width) / 2;
1560           cb -> pixBut.x_pixmap = cb -> pixBut.x_string +
1561                                   cb -> pixBut.string_width +
1562                                   cb -> pixBut.spacing;
1563           break;
1564       }
1565 
1566       break;
1567 
1568     case XitRwTOP:
1569     case XitRwBOTTOM:
1570       /* Vertical organization. */
1571 
1572       /* Components should be centered in the horizontal dimension. */
1573       cb -> pixBut.x_string = middle_x_pos - (cb -> pixBut.string_width / 2);
1574       cb -> pixBut.x_pixmap = middle_x_pos - (cb -> pixBut.pixmap_width / 2);
1575 
1576       break;
1577 
1578   }
1579 
1580   /* Y position. */
1581   switch( cb -> pixBut.pixmap_position ){
1582 
1583     case XitRwTOP:
1584       /* Vertical layout. Pixmap over string. */
1585 
1586       switch( cb -> pixBut.alignment ){
1587         case XmALIGNMENT_BEGINNING:
1588 	  cb -> pixBut.y_pixmap = basic_top_offset;
1589 	  cb -> pixBut.y_string = cb -> pixBut.y_pixmap +
1590                                   cb -> pixBut.pixmap_height +
1591 			          cb -> pixBut.spacing;
1592           break;
1593 
1594         case XmALIGNMENT_END:
1595           /* As low as possible. */
1596           cb -> pixBut.y_string = cb -> core.height - basic_bottom_offset -
1597                                   cb -> pixBut.string_height;
1598           cb -> pixBut.y_pixmap = cb -> pixBut.y_string -
1599                                   cb -> pixBut.spacing -
1600                                   cb -> pixBut.pixmap_height;
1601           break;
1602 
1603         case XmALIGNMENT_CENTER:
1604           /* Center the components. */
1605           cb -> pixBut.y_pixmap = middle_y_pos -
1606                                   (cb -> pixBut.pixmap_height +
1607                                    cb -> pixBut.spacing +
1608                                    cb -> pixBut.string_height) / 2;
1609           cb -> pixBut.y_string = cb -> pixBut.y_pixmap +
1610                                   cb -> pixBut.pixmap_height +
1611                                   cb -> pixBut.spacing;
1612           break;
1613       }
1614 
1615       break;
1616 
1617     case XitRwBOTTOM:
1618       /* Vertical layout. Pixmap under string. */
1619 
1620       switch( cb -> pixBut.alignment ){
1621         case XmALIGNMENT_BEGINNING:
1622 	  cb -> pixBut.y_string = basic_top_offset;
1623 	  cb -> pixBut.y_pixmap = cb -> pixBut.y_string +
1624                                   cb -> pixBut.string_height +
1625 			          cb -> pixBut.spacing;
1626           break;
1627 
1628         case XmALIGNMENT_END:
1629           cb -> pixBut.y_pixmap = cb -> core.height - basic_bottom_offset -
1630                                   cb -> pixBut.pixmap_height;
1631           cb -> pixBut.y_string = cb -> pixBut.y_pixmap -
1632                                   cb -> pixBut.spacing -
1633                                   cb -> pixBut.string_height;
1634           break;
1635 
1636         case XmALIGNMENT_CENTER:
1637           cb -> pixBut.y_string = middle_y_pos -
1638                                   (cb -> pixBut.pixmap_height +
1639                                    cb -> pixBut.spacing +
1640                                    cb -> pixBut.string_height) / 2;
1641           cb -> pixBut.y_pixmap = cb -> pixBut.y_string +
1642                                   cb -> pixBut.string_height +
1643                                   cb -> pixBut.spacing;
1644           break;
1645       }
1646 
1647       break;
1648 
1649     case XitRwLEFT:
1650     case XitRwRIGHT:
1651       /* Horizontal organization. */
1652       if( cb -> pixBut.string_height > cb -> core.height ||
1653           cb -> pixBut.opposite_alignment == XmALIGNMENT_BEGINNING )
1654         cb -> pixBut.y_string = basic_top_offset;
1655       else
1656         cb -> pixBut.y_string = middle_y_pos -
1657                                 (cb -> pixBut.string_height / 2);
1658 
1659       cb -> pixBut.y_pixmap = middle_y_pos - (cb -> pixBut.pixmap_height / 2);
1660 
1661       break;
1662 
1663   }
1664 
1665 
1666   return;
1667 
1668 } /* SetComponentPositions */
1669 
1670 
1671 /*---------------------------------------------------------------------------*/
1672 
1673 static Boolean
SetValues(Widget current,Widget request,Widget new,ArgList args,Cardinal * num_args)1674   SetValues( Widget    current,
1675              Widget    request,
1676              Widget    new,
1677              ArgList   args,
1678              Cardinal  *num_args )
1679 {
1680 
1681   /* Variables. */
1682   Boolean               new_size;
1683   Boolean               redraw = False;
1684   Dimension             desired_height;
1685   Dimension             desired_width;
1686   XitRwPixButtonWidget  curW;
1687   XitRwPixButtonWidget  newW;
1688   XmString              tmp_label;
1689 
1690 
1691   /* Code. */
1692 
1693   curW = (XitRwPixButtonWidget) current;
1694   newW = (XitRwPixButtonWidget) new;
1695 
1696   /* Initialize. */
1697   new_size = False;
1698 
1699   if( newW -> core.width != curW -> core.width ) {
1700     if( newW -> core.width == 0 ) {
1701       if( newW -> pixBut.user_set_width ) {
1702         newW -> pixBut.user_set_width = False;
1703         new_size = True;
1704       } else {
1705         newW -> core.width = curW -> core.width;
1706       }
1707     } else {
1708       newW -> pixBut.user_set_width = True;
1709     }
1710   }
1711 
1712   if( newW -> core.height != curW -> core.height ) {
1713     if( newW -> core.height == 0 ) {
1714       if( newW -> pixBut.user_set_height ) {
1715         newW -> pixBut.user_set_height = False;
1716         new_size = True;
1717       } else {
1718         newW -> core.height = curW -> core.height;
1719       }
1720     } else {
1721       newW -> pixBut.user_set_height = True;
1722     }
1723   }
1724 
1725   if( newW -> pixBut.font_list != curW -> pixBut.font_list )
1726     new_size = True;
1727 
1728 
1729   if( newW -> pixBut.label != curW -> pixBut.label ) {
1730     if( curW -> pixBut.label != NULL )
1731       XmStringFree( curW -> pixBut.label );
1732 
1733     tmp_label            = XmStringCopy( newW -> pixBut.label );
1734     newW -> pixBut.label = tmp_label;
1735 
1736     new_size = True;
1737   }
1738 
1739 
1740   if( newW -> pixBut.pixmap != curW -> pixBut.pixmap )
1741     new_size = True;
1742 
1743 
1744   /* Check if any resource values were changed that may affect other fields
1745      or require that the picture be redrawn. */
1746 
1747   if( ( newW -> pixBut.top_margin    != curW -> pixBut.top_margin )    ||
1748       ( newW -> pixBut.left_margin   != curW -> pixBut.left_margin )   ||
1749       ( newW -> pixBut.right_margin  != curW -> pixBut.right_margin )  ||
1750       ( newW -> pixBut.bottom_margin != curW -> pixBut.bottom_margin ) ||
1751       ( newW -> pixBut.margin_width  != curW -> pixBut.margin_width )  ||
1752       ( newW -> pixBut.margin_height != curW -> pixBut.margin_height ) ||
1753       ( newW -> pixBut.spacing       != curW -> pixBut.spacing ) )
1754     new_size = True;
1755 
1756   if( newW -> core.sensitive != curW -> core.sensitive )
1757     redraw = True;
1758 
1759   /* Color change affects only gc and redraw. */
1760   if( ( newW -> primitive.foreground  != curW -> primitive.foreground )  ||
1761       ( newW -> core.background_pixel != curW -> core.background_pixel ) ||
1762       ( newW -> pixBut.font_list      != curW -> pixBut.font_list ) ) {
1763     GetDrawingGC( (Widget) new );
1764     redraw = True;
1765   }
1766 
1767   /* Check if we want to resize ourselves. */
1768   if( new_size ) {
1769 
1770     redraw = True;
1771 
1772     /* Size request must be based on new values. */
1773     SetComponentDimensions( (Widget) new );
1774 
1775     DesiredDimensions( (Widget) new, False, &desired_width, &desired_height );
1776 
1777     SetComponentPositions( (Widget) new );
1778 
1779 
1780     /* Only request new size if really needed. */
1781     if( desired_width  != curW -> core.width ||
1782         desired_height != curW -> core.height ||
1783         newW -> core.height == 0 ||
1784         newW -> core.width == 0 ) {
1785 
1786       new -> core.width  = desired_width;
1787       new -> core.height = desired_height;
1788 
1789       /* Should not change these according to the Xt documentation, but try. */
1790       request -> core.width  = desired_width;
1791       request -> core.height = desired_height;
1792 
1793     }
1794 
1795   } /* if */
1796 
1797   /* Redraw ourselves? */
1798   return( redraw );
1799 
1800 
1801 } /* SetValues */
1802 
1803 
1804 /*---------------------------------------------------------------------------*/
1805 
1806 static void
TraverseNextTabGroup(Widget w,XEvent * event,String * params,Cardinal num_params)1807   TraverseNextTabGroup( Widget   w,
1808                         XEvent   *event,
1809 	                String   *params,
1810 	                Cardinal num_params )
1811 {
1812   /* Code. */
1813 
1814   XmProcessTraversal( w, XmTRAVERSE_NEXT_TAB_GROUP );
1815 
1816 
1817   return;
1818 
1819 } /* TraverseNextTabGroup */
1820 
1821 /*---------------------------------------------------------------------------*/
1822 
1823 static void
TraversePrevTabGroup(Widget w,XEvent * event,String * params,Cardinal num_params)1824   TraversePrevTabGroup( Widget   w,
1825                         XEvent   *event,
1826 	                String   *params,
1827 	                Cardinal num_params )
1828 {
1829   /* Code. */
1830 
1831   XmProcessTraversal( w, XmTRAVERSE_PREV_TAB_GROUP );
1832 
1833 
1834   return;
1835 
1836 } /* TraversePrevTabGroup */
1837 
1838 /*---------------------------------------------------------------------------*/
1839 
1840 static void
TraverseDown(Widget w,XEvent * event,String * params,Cardinal num_params)1841   TraverseDown( Widget   w,
1842                 XEvent   *event,
1843 	        String   *params,
1844 	        Cardinal num_params )
1845 {
1846   /* Code. */
1847 
1848   XmProcessTraversal( w, XmTRAVERSE_DOWN );
1849 
1850 
1851   return;
1852 
1853 } /* TraverseDown */
1854 
1855 /*---------------------------------------------------------------------------*/
1856 
1857 static void
TraverseHome(Widget w,XEvent * event,String * params,Cardinal num_params)1858   TraverseHome( Widget   w,
1859                 XEvent   *event,
1860 	        String   *params,
1861 	        Cardinal num_params )
1862 {
1863   /* Code. */
1864 
1865   XmProcessTraversal( w, XmTRAVERSE_HOME );
1866 
1867 
1868   return;
1869 
1870 } /* TraverseHome */
1871 
1872 /*---------------------------------------------------------------------------*/
1873 
1874 static void
TraverseLeft(Widget w,XEvent * event,String * params,Cardinal num_params)1875   TraverseLeft( Widget   w,
1876                 XEvent   *event,
1877 	        String   *params,
1878 	        Cardinal num_params )
1879 {
1880   /* Code. */
1881 
1882   XmProcessTraversal( w, XmTRAVERSE_LEFT );
1883 
1884 
1885   return;
1886 
1887 } /* TraverseLeft */
1888 
1889 /*---------------------------------------------------------------------------*/
1890 
1891 static void
TraverseRight(Widget w,XEvent * event,String * params,Cardinal num_params)1892   TraverseRight( Widget   w,
1893                  XEvent   *event,
1894 	         String   *params,
1895 	         Cardinal num_params )
1896 {
1897   /* Code. */
1898 
1899   XmProcessTraversal( w, XmTRAVERSE_RIGHT );
1900 
1901 
1902   return;
1903 
1904 } /* TraverseRight */
1905 
1906 /*---------------------------------------------------------------------------*/
1907 
1908 static void
TraverseUp(Widget w,XEvent * event,String * params,Cardinal num_params)1909   TraverseUp( Widget   w,
1910               XEvent   *event,
1911 	      String   *params,
1912 	      Cardinal num_params )
1913 {
1914   /* Code. */
1915 
1916   XmProcessTraversal( w, XmTRAVERSE_UP );
1917 
1918 
1919   return;
1920 
1921 } /* TraverseUp */
1922 
1923 /*---------------------------------------------------------------------------*/
1924 
1925 static void
Unmap(Widget w,XEvent * event,String * params,Cardinal num_params)1926   Unmap( Widget   w,
1927          XEvent   *event,
1928          String   *params,
1929          Cardinal num_params )
1930 {
1931 
1932   /* Variables. */
1933   XitRwPixButtonWidget  cb;
1934 
1935 
1936   /* Code. */
1937 
1938   cb = (XitRwPixButtonWidget) w;
1939 
1940 #if XmVersion > 1001
1941   _XmPrimitiveUnmap( (Widget) cb, event, NULL, NULL );
1942 #else
1943   _XmPrimitiveUnmap( (XmPrimitiveWidget) cb, event );
1944 #endif
1945 
1946   /* We cannot allow the widget to stay armed if it disappears. */
1947   cb -> pixBut.armed = False;
1948 
1949 
1950   return;
1951 
1952 } /* Unmap */
1953 
1954 
1955 /*---------------------------------------------------------------------------*/
1956 
1957 Boolean
xitRwPixButIsArmed(Widget w)1958   xitRwPixButIsArmed( Widget  w )
1959 {
1960 
1961   /* Code. */
1962 
1963 
1964   return( ((XitRwPixButtonWidget) w) -> pixBut.armed );
1965 
1966 } /* xitRwPixButIsArmed */
1967