#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xos.h>
#include <X11/Xmu/Drawing.h>
#include <X11/Xmu/SysUtil.h>
#include <X11/Xaw/Cardinals.h>
#include <X11/Xaw/SimpleMenu.h>
#include <X11/Xaw/SmeBSBP.h>
#include <X11/Xaw/XawInit.h>
#include "Private.h"
#define ONE_HUNDRED 100
static void FlipColors(Widget);
static void XawSmeBSBClassInitialize(void);
static void XawSmeBSBInitialize(Widget, Widget, ArgList, Cardinal*);
static void XawSmeBSBDestroy(Widget);
static XtGeometryResult XawSmeBSBQueryGeometry(Widget, XtWidgetGeometry*,
XtWidgetGeometry*);
static void XawSmeBSBRedisplay(Widget, XEvent*, Region);
static Boolean XawSmeBSBSetValues(Widget, Widget, Widget,
ArgList, Cardinal*);
static void CreateGCs(Widget);
static void GetBitmapInfo(Widget, Bool);
static void GetDefaultSize(Widget, Dimension*, Dimension*);
static void DestroyGCs(Widget);
static void DrawBitmaps(Widget, GC);
#define offset(field) XtOffsetOf(SmeBSBRec, sme_bsb.field)
static XtResource resources[] = {
{
XtNlabel,
XtCLabel,
XtRString,
sizeof(String),
offset(label),
XtRString,
NULL
},
{
XtNvertSpace,
XtCVertSpace,
XtRInt,
sizeof(int),
offset(vert_space),
XtRImmediate,
(XtPointer)25
},
{
XtNleftBitmap,
XtCLeftBitmap,
XtRBitmap,
sizeof(Pixmap),
offset(left_bitmap),
XtRImmediate,
(XtPointer)None
},
{
XtNjustify,
XtCJustify,
XtRJustify,
sizeof(XtJustify),
offset(justify),
XtRImmediate,
(XtPointer)XtJustifyLeft
},
{
XtNrightBitmap,
XtCRightBitmap,
XtRBitmap,
sizeof(Pixmap),
offset(right_bitmap),
XtRImmediate,
(XtPointer)None
},
{
XtNleftMargin,
XtCHorizontalMargins,
XtRDimension,
sizeof(Dimension),
offset(left_margin),
XtRImmediate,
(XtPointer)4
},
{
XtNrightMargin,
XtCHorizontalMargins,
XtRDimension,
sizeof(Dimension),
offset(right_margin),
XtRImmediate,
(XtPointer)4
},
{
XtNforeground,
XtCForeground,
XtRPixel,
sizeof(Pixel),
offset(foreground),
XtRString,
XtDefaultForeground
},
{
XtNfont,
XtCFont,
XtRFontStruct,
sizeof(XFontStruct*),
offset(font),
XtRString,
XtDefaultFont
},
{
XtNfontSet,
XtCFontSet,
XtRFontSet,
sizeof(XFontSet),
offset(fontset),
XtRString,
XtDefaultFontSet
},
#ifndef OLDXAW
{
XtNmenuName,
XtCMenuName,
XtRString,
sizeof(String),
offset(menu_name),
XtRImmediate,
(XtPointer)NULL
},
#endif
};
#undef offset
#define superclass (&smeClassRec)
SmeBSBClassRec smeBSBClassRec = {
{
(WidgetClass)superclass,
"SmeBSB",
sizeof(SmeBSBRec),
XawSmeBSBClassInitialize,
NULL,
False,
XawSmeBSBInitialize,
NULL,
NULL,
NULL,
0,
resources,
XtNumber(resources),
NULLQUARK,
False,
False,
False,
False,
XawSmeBSBDestroy,
NULL,
XawSmeBSBRedisplay,
XawSmeBSBSetValues,
NULL,
XtInheritSetValuesAlmost,
NULL,
NULL,
XtVersion,
NULL,
NULL,
XawSmeBSBQueryGeometry,
NULL,
NULL,
},
{
FlipColors,
FlipColors,
XtInheritNotify,
NULL,
},
{
NULL,
},
};
WidgetClass smeBSBObjectClass = (WidgetClass)&smeBSBClassRec;
static void
XawSmeBSBClassInitialize(void)
{
XawInitializeWidgetSet();
XtAddConverter(XtRString, XtRJustify, XmuCvtStringToJustify, NULL, 0);
XtSetTypeConverter(XtRJustify, XtRString, XmuCvtJustifyToString,
NULL, 0, XtCacheNone, NULL);
}
static void
XawSmeBSBInitialize(Widget request, Widget cnew,
ArgList args, Cardinal *num_args)
{
SmeBSBObject entry = (SmeBSBObject)cnew;
if (!entry->sme_bsb.font) XtError("Aborting: no font found\n");
if (entry->sme_bsb.label == NULL)
entry->sme_bsb.label = XtName(cnew);
else
entry->sme_bsb.label = XtNewString(entry->sme_bsb.label);
GetDefaultSize(cnew, &entry->rectangle.width, &entry->rectangle.height);
CreateGCs(cnew);
entry->sme_bsb.left_bitmap_width = entry->sme_bsb.left_bitmap_height = 0;
entry->sme_bsb.right_bitmap_width = entry->sme_bsb.right_bitmap_height = 0;
GetBitmapInfo(cnew, True);
GetBitmapInfo(cnew, False);
}
static void
XawSmeBSBDestroy(Widget w)
{
SmeBSBObject entry = (SmeBSBObject)w;
DestroyGCs(w);
if (entry->sme_bsb.label != XtName(w))
XtFree(entry->sme_bsb.label);
}
static void
XawSmeBSBRedisplay(Widget w, XEvent *event, Region region)
{
GC gc;
SmeBSBObject entry = (SmeBSBObject)w;
int font_ascent, font_descent, y_loc;
int fontset_ascent, fontset_descent;
XFontSetExtents *ext = XExtentsOfFontSet(entry->sme_bsb.fontset);
font_ascent = font_descent = fontset_ascent = fontset_descent = 0;
entry->sme_bsb.set_values_area_cleared = False;
if (entry->sme.international == True) {
fontset_ascent = XawAbs(ext->max_ink_extent.y);
fontset_descent = ext->max_ink_extent.height - fontset_ascent;
}
else {
font_ascent = entry->sme_bsb.font->max_bounds.ascent;
font_descent = entry->sme_bsb.font->max_bounds.descent;
}
y_loc = XtY(entry);
if (XtIsSensitive(w) && XtIsSensitive(XtParent(w))) {
if (w == XawSimpleMenuGetActiveEntry(XtParent(w))) {
XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
entry->sme_bsb.norm_gc, XtX(w), y_loc,
XtWidth(entry), XtHeight(entry));
gc = entry->sme_bsb.rev_gc;
}
else
gc = entry->sme_bsb.norm_gc;
}
else
gc = entry->sme_bsb.norm_gray_gc;
if (entry->sme_bsb.label != NULL) {
int x_loc = entry->sme_bsb.left_margin;
int len = strlen(entry->sme_bsb.label);
char *label = entry->sme_bsb.label;
int width, t_width;
switch(entry->sme_bsb.justify) {
case XtJustifyCenter:
if (entry->sme.international == True) {
t_width = XmbTextEscapement(entry->sme_bsb.fontset,label,
len);
width = XtWidth(entry) - (entry->sme_bsb.left_margin +
entry->sme_bsb.right_margin);
}
else {
t_width = XTextWidth(entry->sme_bsb.font, label, len);
width = XtWidth(entry) - (entry->sme_bsb.left_margin +
entry->sme_bsb.right_margin);
}
x_loc += (width - t_width) >> 1;
break;
case XtJustifyRight:
if (entry->sme.international == True) {
t_width = XmbTextEscapement(entry->sme_bsb.fontset,label,
len);
x_loc = XtWidth(entry) - (entry->sme_bsb.right_margin +
t_width);
}
else {
t_width = XTextWidth(entry->sme_bsb.font, label, len);
x_loc = XtWidth(entry) - (entry->sme_bsb.right_margin +
t_width);
}
break;
case XtJustifyLeft:
default:
break;
}
if (entry->sme.international == True) {
y_loc += ((XtHeight(entry) -
(fontset_ascent + fontset_descent)) >> 1) +
fontset_ascent;
XmbDrawString(XtDisplayOfObject(w), XtWindowOfObject(w),
entry->sme_bsb.fontset, gc,
XtX(w) + x_loc, y_loc, label, len);
}
else {
y_loc += ((XtHeight(entry) -
(font_ascent + font_descent)) >> 1) + font_ascent;
XDrawString(XtDisplayOfObject(w), XtWindowOfObject(w), gc,
XtX(w) + x_loc, y_loc, label, len);
}
}
DrawBitmaps(w, gc);
}
static Boolean
XawSmeBSBSetValues(Widget current, Widget request, Widget cnew,
ArgList args, Cardinal *num_args)
{
SmeBSBObject entry = (SmeBSBObject)cnew;
SmeBSBObject old_entry = (SmeBSBObject)current;
Boolean ret_val = False;
if (old_entry->sme_bsb.label != entry->sme_bsb.label) {
if (old_entry->sme_bsb.label != XtName(cnew))
XtFree((char *)old_entry->sme_bsb.label);
if (entry->sme_bsb.label != XtName(cnew))
entry->sme_bsb.label = XtNewString(entry->sme_bsb.label);
ret_val = True;
}
if (entry->rectangle.sensitive != old_entry->rectangle.sensitive)
ret_val = True;
if (entry->sme_bsb.left_bitmap != old_entry->sme_bsb.left_bitmap) {
GetBitmapInfo(cnew, True);
ret_val = True;
}
if (entry->sme_bsb.right_bitmap != old_entry->sme_bsb.right_bitmap) {
GetBitmapInfo(cnew, False);
ret_val = True;
}
if ((old_entry->sme_bsb.font != entry->sme_bsb.font
&& old_entry->sme.international == False)
|| old_entry->sme_bsb.foreground != entry->sme_bsb.foreground) {
DestroyGCs(current);
CreateGCs(cnew);
ret_val = True;
}
if (old_entry->sme_bsb.fontset != entry->sme_bsb.fontset &&
old_entry->sme.international == True)
ret_val = True;
if (ret_val) {
Dimension width, height;
GetDefaultSize(cnew, &width, &height);
entry->sme_bsb.set_values_area_cleared = True;
XtMakeResizeRequest(cnew, width, height, NULL, NULL);
}
return (ret_val);
}
static XtGeometryResult
XawSmeBSBQueryGeometry(Widget w, XtWidgetGeometry *intended,
XtWidgetGeometry *return_val)
{
SmeBSBObject entry = (SmeBSBObject)w;
Dimension width, height;
XtGeometryResult ret_val = XtGeometryYes;
XtGeometryMask mode = intended->request_mode;
GetDefaultSize(w, &width, &height);
if (((mode & CWWidth) && intended->width != width) || !(mode & CWWidth)) {
return_val->request_mode |= CWWidth;
return_val->width = width;
ret_val = XtGeometryAlmost;
}
if (((mode & CWHeight) && intended->height != height) || !(mode & CWHeight)) {
return_val->request_mode |= CWHeight;
return_val->height = height;
ret_val = XtGeometryAlmost;
}
if (ret_val == XtGeometryAlmost) {
mode = return_val->request_mode;
if (((mode & CWWidth) && width == XtWidth(entry)) &&
((mode & CWHeight) && height == XtHeight(entry)))
return (XtGeometryNo);
}
return (ret_val);
}
static void
FlipColors(Widget w)
{
SmeBSBObject entry = (SmeBSBObject)w;
if (entry->sme_bsb.set_values_area_cleared)
return;
XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
entry->sme_bsb.invert_gc,
XtX(w), XtY(entry), XtWidth(entry), XtHeight(entry));
}
static void
GetDefaultSize(Widget w, Dimension *width, Dimension *height)
{
SmeBSBObject entry = (SmeBSBObject)w;
if (entry->sme.international == True) {
XFontSetExtents *ext = XExtentsOfFontSet(entry->sme_bsb.fontset);
if (entry->sme_bsb.label == NULL)
*width = 0;
else
*width = XmbTextEscapement(entry->sme_bsb.fontset,
entry->sme_bsb.label,
strlen(entry->sme_bsb.label));
*width += entry->sme_bsb.left_margin + entry->sme_bsb.right_margin;
*height = ext->max_ink_extent.height;
*height = ((int)*height * (ONE_HUNDRED +
entry->sme_bsb.vert_space)) / ONE_HUNDRED;
}
else {
if (entry->sme_bsb.label == NULL)
*width = 0;
else
*width = XTextWidth(entry->sme_bsb.font, entry->sme_bsb.label,
strlen(entry->sme_bsb.label));
*width += entry->sme_bsb.left_margin + entry->sme_bsb.right_margin;
*height = entry->sme_bsb.font->max_bounds.ascent +
entry->sme_bsb.font->max_bounds.descent;
*height = ((int)*height * (ONE_HUNDRED +
entry->sme_bsb.vert_space)) / ONE_HUNDRED;
}
}
static void
DrawBitmaps(Widget w, GC gc)
{
int x_loc, y_loc;
SmeBSBObject entry = (SmeBSBObject)w;
if (entry->sme_bsb.left_bitmap == None &&
entry->sme_bsb.right_bitmap == None)
return;
if (entry->sme_bsb.left_bitmap != None) {
x_loc = ((entry->sme_bsb.left_margin -
entry->sme_bsb.left_bitmap_width) >> 1) + XtX(w);
y_loc = XtY(entry) + ((XtHeight(entry) -
entry->sme_bsb.left_bitmap_height) >> 1);
XCopyPlane(XtDisplayOfObject(w), entry->sme_bsb.left_bitmap,
XtWindowOfObject(w), gc, 0, 0,
entry->sme_bsb.left_bitmap_width,
entry->sme_bsb.left_bitmap_height, x_loc, y_loc, 1);
}
if (entry->sme_bsb.right_bitmap != None) {
x_loc = XtWidth(entry) - ((entry->sme_bsb.right_margin +
entry->sme_bsb.right_bitmap_width) >> 1) +
XtX(w);
y_loc = XtY(entry) + ((XtHeight(entry) -
entry->sme_bsb.right_bitmap_height) >> 1);
XCopyPlane(XtDisplayOfObject(w), entry->sme_bsb.right_bitmap,
XtWindowOfObject(w), gc, 0, 0,
entry->sme_bsb.right_bitmap_width,
entry->sme_bsb.right_bitmap_height, x_loc, y_loc, 1);
}
}
static void
GetBitmapInfo(Widget w, Bool is_left)
{
SmeBSBObject entry = (SmeBSBObject)w;
unsigned int depth, bw;
Window root;
int x, y;
unsigned int width, height;
if (is_left) {
if (entry->sme_bsb.left_bitmap != None &&
XGetGeometry(XtDisplayOfObject(w),
entry->sme_bsb.left_bitmap, &root,
&x, &y, &width, &height, &bw, &depth)) {
entry->sme_bsb.left_bitmap_width = width;
entry->sme_bsb.left_bitmap_height = height;
}
}
else if (entry->sme_bsb.right_bitmap != None &&
XGetGeometry(XtDisplayOfObject(w),
entry->sme_bsb.right_bitmap, &root,
&x, &y, &width, &height, &bw, &depth)) {
entry->sme_bsb.right_bitmap_width = width;
entry->sme_bsb.right_bitmap_height = height;
}
}
static void
CreateGCs(Widget w)
{
SmeBSBObject entry = (SmeBSBObject)w;
XGCValues values;
XtGCMask mask, mask_i18n;
values.foreground = XtParent(w)->core.background_pixel;
values.background = entry->sme_bsb.foreground;
values.font = entry->sme_bsb.font->fid;
values.graphics_exposures = False;
mask = GCForeground | GCBackground | GCGraphicsExposures | GCFont;
mask_i18n = GCForeground | GCBackground | GCGraphicsExposures;
if (entry->sme.international == True)
entry->sme_bsb.rev_gc = XtAllocateGC(w, 0, mask_i18n, &values, GCFont, 0);
else
entry->sme_bsb.rev_gc = XtGetGC(w, mask, &values);
values.foreground = entry->sme_bsb.foreground;
values.background = XtParent(w)->core.background_pixel;
if (entry->sme.international == True)
entry->sme_bsb.norm_gc = XtAllocateGC(w, 0, mask_i18n, &values, GCFont, 0);
else
entry->sme_bsb.norm_gc = XtGetGC(w, mask, &values);
values.fill_style = FillTiled;
values.tile = XmuCreateStippledPixmap(XtScreenOfObject(w),
entry->sme_bsb.foreground,
XtParent(w)->core.background_pixel,
XtParent(w)->core.depth);
values.graphics_exposures = False;
mask |= GCTile | GCFillStyle;
mask_i18n |= GCTile | GCFillStyle;
if (entry->sme.international == True)
entry->sme_bsb.norm_gray_gc = XtAllocateGC(w, 0, mask_i18n, &values,
GCFont, 0);
else
entry->sme_bsb.norm_gray_gc = XtGetGC(w, mask, &values);
values.foreground ^= values.background;
values.background = 0;
values.function = GXxor;
mask = GCForeground | GCBackground | GCGraphicsExposures | GCFunction;
entry->sme_bsb.invert_gc = XtGetGC(w, mask, &values);
}
static void
DestroyGCs(Widget w)
{
SmeBSBObject entry = (SmeBSBObject)w;
XtReleaseGC(w, entry->sme_bsb.norm_gc);
XtReleaseGC(w, entry->sme_bsb.norm_gray_gc);
XtReleaseGC(w, entry->sme_bsb.rev_gc);
XtReleaseGC(w, entry->sme_bsb.invert_gc);
}