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