ULabel.c revision 0d6f290a
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#ifndef OLDXAW
157    /* extension		*/	,NULL
158#endif
159  },
160/* UCSLabel class fields initialization */
161  {
162    /* ignore 			*/	0
163  }
164};
165WidgetClass ucsLabelWidgetClass = (WidgetClass)&ucsLabelClassRec;
166/****************************************************************
167 *
168 * Private Procedures
169 *
170 ****************************************************************/
171
172static void ClassInitialize(void)
173{
174    XawInitializeWidgetSet();
175    XtAddConverter( XtRString, XtRJustify, XmuCvtStringToJustify,
176		    (XtConvertArgList)NULL, 0 );
177}
178
179static XChar2b *buf2b;
180static int buf2blen = 0;
181
182static void _XawLabelDrawUCS(Display *dpy, Drawable d, GC gc,
183			     int x, int y, const char *str, int n)
184{
185    const char *ep;
186    unsigned short codepoint;
187    XChar2b *ptr;
188
189    /*
190     * Convert to UCS2 string on the fly.
191     */
192
193    if (n > buf2blen) {
194	buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b));
195	buf2blen = n;
196    }
197    ep = str + n;
198    for (ptr = buf2b; str < ep; ptr++) {
199        if((str[0]&0x80)==0) {
200            codepoint=str[0];
201            str++;
202        } else if((str[0]&0x20)==0) {
203            codepoint=(str[0]&0x1F)<<6 | (str[1]&0x3F);
204            str+=2;
205        } else if((str[0]&0x10)==0) {
206            codepoint=(str[0]&0x0F)<<12 | (str[1]&0x3F)<<6 | (str[2]&0x3F);
207            str+=3;
208        } else {                    /* wrong UTF-8 */
209            codepoint=(unsigned)'?';
210            str++;
211        }
212	ptr->byte1 = (codepoint >> 8) & 0xff;
213	ptr->byte2 = codepoint & 0xff;
214    }
215    XDrawString16(dpy, d, gc, x, y, buf2b, ptr - buf2b);
216}
217
218static int _XawLabelWidthUCS(
219    XFontStruct *fs,
220    const char *str,
221    int	n
222)
223{
224    const char *ep;
225    unsigned short codepoint;
226    XChar2b *ptr;
227
228    /*
229     * Convert to UCS2 string on the fly.
230     */
231
232    if (n > buf2blen) {
233	buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b));
234	buf2blen = n;
235    }
236    ep = str + n;
237    for (ptr = buf2b; str < ep; ptr++) {
238        if((str[0]&0x80)==0) {
239            codepoint=str[0];
240            str++;
241        } else if((str[0]&0x20)==0) {
242            codepoint=(str[0]&0x1F)<<6 | (str[1]&0x3F);
243            str+=2;
244        } else if((str[0]&0x10)==0) {
245            codepoint=(str[0]&0x0F)<<12 | (str[1]&0x3F)<<6 | (str[2]&0x3F);
246            str+=3;
247        } else {                    /* wrong UTF-8 */
248            codepoint=(unsigned)'?';
249            str++;
250        }
251	ptr->byte1 = (codepoint >> 8) & 0xff;
252	ptr->byte2 = codepoint & 0xff;
253    }
254    return XTextWidth16(fs, buf2b, ptr - buf2b);
255}
256
257#define XTextWidthUCS _XawLabelWidthUCS
258#define XDrawStringUCS _XawLabelDrawUCS
259
260/*
261 * Calculate width and height of displayed text in pixels
262 */
263
264static void SetTextWidthAndHeight(UCSLabelWidget lw)
265{
266    XFontStruct	*fs = lw->label.font;
267
268    char *nl;
269
270    if (lw->label.pixmap != None) {
271	Window root;
272	int x, y;
273	unsigned int width, height, bw, depth;
274	if (XGetGeometry(XtDisplay(lw), lw->label.pixmap, &root, &x, &y,
275			 &width, &height, &bw, &depth)) {
276	    lw->label.label_height = height;
277	    lw->label.label_width = width;
278	    lw->label.label_len = depth;
279	    return;
280	}
281    }
282    if ( lw->simple.international == True ) {
283
284      XFontSet	fset = lw->label.fontset;
285      XFontSetExtents *ext = XExtentsOfFontSet(fset);
286
287      lw->label.label_height = ext->max_ink_extent.height;
288      if (lw->label.label == NULL) {
289	  lw->label.label_len = 0;
290	  lw->label.label_width = 0;
291      }
292      else if ((nl = index(lw->label.label, '\n')) != NULL) {
293	  const char *label;
294	  lw->label.label_len = MULTI_LINE_LABEL;
295	  lw->label.label_width = 0;
296	  for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) {
297	      int width = XmbTextEscapement(fset, label, (int)(nl - label));
298
299	      if (width > (int)lw->label.label_width)
300		  lw->label.label_width = width;
301	      label = nl + 1;
302	      if (*label)
303		  lw->label.label_height +=
304		      ext->max_ink_extent.height;
305	  }
306	  if (*label) {
307	      int width = XmbTextEscapement(fset, label, strlen(label));
308
309	      if (width > (int) lw->label.label_width)
310		  lw->label.label_width = width;
311	  }
312      } else {
313	  lw->label.label_len = strlen(lw->label.label);
314	  lw->label.label_width =
315	      XmbTextEscapement(fset, lw->label.label, (int) lw->label.label_len);
316      }
317
318    } else {
319
320        lw->label.label_height = fs->max_bounds.ascent + fs->max_bounds.descent;
321        if (lw->label.label == NULL) {
322            lw->label.label_len = 0;
323            lw->label.label_width = 0;
324        }
325        else if ((nl = index(lw->label.label, '\n')) != NULL) {
326	    const char *label;
327            lw->label.label_len = MULTI_LINE_LABEL;
328            lw->label.label_width = 0;
329            for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) {
330	        int width;
331
332	        if (lw->label.encoding == XawTextEncodingChar2b)
333		    width = XTextWidth16(fs, (XChar2b *)label, (int)(nl - label)/2);
334                else if (lw->label.encoding == XawTextEncodingUCS)
335		    width = XTextWidthUCS(fs, label, nl - label);
336	        else
337		    width = XTextWidth(fs, label, (int)(nl - label));
338	        if (width > (int)lw->label.label_width)
339		    lw->label.label_width = width;
340	        label = nl + 1;
341	        if (*label)
342		    lw->label.label_height +=
343		        fs->max_bounds.ascent + fs->max_bounds.descent;
344	    }
345	    if (*label) {
346	        int width;
347
348	        if (lw->label.encoding == XawTextEncodingChar2b)
349		    width = XTextWidth16(fs, (XChar2b *)label, (int)strlen(label)/2);
350                else if (lw->label.encoding == XawTextEncodingUCS)
351		    width = XTextWidthUCS(fs, label, strlen(label));
352	        else
353		    width = XTextWidth(fs, label, strlen(label));
354	        if (width > (int) lw->label.label_width)
355		    lw->label.label_width = width;
356	    }
357        } else {
358	    lw->label.label_len = strlen(lw->label.label);
359	    if (lw->label.encoding == XawTextEncodingChar2b)
360	        lw->label.label_width =
361		    XTextWidth16(fs, (XChar2b *)lw->label.label,
362			         (int) lw->label.label_len/2);
363            else if (lw->label.encoding == XawTextEncodingUCS)
364		lw->label.label_width = XTextWidthUCS(fs, lw->label.label,
365                                                      lw->label.label_len);
366	    else
367	        lw->label.label_width =
368		    XTextWidth(fs, lw->label.label, (int) lw->label.label_len);
369        }
370
371    }
372}
373
374static void GetnormalGC(UCSLabelWidget lw)
375{
376    XGCValues	values;
377
378    values.foreground	= lw->label.foreground;
379    values.background	= lw->core.background_pixel;
380    values.font		= lw->label.font->fid;
381    values.graphics_exposures = False;
382
383    if ( lw->simple.international == True )
384        /* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC. */
385        lw->label.normal_GC = XtAllocateGC(
386                (Widget)lw, 0,
387	(unsigned) GCForeground | GCBackground | GCGraphicsExposures,
388	&values, GCFont, 0 );
389    else
390        lw->label.normal_GC = XtGetGC(
391	(Widget)lw,
392	(unsigned) GCForeground | GCBackground | GCFont | GCGraphicsExposures,
393	&values);
394}
395
396static void GetgrayGC(UCSLabelWidget lw)
397{
398    XGCValues	values;
399
400    values.foreground = lw->label.foreground;
401    values.background = lw->core.background_pixel;
402    values.font	      = lw->label.font->fid;
403    values.fill_style = FillTiled;
404    values.tile       = XmuCreateStippledPixmap(XtScreen((Widget)lw),
405						lw->label.foreground,
406						lw->core.background_pixel,
407						lw->core.depth);
408    values.graphics_exposures = False;
409
410    lw->label.stipple = values.tile;
411    if ( lw->simple.international == True )
412        /* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC. */
413        lw->label.gray_GC = XtAllocateGC((Widget)lw,  0,
414				(unsigned) GCForeground | GCBackground |
415					   GCTile | GCFillStyle |
416					   GCGraphicsExposures,
417				&values, GCFont, 0);
418    else
419        lw->label.gray_GC = XtGetGC((Widget)lw,
420				(unsigned) GCForeground | GCBackground |
421					   GCFont | GCTile | GCFillStyle |
422					   GCGraphicsExposures,
423				&values);
424}
425
426static void compute_bitmap_offsets(UCSLabelWidget lw)
427{
428    /*
429     * bitmap will be eventually be displayed at
430     * (internal_width, internal_height + lbm_y)
431     */
432    if (lw->label.lbm_height != 0) {
433	lw->label.lbm_y = (lw->core.height -
434			  (lw->label.internal_height * 2 +
435			   lw->label.lbm_height)) / 2;
436    } else {
437	lw->label.lbm_y = 0;
438    }
439}
440
441
442static void set_bitmap_info(UCSLabelWidget lw)
443{
444    Window root;
445    int x, y;
446    unsigned int bw, depth;
447
448    if (!(lw->label.left_bitmap &&
449	  XGetGeometry (XtDisplay(lw), lw->label.left_bitmap, &root, &x, &y,
450			&lw->label.lbm_width, &lw->label.lbm_height,
451			&bw, &depth))) {
452	lw->label.lbm_width = lw->label.lbm_height = 0;
453    }
454    compute_bitmap_offsets (lw);
455}
456
457
458
459/* ARGSUSED */
460static void
461Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args)
462{
463    UCSLabelWidget lw = (UCSLabelWidget) new;
464
465    if (lw->label.label == NULL)
466        lw->label.label = XtNewString(lw->core.name);
467    else {
468        lw->label.label = XtNewString(lw->label.label);
469    }
470
471    GetnormalGC(lw);
472    GetgrayGC(lw);
473
474    SetTextWidthAndHeight(lw);
475
476    if (lw->core.height == 0)
477        lw->core.height = lw->label.label_height +
478			    2 * lw->label.internal_height;
479
480    set_bitmap_info (lw);		/* need core.height */
481
482    if (lw->core.width == 0)		/* need label.lbm_width */
483        lw->core.width = (lw->label.label_width +
484			    2 * lw->label.internal_width +
485			    LEFT_OFFSET(lw));
486
487    lw->label.label_x = lw->label.label_y = 0;
488    (*XtClass(new)->core_class.resize) ((Widget)lw);
489
490} /* Initialize */
491
492/*
493 * Repaint the widget window
494 */
495
496/* ARGSUSED */
497static void Redisplay(Widget gw, XEvent *event, Region region)
498{
499    UCSLabelWidget w = (UCSLabelWidget) gw;
500    GC gc;
501
502    /*
503     * now we'll see if we need to draw the rest of the label
504     */
505    if (region != NULL) {
506	int x = w->label.label_x;
507	unsigned int width = w->label.label_width;
508	if (w->label.lbm_width) {
509	    if (w->label.label_x > (x = w->label.internal_width))
510		width += w->label.label_x - x;
511	}
512	if (XRectInRegion(region, x, w->label.label_y,
513			 width, w->label.label_height) == RectangleOut){
514	    return;
515	}
516    }
517
518    gc = XtIsSensitive(gw) ? w->label.normal_GC : w->label.gray_GC;
519#ifdef notdef
520    if (region != NULL)
521	XSetRegion(XtDisplay(gw), gc, region);
522#endif /*notdef*/
523
524    if (w->label.pixmap == None) {
525	int len = w->label.label_len;
526	const char *label = w->label.label;
527	Position y = w->label.label_y + w->label.font->max_bounds.ascent;
528        Position ksy = w->label.label_y;
529
530	/* display left bitmap */
531	if (w->label.left_bitmap && w->label.lbm_width != 0) {
532	    XCopyPlane (XtDisplay(gw), w->label.left_bitmap, XtWindow(gw), gc,
533		       0, 0, w->label.lbm_width, w->label.lbm_height,
534		       (int) w->label.internal_width,
535		       (int) w->label.internal_height + w->label.lbm_y,
536		       (unsigned long) 1L);
537	}
538
539        if ( w->simple.international == True ) {
540
541	    XFontSetExtents *ext = XExtentsOfFontSet(w->label.fontset);
542
543	    ksy += abs(ext->max_ink_extent.y);
544
545            if (len == MULTI_LINE_LABEL) {
546	        char *nl;
547	        while ((nl = index(label, '\n')) != NULL) {
548	            XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, gc,
549	  		        w->label.label_x, ksy, label, (int)(nl - label));
550	            ksy += ext->max_ink_extent.height;
551	            label = nl + 1;
552	        }
553	        len = strlen(label);
554            }
555            if (len)
556	        XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, gc,
557			      w->label.label_x, ksy, label, len);
558
559        } else { /*international false, so use R5 routine */
560
561	    if (len == MULTI_LINE_LABEL) {
562	        char *nl;
563	        while ((nl = index(label, '\n')) != NULL) {
564		    if (w->label.encoding == XawTextEncodingChar2b)
565		        XDrawString16(XtDisplay(gw), XtWindow(gw), gc,
566				 		w->label.label_x, y,
567                                      (XChar2b *)label, (int)(nl - label)/2);
568                    else if (w->label.encoding == XawTextEncodingUCS)
569		        XDrawStringUCS(XtDisplay(gw), XtWindow(gw), gc,
570			       		w->label.label_x, y, label, (int)(nl - label));
571		    else
572		        XDrawString(XtDisplay(gw), XtWindow(gw), gc,
573			       		w->label.label_x, y, label, (int)(nl - label));
574		    y += w->label.font->max_bounds.ascent +
575		                        w->label.font->max_bounds.descent;
576		    label = nl + 1;
577	        }
578	        len = strlen(label);
579	    }
580	    if (len) {
581	        if (w->label.encoding == XawTextEncodingChar2b)
582		    XDrawString16(XtDisplay(gw), XtWindow(gw), gc,
583			     w->label.label_x, y, (XChar2b *)label, len/2);
584                else if (w->label.encoding == XawTextEncodingUCS)
585                    XDrawStringUCS(XtDisplay(gw), XtWindow(gw), gc,
586                             w->label.label_x, y, label, len);
587	        else
588		    XDrawString(XtDisplay(gw), XtWindow(gw), gc,
589			   w->label.label_x, y, label, len);
590	    }
591
592        } /*endif international*/
593
594    } else if (w->label.label_len == 1) { /* depth */
595	XCopyPlane(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc,
596				0, 0, w->label.label_width, w->label.label_height,
597				w->label.label_x, w->label.label_y, 1L);
598    } else {
599	XCopyArea(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc,
600				0, 0, w->label.label_width, w->label.label_height,
601				w->label.label_x, w->label.label_y);
602    }
603
604#ifdef notdef
605    if (region != NULL)
606	XSetClipMask(XtDisplay(gw), gc, (Pixmap)None);
607#endif /* notdef */
608}
609
610static void _Reposition(UCSLabelWidget lw, Dimension width, Dimension height,
611			Position *dx, Position *dy)
612{
613    Position newPos;
614    Position leftedge = lw->label.internal_width + LEFT_OFFSET(lw);
615
616    switch (lw->label.justify) {
617
618	case XtJustifyLeft   :
619	    newPos = leftedge;
620	    break;
621
622	case XtJustifyRight  :
623	    newPos = width -
624		(lw->label.label_width + lw->label.internal_width);
625	    break;
626
627	case XtJustifyCenter :
628	default:
629	    newPos = (int)(width - lw->label.label_width) / 2;
630	    break;
631    }
632    if (newPos < (Position)leftedge)
633	newPos = leftedge;
634    *dx = newPos - lw->label.label_x;
635    lw->label.label_x = newPos;
636    *dy = (newPos = (int)(height - lw->label.label_height) / 2)
637	  - lw->label.label_y;
638    lw->label.label_y = newPos;
639    return;
640}
641
642static void Resize(Widget w)
643{
644    UCSLabelWidget lw = (UCSLabelWidget)w;
645    Position dx, dy;
646
647    _Reposition(lw, w->core.width, w->core.height, &dx, &dy);
648    compute_bitmap_offsets (lw);
649}
650
651/*
652 * Set specified arguments into widget
653 */
654
655#define PIXMAP 0
656#define WIDTH 1
657#define HEIGHT 2
658#define NUM_CHECKS 3
659
660static Boolean
661SetValues(Widget current, Widget request, Widget new,
662	  ArgList args, Cardinal *num_args)
663{
664    UCSLabelWidget curlw = (UCSLabelWidget) current;
665    UCSLabelWidget reqlw = (UCSLabelWidget) request;
666    UCSLabelWidget newlw = (UCSLabelWidget) new;
667    unsigned int i;
668    Boolean was_resized = False, redisplay = False, checks[NUM_CHECKS];
669
670    for (i = 0; i < NUM_CHECKS; i++)
671	checks[i] = FALSE;
672
673    for (i = 0; i < *num_args; i++) {
674	if (streq(XtNbitmap, args[i].name))
675	    checks[PIXMAP] = TRUE;
676	if (streq(XtNwidth, args[i].name))
677	    checks[WIDTH] = TRUE;
678	if (streq(XtNheight, args[i].name))
679	    checks[HEIGHT] = TRUE;
680    }
681
682    if (newlw->label.label == NULL) {
683	newlw->label.label = newlw->core.name;
684    }
685
686    /*
687     * resize on bitmap change
688     */
689    if (curlw->label.left_bitmap != newlw->label.left_bitmap) {
690	was_resized = True;
691    }
692
693    if (curlw->label.encoding != newlw->label.encoding)
694	was_resized = True;
695
696    if ( (curlw->label.fontset != newlw->label.fontset) &&
697					 curlw->simple.international ){
698	was_resized = True;
699    }
700    if (curlw->label.label != newlw->label.label) {
701        if (curlw->label.label != curlw->core.name)
702	    XtFree( (char *)curlw->label.label );
703
704	if (newlw->label.label != newlw->core.name) {
705	    newlw->label.label = XtNewString( newlw->label.label );
706	}
707	was_resized = True;
708    }
709
710    if (was_resized || (curlw->label.font != newlw->label.font) ||
711	(curlw->label.justify != newlw->label.justify) || checks[PIXMAP]) {
712
713	SetTextWidthAndHeight(newlw);
714	was_resized = True;
715    }
716
717    /* recalculate the window size if something has changed. */
718    if (newlw->label.resize && was_resized) {
719	if ((curlw->core.height == reqlw->core.height) && !checks[HEIGHT])
720	    newlw->core.height = (newlw->label.label_height +
721				    2 * newlw->label.internal_height);
722
723	set_bitmap_info (newlw);
724
725	if ((curlw->core.width == reqlw->core.width) && !checks[WIDTH])
726	    newlw->core.width = (newlw->label.label_width +
727				    LEFT_OFFSET(newlw) +
728				    2 * newlw->label.internal_width);
729    }
730
731    if (curlw->label.foreground		!= newlw->label.foreground
732	|| curlw->core.background_pixel != newlw->core.background_pixel
733	|| curlw->label.font->fid	!= newlw->label.font->fid	  ) {
734
735        /* The Fontset is not in the GC - don't make a new GC if FS changes! */
736
737	XtReleaseGC(new, curlw->label.normal_GC);
738	XtReleaseGC(new, curlw->label.gray_GC);
739	XmuReleaseStippledPixmap( XtScreen(current), curlw->label.stipple );
740	GetnormalGC(newlw);
741	GetgrayGC(newlw);
742	redisplay = True;
743    }
744
745    if ((curlw->label.internal_width != newlw->label.internal_width)
746        || (curlw->label.internal_height != newlw->label.internal_height)
747	|| was_resized) {
748	/* Resize() will be called if geometry changes succeed */
749	Position dx, dy;
750	_Reposition(newlw, curlw->core.width, curlw->core.height, &dx, &dy);
751    }
752
753    return was_resized || redisplay ||
754	   XtIsSensitive(current) != XtIsSensitive(new);
755}
756
757static void Destroy(Widget w)
758{
759    UCSLabelWidget lw = (UCSLabelWidget)w;
760
761    if ( lw->label.label != lw->core.name )
762	XtFree( (char *) lw->label.label );
763    XtReleaseGC( w, lw->label.normal_GC );
764    XtReleaseGC( w, lw->label.gray_GC);
765    XmuReleaseStippledPixmap( XtScreen(w), lw->label.stipple );
766}
767
768
769static XtGeometryResult
770QueryGeometry(Widget w, XtWidgetGeometry *intended, XtWidgetGeometry *preferred)
771{
772    UCSLabelWidget lw = (UCSLabelWidget)w;
773
774    preferred->request_mode = CWWidth | CWHeight;
775    preferred->width = (lw->label.label_width +
776			    2 * lw->label.internal_width +
777			    LEFT_OFFSET(lw));
778    preferred->height = lw->label.label_height +
779			    2 * lw->label.internal_height;
780    if (  ((intended->request_mode & (CWWidth | CWHeight))
781	   	== (CWWidth | CWHeight)) &&
782	  intended->width == preferred->width &&
783	  intended->height == preferred->height)
784	return XtGeometryYes;
785    else if (preferred->width == w->core.width &&
786	     preferred->height == w->core.height)
787	return XtGeometryNo;
788    else
789	return XtGeometryAlmost;
790}
791