19027f4a0Smrg/***********************************************************
29027f4a0Smrg
39027f4a0SmrgCopyright (c) 1987, 1988, 1994  X Consortium
49027f4a0Smrg
59027f4a0SmrgPermission is hereby granted, free of charge, to any person obtaining a copy
69027f4a0Smrgof this software and associated documentation files (the "Software"), to deal
79027f4a0Smrgin the Software without restriction, including without limitation the rights
89027f4a0Smrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
99027f4a0Smrgcopies of the Software, and to permit persons to whom the Software is
109027f4a0Smrgfurnished to do so, subject to the following conditions:
119027f4a0Smrg
129027f4a0SmrgThe above copyright notice and this permission notice shall be included in
139027f4a0Smrgall copies or substantial portions of the Software.
149027f4a0Smrg
159027f4a0SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
169027f4a0SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
179027f4a0SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
189027f4a0SmrgX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
199027f4a0SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
209027f4a0SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
219027f4a0Smrg
229027f4a0SmrgExcept as contained in this notice, the name of the X Consortium shall not be
239027f4a0Smrgused in advertising or otherwise to promote the sale, use or other dealings
249027f4a0Smrgin this Software without prior written authorization from the X Consortium.
259027f4a0Smrg
269027f4a0Smrg
279027f4a0SmrgCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
289027f4a0Smrg
299027f4a0Smrg                        All Rights Reserved
309027f4a0Smrg
31fe2ac8d7SmrgPermission to use, copy, modify, and distribute this software and its
32fe2ac8d7Smrgdocumentation for any purpose and without fee is hereby granted,
339027f4a0Smrgprovided that the above copyright notice appear in all copies and that
34fe2ac8d7Smrgboth that copyright notice and this permission notice appear in
359027f4a0Smrgsupporting documentation, and that the name of Digital not be
369027f4a0Smrgused in advertising or publicity pertaining to distribution of the
37fe2ac8d7Smrgsoftware without specific, written prior permission.
389027f4a0Smrg
399027f4a0SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
409027f4a0SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
419027f4a0SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
429027f4a0SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
439027f4a0SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
449027f4a0SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
459027f4a0SmrgSOFTWARE.
469027f4a0Smrg
479027f4a0Smrg******************************************************************/
489027f4a0Smrg
499027f4a0Smrg/*
509027f4a0Smrg * ULabel.c - UCSLabel widget
519027f4a0Smrg *
529027f4a0Smrg */
539027f4a0Smrg
549027f4a0Smrg#include <X11/IntrinsicP.h>
559027f4a0Smrg#include <X11/StringDefs.h>
569027f4a0Smrg#include <X11/Xos.h>
579027f4a0Smrg#include <X11/Xaw/XawInit.h>
589027f4a0Smrg#include "ULabelP.h"
599027f4a0Smrg#include <X11/Xmu/Converters.h>
609027f4a0Smrg#include <X11/Xmu/Drawing.h>
619027f4a0Smrg#include <stdio.h>
629027f4a0Smrg#include <ctype.h>
639027f4a0Smrg/* needed for abs() */
649027f4a0Smrg#include <stdlib.h>
659027f4a0Smrg
669027f4a0Smrg#define streq(a,b) (strcmp( (a), (b) ) == 0)
679027f4a0Smrg
689027f4a0Smrg#define MULTI_LINE_LABEL 32767
699027f4a0Smrg
709027f4a0Smrg
719027f4a0Smrg/****************************************************************
729027f4a0Smrg *
739027f4a0Smrg * Full class record constant
749027f4a0Smrg *
759027f4a0Smrg ****************************************************************/
769027f4a0Smrg
779027f4a0Smrg/* Private Data */
789027f4a0Smrg
799027f4a0Smrg#define offset(field) XtOffsetOf(UCSLabelRec, field)
809027f4a0Smrgstatic XtResource resources[] = {
819027f4a0Smrg    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
829027f4a0Smrg	offset(label.foreground), XtRString, XtDefaultForeground},
839027f4a0Smrg    {XtNfont,  XtCFont, XtRFontStruct, sizeof(XFontStruct *),
849027f4a0Smrg	offset(label.font),XtRString, XtDefaultFont},
859027f4a0Smrg    {XtNfontSet,  XtCFontSet, XtRFontSet, sizeof(XFontSet ),
869027f4a0Smrg        offset(label.fontset),XtRString, XtDefaultFontSet},
879027f4a0Smrg    {XtNlabel,  XtCLabel, XtRString, sizeof(String),
889027f4a0Smrg	offset(label.label), XtRString, NULL},
899027f4a0Smrg    {XtNencoding, XtCEncoding, XtRUnsignedChar, sizeof(unsigned char),
909027f4a0Smrg	offset(label.encoding), XtRImmediate, (XtPointer)XawTextEncoding8bit},
919027f4a0Smrg    {XtNjustify, XtCJustify, XtRJustify, sizeof(XtJustify),
929027f4a0Smrg	offset(label.justify), XtRImmediate, (XtPointer)XtJustifyCenter},
939027f4a0Smrg    {XtNinternalWidth, XtCWidth, XtRDimension,  sizeof(Dimension),
949027f4a0Smrg	offset(label.internal_width), XtRImmediate, (XtPointer)4},
959027f4a0Smrg    {XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension),
969027f4a0Smrg	offset(label.internal_height), XtRImmediate, (XtPointer)2},
979027f4a0Smrg    {XtNleftBitmap, XtCLeftBitmap, XtRBitmap, sizeof(Pixmap),
989027f4a0Smrg       offset(label.left_bitmap), XtRImmediate, (XtPointer) None},
999027f4a0Smrg    {XtNbitmap, XtCPixmap, XtRBitmap, sizeof(Pixmap),
1009027f4a0Smrg	offset(label.pixmap), XtRImmediate, (XtPointer)None},
1019027f4a0Smrg    {XtNresize, XtCResize, XtRBoolean, sizeof(Boolean),
1029027f4a0Smrg	offset(label.resize), XtRImmediate, (XtPointer)True},
1039027f4a0Smrg};
1049027f4a0Smrg#undef offset
1059027f4a0Smrg
1063a72f200Smrgstatic void Initialize(Widget request, Widget new,
1073a72f200Smrg		       ArgList args, Cardinal *num_args);
1083a72f200Smrgstatic void Resize(Widget w);
1093a72f200Smrgstatic void Redisplay(Widget gw, XEvent *event, Region region);
1103a72f200Smrgstatic Boolean SetValues(Widget current, Widget request, Widget new,
1113a72f200Smrg			 ArgList args, Cardinal *num_args);
1123a72f200Smrgstatic void ClassInitialize(void);
1133a72f200Smrgstatic void Destroy(Widget w);
1143a72f200Smrgstatic XtGeometryResult QueryGeometry(Widget w, XtWidgetGeometry *intended,
1153a72f200Smrg				      XtWidgetGeometry *preferred);
1169027f4a0Smrg
1179027f4a0SmrgUCSLabelClassRec ucsLabelClassRec = {
1189027f4a0Smrg  {
119fe2ac8d7Smrg/* core_class fields */
1209027f4a0Smrg    /* superclass	  	*/	(WidgetClass) &simpleClassRec,
1219027f4a0Smrg    /* class_name	  	*/	"UCSLabel",
1229027f4a0Smrg    /* widget_size	  	*/	sizeof(UCSLabelRec),
1239027f4a0Smrg    /* class_initialize   	*/	ClassInitialize,
1249027f4a0Smrg    /* class_part_initialize	*/	NULL,
1259027f4a0Smrg    /* class_inited       	*/	FALSE,
1269027f4a0Smrg    /* initialize	  	*/	Initialize,
1279027f4a0Smrg    /* initialize_hook		*/	NULL,
1289027f4a0Smrg    /* realize		  	*/	XtInheritRealize,
1299027f4a0Smrg    /* actions		  	*/	NULL,
1309027f4a0Smrg    /* num_actions	  	*/	0,
1319027f4a0Smrg    /* resources	  	*/	resources,
1329027f4a0Smrg    /* num_resources	  	*/	XtNumber(resources),
1339027f4a0Smrg    /* xrm_class	  	*/	NULLQUARK,
1349027f4a0Smrg    /* compress_motion	  	*/	TRUE,
1359027f4a0Smrg    /* compress_exposure  	*/	TRUE,
1369027f4a0Smrg    /* compress_enterleave	*/	TRUE,
1379027f4a0Smrg    /* visible_interest	  	*/	FALSE,
1389027f4a0Smrg    /* destroy		  	*/	Destroy,
1399027f4a0Smrg    /* resize		  	*/	Resize,
1409027f4a0Smrg    /* expose		  	*/	Redisplay,
1419027f4a0Smrg    /* set_values	  	*/	SetValues,
1429027f4a0Smrg    /* set_values_hook		*/	NULL,
1439027f4a0Smrg    /* set_values_almost	*/	XtInheritSetValuesAlmost,
1449027f4a0Smrg    /* get_values_hook		*/	NULL,
1459027f4a0Smrg    /* accept_focus	 	*/	NULL,
1469027f4a0Smrg    /* version			*/	XtVersion,
1479027f4a0Smrg    /* callback_private   	*/	NULL,
1489027f4a0Smrg    /* tm_table		   	*/	NULL,
1499027f4a0Smrg    /* query_geometry		*/	QueryGeometry,
1509027f4a0Smrg    /* display_accelerator	*/	XtInheritDisplayAccelerator,
1519027f4a0Smrg    /* extension		*/	NULL
1529027f4a0Smrg  },
1539027f4a0Smrg/* Simple class fields initialization */
1549027f4a0Smrg  {
1559027f4a0Smrg    /* change_sensitive		*/	XtInheritChangeSensitive
1560d6f290aSmrg#ifndef OLDXAW
1570d6f290aSmrg    /* extension		*/	,NULL
1580d6f290aSmrg#endif
1599027f4a0Smrg  },
1609027f4a0Smrg/* UCSLabel class fields initialization */
1619027f4a0Smrg  {
1629027f4a0Smrg    /* ignore 			*/	0
1639027f4a0Smrg  }
1649027f4a0Smrg};
1659027f4a0SmrgWidgetClass ucsLabelWidgetClass = (WidgetClass)&ucsLabelClassRec;
1669027f4a0Smrg/****************************************************************
1679027f4a0Smrg *
1689027f4a0Smrg * Private Procedures
1699027f4a0Smrg *
1709027f4a0Smrg ****************************************************************/
1719027f4a0Smrg
1723a72f200Smrgstatic void ClassInitialize(void)
1739027f4a0Smrg{
1749027f4a0Smrg    XawInitializeWidgetSet();
175fe2ac8d7Smrg    XtAddConverter( XtRString, XtRJustify, XmuCvtStringToJustify,
1769027f4a0Smrg		    (XtConvertArgList)NULL, 0 );
1779027f4a0Smrg}
1789027f4a0Smrg
1799027f4a0Smrgstatic XChar2b *buf2b;
1809027f4a0Smrgstatic int buf2blen = 0;
1819027f4a0Smrg
1823a72f200Smrgstatic void _XawLabelDrawUCS(Display *dpy, Drawable d, GC gc,
1830d6f290aSmrg			     int x, int y, const char *str, int n)
1849027f4a0Smrg{
1850d6f290aSmrg    const char *ep;
1869027f4a0Smrg    unsigned short codepoint;
1879027f4a0Smrg    XChar2b *ptr;
1889027f4a0Smrg
1899027f4a0Smrg    /*
1909027f4a0Smrg     * Convert to UCS2 string on the fly.
1919027f4a0Smrg     */
1929027f4a0Smrg
1939027f4a0Smrg    if (n > buf2blen) {
1949027f4a0Smrg	buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b));
1959027f4a0Smrg	buf2blen = n;
1969027f4a0Smrg    }
1979027f4a0Smrg    ep = str + n;
1989027f4a0Smrg    for (ptr = buf2b; str < ep; ptr++) {
1999027f4a0Smrg        if((str[0]&0x80)==0) {
2009027f4a0Smrg            codepoint=str[0];
2019027f4a0Smrg            str++;
2029027f4a0Smrg        } else if((str[0]&0x20)==0) {
2039027f4a0Smrg            codepoint=(str[0]&0x1F)<<6 | (str[1]&0x3F);
2049027f4a0Smrg            str+=2;
2059027f4a0Smrg        } else if((str[0]&0x10)==0) {
2069027f4a0Smrg            codepoint=(str[0]&0x0F)<<12 | (str[1]&0x3F)<<6 | (str[2]&0x3F);
2079027f4a0Smrg            str+=3;
2089027f4a0Smrg        } else {                    /* wrong UTF-8 */
2099027f4a0Smrg            codepoint=(unsigned)'?';
2109027f4a0Smrg            str++;
2119027f4a0Smrg        }
212376c9fa8Smrg	ptr->byte1 = (codepoint >> 8) & 0xff;
2139027f4a0Smrg	ptr->byte2 = codepoint & 0xff;
2149027f4a0Smrg    }
2159027f4a0Smrg    XDrawString16(dpy, d, gc, x, y, buf2b, ptr - buf2b);
2169027f4a0Smrg}
2179027f4a0Smrg
2189027f4a0Smrgstatic int _XawLabelWidthUCS(
2199027f4a0Smrg    XFontStruct *fs,
2200d6f290aSmrg    const char *str,
2219027f4a0Smrg    int	n
2229027f4a0Smrg)
2239027f4a0Smrg{
2240d6f290aSmrg    const char *ep;
2259027f4a0Smrg    unsigned short codepoint;
2269027f4a0Smrg    XChar2b *ptr;
2279027f4a0Smrg
2289027f4a0Smrg    /*
2299027f4a0Smrg     * Convert to UCS2 string on the fly.
2309027f4a0Smrg     */
2319027f4a0Smrg
2329027f4a0Smrg    if (n > buf2blen) {
2339027f4a0Smrg	buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b));
2349027f4a0Smrg	buf2blen = n;
2359027f4a0Smrg    }
2369027f4a0Smrg    ep = str + n;
2379027f4a0Smrg    for (ptr = buf2b; str < ep; ptr++) {
2389027f4a0Smrg        if((str[0]&0x80)==0) {
2399027f4a0Smrg            codepoint=str[0];
2409027f4a0Smrg            str++;
2419027f4a0Smrg        } else if((str[0]&0x20)==0) {
2429027f4a0Smrg            codepoint=(str[0]&0x1F)<<6 | (str[1]&0x3F);
2439027f4a0Smrg            str+=2;
2449027f4a0Smrg        } else if((str[0]&0x10)==0) {
2459027f4a0Smrg            codepoint=(str[0]&0x0F)<<12 | (str[1]&0x3F)<<6 | (str[2]&0x3F);
2469027f4a0Smrg            str+=3;
2479027f4a0Smrg        } else {                    /* wrong UTF-8 */
2489027f4a0Smrg            codepoint=(unsigned)'?';
2499027f4a0Smrg            str++;
2509027f4a0Smrg        }
251376c9fa8Smrg	ptr->byte1 = (codepoint >> 8) & 0xff;
2529027f4a0Smrg	ptr->byte2 = codepoint & 0xff;
2539027f4a0Smrg    }
2549027f4a0Smrg    return XTextWidth16(fs, buf2b, ptr - buf2b);
2559027f4a0Smrg}
2569027f4a0Smrg
2579027f4a0Smrg#define XTextWidthUCS _XawLabelWidthUCS
2589027f4a0Smrg#define XDrawStringUCS _XawLabelDrawUCS
2599027f4a0Smrg
2609027f4a0Smrg/*
2619027f4a0Smrg * Calculate width and height of displayed text in pixels
2629027f4a0Smrg */
2639027f4a0Smrg
2643a72f200Smrgstatic void SetTextWidthAndHeight(UCSLabelWidget lw)
2659027f4a0Smrg{
2669027f4a0Smrg    XFontStruct	*fs = lw->label.font;
2679027f4a0Smrg
2689027f4a0Smrg    char *nl;
2699027f4a0Smrg
2709027f4a0Smrg    if (lw->label.pixmap != None) {
2719027f4a0Smrg	Window root;
2729027f4a0Smrg	int x, y;
2739027f4a0Smrg	unsigned int width, height, bw, depth;
2749027f4a0Smrg	if (XGetGeometry(XtDisplay(lw), lw->label.pixmap, &root, &x, &y,
2759027f4a0Smrg			 &width, &height, &bw, &depth)) {
2769027f4a0Smrg	    lw->label.label_height = height;
2779027f4a0Smrg	    lw->label.label_width = width;
2789027f4a0Smrg	    lw->label.label_len = depth;
2799027f4a0Smrg	    return;
2809027f4a0Smrg	}
2819027f4a0Smrg    }
2829027f4a0Smrg    if ( lw->simple.international == True ) {
2839027f4a0Smrg
2849027f4a0Smrg      XFontSet	fset = lw->label.fontset;
2859027f4a0Smrg      XFontSetExtents *ext = XExtentsOfFontSet(fset);
2869027f4a0Smrg
2879027f4a0Smrg      lw->label.label_height = ext->max_ink_extent.height;
2889027f4a0Smrg      if (lw->label.label == NULL) {
2899027f4a0Smrg	  lw->label.label_len = 0;
2909027f4a0Smrg	  lw->label.label_width = 0;
2919027f4a0Smrg      }
2929027f4a0Smrg      else if ((nl = index(lw->label.label, '\n')) != NULL) {
2930d6f290aSmrg	  const char *label;
2949027f4a0Smrg	  lw->label.label_len = MULTI_LINE_LABEL;
2959027f4a0Smrg	  lw->label.label_width = 0;
2969027f4a0Smrg	  for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) {
2979027f4a0Smrg	      int width = XmbTextEscapement(fset, label, (int)(nl - label));
2989027f4a0Smrg
2999027f4a0Smrg	      if (width > (int)lw->label.label_width)
3009027f4a0Smrg		  lw->label.label_width = width;
3019027f4a0Smrg	      label = nl + 1;
3029027f4a0Smrg	      if (*label)
3039027f4a0Smrg		  lw->label.label_height +=
3049027f4a0Smrg		      ext->max_ink_extent.height;
3059027f4a0Smrg	  }
3069027f4a0Smrg	  if (*label) {
3079027f4a0Smrg	      int width = XmbTextEscapement(fset, label, strlen(label));
3089027f4a0Smrg
3099027f4a0Smrg	      if (width > (int) lw->label.label_width)
3109027f4a0Smrg		  lw->label.label_width = width;
3119027f4a0Smrg	  }
3129027f4a0Smrg      } else {
3139027f4a0Smrg	  lw->label.label_len = strlen(lw->label.label);
3149027f4a0Smrg	  lw->label.label_width =
3159027f4a0Smrg	      XmbTextEscapement(fset, lw->label.label, (int) lw->label.label_len);
3169027f4a0Smrg      }
3179027f4a0Smrg
3189027f4a0Smrg    } else {
3199027f4a0Smrg
3209027f4a0Smrg        lw->label.label_height = fs->max_bounds.ascent + fs->max_bounds.descent;
3219027f4a0Smrg        if (lw->label.label == NULL) {
3229027f4a0Smrg            lw->label.label_len = 0;
3239027f4a0Smrg            lw->label.label_width = 0;
3249027f4a0Smrg        }
3259027f4a0Smrg        else if ((nl = index(lw->label.label, '\n')) != NULL) {
3260d6f290aSmrg	    const char *label;
3279027f4a0Smrg            lw->label.label_len = MULTI_LINE_LABEL;
3289027f4a0Smrg            lw->label.label_width = 0;
3299027f4a0Smrg            for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) {
3309027f4a0Smrg	        int width;
3319027f4a0Smrg
3329027f4a0Smrg	        if (lw->label.encoding == XawTextEncodingChar2b)
333376c9fa8Smrg		    width = XTextWidth16(fs, (XChar2b *)label, (int)(nl - label)/2);
3349027f4a0Smrg                else if (lw->label.encoding == XawTextEncodingUCS)
3359027f4a0Smrg		    width = XTextWidthUCS(fs, label, nl - label);
3369027f4a0Smrg	        else
3379027f4a0Smrg		    width = XTextWidth(fs, label, (int)(nl - label));
3389027f4a0Smrg	        if (width > (int)lw->label.label_width)
3399027f4a0Smrg		    lw->label.label_width = width;
3409027f4a0Smrg	        label = nl + 1;
3419027f4a0Smrg	        if (*label)
3429027f4a0Smrg		    lw->label.label_height +=
3439027f4a0Smrg		        fs->max_bounds.ascent + fs->max_bounds.descent;
3449027f4a0Smrg	    }
3459027f4a0Smrg	    if (*label) {
3469027f4a0Smrg	        int width;
3479027f4a0Smrg
3489027f4a0Smrg	        if (lw->label.encoding == XawTextEncodingChar2b)
349376c9fa8Smrg		    width = XTextWidth16(fs, (XChar2b *)label, (int)strlen(label)/2);
3509027f4a0Smrg                else if (lw->label.encoding == XawTextEncodingUCS)
3519027f4a0Smrg		    width = XTextWidthUCS(fs, label, strlen(label));
3529027f4a0Smrg	        else
3539027f4a0Smrg		    width = XTextWidth(fs, label, strlen(label));
3549027f4a0Smrg	        if (width > (int) lw->label.label_width)
3559027f4a0Smrg		    lw->label.label_width = width;
3569027f4a0Smrg	    }
3579027f4a0Smrg        } else {
3589027f4a0Smrg	    lw->label.label_len = strlen(lw->label.label);
3599027f4a0Smrg	    if (lw->label.encoding == XawTextEncodingChar2b)
3609027f4a0Smrg	        lw->label.label_width =
361376c9fa8Smrg		    XTextWidth16(fs, (XChar2b *)lw->label.label,
3629027f4a0Smrg			         (int) lw->label.label_len/2);
3639027f4a0Smrg            else if (lw->label.encoding == XawTextEncodingUCS)
3649027f4a0Smrg		lw->label.label_width = XTextWidthUCS(fs, lw->label.label,
3659027f4a0Smrg                                                      lw->label.label_len);
3669027f4a0Smrg	    else
3679027f4a0Smrg	        lw->label.label_width =
3689027f4a0Smrg		    XTextWidth(fs, lw->label.label, (int) lw->label.label_len);
3699027f4a0Smrg        }
3709027f4a0Smrg
3719027f4a0Smrg    }
3729027f4a0Smrg}
3739027f4a0Smrg
3743a72f200Smrgstatic void GetnormalGC(UCSLabelWidget lw)
3759027f4a0Smrg{
3769027f4a0Smrg    XGCValues	values;
3779027f4a0Smrg
3789027f4a0Smrg    values.foreground	= lw->label.foreground;
3799027f4a0Smrg    values.background	= lw->core.background_pixel;
3809027f4a0Smrg    values.font		= lw->label.font->fid;
3819027f4a0Smrg    values.graphics_exposures = False;
3829027f4a0Smrg
3839027f4a0Smrg    if ( lw->simple.international == True )
3849027f4a0Smrg        /* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC. */
3859027f4a0Smrg        lw->label.normal_GC = XtAllocateGC(
3869027f4a0Smrg                (Widget)lw, 0,
3879027f4a0Smrg	(unsigned) GCForeground | GCBackground | GCGraphicsExposures,
3889027f4a0Smrg	&values, GCFont, 0 );
3899027f4a0Smrg    else
3909027f4a0Smrg        lw->label.normal_GC = XtGetGC(
3919027f4a0Smrg	(Widget)lw,
3929027f4a0Smrg	(unsigned) GCForeground | GCBackground | GCFont | GCGraphicsExposures,
3939027f4a0Smrg	&values);
3949027f4a0Smrg}
3959027f4a0Smrg
3963a72f200Smrgstatic void GetgrayGC(UCSLabelWidget lw)
3979027f4a0Smrg{
3989027f4a0Smrg    XGCValues	values;
3999027f4a0Smrg
4009027f4a0Smrg    values.foreground = lw->label.foreground;
4019027f4a0Smrg    values.background = lw->core.background_pixel;
4029027f4a0Smrg    values.font	      = lw->label.font->fid;
4039027f4a0Smrg    values.fill_style = FillTiled;
4049027f4a0Smrg    values.tile       = XmuCreateStippledPixmap(XtScreen((Widget)lw),
405fe2ac8d7Smrg						lw->label.foreground,
4069027f4a0Smrg						lw->core.background_pixel,
4079027f4a0Smrg						lw->core.depth);
4089027f4a0Smrg    values.graphics_exposures = False;
4099027f4a0Smrg
4109027f4a0Smrg    lw->label.stipple = values.tile;
4119027f4a0Smrg    if ( lw->simple.international == True )
4129027f4a0Smrg        /* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC. */
4139027f4a0Smrg        lw->label.gray_GC = XtAllocateGC((Widget)lw,  0,
4149027f4a0Smrg				(unsigned) GCForeground | GCBackground |
4159027f4a0Smrg					   GCTile | GCFillStyle |
4169027f4a0Smrg					   GCGraphicsExposures,
4179027f4a0Smrg				&values, GCFont, 0);
4189027f4a0Smrg    else
419fe2ac8d7Smrg        lw->label.gray_GC = XtGetGC((Widget)lw,
4209027f4a0Smrg				(unsigned) GCForeground | GCBackground |
4219027f4a0Smrg					   GCFont | GCTile | GCFillStyle |
4229027f4a0Smrg					   GCGraphicsExposures,
4239027f4a0Smrg				&values);
4249027f4a0Smrg}
4259027f4a0Smrg
4263a72f200Smrgstatic void compute_bitmap_offsets(UCSLabelWidget lw)
4279027f4a0Smrg{
4289027f4a0Smrg    /*
429fe2ac8d7Smrg     * bitmap will be eventually be displayed at
4309027f4a0Smrg     * (internal_width, internal_height + lbm_y)
4319027f4a0Smrg     */
4329027f4a0Smrg    if (lw->label.lbm_height != 0) {
4339027f4a0Smrg	lw->label.lbm_y = (lw->core.height -
434fe2ac8d7Smrg			  (lw->label.internal_height * 2 +
4359027f4a0Smrg			   lw->label.lbm_height)) / 2;
4369027f4a0Smrg    } else {
4379027f4a0Smrg	lw->label.lbm_y = 0;
4389027f4a0Smrg    }
4399027f4a0Smrg}
4409027f4a0Smrg
4419027f4a0Smrg
4423a72f200Smrgstatic void set_bitmap_info(UCSLabelWidget lw)
4439027f4a0Smrg{
4449027f4a0Smrg    Window root;
4459027f4a0Smrg    int x, y;
4469027f4a0Smrg    unsigned int bw, depth;
4479027f4a0Smrg
4489027f4a0Smrg    if (!(lw->label.left_bitmap &&
4499027f4a0Smrg	  XGetGeometry (XtDisplay(lw), lw->label.left_bitmap, &root, &x, &y,
4509027f4a0Smrg			&lw->label.lbm_width, &lw->label.lbm_height,
4519027f4a0Smrg			&bw, &depth))) {
4529027f4a0Smrg	lw->label.lbm_width = lw->label.lbm_height = 0;
4539027f4a0Smrg    }
4549027f4a0Smrg    compute_bitmap_offsets (lw);
4559027f4a0Smrg}
4569027f4a0Smrg
4579027f4a0Smrg
4589027f4a0Smrg
4599027f4a0Smrg/* ARGSUSED */
4603a72f200Smrgstatic void
4613a72f200SmrgInitialize(Widget request, Widget new, ArgList args, Cardinal *num_args)
4629027f4a0Smrg{
4639027f4a0Smrg    UCSLabelWidget lw = (UCSLabelWidget) new;
4649027f4a0Smrg
465fe2ac8d7Smrg    if (lw->label.label == NULL)
4669027f4a0Smrg        lw->label.label = XtNewString(lw->core.name);
4679027f4a0Smrg    else {
4689027f4a0Smrg        lw->label.label = XtNewString(lw->label.label);
4699027f4a0Smrg    }
4709027f4a0Smrg
4719027f4a0Smrg    GetnormalGC(lw);
4729027f4a0Smrg    GetgrayGC(lw);
4739027f4a0Smrg
4749027f4a0Smrg    SetTextWidthAndHeight(lw);
4759027f4a0Smrg
4769027f4a0Smrg    if (lw->core.height == 0)
4779027f4a0Smrg        lw->core.height = lw->label.label_height +
4789027f4a0Smrg			    2 * lw->label.internal_height;
4799027f4a0Smrg
4809027f4a0Smrg    set_bitmap_info (lw);		/* need core.height */
4819027f4a0Smrg
4829027f4a0Smrg    if (lw->core.width == 0)		/* need label.lbm_width */
4839027f4a0Smrg        lw->core.width = (lw->label.label_width +
4849027f4a0Smrg			    2 * lw->label.internal_width +
4859027f4a0Smrg			    LEFT_OFFSET(lw));
4869027f4a0Smrg
4879027f4a0Smrg    lw->label.label_x = lw->label.label_y = 0;
4889027f4a0Smrg    (*XtClass(new)->core_class.resize) ((Widget)lw);
4899027f4a0Smrg
4909027f4a0Smrg} /* Initialize */
4919027f4a0Smrg
4929027f4a0Smrg/*
4939027f4a0Smrg * Repaint the widget window
4949027f4a0Smrg */
4959027f4a0Smrg
4969027f4a0Smrg/* ARGSUSED */
4973a72f200Smrgstatic void Redisplay(Widget gw, XEvent *event, Region region)
4989027f4a0Smrg{
4999027f4a0Smrg    UCSLabelWidget w = (UCSLabelWidget) gw;
5009027f4a0Smrg    GC gc;
5019027f4a0Smrg
5029027f4a0Smrg    /*
5039027f4a0Smrg     * now we'll see if we need to draw the rest of the label
5049027f4a0Smrg     */
5059027f4a0Smrg    if (region != NULL) {
5069027f4a0Smrg	int x = w->label.label_x;
5079027f4a0Smrg	unsigned int width = w->label.label_width;
5089027f4a0Smrg	if (w->label.lbm_width) {
5099027f4a0Smrg	    if (w->label.label_x > (x = w->label.internal_width))
5109027f4a0Smrg		width += w->label.label_x - x;
5119027f4a0Smrg	}
5129027f4a0Smrg	if (XRectInRegion(region, x, w->label.label_y,
5139027f4a0Smrg			 width, w->label.label_height) == RectangleOut){
5149027f4a0Smrg	    return;
5159027f4a0Smrg	}
5169027f4a0Smrg    }
5179027f4a0Smrg
5189027f4a0Smrg    gc = XtIsSensitive(gw) ? w->label.normal_GC : w->label.gray_GC;
5199027f4a0Smrg#ifdef notdef
5209027f4a0Smrg    if (region != NULL)
5219027f4a0Smrg	XSetRegion(XtDisplay(gw), gc, region);
5229027f4a0Smrg#endif /*notdef*/
5239027f4a0Smrg
5249027f4a0Smrg    if (w->label.pixmap == None) {
5259027f4a0Smrg	int len = w->label.label_len;
5260d6f290aSmrg	const char *label = w->label.label;
5279027f4a0Smrg	Position y = w->label.label_y + w->label.font->max_bounds.ascent;
5289027f4a0Smrg        Position ksy = w->label.label_y;
5299027f4a0Smrg
5309027f4a0Smrg	/* display left bitmap */
5319027f4a0Smrg	if (w->label.left_bitmap && w->label.lbm_width != 0) {
5329027f4a0Smrg	    XCopyPlane (XtDisplay(gw), w->label.left_bitmap, XtWindow(gw), gc,
5339027f4a0Smrg		       0, 0, w->label.lbm_width, w->label.lbm_height,
5349027f4a0Smrg		       (int) w->label.internal_width,
535fe2ac8d7Smrg		       (int) w->label.internal_height + w->label.lbm_y,
5369027f4a0Smrg		       (unsigned long) 1L);
5379027f4a0Smrg	}
5389027f4a0Smrg
5399027f4a0Smrg        if ( w->simple.international == True ) {
5409027f4a0Smrg
5419027f4a0Smrg	    XFontSetExtents *ext = XExtentsOfFontSet(w->label.fontset);
5429027f4a0Smrg
5439027f4a0Smrg	    ksy += abs(ext->max_ink_extent.y);
5449027f4a0Smrg
5459027f4a0Smrg            if (len == MULTI_LINE_LABEL) {
5469027f4a0Smrg	        char *nl;
5479027f4a0Smrg	        while ((nl = index(label, '\n')) != NULL) {
5489027f4a0Smrg	            XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, gc,
5499027f4a0Smrg	  		        w->label.label_x, ksy, label, (int)(nl - label));
5509027f4a0Smrg	            ksy += ext->max_ink_extent.height;
5519027f4a0Smrg	            label = nl + 1;
5529027f4a0Smrg	        }
5539027f4a0Smrg	        len = strlen(label);
5549027f4a0Smrg            }
5559027f4a0Smrg            if (len)
5569027f4a0Smrg	        XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, gc,
5579027f4a0Smrg			      w->label.label_x, ksy, label, len);
5589027f4a0Smrg
5599027f4a0Smrg        } else { /*international false, so use R5 routine */
5609027f4a0Smrg
5619027f4a0Smrg	    if (len == MULTI_LINE_LABEL) {
5629027f4a0Smrg	        char *nl;
5639027f4a0Smrg	        while ((nl = index(label, '\n')) != NULL) {
5649027f4a0Smrg		    if (w->label.encoding == XawTextEncodingChar2b)
5659027f4a0Smrg		        XDrawString16(XtDisplay(gw), XtWindow(gw), gc,
5669027f4a0Smrg				 		w->label.label_x, y,
567376c9fa8Smrg                                      (XChar2b *)label, (int)(nl - label)/2);
5689027f4a0Smrg                    else if (w->label.encoding == XawTextEncodingUCS)
5699027f4a0Smrg		        XDrawStringUCS(XtDisplay(gw), XtWindow(gw), gc,
5709027f4a0Smrg			       		w->label.label_x, y, label, (int)(nl - label));
5719027f4a0Smrg		    else
5729027f4a0Smrg		        XDrawString(XtDisplay(gw), XtWindow(gw), gc,
5739027f4a0Smrg			       		w->label.label_x, y, label, (int)(nl - label));
574fe2ac8d7Smrg		    y += w->label.font->max_bounds.ascent +
5759027f4a0Smrg		                        w->label.font->max_bounds.descent;
5769027f4a0Smrg		    label = nl + 1;
5779027f4a0Smrg	        }
5789027f4a0Smrg	        len = strlen(label);
5799027f4a0Smrg	    }
5809027f4a0Smrg	    if (len) {
5819027f4a0Smrg	        if (w->label.encoding == XawTextEncodingChar2b)
5829027f4a0Smrg		    XDrawString16(XtDisplay(gw), XtWindow(gw), gc,
583376c9fa8Smrg			     w->label.label_x, y, (XChar2b *)label, len/2);
5849027f4a0Smrg                else if (w->label.encoding == XawTextEncodingUCS)
5859027f4a0Smrg                    XDrawStringUCS(XtDisplay(gw), XtWindow(gw), gc,
5869027f4a0Smrg                             w->label.label_x, y, label, len);
5879027f4a0Smrg	        else
5889027f4a0Smrg		    XDrawString(XtDisplay(gw), XtWindow(gw), gc,
5899027f4a0Smrg			   w->label.label_x, y, label, len);
5909027f4a0Smrg	    }
5919027f4a0Smrg
5929027f4a0Smrg        } /*endif international*/
5939027f4a0Smrg
5949027f4a0Smrg    } else if (w->label.label_len == 1) { /* depth */
5959027f4a0Smrg	XCopyPlane(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc,
5969027f4a0Smrg				0, 0, w->label.label_width, w->label.label_height,
5979027f4a0Smrg				w->label.label_x, w->label.label_y, 1L);
5989027f4a0Smrg    } else {
5999027f4a0Smrg	XCopyArea(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc,
6009027f4a0Smrg				0, 0, w->label.label_width, w->label.label_height,
6019027f4a0Smrg				w->label.label_x, w->label.label_y);
6029027f4a0Smrg    }
6039027f4a0Smrg
6049027f4a0Smrg#ifdef notdef
6059027f4a0Smrg    if (region != NULL)
6069027f4a0Smrg	XSetClipMask(XtDisplay(gw), gc, (Pixmap)None);
6079027f4a0Smrg#endif /* notdef */
6089027f4a0Smrg}
6099027f4a0Smrg
6103a72f200Smrgstatic void _Reposition(UCSLabelWidget lw, Dimension width, Dimension height,
6113a72f200Smrg			Position *dx, Position *dy)
6129027f4a0Smrg{
6139027f4a0Smrg    Position newPos;
6149027f4a0Smrg    Position leftedge = lw->label.internal_width + LEFT_OFFSET(lw);
6159027f4a0Smrg
6169027f4a0Smrg    switch (lw->label.justify) {
6179027f4a0Smrg
6189027f4a0Smrg	case XtJustifyLeft   :
6199027f4a0Smrg	    newPos = leftedge;
6209027f4a0Smrg	    break;
6219027f4a0Smrg
6229027f4a0Smrg	case XtJustifyRight  :
6239027f4a0Smrg	    newPos = width -
6249027f4a0Smrg		(lw->label.label_width + lw->label.internal_width);
6259027f4a0Smrg	    break;
6269027f4a0Smrg
6279027f4a0Smrg	case XtJustifyCenter :
6289027f4a0Smrg	default:
6299027f4a0Smrg	    newPos = (int)(width - lw->label.label_width) / 2;
6309027f4a0Smrg	    break;
6319027f4a0Smrg    }
6329027f4a0Smrg    if (newPos < (Position)leftedge)
6339027f4a0Smrg	newPos = leftedge;
6349027f4a0Smrg    *dx = newPos - lw->label.label_x;
6359027f4a0Smrg    lw->label.label_x = newPos;
6369027f4a0Smrg    *dy = (newPos = (int)(height - lw->label.label_height) / 2)
6379027f4a0Smrg	  - lw->label.label_y;
6389027f4a0Smrg    lw->label.label_y = newPos;
6399027f4a0Smrg    return;
6409027f4a0Smrg}
6419027f4a0Smrg
6423a72f200Smrgstatic void Resize(Widget w)
6439027f4a0Smrg{
6449027f4a0Smrg    UCSLabelWidget lw = (UCSLabelWidget)w;
6459027f4a0Smrg    Position dx, dy;
6469027f4a0Smrg
6479027f4a0Smrg    _Reposition(lw, w->core.width, w->core.height, &dx, &dy);
6489027f4a0Smrg    compute_bitmap_offsets (lw);
6499027f4a0Smrg}
6509027f4a0Smrg
6519027f4a0Smrg/*
6529027f4a0Smrg * Set specified arguments into widget
6539027f4a0Smrg */
6549027f4a0Smrg
6559027f4a0Smrg#define PIXMAP 0
6569027f4a0Smrg#define WIDTH 1
6579027f4a0Smrg#define HEIGHT 2
6589027f4a0Smrg#define NUM_CHECKS 3
6599027f4a0Smrg
6603a72f200Smrgstatic Boolean
6613a72f200SmrgSetValues(Widget current, Widget request, Widget new,
6623a72f200Smrg	  ArgList args, Cardinal *num_args)
6639027f4a0Smrg{
6649027f4a0Smrg    UCSLabelWidget curlw = (UCSLabelWidget) current;
6659027f4a0Smrg    UCSLabelWidget reqlw = (UCSLabelWidget) request;
6669027f4a0Smrg    UCSLabelWidget newlw = (UCSLabelWidget) new;
6670d6f290aSmrg    unsigned int i;
6689027f4a0Smrg    Boolean was_resized = False, redisplay = False, checks[NUM_CHECKS];
6699027f4a0Smrg
6709027f4a0Smrg    for (i = 0; i < NUM_CHECKS; i++)
6719027f4a0Smrg	checks[i] = FALSE;
6729027f4a0Smrg
6739027f4a0Smrg    for (i = 0; i < *num_args; i++) {
6749027f4a0Smrg	if (streq(XtNbitmap, args[i].name))
6759027f4a0Smrg	    checks[PIXMAP] = TRUE;
6769027f4a0Smrg	if (streq(XtNwidth, args[i].name))
6779027f4a0Smrg	    checks[WIDTH] = TRUE;
6789027f4a0Smrg	if (streq(XtNheight, args[i].name))
6799027f4a0Smrg	    checks[HEIGHT] = TRUE;
6809027f4a0Smrg    }
6819027f4a0Smrg
6829027f4a0Smrg    if (newlw->label.label == NULL) {
6839027f4a0Smrg	newlw->label.label = newlw->core.name;
6849027f4a0Smrg    }
6859027f4a0Smrg
6869027f4a0Smrg    /*
6879027f4a0Smrg     * resize on bitmap change
6889027f4a0Smrg     */
6899027f4a0Smrg    if (curlw->label.left_bitmap != newlw->label.left_bitmap) {
6909027f4a0Smrg	was_resized = True;
6919027f4a0Smrg    }
6929027f4a0Smrg
6939027f4a0Smrg    if (curlw->label.encoding != newlw->label.encoding)
6949027f4a0Smrg	was_resized = True;
6959027f4a0Smrg
6969027f4a0Smrg    if ( (curlw->label.fontset != newlw->label.fontset) &&
6979027f4a0Smrg					 curlw->simple.international ){
6989027f4a0Smrg	was_resized = True;
6999027f4a0Smrg    }
7009027f4a0Smrg    if (curlw->label.label != newlw->label.label) {
7019027f4a0Smrg        if (curlw->label.label != curlw->core.name)
7029027f4a0Smrg	    XtFree( (char *)curlw->label.label );
7039027f4a0Smrg
7049027f4a0Smrg	if (newlw->label.label != newlw->core.name) {
7059027f4a0Smrg	    newlw->label.label = XtNewString( newlw->label.label );
7069027f4a0Smrg	}
7079027f4a0Smrg	was_resized = True;
7089027f4a0Smrg    }
7099027f4a0Smrg
7109027f4a0Smrg    if (was_resized || (curlw->label.font != newlw->label.font) ||
7119027f4a0Smrg	(curlw->label.justify != newlw->label.justify) || checks[PIXMAP]) {
7129027f4a0Smrg
7139027f4a0Smrg	SetTextWidthAndHeight(newlw);
7149027f4a0Smrg	was_resized = True;
7159027f4a0Smrg    }
7169027f4a0Smrg
7179027f4a0Smrg    /* recalculate the window size if something has changed. */
7189027f4a0Smrg    if (newlw->label.resize && was_resized) {
7199027f4a0Smrg	if ((curlw->core.height == reqlw->core.height) && !checks[HEIGHT])
7209027f4a0Smrg	    newlw->core.height = (newlw->label.label_height +
7219027f4a0Smrg				    2 * newlw->label.internal_height);
7229027f4a0Smrg
7239027f4a0Smrg	set_bitmap_info (newlw);
7249027f4a0Smrg
7259027f4a0Smrg	if ((curlw->core.width == reqlw->core.width) && !checks[WIDTH])
7269027f4a0Smrg	    newlw->core.width = (newlw->label.label_width +
7279027f4a0Smrg				    LEFT_OFFSET(newlw) +
7289027f4a0Smrg				    2 * newlw->label.internal_width);
7299027f4a0Smrg    }
7309027f4a0Smrg
7319027f4a0Smrg    if (curlw->label.foreground		!= newlw->label.foreground
7329027f4a0Smrg	|| curlw->core.background_pixel != newlw->core.background_pixel
7339027f4a0Smrg	|| curlw->label.font->fid	!= newlw->label.font->fid	  ) {
7349027f4a0Smrg
7359027f4a0Smrg        /* The Fontset is not in the GC - don't make a new GC if FS changes! */
7369027f4a0Smrg
7379027f4a0Smrg	XtReleaseGC(new, curlw->label.normal_GC);
7389027f4a0Smrg	XtReleaseGC(new, curlw->label.gray_GC);
7399027f4a0Smrg	XmuReleaseStippledPixmap( XtScreen(current), curlw->label.stipple );
7409027f4a0Smrg	GetnormalGC(newlw);
7419027f4a0Smrg	GetgrayGC(newlw);
7429027f4a0Smrg	redisplay = True;
7439027f4a0Smrg    }
7449027f4a0Smrg
7459027f4a0Smrg    if ((curlw->label.internal_width != newlw->label.internal_width)
7469027f4a0Smrg        || (curlw->label.internal_height != newlw->label.internal_height)
7479027f4a0Smrg	|| was_resized) {
7489027f4a0Smrg	/* Resize() will be called if geometry changes succeed */
7499027f4a0Smrg	Position dx, dy;
7509027f4a0Smrg	_Reposition(newlw, curlw->core.width, curlw->core.height, &dx, &dy);
7519027f4a0Smrg    }
7529027f4a0Smrg
7539027f4a0Smrg    return was_resized || redisplay ||
7549027f4a0Smrg	   XtIsSensitive(current) != XtIsSensitive(new);
7559027f4a0Smrg}
7569027f4a0Smrg
7573a72f200Smrgstatic void Destroy(Widget w)
7589027f4a0Smrg{
7599027f4a0Smrg    UCSLabelWidget lw = (UCSLabelWidget)w;
7609027f4a0Smrg
7619027f4a0Smrg    if ( lw->label.label != lw->core.name )
7620d6f290aSmrg	XtFree( (char *) lw->label.label );
7639027f4a0Smrg    XtReleaseGC( w, lw->label.normal_GC );
7649027f4a0Smrg    XtReleaseGC( w, lw->label.gray_GC);
7659027f4a0Smrg    XmuReleaseStippledPixmap( XtScreen(w), lw->label.stipple );
7669027f4a0Smrg}
7679027f4a0Smrg
7689027f4a0Smrg
7693a72f200Smrgstatic XtGeometryResult
7703a72f200SmrgQueryGeometry(Widget w, XtWidgetGeometry *intended, XtWidgetGeometry *preferred)
7719027f4a0Smrg{
7729027f4a0Smrg    UCSLabelWidget lw = (UCSLabelWidget)w;
7739027f4a0Smrg
7749027f4a0Smrg    preferred->request_mode = CWWidth | CWHeight;
775fe2ac8d7Smrg    preferred->width = (lw->label.label_width +
7769027f4a0Smrg			    2 * lw->label.internal_width +
7779027f4a0Smrg			    LEFT_OFFSET(lw));
778fe2ac8d7Smrg    preferred->height = lw->label.label_height +
7799027f4a0Smrg			    2 * lw->label.internal_height;
7809027f4a0Smrg    if (  ((intended->request_mode & (CWWidth | CWHeight))
7819027f4a0Smrg	   	== (CWWidth | CWHeight)) &&
7829027f4a0Smrg	  intended->width == preferred->width &&
7839027f4a0Smrg	  intended->height == preferred->height)
7849027f4a0Smrg	return XtGeometryYes;
7859027f4a0Smrg    else if (preferred->width == w->core.width &&
7869027f4a0Smrg	     preferred->height == w->core.height)
7879027f4a0Smrg	return XtGeometryNo;
7889027f4a0Smrg    else
7899027f4a0Smrg	return XtGeometryAlmost;
7909027f4a0Smrg}
791