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