#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xos.h>
#include <X11/Xaw/XawInit.h>
#include "ULabelP.h"
#include <X11/Xmu/Converters.h>
#include <X11/Xmu/Drawing.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#define streq(a,b) (strcmp( (a), (b) ) == 0)
#define MULTI_LINE_LABEL 32767
#ifdef CRAY
#define WORD64
#endif
#define offset(field) XtOffsetOf(UCSLabelRec, field)
static XtResource resources[] = {
{XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
offset(label.foreground), XtRString, XtDefaultForeground},
{XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
offset(label.font),XtRString, XtDefaultFont},
{XtNfontSet, XtCFontSet, XtRFontSet, sizeof(XFontSet ),
offset(label.fontset),XtRString, XtDefaultFontSet},
{XtNlabel, XtCLabel, XtRString, sizeof(String),
offset(label.label), XtRString, NULL},
{XtNencoding, XtCEncoding, XtRUnsignedChar, sizeof(unsigned char),
offset(label.encoding), XtRImmediate, (XtPointer)XawTextEncoding8bit},
{XtNjustify, XtCJustify, XtRJustify, sizeof(XtJustify),
offset(label.justify), XtRImmediate, (XtPointer)XtJustifyCenter},
{XtNinternalWidth, XtCWidth, XtRDimension, sizeof(Dimension),
offset(label.internal_width), XtRImmediate, (XtPointer)4},
{XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension),
offset(label.internal_height), XtRImmediate, (XtPointer)2},
{XtNleftBitmap, XtCLeftBitmap, XtRBitmap, sizeof(Pixmap),
offset(label.left_bitmap), XtRImmediate, (XtPointer) None},
{XtNbitmap, XtCPixmap, XtRBitmap, sizeof(Pixmap),
offset(label.pixmap), XtRImmediate, (XtPointer)None},
{XtNresize, XtCResize, XtRBoolean, sizeof(Boolean),
offset(label.resize), XtRImmediate, (XtPointer)True},
};
#undef offset
static void Initialize();
static void Resize();
static void Redisplay();
static Boolean SetValues();
static void ClassInitialize();
static void Destroy();
static XtGeometryResult QueryGeometry();
UCSLabelClassRec ucsLabelClassRec = {
{
(WidgetClass) &simpleClassRec,
"UCSLabel",
sizeof(UCSLabelRec),
ClassInitialize,
NULL,
FALSE,
Initialize,
NULL,
XtInheritRealize,
NULL,
0,
resources,
XtNumber(resources),
NULLQUARK,
TRUE,
TRUE,
TRUE,
FALSE,
Destroy,
Resize,
Redisplay,
SetValues,
NULL,
XtInheritSetValuesAlmost,
NULL,
NULL,
XtVersion,
NULL,
NULL,
QueryGeometry,
XtInheritDisplayAccelerator,
NULL
},
{
XtInheritChangeSensitive
},
{
0
}
};
WidgetClass ucsLabelWidgetClass = (WidgetClass)&ucsLabelClassRec;
static void ClassInitialize()
{
XawInitializeWidgetSet();
XtAddConverter( XtRString, XtRJustify, XmuCvtStringToJustify,
(XtConvertArgList)NULL, 0 );
}
static XChar2b *buf2b;
static int buf2blen = 0;
#ifndef WORD64
#define TXT16 XChar2b
#else
#define TXT16 char
static int _XawLabelWidth16(fs, str, n)
XFontStruct *fs;
char *str;
int n;
{
int i;
XChar2b *ptr;
if (n > buf2blen) {
buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b));
buf2blen = n;
}
for (ptr = buf2b, i = n; --i >= 0; ptr++) {
ptr->byte1 = *str++;
ptr->byte2 = *str++;
}
return XTextWidth16(fs, buf2b, n);
}
static void _XawLabelDraw16(dpy, d, gc, x, y, str, n)
Display *dpy;
Drawable d;
GC gc;
int x, y;
char *str;
int n;
{
int i;
XChar2b *ptr;
if (n > buf2blen) {
buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b));
buf2blen = n;
}
for (ptr = buf2b, i = n; --i >= 0; ptr++) {
ptr->byte1 = *str++;
ptr->byte2 = *str++;
}
XDrawString16(dpy, d, gc, x, y, buf2b, n);
}
#define XTextWidth16 _XawLabelWidth16
#define XDrawString16 _XawLabelDraw16
#endif
static void _XawLabelDrawUCS(dpy, d, gc, x, y, str, n)
Display *dpy;
Drawable d;
GC gc;
int x, y;
char *str;
int n;
{
char *ep;
unsigned short codepoint;
XChar2b *ptr;
if (n > buf2blen) {
buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b));
buf2blen = n;
}
ep = str + n;
for (ptr = buf2b; str < ep; ptr++) {
if((str[0]&0x80)==0) {
codepoint=str[0];
str++;
} else if((str[0]&0x20)==0) {
codepoint=(str[0]&0x1F)<<6 | (str[1]&0x3F);
str+=2;
} else if((str[0]&0x10)==0) {
codepoint=(str[0]&0x0F)<<12 | (str[1]&0x3F)<<6 | (str[2]&0x3F);
str+=3;
} else {
codepoint=(unsigned)'?';
str++;
}
ptr->byte1 = (codepoint >> 8) & 0xff;;
ptr->byte2 = codepoint & 0xff;
}
XDrawString16(dpy, d, gc, x, y, buf2b, ptr - buf2b);
}
static int _XawLabelWidthUCS(
XFontStruct *fs,
char *str,
int n
)
{
char *ep;
unsigned short codepoint;
XChar2b *ptr;
if (n > buf2blen) {
buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b));
buf2blen = n;
}
ep = str + n;
for (ptr = buf2b; str < ep; ptr++) {
if((str[0]&0x80)==0) {
codepoint=str[0];
str++;
} else if((str[0]&0x20)==0) {
codepoint=(str[0]&0x1F)<<6 | (str[1]&0x3F);
str+=2;
} else if((str[0]&0x10)==0) {
codepoint=(str[0]&0x0F)<<12 | (str[1]&0x3F)<<6 | (str[2]&0x3F);
str+=3;
} else {
codepoint=(unsigned)'?';
str++;
}
ptr->byte1 = (codepoint >> 8) & 0xff;;
ptr->byte2 = codepoint & 0xff;
}
return XTextWidth16(fs, buf2b, ptr - buf2b);
}
#define XTextWidthUCS _XawLabelWidthUCS
#define XDrawStringUCS _XawLabelDrawUCS
static void SetTextWidthAndHeight(lw)
UCSLabelWidget lw;
{
XFontStruct *fs = lw->label.font;
char *nl;
if (lw->label.pixmap != None) {
Window root;
int x, y;
unsigned int width, height, bw, depth;
if (XGetGeometry(XtDisplay(lw), lw->label.pixmap, &root, &x, &y,
&width, &height, &bw, &depth)) {
lw->label.label_height = height;
lw->label.label_width = width;
lw->label.label_len = depth;
return;
}
}
if ( lw->simple.international == True ) {
XFontSet fset = lw->label.fontset;
XFontSetExtents *ext = XExtentsOfFontSet(fset);
lw->label.label_height = ext->max_ink_extent.height;
if (lw->label.label == NULL) {
lw->label.label_len = 0;
lw->label.label_width = 0;
}
else if ((nl = index(lw->label.label, '\n')) != NULL) {
char *label;
lw->label.label_len = MULTI_LINE_LABEL;
lw->label.label_width = 0;
for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) {
int width = XmbTextEscapement(fset, label, (int)(nl - label));
if (width > (int)lw->label.label_width)
lw->label.label_width = width;
label = nl + 1;
if (*label)
lw->label.label_height +=
ext->max_ink_extent.height;
}
if (*label) {
int width = XmbTextEscapement(fset, label, strlen(label));
if (width > (int) lw->label.label_width)
lw->label.label_width = width;
}
} else {
lw->label.label_len = strlen(lw->label.label);
lw->label.label_width =
XmbTextEscapement(fset, lw->label.label, (int) lw->label.label_len);
}
} else {
lw->label.label_height = fs->max_bounds.ascent + fs->max_bounds.descent;
if (lw->label.label == NULL) {
lw->label.label_len = 0;
lw->label.label_width = 0;
}
else if ((nl = index(lw->label.label, '\n')) != NULL) {
char *label;
lw->label.label_len = MULTI_LINE_LABEL;
lw->label.label_width = 0;
for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) {
int width;
if (lw->label.encoding == XawTextEncodingChar2b)
width = XTextWidth16(fs, (TXT16*)label, (int)(nl - label)/2);
else if (lw->label.encoding == XawTextEncodingUCS)
width = XTextWidthUCS(fs, label, nl - label);
else
width = XTextWidth(fs, label, (int)(nl - label));
if (width > (int)lw->label.label_width)
lw->label.label_width = width;
label = nl + 1;
if (*label)
lw->label.label_height +=
fs->max_bounds.ascent + fs->max_bounds.descent;
}
if (*label) {
int width;
if (lw->label.encoding == XawTextEncodingChar2b)
width = XTextWidth16(fs, (TXT16*)label, (int)strlen(label)/2);
else if (lw->label.encoding == XawTextEncodingUCS)
width = XTextWidthUCS(fs, label, strlen(label));
else
width = XTextWidth(fs, label, strlen(label));
if (width > (int) lw->label.label_width)
lw->label.label_width = width;
}
} else {
lw->label.label_len = strlen(lw->label.label);
if (lw->label.encoding == XawTextEncodingChar2b)
lw->label.label_width =
XTextWidth16(fs, (TXT16*)lw->label.label,
(int) lw->label.label_len/2);
else if (lw->label.encoding == XawTextEncodingUCS)
lw->label.label_width = XTextWidthUCS(fs, lw->label.label,
lw->label.label_len);
else
lw->label.label_width =
XTextWidth(fs, lw->label.label, (int) lw->label.label_len);
}
}
}
static void GetnormalGC(lw)
UCSLabelWidget lw;
{
XGCValues values;
values.foreground = lw->label.foreground;
values.background = lw->core.background_pixel;
values.font = lw->label.font->fid;
values.graphics_exposures = False;
if ( lw->simple.international == True )
lw->label.normal_GC = XtAllocateGC(
(Widget)lw, 0,
(unsigned) GCForeground | GCBackground | GCGraphicsExposures,
&values, GCFont, 0 );
else
lw->label.normal_GC = XtGetGC(
(Widget)lw,
(unsigned) GCForeground | GCBackground | GCFont | GCGraphicsExposures,
&values);
}
static void GetgrayGC(lw)
UCSLabelWidget lw;
{
XGCValues values;
values.foreground = lw->label.foreground;
values.background = lw->core.background_pixel;
values.font = lw->label.font->fid;
values.fill_style = FillTiled;
values.tile = XmuCreateStippledPixmap(XtScreen((Widget)lw),
lw->label.foreground,
lw->core.background_pixel,
lw->core.depth);
values.graphics_exposures = False;
lw->label.stipple = values.tile;
if ( lw->simple.international == True )
lw->label.gray_GC = XtAllocateGC((Widget)lw, 0,
(unsigned) GCForeground | GCBackground |
GCTile | GCFillStyle |
GCGraphicsExposures,
&values, GCFont, 0);
else
lw->label.gray_GC = XtGetGC((Widget)lw,
(unsigned) GCForeground | GCBackground |
GCFont | GCTile | GCFillStyle |
GCGraphicsExposures,
&values);
}
static void compute_bitmap_offsets (lw)
UCSLabelWidget lw;
{
if (lw->label.lbm_height != 0) {
lw->label.lbm_y = (lw->core.height -
(lw->label.internal_height * 2 +
lw->label.lbm_height)) / 2;
} else {
lw->label.lbm_y = 0;
}
}
static void set_bitmap_info (lw)
UCSLabelWidget lw;
{
Window root;
int x, y;
unsigned int bw, depth;
if (!(lw->label.left_bitmap &&
XGetGeometry (XtDisplay(lw), lw->label.left_bitmap, &root, &x, &y,
&lw->label.lbm_width, &lw->label.lbm_height,
&bw, &depth))) {
lw->label.lbm_width = lw->label.lbm_height = 0;
}
compute_bitmap_offsets (lw);
}
static void Initialize(request, new, args, num_args)
Widget request, new;
ArgList args;
Cardinal *num_args;
{
UCSLabelWidget lw = (UCSLabelWidget) new;
if (lw->label.label == NULL)
lw->label.label = XtNewString(lw->core.name);
else {
lw->label.label = XtNewString(lw->label.label);
}
GetnormalGC(lw);
GetgrayGC(lw);
SetTextWidthAndHeight(lw);
if (lw->core.height == 0)
lw->core.height = lw->label.label_height +
2 * lw->label.internal_height;
set_bitmap_info (lw);
if (lw->core.width == 0)
lw->core.width = (lw->label.label_width +
2 * lw->label.internal_width +
LEFT_OFFSET(lw));
lw->label.label_x = lw->label.label_y = 0;
(*XtClass(new)->core_class.resize) ((Widget)lw);
}
static void Redisplay(gw, event, region)
Widget gw;
XEvent *event;
Region region;
{
UCSLabelWidget w = (UCSLabelWidget) gw;
GC gc;
if (region != NULL) {
int x = w->label.label_x;
unsigned int width = w->label.label_width;
if (w->label.lbm_width) {
if (w->label.label_x > (x = w->label.internal_width))
width += w->label.label_x - x;
}
if (XRectInRegion(region, x, w->label.label_y,
width, w->label.label_height) == RectangleOut){
return;
}
}
gc = XtIsSensitive(gw) ? w->label.normal_GC : w->label.gray_GC;
#ifdef notdef
if (region != NULL)
XSetRegion(XtDisplay(gw), gc, region);
#endif
if (w->label.pixmap == None) {
int len = w->label.label_len;
char *label = w->label.label;
Position y = w->label.label_y + w->label.font->max_bounds.ascent;
Position ksy = w->label.label_y;
if (w->label.left_bitmap && w->label.lbm_width != 0) {
XCopyPlane (XtDisplay(gw), w->label.left_bitmap, XtWindow(gw), gc,
0, 0, w->label.lbm_width, w->label.lbm_height,
(int) w->label.internal_width,
(int) w->label.internal_height + w->label.lbm_y,
(unsigned long) 1L);
}
if ( w->simple.international == True ) {
XFontSetExtents *ext = XExtentsOfFontSet(w->label.fontset);
ksy += abs(ext->max_ink_extent.y);
if (len == MULTI_LINE_LABEL) {
char *nl;
while ((nl = index(label, '\n')) != NULL) {
XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, gc,
w->label.label_x, ksy, label, (int)(nl - label));
ksy += ext->max_ink_extent.height;
label = nl + 1;
}
len = strlen(label);
}
if (len)
XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, gc,
w->label.label_x, ksy, label, len);
} else {
if (len == MULTI_LINE_LABEL) {
char *nl;
while ((nl = index(label, '\n')) != NULL) {
if (w->label.encoding == XawTextEncodingChar2b)
XDrawString16(XtDisplay(gw), XtWindow(gw), gc,
w->label.label_x, y,
(TXT16*)label, (int)(nl - label)/2);
else if (w->label.encoding == XawTextEncodingUCS)
XDrawStringUCS(XtDisplay(gw), XtWindow(gw), gc,
w->label.label_x, y, label, (int)(nl - label));
else
XDrawString(XtDisplay(gw), XtWindow(gw), gc,
w->label.label_x, y, label, (int)(nl - label));
y += w->label.font->max_bounds.ascent +
w->label.font->max_bounds.descent;
label = nl + 1;
}
len = strlen(label);
}
if (len) {
if (w->label.encoding == XawTextEncodingChar2b)
XDrawString16(XtDisplay(gw), XtWindow(gw), gc,
w->label.label_x, y, (TXT16*)label, len/2);
else if (w->label.encoding == XawTextEncodingUCS)
XDrawStringUCS(XtDisplay(gw), XtWindow(gw), gc,
w->label.label_x, y, label, len);
else
XDrawString(XtDisplay(gw), XtWindow(gw), gc,
w->label.label_x, y, label, len);
}
}
} else if (w->label.label_len == 1) {
XCopyPlane(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc,
0, 0, w->label.label_width, w->label.label_height,
w->label.label_x, w->label.label_y, 1L);
} else {
XCopyArea(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc,
0, 0, w->label.label_width, w->label.label_height,
w->label.label_x, w->label.label_y);
}
#ifdef notdef
if (region != NULL)
XSetClipMask(XtDisplay(gw), gc, (Pixmap)None);
#endif
}
static void _Reposition(lw, width, height, dx, dy)
UCSLabelWidget lw;
Dimension width, height;
Position *dx, *dy;
{
Position newPos;
Position leftedge = lw->label.internal_width + LEFT_OFFSET(lw);
switch (lw->label.justify) {
case XtJustifyLeft :
newPos = leftedge;
break;
case XtJustifyRight :
newPos = width -
(lw->label.label_width + lw->label.internal_width);
break;
case XtJustifyCenter :
default:
newPos = (int)(width - lw->label.label_width) / 2;
break;
}
if (newPos < (Position)leftedge)
newPos = leftedge;
*dx = newPos - lw->label.label_x;
lw->label.label_x = newPos;
*dy = (newPos = (int)(height - lw->label.label_height) / 2)
- lw->label.label_y;
lw->label.label_y = newPos;
return;
}
static void Resize(w)
Widget w;
{
UCSLabelWidget lw = (UCSLabelWidget)w;
Position dx, dy;
_Reposition(lw, w->core.width, w->core.height, &dx, &dy);
compute_bitmap_offsets (lw);
}
#define PIXMAP 0
#define WIDTH 1
#define HEIGHT 2
#define NUM_CHECKS 3
static Boolean SetValues(current, request, new, args, num_args)
Widget current, request, new;
ArgList args;
Cardinal *num_args;
{
UCSLabelWidget curlw = (UCSLabelWidget) current;
UCSLabelWidget reqlw = (UCSLabelWidget) request;
UCSLabelWidget newlw = (UCSLabelWidget) new;
int i;
Boolean was_resized = False, redisplay = False, checks[NUM_CHECKS];
for (i = 0; i < NUM_CHECKS; i++)
checks[i] = FALSE;
for (i = 0; i < *num_args; i++) {
if (streq(XtNbitmap, args[i].name))
checks[PIXMAP] = TRUE;
if (streq(XtNwidth, args[i].name))
checks[WIDTH] = TRUE;
if (streq(XtNheight, args[i].name))
checks[HEIGHT] = TRUE;
}
if (newlw->label.label == NULL) {
newlw->label.label = newlw->core.name;
}
if (curlw->label.left_bitmap != newlw->label.left_bitmap) {
was_resized = True;
}
if (curlw->label.encoding != newlw->label.encoding)
was_resized = True;
if ( (curlw->label.fontset != newlw->label.fontset) &&
curlw->simple.international ){
was_resized = True;
}
if (curlw->label.label != newlw->label.label) {
if (curlw->label.label != curlw->core.name)
XtFree( (char *)curlw->label.label );
if (newlw->label.label != newlw->core.name) {
newlw->label.label = XtNewString( newlw->label.label );
}
was_resized = True;
}
if (was_resized || (curlw->label.font != newlw->label.font) ||
(curlw->label.justify != newlw->label.justify) || checks[PIXMAP]) {
SetTextWidthAndHeight(newlw);
was_resized = True;
}
if (newlw->label.resize && was_resized) {
if ((curlw->core.height == reqlw->core.height) && !checks[HEIGHT])
newlw->core.height = (newlw->label.label_height +
2 * newlw->label.internal_height);
set_bitmap_info (newlw);
if ((curlw->core.width == reqlw->core.width) && !checks[WIDTH])
newlw->core.width = (newlw->label.label_width +
LEFT_OFFSET(newlw) +
2 * newlw->label.internal_width);
}
if (curlw->label.foreground != newlw->label.foreground
|| curlw->core.background_pixel != newlw->core.background_pixel
|| curlw->label.font->fid != newlw->label.font->fid ) {
XtReleaseGC(new, curlw->label.normal_GC);
XtReleaseGC(new, curlw->label.gray_GC);
XmuReleaseStippledPixmap( XtScreen(current), curlw->label.stipple );
GetnormalGC(newlw);
GetgrayGC(newlw);
redisplay = True;
}
if ((curlw->label.internal_width != newlw->label.internal_width)
|| (curlw->label.internal_height != newlw->label.internal_height)
|| was_resized) {
Position dx, dy;
_Reposition(newlw, curlw->core.width, curlw->core.height, &dx, &dy);
}
return was_resized || redisplay ||
XtIsSensitive(current) != XtIsSensitive(new);
}
static void Destroy(w)
Widget w;
{
UCSLabelWidget lw = (UCSLabelWidget)w;
if ( lw->label.label != lw->core.name )
XtFree( lw->label.label );
XtReleaseGC( w, lw->label.normal_GC );
XtReleaseGC( w, lw->label.gray_GC);
XmuReleaseStippledPixmap( XtScreen(w), lw->label.stipple );
}
static XtGeometryResult QueryGeometry(w, intended, preferred)
Widget w;
XtWidgetGeometry *intended, *preferred;
{
UCSLabelWidget lw = (UCSLabelWidget)w;
preferred->request_mode = CWWidth | CWHeight;
preferred->width = (lw->label.label_width +
2 * lw->label.internal_width +
LEFT_OFFSET(lw));
preferred->height = lw->label.label_height +
2 * lw->label.internal_height;
if ( ((intended->request_mode & (CWWidth | CWHeight))
== (CWWidth | CWHeight)) &&
intended->width == preferred->width &&
intended->height == preferred->height)
return XtGeometryYes;
else if (preferred->width == w->core.width &&
preferred->height == w->core.height)
return XtGeometryNo;
else
return XtGeometryAlmost;
}