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