#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/TextP.h>
#include <X11/Xaw/TextSinkP.h>
#include <X11/Xaw/XawInit.h>
#include "Private.h"
static void XawTextSinkClassPartInitialize(WidgetClass);
static void XawTextSinkInitialize(Widget, Widget, ArgList, Cardinal*);
static void XawTextSinkDestroy(Widget);
static Boolean XawTextSinkSetValues(Widget, Widget, Widget,
ArgList, Cardinal*);
static int MaxLines(Widget, unsigned int);
static int MaxHeight(Widget, int);
static void DisplayText(Widget, int, int, XawTextPosition, XawTextPosition,
Bool);
static void InsertCursor(Widget, int, int, XawTextInsertState);
static void ClearToBackground(Widget, int, int, unsigned int, unsigned int);
static void FindPosition(Widget, XawTextPosition, int, int, Bool,
XawTextPosition*, int*, int*);
static void FindDistance(Widget, XawTextPosition, int, XawTextPosition, int*,
XawTextPosition*, int*);
static void Resolve(Widget, XawTextPosition, int, int, XawTextPosition*);
static void SetTabs(Widget, int, short*);
static void GetCursorBounds(Widget, XRectangle*);
#ifndef OLDXAW
static Boolean CvtStringToPropertyList(Display*, XrmValue*, Cardinal*,
XrmValue*, XrmValue*, XtPointer*);
static Boolean CvtPropertyListToString(Display*, XrmValue*, Cardinal*,
XrmValue*, XrmValue*, XtPointer*);
static Bool BeginPaint(Widget);
static Bool EndPaint(Widget);
static void SetXlfdDefaults(Display*, XawTextProperty*);
#endif
void _XawTextSinkClearToBackground(Widget, int, int, unsigned, unsigned);
void _XawTextSinkDisplayText(Widget, int, int, XawTextPosition, XawTextPosition,
Bool);
#define offset(field) XtOffsetOf(TextSinkRec, text_sink.field)
static XtResource resources[] = {
{
XtNforeground,
XtCForeground,
XtRPixel,
sizeof(Pixel),
offset(foreground),
XtRString,
XtDefaultForeground
},
{
XtNbackground,
XtCBackground,
XtRPixel,
sizeof(Pixel),
offset(background),
XtRString,
XtDefaultBackground
},
#ifndef OLDXAW
{
XtNcursorColor,
XtCColor,
XtRPixel,
sizeof(Pixel),
offset(cursor_color),
XtRString,
XtDefaultForeground
},
{
XawNtextProperties,
XawCTextProperties,
XawRTextProperties,
sizeof(XawTextPropertyList*),
offset(properties),
XtRImmediate,
NULL
},
#endif
};
#undef offset
#ifndef OLDXAW
static TextSinkExtRec extension_rec = {
NULL,
NULLQUARK,
1,
sizeof(TextSinkExtRec),
BeginPaint,
NULL,
NULL,
EndPaint
};
static XrmQuark Qdefault;
#endif
#define Superclass (&objectClassRec)
TextSinkClassRec textSinkClassRec = {
{
(WidgetClass)Superclass,
"TextSink",
sizeof(TextSinkRec),
XawInitializeWidgetSet,
XawTextSinkClassPartInitialize,
False,
XawTextSinkInitialize,
NULL,
NULL,
NULL,
0,
resources,
XtNumber(resources),
NULLQUARK,
False,
False,
False,
False,
XawTextSinkDestroy,
NULL,
NULL,
XawTextSinkSetValues,
NULL,
NULL,
NULL,
NULL,
XtVersion,
NULL,
NULL,
NULL,
NULL,
NULL,
},
{
DisplayText,
InsertCursor,
ClearToBackground,
FindPosition,
FindDistance,
Resolve,
MaxLines,
MaxHeight,
SetTabs,
GetCursorBounds,
},
};
WidgetClass textSinkObjectClass = (WidgetClass)&textSinkClassRec;
static void
XawTextSinkClassPartInitialize(WidgetClass wc)
{
TextSinkObjectClass t_src, superC;
#ifndef OLDXAW
static XtConvertArgRec CvtArgs[] = {
{XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.self),
sizeof(Widget)},
};
#endif
t_src = (TextSinkObjectClass) wc;
superC = (TextSinkObjectClass) t_src->object_class.superclass;
#ifndef OLDXAW
extension_rec.record_type = XrmPermStringToQuark("TextSink");
extension_rec.next_extension = (XtPointer)t_src->text_sink_class.extension;
t_src->text_sink_class.extension = &extension_rec;
Qdefault = XrmPermStringToQuark("default");
#endif
if (t_src->text_sink_class.DisplayText == XtInheritDisplayText)
t_src->text_sink_class.DisplayText =
superC->text_sink_class.DisplayText;
if (t_src->text_sink_class.InsertCursor == XtInheritInsertCursor)
t_src->text_sink_class.InsertCursor =
superC->text_sink_class.InsertCursor;
if (t_src->text_sink_class.ClearToBackground== XtInheritClearToBackground)
t_src->text_sink_class.ClearToBackground =
superC->text_sink_class.ClearToBackground;
if (t_src->text_sink_class.FindPosition == XtInheritFindPosition)
t_src->text_sink_class.FindPosition =
superC->text_sink_class.FindPosition;
if (t_src->text_sink_class.FindDistance == XtInheritFindDistance)
t_src->text_sink_class.FindDistance =
superC->text_sink_class.FindDistance;
if (t_src->text_sink_class.Resolve == XtInheritResolve)
t_src->text_sink_class.Resolve =
superC->text_sink_class.Resolve;
if (t_src->text_sink_class.MaxLines == XtInheritMaxLines)
t_src->text_sink_class.MaxLines =
superC->text_sink_class.MaxLines;
if (t_src->text_sink_class.MaxHeight == XtInheritMaxHeight)
t_src->text_sink_class.MaxHeight =
superC->text_sink_class.MaxHeight;
if (t_src->text_sink_class.SetTabs == XtInheritSetTabs)
t_src->text_sink_class.SetTabs =
superC->text_sink_class.SetTabs;
if (t_src->text_sink_class.GetCursorBounds == XtInheritGetCursorBounds)
t_src->text_sink_class.GetCursorBounds =
superC->text_sink_class.GetCursorBounds;
#ifndef OLDXAW
XtSetTypeConverter(XtRString, XawRTextProperties, CvtStringToPropertyList,
&CvtArgs[0], XtNumber(CvtArgs), XtCacheNone, NULL);
XtSetTypeConverter(XawRTextProperties, XtRString, CvtPropertyListToString,
NULL, 0, XtCacheNone, NULL);
#endif
}
static void
XawTextSinkInitialize(Widget request, Widget cnew,
ArgList args, Cardinal *num_args)
{
TextSinkObject sink = (TextSinkObject)cnew;
sink->text_sink.tab_count = 0;
sink->text_sink.tabs = NULL;
sink->text_sink.char_tabs = NULL;
#ifndef OLDXAW
sink->text_sink.paint = NULL;
#endif
}
static void
XawTextSinkDestroy(Widget w)
{
TextSinkObject sink = (TextSinkObject) w;
XtFree((char *)sink->text_sink.tabs);
XtFree((char *)sink->text_sink.char_tabs);
}
static Boolean
XawTextSinkSetValues(Widget current, Widget request, Widget cnew,
ArgList args, Cardinal *num_args)
{
TextSinkObject w = (TextSinkObject)cnew;
TextSinkObject old_w = (TextSinkObject)current;
if (w->text_sink.foreground != old_w->text_sink.foreground)
((TextWidget)XtParent(cnew))->text.redisplay_needed = True;
return (False);
}
static void
DisplayText(Widget w, int x, int y,
XawTextPosition pos1, XawTextPosition pos2, Bool highlight)
{
return;
}
static void
InsertCursor(Widget w, int x, int y, XawTextInsertState state)
{
return;
}
static void
ClearToBackground(Widget w, int x, int y,
unsigned int width, unsigned int height)
{
TextWidget xaw = (TextWidget)XtParent(w);
Position x1, y1, x2, y2;
x1 = XawMax(x, xaw->text.r_margin.left);
y1 = XawMax(y, xaw->text.r_margin.top);
x2 = XawMin(x + (int)width, (int)XtWidth(xaw) - xaw->text.r_margin.right);
y2 = XawMin(y + (int)height, (int)XtHeight(xaw) - xaw->text.r_margin.bottom);
x = x1;
y = y1;
width = XawMax(0, x2 - x1);
height = XawMax(0, y2 - y1);
if (height != 0 && width != 0)
XClearArea(XtDisplayOfObject(w), XtWindowOfObject(w),
x, y, width, height, False);
}
static void
FindPosition(Widget w, XawTextPosition fromPos, int fromx, int width,
Bool stopAtWordBreak, XawTextPosition *resPos,
int *resWidth, int *resHeight)
{
*resPos = fromPos;
*resHeight = *resWidth = 0;
}
static void
FindDistance(Widget w, XawTextPosition fromPos, int fromx,
XawTextPosition toPos, int *resWidth,
XawTextPosition *resPos, int *resHeight)
{
*resWidth = *resHeight = 0;
*resPos = fromPos;
}
static void
Resolve(Widget w, XawTextPosition pos, int fromx, int width,
XawTextPosition *resPos)
{
*resPos = pos;
}
static int
MaxLines(Widget w, unsigned int height)
{
return (0);
}
static int
MaxHeight(Widget w, int lines)
{
return (0);
}
static void
SetTabs(Widget w, int tab_count, short *tabs)
{
return;
}
static void
GetCursorBounds(Widget w, XRectangle *rect)
{
rect->x = rect->y = rect->width = rect->height = 0;
}
void
XawTextSinkDisplayText(Widget w,
#if NeedWidePrototypes
int x, int y,
#else
Position x, Position y,
#endif
XawTextPosition pos1, XawTextPosition pos2,
#if NeedWidePrototypes
int highlight
#else
Boolean highlight
#endif
)
{
_XawTextSinkDisplayText(w, x, y, pos1, pos2, highlight);
}
void
_XawTextSinkDisplayText(Widget w, int x, int y,
XawTextPosition pos1, XawTextPosition pos2,
Bool highlight)
{
TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
(*cclass->text_sink_class.DisplayText)(w, x, y, pos1, pos2, highlight);
}
void
#if NeedWidePrototypes
XawTextSinkInsertCursor(Widget w, int x, int y, int state)
#else
XawTextSinkInsertCursor(Widget w, Position x, Position y, XawTextInsertState state)
#endif
{
TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
(*cclass->text_sink_class.InsertCursor)(w, x, y, state);
}
void
XawTextSinkClearToBackground(Widget w,
#if NeedWidePrototypes
int x, int y,
unsigned int width, unsigned int height
#else
Position x, Position y,
Dimension width, Dimension height
#endif
)
{
_XawTextSinkClearToBackground(w, x, y, width, height);
}
void
_XawTextSinkClearToBackground(Widget w,
int x, int y,
unsigned int width, unsigned int height)
{
TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
(*cclass->text_sink_class.ClearToBackground)(w, x, y, width, height);
}
void
XawTextSinkFindPosition(Widget w, XawTextPosition fromPos, int fromx, int width,
#if NeedWidePrototypes
int stopAtWordBreak,
#else
Boolean stopAtWordBreak,
#endif
XawTextPosition *resPos, int *resWidth, int *resHeight)
{
TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
(*cclass->text_sink_class.FindPosition)(w, fromPos, fromx, width,
stopAtWordBreak,
resPos, resWidth, resHeight);
}
void
XawTextSinkFindDistance(Widget w, XawTextPosition fromPos, int fromx,
XawTextPosition toPos, int *resWidth,
XawTextPosition *resPos, int *resHeight)
{
TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
(*cclass->text_sink_class.FindDistance)(w, fromPos, fromx, toPos,
resWidth, resPos, resHeight);
}
void
XawTextSinkResolve(Widget w, XawTextPosition pos, int fromx, int width,
XawTextPosition *resPos)
{
TextSinkObjectClass cclass = (TextSinkObjectClass) w->core.widget_class;
(*cclass->text_sink_class.Resolve)(w, pos, fromx, width, resPos);
}
int
#if NeedWidePrototypes
XawTextSinkMaxLines(Widget w, unsigned int height)
#else
XawTextSinkMaxLines(Widget w, Dimension height)
#endif
{
TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
return((*cclass->text_sink_class.MaxLines)(w, height));
}
int
XawTextSinkMaxHeight(Widget w, int lines)
{
TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
return((*cclass->text_sink_class.MaxHeight)(w, lines));
}
void
XawTextSinkSetTabs(Widget w, int tab_count, int *tabs)
{
if (tab_count > 0) {
TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
short *char_tabs = (short*)XtMalloc((unsigned)tab_count * sizeof(short));
short *tab, len = 0;
int i;
for (i = tab_count, tab = char_tabs; i; i--) {
if ((short)*tabs > len)
*tab++ = (len = (short)*tabs++);
else {
tabs++;
--tab_count;
}
}
if (tab_count > 0)
(*cclass->text_sink_class.SetTabs)(w, tab_count, char_tabs);
XtFree((char *)char_tabs);
}
}
void
XawTextSinkGetCursorBounds(Widget w, XRectangle *rect)
{
TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
(*cclass->text_sink_class.GetCursorBounds)(w, rect);
}
#ifndef OLDXAW
Bool
XawTextSinkBeginPaint(Widget w)
{
TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
if (cclass->text_sink_class.extension->BeginPaint == NULL ||
cclass->text_sink_class.extension->PreparePaint == NULL ||
cclass->text_sink_class.extension->DoPaint == NULL ||
cclass->text_sink_class.extension->EndPaint == NULL)
return (False);
return ((*cclass->text_sink_class.extension->BeginPaint)(w));
}
static Bool
BeginPaint(Widget w)
{
TextSinkObject sink = (TextSinkObject)w;
if (sink->text_sink.paint != NULL)
return (False);
sink->text_sink.paint = XtNew(XawTextPaintList);
sink->text_sink.paint->clip = XmuCreateArea();
sink->text_sink.paint->hightabs = NULL;
sink->text_sink.paint->paint = NULL;
sink->text_sink.paint->bearings = NULL;
return (True);
}
void
XawTextSinkPreparePaint(Widget w, int y, int line, XawTextPosition from,
XawTextPosition to, Bool highlight)
{
TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
(*cclass->text_sink_class.extension->PreparePaint)
(w, y, line, from, to, highlight);
}
#if 0
static void
PreparePaint(Widget w, int y, int line, XawTextPosition from, XawTextPosition to,
Bool highlight)
{
}
#endif
void
XawTextSinkDoPaint(Widget w)
{
TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
(*cclass->text_sink_class.extension->DoPaint)(w);
}
#if 0
static void
DoPaint(Widget w)
{
}
#endif
Bool
XawTextSinkEndPaint(Widget w)
{
TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
return ((*cclass->text_sink_class.extension->EndPaint)(w));
}
static Bool
EndPaint(Widget w)
{
TextSinkObject sink = (TextSinkObject)w;
XawTextPaintStruct *paint, *next;
if (sink->text_sink.paint == NULL)
return (False);
XmuDestroyArea(sink->text_sink.paint->clip);
if (sink->text_sink.paint->hightabs)
XmuDestroyArea(sink->text_sink.paint->hightabs);
paint = sink->text_sink.paint->paint;
while (paint) {
next = paint->next;
if (paint->text)
XtFree((XtPointer)paint->text);
if (paint->backtabs)
XmuDestroyArea(paint->backtabs);
XtFree((XtPointer)paint);
paint = next;
}
paint = sink->text_sink.paint->bearings;
while (paint) {
next = paint->next;
if (paint->text)
XtFree((XtPointer)paint->text);
XtFree((XtPointer)paint);
paint = next;
}
XtFree((XtPointer)sink->text_sink.paint);
sink->text_sink.paint = NULL;
return (True);
}
static XawTextPropertyList **prop_lists;
static Cardinal num_prop_lists;
static int
bcmp_qident(_Xconst void *left, _Xconst void *right)
{
return ((long)left - (*(XawTextProperty**)right)->identifier);
}
static int
qcmp_qident(_Xconst void *left, _Xconst void *right)
{
return ((*(XawTextProperty**)left)->identifier -
(*(XawTextProperty**)right)->identifier);
}
static void
SetXlfdDefaults(Display *display, XawTextProperty *property)
{
Atom atom = XInternAtom(display, "FONT", True);
unsigned long value;
char *str;
if (XGetFontProperty(property->font, atom, &value)) {
char *xlfd = XGetAtomName(display, value);
if (xlfd) {
char *sep = xlfd + 1;
char *name = sep;
property->xlfd = XrmStringToQuark(xlfd);
sep = strchr(sep, '-'); *sep++ = '\0';
property->foundry = XrmStringToQuark(name);
name = sep;
sep = strchr(sep, '-'); *sep++ = '\0';
property->family = XrmStringToQuark(name);
name = sep;
sep = strchr(sep, '-'); *sep++ = '\0';
property->weight = XrmStringToQuark(name);
name = sep;
sep = strchr(sep, '-'); *sep++ = '\0';
property->slant = XrmStringToQuark(name);
name = sep;
sep = strchr(sep, '-'); *sep++ = '\0';
property->setwidth = XrmStringToQuark(name);
name = sep;
sep = strchr(sep, '-'); *sep++ = '\0';
property->addstyle = XrmStringToQuark(name);
name = sep;
sep = strchr(sep, '-'); *sep++ = '\0';
property->pixel_size = XrmStringToQuark(name);
name = sep;
sep = strchr(sep, '-'); *sep++ = '\0';
property->point_size = XrmStringToQuark(name);
name = sep;
sep = strchr(sep, '-'); *sep++ = '\0';
property->res_x = XrmStringToQuark(name);
name = sep;
sep = strchr(sep, '-'); *sep++ = '\0';
property->res_y = XrmStringToQuark(name);
name = sep;
sep = strchr(sep, '-'); *sep++ = '\0';
property->spacing = XrmStringToQuark(name);
name = sep;
sep = strchr(sep, '-'); *sep++ = '\0';
property->avgwidth = XrmStringToQuark(name);
name = sep;
sep = strchr(sep, '-'); *sep++ = '\0';
property->registry = XrmStringToQuark(name);
name = sep;
property->encoding = XrmStringToQuark(name);
XFree(xlfd);
}
}
atom = XInternAtom(display, "UNDERLINE_THICKNESS", True);
if (XGetFontProperty(property->font, atom, &value) &&
(str = XGetAtomName(display, value)) != NULL) {
property->underline_thickness = atoi(str);
XFree(str);
}
else {
if (property->pixel_size != NULLQUARK) {
property->underline_thickness =
atoi(XrmQuarkToString(property->pixel_size)) / 10;
property->underline_thickness =
XawMax(1, property->underline_thickness);
}
else
property->underline_thickness = 1;
}
atom = XInternAtom(display, "UNDERLINE_POSITION", True);
if (XGetFontProperty(property->font, atom, &value) &&
(str = XGetAtomName(display, value)) != NULL) {
property->underline_position = atoi(str);
XFree(str);
}
else
property->underline_position =
property->font->max_bounds.descent >> 1;
property->underline_position += property->underline_thickness >> 1;
}
static void
DestroyTextPropertyList(XawTextPropertyList *list)
{
int i;
for (i = 0; i < list->num_properties; i++) {
if (list->properties[i]->font)
XFreeFont(DisplayOfScreen(list->screen), list->properties[i]->font);
XtFree((char*)list->properties[i]);
}
if (list->properties)
XtFree((char*)list->properties);
XtFree((char*)list);
}
static XawTextProperty *
_XawTextSinkGetProperty(XawTextPropertyList *list, XrmQuark property)
{
if (property != NULLQUARK && list && list->properties) {
XawTextProperty **ptr = (XawTextProperty**)
bsearch((void*)(long)property,
list->properties, list->num_properties,
sizeof(XawTextProperty*), bcmp_qident);
if (ptr)
return (*ptr);
}
return (NULL);
}
XawTextProperty *
XawTextSinkGetProperty(Widget w, XrmQuark property)
{
TextSinkObject sink = (TextSinkObject)w;
XawTextPropertyList *list = sink->text_sink.properties;
return (_XawTextSinkGetProperty(list, property));
}
XawTextProperty *
XawTextSinkCopyProperty(Widget w, XrmQuark property)
{
XawTextProperty *cur, *ret;
if ((cur = XawTextSinkGetProperty(w, property)) == NULL)
cur = XawTextSinkGetProperty(w, Qdefault);
ret = (XawTextProperty*)XtCalloc(1, sizeof(XawTextProperty));
if (cur)
memcpy(ret, cur, sizeof(XawTextProperty));
ret->identifier = NULLQUARK;
ret->mask &= ~XAW_TPROP_FONT;
return (ret);
}
static XawTextProperty *
_XawTextSinkAddProperty(XawTextPropertyList *list, XawTextProperty *property,
Bool replace)
{
XawTextProperty *result;
XColor color;
char identifier[1024];
char foreground[16];
char background[16];
char *foundry, *family, *weight, *slant, *setwidth, *addstyle, *pixel_size,
*point_size, *res_x, *res_y, *spacing, *avgwidth, *registry, *encoding;
char *xlfd;
static char *asterisk = "*", *null = "";
XrmQuark quark;
if (list == NULL || property == NULL)
return (NULL);
if (property->mask & XAW_TPROP_FOREGROUND) {
color.pixel = property->foreground;
XQueryColor(DisplayOfScreen(list->screen), list->colormap, &color);
XmuSnprintf(foreground, sizeof(foreground), "%04x%04x%04x",
color.red, color.green, color.blue);
}
else
strcpy(foreground, asterisk);
if (property->mask & XAW_TPROP_BACKGROUND) {
color.pixel = property->background;
XQueryColor(DisplayOfScreen(list->screen), list->colormap, &color);
XmuSnprintf(background, sizeof(background), "%04x%04x%04x",
color.red, color.green, color.blue);
}
else
strcpy(background, asterisk);
if (property->xlfd_mask & XAW_TPROP_FOUNDRY)
foundry = XrmQuarkToString(property->foundry);
else
foundry = asterisk;
if (property->family != NULLQUARK)
family = XrmQuarkToString(property->family);
else
family = asterisk;
if (property->weight != NULLQUARK)
weight = XrmQuarkToString(property->weight);
else
weight = asterisk;
if (property->slant != NULLQUARK) {
slant = XrmQuarkToString(property->slant);
if (toupper(*slant) != 'R')
slant = asterisk;
}
else
slant = asterisk;
if (property->xlfd_mask & XAW_TPROP_SETWIDTH)
setwidth = XrmQuarkToString(property->setwidth);
else
setwidth = asterisk;
if (property->xlfd_mask & XAW_TPROP_ADDSTYLE)
addstyle = XrmQuarkToString(property->addstyle);
else
addstyle = null;
if (!(property->mask & XAW_TPROP_POINTSIZE) &&
property->pixel_size != NULLQUARK)
pixel_size = XrmQuarkToString(property->pixel_size);
else
pixel_size = asterisk;
if (property->xlfd_mask & XAW_TPROP_POINTSIZE)
point_size = XrmQuarkToString(property->point_size);
else
point_size = asterisk;
if (property->xlfd_mask & XAW_TPROP_RESX)
res_x = XrmQuarkToString(property->res_x);
else
res_x = asterisk;
if (property->xlfd_mask & XAW_TPROP_RESY)
res_y = XrmQuarkToString(property->res_y);
else
res_y = asterisk;
if (property->xlfd_mask & XAW_TPROP_SPACING)
spacing = XrmQuarkToString(property->spacing);
else
spacing = asterisk;
if (property->xlfd_mask & XAW_TPROP_AVGWIDTH)
avgwidth = XrmQuarkToString(property->avgwidth);
else
avgwidth = asterisk;
if (property->registry != NULLQUARK)
registry = XrmQuarkToString(property->registry);
else
registry = asterisk;
if (property->encoding != NULLQUARK)
encoding = XrmQuarkToString(property->encoding);
else
encoding = asterisk;
if (replace) {
result = XtNew(XawTextProperty);
memcpy(result, property, sizeof(XawTextProperty));
}
else
result = property;
if (!(result->mask & XAW_TPROP_FONT)) {
XmuSnprintf(identifier, sizeof(identifier),
"-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
foundry, family, weight, slant, setwidth, addstyle, pixel_size,
point_size, res_x, res_y, spacing, avgwidth, registry, encoding);
if ((result->font = XLoadQueryFont(DisplayOfScreen(list->screen),
identifier)) != NULL) {
result->mask |= XAW_TPROP_FONT;
SetXlfdDefaults(DisplayOfScreen(list->screen), result);
}
else
result->mask &= ~XAW_TPROP_FONT;
}
if (result->font)
xlfd = XrmQuarkToString(result->xlfd);
else
xlfd = null;
XmuSnprintf(identifier, sizeof(identifier), "%08lx%08lx%s%s%d%d%d%d%s",
property->mask, property->xlfd_mask,
foreground, background,
(result->mask & XAW_TPROP_UNDERLINE) != 0,
(result->mask & XAW_TPROP_OVERSTRIKE) != 0,
(result->mask & XAW_TPROP_SUBSCRIPT) != 0,
(result->mask & XAW_TPROP_SUPERSCRIPT) != 0,
xlfd);
quark = XrmStringToQuark(identifier);
if (result->identifier == NULLQUARK)
result->identifier = quark;
result->code = quark;
if ((property = _XawTextSinkGetProperty(list, result->identifier)) != NULL) {
if (result->font)
XFreeFont(DisplayOfScreen(list->screen), result->font);
if (replace)
XtFree((XtPointer)result);
return (property);
}
list->properties = (XawTextProperty**)
XtRealloc((XtPointer)list->properties, sizeof(XawTextProperty*) *
(list->num_properties + 1));
list->properties[list->num_properties++] = result;
qsort((void*)list->properties, list->num_properties,
sizeof(XawTextProperty*), qcmp_qident);
return (result);
}
XawTextProperty *
XawTextSinkAddProperty(Widget w, XawTextProperty *property)
{
TextSinkObject sink = (TextSinkObject)w;
XawTextPropertyList *list = sink->text_sink.properties;
return (_XawTextSinkAddProperty(list, property, True));
}
XawTextProperty *
XawTextSinkCombineProperty(Widget w,
XawTextProperty *property, XawTextProperty *combine,
Bool override)
{
if (property == NULL || combine == NULL)
return (property);
if ((override || !(property->mask & XAW_TPROP_FOREGROUND)) &&
(combine->mask & XAW_TPROP_FOREGROUND)) {
property->mask |= XAW_TPROP_FOREGROUND;
property->foreground = combine->foreground;
}
if ((override || !(property->mask & XAW_TPROP_BACKGROUND)) &&
(combine->mask & XAW_TPROP_BACKGROUND)) {
property->mask |= XAW_TPROP_BACKGROUND;
property->background = combine->background;
}
if ((override || !(property->mask & XAW_TPROP_FPIXMAP)) &&
(combine->mask & XAW_TPROP_FPIXMAP)) {
property->mask |= XAW_TPROP_FPIXMAP;
property->foreground_pixmap = combine->foreground_pixmap;
}
if ((override || !(property->mask & XAW_TPROP_BPIXMAP)) &&
(combine->mask & XAW_TPROP_BPIXMAP)) {
property->mask |= XAW_TPROP_BPIXMAP;
property->background_pixmap = combine->background_pixmap;
}
if (combine->mask & XAW_TPROP_UNDERLINE)
property->mask |= XAW_TPROP_UNDERLINE;
if (combine->mask & XAW_TPROP_OVERSTRIKE)
property->mask |= XAW_TPROP_OVERSTRIKE;
if ((override || !(property->mask & XAW_TPROP_SUPERSCRIPT)) &&
(combine->mask & XAW_TPROP_SUBSCRIPT))
property->mask |= XAW_TPROP_SUBSCRIPT;
if ((property->mask & XAW_TPROP_SUBSCRIPT) &&
(combine->mask & XAW_TPROP_SUPERSCRIPT))
property->mask |= XAW_TPROP_SUPERSCRIPT;
if ((override || !(property->xlfd_mask & XAW_TPROP_FOUNDRY)) &&
(combine->xlfd_mask & XAW_TPROP_FOUNDRY)) {
property->xlfd_mask |= XAW_TPROP_FOUNDRY;
property->foundry = combine->foundry;
}
if ((override || !(property->xlfd_mask & XAW_TPROP_FAMILY)) &&
(combine->xlfd_mask & XAW_TPROP_FAMILY)) {
property->xlfd_mask |= XAW_TPROP_FAMILY;
property->family = combine->family;
}
if ((override || !(property->xlfd_mask & XAW_TPROP_WEIGHT)) &&
(combine->xlfd_mask & XAW_TPROP_WEIGHT)) {
property->xlfd_mask |= XAW_TPROP_WEIGHT;
property->weight = combine->weight;
}
if ((override || !(property->xlfd_mask & XAW_TPROP_SLANT)) &&
(combine->xlfd_mask & XAW_TPROP_SLANT)) {
property->xlfd_mask |= XAW_TPROP_SLANT;
property->slant = combine->slant;
}
if ((override || !(property->xlfd_mask & XAW_TPROP_SETWIDTH)) &&
(combine->xlfd_mask & XAW_TPROP_SETWIDTH)) {
property->xlfd_mask |= XAW_TPROP_SETWIDTH;
property->setwidth = combine->setwidth;
}
if ((override || !(property->xlfd_mask & XAW_TPROP_ADDSTYLE)) &&
(combine->xlfd_mask & XAW_TPROP_ADDSTYLE)) {
property->xlfd_mask |= XAW_TPROP_ADDSTYLE;
property->addstyle = combine->addstyle;
}
if ((override || !(property->xlfd_mask & XAW_TPROP_PIXELSIZE)) &&
(combine->xlfd_mask & XAW_TPROP_PIXELSIZE)) {
property->xlfd_mask |= XAW_TPROP_PIXELSIZE;
property->pixel_size = combine->pixel_size;
}
if ((override || !(property->xlfd_mask & XAW_TPROP_POINTSIZE)) &&
(combine->xlfd_mask & XAW_TPROP_POINTSIZE)) {
property->xlfd_mask |= XAW_TPROP_POINTSIZE;
property->point_size = combine->point_size;
}
if ((override || !(property->xlfd_mask & XAW_TPROP_RESX)) &&
(combine->xlfd_mask & XAW_TPROP_RESX)) {
property->xlfd_mask |= XAW_TPROP_RESX;
property->res_x = combine->res_x;
}
if ((override || !(property->xlfd_mask & XAW_TPROP_RESY)) &&
(combine->xlfd_mask & XAW_TPROP_RESY)) {
property->xlfd_mask |= XAW_TPROP_RESY;
property->res_y = combine->res_y;
}
if ((override || !(property->xlfd_mask & XAW_TPROP_SPACING)) &&
(combine->xlfd_mask & XAW_TPROP_SPACING)) {
property->xlfd_mask |= XAW_TPROP_SPACING;
property->spacing = combine->spacing;
}
if ((override || !(property->xlfd_mask & XAW_TPROP_AVGWIDTH)) &&
(combine->xlfd_mask & XAW_TPROP_AVGWIDTH)) {
property->xlfd_mask |= XAW_TPROP_AVGWIDTH;
property->avgwidth = combine->avgwidth;
}
if ((override || !(property->xlfd_mask & XAW_TPROP_REGISTRY)) &&
(combine->xlfd_mask & XAW_TPROP_REGISTRY)) {
property->xlfd_mask |= XAW_TPROP_REGISTRY;
property->registry = combine->registry;
}
if ((override || !(property->xlfd_mask & XAW_TPROP_ENCODING)) &&
(combine->xlfd_mask & XAW_TPROP_ENCODING)) {
property->xlfd_mask |= XAW_TPROP_ENCODING;
property->encoding = combine->encoding;
}
return (property);
}
XawTextPropertyList *
XawTextSinkConvertPropertyList(String name, String spec, Screen *screen,
Colormap colormap, int depth)
{
XrmQuark qname = XrmStringToQuark(name);
XawTextPropertyList **ptr = NULL;
XawTextPropertyList *propl, *prev = NULL;
XawTextProperty *def_prop = NULL;
String str, tok, tmp;
char buffer[BUFSIZ];
if (prop_lists) ptr = (XawTextPropertyList**)
bsearch((void*)(long)qname, prop_lists, num_prop_lists,
sizeof(XawTextPropertyList*), bcmp_qident);
if (ptr) {
propl = *ptr;
while (propl) {
prev = propl;
if (propl->screen == screen &&
propl->colormap == colormap &&
propl->depth == depth)
return (propl);
propl = propl->next;
}
}
propl = XtNew(XawTextPropertyList);
propl->identifier = qname;
propl->screen = screen;
propl->colormap = colormap;
propl->depth = depth;
propl->next = NULL;
if (prev)
prev->next = propl;
propl->properties = NULL;
propl->num_properties = 0;
str = XtNewString(spec);
for (tok = str; tok; tok = tmp) {
XawTextProperty *prop;
XawParams *params;
XrmQuark ident;
XawArgVal *argval;
XColor color, exact;
if (def_prop == NULL && propl->num_properties)
def_prop = _XawTextSinkGetProperty(propl, Qdefault);
tmp = strchr(tok, ',');
if (tmp) {
*tmp = '\0';
if (*++tmp == '\0')
tmp = NULL;
}
params = XawParseParamsString(tok);
ident = XrmStringToQuark(params->name);
if (ident == NULLQUARK) {
XmuSnprintf(buffer, sizeof(buffer),
"Bad text property name \"%s\".", params->name);
XtAppWarning(XtDisplayToApplicationContext
(DisplayOfScreen(screen)), buffer);
DestroyTextPropertyList(propl);
if (prev)
prev->next = NULL;
XawFreeParamsStruct(params);
return (NULL);
}
else if (_XawTextSinkGetProperty(propl, ident) != NULL) {
XawFreeParamsStruct(params);
continue;
}
prop = (XawTextProperty*)XtCalloc(1, sizeof(XawTextProperty));
prop->identifier = ident;
if ((argval = XawFindArgVal(params, "font")) != NULL &&
argval->value) {
if ((prop->font = XLoadQueryFont(DisplayOfScreen(screen),
argval->value)) == NULL) {
XmuSnprintf(buffer, sizeof(buffer),
"Cannot load font \"%s\".", argval->value);
XtAppWarning(XtDisplayToApplicationContext
(DisplayOfScreen(screen)), buffer);
DestroyTextPropertyList(propl);
if (prev)
prev->next = NULL;
XawFreeParamsStruct(params);
return (NULL);
}
prop->mask |= XAW_TPROP_FONT;
SetXlfdDefaults(DisplayOfScreen(screen), prop);
}
if ((argval = XawFindArgVal(params, "foreground")) != NULL &&
argval->value) {
if (!XAllocNamedColor(DisplayOfScreen(screen), colormap,
argval->value, &color, &exact)) {
XmuSnprintf(buffer, sizeof(buffer),
"Cannot allocate color \"%s\".", argval->value);
XtAppWarning(XtDisplayToApplicationContext
(DisplayOfScreen(screen)), buffer);
DestroyTextPropertyList(propl);
if (prev)
prev->next = NULL;
XawFreeParamsStruct(params);
return (NULL);
}
prop->foreground = color.pixel;
prop->mask |= XAW_TPROP_FOREGROUND;
}
if ((argval = XawFindArgVal(params, "background")) != NULL &&
argval->value) {
if (!XAllocNamedColor(DisplayOfScreen(screen), colormap,
argval->value, &color, &exact)) {
XmuSnprintf(buffer, sizeof(buffer),
"Cannot allocate color \"%s\".", argval->value);
XtAppWarning(XtDisplayToApplicationContext
(DisplayOfScreen(screen)), buffer);
DestroyTextPropertyList(propl);
if (prev)
prev->next = NULL;
XawFreeParamsStruct(params);
return (NULL);
}
prop->background = color.pixel;
prop->mask |= XAW_TPROP_BACKGROUND;
}
if (XawFindArgVal(params, "underline"))
prop->mask |= XAW_TPROP_UNDERLINE;
if (XawFindArgVal(params, "overstrike"))
prop->mask |= XAW_TPROP_OVERSTRIKE;
if (XawFindArgVal(params, "subscript"))
prop->mask |= XAW_TPROP_SUBSCRIPT;
else if (XawFindArgVal(params, "superscript"))
prop->mask |= XAW_TPROP_SUPERSCRIPT;
if ((argval = XawFindArgVal(params, "foundry")) != NULL &&
argval->value) {
prop->xlfd_mask |= XAW_TPROP_FOUNDRY;
prop->foundry = XrmStringToQuark(argval->value);
}
if ((argval = XawFindArgVal(params, "family")) != NULL &&
argval->value) {
prop->xlfd_mask |= XAW_TPROP_FAMILY;
prop->family = XrmStringToQuark(argval->value);
}
if ((argval = XawFindArgVal(params, "weight")) != NULL &&
argval->value) {
prop->xlfd_mask |= XAW_TPROP_WEIGHT;
prop->weight = XrmStringToQuark(argval->value);
}
if ((argval = XawFindArgVal(params, "slant")) != NULL &&
argval->value) {
prop->xlfd_mask |= XAW_TPROP_SLANT;
prop->slant = XrmStringToQuark(argval->value);
}
if ((argval = XawFindArgVal(params, "setwidth")) != NULL &&
argval->value) {
prop->xlfd_mask |= XAW_TPROP_SETWIDTH;
prop->setwidth = XrmStringToQuark(argval->value);
}
if ((argval = XawFindArgVal(params, "addstyle")) != NULL &&
argval->value) {
prop->xlfd_mask |= XAW_TPROP_ADDSTYLE;
prop->addstyle = XrmStringToQuark(argval->value);
}
if ((argval = XawFindArgVal(params, "pixelsize")) != NULL &&
argval->value) {
prop->xlfd_mask |= XAW_TPROP_PIXELSIZE;
prop->pixel_size = XrmStringToQuark(argval->value);
}
if ((argval = XawFindArgVal(params, "pointsize")) != NULL &&
argval->value) {
prop->xlfd_mask |= XAW_TPROP_POINTSIZE;
prop->point_size = XrmStringToQuark(argval->value);
}
if ((argval = XawFindArgVal(params, "resx")) != NULL &&
argval->value) {
prop->xlfd_mask |= XAW_TPROP_RESX;
prop->res_x = XrmStringToQuark(argval->value);
}
if ((argval = XawFindArgVal(params, "resy")) != NULL &&
argval->value) {
prop->xlfd_mask |= XAW_TPROP_RESY;
prop->res_y = XrmStringToQuark(argval->value);
}
if ((argval = XawFindArgVal(params, "spacing")) != NULL &&
argval->value) {
prop->xlfd_mask |= XAW_TPROP_SPACING;
prop->spacing = XrmStringToQuark(argval->value);
}
if ((argval = XawFindArgVal(params, "avgwidth")) != NULL &&
argval->value) {
prop->xlfd_mask |= XAW_TPROP_AVGWIDTH;
prop->avgwidth = XrmStringToQuark(argval->value);
}
if ((argval = XawFindArgVal(params, "registry")) != NULL &&
argval->value) {
prop->xlfd_mask |= XAW_TPROP_REGISTRY;
prop->registry = XrmStringToQuark(argval->value);
}
if ((argval = XawFindArgVal(params, "encoding")) != NULL &&
argval->value) {
prop->xlfd_mask |= XAW_TPROP_ENCODING;
prop->encoding = XrmStringToQuark(argval->value);
}
if (def_prop)
(void)XawTextSinkCombineProperty(NULL, prop, def_prop, False);
(void)_XawTextSinkAddProperty(propl, prop, False);
XawFreeParamsStruct(params);
}
prop_lists = (XawTextPropertyList**)
XtRealloc((XtPointer)prop_lists, sizeof(XawTextPropertyList*) *
(num_prop_lists + 1));
prop_lists[num_prop_lists++] = propl;
qsort((void*)prop_lists, num_prop_lists, sizeof(XawTextPropertyList*),
qcmp_qident);
XtFree(str);
return (propl);
}
static Boolean
CvtStringToPropertyList(Display *dpy, XrmValue *args, Cardinal *num_args,
XrmValue *fromVal, XrmValue *toVal,
XtPointer *converter_data)
{
XawTextPropertyList *propl = NULL;
String name;
Widget w;
if (*num_args != 1) {
XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
"wrongParameters", "cvtStringToTextProperties",
"ToolkitError",
"String to textProperties conversion needs widget argument",
NULL, NULL);
return (False);
}
w = *(Widget*)args[0].addr;
while (w && !XtIsWidget(w))
w = XtParent(w);
name = (String)(fromVal[0].addr);
if (w) {
XawTextPropertyList **ptr = NULL;
if (prop_lists) ptr = (XawTextPropertyList**)
bsearch((void*)(long)XrmStringToQuark(name),
prop_lists, num_prop_lists,
sizeof(XawTextPropertyList*), bcmp_qident);
if (ptr) {
Screen *screen = w->core.screen;
Colormap colormap = w->core.colormap;
int depth = w->core.depth;
propl = *ptr;
while (propl) {
if (propl->screen == screen &&
propl->colormap == colormap &&
propl->depth == depth)
break;
propl = propl->next;
}
}
}
if (!propl) {
XtDisplayStringConversionWarning(dpy, (String)fromVal->addr,
XawRTextProperties);
toVal->addr = NULL;
toVal->size = sizeof(XawTextPropertyList*);
return (False);
}
if (toVal->addr != NULL) {
if (toVal->size < sizeof(XawTextPropertyList*)) {
toVal->size = sizeof(XawTextPropertyList*);
return (False);
}
*(XawTextPropertyList**)(toVal->addr) = propl;
}
else {
static XawTextPropertyList *static_val;
static_val = propl;
toVal->addr = (XPointer)&static_val;
}
toVal->size = sizeof(XawTextProperty*);
return (True);
}
static Boolean
CvtPropertyListToString(Display *dpy, XrmValue *args, Cardinal *num_args,
XrmValue *fromVal, XrmValue *toVal,
XtPointer *converter_data)
{
static char *buffer;
Cardinal size;
XawTextPropertyList *propl;
propl = *(XawTextPropertyList**)fromVal[0].addr;
buffer = XrmQuarkToString(propl->identifier);
size = strlen(buffer) + 1;
if (toVal->addr != NULL) {
if (toVal->size < size) {
toVal->size = size;
return (False);
}
strcpy((char *)toVal->addr, buffer);
}
else
toVal->addr = buffer;
toVal->size = size;
return (True);
}
#endif