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  */
24 
25 /************************************************************
26 *	INCLUDE FILES
27 *************************************************************/
28 
29 #include <Xm/XmP.h>
30 #include <Xm/DrawP.h>
31 #include <Xm/TraitP.h>
32 #include <Xm/ActivatableT.h>
33 #include <stdio.h>
34 #include <Xm/IconButtonP.h>
35 #include <X11/bitmaps/gray>
36 #include <Xm/ExtP.h>
37 #include "PrimitiveI.h"
38 #include "XmStrDefsI.h"
39 #include "xmlist.h"
40 #include "RepTypeI.h"
41 
42 /************************************************************
43 *	TYPEDEFS AND DEFINES
44 *************************************************************/
45 
46 #define SUPERCLASS ((WidgetClass) &xmPrimitiveClassRec)
47 
48 #define FILL_SPACE(iw)		((iw)->primitive.highlight_thickness + \
49                                  (iw)->primitive.shadow_thickness)
50 
51 #define H_SPACE(iw)		(FILL_SPACE(iw) + XmIconButton_h_space(iw))
52 #define V_SPACE(iw)		(FILL_SPACE(iw) + XmIconButton_v_space(iw))
53 
54 #define ALLOC_INCREMENT         5
55 #define DELAY			100
56 
57 #define NO_TIMER		0
58 
59 #define NEW_LINE  		('\n')
60 #define EOL       		('\0')
61 
62 typedef struct _PixCacheEntry {
63     Display *display;
64     Pixmap pixmap;
65     long count;			/*The tree widget uses the folder icon A LOT*/
66     Dimension width, height, depth;
67 } PixCacheEntry;
68 
69 /************************************************************
70 *	MACROS
71 *************************************************************/
72 
73 #define streq(a, b) (((a) != NULL) && ((b) != NULL) && (strcmp((a), (b)) == 0))
74 #define ValidPixmap(p) ((p)!=None&&(p)!=XmUNSPECIFIED_PIXMAP)
75 
76 /************************************************************
77 *	GLOBAL DECLARATIONS
78 *************************************************************/
79 
80 extern void _XmSelectColorDefault();
81 static XmList pix_cache_list = NULL;
82 
83 /************************************************************
84 *	STATIC FUNCTION DECLARATIONS
85 *************************************************************/
86 
87 static void Resize(Widget), Destroy(Widget), ClassInit(void);
88 static void ClassPartInitialize(WidgetClass w_class);
89 static void Initialize(Widget, Widget, ArgList, Cardinal *);
90 static void Redisplay(Widget, XEvent *, Region);
91 static XtGeometryResult QueryGeometry(Widget,
92 				      XtWidgetGeometry *, XtWidgetGeometry *);
93 
94 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
95 static void SetValuesAlmost(Widget, Widget,
96 			    XtWidgetGeometry *,  XtWidgetGeometry *);
97 
98 static void GetValues_labelString ( Widget w, int n, XtArgVal *value) ;
99 static void ChangeCB(Widget w, XtCallbackProc activCB, XtPointer closure, Boolean setunset);
100 
101 /************************
102  * Actions and callbacks.
103  ************************/
104 
105 static void ToggleState(Widget, XEvent *, String *, Cardinal *);
106 static void Notify(Widget, XEvent *, String *, Cardinal *);
107 static void DoubleNotify(Widget, XEvent *, String *, Cardinal *);
108 static void ArmAndActivate(Widget, XEvent *, String *, Cardinal *);
109 static void ButtonUp(Widget, XEvent *, String *, Cardinal *);
110 
111 /*********************
112  * Internal Routines.
113  *********************/
114 
115 static XmListElem * GetCacheElem(Display *, Pixmap);
116 static Boolean CheckPixCache(Display *, Pixmap,
117 			     unsigned int *, unsigned int *, unsigned int *);
118 static void AddPixCache(Display *, Pixmap,
119 			unsigned int, unsigned int, unsigned int);
120 static void IncPixCache(Display *, Pixmap);
121 static void DecPixCache(Display *, Pixmap);
122 
123 static void Deactivate(XtPointer, XtIntervalId *);
124 static void GetDesiredSize(Widget, Dimension *, Dimension *);
125 static void RequestNewSize(Widget, Dimension, Dimension);
126 static void CalcLocations(Widget), DrawTextAndImage(Widget, GC, GC, GC);
127 static void CreateGCs(Widget), DestroyGCs(Widget w);
128 
129 static void FromPaddingPixels(Widget, int, XtArgVal *);
130 static XmImportOperator ToPaddingPixels(Widget, int, XtArgVal *);
131 static XmString CreateXmString(Widget, String);
132 static void CheckSetRenderTable(Widget wid, int offs, XrmValue *value);
133 
134 /******************
135  * Type Converters
136  ******************/
137 
138 static Boolean CvtStringToIconPlacement(Display *, XrmValuePtr, Cardinal *,
139 					XrmValuePtr, XrmValuePtr);
140 
141 /************************************************************
142 *	STATIC DECLARATIONS
143 *************************************************************/
144 
145 /*
146  * It seems redundant to have both Btn1Up and BtnUp bound to
147  * EndDrag, but for some reason BtnUp does not cause the event to
148  * fire on button 1, must be some Translations magic that I don't
149  * understand.
150  *
151  * CDP - 5/11/91.
152  */
153 
154 typedef struct _StippleInfo {
155     struct _StippleInfo *next;
156     Pixmap stipple;
157     Display *disp;
158     Screen *screen;
159 } StippleInfo;
160 
161 /*
162  * ||| It would be nice to put this in the widget class.
163  */
164 
165 static StippleInfo *stipple_cache; /* Only one of these for each app. */
166 
167 static char defaultTranslations[] =
168     "<Btn1Down>,<Btn1Up>:		XiToggle() XmNotify() XiButtonUp()\n\
169      <Btn1Down>:			XiGetFocus() XiToggle() \n\
170      <Key>osfSelect:  			XiArmAndActivate()\n\
171      <Key>osfActivate:  		XiArmAndActivate()\n\
172      None<Key>space:			XiArmAndActivate()\n\
173      None<Key>Return:  			XiArmAndActivate()\n\
174      <Btn1Down>,<Leave>:		XiToggle()";
175 
176 /*
177  * These are the primitive translations that we need, this list
178  * adds enter and leave to the primitive defaults.
179  */
180 
181 static char traverseTranslations[] =
182 "<Key>osfBeginLine: PrimitiveTraverseHome()\n\
183  <Key>osfHelp:	PrimitiveHelp()\n\
184  <Key>osfUp:	PrimitiveTraverseUp()\n\
185  <Key>osfDown:	PrimitiveTraverseDown()\n\
186  <Key>osfLeft:	PrimitiveTraverseLeft()\n\
187  <Key>osfRight:	PrimitiveTraverseRight()\n\
188  Shift ~Meta ~Alt <Key>Tab: PrimitivePrevTabGroup()\n\
189  ~Meta ~Alt <Key>Tab: PrimitiveNextTabGroup()\n\
190  <FocusIn>:	PrimitiveFocusIn()\n\
191  <FocusOut>:	PrimitiveFocusOut()\n\
192  <Enter>:	PrimitiveEnter()\n\
193  <Leave>:	PrimitiveLeave()\n\
194  <Unmap>:	PrimitiveUnmap()";
195 
196 static XtActionsRec actionsList[] =
197 {
198     {"XiArmAndActivate",		ArmAndActivate},
199     {"XiToggle",			ToggleState},
200     {"XmNotify",			Notify},
201     {"XiGetFocus",			_XmGetFocus},
202     {"XiDoubleNotify",			DoubleNotify},
203     {"XiButtonUp",			ButtonUp},
204     /*
205      * Why aren't these in primitive?
206      */
207     { "PrimitiveEnter",		(XtActionProc) _XmPrimitiveEnter },
208     { "PrimitiveLeave",		(XtActionProc) _XmPrimitiveLeave },
209 };
210 
211 static XtResource resources[] =
212 {
213   {
214     XmNlabel, XmCLabel, XmRString,
215     sizeof(String), XtOffsetOf(XmIconButtonRec, icon.label),
216     XmRImmediate, (XtPointer) NULL
217   },
218 
219   {
220     XmNlabelString, XmCLabelString, XmRXmString,
221     sizeof(XmString), XtOffsetOf(XmIconButtonRec, icon.label_string),
222     XmRImmediate, (XtPointer) NULL
223   },
224 
225   {
226     XmNpixmap, XmCPixmap, XmRPrimForegroundPixmap,
227     sizeof(Pixmap), XtOffsetOf(XmIconButtonRec, icon.pixmap),
228     XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP
229   },
230 
231   {
232     "pri.vate", "Pri.vate", XmRBoolean,
233     sizeof(Boolean), XtOffsetOf(XmIconButtonRec, icon.check_set_render_table),
234     XmRImmediate, (XtPointer) False
235   },
236 
237   {
238     XmNfontList, XmCFontList, XmRFontList,
239     sizeof(XmFontList), XtOffsetOf(XmIconButtonRec, icon.font_list),
240     XmRCallProc, (XtPointer)CheckSetRenderTable
241   },
242 
243   {
244     XmNrenderTable, XmCRenderTable, XmRRenderTable,
245     sizeof(XmRenderTable), XtOffsetOf(XmIconButtonRec, icon.font_list),
246     XmRCallProc, (XtPointer)CheckSetRenderTable
247   },
248 
249   {
250     XmNalignment, XmCAlignment, XmRAlignment,
251     sizeof(unsigned char), XtOffsetOf(XmIconButtonRec, icon.alignment),
252     XmRImmediate,(XtPointer) XmALIGNMENT_BEGINNING
253   },
254 
255   {
256     XmNstringDirection, XmCStringDirection, XmRStringDirection,
257     sizeof(unsigned char), XtOffsetOf(XmIconButtonRec, icon.string_direction),
258     XmRImmediate, (XtPointer) XmDEFAULT_DIRECTION
259   },
260 
261   {
262     XmNiconPlacement, XmCIconPlacement, XmRXmIconPlacement,
263     sizeof(XmIconPlacement), XtOffsetOf(XmIconButtonRec, icon.icon_placement),
264     XmRImmediate, (XtPointer) XmIconTop
265   },
266 
267   {
268     XmNrecomputeSize, XmCBoolean , XmRBoolean,
269     sizeof(Boolean), XtOffsetOf(XmIconButtonRec, icon.recompute),
270     XmRImmediate, (XtPointer) True
271   },
272 
273   {
274     XmNarmColor, XmCArmColor, XmRPixel,
275     sizeof(Pixel), XtOffsetOf(XmIconButtonRec, icon.arm_color),
276     XmRCallProc, (XtPointer) _XmSelectColorDefault
277   },
278 
279   {
280     XmNset, XmCBoolean , XmRBoolean,
281     sizeof(Boolean), XtOffsetOf(XmIconButtonRec, icon.set),
282     XmRImmediate, (XtPointer) False
283   },
284 
285   {
286     XmNverticalMargin, XmCSpace, XmRVerticalDimension,
287     sizeof(Dimension), XtOffsetOf(XmIconButtonRec, icon.v_space),
288     XmRImmediate, (XtPointer) 2
289   },
290 
291   {
292     XmNhorizontalMargin, XmCSpace, XmRHorizontalDimension,
293     sizeof(Dimension), XtOffsetOf(XmIconButtonRec, icon.h_space),
294     XmRImmediate, (XtPointer) 2
295   },
296 
297   {
298     XmNiconTextPadding, XmCSpace, XmRVerticalDimension,
299     sizeof(Dimension), XtOffsetOf(XmIconButtonRec, icon.icon_text_padding),
300     XmRImmediate, (XtPointer) 2
301   },
302 
303   {
304     XmNactivateCallback, XmCCallback, XmRCallback,
305     sizeof(XtCallbackList), XtOffsetOf(XmIconButtonRec, icon.activate_callback),
306     XmRPointer, (XtPointer) NULL
307   },
308 
309   {
310     XmNdoubleClickCallback, XmCCallback, XmRCallback,
311     sizeof(XtCallbackList), XtOffsetOf(XmIconButtonRec, icon.double_click_callback),
312     XmRPointer, (XtPointer) NULL
313   },
314 
315   {
316     XmNpixmapWidth, XmCDimension, XmRDimension,
317     sizeof(Dimension), XtOffsetOf(XmIconButtonRec, icon.pix_width),
318     XmRImmediate, (XtPointer) 0
319   },
320 
321   {
322     XmNpixmapHeight, XmCDimension, XmRDimension,
323     sizeof(Dimension), XtOffsetOf(XmIconButtonRec, icon.pix_height),
324     XmRImmediate, (XtPointer) 0
325   },
326 
327   {
328     XmNpixmapDepth, XmCDimension, XmRDimension,
329     sizeof(Dimension), XtOffsetOf(XmIconButtonRec, icon.pix_depth),
330     XmRImmediate, (XtPointer) 0
331   }
332 };
333 
334 static XmSyntheticResource get_resources[] =
335 {
336   {
337     XmNhorizontalMargin, sizeof(Dimension),
338     XtOffsetOf(XmIconButtonRec, icon.h_space),
339     XmeFromHorizontalPixels, (XmImportProc) XmeToHorizontalPixels
340   },
341   {
342     XmNverticalMargin, sizeof(Dimension),
343     XtOffsetOf(XmIconButtonRec, icon.v_space),
344     XmeFromVerticalPixels, (XmImportProc) XmeToVerticalPixels
345   },
346   {
347     XmNiconTextPadding, sizeof(Dimension),
348     XtOffsetOf(XmIconButtonRec, icon.icon_text_padding),
349     FromPaddingPixels, (XmImportProc) ToPaddingPixels
350   },
351   {
352     XmNlabelString, sizeof(XmString),
353     XtOffsetOf(XmIconButtonRec, icon.label_string),
354     GetValues_labelString, NULL
355   }
356 };
357 
358 XmIconButtonClassRec xmIconButtonClassRec = {
359   { /* core fields */
360     /* superclass		*/	SUPERCLASS,
361     /* class_name		*/	XM_ICON_BUTTON_CLASS_NAME,
362     /* widget_size		*/	sizeof(XmIconButtonRec),
363     /* class_initialize		*/	ClassInit,
364     /* class_part_initialize	*/	ClassPartInitialize,
365     /* class_inited		*/	FALSE,
366     /* initialize		*/	Initialize,
367     /* initialize_hook		*/	NULL,
368     /* realize			*/	XtInheritRealize,
369     /* actions			*/	actionsList,
370     /* num_actions		*/	XtNumber(actionsList),
371     /* resources		*/	(XtResourceList)resources,
372     /* num_resources		*/	XtNumber(resources),
373     /* xrm_class		*/	NULLQUARK,
374     /* compress_motion		*/	TRUE,
375     /* compress_exposure	*/	XtExposeCompressMultiple,
376     /* compress_enterleave	*/	TRUE,
377     /* visible_interest		*/	FALSE,
378     /* destroy			*/	Destroy,
379     /* resize			*/	Resize,
380     /* expose			*/	Redisplay,
381     /* set_values		*/	SetValues,
382     /* set_values_hook		*/	NULL,
383     /* set_values_almost	*/	SetValuesAlmost,
384     /* get_values_hook		*/	NULL,
385     /* accept_focus		*/	NULL,
386     /* version			*/	XtVersion,
387     /* callback_private		*/	NULL,
388     /* tm_table			*/	defaultTranslations,
389     /* query_geometry		*/	(XtGeometryHandler) QueryGeometry,
390     /* display_accelerator	*/	XtInheritDisplayAccelerator,
391     /* extension		*/	NULL
392   },
393   { /* Xmprimitive fields */
394       (XtWidgetProc)_XtInherit, /* border_highlight   */
395       (XtWidgetProc)_XtInherit, /* border_unhighlight */
396       traverseTranslations,	/* translations       */
397       NULL,                     /* arm_and_activate   */
398       get_resources,   	    	/* syn resources      */
399       XtNumber(get_resources),	/* num syn_resources  */
400       NULL                      /* extension          */
401   },
402   { /* Icon Button class fields */
403       NULL                      /* extension          */
404   }
405 };
406 
407 WidgetClass xmIconButtonWidgetClass = (WidgetClass)&xmIconButtonClassRec;
408 
409 /* Trait record for iconButton */
410 static XmConst XmActivatableTraitRec iconButtonAT =
411 {
412   0,				/* version	*/
413   ChangeCB			/* changeCB	*/
414 };
415 
416 /************************************************************
417 *	STATIC CODE
418 *************************************************************/
419 
420 /*	Function Name: ClassInit
421  *	Description:   Called to initialize information specific
422  *                     to this widget class.
423  *	Arguments:     none.
424  *	Returns:       none.
425  */
426 
427 /*ARGSUSED*/
428 static void
ClassInit()429 ClassInit()
430 {
431     XmIconButtonClassRec *wc = &xmIconButtonClassRec;
432 
433     XtSetTypeConverter(XmRString, XmRXmIconPlacement,
434 		       (XtTypeConverter) CvtStringToIconPlacement,
435 		       NULL, (Cardinal) 0, XtCacheAll, (XtDestructor) NULL);
436 }
437 
438 /*
439  * ClassPartInitialize sets up the fast subclassing for the widget.
440  */
441 static void
442 #ifdef _NO_PROTO
ClassPartInitialize(w_class)443 ClassPartInitialize(w_class)
444         WidgetClass w_class ;
445 #else
446 ClassPartInitialize(WidgetClass w_class)
447 #endif /* _NO_PROTO */
448 {
449     _XmFastSubclassInit (w_class, XmICONBUTTON_BIT );
450 
451     /* Install the activatable trait for all subclasses */
452     XmeTraitSet((XtPointer)w_class, XmQTactivatable, (XtPointer) &iconButtonAT);
453 }
454 
455 
456 /*	Function Name: Initialize
457  *	Description:   Called to initialize information specific
458  *                     to this widget.
459  *	Arguments:     req - what was originally requested.
460  *                     set - what will be created (our superclassed have
461  *                           already mucked with this)
462  *                     args, num_args - The arguments passed to
463  *                                      the creation call.
464  *	Returns:       none.
465  */
466 
467 /*ARGSUSED*/
468 static void
Initialize(Widget req,Widget set,ArgList args,Cardinal * num_args)469 Initialize(Widget req, Widget set, ArgList args, Cardinal * num_args)
470 {
471     XmIconButtonWidget iw = (XmIconButtonWidget) set;
472     Boolean resetPixmapValues = True;
473 
474     XmIconButton_unset_timer(iw) = NO_TIMER;
475     XmIconButton_time(iw) = 0L;
476 
477     /*
478      * If the label string is specified then it wins.  If only the label
479      * is specified the it is converted into an XmString and stored
480      * in the label_string.
481      */
482 
483     XmIconButton_label_from_name(iw) = False;
484     if (XmIconButton_label_string(iw) == NULL) {
485 	if (XmIconButton_label(iw) == NULL)
486 	{
487 	    XmIconButton_label_string(iw) = CreateXmString(set, XtName(set));
488 	    XmIconButton_label_from_name(iw) = True;
489 	}
490 	else {
491 	    if ((XmIconButton_label_string(iw) =
492 		 CreateXmString(set, XmIconButton_label(iw))) == NULL)
493 	    {
494 		XmIconButton_label_string(iw) = CreateXmString(set, XtName(set));
495 		XmIconButton_label_from_name(iw) = True;
496 	    }
497 	}
498     }
499     else {
500 	XmIconButton_label_string(iw) =
501 	  XmStringCopy(XmIconButton_label_string(iw));
502     }
503     if (XmIconButton_label(iw))
504 	    XmIconButton_label(iw) = XtNewString(XmIconButton_label(iw));
505 
506     if (ValidPixmap(XmIconButton_pixmap(iw)))
507     {
508 	/* here's what we enforce: all must be non-zero */
509 	if (	(0 != XmIconButton_pix_width(iw)) 	&&
510 		(0 != XmIconButton_pix_height(iw)) 	&&
511 		(0 != XmIconButton_pix_depth(iw))	)
512 		resetPixmapValues = False;
513     }
514 
515     if (resetPixmapValues)
516 	{
517 	XmIconButton_pix_width(iw) = 0;
518 	XmIconButton_pix_height(iw) = 0;
519 	XmIconButton_pix_depth(iw) = 0;
520    	}
521     else
522     {
523 	/* we have a validPixmap and valid values */
524 	AddPixCache(XtDisplay(set), XmIconButton_pixmap(iw),
525 		    XmIconButton_pix_width(iw),
526 		    XmIconButton_pix_height(iw),
527 		    XmIconButton_pix_depth(iw));
528         IncPixCache(XtDisplay(set), XmIconButton_pixmap(iw));
529     }
530 
531     /* If layout_direction is set, it overrides string_direction.
532      * If string_direction is set, but not layout_direction, use
533      *	string_direction value.
534      * If neither is set, get from parent
535      */
536     if (XmPrim_layout_direction(iw) != XmDEFAULT_DIRECTION) {
537 	if (XmIconButton_string_direction(iw) == XmDEFAULT_DIRECTION)
538 	    XmIconButton_string_direction(iw) =
539 		XmDirectionToStringDirection(XmPrim_layout_direction(iw));
540     } else if (XmIconButton_string_direction(iw) != XmDEFAULT_DIRECTION) {
541 	XmPrim_layout_direction(iw) =
542 	    XmStringDirectionToDirection(XmIconButton_string_direction(iw));
543     } else {
544 	XmPrim_layout_direction(iw) = _XmGetLayoutDirection(XtParent(set));
545 	XmIconButton_string_direction(iw) =
546 	    XmDirectionToStringDirection(XmPrim_layout_direction(iw));
547     }
548 
549     if (!XmRepTypeValidValue(XmRID_STRING_DIRECTION,
550 	    XmIconButton_string_direction(iw), (Widget) iw))
551     {
552 	XmIconButton_string_direction(iw) = XmSTRING_DIRECTION_L_TO_R;
553 	XmPrim_layout_direction(iw) =
554 	    XmStringDirectionToDirection(XmIconButton_string_direction(iw));
555     }
556 
557     if (XmIconButton_font_list(iw) == NULL)
558     {
559         XmIconButton_font_list(iw) = XmeGetDefaultRenderTable((Widget) iw,
560 						   XmBUTTON_FONTLIST);
561     }
562 
563     /* Make a local copy of the font list */
564     XmIconButton_font_list(iw) = XmFontListCopy( XmIconButton_font_list(iw));
565 
566     if ((req->core.width == 0) || (req->core.height == 0)) {
567 	Dimension width, height;
568 
569 	GetDesiredSize(set, &width,  &height);
570 	RequestNewSize(set, width, height);
571     }
572 
573     CalcLocations(set);
574     CreateGCs(set);
575 }
576 
577 /*	Function Name: Resize
578  *	Description:   Called when this widget has been resized.
579  *	Arguments:     w - the widget to resize.
580  *	Returns:       none.
581  */
582 
583 static void
Resize(Widget w)584 Resize(Widget w)
585 {
586     CalcLocations(w);
587 }
588 
589 /*	Function Name: Redisplay
590  *	Description:   This function redraws the contents of the widget.
591  *	Arguments:     w - the widget.
592  *                     event - event that caused the exposure.
593  *                     region - the region containing all the exposures.
594  *	Returns:       none
595  */
596 
597 /*ARGSUSED*/
598 static void
Redisplay(Widget w,XEvent * event,Region region)599 Redisplay(Widget w, XEvent * event, Region region)
600 {
601     XmIconButtonWidget iw = (XmIconButtonWidget) w;
602     int dx, dy, width, height;
603     GC topgc, bottomgc, text_gc, icon_gc, icon_stippled_gc;
604 
605     dx = iw->primitive.highlight_thickness;
606     dy = dx;
607 
608     width = iw->core.width - (2 * dx);
609     height = iw->core.height - (2 * dy);
610 
611     if (XmIconButton_set(iw)) {
612 	Dimension fill_width, fill_height;
613 
614 	if ((int)iw->core.width > (int)(2 * H_SPACE(iw)))
615 	    fill_width = iw->core.width - 2 * FILL_SPACE(iw);
616 	else
617 	    fill_width = 0;
618 
619 	if ((int)iw->core.height > (int)(2 * V_SPACE(iw)))
620 	    fill_height = iw->core.height - 2 * FILL_SPACE(iw);
621 	else
622 	    fill_height = 0;
623 
624 	if ((fill_width != 0) && (fill_height != 0))
625 	    XFillRectangle(XtDisplay(w), XtWindow(w), XmIconButton_fill_gc(iw),
626 			   FILL_SPACE(iw), FILL_SPACE(iw),
627 			   fill_width, fill_height);
628 
629 	icon_gc = XmIconButton_pixmap_fill_gc(iw);
630 	icon_stippled_gc = XmIconButton_stippled_set_gc(iw);
631 	topgc    = iw->primitive.bottom_shadow_GC;
632 	bottomgc = iw->primitive.top_shadow_GC;
633     }
634     else {
635 	icon_gc  = XmIconButton_gc(iw);
636 	icon_stippled_gc = XmIconButton_stippled_unset_gc(iw);
637 	topgc     = iw->primitive.top_shadow_GC;
638 	bottomgc  = iw->primitive.bottom_shadow_GC;
639     }
640 
641     if (XtIsSensitive(w)) {
642 	if (XmIconButton_set(iw))
643 	    text_gc = XmIconButton_pixmap_fill_gc(iw);
644 	else
645 	    text_gc = XmIconButton_gc(iw);
646 
647 	icon_stippled_gc = None;
648     }
649     else {
650 	if (XmIconButton_set(iw))
651 	    text_gc = XmIconButton_stippled_set_text_gc(iw);
652 	else
653 	    text_gc = XmIconButton_stippled_text_gc(iw);
654     }
655 
656     DrawTextAndImage(w, text_gc, icon_gc, icon_stippled_gc);
657 
658     XmeDrawShadows(XtDisplay(w), XtWindow(w), topgc, bottomgc,
659 		   dx, dy, width, height, iw->primitive.shadow_thickness,
660 		   XmSHADOW_OUT);
661 
662     if (iw->primitive.highlighted)
663 	_XmExtHighlightBorder(w);
664     else
665 	_XmExtUnhighlightBorder(w);
666 }
667 
668 /*	Function Name: SetValuesAlmost
669  *	Description: Handles the case of our geom request being denied.
670  *	Arguments: old - the old state of the widget.
671  *                 set - the new state of the widget.
672  *                 request - the requested new geometry.
673  *                 reply - the compromise from our parent.
674  *	Returns: none
675  */
676 /* ARGSUSED */
677 static void
SetValuesAlmost(Widget old,Widget set,XtWidgetGeometry * request,XtWidgetGeometry * reply)678 SetValuesAlmost(Widget old, Widget set,
679 		XtWidgetGeometry * request,  XtWidgetGeometry * reply)
680 {
681     if (request->request_mode != 0) /* XtGeometryAlmost, make new request */
682 	*request = *reply;
683 
684     CalcLocations(set);
685 }
686 
687 /*	Function Name: SetValues
688  *	Description:   Called when some widget data needs to be modified on-
689  *                     the-fly.
690  *	Arguments:     current - the current (old) widget values.
691  *                     request - before superclassed have changed things.
692  *                     set - what will acutally be the new values.
693  *                     args, num_args - the arguments in the list.
694  *	Returns:       none
695  */
696 
697 /*ARGSUSED*/
698 static Boolean
SetValues(Widget current,Widget request,Widget set,ArgList args,Cardinal * num_args)699 SetValues(Widget current, Widget request, Widget set,
700 	  ArgList args, Cardinal * num_args)
701 {
702     Boolean resetGCs, recalc, redisplay, reinit_l, reinit_ls;
703     XmIconButtonWidget old_iw = (XmIconButtonWidget) current;
704     XmIconButtonWidget set_iw = (XmIconButtonWidget) set;
705     register int i;
706 
707     Boolean pixmapChanged = False;
708     Boolean pixmapGeoChanged = False;
709     Boolean resetPixmapValues = False;
710 
711     reinit_l = reinit_ls = resetGCs = recalc = redisplay = False;
712 
713     for (i = 0; i < *num_args; i++) {
714 	String name = args[i].name;
715 
716 	if (streq(XmNlabel, name))
717 	    reinit_l = resetGCs = recalc = redisplay = TRUE;
718 
719 	if (streq(XmNlabelString, name))
720 	    reinit_ls = resetGCs = recalc = redisplay = TRUE;
721 
722 	if (streq(XmNpixmap, name))
723 	{
724 	    DecPixCache(XtDisplay(current), XmIconButton_pixmap(old_iw));
725 	    recalc = redisplay = TRUE;
726 	    pixmapChanged = True;
727 	}
728 
729 	if ( streq(XmNpixmapWidth, name) || streq(XmNpixmapHeight, name) || streq(XmNpixmapDepth, name) )
730 	{
731 	    pixmapGeoChanged = True;
732 	    /* for now, we naively assume that the user knows that all of
733 	    ** these resources should be changed at the same time
734 	    */
735 	}
736 
737 	if (streq(XmNset, name)) {
738 	    /*
739 	     * Remove the timer since programmer has changed value.
740 	     */
741 	    if (XmIconButton_unset_timer(set_iw) != NO_TIMER) {
742 		XtRemoveTimeOut(XmIconButton_unset_timer(set_iw));
743 		XmIconButton_unset_timer(set_iw) = NO_TIMER;
744 	    }
745 	}
746     }
747 
748     /* ----------------------------------------------------------------- */
749 
750     /* now make sense of the pixmap changes */
751     if (pixmapChanged && !pixmapGeoChanged)
752     {
753 	/* for backward compatibility, reset values and fall through to
754 	** GetDesiredSize
755 	*/
756 	resetPixmapValues = True;
757     }
758     else if (pixmapGeoChanged && !pixmapChanged)
759     {
760 	/* we don't allow this case */
761 	resetPixmapValues = True;
762     }
763     /* else if neither changed, then we don't worry about anything */
764     /* else if both changed, we use new values */
765 
766     if (pixmapGeoChanged)
767     {
768 	/* here's what we enforce: all must be non-zero */
769 	if (!(	(0 != XmIconButton_pix_width(set_iw)) 	&&
770 		(0 != XmIconButton_pix_height(set_iw)) 	&&
771 		(0 != XmIconButton_pix_depth(set_iw))	))
772 		resetPixmapValues = True;
773     }
774 
775     /* for backward-compatibility, preserve old behavior in which pixmap
776     ** can change without sizes changing when recomputeSize is not set, in
777     ** which case we restore the values rather than use the new ones
778     */
779     if (resetPixmapValues)
780     {
781     	if (XmIconButton_recompute(set_iw))
782 	{
783 		XmIconButton_pix_width(set_iw) = 0;
784 		XmIconButton_pix_height(set_iw) =
785 		XmIconButton_pix_depth(set_iw) = 0;
786 	}
787 	else
788 	{
789 		XmIconButton_pix_width(set_iw) = XmIconButton_pix_width(old_iw);
790 		XmIconButton_pix_height(set_iw) = XmIconButton_pix_height(old_iw);
791 		XmIconButton_pix_depth(set_iw) = XmIconButton_pix_depth(old_iw);
792 	}
793     }
794 
795     /* ----------------------------------------------------------------- */
796 
797     if ((old_iw->primitive.foreground != set_iw->primitive.foreground) ||
798 	(old_iw->core.background_pixel != set_iw->core.background_pixel) ||
799 	(XmIconButton_arm_color(old_iw) != XmIconButton_arm_color(set_iw)))
800     {
801 	resetGCs = redisplay = True;
802     }
803 
804     if( XtIsSensitive(current) != XtIsSensitive(set) )
805     {
806 	redisplay = True;
807     }
808 
809     if( XmIconButton_font_list(old_iw) != XmIconButton_font_list(set_iw) ) {
810 	if( XmIconButton_font_list(old_iw)  != NULL )
811 	{
812 	    XmFontListFree (XmIconButton_font_list(old_iw));
813 	}
814 	if( XmIconButton_font_list(set_iw) == NULL )
815 	{
816 	    XmIconButton_font_list(set_iw) = XmeGetDefaultRenderTable(set,
817 							   XmBUTTON_FONTLIST);
818 	}
819 	XmIconButton_font_list(set_iw) = XmFontListCopy(XmIconButton_font_list(set_iw));
820 	recalc = redisplay = True;
821     }
822 
823     if ((XmIconButton_icon_placement(old_iw) != XmIconButton_icon_placement(set_iw)) ||
824 	(XmIconButton_v_space(old_iw) != XmIconButton_v_space(set_iw)) ||
825 	(XmIconButton_h_space(old_iw) != XmIconButton_h_space(set_iw)) ||
826 	(XmIconButton_icon_text_padding(old_iw) != XmIconButton_icon_text_padding(set_iw)))
827     {
828 	recalc = redisplay = TRUE;
829     }
830 
831     if ((XmIconButton_set(old_iw) != XmIconButton_set(set_iw)) ||
832 	(XmIconButton_alignment(old_iw) != XmIconButton_alignment(set_iw)) ||
833 	(XmIconButton_string_direction(old_iw) != XmIconButton_string_direction(set_iw)) ||
834         (XmPrim_layout_direction(old_iw) != XmPrim_layout_direction(set_iw)))
835     {
836 	redisplay = TRUE;
837     }
838 
839     if (XmIconButton_recompute(old_iw) != XmIconButton_recompute(set_iw)) {
840 	if (XmIconButton_recompute(set_iw))
841 	    redisplay = recalc = TRUE;
842     }
843 
844     if (reinit_l || reinit_ls)
845     {
846 	/*
847 	 * The order here makes sure that label string overrides label
848 	 * when both are set. Fix up data first, then check what we
849 	 * should be displaying. If both have changed, deal only with
850 	 * the label string case.
851 	 */
852 
853 	/* this has the desired behavior, except in this case: only
854 	 * XmNlabel is set at the beginning, then it migrates to
855 	 * XmNlabelString; then XmNlabel is reset to NULL. What value
856 	 * should be used?
857 	*/
858 	/* Boolean	was_from_name; */
859 	if (reinit_ls) {
860 		XmStringFree(XmIconButton_label_string(old_iw));
861 		if (XmIconButton_label_string(set_iw))
862 			XmIconButton_label_string(set_iw) = XmStringCopy(XmIconButton_label_string(set_iw));
863 	    }
864 	    if (reinit_l) {
865 		XtFree(XmIconButton_label(old_iw));
866 		if (XmIconButton_label(set_iw))
867 			XmIconButton_label(set_iw) = XtNewString(XmIconButton_label(set_iw));
868 	    }
869 	    /* was_from_name = XmIconButton_label_from_name(set_iw); */
870 	    XmIconButton_label_from_name(set_iw) = False;
871 	    if (reinit_ls) {
872 		if (XmIconButton_label_string(set_iw) == NULL) {
873 		    if (XmIconButton_label(set_iw) == NULL)
874 		    {
875 			XmIconButton_label_string(set_iw) = CreateXmString(set, XtName(set));
876 			XmIconButton_label_from_name(set_iw) = True;
877 		    }
878 		    else
879 		    {
880 			if ((XmIconButton_label_string(set_iw) =
881 			     CreateXmString(set, XmIconButton_label(set_iw))) == NULL)
882 			{
883 			    XmIconButton_label_string(set_iw) =
884 				CreateXmString(set, XtName(set));
885 			    XmIconButton_label_from_name(set_iw) = True;
886 			}
887 		    }
888 		}
889 	    }
890 	    else
891 	    if (reinit_l) {
892 		/* spec says, if labelString is set it is used, which
893 		 * isn't enough to really work with; I think it really
894 		 * means that if both are set, XmNlabelString is used,
895 		 * which is a much different thing
896 		 */
897 		/* now I'm confused as to why this was ever necessary */
898 		/* if (was_from_name)	*/
899 		{
900 			XmStringFree(XmIconButton_label_string(set_iw));
901 			if (XmIconButton_label(set_iw) == NULL)
902 			{
903 				XmIconButton_label_string(set_iw) = CreateXmString(set, XtName(set));
904 				XmIconButton_label_from_name(set_iw) = True;
905 			}
906 			else
907 			{
908 				if ((XmIconButton_label_string(set_iw) =
909 					 CreateXmString(set, XmIconButton_label(set_iw))) == NULL)
910 				{
911 					XmIconButton_label_string(set_iw) =
912 						CreateXmString(set, XtName(set));
913 					XmIconButton_label_from_name(set_iw) = True;
914 				}
915 			}
916 		}
917 	    }
918     }
919 
920     if (recalc) {
921 	if (XmIconButton_recompute(set_iw)) {
922 	    Dimension width, height;
923 
924 	    GetDesiredSize(set, &width,  &height);
925 
926 	    /*
927 	     * SetValues will ask for a new size.
928 	     */
929 
930 	    set->core.height = height;
931 	    set->core.width = width;
932 	}
933 
934 	CalcLocations(set);
935     }
936 
937     if (resetGCs) {
938 	DestroyGCs(current);
939 	CreateGCs(set);
940     }
941 
942     return(redisplay);
943 }
944 
945 /*	Function Name: Destroy
946  *	Description:   Cleans up after the widget.
947  *	Arguments:     w - the widget.
948  *	Returns:       none.
949  */
950 
951 /*ARGSUSED*/
952 static void
Destroy(Widget w)953 Destroy(Widget w)
954 {
955     XmIconButtonWidget iw = (XmIconButtonWidget) w;
956 
957     XtFree(XmIconButton_label(iw));
958     XmStringFree(XmIconButton_label_string(iw));
959     if (XmIconButton_font_list(iw)  != NULL) XmFontListFree (XmIconButton_font_list(iw));
960     DestroyGCs(w);
961 
962     if (XmIconButton_unset_timer(w) != NO_TIMER) {
963 	XtRemoveTimeOut(XmIconButton_unset_timer(w));
964 	XmIconButton_unset_timer(w) = NO_TIMER;
965     }
966 }
967 
968 /*	Function Name: QueryGeometry
969  *	Description:   Called when my parent wants to know what size
970  *                     I would like to be.
971  *	Arguments:     w - the widget to check.
972  *                     indended - constriants imposed by the parent.
973  *                     preferred - what I would like.
974  *	Returns:       See Xt Manual.
975  */
976 
977 static XtGeometryResult
QueryGeometry(Widget w,XtWidgetGeometry * intended,XtWidgetGeometry * preferred)978 QueryGeometry(Widget w,XtWidgetGeometry *intended, XtWidgetGeometry *preferred)
979 {
980     XmIconButtonWidget iw = (XmIconButtonWidget) w;
981 
982     if (XmIconButton_recompute(iw))
983 	GetDesiredSize(w, &(preferred->width), &(preferred->height));
984     else {
985 	preferred->width = w->core.width;
986 	preferred->height = w->core.height;
987     }
988 
989     return(_XmHWQuery(w, intended, preferred));
990 }
991 
992 /************************************************************
993  *
994  * Type Converters.
995  *
996  ************************************************************/
997 
998 /*	Function Name: CvtStringToIconPlacement
999  *	Description:   Converts a string to an Icon Placement
1000  *	Arguments:     dpy - the X Display.
1001  *                     args, num_args - *** NOT USED ***
1002  *                     fromVal - contains the string to convert.
1003  *                     toVal - contains the converted node state.
1004  *	Returns:       True if the SetValues succeeds.
1005  */
1006 
1007 /*ARGSUSED*/
1008 static Boolean
CvtStringToIconPlacement(Display * dpy,XrmValuePtr args,Cardinal * num_args,XrmValuePtr fromVal,XrmValuePtr toVal)1009 CvtStringToIconPlacement(Display * dpy, XrmValuePtr args, Cardinal *num_args,
1010 			 XrmValuePtr fromVal, XrmValuePtr toVal)
1011 {
1012     static XmIconPlacement type;
1013     static XrmQuark XtQETop;
1014     static XrmQuark XtQELeft;
1015     static XrmQuark XtQERight;
1016     static XrmQuark XtQEBottom;
1017     static XrmQuark XtQEIconOnly;
1018     static XrmQuark XtQEIconNone;
1019     static Boolean haveQuarks = FALSE;
1020     XrmQuark q;
1021     char lowerName[BUFSIZ];
1022 
1023     if (!haveQuarks) {
1024 	XtQETop = XrmStringToQuark("top");
1025 	XtQELeft = XrmStringToQuark("left");
1026 	XtQERight = XrmStringToQuark("right");
1027 	XtQEBottom = XrmStringToQuark("bottom");
1028 	XtQEIconOnly = XrmStringToQuark("icononly");
1029 	XtQEIconNone = XrmStringToQuark("none");
1030 	haveQuarks = TRUE;
1031     }
1032 
1033     XmCopyISOLatin1Lowered(lowerName, (char *) fromVal->addr);
1034     q = XrmStringToQuark(lowerName);
1035 
1036     if ( (q == XtQETop) || streq(lowerName, "icontop") )
1037 	type = XmIconTop;
1038     else if ( (q == XtQELeft) || streq(lowerName, "iconleft") )
1039 	type = XmIconLeft;
1040     else if ( (q == XtQERight) || streq(lowerName, "iconright") )
1041 	type = XmIconRight;
1042     else if ( (q == XtQEBottom) || streq(lowerName, "iconbottom") )
1043 	type = XmIconBottom;
1044     else if (q == XtQEIconOnly)
1045 	type = XmIconOnly;
1046     else if ( (q == XtQEIconNone) || streq(lowerName, "iconnone") )
1047 	type = XmIconNone;
1048     else {
1049 	XtDisplayStringConversionWarning(dpy,
1050 					 fromVal->addr, XmRXmIconPlacement);
1051 	return(FALSE);		/* Conversion failed. */
1052     }
1053 
1054     if (toVal->addr == NULL) {
1055 	toVal->size = sizeof(XmIconPlacement);
1056 	toVal->addr = (XtPointer) &type;
1057 	return(TRUE);
1058     }
1059 
1060     if (toVal->size >= sizeof(XmIconPlacement)) {
1061 	XmIconPlacement *loc = (XmIconPlacement *)toVal->addr;
1062 
1063 	*loc = type;
1064 	return(TRUE);
1065     }
1066 
1067     toVal->size = sizeof(XmIconPlacement);
1068     return(FALSE);
1069 }
1070 
1071 /************************************************************
1072  *
1073  * Actions and Callbacks.
1074  *
1075  ************************************************************/
1076 
1077 /*	Function Name: ToggleState
1078  *	Description:   Toggles the state of the icon button.
1079  *	Arguments:     w - the icon button widget.
1080  *                     event - the event that caused this action.
1081  *                     params, num_params - action routine parameters.
1082  *	Returns:       none.
1083  */
1084 
1085 /*ARGSUSED*/
1086 static void
ToggleState(Widget w,XEvent * event,String * params,Cardinal * num_params)1087 ToggleState(Widget w, XEvent * event, String * params, Cardinal * num_params)
1088 {
1089     XmIconButtonWidget iw = (XmIconButtonWidget) w;
1090     Arg args[1];
1091 
1092     XtSetArg(args[0], XmNset, !(XmIconButton_set(iw)));
1093     XtSetValues(w, args, (Cardinal) 1);
1094 }
1095 
1096 /*	Function Name: DoubleNotify
1097  *	Description:   Calls all functions on the icon button's
1098  *                     doubleClickCallback list
1099  *	Arguments:     w - the icon button widget.
1100  *                     event - the event that caused this action.
1101  *                     params, num_params - action routine parameters.
1102  *	Returns:       none.
1103  */
1104 
1105 /*ARGSUSED*/
1106 static void
DoubleNotify(Widget w,XEvent * event,String * params,Cardinal * num_params)1107 DoubleNotify(Widget w, XEvent * event, String * params, Cardinal * num_params)
1108 {
1109     XmIconButtonWidget iw = (XmIconButtonWidget) w;
1110     XmIconButtonCallbackInfo info;
1111 
1112     info.state = XmIconButton_set(iw);
1113     info.event = event;
1114 
1115     XtCallCallbackList(w, XmIconButton_double_click_callback(iw), &info);
1116 }
1117 
1118 /*	Function Name: Notify
1119  *	Description:   Calls all functions on the icon button's
1120  *                     activateCallback list
1121  *	Arguments:     w - the icon button widget.
1122  *                     event - the event that caused this action.
1123  *                     params, num_params - action routine parameters.
1124  *	Returns:       none.
1125  */
1126 
1127 /*ARGSUSED*/
1128 static void
Notify(Widget w,XEvent * event,String * params,Cardinal * num_params)1129 Notify(Widget w, XEvent * event, String * params, Cardinal * num_params)
1130 {
1131     XmIconButtonWidget iw = (XmIconButtonWidget) w;
1132     XmIconButtonCallbackInfo info;
1133     Boolean dclick;
1134 
1135     if ((event->type == ButtonPress) || (event->type == ButtonRelease))
1136 	dclick = ((event->xbutton.time - XmIconButton_time(iw)) <=
1137 		  XtGetMultiClickTime(XtDisplay(w)));
1138     else
1139 	dclick = False;
1140 
1141     info.state = XmIconButton_set(iw);
1142     info.event = event;
1143 
1144     if (dclick)
1145 	XtCallCallbackList(w, XmIconButton_double_click_callback(iw), &info);
1146     else
1147 	XtCallCallbackList(w, XmIconButton_activate_callback(iw), &info);
1148 }
1149 
1150 /*	Function Name: ArmAndActivate
1151  *	Description:   Arms the button, notifies it of the action, then
1152  *                     disarms the button after a small delay.
1153  *	Arguments:     w - the icon button widget.
1154  *                     event - the event that caused this action.
1155  *                     params, num_params - action routine parameters.
1156  *	Returns:       none.
1157  */
1158 
1159 /*ARGSUSED*/
1160 static void
ArmAndActivate(Widget w,XEvent * event,String * params,Cardinal * num_params)1161 ArmAndActivate(Widget w,
1162 	       XEvent * event, String * params, Cardinal * num_params)
1163 {
1164     XmIconButtonWidget iw = (XmIconButtonWidget) w;
1165     Arg args[1];
1166 
1167     if (!XmIconButton_set(iw)) {
1168 	XtSetArg(args[0], XmNset, True);
1169 	XtSetValues(w, args, (Cardinal) 1);
1170     }
1171 
1172     XmIconButton_unset_timer(iw) = XtAppAddTimeOut(XtWidgetToApplicationContext(w),
1173 					   (unsigned long) DELAY,
1174 					   Deactivate, (XtPointer) w);
1175 
1176     Notify(w, event, params, num_params);
1177 }
1178 
1179 /*	Function Name: Deactivate
1180  *	Description: Called when the icon button should be deactivated.
1181  *	Arguments: data - the client data.
1182  *                 timer - the timer that fired.
1183  *	Returns: none.
1184  */
1185 
1186 /* ARGSUSED */
1187 static void
Deactivate(XtPointer data,XtIntervalId * timer)1188 Deactivate(XtPointer data, XtIntervalId *timer)
1189 {
1190     Arg args[1];
1191     Widget w = (Widget) data;
1192     XmIconButtonWidget iw = (XmIconButtonWidget) w;
1193 
1194     XtSetArg(args[0], XmNset, False);
1195     XtSetValues(w, args, (Cardinal) 1);
1196 
1197     XmIconButton_unset_timer(iw) = NO_TIMER;
1198 }
1199 
1200 /*	Function Name: ButtonUp
1201  *	Description:   Saves the timestamp of the ButtonUp event
1202  *                     for later double click processing
1203  *	Arguments:     w - the icon button widget.
1204  *                     event - the event that caused this action.
1205  *                     params, num_params - action routine parameters.
1206  *	Returns:       none.
1207  */
1208 
1209 /*ARGSUSED*/
1210 static void
ButtonUp(Widget w,XEvent * event,String * params,Cardinal * num_params)1211 ButtonUp(Widget w,
1212 	       XEvent * event, String * params, Cardinal * num_params)
1213 {
1214     XmIconButtonWidget iw = (XmIconButtonWidget) w;
1215 
1216     XmIconButton_time(iw) = event->xbutton.time;
1217 }
1218 
1219 /************************************************************
1220  *
1221  * Internal routines.
1222  *
1223  ************************************************************/
1224 
1225 /*	Function Name: GetCacheElem
1226  *	Description: Gets an element in the cache.
1227  *	Arguments: disp, pixmap - The keys into the cache.
1228  *	Returns: elem - The list elem for this element.
1229  */
1230 
1231 static XmListElem *
GetCacheElem(Display * disp,Pixmap pix)1232 GetCacheElem(Display *disp, Pixmap pix)
1233 {
1234     register XmListElem *elem;
1235 
1236     if (pix_cache_list == NULL)
1237 	return(NULL);
1238 
1239     for (elem = XmListFirst(pix_cache_list); elem != NULL;
1240 	 elem = XmListElemNext(elem))
1241     {
1242 	PixCacheEntry * entry = (PixCacheEntry *) XmListElemData(elem);
1243 
1244 	if ((entry->display == disp) && (entry->pixmap == pix))
1245 	{
1246 	    return(elem);
1247 	}
1248     }
1249 
1250     return(NULL);
1251 }
1252 
1253 /*	Function Name: CheckPixCache
1254  *	Description: Checks the cache to see if this pixmap is in it.
1255  *	Arguments: disp, pixmap - The keys into the cache.
1256  *                 width, height and depth - data about the pixmap.
1257  *	Returns: True if a match found.
1258  */
1259 
1260 static Boolean
CheckPixCache(Display * disp,Pixmap pixmap,unsigned int * width,unsigned int * height,unsigned int * depth)1261 CheckPixCache(Display *disp, Pixmap pixmap,
1262 	      unsigned int *width, unsigned int *height, unsigned int *depth)
1263 {
1264     XmListElem * elem = GetCacheElem(disp, pixmap);
1265     PixCacheEntry * entry;
1266 
1267     if (elem == NULL)
1268 	return(False);
1269 
1270     entry = (PixCacheEntry *) XmListElemData(elem);
1271 
1272     *width = entry->width;
1273     *height = entry->height;
1274     *depth = entry->depth;
1275 
1276     return(True);
1277 }
1278 
1279 /*	Function Name: AddPixCache
1280  *	Description: Adds or updates data in the pixmap cache.
1281  *	Arguments: disp, pixmap - The keys into the cache.
1282  *                 width, height and depth - data about the pixmap.
1283  *	Returns: True if a match found.
1284  */
1285 
1286 static void
AddPixCache(Display * disp,Pixmap pixmap,unsigned int width,unsigned int height,unsigned int depth)1287 AddPixCache(Display *disp, Pixmap pixmap,
1288 	    unsigned int width, unsigned int height, unsigned int depth)
1289 {
1290     XmListElem * elem = GetCacheElem(disp, pixmap);
1291     PixCacheEntry * entry;
1292 
1293     if (elem == NULL)
1294     {
1295 	entry = (PixCacheEntry *) XtCalloc(sizeof(PixCacheEntry), 1);
1296 	entry->display = disp;
1297 	entry->pixmap = pixmap;
1298 
1299 	if (pix_cache_list == NULL)
1300 	    pix_cache_list = _XmListInit();
1301 	_XmListAddBefore(pix_cache_list, NULL, (XtPointer) entry);
1302     }
1303     else
1304 	entry = (PixCacheEntry *) XmListElemData(elem);
1305 
1306     entry->width = width;
1307     entry->height = height;
1308     entry->depth = depth;
1309 }
1310 
1311 /*	Function Name: IncPixCache
1312  *	Description: Increments the count in the pixmap cache.
1313  *	Arguments: disp - The current display.
1314  *                 pix - The pixmap to increment.
1315  *	Returns: none.
1316  */
1317 
1318 static void
IncPixCache(Display * disp,Pixmap pix)1319 IncPixCache(Display *disp, Pixmap pix)
1320 {
1321     XmListElem * elem = GetCacheElem(disp, pix);
1322 
1323     if (elem != NULL)
1324 	(((PixCacheEntry *) XmListElemData(elem))->count)++;
1325 }
1326 
1327 /*	Function Name: DecPixCache
1328  *	Description: Decrements the count in the pixmap cache.
1329  *	Arguments: disp - The current display.
1330  *                 pix - The pixmap to increment.
1331  *	Returns: none.
1332  */
1333 
1334 static void
DecPixCache(Display * disp,Pixmap pix)1335 DecPixCache(Display *disp, Pixmap pix)
1336 {
1337     XmListElem * elem = GetCacheElem(disp, pix);
1338     PixCacheEntry * entry;
1339 
1340     if (elem == NULL)
1341 	return;
1342 
1343     entry = (PixCacheEntry *) XmListElemData(elem);
1344 
1345     if (entry->count > 0)
1346 	(entry->count)--;
1347 
1348     if (entry->count == 0) {
1349 	_XmListRemove(pix_cache_list, elem);
1350 	XtFree((char *) entry);
1351     }
1352 }
1353 
1354 /* ARGSUSED */
GetValues_labelString(Widget w,int n,XtArgVal * value)1355 static void GetValues_labelString ( Widget w, int n, XtArgVal *value)
1356 {
1357 	(*value) = (XtArgVal) XmStringCopy(XmIconButton_label_string(w));
1358 }
1359 
1360 /*	Function Name: FromPaddingPixels
1361  *	Description: Converts from pixels to current unit type
1362  *                   does either horiz or vert depending on icon placement.
1363  *	Arguments: widget - the icon button widget.
1364  *                 offset, value - passed to correct function based
1365  *                                 on orientation.
1366  *	Returns: none
1367  */
1368 
1369 static void
FromPaddingPixels(Widget widget,int offset,XtArgVal * value)1370 FromPaddingPixels(Widget widget, int offset, XtArgVal *value)
1371 {
1372     XmIconButtonWidget iw = (XmIconButtonWidget) widget;
1373 
1374     switch(XmIconButton_icon_placement(iw)) {
1375     case XmIconTop:
1376     case XmIconBottom:
1377 	XmeFromVerticalPixels(widget, offset, value);
1378 	break;
1379     default:			/* everything else is horiz. */
1380 	XmeFromHorizontalPixels(widget, offset, value);
1381 	break;
1382     }
1383 }
1384 
1385 /*	Function Name: ToPaddingPixels
1386  *	Description: Converts to pixels from current unit type
1387  *                   does either horiz or vert depending on icon placement.
1388  *	Arguments: widget - the icon button widget.
1389  *                 offset, value - passed to correct function based
1390  *                                 on orientation.
1391  *	Returns: the import order from _XmTo{Horizontal, Vertical}Pixels.
1392  */
1393 
1394 static XmImportOperator
ToPaddingPixels(Widget widget,int offset,XtArgVal * value)1395 ToPaddingPixels(Widget widget, int offset, XtArgVal *value)
1396 {
1397     XmIconButtonWidget iw = (XmIconButtonWidget) widget;
1398 
1399     switch(XmIconButton_icon_placement(iw)) {
1400     case XmIconTop:
1401     case XmIconBottom:
1402 	return(XmeToVerticalPixels(widget, offset, value));
1403     default:
1404 	return(XmeToHorizontalPixels(widget, offset, value));
1405     }
1406 }
1407 
1408 /*	Function Name: GetDesiredSize
1409  *	Description:   Gets the size that this widget would like to be.
1410  *	Arguments:     w - the icon widget.
1411  *  RETURNED           width, height - the desired size.
1412  *	Returns:       none.
1413  */
1414 
1415 static void
GetDesiredSize(Widget w,Dimension * width,Dimension * height)1416 GetDesiredSize(Widget w, Dimension * width, Dimension * height)
1417 {
1418     XmIconButtonWidget iw = (XmIconButtonWidget) w;
1419     Dimension total_width, total_height;
1420 
1421     XmStringExtent(XmIconButton_font_list(iw), XmIconButton_label_string(iw),
1422 		   &total_width, &total_height);
1423 
1424     if( (XmIconButton_icon_placement(iw) != XmIconNone) && ValidPixmap(XmIconButton_pixmap(iw)) )
1425     {
1426 	Window root;
1427 	int x, y;
1428 	unsigned int local_width, local_height, bw, depth;
1429 
1430 	/*
1431 	 * If we have an icon of unknown size then ask the server,
1432 	 * be sure to not make a round trip if not needed.
1433 	 */
1434 
1435 	if ((XmIconButton_pix_width(iw) == 0) || (XmIconButton_pix_height(iw) == 0) ||
1436 	    (XmIconButton_pix_depth(iw) == 0))
1437 	{
1438 	    if (!CheckPixCache(XtDisplay(w), XmIconButton_pixmap(iw),
1439 			       &local_width, &local_height, &depth))
1440 	    {
1441 		XGetGeometry(XtDisplay(w), XmIconButton_pixmap(iw), &root, &x, &y,
1442 			     &local_width, &local_height, &bw, &depth);
1443 
1444 		AddPixCache(XtDisplay(w), XmIconButton_pixmap(iw),
1445 			    local_width, local_height, depth);
1446 	    }
1447 
1448 	    IncPixCache(XtDisplay(w), XmIconButton_pixmap(iw));
1449 
1450 	    XmIconButton_pix_width(iw) = local_width;
1451 	    XmIconButton_pix_height(iw) = local_height;
1452 	    XmIconButton_pix_depth(iw) = depth;
1453 	}
1454 	else {
1455 	    local_width = XmIconButton_pix_width(iw);
1456 	    local_height = XmIconButton_pix_height(iw);
1457 	    depth = XmIconButton_pix_depth(iw);
1458 	}
1459 
1460 	switch (XmIconButton_icon_placement(iw)) {
1461 	case XmIconTop:
1462 	case XmIconBottom:
1463 	    total_height += local_height + XmIconButton_icon_text_padding(iw);
1464 
1465 	    if ( local_width > total_width )
1466 		total_width = local_width;
1467 
1468 	    break;
1469 	case XmIconOnly:
1470 	    total_height = local_height;
1471 	    total_width = local_width;
1472 	    break;
1473 	case XmIconLeft:
1474 	case XmIconRight:
1475 	    total_width += local_width + XmIconButton_icon_text_padding(iw);
1476 
1477 	    if (local_height > total_height)
1478 		total_height = local_height;
1479 
1480 	    break;
1481 	default:
1482 	    break;
1483 	}
1484     }
1485     else {
1486 	XmIconButton_pix_width(iw) = XmIconButton_pix_height(iw) = 0;
1487 	XmIconButton_pix_depth(iw) = 0;
1488     }
1489 
1490 
1491     *height = total_height + 2 * V_SPACE(iw);
1492     *width = total_width + 2 * H_SPACE(iw);
1493 }
1494 
1495 /*	Function Name: RequestNewSize
1496  *	Description:   Asks our parent for a new size.
1497  *	Arguments:     w - the Icon Button widget.
1498  *                     width, height - the width and height we want to be.
1499  *	Returns:       none.
1500  */
1501 
1502 static void
RequestNewSize(Widget w,Dimension width,Dimension height)1503 RequestNewSize(Widget w, Dimension width, Dimension height)
1504 {
1505     Dimension w_ret, h_ret;
1506     XtGeometryResult ret_val;
1507 
1508     ret_val = XtMakeResizeRequest(w, width, height, &w_ret, &h_ret);
1509 
1510     if (ret_val == XtGeometryAlmost)
1511 	(void) XtMakeResizeRequest(w, w_ret, h_ret, NULL, NULL);
1512 
1513     Resize(w);			/* May not have been called. */
1514 }
1515 
1516 /*	Function Name: CalcLocations
1517  *	Description:   Calculates where the icon and strings should be
1518  *                     painted.
1519  *	Arguments:     w - the icon button widget.
1520  *	Returns:       none.
1521  */
1522 
1523 static void
CalcLocations(Widget w)1524 CalcLocations(Widget w)
1525 {
1526     XmIconButtonWidget iw = (XmIconButtonWidget) w;
1527     Dimension width, height, d_width, d_height;
1528     Dimension extra_y_space;
1529     Boolean   have_pixmap = True;
1530 
1531     width = w->core.width;
1532     height = w->core.height;
1533 
1534     GetDesiredSize(w, &d_width, &d_height);
1535 
1536     if (height > d_height)
1537 	extra_y_space = (int)(height - d_height)/2;
1538     else
1539 	extra_y_space = 0;
1540 
1541     XmIconButton_max_text_width(iw) = width - 2 * H_SPACE(iw);
1542     XmIconButton_max_text_height(iw) = height - 2 * V_SPACE(iw);
1543     XmIconButton_text_x(iw) = H_SPACE(iw);
1544     XmIconButton_text_y(iw) = V_SPACE(iw);
1545 
1546     if( XmIconButton_icon_placement(iw) != XmIconNone && ValidPixmap(XmIconButton_pixmap(iw)) )
1547     {
1548 	/*
1549 	 * Here we actually have a pixmap so lets figure out the
1550 	 * location of the pixmap.  First we will loook at the
1551 	 * horizontal position.
1552 	 */
1553 	switch (XmIconButton_icon_placement(iw)) {
1554 	case XmIconLeft: /* Flush Left */
1555 	    XmIconButton_pix_x(iw) = (Position) H_SPACE(iw);
1556 	    break;
1557 	case XmIconRight: /* Flush Right */
1558 	    XmIconButton_pix_x(iw) = (Position) (width - H_SPACE(iw) -
1559 					 XmIconButton_pix_width(iw));
1560 	    break;
1561 	default: /* Centered */
1562 	    XmIconButton_pix_x(iw) = ((Position) width -
1563 			      (Position) XmIconButton_pix_width(iw))/2;
1564 	    break;
1565 	}
1566 
1567 	/*
1568 	 * Now lets deside on the the vertical position
1569 	 */
1570 	switch (XmIconButton_icon_placement(iw)) {
1571 	case XmIconTop: /* Centered At the top */
1572 	    XmIconButton_pix_y(iw) = V_SPACE(iw) + extra_y_space;
1573 	    break;
1574 	case XmIconBottom: /* Centered at the bottom */
1575 	    XmIconButton_pix_y(iw) = ((Position) height -
1576 			      ((Position) V_SPACE(iw) +
1577 			       (Position) extra_y_space +
1578 			       (Position) XmIconButton_pix_height(iw)));
1579 	    break;
1580 	default: /* Centered */
1581 	    XmIconButton_pix_y(iw) = ((Position) height -
1582 			      (Position) XmIconButton_pix_height(iw))/2;
1583 	    break;
1584 	}
1585     }
1586     else
1587     {
1588 	/*
1589 	 * If we get here that means that we do not have a pixmap
1590 	 * to play with so lets just zero the x and y locations of the
1591 	 * pixmap.
1592 	 */
1593 	XmIconButton_pix_x(iw) = XmIconButton_pix_y(iw) = 0;
1594 	have_pixmap = False;
1595     }
1596 
1597     /*
1598      * Now that we know the location of the pixmap, lets go and try to
1599      * find out what we want to do with the XmString if there is one.
1600      */
1601     if( XmIconButton_icon_placement(iw) != XmIconOnly ) {
1602 	Dimension text_width, text_height;
1603 	int       tmp;
1604 
1605 	/*
1606 	 * First let find out what the size of the string we have is
1607 	 */
1608 	XmStringExtent(XmIconButton_font_list(iw), XmIconButton_label_string(iw),
1609 		       &text_width, &text_height);
1610 	XmIconButton_max_text_height(iw) = text_height;
1611 
1612 	switch (XmIconButton_icon_placement(iw)) {
1613 	case XmIconLeft: /* Aligned to Right of Icon. */
1614 	    /*
1615 	     * If the pixmap is to our left then we can use all the
1616 	     * space to the right of the pixmap.
1617 	     */
1618 	    if( have_pixmap )
1619 	    {
1620 		XmIconButton_text_x(iw) = XmIconButton_pix_x(iw) + XmIconButton_pix_width(iw) +
1621 		    XmIconButton_icon_text_padding(iw);
1622 		if( (tmp = (int)width - (int)H_SPACE(iw) -
1623 		     (int)XmIconButton_text_x(iw)) < 0 )
1624 		{
1625 		    tmp = 0;
1626 		}
1627 
1628 		XmIconButton_max_text_width(iw) = tmp;
1629 	    }
1630 	    break;
1631 	case XmIconRight: /* Aligned to left of Icon. */
1632 	    if( have_pixmap )
1633 	    {
1634 		XmIconButton_text_x(iw) = H_SPACE(iw);
1635 		if( (tmp = XmIconButton_pix_x(iw) - XmIconButton_text_x(iw)) < 0 ) tmp = 0;
1636 		XmIconButton_max_text_width(iw) = tmp;
1637 	    }
1638 	    break;
1639 	default:
1640 	    break;
1641 	}
1642 
1643 	switch (XmIconButton_icon_placement(iw)) {
1644 	case XmIconTop: /* Along Bottom. */
1645 	    XmIconButton_text_y(iw) = height - (V_SPACE(iw) + (Position)text_height);
1646 	    if( have_pixmap )
1647 	    {
1648 		tmp = XmIconButton_pix_y(iw) + XmIconButton_pix_height(iw) +
1649 		    XmIconButton_icon_text_padding(iw);
1650 		if( XmIconButton_text_y(iw) < tmp )
1651 		{
1652 		    XmIconButton_text_y(iw) = tmp;
1653 		    if( (tmp = height - V_SPACE(iw) - XmIconButton_text_y(iw)) < 0 )
1654 			tmp = 0;
1655 		    XmIconButton_max_text_height(iw) = tmp;
1656 		}
1657 	    }
1658 	    break;
1659 	case XmIconBottom: /* Along Top. */
1660 	    XmIconButton_text_y(iw) = V_SPACE(iw);
1661 	    if( have_pixmap )
1662 	    {
1663 		tmp = XmIconButton_pix_y(iw) - XmIconButton_icon_text_padding(iw) -
1664 		    XmIconButton_text_y(iw);
1665 		if( tmp < 0 ) tmp = 0;
1666 		XmIconButton_max_text_height(iw) = tmp;
1667 	    }
1668 	    break;
1669 	default:
1670 	    /* Centered. */
1671 	    XmIconButton_text_y(iw) = ((Position) height - (Position) text_height)/2;
1672 	    break;
1673 	}
1674     }
1675 
1676     /*
1677      * Else
1678      *
1679      * Text_x and Text_y are garbage, but never used.
1680      */
1681 }
1682 
1683 /*	Function Name: DrawTextAndImage
1684  *	Description:   Renders the Text and the image.
1685  *	Arguments:     w - the icon button widget.
1686  *                     text_gc - gc to use when drawing the text.
1687  *                     icon_gc - gc to use when drawing the icon.
1688  *                     icon_stippled_gc - gc to use to fake a stipple
1689  *                                       on the image.
1690  *	Returns:       none.
1691  */
1692 
1693 static void
DrawTextAndImage(Widget w,GC text_gc,GC icon_gc,GC icon_stippled_gc)1694     DrawTextAndImage(Widget w, GC text_gc, GC icon_gc, GC icon_stippled_gc)
1695 {
1696     XmIconButtonWidget iw = (XmIconButtonWidget) w;
1697 
1698     if( XmIconButton_icon_placement(iw) != XmIconNone && ValidPixmap(XmIconButton_pixmap(iw)) )
1699     {
1700 	if (XmIconButton_pix_depth(iw) == 1)
1701 	{
1702 	    XCopyPlane(XtDisplay(w), XmIconButton_pixmap(iw), XtWindow(w), icon_gc,
1703 		       0, 0, XmIconButton_pix_width(iw), XmIconButton_pix_height(iw),
1704 		       XmIconButton_pix_x(iw), XmIconButton_pix_y(iw), 1L);
1705 	}
1706 	else
1707 	{
1708 	    XCopyArea(XtDisplay(w), XmIconButton_pixmap(iw), XtWindow(w), icon_gc,
1709 		      0, 0, XmIconButton_pix_width(iw), XmIconButton_pix_height(iw),
1710 		      XmIconButton_pix_x(iw), XmIconButton_pix_y(iw));
1711 	}
1712 
1713 	/*
1714 	 * Stipple the background color over the top of the image
1715 	 * since XCopyPlace and Area do not use the tile or stipple.
1716 	 */
1717 
1718 	if( icon_stippled_gc != None )
1719 	{
1720 	    XFillRectangle(XtDisplay(w), XtWindow(w), icon_stippled_gc,
1721 			   XmIconButton_pix_x(iw), XmIconButton_pix_y(iw),
1722 			   XmIconButton_pix_width(iw), XmIconButton_pix_height(iw));
1723 	}
1724     }
1725 
1726     if( XmIconButton_icon_placement(iw) != XmIconOnly )
1727     {
1728 	int        size, tmp;
1729 	XRectangle clip;
1730 
1731 	clip.x = XmIconButton_text_x(iw);
1732 	clip.y = XmIconButton_text_y(iw);
1733 	clip.width = XmIconButton_max_text_width(iw);
1734 	clip.height = XmIconButton_max_text_height(iw);
1735 
1736 	if( (int)clip.x < (int)H_SPACE(iw) ) clip.x = H_SPACE(iw);
1737 	if( (int)clip.y < (int)V_SPACE(iw) ) clip.y = V_SPACE(iw);
1738 
1739 	size = XtWidth(iw) - H_SPACE(iw);
1740 	if( (int) (clip.x + clip.width) > size )
1741 	{
1742 	    tmp = size - (int)clip.x;
1743 	    if( tmp < 0 ) tmp = 0;
1744 	    clip.width = tmp;
1745 	}
1746 
1747 	size = XtHeight(iw) - V_SPACE(iw);
1748 	if( (int)(clip.y + clip.height) > size )
1749 	{
1750 	    tmp = size - (int)clip.y;
1751 	    if( tmp < 0 ) tmp = 0;
1752 	    clip.height = tmp;
1753 	}
1754 
1755 	if( clip.width != 0 && clip.height != 0 )
1756 	{
1757 	    /*
1758 	     * Set the clip rectangle so things do not
1759 	     * overlap or go out of bounds.
1760 	     */
1761 	    XSetClipRectangles(XtDisplay(w), text_gc,
1762 			       0, 0, &clip, 1, Unsorted);
1763 #ifdef FIX_1381
1764 		/*Draw shadow for insensitive text*/
1765 		if (!XtIsSensitive(w)) {
1766 			XmStringDraw(XtDisplay(w), XtWindow(w), XmIconButton_font_list(iw),
1767 				XmIconButton_label_string(iw), XmIconButton_shadow_gc(iw),
1768 				XmIconButton_text_x(iw)+1, XmIconButton_text_y(iw)+1,
1769 				XmIconButton_max_text_width(iw), XmIconButton_alignment(iw),
1770 				XmPrim_layout_direction(iw), NULL);
1771 		}
1772 #endif
1773 	    XmStringDraw(XtDisplay(w), XtWindow(w), XmIconButton_font_list(iw),
1774 			 XmIconButton_label_string(iw), text_gc,
1775 			 XmIconButton_text_x(iw), XmIconButton_text_y(iw),
1776 			 XmIconButton_max_text_width(iw), XmIconButton_alignment(iw),
1777 			 XmPrim_layout_direction(iw), NULL);
1778 	    XSetClipMask(XtDisplay(w), text_gc, None);
1779 	}
1780     }
1781 }
1782 
1783 /*
1784  * There is almost always only 1 display, and certainly only a few, therefore
1785  * there is no need to be clever here, just make sure it works for one
1786  * fast, and doesn't break when using many.
1787  *
1788  * Would be nice to refocunt and remove...
1789  */
1790 
1791 static Pixmap
GetGreyStipple(Widget w)1792 GetGreyStipple(Widget w)
1793 {
1794   StippleInfo *set, *ptr;
1795 
1796   for (ptr = stipple_cache; ptr != NULL; ptr = ptr->next) {
1797     /* Check for both screen and display, such that it displays */
1798     /* correctly on multi-headed X-servers.                     */
1799     /* Change Request #: CR03619                                */
1800     if (ptr->disp == XtDisplay(w) && ptr->screen == XtScreen(w)) {
1801       return (ptr->stipple);
1802     }
1803   }
1804 
1805   set = (StippleInfo *) XtMalloc(sizeof(StippleInfo));
1806   set->stipple = XCreateBitmapFromData(XtDisplay(w),
1807 				       RootWindowOfScreen(XtScreen(w)),
1808 				       gray_bits, gray_width, gray_height);
1809   set->disp = XtDisplay(w);
1810   set->screen = XtScreen(w);
1811   set->next = NULL;
1812 
1813   if (stipple_cache == NULL)
1814     stipple_cache = set;
1815   else
1816     for (ptr = stipple_cache; ptr != NULL; ptr = ptr->next)
1817       if (ptr->next == NULL) {
1818 	ptr->next = set;
1819 	break;
1820       }
1821 
1822   return(set->stipple);
1823 }
1824 
1825 /*	Function Name: CreateGCs
1826  *	Description:   Creates the Graphics contexts
1827  *	Arguments:     w - the icon button widget.
1828  *	Returns:       none
1829  */
1830 
1831 static void
CreateGCs(Widget w)1832 CreateGCs(Widget w)
1833 {
1834     XmIconButtonWidget iw = (XmIconButtonWidget) w;
1835     XtGCMask mask, smask;
1836     XGCValues values;
1837     Pixel fg, bg;
1838     Pixmap stipple;
1839     Arg args[2];
1840     Cardinal num_args = 0;
1841     XFontStruct *fs = NULL;
1842 
1843     XtSetArg(args[num_args], XmNforeground, &fg); num_args++;
1844     XtSetArg(args[num_args], XmNbackground, &bg); num_args++;
1845     XtGetValues(w, args, num_args);
1846 
1847     stipple = GetGreyStipple(w);
1848 
1849     XmeRenderTableGetDefaultFont(XmIconButton_font_list(iw), &fs);
1850 
1851     values.foreground = fg;
1852     values.background = bg;
1853     values.graphics_exposures = False;
1854     values.stipple = stipple;
1855     values.fill_style = FillStippled;
1856 
1857     mask = GCForeground | GCBackground | GCGraphicsExposures;
1858 #ifdef FIX_1381
1859 	smask = mask | GCFillStyle;
1860 #else
1861     smask = mask | GCStipple | GCFillStyle;
1862 #endif
1863 
1864     if (fs) {
1865         values.font = fs->fid;
1866         mask |= GCFont;
1867     }
1868 
1869     XmIconButton_gc(iw) = XtGetGC(w, mask, &values);
1870 
1871 #ifdef FIX_1381
1872     /*generally gray insensitive foreground (instead stipple)*/
1873     values.foreground = _XmAssignInsensitiveColor((Widget)iw);
1874     XmIconButton_insensitive_text_gc(iw) = XtGetGC(w, smask, &values);
1875 #else
1876     XmIconButton_stippled_text_gc(iw) = XtGetGC(w, smask, &values);
1877 #endif
1878 
1879 #ifdef FIX_1381
1880     /*light shadow for insensitive text (instead stipple)*/
1881     values.foreground = iw->primitive.top_shadow_color;
1882     XmIconButton_shadow_gc(iw) = XtGetGC(w, smask, &values);
1883 #endif
1884 
1885     /*
1886      * HACK ALERT: !!! Motif hack for monochrome displays. !!!
1887      *             If fg and arm color are the same then replace fg color
1888      *             with bg color.
1889      */
1890 
1891     if (values.foreground == XmIconButton_arm_color(iw))
1892 	values.foreground = bg;
1893 
1894     /*
1895      * else just use the same fg color we used to be using.
1896      */
1897 
1898     values.background = XmIconButton_arm_color(iw);
1899     XmIconButton_pixmap_fill_gc(iw) = XtGetGC(w, mask, &values);
1900     XmIconButton_stippled_set_text_gc(iw) = XtGetGC(w, smask, &values);
1901 
1902     mask = GCForeground;
1903     values.foreground = XmIconButton_arm_color(iw);
1904 
1905     XmIconButton_fill_gc(iw) = XtGetGC(w, mask, &values);
1906 
1907     values.foreground = bg;
1908     smask = mask | GCStipple | GCFillStyle;
1909     XmIconButton_stippled_unset_gc(iw) = XtGetGC(w, smask, &values);
1910 
1911     values.foreground = XmIconButton_arm_color(iw);
1912     XmIconButton_stippled_set_gc(iw) = XtGetGC(w, smask, &values);
1913 }
1914 
1915 /*	Function Name: DestroyGCs
1916  *	Description:   Destroys all GC's needed by icon button.
1917  *	Arguments:     w - the icon button widget.
1918  *	Returns:       none.
1919  */
1920 
1921 static void
DestroyGCs(Widget w)1922 DestroyGCs(Widget w)
1923 {
1924     XmIconButtonWidget iw = (XmIconButtonWidget) w;
1925 
1926     XtReleaseGC(w, XmIconButton_gc(iw));
1927     XtReleaseGC(w, XmIconButton_fill_gc(iw));
1928     XtReleaseGC(w, XmIconButton_pixmap_fill_gc(iw));
1929     XtReleaseGC(w, XmIconButton_stippled_set_gc(iw));
1930     XtReleaseGC(w, XmIconButton_stippled_unset_gc(iw));
1931 #ifdef FIX_1381
1932     XtReleaseGC(w, XmIconButton_shadow_gc(iw));
1933     XtReleaseGC(w, XmIconButton_insensitive_text_gc(iw));
1934 #else
1935     XtReleaseGC(w, XmIconButton_stippled_text_gc(iw));
1936 #endif
1937     XtReleaseGC(w, XmIconButton_stippled_set_text_gc(iw));
1938 }
1939 
1940 /*	Function Name: CreateXmString
1941  *	Description: Given a char * create an Xm String.
1942  *                   an remember to put in the new lines.
1943  *	Arguments: str - the String.
1944  *	Returns: The Motif string for this string.
1945  */
1946 
1947 static XmString
CreateXmString(Widget w,String str)1948 CreateXmString(Widget w, String str)
1949 {
1950     XrmValue		fromVal, toVal;
1951     XmString xmstr;
1952 
1953     fromVal.size = strlen(str) + 1; /* space for NULL. */
1954     fromVal.addr = str;
1955 
1956     toVal.size = sizeof(XmString);
1957     toVal.addr = (XtPointer) &xmstr;
1958 
1959     if (XtConvertAndStore(w, XmRString, &fromVal, XmRXmString, &toVal)) {
1960 	xmstr = XmStringCopy(xmstr); /* because I free it later. */
1961 	return(xmstr);
1962     }
1963     return(NULL);
1964 }
1965 
1966 /*
1967  * XmRCallProc routine for checking font_list before setting it to NULL
1968  * If "check_set_render_table" is True, then function has
1969  * been called twice on same widget, thus resource needs to be set NULL,
1970  * otherwise leave it alone.
1971  */
1972 
1973 /*ARGSUSED*/
1974 static void
CheckSetRenderTable(Widget wid,int offs,XrmValue * value)1975 CheckSetRenderTable(Widget wid,
1976 		    int offs,
1977 		    XrmValue *value)
1978 {
1979   XmIconButtonWidget lw = (XmIconButtonWidget)wid;
1980 
1981   /* Check if been here before */
1982   if (lw->icon.check_set_render_table)
1983       value->addr = NULL;
1984   else {
1985       lw->icon.check_set_render_table = True;
1986       value->addr = (char*)&(lw->icon.font_list);
1987   }
1988 
1989 }
1990 
1991 /*	Function name: ChangeCB
1992  *	Description: add or remove the activate callback list.
1993  *	Arguments:   w - the child widget ha� its list of callbacks modified
1994  *	             activCB - the callback to add or remove from
1995  *	             closure - additional data to be passed to the callback
1996  *	             setunset - set/unset flag
1997  *	Returns: none
1998  */
1999 
2000 static void
ChangeCB(Widget w,XtCallbackProc activCB,XtPointer closure,Boolean setunset)2001 ChangeCB(
2002 	 Widget w,
2003 	 XtCallbackProc activCB,
2004 	 XtPointer closure,
2005 	 Boolean setunset)
2006 {
2007   if (setunset)
2008     XtAddCallback (w, XmNactivateCallback, activCB, closure);
2009   else
2010     XtRemoveCallback (w, XmNactivateCallback, activCB, closure);
2011 }
2012 
2013 /************************************************************
2014  *
2015  * Public routines.
2016  *
2017  ************************************************************/
2018 
2019 /*	Function Name: XmCreateIconButton
2020  *	Description: Creation Routine for UIL and ADA.
2021  *	Arguments: parent - the parent widget.
2022  *                 name - the name of the widget.
2023  *                 args, num_args - the number and list of args.
2024  *	Returns: The created widget.
2025  */
2026 
2027 Widget
XmCreateIconButton(Widget parent,String name,ArgList args,Cardinal num_args)2028 XmCreateIconButton(Widget parent, String name,
2029 		   ArgList args, Cardinal num_args)
2030 {
2031     return(XtCreateWidget(name, xmIconButtonWidgetClass,
2032 			  parent, args, num_args));
2033 }
2034