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
67/*
68 * Class Methods
69 */
70static void XawLabelClassInitialize(void);
71static void XawLabelDestroy(Widget);
72static void XawLabelInitialize(Widget, Widget, ArgList, Cardinal*);
73static XtGeometryResult XawLabelQueryGeometry(Widget, XtWidgetGeometry*,
74					      XtWidgetGeometry*);
75static void XawLabelRedisplay(Widget, XEvent*, Region);
76static void XawLabelResize(Widget);
77static Boolean XawLabelSetValues(Widget, Widget, Widget,
78				 ArgList, Cardinal*);
79
80/*
81 * Prototypes
82 */
83static void compute_bitmap_offsets(LabelWidget);
84static void GetGrayGC(LabelWidget);
85static void GetNormalGC(LabelWidget);
86static void _Reposition(LabelWidget, unsigned int, unsigned int,
87			Position*, Position*);
88static void set_bitmap_info(LabelWidget);
89static void SetTextWidthAndHeight(LabelWidget);
90
91/*
92 * Initialization
93 */
94#define offset(field) XtOffsetOf(LabelRec, field)
95static XtResource resources[] = {
96  {
97    XtNforeground,
98    XtCForeground,
99    XtRPixel,
100    sizeof(Pixel),
101    offset(label.foreground),
102    XtRString,
103    (XtPointer)XtDefaultForeground
104  },
105  {
106    XtNfont,
107    XtCFont,
108    XtRFontStruct,
109    sizeof(XFontStruct*),
110    offset(label.font),
111    XtRString,
112    (XtPointer)XtDefaultFont
113  },
114  {
115    XtNfontSet,
116    XtCFontSet,
117    XtRFontSet,
118    sizeof(XFontSet),
119    offset(label.fontset),
120    XtRString,
121    (XtPointer)XtDefaultFontSet
122  },
123  {
124    XtNlabel,
125    XtCLabel,
126    XtRString,
127    sizeof(String),
128    offset(label.label),
129    XtRString,
130    NULL
131  },
132  {
133    XtNencoding,
134    XtCEncoding,
135    XtRUnsignedChar,
136    sizeof(unsigned char),
137    offset(label.encoding),
138    XtRImmediate,
139    (XtPointer)XawTextEncoding8bit
140  },
141  {
142    XtNjustify,
143    XtCJustify,
144    XtRJustify,
145    sizeof(XtJustify),
146    offset(label.justify),
147    XtRImmediate,
148    (XtPointer)XtJustifyCenter
149  },
150  {
151    XtNinternalWidth,
152    XtCWidth,
153    XtRDimension,
154    sizeof(Dimension),
155    offset(label.internal_width),
156    XtRImmediate,
157    (XtPointer)4
158  },
159  {
160    XtNinternalHeight,
161    XtCHeight,
162    XtRDimension,
163    sizeof(Dimension),
164    offset(label.internal_height),
165    XtRImmediate,
166    (XtPointer)2
167  },
168  {
169    XtNleftBitmap,
170    XtCLeftBitmap,
171    XtRBitmap,
172    sizeof(Pixmap),
173    offset(label.left_bitmap),
174    XtRImmediate,
175    (XtPointer)None
176  },
177  {
178    XtNbitmap,
179    XtCPixmap,
180    XtRBitmap,
181    sizeof(Pixmap),
182    offset(label.pixmap),
183    XtRImmediate,
184    (XtPointer)None
185  },
186  {
187    XtNresize,
188    XtCResize,
189    XtRBoolean,
190    sizeof(Boolean),
191    offset(label.resize),
192    XtRImmediate,
193    (XtPointer)True
194  },
195  {
196    XtNlabelX,
197    XtCPosition,
198    XtRPosition,
199    sizeof(Position),
200    offset(label.label_x),
201    XtRImmediate,
202    (XtPointer)0
203  },
204  {
205    XtNlabelY,
206    XtCPosition,
207    XtRPosition,
208    sizeof(Position),
209    offset(label.label_y),
210    XtRImmediate,
211    (XtPointer)0
212  },
213};
214#undef offset
215
216#define Superclass (&simpleClassRec)
217LabelClassRec labelClassRec = {
218  /* core */
219  {
220    (WidgetClass)&simpleClassRec,	/* superclass */
221    "Label",				/* class_name */
222    sizeof(LabelRec),			/* widget_size */
223    XawLabelClassInitialize,		/* class_initialize */
224    NULL,				/* class_part_initialize */
225    False,				/* class_inited */
226    XawLabelInitialize,			/* initialize */
227    NULL,				/* initialize_hook */
228    XtInheritRealize,			/* realize */
229    NULL,				/* actions */
230    0,					/* num_actions */
231    resources,				/* resources */
232    XtNumber(resources),		/* num_resources */
233    NULLQUARK,				/* xrm_class */
234    True,				/* compress_motion */
235    True,				/* compress_exposure */
236    True,				/* compress_enterleave */
237    False,				/* visible_interest */
238    XawLabelDestroy,			/* destroy */
239    XawLabelResize,			/* resize */
240    XawLabelRedisplay,			/* expose */
241    XawLabelSetValues,			/* set_values */
242    NULL,				/* set_values_hook */
243    XtInheritSetValuesAlmost,		/* set_values_almost */
244    NULL,				/* get_values_hook */
245    NULL,				/* accept_focus */
246    XtVersion,				/* version */
247    NULL,				/* callback_private */
248    NULL,				/* tm_table */
249    XawLabelQueryGeometry,		/* query_geometry */
250    XtInheritDisplayAccelerator,	/* display_accelerator */
251    NULL,				/* extension */
252  },
253  /* simple */
254  {
255    XtInheritChangeSensitive,		/* change_sensitive */
256#ifndef OLDXAW
257    NULL,
258#endif
259  },
260  /* label */
261  {
262    NULL,				/* extension */
263  }
264};
265
266WidgetClass labelWidgetClass = (WidgetClass)&labelClassRec;
267
268/*
269 * Implementation
270 */
271static void
272XawLabelClassInitialize(void)
273{
274    XawInitializeWidgetSet();
275    XtAddConverter(XtRString, XtRJustify, XmuCvtStringToJustify, NULL, 0);
276    XtSetTypeConverter(XtRJustify, XtRString, XmuCvtJustifyToString,
277		       NULL, 0, XtCacheNone, NULL);
278}
279
280/*
281 * Calculate width and height of displayed text in pixels
282 */
283static void
284SetTextWidthAndHeight(LabelWidget lw)
285{
286    XFontStruct	*fs = lw->label.font;
287    char *nl;
288
289    if (lw->label.pixmap != None) {
290	Window root;
291	int x, y;
292	unsigned int width, height, bw, depth;
293
294	if (XGetGeometry(XtDisplay(lw), lw->label.pixmap, &root, &x, &y,
295		       &width, &height, &bw, &depth)) {
296	    lw->label.label_height = (Dimension)height;
297	    lw->label.label_width = (Dimension)width;
298	    lw->label.label_len = (Dimension)depth;
299	    return;
300	}
301    }
302    if (lw->simple.international == True) {
303	XFontSet	fset = lw->label.fontset;
304	XFontSetExtents *ext = XExtentsOfFontSet(fset);
305
306	lw->label.label_height = ext->max_ink_extent.height;
307	if (lw->label.label == NULL) {
308	    lw->label.label_len = 0;
309	    lw->label.label_width = 0;
310	}
311	else if ((nl = strchr(lw->label.label, '\n')) != NULL) {
312	    char *label;
313
314	    lw->label.label_len = MULTI_LINE_LABEL;
315	    lw->label.label_width = 0;
316	    for (label = lw->label.label; nl != NULL; nl = strchr(label, '\n')) {
317		int width = XmbTextEscapement(fset, label, (int)(nl - label));
318
319		if (width > (int)lw->label.label_width)
320		    lw->label.label_width = (Dimension)width;
321		label = nl + 1;
322		if (*label)
323		    lw->label.label_height = (Dimension)(lw->label.label_height + ext->max_ink_extent.height);
324	    }
325	    if (*label) {
326		int width = XmbTextEscapement(fset, label, (int)strlen(label));
327
328		if (width > (int)lw->label.label_width)
329		    lw->label.label_width = (Dimension)width;
330	    }
331	}
332	else {
333	    lw->label.label_len = (Dimension)strlen(lw->label.label);
334	    lw->label.label_width =
335		(Dimension)XmbTextEscapement(fset, lw->label.label, lw->label.label_len);
336	}
337    }
338    else {
339	lw->label.label_height = (Dimension)(fs->max_bounds.ascent + fs->max_bounds.descent);
340	if (lw->label.label == NULL) {
341	    lw->label.label_len = 0;
342	    lw->label.label_width = 0;
343	}
344	else if ((nl = strchr(lw->label.label, '\n')) != NULL) {
345	    char *label;
346
347	    lw->label.label_len = MULTI_LINE_LABEL;
348	    lw->label.label_width = 0;
349	    for (label = lw->label.label; nl != NULL; nl = strchr(label, '\n')) {
350		int width;
351
352		if (lw->label.encoding)
353		    width = XTextWidth16(fs, (XChar2b *)label, (int)(nl - label) / 2);
354		else
355		    width = XTextWidth(fs, label, (int)(nl - label));
356		if (width > (int)lw->label.label_width)
357		    lw->label.label_width = (Dimension)width;
358		label = nl + 1;
359		if (*label)
360		    lw->label.label_height +=
361			(Dimension)(fs->max_bounds.ascent + fs->max_bounds.descent);
362	    }
363	    if (*label) {
364		int width;
365
366		if (lw->label.encoding)
367		    width = XTextWidth16(fs, (XChar2b *)label, (int)(strlen(label) / 2));
368		else
369		    width = XTextWidth(fs, label, (int)strlen(label));
370		if (width > (int) lw->label.label_width)
371		    lw->label.label_width = (Dimension)width;
372	    }
373	}
374	else {
375	    lw->label.label_len = (Dimension)strlen(lw->label.label);
376	    if (lw->label.encoding)
377		lw->label.label_width =
378		    (Dimension)XTextWidth16(fs, (XChar2b *)lw->label.label,
379			   (int)lw->label.label_len / 2);
380	    else
381		lw->label.label_width =
382		    (Dimension)XTextWidth(fs, lw->label.label, (int)lw->label.label_len);
383	}
384    }
385}
386
387static void
388GetNormalGC(LabelWidget lw)
389{
390    XGCValues	values = {
391	.foreground		= lw->label.foreground,
392	.background		= lw->core.background_pixel,
393	.font			= lw->label.font->fid,
394	.graphics_exposures	= False
395    };
396
397    if (lw->simple.international == True)
398    /* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC */
399	lw->label.normal_GC = XtAllocateGC((Widget)lw, 0,
400					   GCForeground | GCBackground |
401					   GCGraphicsExposures,
402					   &values, GCFont, 0);
403    else
404	lw->label.normal_GC = XtGetGC((Widget)lw,
405				      GCForeground | GCBackground | GCFont |
406				      GCGraphicsExposures, &values);
407}
408
409static void
410GetGrayGC(LabelWidget lw)
411{
412    XGCValues	values = {
413	.foreground = lw->label.foreground,
414	.background = lw->core.background_pixel,
415	.font	    = lw->label.font->fid,
416	.fill_style = FillTiled,
417	.tile	    = XmuCreateStippledPixmap(XtScreen((Widget)lw),
418					      lw->label.foreground,
419					      lw->core.background_pixel,
420					      lw->core.depth),
421	.graphics_exposures = False
422    };
423
424    lw->label.stipple = values.tile;
425    if (lw->simple.international == True)
426	/* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC */
427	lw->label.gray_GC = XtAllocateGC((Widget)lw, 0,
428					 GCForeground | GCBackground |
429					 GCTile | GCFillStyle |
430					 GCGraphicsExposures,
431					 &values, GCFont, 0);
432	else
433	    lw->label.gray_GC = XtGetGC((Widget)lw,
434					GCForeground | GCBackground |
435					GCFont | GCTile | GCFillStyle |
436					GCGraphicsExposures,
437					&values);
438}
439
440static void
441compute_bitmap_offsets(LabelWidget lw)
442{
443    /*
444     * bitmap will be eventually be displayed at
445     * (internal_width, internal_height + lbm_y)
446     */
447    if (lw->label.lbm_height != 0)
448	lw->label.lbm_y = (int)((XtHeight(lw)
449				- ((lw->label.internal_height * 2)
450				+ lw->label.lbm_height)) / 2);
451    else
452	lw->label.lbm_y = 0;
453}
454
455static void
456set_bitmap_info(LabelWidget lw)
457{
458    Window root;
459    int x, y;
460    unsigned int bw, depth;
461
462    if (!(lw->label.left_bitmap
463	&& XGetGeometry(XtDisplay(lw), lw->label.left_bitmap, &root, &x, &y,
464			&lw->label.lbm_width, &lw->label.lbm_height,
465			&bw, &depth)))
466	lw->label.lbm_width = lw->label.lbm_height = 0;
467
468    compute_bitmap_offsets(lw);
469}
470
471/*ARGSUSED*/
472static void
473XawLabelInitialize(Widget request _X_UNUSED, Widget cnew,
474		   ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
475{
476    LabelWidget lw = (LabelWidget)cnew;
477
478    if (!lw->label.font) XtError("Aborting: no font found\n");
479    if (lw->simple.international && !lw->label.fontset)
480	XtError("Aborting: no fontset found\n");
481
482    if (lw->label.label == NULL)
483	lw->label.label = XtNewString(lw->core.name);
484    else
485	lw->label.label = XtNewString(lw->label.label);
486
487    GetNormalGC(lw);
488    GetGrayGC(lw);
489
490    SetTextWidthAndHeight(lw);
491
492    if (XtHeight(lw) == 0)
493	XtHeight(lw) = (Dimension)(lw->label.label_height + 2 * lw->label.internal_height);
494
495    set_bitmap_info(lw);		/* need core.height */
496
497    if (XtWidth(lw) == 0)		/* need label.lbm_width */
498	XtWidth(lw) = (Dimension)(lw->label.label_width
499				  + (unsigned)(2 * lw->label.internal_width)
500				  + LEFT_OFFSET(lw));
501
502    lw->label.label_x = lw->label.label_y = 0;
503    (*XtClass(cnew)->core_class.resize)((Widget)lw);
504}
505
506/*ARGSUSED*/
507static void
508XawLabelRedisplay(Widget gw, XEvent *event, Region region)
509{
510    LabelWidget w = (LabelWidget)gw;
511    GC gc;
512
513    if (*Superclass->core_class.expose != NULL)
514	(*Superclass->core_class.expose)(gw, event, region);
515
516    gc = XtIsSensitive(gw) ? w->label.normal_GC : w->label.gray_GC;
517
518    if (w->label.pixmap == None) {
519	int len = w->label.label_len;
520	char *label = w->label.label;
521	Position y = (Position)(w->label.label_y + w->label.font->max_bounds.ascent);
522	Position ksy = w->label.label_y;
523
524	/* display left bitmap */
525	if (w->label.left_bitmap && w->label.lbm_width != 0)
526	    XCopyPlane (XtDisplay(gw), w->label.left_bitmap, XtWindow(gw), gc,
527			0, 0, w->label.lbm_width, w->label.lbm_height,
528			w->label.internal_width,
529			w->label.internal_height + w->label.lbm_y, 1L);
530
531	if (w->simple.international == True) {
532	    XFontSetExtents *ext = XExtentsOfFontSet(w->label.fontset);
533
534	    ksy = (Position) (ksy + XawAbs(ext->max_ink_extent.y));
535
536	    if (len == MULTI_LINE_LABEL) {
537		char *nl;
538
539		while ((nl = strchr(label, '\n')) != NULL) {
540		    XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset,
541				  gc, w->label.label_x, ksy, label,
542				  (int)(nl - label));
543		    ksy = (Position) (ksy + ext->max_ink_extent.height);
544		    label = nl + 1;
545		}
546		len = (int)strlen(label);
547	    }
548	    if (len)
549		XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, gc,
550			      w->label.label_x, ksy, label, len);
551	}
552	else {
553	    if (len == MULTI_LINE_LABEL) {
554		char *nl;
555
556		while ((nl = strchr(label, '\n')) != NULL) {
557		    if (w->label.encoding)
558			XDrawString16(XtDisplay(gw), XtWindow(gw), gc,
559				      w->label.label_x, y,
560				      (XChar2b *)label, (int)(nl - label) / 2);
561		    else
562			XDrawString(XtDisplay(gw), XtWindow(gw), gc,
563				    w->label.label_x, y, label, (int)(nl - label));
564		    y += (Position) (w->label.font->max_bounds.ascent +
565				     w->label.font->max_bounds.descent);
566		    label = nl + 1;
567		}
568		len = (int)strlen(label);
569	    }
570	    if (len) {
571		if (w->label.encoding)
572		    XDrawString16(XtDisplay(gw), XtWindow(gw), gc,
573				  w->label.label_x, y, (XChar2b *)label, len / 2);
574		else
575		    XDrawString(XtDisplay(gw), XtWindow(gw), gc,
576				w->label.label_x, y, label, len);
577	    }
578	}
579    }
580    else if (w->label.label_len == 1)
581	XCopyPlane(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc,
582		   0, 0, w->label.label_width, w->label.label_height,
583		   w->label.label_x, w->label.label_y, 1L);
584    else
585	XCopyArea(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc,
586		  0, 0, w->label.label_width, w->label.label_height,
587		  w->label.label_x, w->label.label_y);
588}
589
590static void
591_Reposition(LabelWidget lw, unsigned int width, unsigned int height,
592	    Position *dx, Position *dy)
593{
594    Position newPos;
595    Position leftedge = (Position)(lw->label.internal_width + LEFT_OFFSET(lw));
596
597    switch (lw->label.justify) {
598	case XtJustifyLeft:
599	    newPos = leftedge;
600	    break;
601	case XtJustifyRight:
602	    newPos = (Position)(width - (unsigned)(lw->label.label_width + lw->label.internal_width));
603	    break;
604	case XtJustifyCenter:
605        /*FALLTRHOUGH*/
606	default:
607	    newPos = (Position)((int)(width - lw->label.label_width) >> 1);
608	    break;
609    }
610    if (newPos < (Position)leftedge)
611	newPos = leftedge;
612    *dx = (Position)(newPos - lw->label.label_x);
613    lw->label.label_x = newPos;
614
615    newPos = (Position)((height - lw->label.label_height) >> 1);
616    *dy = (Position)(newPos - lw->label.label_y);
617    lw->label.label_y = newPos;
618}
619
620static void
621XawLabelResize(Widget w)
622{
623    LabelWidget lw = (LabelWidget)w;
624    Position dx, dy;
625
626    _Reposition(lw, XtWidth(w), XtHeight(w), &dx, &dy);
627    compute_bitmap_offsets(lw);
628}
629
630#define PIXMAP 0
631#define WIDTH 1
632#define HEIGHT 2
633#define NUM_CHECKS 3
634static Boolean
635XawLabelSetValues(Widget current, Widget request, Widget cnew,
636		  ArgList args, Cardinal *num_args)
637{
638    LabelWidget curlw = (LabelWidget)current;
639    LabelWidget reqlw = (LabelWidget)request;
640    LabelWidget newlw = (LabelWidget)cnew;
641    Boolean was_resized = False, redisplay = False, checks[NUM_CHECKS];
642    Cardinal i;
643
644    for (i = 0; i < NUM_CHECKS; i++)
645	checks[i] = False;
646
647    for (i = 0; i < *num_args; i++) {
648	if (streq(XtNbitmap, args[i].name))
649	    checks[PIXMAP] = True;
650	else if (streq(XtNwidth, args[i].name))
651	    checks[WIDTH] = True;
652	else if (streq(XtNheight, args[i].name))
653	    checks[HEIGHT] = True;
654    }
655
656    if (newlw->label.label == NULL)
657	newlw->label.label = (char *)newlw->core.name;
658
659    /*
660     * resize on bitmap change
661     */
662    if (curlw->label.left_bitmap != newlw->label.left_bitmap)
663	was_resized = True;
664
665    if (curlw->label.encoding != newlw->label.encoding)
666	was_resized = True;
667
668    if (curlw->simple.international
669	&& curlw->label.fontset != newlw->label.fontset)
670	was_resized = True;
671
672    if (curlw->label.label != newlw->label.label) {
673	if (curlw->label.label != curlw->core.name)
674	    XtFree((char *)curlw->label.label);
675
676	if (newlw->label.label != newlw->core.name)
677	    newlw->label.label = XtNewString(newlw->label.label);
678
679	was_resized = True;
680    }
681
682    if (was_resized || (curlw->label.font != newlw->label.font) ||
683        curlw->label.justify != newlw->label.justify || checks[PIXMAP]) {
684	SetTextWidthAndHeight(newlw);
685	was_resized = True;
686    }
687
688    /* recalculate the window size if something has changed */
689    if (newlw->label.resize && was_resized) {
690	if (XtHeight(curlw) == XtHeight(reqlw) && !checks[HEIGHT])
691	    XtHeight(newlw) = (Dimension)(newlw->label.label_height +
692			      (newlw->label.internal_height << 1));
693
694	set_bitmap_info(newlw);
695
696	if (XtWidth(curlw) == XtWidth(reqlw) && !checks[WIDTH])
697	    XtWidth(newlw) = (Dimension)(newlw->label.label_width
698					 + LEFT_OFFSET(newlw)
699					 + (unsigned)(newlw->label.internal_width << 1));
700    }
701
702    if (curlw->label.foreground		!= newlw->label.foreground
703	|| curlw->core.background_pixel != newlw->core.background_pixel
704	|| curlw->label.font->fid	!= newlw->label.font->fid) {
705	/* The Fontset is not in the GC - don't make a new GC if FS changes! */
706	XtReleaseGC(cnew, curlw->label.normal_GC);
707	XtReleaseGC(cnew, curlw->label.gray_GC);
708	XmuReleaseStippledPixmap(XtScreen(current), curlw->label.stipple);
709	GetNormalGC(newlw);
710	GetGrayGC(newlw);
711	redisplay = True;
712    }
713
714    if (curlw->label.label_x != newlw->label.label_x ||
715        curlw->label.label_y != newlw->label.label_y)
716	redisplay = True;
717
718    if (curlw->label.internal_width != newlw->label.internal_width
719	|| curlw->label.internal_height != newlw->label.internal_height
720	|| was_resized) {
721	/* Resize() will be called if geometry changes succeed */
722	Position dx, dy;
723
724	_Reposition(newlw, XtWidth(curlw), XtHeight(curlw), &dx, &dy);
725    }
726
727      return (was_resized || redisplay ||
728	      XtIsSensitive(current) != XtIsSensitive(cnew));
729}
730
731static void
732XawLabelDestroy(Widget w)
733{
734    LabelWidget lw = (LabelWidget)w;
735
736    if (lw->label.label != lw->core.name)
737	XtFree(lw->label.label);
738    XtReleaseGC(w, lw->label.normal_GC);
739    XtReleaseGC(w, lw->label.gray_GC);
740    XmuReleaseStippledPixmap(XtScreen(w), lw->label.stipple);
741}
742
743static XtGeometryResult
744XawLabelQueryGeometry(Widget w, XtWidgetGeometry *intended,
745		      XtWidgetGeometry *preferred)
746{
747    LabelWidget lw = (LabelWidget)w;
748
749    preferred->request_mode = CWWidth | CWHeight;
750    preferred->width = (Dimension)(lw->label.label_width
751                                   + (unsigned)(lw->label.internal_width << 1)
752                                   + LEFT_OFFSET(lw));
753    preferred->height = (Dimension)(lw->label.label_height +
754			(lw->label.internal_height << 1));
755
756    if (((intended->request_mode & (CWWidth | CWHeight)) == (CWWidth | CWHeight))
757	&& intended->width == preferred->width
758	&& intended->height == preferred->height)
759	return (XtGeometryYes);
760      else if (preferred->width == XtWidth(w) && preferred->height == XtHeight(w))
761	return (XtGeometryNo);
762
763    return (XtGeometryAlmost);
764}
765