#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xatom.h>
#include <X11/Xaw/XawInit.h>
#include <X11/Xaw/AsciiSinkP.h>
#include <X11/Xaw/AsciiSrcP.h>
#include <X11/Xaw/TextP.h>
#include "Private.h"
#ifdef GETLASTPOS
#undef GETLASTPOS
#endif
#define GETLASTPOS \
XawTextSourceScan(source, 0, XawstAll, XawsdRight, 1, True)
static void XawAsciiSinkClassPartInitialize(WidgetClass);
static void XawAsciiSinkInitialize(Widget, Widget, ArgList, Cardinal*);
static void XawAsciiSinkDestroy(Widget);
static void XawAsciiSinkResize(Widget);
static Boolean XawAsciiSinkSetValues(Widget, Widget, Widget,
ArgList, Cardinal*);
static int MaxLines(Widget, unsigned int);
static int MaxHeight(Widget, int);
static void SetTabs(Widget, int, short*);
static void DisplayText(Widget, int, int,
XawTextPosition, XawTextPosition, Bool);
static void InsertCursor(Widget, int, int, XawTextInsertState);
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 GetCursorBounds(Widget, XRectangle*);
#ifndef OLDXAW
static void AsciiPreparePaint(Widget, int, int,
XawTextPosition, XawTextPosition, Bool);
static void AsciiDoPaint(Widget);
#endif
static void GetGC(AsciiSinkObject);
static int CharWidth(AsciiSinkObject, XFontStruct*, int, unsigned int);
static unsigned int PaintText(Widget w, GC gc, int x, int y,
char *buf, int len, Bool);
void _XawTextSinkClearToBackground(Widget, int, int, unsigned, unsigned);
#define offset(field) XtOffsetOf(AsciiSinkRec, ascii_sink.field)
static XtResource resources[] = {
{
XtNfont,
XtCFont,
XtRFontStruct,
sizeof(XFontStruct*),
offset(font),
XtRString,
XtDefaultFont
},
{
XtNecho,
XtCOutput,
XtRBoolean,
sizeof(Boolean),
offset(echo),
XtRImmediate,
(XtPointer)True
},
{
XtNdisplayNonprinting,
XtCOutput,
XtRBoolean,
sizeof(Boolean),
offset(display_nonprinting),
XtRImmediate,
(XtPointer)
True
},
};
#undef offset
#define Superclass (&textSinkClassRec)
AsciiSinkClassRec asciiSinkClassRec = {
{
(WidgetClass)Superclass,
"AsciiSink",
sizeof(AsciiSinkRec),
XawInitializeWidgetSet,
XawAsciiSinkClassPartInitialize,
False,
XawAsciiSinkInitialize,
NULL,
NULL,
NULL,
0,
resources,
XtNumber(resources),
NULLQUARK,
False,
False,
False,
False,
XawAsciiSinkDestroy,
(XtProc)XawAsciiSinkResize,
NULL,
XawAsciiSinkSetValues,
NULL,
NULL,
NULL,
NULL,
XtVersion,
NULL,
NULL,
NULL,
NULL,
NULL,
},
{
DisplayText,
InsertCursor,
XtInheritClearToBackground,
FindPosition,
FindDistance,
Resolve,
MaxLines,
MaxHeight,
SetTabs,
GetCursorBounds,
#ifndef OLDXAW
NULL
#endif
},
{
NULL,
}
};
WidgetClass asciiSinkObjectClass = (WidgetClass)&asciiSinkClassRec;
static void
XawAsciiSinkClassPartInitialize(WidgetClass wc)
{
#ifndef OLDXAW
AsciiSinkObjectClass cclass = (AsciiSinkObjectClass)wc;
XrmQuark record_type = XrmPermStringToQuark("TextSink");
TextSinkExt ext = cclass->text_sink_class.extension;
while (ext) {
if (ext->record_type == record_type &&
ext->version == 1) {
ext->PreparePaint = AsciiPreparePaint;
ext->DoPaint = AsciiDoPaint;
break;
}
ext = (TextSinkExt)ext->next_extension;
}
if (ext == NULL)
XtError("TextSinkClass: cannot resolve extension.\n");
#endif
}
static int
CharWidth(AsciiSinkObject sink, XFontStruct *font, int x, unsigned int c)
{
int width = 0;
if (c == XawLF)
return (0);
if (c == XawTAB) {
int i;
Position *tab;
width = x;
x -= ((TextWidget)XtParent((Widget)sink))->text.left_margin;
i = 0;
tab = sink->text_sink.tabs;
while (1) {
if (x >= 0 && x < *tab)
return (*tab - x);
if (++i >= sink->text_sink.tab_count) {
x -= *tab;
i = 0;
tab = sink->text_sink.tabs;
if (width == x)
return (0);
}
else
++tab;
}
}
if ((c & 0177) < XawSP || c == 0177) {
if (sink->ascii_sink.display_nonprinting) {
if (c > 0177) {
width = CharWidth(sink, font, x, '\\');
width += CharWidth(sink, font, x, ((c >> 6) & 7) + '0');
width += CharWidth(sink, font, x, ((c >> 3) & 7) + '0');
c = (c & 7) + '0';
}
else {
width = CharWidth(sink, font, x, '^');
if ((c |= 0100) == 0177)
c = '?';
}
}
else
c = XawSP;
}
if (font->per_char
&& (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
width += font->per_char[c - font->min_char_or_byte2].width;
else
width += font->min_bounds.width;
return (width);
}
#ifndef OLDXAW
static int
GetTextWidth(TextWidget ctx, int current_width, XFontStruct *font,
XawTextPosition from, int length)
{
int i, width = 0;
XawTextBlock block;
XawTextPosition pos = from;
while (length > 0) {
pos = XawTextSourceRead(ctx->text.source, from, &block, length);
length -= pos - from;
from = pos;
for (i = 0; i < block.length; i++)
width += CharWidth((AsciiSinkObject)ctx->text.sink, font,
current_width + width,
(unsigned char)block.ptr[i]);
}
return (width);
}
static
void CalculateBearing(TextWidget ctx, XawTextPosition position, int x, int y,
int ascent, int descent, Bool highlight, Bool right)
{
AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink;
XawTextAnchor *anchor;
XawTextEntity *entity;
XawTextProperty *property;
XawTextPaintStruct *paint;
XawTextBlock block;
XFontStruct *font;
property = NULL;
if (XawTextSourceAnchorAndEntity(ctx->text.source, position,
&anchor, &entity) &&
(property = XawTextSinkGetProperty((Widget)sink,
entity->property)) != NULL &&
(property->mask & XAW_TPROP_FONT))
font = property->font;
else
font = sink->ascii_sink.font;
if (right) {
if (font->max_bounds.rbearing > 0) {
int rbearing = font->max_bounds.rbearing - font->max_bounds.width;
unsigned char c;
(void)XawTextSourceRead(ctx->text.source, position, &block, 1);
c = *(unsigned char*)block.ptr;
if (c == '\t' || c == '\n')
c = ' ';
else if ((c & 0177) < XawSP || c == 0177) {
if (sink->ascii_sink.display_nonprinting)
c = c > 0177 ? (c & 7) + '0' : c + '@';
else
c = ' ';
}
if (font->per_char &&
(c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
rbearing = font->per_char[c - font->min_char_or_byte2].rbearing -
font->per_char[c - font->min_char_or_byte2].width;
if (rbearing > 0) {
paint = XtNew(XawTextPaintStruct);
paint->next = sink->text_sink.paint->bearings;
sink->text_sink.paint->bearings = paint;
paint->x = x - (paint->width = CharWidth(sink, font, 0, c));
paint->y = y + ascent;
paint->property = property;
paint->max_ascent = ascent;
paint->max_descent = descent;
paint->backtabs = NULL;
paint->highlight = highlight;
paint->length = 1;
paint->text = XtMalloc(1);
paint->text[0] = c;
}
}
}
else {
if (font->min_bounds.lbearing < 0) {
int lbearing = font->min_bounds.lbearing;
unsigned char c;
(void)XawTextSourceRead(ctx->text.source, position, &block, 1);
c = *(unsigned char*)block.ptr;
if (c == '\t' || c == '\n')
c = ' ';
else if ((c & 0177) < XawSP || c == 0177) {
if (sink->ascii_sink.display_nonprinting)
c = c > 0177 ? '\\' : c + '^';
else
c = ' ';
}
if (font->per_char &&
(c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
lbearing = font->per_char[c - font->min_char_or_byte2].lbearing;
if (lbearing < 0) {
paint = XtNew(XawTextPaintStruct);
paint->next = sink->text_sink.paint->bearings;
sink->text_sink.paint->bearings = paint;
paint->x = x;
paint->width = -CharWidth(sink, font, 0, c);
paint->y = y + ascent;
paint->property = property;
paint->max_ascent = ascent;
paint->max_descent = descent;
paint->backtabs = NULL;
paint->highlight = highlight;
paint->length = 1;
paint->text = XtMalloc(1);
paint->text[0] = c;
}
}
}
}
static void
AsciiPreparePaint(Widget w, int y, int line,
XawTextPosition from, XawTextPosition to, Bool highlight)
{
static XmuSegment segment;
static XmuScanline next;
static XmuScanline scanline = {0, &segment, &next};
static XmuArea area = {&scanline};
TextWidget ctx = (TextWidget)XtParent(w);
AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink;
XawTextPosition left, right, pos, pos2, tmp, length;
XawTextAnchor *anchor;
XawTextEntity *entity;
XawTextProperty *property;
int i, ascent = 0, descent = 0, xl, xr, x = ctx->text.left_margin, bufsiz;
XawTextBlock block;
XFontStruct *font;
XawTextPaintStruct *paint;
if (!sink->ascii_sink.echo)
return;
pos = tmp = left = ctx->text.lt.info[line].position;
right = ctx->text.lt.info[line + 1].position;
right = XawMin(right, ctx->text.lastPos + 1);
while (pos < right) {
if (XawTextSourceAnchorAndEntity(ctx->text.source, pos,
&anchor, &entity)) {
if ((property = XawTextSinkGetProperty((Widget)sink,
entity->property)) != NULL &&
(property->mask & XAW_TPROP_FONT))
font = property->font;
else
font = sink->ascii_sink.font;
tmp = pos;
pos = anchor->position + entity->offset + entity->length;
if ((length = XawMin(from, pos) - tmp) > 0)
x += GetTextWidth(ctx, x, font, tmp, length);
ascent = XawMax(font->ascent, ascent);
descent = XawMax(font->descent, descent);
}
else if (anchor) {
ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
descent = XawMax(sink->ascii_sink.font->descent, descent);
while (entity && pos < right) {
tmp = pos;
if ((pos = anchor->position + entity->offset) < tmp)
pos = tmp;
else {
if ((length = XawMin(from, pos) - tmp) > 0) {
x += GetTextWidth(ctx, x, sink->ascii_sink.font, tmp,
length);
tmp += length;
}
if (pos < right) {
pos += entity->length;
if ((property = XawTextSinkGetProperty((Widget)sink,
entity->property)) != NULL &&
(property->mask & XAW_TPROP_FONT))
font = property->font;
else
font = sink->ascii_sink.font;
if ((length = XawMin(from, pos) - tmp) > 0)
x += GetTextWidth(ctx, x, font, tmp, length);
ascent = XawMax(font->ascent, ascent);
descent = XawMax(font->descent, descent);
}
}
entity = entity->next;
}
if (anchor->entities == NULL) {
tmp = XawMin(pos, from);
if ((length = from - tmp) > 0)
x += GetTextWidth(ctx, x, sink->ascii_sink.font, tmp, length);
break;
}
}
else {
tmp = XawMin(pos, from);
if ((length = from - tmp) > 0)
x += GetTextWidth(ctx, x, sink->ascii_sink.font, tmp, length);
ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
descent = XawMax(sink->ascii_sink.font->descent, descent);
break;
}
}
if (!ascent)
ascent = sink->ascii_sink.font->ascent;
if (!descent)
descent = sink->ascii_sink.font->descent;
xl = x;
pos = from;
while (pos < to) {
paint = XtNew(XawTextPaintStruct);
paint->next = sink->text_sink.paint->paint;
sink->text_sink.paint->paint = paint;
paint->x = x;
paint->y = y + ascent;
paint->property = NULL;
paint->max_ascent = ascent;
paint->max_descent = descent;
paint->backtabs = NULL;
paint->highlight = highlight;
tmp = pos;
if (XawTextSourceAnchorAndEntity(ctx->text.source, pos,
&anchor, &entity)) {
pos = anchor->position + entity->offset + entity->length;
if ((paint->property = XawTextSinkGetProperty((Widget)sink,
entity->property)) != NULL &&
(paint->property->mask & XAW_TPROP_FONT))
font = paint->property->font;
else
font = sink->ascii_sink.font;
}
else {
if (anchor) {
while (entity && anchor->position + entity->offset < pos)
entity = entity->next;
if (entity)
pos = anchor->position + entity->offset;
else
pos = to;
}
else
pos = to;
font = sink->ascii_sink.font;
}
pos = XawMin(pos, to);
length = pos - tmp;
paint->text = XtMalloc(bufsiz = pos - tmp + 4);
paint->length = 0;
segment.x1 = x;
pos2 = tmp;
while (length > 0) {
pos2 = XawTextSourceRead(ctx->text.source, tmp, &block, length);
length = pos - pos2;
tmp = pos2;
for (i = 0; i < block.length; i++) {
unsigned char c = (unsigned char)block.ptr[i];
if (paint->length + 4 > bufsiz)
paint->text = XtRealloc(paint->text, bufsiz += 32);
paint->text[paint->length] = c;
if (c == '\n') {
x += CharWidth(sink, font, 0, ' ');
continue;
}
if (c == '\t') {
x += XTextWidth(font, paint->text, paint->length);
segment.x2 = x + CharWidth(sink, font, x, '\t');
if (XmuValidSegment(&segment)) {
if (!highlight && (paint->property &&
(paint->property->mask & XAW_TPROP_BACKGROUND))) {
if (ascent > font->ascent) {
scanline.y = y;
next.y = y + ascent - font->ascent;
XmuAreaOr(sink->text_sink.paint->clip, &area);
}
if (descent >= font->descent) {
scanline.y = y + ascent + font->descent;
next.y = scanline.y + descent - font->descent + 1;
XmuAreaOr(sink->text_sink.paint->clip, &area);
}
if (paint->backtabs == NULL)
paint->backtabs = XmuCreateArea();
scanline.y = y + ascent - font->ascent;
next.y = y + ascent + font->descent;
XmuAreaOr(paint->backtabs, &area);
}
else {
scanline.y = y;
next.y = ctx->text.lt.info[line + 1].y;
if (highlight) {
if (!sink->text_sink.paint->hightabs)
sink->text_sink.paint->hightabs =
XmuCreateArea();
XmuAreaOr(sink->text_sink.paint->hightabs, &area);
}
else
XmuAreaOr(sink->text_sink.paint->clip, &area);
}
}
paint->width = segment.x2 - segment.x1;
x = segment.x1 = segment.x2;
if (paint->length == 0) {
paint->x = x;
continue;
}
paint->text = XtRealloc(paint->text, paint->length);
property = paint->property;
paint = XtNew(XawTextPaintStruct);
paint->next = sink->text_sink.paint->paint;
sink->text_sink.paint->paint = paint;
paint->x = x;
paint->y = y + ascent;
paint->property = property;
paint->max_ascent = ascent;
paint->max_descent = descent;
paint->backtabs = NULL;
paint->highlight = highlight;
paint->text = XtMalloc(bufsiz = pos - tmp - length +
block.length - i + 4);
paint->length = 0;
continue;
}
if ((c & 0177) < XawSP || c == 0177) {
if (sink->ascii_sink.display_nonprinting) {
if (c > 0177) {
paint->text[paint->length++] = '\\';
paint->text[paint->length++] = ((c >> 6) & 7) + '0';
paint->text[paint->length++] = ((c >> 3) & 7) + '0';
paint->text[paint->length] = (c & 7) + '0';
}
else {
c |= 0100;
paint->text[paint->length++] = '^';
paint->text[paint->length] = c == 0177 ? '?' : c;
}
}
else
paint->text[paint->length] = ' ';
}
paint->length++;
}
}
x += XTextWidth(font, paint->text, paint->length);
segment.x2 = x;
if (XmuValidSegment(&segment)) {
{
scanline.y = y;
next.y = ctx->text.lt.info[line + 1].y;
XmuAreaOr(sink->text_sink.paint->clip, &area);
}
}
paint->width = x - segment.x1;
}
xr = x;
if (left < from) {
CalculateBearing(ctx, from - 1, xl, y, ascent, descent, highlight, True);
if (ctx->text.s.left < ctx->text.s.right) {
if (ctx->text.s.right == from)
CalculateBearing(ctx, from, xl, y, ascent, descent, True, False);
else if (ctx->text.s.left == from)
CalculateBearing(ctx, from, xl, y, ascent, descent, False, False);
}
}
right = XawMin(right, ctx->text.lastPos);
if (right >= to && to > from) {
if (to < right)
CalculateBearing(ctx, to, xr, y, ascent, descent, highlight, False);
if (ctx->text.s.left < ctx->text.s.right) {
if (ctx->text.s.right == to)
CalculateBearing(ctx, to - 1, xr, y, ascent, descent, False, True);
else if (ctx->text.s.left == to)
CalculateBearing(ctx, to - 1, xr, y, ascent, descent, True, True);
}
}
}
static int
qcmp_paint_struct(_Xconst void *left, _Xconst void *right)
{
return ((*(XawTextPaintStruct**)left)->property -
(*(XawTextPaintStruct**)right)->property);
}
static void
AsciiDoPaint(Widget w)
{
TextWidget ctx = (TextWidget)XtParent(w);
AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink;
XmuScanline *scan;
XmuSegment *seg;
XawTextPaintList *list = sink->text_sink.paint;
#if 0
XawTextPaintStruct *base, *head;
#endif
XawTextPaintStruct *paint = list->paint;
XawTextProperty *property;
XFontStruct *font = NULL;
XRectangle *rects;
int n_rects, i_rects;
GC gc;
Bool highlight;
XRectangle rect;
int width, height, line_width = -1;
XGCValues values;
for (scan = list->clip->scanline; scan && scan->next; scan = scan->next)
for (seg = scan->segment; seg; seg = seg->next)
_XawTextSinkClearToBackground(ctx->text.sink,
seg->x1, scan->y,
seg->x2 - seg->x1,
scan->next->y - scan->y);
#if 0
while (paint) {
base = paint;
head = paint->next;
while (head) {
if (head->property == paint->property) {
base->next = head->next;
head->next = paint->next;
paint->next = head;
paint = head;
}
base = head;
head = head->next;
}
paint = paint->next;
}
#endif
if (paint && paint->next) {
XawTextPaintStruct **paints;
int i = 0, n_paints = 0;
while (paint) {
paint = paint->next;
++n_paints;
}
paints = (XawTextPaintStruct**)
XtMalloc(n_paints * sizeof(XawTextPaintStruct));
paint = list->paint;
while (paint) {
paints[i++] = paint;
paint = paint->next;
}
qsort((void*)paints, n_paints, sizeof(XawTextPaintStruct*),
qcmp_paint_struct);
list->paint = paints[0];
for (i = 0; i < n_paints - 1; i++)
paints[i]->next = paints[i + 1];
paints[i]->next = NULL;
XtFree((XtPointer)paints);
}
gc = sink->ascii_sink.normgc;
rect.x = ctx->text.r_margin.left;
rect.y = ctx->text.r_margin.top;
width = (int)XtWidth(ctx) - RHMargins(ctx);
height = (int)XtHeight(ctx) - RVMargins(ctx);
rect.width = width;
rect.height = height;
if (width >= 0 && height >= 0)
XSetClipRectangles(XtDisplay((Widget)ctx), gc,
0, 0, &rect, 1, Unsorted);
else
XSetClipMask(XtDisplay((Widget)ctx), gc, None);
paint = list->paint;
property = NULL;
rects = NULL;
i_rects = n_rects = 0;
while (paint) {
if (paint->property && (paint->property->mask & XAW_TPROP_BACKGROUND)) {
if (property != paint->property) {
if (i_rects)
XFillRectangles(XtDisplay(ctx), XtWindow(ctx), gc,
rects, i_rects);
i_rects = 0;
property = paint->property;
if (property->mask & XAW_TPROP_FONT)
font = property->font;
else
font = sink->ascii_sink.font;
XSetForeground(XtDisplay(ctx), gc, property->background);
}
if (i_rects <= n_rects)
rects = (XRectangle*)
XtRealloc((XtPointer)rects, sizeof(XRectangle) *
++n_rects);
rects[i_rects].x = paint->x;
rects[i_rects].y = paint->y - font->ascent;
rects[i_rects].width = paint->width;
rects[i_rects++].height = font->ascent + font->descent;
if (paint->backtabs) {
for (scan = paint->backtabs->scanline; scan && scan->next;
scan = scan->next)
for (seg = scan->segment; seg; seg = seg->next) {
if (i_rects <= n_rects)
rects = (XRectangle*)
XtRealloc((XtPointer)rects, sizeof(XRectangle) *
++n_rects);
rects[i_rects].x = seg->x1;
rects[i_rects].y = scan->y;
rects[i_rects].width = seg->x2 - seg->x1;
rects[i_rects++].height = scan->next->y - scan->y;
}
}
}
paint = paint->next;
}
if (i_rects)
XFillRectangles(XtDisplay(ctx), XtWindow(ctx), gc, rects, i_rects);
paint = list->paint;
i_rects = 0;
while (paint) {
if (paint->highlight) {
if (i_rects == 0)
XSetForeground(XtDisplay(ctx), gc, sink->text_sink.cursor_color);
if (i_rects <= n_rects)
rects = (XRectangle*)
XtRealloc((XtPointer)rects, sizeof(XRectangle) *
++n_rects);
rects[i_rects].x = paint->x;
rects[i_rects].y = paint->y - paint->max_ascent;
rects[i_rects].width = paint->width;
rects[i_rects++].height = paint->max_ascent + paint->max_descent + 1;
}
paint = paint->next;
}
if (list->hightabs) {
for (scan = list->hightabs->scanline; scan && scan->next;
scan = scan->next)
for (seg = scan->segment; seg; seg = seg->next) {
if (i_rects == 0)
XSetForeground(XtDisplay(ctx), gc,
sink->text_sink.cursor_color);
if (i_rects <= n_rects)
rects = (XRectangle*)
XtRealloc((XtPointer)rects, sizeof(XRectangle) *
++n_rects);
rects[i_rects].x = seg->x1;
rects[i_rects].y = scan->y;
rects[i_rects].width = seg->x2 - seg->x1;
rects[i_rects++].height = scan->next->y - scan->y;
}
}
if (i_rects)
XFillRectangles(XtDisplay(ctx), XtWindow(ctx), gc, rects, i_rects);
if (rects)
XtFree((XtPointer)rects);
paint = list->paint;
if (paint && (property = paint->property) == NULL) {
font = sink->ascii_sink.font;
XSetFont(XtDisplay(ctx), gc, font->fid);
if (!paint->highlight)
XSetForeground(XtDisplay(ctx), gc, sink->text_sink.foreground);
}
else
property = NULL;
highlight = False;
while (paint) {
if (!highlight && paint->highlight)
XSetForeground(XtDisplay(ctx), gc, sink->text_sink.background);
if (highlight || paint->highlight || paint->property != property) {
if (!paint->property || !(paint->property->mask & XAW_TPROP_FONT))
font = sink->ascii_sink.font;
else
font = paint->property->font;
XSetFont(XtDisplay(ctx), gc, font->fid);
if (!paint->highlight) {
if (!paint->property ||
!(paint->property->mask & XAW_TPROP_FOREGROUND))
XSetForeground(XtDisplay(ctx), gc,
sink->text_sink.foreground);
else
XSetForeground(XtDisplay(ctx), gc,
paint->property->foreground);
}
highlight = paint->highlight;
property = paint->property;
}
if (paint->x < XtWidth(ctx) && paint->x + paint->width > 0) {
XDrawString(XtDisplay(ctx), XtWindow(ctx), gc, paint->x, paint->y,
paint->text, paint->length);
if (property) {
if (property->mask & XAW_TPROP_UNDERLINE) {
if (line_width != property->underline_thickness) {
values.line_width = line_width =
property->underline_thickness;
XChangeGC(XtDisplay(ctx), gc, GCLineWidth, &values);
}
XDrawLine(XtDisplay(ctx), XtWindow(ctx), gc, paint->x,
paint->y + property->underline_position,
paint->x + paint->width,
paint->y + property->underline_position);
}
if (property->mask & XAW_TPROP_OVERSTRIKE) {
if (line_width != property->underline_thickness) {
values.line_width = line_width =
property->underline_thickness;
XChangeGC(XtDisplay(ctx), gc, GCLineWidth, &values);
}
XDrawLine(XtDisplay(ctx), XtWindow(ctx), gc, paint->x,
paint->y - (font->ascent>>1) + (font->descent>>1),
paint->x + paint->width,
paint->y - (font->ascent>>1) + (font->descent>>1));
}
}
}
paint = paint->next;
}
paint = list->bearings;
while (paint) {
XRectangle rect;
if (paint->highlight)
XSetForeground(XtDisplay(ctx), gc, sink->text_sink.background);
if (!paint->property || !(paint->property->mask & XAW_TPROP_FONT))
font = sink->ascii_sink.font;
else
font = paint->property->font;
XSetFont(XtDisplay(ctx), gc, font->fid);
if (!paint->highlight) {
if (!paint->property ||
!(paint->property->mask & XAW_TPROP_FOREGROUND))
XSetForeground(XtDisplay(ctx), gc, sink->text_sink.foreground);
else
XSetForeground(XtDisplay(ctx), gc, paint->property->foreground);
}
if (paint->x < XtWidth(ctx) && paint->x + paint->width > 0) {
rect.x = paint->x + paint->width;
rect.width = XawAbs(paint->width);
rect.y = paint->y - font->ascent;
rect.height = rect.y + font->ascent + font->descent;
XSetClipRectangles(XtDisplay((Widget)ctx), gc,
0, 0, &rect, 1, Unsorted);
XDrawString(XtDisplay(ctx), XtWindow(ctx), gc, paint->x, paint->y,
paint->text, paint->length);
}
paint = paint->next;
}
}
#endif
static unsigned int
PaintText(Widget w, GC gc, int x, int y, char *buf, int len, Bool clear_bg)
{
AsciiSinkObject sink = (AsciiSinkObject)w;
TextWidget ctx = (TextWidget)XtParent(w);
int width = XTextWidth(sink->ascii_sink.font, buf, len);
if ((x > XtWidth(ctx)) || width <= -x)
return (width);
if (clear_bg) {
_XawTextSinkClearToBackground(w, x, y - sink->ascii_sink.font->ascent,
width, sink->ascii_sink.font->ascent
+ sink->ascii_sink.font->descent);
XDrawString(XtDisplay(ctx), XtWindow(ctx), gc, x, y, buf, len);
}
else
XDrawImageString(XtDisplay(ctx), XtWindow(ctx), gc, x, y, buf, len);
return (width);
}
static void
DisplayText(Widget w, int x, int y,
XawTextPosition pos1, XawTextPosition pos2, Bool highlight)
{
TextWidget ctx = (TextWidget)XtParent(w);
AsciiSinkObject sink = (AsciiSinkObject)w;
XFontStruct *font = sink->ascii_sink.font;
Widget source = XawTextGetSource(XtParent(w));
unsigned char buf[260];
int j, k;
XawTextBlock blk;
GC gc, invgc, tabgc;
int max_x;
Bool clear_bg;
if (!sink->ascii_sink.echo || !ctx->text.lt.lines)
return;
max_x = (int)XtWidth(ctx) - ctx->text.r_margin.right;
clear_bg = !highlight && ctx->core.background_pixmap != XtUnspecifiedPixmap;
gc = highlight ? sink->ascii_sink.invgc : sink->ascii_sink.normgc;
invgc = highlight ? sink->ascii_sink.normgc : sink->ascii_sink.invgc;
if (highlight && sink->ascii_sink.xorgc)
tabgc = sink->ascii_sink.xorgc;
else
tabgc = invgc;
y += sink->ascii_sink.font->ascent;
for (j = 0; pos1 < pos2;) {
pos1 = XawTextSourceRead(source, pos1, &blk, pos2 - pos1);
for (k = 0; k < blk.length; k++) {
if (j >= sizeof(buf) - 4) {
if ((x += PaintText(w, gc, x, y, (char*)buf, j, clear_bg))
>= max_x)
return;
j = 0;
}
buf[j] = blk.ptr[k];
if (buf[j] == XawLF)
continue;
else if (buf[j] == '\t') {
int width;
if (j != 0
&& (x += PaintText(w, gc, x, y, (char*)buf, j, clear_bg))
>= max_x)
return;
if ((width = CharWidth(sink, font, x, '\t')) > -x) {
if (clear_bg)
_XawTextSinkClearToBackground(w, x, y-font->ascent, width,
font->ascent+font->descent);
else
XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
tabgc, x, y - font->ascent, width,
font->ascent + font->descent);
}
if ((x += width) >= max_x)
return;
j = -1;
}
else if ((buf[j] & 0177) < XawSP || buf[j] == 0177) {
if (sink->ascii_sink.display_nonprinting) {
unsigned char c = buf[j];
if (c > 0177) {
buf[j++] = '\\';
buf[j++] = ((c >> 6) & 7) + '0';
buf[j++] = ((c >> 3) & 7) + '0';
buf[j] = (c & 7) + '0';
}
else {
c |= 0100;
buf[j++] = '^';
buf[j] = c == 0177 ? '?' : c;
}
}
else
buf[j] = ' ';
}
j++;
}
}
if (j > 0)
(void)PaintText(w, gc, x, y, (char*)buf, j, clear_bg);
}
static void
GetCursorBounds(Widget w, XRectangle *rect)
{
AsciiSinkObject sink = (AsciiSinkObject)w;
XFontStruct *font = sink->ascii_sink.font;
unsigned char ch;
#ifndef OLDXAW
TextWidget ctx = (TextWidget)XtParent(w);
XawTextBlock block;
XawTextAnchor *anchor;
XawTextEntity *entity;
XawTextProperty *property;
if (XawTextSourceAnchorAndEntity(XawTextGetSource(XtParent(w)),
sink->ascii_sink.cursor_position,
&anchor, &entity)) {
if ((property = XawTextSinkGetProperty((Widget)sink,
entity->property)) != NULL &&
(property->mask & XAW_TPROP_FONT))
font = property->font;
}
(void)XawTextSourceRead(XawTextGetSource((Widget)ctx),
ctx->text.insertPos, &block, 1);
if (!block.length || block.ptr[0] == '\n' || block.ptr[0] == '\t')
ch = ' ';
else if ((*((unsigned char*)block.ptr) & 0177) < XawSP ||
*(unsigned char*)block.ptr == 0177) {
if (sink->ascii_sink.display_nonprinting)
ch = *((unsigned char*)block.ptr) > 0177 ? '\\' : '^';
else
ch = ' ';
}
else
ch = *(unsigned char*)block.ptr;
#else
ch = ' ';
#endif
rect->width = CharWidth(sink, font, 0, ch);
rect->height = font->descent + font->ascent + 1;
rect->x = sink->ascii_sink.cursor_x;
rect->y = sink->ascii_sink.cursor_y - font->ascent;
}
static int
FindCursorY(TextWidget ctx, XawTextPosition position)
{
int y, line, ascent;
AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink;
#ifndef OLDXAW
XawTextAnchor *anchor;
XawTextEntity *entity;
XawTextProperty *property;
XawTextPosition left, right;
#endif
for (line = 0; line < ctx->text.lt.lines; line++)
if (position < ctx->text.lt.info[line + 1].position)
break;
y = ctx->text.lt.info[line].y;
#ifndef OLDXAW
ascent = 0;
left = ctx->text.lt.info[line].position;
right = ctx->text.lt.info[line + 1].position;
right = XawMin(right, ctx->text.lastPos + 1);
while (left < right) {
if (XawTextSourceAnchorAndEntity(ctx->text.source, left,
&anchor, &entity)) {
if ((property = XawTextSinkGetProperty((Widget)sink,
entity->property)) != NULL &&
(property->mask & XAW_TPROP_FONT))
ascent = XawMax(property->font->ascent, ascent);
else
ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
left = anchor->position + entity->offset + entity->length;
}
else if (anchor) {
ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
while (entity) {
XawTextPosition tmp = anchor->position + entity->offset + entity->length;
if (tmp > left && tmp < right) {
left = tmp;
if ((property = XawTextSinkGetProperty((Widget)sink,
entity->property)) != NULL &&
(property->mask & XAW_TPROP_FONT))
ascent = XawMax(property->font->ascent, ascent);
else
ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
}
entity = entity->next;
}
if (entity == NULL)
break;
}
else {
ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
break;
}
}
if (!ascent)
ascent = sink->ascii_sink.font->ascent;
#else
ascent = sink->ascii_sink.font->ascent;
#endif
return (y + ascent);
}
static void
InsertCursor(Widget w, int x, int y, XawTextInsertState state)
{
AsciiSinkObject sink = (AsciiSinkObject)w;
XFontStruct *font = sink->ascii_sink.font;
TextWidget ctx = (TextWidget)XtParent(w);
XawTextPosition position = XawTextGetInsertionPoint((Widget)ctx);
Boolean overflow = (x & 0xffff8000) != 0;
#ifndef OLDXAW
XawTextAnchor *anchor;
XawTextEntity *entity;
XawTextProperty *property;
#endif
if (XtIsRealized((Widget)ctx)) {
int fheight;
XawTextBlock block;
XawTextPosition selection_start, selection_end;
Boolean has_selection;
if (!sink->ascii_sink.echo) {
if (sink->ascii_sink.laststate != state) {
int width = CharWidth(sink, font, 0, ' ') - 1;
x = ctx->text.margin.left;
y = ctx->text.margin.top;
font = sink->ascii_sink.font;
fheight = font->ascent + font->descent;
if (state == XawisOn) {
if (ctx->text.hasfocus)
XFillRectangle(XtDisplay(ctx), XtWindow(ctx),
sink->ascii_sink.xorgc, x, y,
width + 1, fheight + 1);
else
XDrawRectangle(XtDisplay(ctx), XtWindow(ctx),
sink->ascii_sink.xorgc, x, y,
width, fheight);
}
else
_XawTextSinkClearToBackground(w, x, y,
width + 1, fheight + 1);
}
sink->ascii_sink.cursor_x = x;
sink->ascii_sink.cursor_y = y;
sink->ascii_sink.laststate = state;
return;
}
XawTextGetSelectionPos((Widget)ctx, &selection_start, &selection_end);
has_selection = selection_start != selection_end;
if (sink->ascii_sink.laststate != state) {
unsigned char ch;
#ifndef OLDXAW
if (XawTextSourceAnchorAndEntity(ctx->text.source,
position, &anchor, &entity) &&
(property = XawTextSinkGetProperty((Widget)sink,
entity->property)) != NULL &&
(property->mask & XAW_TPROP_FONT))
font = property->font;
else
font = sink->ascii_sink.font;
#endif
fheight = font->ascent + font->descent;
(void)XawTextSourceRead(XawTextGetSource((Widget)ctx),
position, &block, 1);
if (!block.length || block.ptr[0] == '\n' || block.ptr[0] == '\t')
ch = ' ';
else if ((*((unsigned char*)block.ptr) & 0177) < XawSP
|| *(unsigned char*)block.ptr == 0177) {
if (sink->ascii_sink.display_nonprinting)
ch = *((unsigned char*)block.ptr) > 0177 ? '\\' : '^';
else
ch = ' ';
}
else
ch = *(unsigned char*)block.ptr;
y = FindCursorY(ctx, position);
if (ctx->text.hasfocus && !has_selection)
XFillRectangle(XtDisplay(ctx), XtWindow(ctx),
sink->ascii_sink.xorgc, x, y - font->ascent,
CharWidth(sink, font, 0, ch), fheight + 1);
else
XDrawRectangle(XtDisplay(ctx), XtWindow(ctx),
sink->ascii_sink.xorgc, x, y - font->ascent,
CharWidth(sink, font, 0, ch) - 1, fheight);
}
}
sink->ascii_sink.cursor_x = overflow ? -16384 : x;
sink->ascii_sink.cursor_y = y;
sink->ascii_sink.laststate = state;
sink->ascii_sink.cursor_position = position;
}
static void
FindDistance(Widget w, XawTextPosition fromPos, int fromx,
XawTextPosition toPos, int *resWidth,
XawTextPosition *resPos, int *resHeight)
{
#ifndef OLDXAW
AsciiSinkObject sink = (AsciiSinkObject)w;
TextWidget ctx = (TextWidget)XtParent(w);
XFontStruct *font = sink->ascii_sink.font;
Widget source = ctx->text.source;
XawTextPosition idx, pos;
unsigned char c;
XawTextBlock blk;
int i, rWidth, ascent = 0, descent = 0;
XawTextAnchor *anchor;
XawTextEntity *entity;
XawTextProperty *property;
Cardinal length;
Bool done = False;
pos = idx = fromPos;
rWidth = 0;
c = 0;
while (!done) {
if (XawTextSourceAnchorAndEntity(source, pos, &anchor, &entity)) {
length = anchor->position + entity->offset + entity->length;
length = XawMin(toPos, length) - pos;
if ((property = XawTextSinkGetProperty((Widget)sink,
entity->property)) != NULL &&
(property->mask & XAW_TPROP_FONT))
font = property->font;
else
font = sink->ascii_sink.font;
}
else {
if (anchor) {
while (entity && anchor->position + entity->offset < pos)
entity = entity->next;
if (entity) {
length = anchor->position + entity->offset;
length = XawMin(toPos, length) - pos;
}
else
length = XawMin(toPos - pos, 4096);
}
else
length = XawMin(toPos - pos, 4096);
font = sink->ascii_sink.font;
}
ascent = XawMax(font->ascent, ascent);
descent = XawMax(font->descent, descent);
pos = XawTextSourceRead(source, pos, &blk, length);
if (blk.length == 0 && pos == idx)
break;
idx = blk.firstPos;
for (i = 0; idx < toPos; i++, idx++) {
if (i >= blk.length)
break;
c = blk.ptr[i];
rWidth += CharWidth(sink, font, fromx + rWidth, c);
if (c == XawLF) {
idx++;
done = True;
break;
}
}
if (idx >= toPos)
break;
}
*resPos = idx;
*resWidth = rWidth;
*resHeight = ascent + descent + 1;
#else
AsciiSinkObject sink = (AsciiSinkObject)w;
TextWidget ctx = (TextWidget)XtParent(w);
XFontStruct *font = sink->ascii_sink.font;
Widget source = ctx->text.source;
XawTextPosition idx, pos;
unsigned char c;
XawTextBlock blk;
int i, rWidth;
pos = XawTextSourceRead(source, fromPos, &blk, toPos - fromPos);
rWidth = 0;
for (i = 0, idx = fromPos; idx < toPos; i++, idx++) {
if (i >= blk.length) {
i = 0;
pos = XawTextSourceRead(source, pos, &blk, toPos - pos);
if (blk.length == 0)
break;
}
c = blk.ptr[i];
rWidth += CharWidth(sink, font, fromx + rWidth, c);
if (c == XawLF) {
idx++;
break;
}
}
*resPos = idx;
*resWidth = rWidth;
*resHeight = font->ascent + font->descent + 1;
#endif
}
static void
FindPosition(Widget w, XawTextPosition fromPos, int fromx, int width,
Bool stopAtWordBreak, XawTextPosition *resPos,
int *resWidth, int *resHeight)
{
#ifndef OLDXAW
AsciiSinkObject sink = (AsciiSinkObject)w;
TextWidget ctx = (TextWidget)XtParent(w);
Widget source = ctx->text.source;
XFontStruct *font = sink->ascii_sink.font;
XawTextPosition idx, pos, whiteSpacePosition = 0;
int i, lastWidth, whiteSpaceWidth, rWidth, ascent = 0, descent = 0;
Boolean whiteSpaceSeen;
unsigned char c;
XawTextBlock blk;
XawTextAnchor *anchor;
XawTextEntity *entity;
XawTextProperty *property;
Cardinal length;
Bool done = False;
pos = idx = fromPos;
rWidth = lastWidth = whiteSpaceWidth = 0;
whiteSpaceSeen = False;
c = 0;
while (!done) {
font = sink->ascii_sink.font;
if (XawTextSourceAnchorAndEntity(source, pos, &anchor, &entity)) {
length = anchor->position + entity->offset + entity->length - pos;
if ((property = XawTextSinkGetProperty((Widget)sink,
entity->property)) != NULL &&
(property->mask & XAW_TPROP_FONT))
font = property->font;
}
else {
if (anchor) {
while (entity && anchor->position + entity->offset < pos)
entity = entity->next;
if (entity)
length = anchor->position + entity->offset - pos;
else
length = 4096;
}
else
length = 4096;
}
ascent = XawMax(font->ascent, ascent);
descent = XawMax(font->descent, descent);
pos = XawTextSourceRead(source, pos, &blk, length);
if (blk.length == 0 && pos == idx)
break;
idx = blk.firstPos;
for (i = 0; rWidth <= width && i < blk.length; i++, idx++) {
c = blk.ptr[i];
lastWidth = rWidth;
rWidth += CharWidth(sink, font, fromx + rWidth, c);
if (c == XawLF) {
idx++;
done = True;
break;
}
else if ((c == XawSP || c == XawTAB) && rWidth <= width) {
whiteSpaceSeen = True;
whiteSpacePosition = idx;
whiteSpaceWidth = rWidth;
}
}
if (rWidth > width)
break;
}
if (rWidth > width && idx > fromPos) {
idx--;
rWidth = lastWidth;
if (stopAtWordBreak && whiteSpaceSeen) {
idx = whiteSpacePosition + 1;
rWidth = whiteSpaceWidth;
}
}
if (idx >= ctx->text.lastPos && c != XawLF)
idx = ctx->text.lastPos + 1;
*resPos = idx;
*resWidth = rWidth;
*resHeight = ascent + descent + 1;
#else
AsciiSinkObject sink = (AsciiSinkObject)w;
TextWidget ctx = (TextWidget)XtParent(w);
Widget source = ctx->text.source;
XFontStruct *font = sink->ascii_sink.font;
XawTextPosition idx, pos, whiteSpacePosition = 0;
int i, lastWidth, whiteSpaceWidth, rWidth;
Boolean whiteSpaceSeen;
unsigned char c;
XawTextBlock blk;
pos = XawTextSourceRead(source, fromPos, &blk, BUFSIZ);
rWidth = lastWidth = whiteSpaceWidth = 0;
whiteSpaceSeen = False;
c = 0;
for (i = 0, idx = fromPos; rWidth <= width; i++, idx++) {
if (i >= blk.length) {
i = 0;
pos = XawTextSourceRead(source, pos, &blk, BUFSIZ);
if (blk.length == 0)
break;
}
c = blk.ptr[i];
lastWidth = rWidth;
rWidth += CharWidth(sink, font, fromx + rWidth, c);
if (c == XawLF) {
idx++;
break;
}
else if ((c == XawSP || c == XawTAB) && rWidth <= width) {
whiteSpaceSeen = True;
whiteSpacePosition = idx;
whiteSpaceWidth = rWidth;
}
}
if (rWidth > width && idx > fromPos) {
idx--;
rWidth = lastWidth;
if (stopAtWordBreak && whiteSpaceSeen) {
idx = whiteSpacePosition + 1;
rWidth = whiteSpaceWidth;
}
}
if (idx >= ctx->text.lastPos && c != XawLF)
idx = ctx->text.lastPos + 1;
*resPos = idx;
*resWidth = rWidth;
*resHeight = font->ascent + font->descent + 1;
#endif
}
static void
Resolve(Widget w, XawTextPosition pos, int fromx, int width,
XawTextPosition *pos_return)
{
int resWidth, resHeight;
Widget source = XawTextGetSource(XtParent(w));
FindPosition(w, pos, fromx, width, False, pos_return, &resWidth, &resHeight);
if (*pos_return > GETLASTPOS)
*pos_return = GETLASTPOS;
}
static void
GetGC(AsciiSinkObject sink)
{
XtGCMask valuemask = (GCFont | GCGraphicsExposures | GCClipXOrigin |
GCForeground | GCBackground);
XGCValues values;
values.clip_x_origin = (long)sink;
values.clip_mask = None;
values.font = sink->ascii_sink.font->fid;
values.graphics_exposures = False;
values.foreground = sink->text_sink.foreground;
values.background = sink->text_sink.background;
sink->ascii_sink.normgc = XtAllocateGC((Widget)sink, 0, valuemask, &values,
GCClipMask | GCFont | GCForeground |
GCBackground, 0);
values.foreground = sink->text_sink.background;
#ifndef OLDXAW
values.background = sink->text_sink.cursor_color;
#else
values.background = sink->text_sink.foreground;
#endif
sink->ascii_sink.invgc = XtAllocateGC((Widget)sink, 0, valuemask, &values,
GCClipMask | GCFont, 0);
valuemask |= GCFunction;
values.function = GXxor;
#ifndef OLDXAW
values.foreground = sink->text_sink.background ^ sink->text_sink.cursor_color;
#else
values.foreground = sink->text_sink.background ^ sink->text_sink.foreground;
#endif
values.background = 0L;
sink->ascii_sink.xorgc = XtAllocateGC((Widget)sink, 0, valuemask,
&values, GCClipMask | GCFont, 0);
XawAsciiSinkResize((Widget)sink);
}
static void
XawAsciiSinkInitialize(Widget request, Widget cnew,
ArgList args, Cardinal *num_args)
{
AsciiSinkObject sink = (AsciiSinkObject)cnew;
GetGC(sink);
if (!sink->ascii_sink.font) XtError("Aborting: no font found\n");
sink->ascii_sink.cursor_position = 0;
sink->ascii_sink.laststate = XawisOff;
sink->ascii_sink.cursor_x = sink->ascii_sink.cursor_y = 0;
}
static void
XawAsciiSinkDestroy(Widget w)
{
AsciiSinkObject sink = (AsciiSinkObject)w;
XtReleaseGC(w, sink->ascii_sink.normgc);
XtReleaseGC(w, sink->ascii_sink.invgc);
XtReleaseGC(w, sink->ascii_sink.xorgc);
sink->ascii_sink.normgc =
sink->ascii_sink.invgc =
sink->ascii_sink.xorgc = NULL;
}
static void
XawAsciiSinkResize(Widget w)
{
TextWidget ctx = (TextWidget)XtParent(w);
AsciiSinkObject sink = (AsciiSinkObject)w;
XRectangle rect;
int width, height;
if (w->core.widget_class != asciiSinkObjectClass)
return;
rect.x = ctx->text.r_margin.left;
rect.y = ctx->text.r_margin.top;
width = (int)XtWidth(ctx) - RHMargins(ctx);
height = (int)XtHeight(ctx) - RVMargins(ctx);
rect.width = width;
rect.height = height;
if (sink->ascii_sink.normgc) {
if (width >= 0 && height >= 0)
XSetClipRectangles(XtDisplay((Widget)ctx), sink->ascii_sink.normgc,
0, 0, &rect, 1, Unsorted);
else
XSetClipMask(XtDisplay((Widget)ctx), sink->ascii_sink.normgc, None);
}
if (sink->ascii_sink.invgc) {
if (width >= 0 && height >= 0)
XSetClipRectangles(XtDisplay((Widget)ctx), sink->ascii_sink.invgc,
0, 0, &rect, 1, Unsorted);
else
XSetClipMask(XtDisplay((Widget)ctx), sink->ascii_sink.invgc, None);
}
if (sink->ascii_sink.xorgc) {
if (width >= 0 && height >= 0)
XSetClipRectangles(XtDisplay((Widget)ctx), sink->ascii_sink.xorgc,
0, 0, &rect, 1, Unsorted);
else
XSetClipMask(XtDisplay((Widget)ctx), sink->ascii_sink.xorgc, None);
}
}
static Boolean
XawAsciiSinkSetValues(Widget current, Widget request, Widget cnew,
ArgList args, Cardinal *num_args)
{
AsciiSinkObject w = (AsciiSinkObject)cnew;
AsciiSinkObject old_w = (AsciiSinkObject)current;
if (w->ascii_sink.font != old_w->ascii_sink.font
|| w->text_sink.background != old_w->text_sink.background
|| w->text_sink.foreground != old_w->text_sink.foreground
#ifndef OLDXAW
|| w->text_sink.cursor_color != old_w->text_sink.cursor_color
|| w->text_sink.properties != old_w->text_sink.properties
#endif
) {
#ifdef OLDXAW
XtReleaseGC(cnew, w->ascii_sink.normgc);
XtReleaseGC(cnew, w->ascii_sink.invgc);
XtReleaseGC(cnew, w->ascii_sink.xorgc);
GetGC(w);
#endif
((TextWidget)XtParent(cnew))->text.redisplay_needed = True;
}
else if (w->ascii_sink.echo != old_w->ascii_sink.echo
|| w->ascii_sink.display_nonprinting
!= old_w->ascii_sink.display_nonprinting)
((TextWidget)XtParent(cnew))->text.redisplay_needed = True;
#ifndef OLDXAW
if (w->text_sink.properties != old_w->text_sink.properties) {
XawTextProperty *property =
XawTextSinkGetProperty(cnew, XrmStringToQuark("default"));
if (property) {
if (property->mask & XAW_TPROP_FONT)
w->ascii_sink.font = property->font;
if (property->mask & XAW_TPROP_FOREGROUND)
w->text_sink.foreground = property->foreground;
if (property->mask & XAW_TPROP_BACKGROUND)
w->text_sink.background = property->background;
}
}
#endif
return (False);
}
static int
MaxLines(Widget w, unsigned int height)
{
AsciiSinkObject sink = (AsciiSinkObject)w;
int font_height;
font_height = sink->ascii_sink.font->ascent + sink->ascii_sink.font->descent + 1;
return ((int)height / font_height);
}
static int
MaxHeight(Widget w, int lines)
{
AsciiSinkObject sink = (AsciiSinkObject)w;
return (lines * (sink->ascii_sink.font->ascent +
sink->ascii_sink.font->descent + 1));
}
static void
SetTabs(Widget w, int tab_count, short *tabs)
{
AsciiSinkObject sink = (AsciiSinkObject)w;
int i;
Atom XA_FIGURE_WIDTH;
unsigned long figure_width = 0;
XFontStruct *font = sink->ascii_sink.font;
XA_FIGURE_WIDTH = XInternAtom(XtDisplayOfObject(w), "FIGURE_WIDTH", False);
if (XA_FIGURE_WIDTH != None
&& (!XGetFontProperty(font, XA_FIGURE_WIDTH, &figure_width)
|| figure_width == 0)) {
if (font->per_char && font->min_char_or_byte2 <= '$'
&& font->max_char_or_byte2 >= '$')
figure_width = font->per_char['$' - font->min_char_or_byte2].width;
else
figure_width = font->max_bounds.width;
}
if (tab_count > sink->text_sink.tab_count) {
sink->text_sink.tabs = (Position *)
XtRealloc((char*)sink->text_sink.tabs, tab_count * sizeof(Position));
sink->text_sink.char_tabs = (short *)
XtRealloc((char*)sink->text_sink.char_tabs, tab_count * sizeof(short));
}
for (i = 0 ; i < tab_count ; i++) {
sink->text_sink.tabs[i] = tabs[i] * figure_width;
sink->text_sink.char_tabs[i] = tabs[i];
}
sink->text_sink.tab_count = tab_count;
#ifndef NO_TAB_FIX
{
TextWidget ctx = (TextWidget)XtParent(w);
ctx->text.redisplay_needed = True;
_XawTextBuildLineTable(ctx, ctx->text.lt.top, True);
}
#endif
}