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