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