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