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