1 /********************************************************************\
2 **                             _________________________________    **
3 **   A n t h o n y            |________    __    __    _________|   **
4 **                                     |  |o_|  |o_|  |             **
5 **           T h y s s e n           __|   __    __   |__           **
6 **                                __|   __|  |  |  |__   |__        **
7 **  `` Dragon Computing! ''    __|   __|     |  |     |__   |__     **
8 **                            |_____|        |__|        |_____|    **
9 **                                                                  **
10 \********************************************************************/
11 /*
12 ** IconLabel.c - IconLabel Widget   Display a Pixmap  with optional label
13 **
14 ** Author: Anthony Thyssen
15 **         Griffith University
16 **         anthony@cit.gu.edu.au
17 **
18 ** Date:   March 30, 1996
19 **
20 ** This Widget was created due to problems with using the original X
21 ** Consortium Label Widget for displaying Bitmap and Pixmap in my
22 ** XbmBrowser program.  I designed this widget to basically display a
23 ** pixmap and optionally a title or filename centered underneath this
24 ** image.
25 **
26 ** FEATURES
27 **    1/  Pixmap displayed correctly (a flag indicates to treat it as a bitmap)
28 **    2/  Shaped Windows using the bitmap mask given
29 **    3/  Optional Label centered either above or below the image
30 **    4/  Numerous inter-dimension controls for good user control
31 **
32 */
33 
34 #include <X11/IntrinsicP.h>
35 #include <X11/StringDefs.h>
36 #include "IconLabelP.h"          /* Private header file */
37 
38 /* shape extension stuff */
39 #include <X11/extensions/shape.h>
40 
41 #define streq(a,b) (strcmp( (a), (b) ) == 0)
42 
43 /*---------------------------------------------------------------------------*/
44 /*-------------------------- Subroutine Declaration -------------------------*/
45 
46 static void Initialize();
47 static void Realize();
48 static void Redisplay();
49 static void Resize();
50 static Boolean SetValues();
51 static void Destroy();
52 static XtGeometryResult QueryGeometry();
53 
54 /*---------------------------------------------------------------------------*/
55 /*-------------------------------- Resources --------------------------------*/
56 
57 #define offset(field) XtOffsetOf(IconLabelRec, icon_label.field)
58 static XtResource resources[] = {
59 /* miscellanous */
60     {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
61         offset(foreground), XtRString, XtDefaultForeground},
62     {XtNfont,  XtCFont, XtRFontStruct, sizeof(XFontStruct *),
63         offset(font),XtRString, XtDefaultFont},
64     {XtNshape, XtCShape, XtRBoolean, sizeof(Boolean),
65         offset(shape), XtRImmediate, (XtPointer)False},
66     {XtNresize, XtCResize, XtRBoolean, sizeof(Boolean),
67         offset(resize), XtRImmediate, (XtPointer)True},
68 /* pixmap stuff */
69     {XtNpixmap, XtCPixmap, XtRPixmap, sizeof(Pixmap),
70         offset(pixmap), XtRImmediate, (XtPointer)None},
71     {XtNmask, XtCMask, XtRBitmap, sizeof(Pixmap),
72         offset(mask), XtRImmediate, (XtPointer)None},
73     {XtNisBitmap, XtCIsBitmap, XtRBoolean, sizeof(Boolean),
74         offset(is_bitmap), XtRImmediate, (XtPointer)False},
75 /* label stuff */
76     {XtNlabel,  XtCLabel, XtRString, sizeof(String),
77         offset(label), XtRString, NULL},
78     {XtNlabelTop, XtCLabelTop, XtRBoolean, sizeof(Boolean),
79         offset(label_top), XtRImmediate, (XtPointer)False},
80 /* internal space */
81     {XtNinternalWidth, XtCWidth, XtRDimension,  sizeof(Dimension),
82         offset(internal_width), XtRImmediate, (XtPointer)2},
83     {XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension),
84         offset(internal_height), XtRImmediate, (XtPointer)1},
85     {XtNlabelGap, XtCHeight, XtRDimension, sizeof(Dimension),
86         offset(label_gap), XtRImmediate, (XtPointer)1},
87 /* extra information pointer */
88     {XtNinfoPtr, XtCInfoPtr, XtRPointer, sizeof(XtPointer),
89         offset(info_ptr), XtRImmediate, (XtPointer)NULL},
90 
91 };
92 #undef offset
93 
94 
95 /*---------------------------------------------------------------------------*/
96 /*---------------------- Class Structure Initialization ---------------------*/
97 
98 #define SuperClass ((WidgetClass)&simpleClassRec)
99 
100 IconLabelClassRec iconLabelClassRec = {
101   { /* CoreClass
102     **  S -  self contained,   C v  down chain (super->sub),
103     **  P    private Xt only,  C ^  up chained (sub->super),  ?  unknowen
104     */
105     SuperClass,                         /* superclass            C ^ (link) */
106     "IconLabel",                        /* class_name            P   (data) */
107     sizeof(IconLabelRec),               /* widget_size           P   (data) */
108     NULL,                               /* class_initialize      S - (exe)  */
109     NULL,                               /* class_part_initialize C v (exe)  */
110     FALSE,                              /* class_inited          P   (flag) */
111     Initialize,                         /* initialize            C v (exe)  */
112     NULL,                               /* initialize_hook       C v (exe)  */
113     Realize,                            /* realize               S - (exe)  */
114     NULL,                               /* actions               C ^ (srch) */
115     0,                                  /* num_actions           C ^ (srch) */
116     resources,                          /* resources             C v (comp) */
117     XtNumber(resources),                /* num_resources         C v (comp) */
118     NULLQUARK,                          /* xrm_class             P   (???)  */
119     TRUE,                               /* compress_motion       S   (flag) */
120     TRUE,                               /* compress_exposure     S   (flag) */
121     TRUE,                               /* compress_enterleave   S   (flag) */
122     FALSE,                              /* visible_interest      S   (flag) */
123     Destroy,                            /* destroy               C ^ (exe)  */
124     Resize,                             /* resize                S - (exe)  */
125     Redisplay,                          /* expose                S - (exe)  */
126     SetValues,                          /* set_values            C v (exe)  */
127     NULL,                               /* set_values_hook       C v (exe)  */
128     XtInheritSetValuesAlmost,           /* set_values_almost     S - (exe)  */
129     NULL,                               /* get_values_hook       C v (exe)  */
130     NULL,                               /* accept_focus          S - (exe)  */
131     XtVersion,                          /* version               S - (data) */
132     NULL,                               /* callback_private      P   (???)  */
133     NULL,                               /* tm_table              S - (data) */
134     QueryGeometry,                      /* query_geometry        S - (exe)  */
135     XtInheritDisplayAccelerator,        /* display_accelerator   ?   (data) */
136     NULL                                /* extension             S   (link) */
137   },
138   { /* SimpleClass */
139     XtInheritChangeSensitive            /* change_sensitive  */
140   },
141   { /* IconLabelClass */
142     0                                   /* field not used    */
143   }
144 };
145 
146 WidgetClass iconLabelWidgetClass = (WidgetClass)&iconLabelClassRec;
147 
148 /*---------------------------------------------------------------------------*/
149 /*---------------------------- Private Procedures ---------------------------*/
150 
151 static void
GetGCs(ilw)152 GetGCs(ilw)
153   IconLabelWidget ilw;
154 /* Create the required drawing GCs */
155 {
156   XGCValues     values;
157 
158   /* main drawing GC */
159   values.foreground = ilw->icon_label.foreground;
160   values.background = ilw->core.background_pixel;
161   values.font       = ilw->icon_label.font->fid;
162   values.graphics_exposures = False;
163 
164   ilw->icon_label.normal_GC = XtGetGC( (Widget)ilw,
165       (unsigned) GCForeground | GCBackground | GCFont | GCGraphicsExposures,
166       &values);
167 
168   /* grey insensitive GC -- and its stipple */
169   values.fill_style = FillTiled;
170   values.tile       = XmuCreateStippledPixmap( XtScreen((Widget)ilw),
171        ilw->icon_label.foreground, ilw->core.background_pixel, ilw->core.depth);
172 
173   ilw->icon_label.stipple = values.tile;
174   ilw->icon_label.gray_GC = XtGetGC( (Widget)ilw,
175        (unsigned) GCForeground | GCBackground | GCFont | GCTile |
176                   GCFillStyle | GCGraphicsExposures, &values);
177 }
178 
179 
180 static void
ReleaseGCs(ilw)181 ReleaseGCs(ilw)
182   IconLabelWidget ilw;
183 /* Release the required drawing GCs */
184 {
185   XtReleaseGC( (Widget)ilw, ilw->icon_label.normal_GC );
186   XtReleaseGC( (Widget)ilw, ilw->icon_label.gray_GC);
187   XmuReleaseStippledPixmap( XtScreen((Widget)ilw), ilw->icon_label.stipple );
188 }
189 
190 
191 static void
SetPixmapDimensions(ilw)192 SetPixmapDimensions(ilw)
193   IconLabelWidget ilw;
194 {
195   XRectangle  *rect = &ilw->icon_label.pm_rect;
196 
197   if (ilw->icon_label.pixmap != None) {
198     Window w;
199     int x, y;
200     unsigned int width, height, bw, depth;
201 
202     if (XGetGeometry(XtDisplay(ilw), ilw->icon_label.pixmap,
203                   &w, &x, &y, &width, &height, &bw, &depth)) {
204       rect->width  = (unsigned short) width;
205       rect->height = (unsigned short) height;
206       ilw->icon_label.pm_depth = depth;
207       return;
208     }
209   }
210 
211   /* failed -- no dimensions */
212   rect->width  = 0;
213   rect->height = 0;
214   ilw->icon_label.pm_depth = 0;
215 
216 }
217 
218 
219 static void
SetLabelDimensions(ilw)220 SetLabelDimensions(ilw)
221   IconLabelWidget ilw;
222 {
223   XRectangle  *rect = &ilw->icon_label.lb_rect;
224   XFontStruct *fs = ilw->icon_label.font;
225   char        *nl;
226 
227   rect->width  = 0;
228   rect->height = 0;
229   ilw->icon_label.label_len = 0;
230 
231   if( ilw->icon_label.label != NULL ) {
232     ilw->icon_label.label_len = strlen(ilw->icon_label.label);
233     rect->width = (unsigned short)
234          XTextWidth(fs, ilw->icon_label.label, (int) ilw->icon_label.label_len)
235          + 2 * ilw->icon_label.internal_width;
236     rect->height = (unsigned short)
237          fs->max_bounds.ascent + fs->max_bounds.descent + 1;
238   }
239 }
240 
241 
242 static Dimension
PreferredWidth(ilw)243 PreferredWidth(ilw)
244   IconLabelWidget ilw;
245 /* Figure out the prefered width of the widget */
246 {
247   IconLabelPart *ilwp = &ilw->icon_label;
248 
249   /* width of the parts -- No pixmap then its width is 0 */
250   Dimension p = ilwp->pm_rect.width + 2 * ilwp->internal_width;
251   Dimension l = ilwp->lb_rect.width;
252 
253   return ( ilwp->label != NULL && l>p ) ? l : p;
254 }
255 
256 
257 static Dimension
PreferredHeight(ilw)258 PreferredHeight(ilw)
259   IconLabelWidget ilw;
260 /* Figure out the prefered height of the widget */
261 {
262   IconLabelPart *ilwp = &ilw->icon_label;
263   Dimension h = ilwp->internal_height;
264 
265   /* NOTE: height is the same regardless of if label at top or
266   ** the bottom of widget. The comments pretend it is at bottom */
267 
268   if ( ilwp->label != NULL ) {
269     h += ilwp->lb_rect.height;   /* label present */
270     if ( ilwp->pm_depth > 0 )
271       h += ilwp->label_gap;      /* label & pixmap -- add gap space */
272   } else {
273     h += ilwp->internal_height;  /* no label internal space instead */
274   }
275   if ( ilwp->pm_depth > 0 )   /* pixmap present add it and top space */
276     h += ilwp->pm_rect.height;
277 
278   return h;
279 }
280 
281 
282 static void
SetWindowShape(ilw)283 SetWindowShape(ilw)
284   IconLabelWidget ilw;
285 /* set the shape masks for this widget */
286 {
287   IconLabelPart *ilwp = &ilw->icon_label;
288 
289   if ( !ilwp->shape ) {
290     if ( ilwp->shape_on ) {
291       ilwp->shape_on = False;  /* don't do this all the time */
292       /* turn off shaped window entirely */
293       XShapeCombineMask(XtDisplay((Widget)ilw), XtWindow((Widget)ilw),
294                ShapeBounding, 0, 0, (Pixmap)None, ShapeSet);
295     }
296   } else {
297     ilwp->shape_on = True;
298 
299     /* Set region appropriate for pixmap and mask */
300     if ( ilwp->pm_depth > 0 ) {
301       if ( ilwp->mask != None )
302         XShapeCombineMask(XtDisplay((Widget)ilw), XtWindow((Widget)ilw),
303                 ShapeBounding, (int)ilwp->pm_rect.x, (int)ilwp->pm_rect.y,
304                 ilwp->mask, ShapeSet );
305       else
306         XShapeCombineRectangles(XtDisplay((Widget)ilw), XtWindow((Widget)ilw),
307                 ShapeBounding, 0, 0, &ilwp->pm_rect, 1, ShapeSet, Unsorted );
308     }
309     else /* no pixmap found */
310       XShapeCombineRectangles( XtDisplay((Widget)ilw), XtWindow((Widget)ilw),
311                 ShapeBounding, 0, 0, &ilwp->pm_rect, 0, ShapeSet, Unsorted );
312 
313     /* Add a label region if needed */
314     if ( ilwp->label != NULL ) {
315       XShapeCombineRectangles(XtDisplay((Widget)ilw), XtWindow((Widget)ilw),
316                 ShapeBounding, 0, 0, &ilwp->lb_rect, 1, ShapeUnion, Unsorted );
317     }
318   }
319 }
320 
321 static void
PositionParts(ilw,width,height)322 PositionParts(ilw, width, height)
323   IconLabelWidget ilw;
324   Dimension width, height;
325 /* position the parts in the current window size */
326 {
327   IconLabelPart *ilwp = &ilw->icon_label;
328 
329   /* X positions are easy */
330   ilwp->pm_rect.x = (width - ilwp->pm_rect.width) / 2;
331   ilwp->lb_rect.x = (width - ilwp->lb_rect.width) / 2;
332   if( ilwp->lb_rect.x < 0 ) ilwp->lb_rect.x = 0;
333 
334   /* Y positions depends on label -- This is halved later. */
335   ilwp->pm_rect.y = height - ilwp->pm_rect.height - ilwp->internal_height;
336 
337   if( ilwp->label == NULL ) {              /* No label */
338     ilwp->pm_rect.y += ilwp->internal_height; /* +ve -- work it out! */
339     ilwp->pm_rect.y /= 2; /* now halve it */
340   } else {                                 /* Label present */
341     ilwp->pm_rect.y -=  ilwp->lb_rect.height + ilwp->label_gap;
342     ilwp->pm_rect.y /= 2; /* now halve it */
343 
344     if( ilwp->label_top ) {               /* Label is at top */
345       ilwp->lb_rect.y = 0;
346       ilwp->pm_rect.y += ilwp->lb_rect.height + ilwp->label_gap;
347     } else {                              /* Label is at bottom */
348       ilwp->lb_rect.y = height - ilwp->lb_rect.height;
349       ilwp->pm_rect.y += ilwp->internal_height;
350     }
351   }
352 
353   if (XtIsRealized((Widget)ilw))
354     SetWindowShape(ilw);
355 }
356 
357 /*---------------------------------------------------------------------------*/
358 /*------------------------------ Widget Methods -----------------------------*/
359 
360 #if 0  /* not required */
361 static void
362 ClassInitialize()
363 /* Class Initialization (Self Contained)
364 ** Install type converters
365 */
366 {
367 }
368 #endif
369 
370 
371 /* ARGSUSED */
372 static void
Initialize(req,new,args,num_args)373 Initialize(req, new, args, num_args)
374   Widget   req;      /* widget user originally requested */
375   Widget   new;      /* widget modified by superclases */
376   ArgList  args;     /* resource list from Creation call */
377   Cardinal num_args;
378 /* Initialize this widget (Chained Downward : Super -> Sub)
379 ** Insure all public and private variables are reasonable.
380 */
381 {
382   IconLabelWidget  ilw = (IconLabelWidget)new;
383   int x;  /* junk variable */
384 
385   if( ilw->icon_label.label != NULL )   /* make our own copy */
386     ilw->icon_label.label = XtNewString(ilw->icon_label.label);
387 
388   ilw->icon_label.shape_on = False;
389   if ( ilw->icon_label.shape && !XShapeQueryExtension(XtDisplay(new),&x,&x) )
390     ilw->icon_label.shape = False;
391 
392   GetGCs(ilw);
393   SetPixmapDimensions(ilw);
394   SetLabelDimensions(ilw);
395 
396   /* set prefered size if not already set */
397   if (ilw->core.width == 0)
398     ilw->core.width = PreferredWidth(ilw);
399   if (ilw->core.height == 0)
400     ilw->core.height = PreferredHeight(ilw);
401 
402   /* call that widgets resize routine */
403   (XtClass(new)->core_class.resize)(new);
404 }
405 
406 
407 static void
Realize(w,valueMask,attributes)408 Realize(w, valueMask, attributes)
409   Widget w;                /* reliase the widget now */
410   XtValueMask *valueMask;
411   XSetWindowAttributes *attributes;
412 /* Reliase this Widget (Self Contained)
413 ** set window attributes, and create the window
414 ** and set the windows shape
415 */
416 {
417   /* Call the Realise of the superclass to create the window */
418   (SuperClass->core_class.realize)(w, valueMask, attributes);
419 
420   /* Now set the Shape Extension Stuff */
421   SetWindowShape( (IconLabelWidget)w );
422 }
423 
424 
425 /* ARGSUSED */
426 static void
Redisplay(w,event,region)427 Redisplay(w, event, region)
428   Widget w;        /* widget to be (re)drawen */
429   XEvent *event;   /* event which caused the redraw */
430   Region region;   /* region to be drawn */
431 /* Redraw the Exposed Parts (Self Contained)
432 ** part of the widget is now visible to the user so
433 ** draw the parts required or all of it
434 */
435 {
436   IconLabelPart *ilwp = &((IconLabelWidget)w)->icon_label;
437   GC  gc = XtIsSensitive(w) ? ilwp->normal_GC : ilwp->gray_GC;
438 
439 #ifdef notdef
440   if (region != NULL)
441     XSetRegion(XtDisplay(w), gc, region);
442 #endif /*notdef*/
443 
444   /* --- label draw --- */
445   /* this is done first so that pixmap can overwrite it if
446   ** the widget is too small, and they overlap */
447   if ( ilwp->label != NULL ) {   /* is label available? */
448     XDrawString(XtDisplay(w), XtWindow(w), gc,
449              (int)ilwp->lb_rect.x + ilwp->internal_width,
450              (int)ilwp->lb_rect.y + ilwp->font->max_bounds.ascent,
451              (char *)ilwp->label,  ilwp->label_len);
452   }
453 
454   /* --- pixmap draw --- */
455   if ( ilwp->pm_depth > 0 ) {  /* is a pixmap provided? */
456     if ( ilwp->is_bitmap && ilwp->pm_depth == 1 ) { /* is it a bitmap */
457       XCopyPlane(XtDisplay(w), ilwp->pixmap, XtWindow(w), gc,
458                   0, 0, (int)ilwp->pm_rect.width, (int)ilwp->pm_rect.height,
459                   (int)ilwp->pm_rect.x, (int)ilwp->pm_rect.y, 1L );
460     } else {
461       XCopyArea(XtDisplay(w), ilwp->pixmap, XtWindow(w), gc,
462                   0, 0, (int)ilwp->pm_rect.width, (int)ilwp->pm_rect.height,
463                   (int)ilwp->pm_rect.x, (int)ilwp->pm_rect.y );
464     }
465     if( ilwp->mask != None && ! ilwp->shape ) {  /* mask but no shape? */
466       ; /* paint the mask in the background color! */
467     }
468   }
469 
470 #ifdef notdef
471   if (region != NULL)
472     XSetClipMask(XtDisplay(w), gc, (Pixmap)None);
473 #endif /* notdef */
474 }
475 
476 
477 static void
Resize(w)478 Resize(w)
479   Widget w;   /* widget to be resized */
480 /* Resize and Position Internals (Self Contained)
481 ** recalculate internals based on new window position and size
482 */
483 {
484   PositionParts( (IconLabelWidget)w, w->core.width, w->core.height );
485 }
486 
487 
488 /* user_requests found */
489 #define PIXMAP     0
490 #define MASK       1
491 #define WIDTH      2
492 #define HEIGHT     3
493 #define NUM_CHECKS 4
494 
495 /* ARGSUSED */
496 static Boolean
SetValues(cur,req,new,args,num_args)497 SetValues(cur, req, new, args, num_args)
498   Widget cur;     /* original before change resources */
499   Widget req;     /* user requested changes to resources */
500   Widget new;     /* resources modified by superclasses (modify this) */
501   ArgList  args;  /* resource list from Creation call */
502   Cardinal *num_args;
503 /* Set Public Variables (Chained Downward : Super -> Sub)
504 ** Change the public variables and do whatever is needed
505 ** to affect the changes ask for by the user
506 */
507 {
508   IconLabelPart *ilwp_cur = &((IconLabelWidget)cur)->icon_label;
509   IconLabelPart *ilwp_req = &((IconLabelWidget)req)->icon_label;
510   IconLabelPart *ilwp_new = &((IconLabelWidget)new)->icon_label;
511 
512   Boolean was_resized = False;
513   Boolean redisplay = False;
514   Boolean user_reqs[NUM_CHECKS];
515   int i;
516 
517   /* Check the user set value requests for specific things */
518   for (i = 0; i < NUM_CHECKS; i++)
519     user_reqs[i] = FALSE;
520   for (i = 0; i < *num_args; i++) {
521     if (streq(XtNpixmap, args[i].name))
522       user_reqs[PIXMAP] = TRUE;
523     if (streq(XtNmask, args[i].name))
524       user_reqs[MASK] = TRUE;
525     if (streq(XtNwidth, args[i].name))
526       user_reqs[WIDTH] = TRUE;
527     if (streq(XtNheight, args[i].name))
528       user_reqs[HEIGHT] = TRUE;
529   }
530 
531   /* Label changed? */
532   if ( ilwp_cur->label != ilwp_new->label ) {
533     XtFree( (char *)ilwp_cur->label );   /* free the old label (if present) */
534 
535     if ( ilwp_new->label != NULL ) {
536       ilwp_new->label = XtNewString( ilwp_new->label ); /* allocate new */
537     }
538     was_resized = True;
539   }
540 
541   /* change position of label? */
542   if ( was_resized || ilwp_cur->font != ilwp_new->font ) {
543     SetLabelDimensions((IconLabelWidget)new);
544     was_resized = True;
545   }
546 
547   /* Did the pixmap change?
548   ** Originally any pixmap change means redisplay -- don't do this
549   ** maybe I should add a option which resets to false called
550   ** redisplay -- IE: if true reset to false and re-display pixmap
551   ** if ( user_reqs[PIXMAP] ) {  <=== Original If statment */
552   if ( ilwp_cur->pixmap != ilwp_new->pixmap ) {
553     SetPixmapDimensions((IconLabelWidget)new);
554     was_resized = True;
555     redisplay = True;
556   }
557 
558   /* Set prefered width and height  IF
559   **   resize is allowed and any sub-class or the user doesn't set it */
560   if ( ilwp_new->resize && was_resized ) {
561     if ( cur->core.height == req->core.height && !user_reqs[HEIGHT] )
562       new->core.height = PreferredHeight((IconLabelWidget)new);
563     if ( cur->core.width == req->core.width   && !user_reqs[WIDTH] )
564       new->core.width = PreferredWidth((IconLabelWidget)new);
565   }
566 
567   /* don't turn on shape ext if no shape ext is available */
568   if ( !ilwp_cur->shape && ilwp_new->shape &&
569                   !XShapeQueryExtension(XtDisplay(new),&i,&i) ) {
570     ilwp_new->shape = False;
571   }
572 
573   /* Drawing GCs changed? */
574   if (    ilwp_cur->foreground       != ilwp_new->foreground
575        || cur->core.background_pixel != new->core.background_pixel
576        || ilwp_cur->font->fid        != ilwp_new->font->fid  ) {
577     ReleaseGCs((IconLabelWidget)new);
578     GetGCs((IconLabelWidget)new);
579     redisplay = True;
580   }
581 
582   /* Do we need to reposition parts */
583   if (    ilwp_cur->internal_width  != ilwp_new->internal_width
584        || ilwp_cur->internal_height != ilwp_new->internal_height
585        || ilwp_cur->label_gap       != ilwp_new->label_gap
586        || was_resized ) {
587     /* Resize() will be called if geometry changes succeed
588     ** So just resize against the current widget size for now */
589     PositionParts((IconLabelWidget)new, cur->core.width, cur->core.height);
590     redisplay = True;
591   }
592   else
593   /* Do we just need to adjust the shape extension? */
594   if (    ilwp_cur->mask  != ilwp_new->mask  /* || user_reqs[MASK] */
595        || ilwp_cur->shape != ilwp_new->shape ) {
596     if (XtIsRealized(new))
597       SetWindowShape((IconLabelWidget)new);
598     /* redisplay = True; -- we don't need to redisplay for shape change */
599   }
600   else
601   /* Just need to redraw everything? */
602   if (    XtIsSensitive(cur)  != XtIsSensitive(new)
603        || ilwp_cur->is_bitmap != ilwp_new->is_bitmap ) {
604     redisplay = True;
605   }
606 
607   return  redisplay;  /* this includes was_resized */
608 }
609 
610 
611 static XtGeometryResult
QueryGeometry(w,intended,preferred)612 QueryGeometry(w, intended, preferred)
613   Widget w;                    /* widget for geometry request */
614   XtWidgetGeometry *intended;  /* what is being requested */
615   XtWidgetGeometry *preferred; /* what we would prefer to be */
616 /* Propose a new Size for Widget (Self Contained)
617 ** Ask the widget what it things of a particular size
618 ** and what it would prefer to be.
619 */
620 {
621   preferred->request_mode = CWWidth | CWHeight;
622   preferred->height = PreferredHeight( (IconLabelWidget)w );
623   preferred->width = PreferredWidth( (IconLabelWidget)w );
624 
625   if ( (intended->request_mode & (CWWidth|CWHeight)) == (CWWidth|CWHeight)
626         && intended->width == preferred->width
627         && intended->height == preferred->height)
628     return XtGeometryYes;
629   else if ( preferred->width == w->core.width &&
630             preferred->height == w->core.height)
631     return XtGeometryNo;  /* I don't know why but what the hey */
632   else
633     return XtGeometryAlmost;
634 }
635 
636 
637 static void
Destroy(w)638 Destroy(w)
639   Widget w; /* widget that is being destroyed */
640 /* Destroy our widget stuff (Chained Upward : Sub -> Super)
641 ** Destroy and de-allocate anything we allocated for
642 ** use within this widget.
643 */
644 {
645   IconLabelWidget ilw = (IconLabelWidget)w;
646 
647   XtFree( ilw->icon_label.label ); /* free our label name (if present) */
648   ReleaseGCs( (IconLabelWidget)w );
649 }
650 
651 /* ------------------------------------------------------------------------- */
652 /* ------------------------- Public Functions ------------------------------ */
653 
SetInfoPtr(w,info_ptr)654 void SetInfoPtr(w, info_ptr)
655   Widget    w;
656   XtPointer info_ptr;
657 /* Set the pointer to extra information provided.
658 ** This information is can then be looked up fast as and when
659 ** required by the program in response to user actions
660 ** without needing to adjust any callback we don't provide
661 */
662 {
663   ((IconLabelWidget)w)->icon_label.info_ptr = info_ptr;
664 }
665 
GetInfoPtr(w)666 XPointer GetInfoPtr(w)
667   Widget    w;
668 /* Get the pointer to extra information provided. */
669 {
670   return ((IconLabelWidget)w)->icon_label.info_ptr;
671 }
672 
673 /* ------------------------------------------------------------------------- */
674