Label.c revision 421c997b
1/***********************************************************
2
3Copyright 1987, 1988, 1994, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25
26Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
27
28                        All Rights Reserved
29
30Permission to use, copy, modify, and distribute this software and its
31documentation for any purpose and without fee is hereby granted,
32provided that the above copyright notice appear in all copies and that
33both that copyright notice and this permission notice appear in
34supporting documentation, and that the name of Digital not be
35used in advertising or publicity pertaining to distribution of the
36software without specific, written prior permission.
37
38DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44SOFTWARE.
45
46******************************************************************/
47
48#ifdef HAVE_CONFIG_H
49#include <config.h>
50#endif
51#include <stdio.h>
52#include <ctype.h>
53#include <X11/IntrinsicP.h>
54#include <X11/StringDefs.h>
55#include <X11/Xos.h>
56#include <X11/Xmu/Converters.h>
57#include <X11/Xmu/Drawing.h>
58#include <X11/Xaw/LabelP.h>
59#include <X11/Xaw/XawInit.h>
60#include "Private.h"
61
62#define streq(a, b)		(strcmp((a), (b)) == 0)
63
64#define MULTI_LINE_LABEL 32767
65
66#ifdef CRAY
67#define WORD64
68#endif
69
70/*
71 * Class Methods
72 */
73static void XawLabelClassInitialize(void);
74static void XawLabelDestroy(Widget);
75static void XawLabelInitialize(Widget, Widget, ArgList, Cardinal*);
76static XtGeometryResult XawLabelQueryGeometry(Widget, XtWidgetGeometry*,
77					      XtWidgetGeometry*);
78static void XawLabelRedisplay(Widget, XEvent*, Region);
79static void XawLabelResize(Widget);
80static Boolean XawLabelSetValues(Widget, Widget, Widget,
81				 ArgList, Cardinal*);
82
83/*
84 * Prototypes
85 */
86#ifdef WORD64
87static int _XawLabelWidth16(XFontStruct*, char*, int);
88static void _XawLabelDraw16(Display*, Drawable, GC, int, int, char*, int);
89#endif
90static void compute_bitmap_offsets(LabelWidget);
91static void GetGrayGC(LabelWidget);
92static void GetNormalGC(LabelWidget);
93static void _Reposition(LabelWidget, unsigned int, unsigned int,
94			Position*, Position*);
95static void set_bitmap_info(LabelWidget);
96static void SetTextWidthAndHeight(LabelWidget);
97
98/*
99 * Initialization
100 */
101#define offset(field) XtOffsetOf(LabelRec, field)
102static XtResource resources[] = {
103  {
104    XtNforeground,
105    XtCForeground,
106    XtRPixel,
107    sizeof(Pixel),
108    offset(label.foreground),
109    XtRString,
110    XtDefaultForeground
111  },
112  {
113    XtNfont,
114    XtCFont,
115    XtRFontStruct,
116    sizeof(XFontStruct*),
117    offset(label.font),
118    XtRString,
119    XtDefaultFont
120  },
121  {
122    XtNfontSet,
123    XtCFontSet,
124    XtRFontSet,
125    sizeof(XFontSet),
126    offset(label.fontset),
127    XtRString,
128    XtDefaultFontSet
129  },
130  {
131    XtNlabel,
132    XtCLabel,
133    XtRString,
134    sizeof(String),
135    offset(label.label),
136    XtRString,
137    NULL
138  },
139  {
140    XtNencoding,
141    XtCEncoding,
142    XtRUnsignedChar,
143    sizeof(unsigned char),
144    offset(label.encoding),
145    XtRImmediate,
146    (XtPointer)XawTextEncoding8bit
147  },
148  {
149    XtNjustify,
150    XtCJustify,
151    XtRJustify,
152    sizeof(XtJustify),
153    offset(label.justify),
154    XtRImmediate,
155    (XtPointer)XtJustifyCenter
156  },
157  {
158    XtNinternalWidth,
159    XtCWidth,
160    XtRDimension,
161    sizeof(Dimension),
162    offset(label.internal_width),
163    XtRImmediate,
164    (XtPointer)4
165  },
166  {
167    XtNinternalHeight,
168    XtCHeight,
169    XtRDimension,
170    sizeof(Dimension),
171    offset(label.internal_height),
172    XtRImmediate,
173    (XtPointer)2
174  },
175  {
176    XtNleftBitmap,
177    XtCLeftBitmap,
178    XtRBitmap,
179    sizeof(Pixmap),
180    offset(label.left_bitmap),
181    XtRImmediate,
182    (XtPointer)None
183  },
184  {
185    XtNbitmap,
186    XtCPixmap,
187    XtRBitmap,
188    sizeof(Pixmap),
189    offset(label.pixmap),
190    XtRImmediate,
191    (XtPointer)None
192  },
193  {
194    XtNresize,
195    XtCResize,
196    XtRBoolean,
197    sizeof(Boolean),
198    offset(label.resize),
199    XtRImmediate,
200    (XtPointer)True
201  },
202  {
203    XtNlabelX,
204    XtCPosition,
205    XtRPosition,
206    sizeof(Position),
207    offset(label.label_x),
208    XtRImmediate,
209    (XtPointer)0
210  },
211  {
212    XtNlabelY,
213    XtCPosition,
214    XtRPosition,
215    sizeof(Position),
216    offset(label.label_y),
217    XtRImmediate,
218    (XtPointer)0
219  },
220};
221#undef offset
222
223#define Superclass (&simpleClassRec)
224LabelClassRec labelClassRec = {
225  /* core */
226  {
227    (WidgetClass)&simpleClassRec,	/* superclass */
228    "Label",				/* class_name */
229    sizeof(LabelRec),			/* widget_size */
230    XawLabelClassInitialize,		/* class_initialize */
231    NULL,				/* class_part_initialize */
232    False,				/* class_inited */
233    XawLabelInitialize,			/* initialize */
234    NULL,				/* initialize_hook */
235    XtInheritRealize,			/* realize */
236    NULL,				/* actions */
237    0,					/* num_actions */
238    resources,				/* resources */
239    XtNumber(resources),		/* num_resources */
240    NULLQUARK,				/* xrm_class */
241    True,				/* compress_motion */
242    True,				/* compress_exposure */
243    True,				/* compress_enterleave */
244    False,				/* visible_interest */
245    XawLabelDestroy,			/* destroy */
246    XawLabelResize,			/* resize */
247    XawLabelRedisplay,			/* expose */
248    XawLabelSetValues,			/* set_values */
249    NULL,				/* set_values_hook */
250    XtInheritSetValuesAlmost,		/* set_values_almost */
251    NULL,				/* get_values_hook */
252    NULL,				/* accept_focus */
253    XtVersion,				/* version */
254    NULL,				/* callback_private */
255    NULL,				/* tm_table */
256    XawLabelQueryGeometry,		/* query_geometry */
257    XtInheritDisplayAccelerator,	/* display_accelerator */
258    NULL,				/* extension */
259  },
260  /* simple */
261  {
262    XtInheritChangeSensitive,		/* change_sensitive */
263  },
264  /* label */
265  {
266    NULL,				/* extension */
267  }
268};
269
270WidgetClass labelWidgetClass = (WidgetClass)&labelClassRec;
271
272/*
273 * Implementation
274 */
275static void
276XawLabelClassInitialize(void)
277{
278    XawInitializeWidgetSet();
279    XtAddConverter(XtRString, XtRJustify, XmuCvtStringToJustify, NULL, 0);
280    XtSetTypeConverter(XtRJustify, XtRString, XmuCvtJustifyToString,
281		       NULL, 0, XtCacheNone, NULL);
282}
283
284#ifndef WORD64
285#define TXT16 XChar2b
286#else
287#define TXT16 char
288
289static XChar2b *buf2b;
290static int buf2blen = 0;
291
292static int
293_XawLabelWidth16(XFontStruct *fs, char *str, int n)
294{
295    int i;
296    XChar2b *ptr;
297
298    if (n > buf2blen) {
299	buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b));
300	buf2blen = n;
301    }
302    for (ptr = buf2b, i = n; --i >= 0; ptr++) {
303	ptr->byte1 = *str++;
304	ptr->byte2 = *str++;
305    }
306
307    return (XTextWidth16(fs, buf2b, n));
308}
309
310static void
311_XawLabelDraw16(Display *dpy, Drawable d, GC gc, int x, int y,
312		char *str, int n)
313{
314    int i;
315    XChar2b *ptr;
316
317    if (n > buf2blen) {
318	buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b));
319	buf2blen = n;
320    }
321    for (ptr = buf2b, i = n; --i >= 0; ptr++) {
322	ptr->byte1 = *str++;
323	ptr->byte2 = *str++;
324    }
325    XDrawString16(dpy, d, gc, x, y, buf2b, n);
326}
327
328#define XTextWidth16 _XawLabelWidth16
329#define XDrawString16 _XawLabelDraw16
330#endif /* WORD64 */
331
332/*
333 * Calculate width and height of displayed text in pixels
334 */
335static void
336SetTextWidthAndHeight(LabelWidget lw)
337{
338    XFontStruct	*fs = lw->label.font;
339    char *nl;
340
341    if (lw->label.pixmap != None) {
342	Window root;
343	int x, y;
344	unsigned int width, height, bw, depth;
345
346	if (XGetGeometry(XtDisplay(lw), lw->label.pixmap, &root, &x, &y,
347		       &width, &height, &bw, &depth)) {
348	    lw->label.label_height = height;
349	    lw->label.label_width = width;
350	    lw->label.label_len = depth;
351	    return;
352	}
353    }
354    if (lw->simple.international == True) {
355	XFontSet	fset = lw->label.fontset;
356	XFontSetExtents *ext = XExtentsOfFontSet(fset);
357
358	lw->label.label_height = ext->max_ink_extent.height;
359	if (lw->label.label == NULL) {
360	    lw->label.label_len = 0;
361	    lw->label.label_width = 0;
362	}
363	else if ((nl = index(lw->label.label, '\n')) != NULL) {
364	    char *label;
365
366	    lw->label.label_len = MULTI_LINE_LABEL;
367	    lw->label.label_width = 0;
368	    for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) {
369		int width = XmbTextEscapement(fset, label, (int)(nl - label));
370
371		if (width > (int)lw->label.label_width)
372		    lw->label.label_width = width;
373		label = nl + 1;
374		if (*label)
375		    lw->label.label_height += ext->max_ink_extent.height;
376	    }
377	    if (*label) {
378		int width = XmbTextEscapement(fset, label, strlen(label));
379
380		if (width > (int)lw->label.label_width)
381		    lw->label.label_width = width;
382	    }
383	}
384	else {
385	    lw->label.label_len = strlen(lw->label.label);
386	    lw->label.label_width =
387		XmbTextEscapement(fset, lw->label.label, lw->label.label_len);
388	}
389    }
390    else {
391	lw->label.label_height = fs->max_bounds.ascent + fs->max_bounds.descent;
392	if (lw->label.label == NULL) {
393	    lw->label.label_len = 0;
394	    lw->label.label_width = 0;
395	}
396	else if ((nl = index(lw->label.label, '\n')) != NULL) {
397	    char *label;
398
399	    lw->label.label_len = MULTI_LINE_LABEL;
400	    lw->label.label_width = 0;
401	    for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) {
402		int width;
403
404		if (lw->label.encoding)
405		    width = XTextWidth16(fs, (TXT16*)label, (int)(nl - label) / 2);
406		else
407		    width = XTextWidth(fs, label, (int)(nl - label));
408		if (width > (int)lw->label.label_width)
409		    lw->label.label_width = width;
410		label = nl + 1;
411		if (*label)
412		    lw->label.label_height +=
413			fs->max_bounds.ascent + fs->max_bounds.descent;
414	    }
415	    if (*label) {
416		int width = XTextWidth(fs, label, strlen(label));
417
418		if (lw->label.encoding)
419		    width = XTextWidth16(fs, (TXT16*)label, strlen(label) / 2);
420		else
421		    width = XTextWidth(fs, label, strlen(label));
422		if (width > (int) lw->label.label_width)
423		    lw->label.label_width = width;
424	    }
425	}
426	else {
427	    lw->label.label_len = strlen(lw->label.label);
428	    if (lw->label.encoding)
429		lw->label.label_width =
430		    XTextWidth16(fs, (TXT16*)lw->label.label,
431			   (int)lw->label.label_len / 2);
432	    else
433		lw->label.label_width =
434	      XTextWidth(fs, lw->label.label, (int)lw->label.label_len);
435	}
436    }
437}
438
439static void
440GetNormalGC(LabelWidget lw)
441{
442    XGCValues	values;
443
444    values.foreground	= lw->label.foreground;
445    values.background	= lw->core.background_pixel;
446    values.font		= lw->label.font->fid;
447    values.graphics_exposures = False;
448
449    if (lw->simple.international == True)
450    /* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC */
451	lw->label.normal_GC = XtAllocateGC((Widget)lw, 0,
452					   GCForeground | GCBackground |
453					   GCGraphicsExposures,
454					   &values, GCFont, 0);
455    else
456	lw->label.normal_GC = XtGetGC((Widget)lw,
457				      GCForeground | GCBackground | GCFont |
458				      GCGraphicsExposures, &values);
459}
460
461static void
462GetGrayGC(LabelWidget lw)
463{
464    XGCValues	values;
465
466    values.foreground = lw->label.foreground;
467    values.background = lw->core.background_pixel;
468    values.font	      = lw->label.font->fid;
469    values.fill_style = FillTiled;
470    values.tile       = XmuCreateStippledPixmap(XtScreen((Widget)lw),
471						lw->label.foreground,
472						lw->core.background_pixel,
473						lw->core.depth);
474    values.graphics_exposures = False;
475
476    lw->label.stipple = values.tile;
477    if (lw->simple.international == True)
478	/* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC */
479	lw->label.gray_GC = XtAllocateGC((Widget)lw, 0,
480					 GCForeground | GCBackground |
481					 GCTile | GCFillStyle |
482					 GCGraphicsExposures,
483					 &values, GCFont, 0);
484	else
485	    lw->label.gray_GC = XtGetGC((Widget)lw,
486					GCForeground | GCBackground |
487					GCFont | GCTile | GCFillStyle |
488					GCGraphicsExposures,
489					&values);
490}
491
492static void
493compute_bitmap_offsets(LabelWidget lw)
494{
495    /*
496     * bitmap will be eventually be displayed at
497     * (internal_width, internal_height + lbm_y)
498     */
499    if (lw->label.lbm_height != 0)
500	lw->label.lbm_y = (XtHeight(lw) - (lw->label.internal_height * 2 +
501			   lw->label.lbm_height)) / 2;
502    else
503	lw->label.lbm_y = 0;
504}
505
506static void
507set_bitmap_info(LabelWidget lw)
508{
509    Window root;
510    int x, y;
511    unsigned int bw, depth;
512
513    if (!(lw->label.left_bitmap
514	&& XGetGeometry(XtDisplay(lw), lw->label.left_bitmap, &root, &x, &y,
515			&lw->label.lbm_width, &lw->label.lbm_height,
516			&bw, &depth)))
517	lw->label.lbm_width = lw->label.lbm_height = 0;
518
519    compute_bitmap_offsets(lw);
520}
521
522/*ARGSUSED*/
523static void
524XawLabelInitialize(Widget request, Widget cnew,
525		   ArgList args, Cardinal *num_args)
526{
527    LabelWidget lw = (LabelWidget)cnew;
528
529    if (!lw->label.font) XtError("Aborting: no font found\n");
530    if (lw->simple.international && !lw->label.fontset)
531	XtError("Aborting: no fontset found\n");
532
533    if (lw->label.label == NULL)
534	lw->label.label = XtNewString(lw->core.name);
535    else
536	lw->label.label = XtNewString(lw->label.label);
537
538    GetNormalGC(lw);
539    GetGrayGC(lw);
540
541    SetTextWidthAndHeight(lw);
542
543    if (XtHeight(lw) == 0)
544	XtHeight(lw) = lw->label.label_height + 2 * lw->label.internal_height;
545
546    set_bitmap_info(lw);		/* need core.height */
547
548    if (XtWidth(lw) == 0)		/* need label.lbm_width */
549	XtWidth(lw) = lw->label.label_width + 2 * lw->label.internal_width +
550		      LEFT_OFFSET(lw);
551
552    lw->label.label_x = lw->label.label_y = 0;
553    (*XtClass(cnew)->core_class.resize)((Widget)lw);
554}
555
556/*ARGSUSED*/
557static void
558XawLabelRedisplay(Widget gw, XEvent *event, Region region)
559{
560    LabelWidget w = (LabelWidget)gw;
561    GC gc;
562
563    if (*Superclass->core_class.expose != NULL)
564	(*Superclass->core_class.expose)(gw, event, region);
565
566    gc = XtIsSensitive(gw) ? w->label.normal_GC : w->label.gray_GC;
567#ifdef notdef
568    if (region != NULL)
569	XSetRegion(XtDisplay(gw), gc, region);
570#endif /*notdef*/
571
572    if (w->label.pixmap == None) {
573	int len = w->label.label_len;
574	char *label = w->label.label;
575	Position y = w->label.label_y + w->label.font->max_bounds.ascent;
576	Position ksy = w->label.label_y;
577
578	/* display left bitmap */
579	if (w->label.left_bitmap && w->label.lbm_width != 0)
580	    XCopyPlane (XtDisplay(gw), w->label.left_bitmap, XtWindow(gw), gc,
581			0, 0, w->label.lbm_width, w->label.lbm_height,
582			w->label.internal_width,
583			w->label.internal_height + w->label.lbm_y, 1L);
584
585	if (w->simple.international == True) {
586	    XFontSetExtents *ext = XExtentsOfFontSet(w->label.fontset);
587
588	    ksy += XawAbs(ext->max_ink_extent.y);
589
590	    if (len == MULTI_LINE_LABEL) {
591		char *nl;
592
593		while ((nl = index(label, '\n')) != NULL) {
594		    XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset,
595				  gc, w->label.label_x, ksy, label,
596				  (int)(nl - label));
597		    ksy += ext->max_ink_extent.height;
598		    label = nl + 1;
599		}
600		len = strlen(label);
601	    }
602	    if (len)
603		XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, gc,
604			      w->label.label_x, ksy, label, len);
605	}
606	else {
607	    if (len == MULTI_LINE_LABEL) {
608		char *nl;
609
610		while ((nl = index(label, '\n')) != NULL) {
611		    if (w->label.encoding)
612			XDrawString16(XtDisplay(gw), XtWindow(gw), gc,
613				      w->label.label_x, y,
614				      (TXT16*)label, (int)(nl - label) / 2);
615		    else
616			XDrawString(XtDisplay(gw), XtWindow(gw), gc,
617				    w->label.label_x, y, label, (int)(nl - label));
618		    y += w->label.font->max_bounds.ascent +
619			 w->label.font->max_bounds.descent;
620		    label = nl + 1;
621		}
622		len = strlen(label);
623	    }
624	    if (len) {
625		if (w->label.encoding)
626		    XDrawString16(XtDisplay(gw), XtWindow(gw), gc,
627				  w->label.label_x, y, (TXT16*)label, len / 2);
628		else
629		    XDrawString(XtDisplay(gw), XtWindow(gw), gc,
630				w->label.label_x, y, label, len);
631	    }
632	}
633    }
634    else if (w->label.label_len == 1)
635	XCopyPlane(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc,
636		   0, 0, w->label.label_width, w->label.label_height,
637		   w->label.label_x, w->label.label_y, 1L);
638    else
639	XCopyArea(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc,
640		  0, 0, w->label.label_width, w->label.label_height,
641		  w->label.label_x, w->label.label_y);
642
643#ifdef notdef
644    if (region != NULL)
645	XSetClipMask(XtDisplay(gw), gc, (Pixmap)None);
646#endif /* notdef */
647}
648
649static void
650_Reposition(LabelWidget lw, unsigned int width, unsigned int height,
651	    Position *dx, Position *dy)
652{
653    Position newPos;
654    Position leftedge = lw->label.internal_width + LEFT_OFFSET(lw);
655
656    switch (lw->label.justify) {
657	case XtJustifyLeft:
658	    newPos = leftedge;
659	    break;
660	case XtJustifyRight:
661	    newPos = width - (lw->label.label_width + lw->label.internal_width);
662	    break;
663	case XtJustifyCenter:
664        /*FALLTRHOUGH*/
665	default:
666	    newPos = (int)(width - lw->label.label_width) >> 1;
667	    break;
668    }
669    if (newPos < (Position)leftedge)
670	newPos = leftedge;
671    *dx = newPos - lw->label.label_x;
672    lw->label.label_x = newPos;
673
674    newPos = (height - lw->label.label_height) >> 1;
675    *dy = newPos - lw->label.label_y;
676    lw->label.label_y = newPos;
677}
678
679static void
680XawLabelResize(Widget w)
681{
682    LabelWidget lw = (LabelWidget)w;
683    Position dx, dy;
684
685    _Reposition(lw, XtWidth(w), XtHeight(w), &dx, &dy);
686    compute_bitmap_offsets(lw);
687}
688
689#define PIXMAP 0
690#define WIDTH 1
691#define HEIGHT 2
692#define NUM_CHECKS 3
693static Boolean
694XawLabelSetValues(Widget current, Widget request, Widget cnew,
695		  ArgList args, Cardinal *num_args)
696{
697    LabelWidget curlw = (LabelWidget)current;
698    LabelWidget reqlw = (LabelWidget)request;
699    LabelWidget newlw = (LabelWidget)cnew;
700    unsigned int i;
701    Boolean was_resized = False, redisplay = False, checks[NUM_CHECKS];
702
703    for (i = 0; i < NUM_CHECKS; i++)
704	checks[i] = False;
705
706    for (i = 0; i < *num_args; i++) {
707	if (streq(XtNbitmap, args[i].name))
708	    checks[PIXMAP] = True;
709	else if (streq(XtNwidth, args[i].name))
710	    checks[WIDTH] = True;
711	else if (streq(XtNheight, args[i].name))
712	    checks[HEIGHT] = True;
713    }
714
715    if (newlw->label.label == NULL)
716	newlw->label.label = newlw->core.name;
717
718    /*
719     * resize on bitmap change
720     */
721    if (curlw->label.left_bitmap != newlw->label.left_bitmap)
722	was_resized = True;
723
724    if (curlw->label.encoding != newlw->label.encoding)
725	was_resized = True;
726
727    if (curlw->simple.international
728	&& curlw->label.fontset != newlw->label.fontset)
729	was_resized = True;
730
731    if (curlw->label.label != newlw->label.label) {
732	if (curlw->label.label != curlw->core.name)
733	    XtFree((char *)curlw->label.label);
734
735	if (newlw->label.label != newlw->core.name)
736	    newlw->label.label = XtNewString(newlw->label.label);
737
738	was_resized = True;
739    }
740
741    if (was_resized || (curlw->label.font != newlw->label.font) ||
742        curlw->label.justify != newlw->label.justify || checks[PIXMAP]) {
743	SetTextWidthAndHeight(newlw);
744	was_resized = True;
745    }
746
747    /* recalculate the window size if something has changed */
748    if (newlw->label.resize && was_resized) {
749	if (XtHeight(curlw) == XtHeight(reqlw) && !checks[HEIGHT])
750	    XtHeight(newlw) = newlw->label.label_height +
751			      (newlw->label.internal_height << 1);
752
753	set_bitmap_info(newlw);
754
755	if (XtWidth(curlw) == XtWidth(reqlw) && !checks[WIDTH])
756	    XtWidth(newlw) = newlw->label.label_width + LEFT_OFFSET(newlw) +
757			     (newlw->label.internal_width << 1);
758    }
759
760    if (curlw->label.foreground		!= newlw->label.foreground
761	|| curlw->core.background_pixel != newlw->core.background_pixel
762	|| curlw->label.font->fid	!= newlw->label.font->fid) {
763	/* The Fontset is not in the GC - don't make a new GC if FS changes! */
764	XtReleaseGC(cnew, curlw->label.normal_GC);
765	XtReleaseGC(cnew, curlw->label.gray_GC);
766	XmuReleaseStippledPixmap(XtScreen(current), curlw->label.stipple);
767	GetNormalGC(newlw);
768	GetGrayGC(newlw);
769	redisplay = True;
770    }
771
772    if (curlw->label.label_x != newlw->label.label_x ||
773        curlw->label.label_y != newlw->label.label_y)
774	redisplay = True;
775
776    if (curlw->label.internal_width != newlw->label.internal_width
777	|| curlw->label.internal_height != newlw->label.internal_height
778	|| was_resized) {
779	/* Resize() will be called if geometry changes succeed */
780	Position dx, dy;
781
782	_Reposition(newlw, XtWidth(curlw), XtHeight(curlw), &dx, &dy);
783    }
784
785      return (was_resized || redisplay ||
786	      XtIsSensitive(current) != XtIsSensitive(cnew));
787}
788
789static void
790XawLabelDestroy(Widget w)
791{
792    LabelWidget lw = (LabelWidget)w;
793
794    if (lw->label.label != lw->core.name)
795	XtFree(lw->label.label);
796    XtReleaseGC(w, lw->label.normal_GC);
797    XtReleaseGC(w, lw->label.gray_GC);
798    XmuReleaseStippledPixmap(XtScreen(w), lw->label.stipple);
799}
800
801static XtGeometryResult
802XawLabelQueryGeometry(Widget w, XtWidgetGeometry *intended,
803		      XtWidgetGeometry *preferred)
804{
805    LabelWidget lw = (LabelWidget)w;
806
807    preferred->request_mode = CWWidth | CWHeight;
808    preferred->width = lw->label.label_width +
809		       (lw->label.internal_width << 1) + LEFT_OFFSET(lw);
810    preferred->height = lw->label.label_height +
811			(lw->label.internal_height << 1);
812
813    if (((intended->request_mode & (CWWidth | CWHeight)) == (CWWidth | CWHeight))
814	&& intended->width == preferred->width
815	&& intended->height == preferred->height)
816	return (XtGeometryYes);
817      else if (preferred->width == XtWidth(w) && preferred->height == XtHeight(w))
818	return (XtGeometryNo);
819
820    return (XtGeometryAlmost);
821}
822