1 /***********************************************************
3 Copyright 1987, 1988, 1994, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
26 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46 ******************************************************************/
53 #include <X11/IntrinsicP.h>
54 #include <X11/StringDefs.h>
55 #include <X11/Xatom.h>
56 #include <X11/Xaw/XawInit.h>
57 #include <X11/Xaw/AsciiSinkP.h>
58 #include <X11/Xaw/AsciiSrcP.h>
59 #include <X11/Xaw/TextP.h>
63 #undef GETLASTPOS /* We will use our own GETLASTPOS */
67 XawTextSourceScan(source, 0, XawstAll, XawsdRight, 1, True)
72 static void XawAsciiSinkClassPartInitialize(WidgetClass);
73 static void XawAsciiSinkInitialize(Widget, Widget, ArgList, Cardinal*);
74 static void XawAsciiSinkDestroy(Widget);
75 static void XawAsciiSinkResize(Widget);
76 static Boolean XawAsciiSinkSetValues(Widget, Widget, Widget,
78 static int MaxLines(Widget, unsigned int);
79 static int MaxHeight(Widget, int);
80 static void SetTabs(Widget, int, short*);
81 static void DisplayText(Widget, int, int,
82 XawTextPosition, XawTextPosition, Bool);
83 static void InsertCursor(Widget, int, int, XawTextInsertState);
84 static void FindPosition(Widget, XawTextPosition, int, int, Bool,
85 XawTextPosition*, int*, int*);
86 static void FindDistance(Widget, XawTextPosition, int, XawTextPosition, int*,
87 XawTextPosition*, int*);
88 static void Resolve(Widget, XawTextPosition, int, int, XawTextPosition*);
89 static void GetCursorBounds(Widget, XRectangle*);
91 static void AsciiPreparePaint(Widget, int, int,
92 XawTextPosition, XawTextPosition, Bool);
93 static void AsciiDoPaint(Widget);
99 static void GetGC(AsciiSinkObject);
100 static int CharWidth(AsciiSinkObject, XFontStruct*, int, unsigned int);
101 static unsigned int PaintText(Widget w, GC gc, int x, int y,
102 char *buf, int len, Bool);
105 * Defined in TextSink.c
107 void _XawTextSinkClearToBackground(Widget, int, int, unsigned, unsigned);
112 #define offset(field) XtOffsetOf(AsciiSinkRec, ascii_sink.field)
113 static XtResource resources[] = {
118 sizeof(XFontStruct*),
133 XtNdisplayNonprinting,
137 offset(display_nonprinting),
145 #define Superclass (&textSinkClassRec)
146 AsciiSinkClassRec asciiSinkClassRec = {
149 (WidgetClass)Superclass, /* superclass */
150 "AsciiSink", /* class_name */
151 sizeof(AsciiSinkRec), /* widget_size */
152 XawInitializeWidgetSet, /* class_initialize */
153 XawAsciiSinkClassPartInitialize, /* class_part_initialize */
154 False, /* class_inited */
155 XawAsciiSinkInitialize, /* initialize */
156 NULL, /* initialize_hook */
160 resources, /* resources */
161 XtNumber(resources), /* num_resources */
162 NULLQUARK, /* xrm_class */
167 XawAsciiSinkDestroy, /* destroy */
168 (XtProc)XawAsciiSinkResize, /* obj8 */
170 XawAsciiSinkSetValues, /* set_values */
171 NULL, /* set_values_hook */
173 NULL, /* get_values_hook */
175 XtVersion, /* version */
176 NULL, /* callback_private */
180 NULL, /* extension */
184 DisplayText, /* DisplayText */
185 InsertCursor, /* InsertCursor */
186 XtInheritClearToBackground, /* ClearToBackground */
187 FindPosition, /* FindPosition */
188 FindDistance, /* FindDistance */
189 Resolve, /* Resolve */
190 MaxLines, /* MaxLines */
191 MaxHeight, /* MaxHeight */
192 SetTabs, /* SetTabs */
193 GetCursorBounds, /* GetCursorBounds */
200 NULL, /* extension */
204 WidgetClass asciiSinkObjectClass = (WidgetClass)&asciiSinkClassRec;
210 XawAsciiSinkClassPartInitialize(WidgetClass wc)
213 AsciiSinkObjectClass cclass = (AsciiSinkObjectClass)wc;
214 XrmQuark record_type = XrmPermStringToQuark("TextSink");
215 TextSinkExt ext = cclass->text_sink_class.extension;
218 if (ext->record_type == record_type &&
220 ext->PreparePaint = AsciiPreparePaint;
221 ext->DoPaint = AsciiDoPaint;
224 ext = (TextSinkExt)ext->next_extension;
227 XtError("TextSinkClass: cannot resolve extension.\n");
232 CharWidth(AsciiSinkObject sink, XFontStruct *font, int x, unsigned int c)
244 /* Adjust for Left Margin */
245 x -= ((TextWidget)XtParent((Widget)sink))->text.left_margin;
248 tab = sink->text_sink.tabs;
251 if (x >= 0 && x < *tab)
254 if (++i >= sink->text_sink.tab_count) {
257 tab = sink->text_sink.tabs;
267 if ((c & 0177) < XawSP || c == 0177) {
268 if (sink->ascii_sink.display_nonprinting) {
270 width = CharWidth(sink, font, x, '\\');
271 width += CharWidth(sink, font, x, ((c >> 6) & 7) + '0');
272 width += CharWidth(sink, font, x, ((c >> 3) & 7) + '0');
276 width = CharWidth(sink, font, x, '^');
277 if ((c |= 0100) == 0177)
286 && (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
287 width += font->per_char[c - font->min_char_or_byte2].width;
289 width += font->min_bounds.width;
296 GetTextWidth(TextWidget ctx, int current_width, XFontStruct *font,
297 XawTextPosition from, int length)
301 XawTextPosition pos = from;
304 pos = XawTextSourceRead(ctx->text.source, from, &block, length);
305 length -= pos - from;
307 for (i = 0; i < block.length; i++)
308 width += CharWidth((AsciiSinkObject)ctx->text.sink, font,
309 current_width + width,
310 (unsigned char)block.ptr[i]);
317 void CalculateBearing(TextWidget ctx, XawTextPosition position, int x, int y,
318 int ascent, int descent, Bool highlight, Bool right)
323 * lbearing| width |rbearing
339 AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink;
340 XawTextAnchor *anchor;
341 XawTextEntity *entity;
342 XawTextProperty *property;
343 XawTextPaintStruct *paint;
348 if (XawTextSourceAnchorAndEntity(ctx->text.source, position,
350 (property = XawTextSinkGetProperty((Widget)sink,
351 entity->property)) != NULL &&
352 (property->mask & XAW_TPROP_FONT))
353 font = property->font;
355 font = sink->ascii_sink.font;
357 if (font->max_bounds.rbearing > 0) {
358 int rbearing = font->max_bounds.rbearing - font->max_bounds.width;
361 (void)XawTextSourceRead(ctx->text.source, position, &block, 1);
362 c = *(unsigned char*)block.ptr;
363 if (c == '\t' || c == '\n')
365 else if ((c & 0177) < XawSP || c == 0177) {
366 if (sink->ascii_sink.display_nonprinting)
367 c = c > 0177 ? (c & 7) + '0' : c + '@';
371 if (font->per_char &&
372 (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
373 rbearing = font->per_char[c - font->min_char_or_byte2].rbearing -
374 font->per_char[c - font->min_char_or_byte2].width;
376 paint = XtNew(XawTextPaintStruct);
377 paint->next = sink->text_sink.paint->bearings;
378 sink->text_sink.paint->bearings = paint;
379 paint->x = x - (paint->width = CharWidth(sink, font, 0, c));
380 paint->y = y + ascent;
381 paint->property = property;
382 paint->max_ascent = ascent;
383 paint->max_descent = descent;
384 paint->backtabs = NULL;
385 paint->highlight = highlight;
387 paint->text = XtMalloc(1);
393 if (font->min_bounds.lbearing < 0) {
394 int lbearing = font->min_bounds.lbearing;
397 (void)XawTextSourceRead(ctx->text.source, position, &block, 1);
398 c = *(unsigned char*)block.ptr;
399 if (c == '\t' || c == '\n')
401 else if ((c & 0177) < XawSP || c == 0177) {
402 if (sink->ascii_sink.display_nonprinting)
403 c = c > 0177 ? '\\' : c + '^';
407 if (font->per_char &&
408 (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
409 lbearing = font->per_char[c - font->min_char_or_byte2].lbearing;
411 paint = XtNew(XawTextPaintStruct);
412 paint->next = sink->text_sink.paint->bearings;
413 sink->text_sink.paint->bearings = paint;
415 paint->width = -CharWidth(sink, font, 0, c);
416 paint->y = y + ascent;
417 paint->property = property;
418 paint->max_ascent = ascent;
419 paint->max_descent = descent;
420 paint->backtabs = NULL;
421 paint->highlight = highlight;
423 paint->text = XtMalloc(1);
431 AsciiPreparePaint(Widget w, int y, int line,
432 XawTextPosition from, XawTextPosition to, Bool highlight)
434 static XmuSegment segment;
435 static XmuScanline next;
436 static XmuScanline scanline = {0, &segment, &next};
437 static XmuArea area = {&scanline};
439 TextWidget ctx = (TextWidget)XtParent(w);
440 AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink;
441 XawTextPosition left, right, pos, pos2, tmp, length;
442 XawTextAnchor *anchor;
443 XawTextEntity *entity;
444 XawTextProperty *property;
445 int i, ascent = 0, descent = 0, xl, xr, x = ctx->text.left_margin, bufsiz;
448 XawTextPaintStruct *paint;
450 if (!sink->ascii_sink.echo)
453 /* pass 1: calculate ascent/descent values and x coordinate */
454 /* XXX the MAX ascent/descent value should be in the line table XXX */
455 /* XXX the x coordinate can be a parameter, but since it is required
456 to calculate the ascent/descent, do it here to avoid an extra
457 search in the entities */
458 pos = tmp = left = ctx->text.lt.info[line].position;
459 right = ctx->text.lt.info[line + 1].position;
460 right = XawMin(right, ctx->text.lastPos + 1);
461 while (pos < right) {
462 if (XawTextSourceAnchorAndEntity(ctx->text.source, pos,
464 if ((property = XawTextSinkGetProperty((Widget)sink,
465 entity->property)) != NULL &&
466 (property->mask & XAW_TPROP_FONT))
467 font = property->font;
469 font = sink->ascii_sink.font;
471 pos = anchor->position + entity->offset + entity->length;
472 if ((length = XawMin(from, pos) - tmp) > 0)
473 x += GetTextWidth(ctx, x, font, tmp, length);
474 ascent = XawMax(font->ascent, ascent);
475 descent = XawMax(font->descent, descent);
478 ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
479 descent = XawMax(sink->ascii_sink.font->descent, descent);
480 while (entity && pos < right) {
482 if ((pos = anchor->position + entity->offset) < tmp)
485 if ((length = XawMin(from, pos) - tmp) > 0) {
486 x += GetTextWidth(ctx, x, sink->ascii_sink.font, tmp,
491 pos += entity->length;
492 if ((property = XawTextSinkGetProperty((Widget)sink,
493 entity->property)) != NULL &&
494 (property->mask & XAW_TPROP_FONT))
495 font = property->font;
497 font = sink->ascii_sink.font;
498 if ((length = XawMin(from, pos) - tmp) > 0)
499 x += GetTextWidth(ctx, x, font, tmp, length);
500 ascent = XawMax(font->ascent, ascent);
501 descent = XawMax(font->descent, descent);
504 entity = entity->next;
507 if (anchor->entities == NULL) {
508 tmp = XawMin(pos, from);
509 if ((length = from - tmp) > 0)
510 x += GetTextWidth(ctx, x, sink->ascii_sink.font, tmp, length);
515 tmp = XawMin(pos, from);
516 if ((length = from - tmp) > 0)
517 x += GetTextWidth(ctx, x, sink->ascii_sink.font, tmp, length);
518 ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
519 descent = XawMax(sink->ascii_sink.font->descent, descent);
524 ascent = sink->ascii_sink.font->ascent;
526 descent = sink->ascii_sink.font->descent;
530 /* pass 2: feed the XawTextPaintStruct lists */
533 paint = XtNew(XawTextPaintStruct);
534 paint->next = sink->text_sink.paint->paint;
535 sink->text_sink.paint->paint = paint;
537 paint->y = y + ascent;
538 paint->property = NULL;
539 paint->max_ascent = ascent;
540 paint->max_descent = descent;
541 paint->backtabs = NULL;
542 paint->highlight = highlight;
545 if (XawTextSourceAnchorAndEntity(ctx->text.source, pos,
547 pos = anchor->position + entity->offset + entity->length;
548 if ((paint->property = XawTextSinkGetProperty((Widget)sink,
549 entity->property)) != NULL &&
550 (paint->property->mask & XAW_TPROP_FONT))
551 font = paint->property->font;
553 font = sink->ascii_sink.font;
557 while (entity && anchor->position + entity->offset < pos)
558 entity = entity->next;
560 pos = anchor->position + entity->offset;
566 font = sink->ascii_sink.font;
568 pos = XawMin(pos, to);
571 paint->text = XtMalloc(bufsiz = pos - tmp + 4);
577 pos2 = XawTextSourceRead(ctx->text.source, tmp, &block, length);
580 for (i = 0; i < block.length; i++) {
581 unsigned char c = (unsigned char)block.ptr[i];
583 if (paint->length + 4 > bufsiz)
584 paint->text = XtRealloc(paint->text, bufsiz += 32);
585 paint->text[paint->length] = c;
587 x += CharWidth(sink, font, 0, ' ');
591 x += XTextWidth(font, paint->text, paint->length);
592 segment.x2 = x + CharWidth(sink, font, x, '\t');
594 if (XmuValidSegment(&segment)) {
595 if (!highlight && (paint->property &&
596 (paint->property->mask & XAW_TPROP_BACKGROUND))) {
597 if (ascent > font->ascent) {
599 next.y = y + ascent - font->ascent;
600 XmuAreaOr(sink->text_sink.paint->clip, &area);
602 if (descent >= font->descent) {
603 scanline.y = y + ascent + font->descent;
604 next.y = scanline.y + descent - font->descent + 1;
605 XmuAreaOr(sink->text_sink.paint->clip, &area);
607 if (paint->backtabs == NULL)
608 paint->backtabs = XmuCreateArea();
609 scanline.y = y + ascent - font->ascent;
610 next.y = y + ascent + font->descent;
611 XmuAreaOr(paint->backtabs, &area);
615 next.y = ctx->text.lt.info[line + 1].y;
617 if (!sink->text_sink.paint->hightabs)
618 sink->text_sink.paint->hightabs =
620 XmuAreaOr(sink->text_sink.paint->hightabs, &area);
623 XmuAreaOr(sink->text_sink.paint->clip, &area);
627 paint->width = segment.x2 - segment.x1;
628 x = segment.x1 = segment.x2;
630 if (paint->length == 0) {
634 paint->text = XtRealloc(paint->text, paint->length);
635 property = paint->property;
636 paint = XtNew(XawTextPaintStruct);
637 paint->next = sink->text_sink.paint->paint;
638 sink->text_sink.paint->paint = paint;
640 paint->y = y + ascent;
641 paint->property = property;
642 paint->max_ascent = ascent;
643 paint->max_descent = descent;
644 paint->backtabs = NULL;
645 paint->highlight = highlight;
646 paint->text = XtMalloc(bufsiz = pos - tmp - length +
647 block.length - i + 4);
651 if ((c & 0177) < XawSP || c == 0177) {
652 if (sink->ascii_sink.display_nonprinting) {
654 paint->text[paint->length++] = '\\';
655 paint->text[paint->length++] = ((c >> 6) & 7) + '0';
656 paint->text[paint->length++] = ((c >> 3) & 7) + '0';
657 paint->text[paint->length] = (c & 7) + '0';
661 paint->text[paint->length++] = '^';
662 paint->text[paint->length] = c == 0177 ? '?' : c;
666 paint->text[paint->length] = ' ';
672 x += XTextWidth(font, paint->text, paint->length);
674 if (XmuValidSegment(&segment)) {
675 /* erase only what really is needed */
676 /*if (!highlight || (paint->property &&
677 (paint->property->mask & XAW_TPROP_BACKGROUND))) {
678 if (ascent > font->ascent) {
680 next.y = y + ascent - font->ascent;
681 XmuAreaOr(sink->text_sink.paint->clip, &area);
683 if (descent > font->descent) {
684 scanline.y = y + ascent + font->descent;
685 next.y = scanline.y + descent - font->descent;
686 XmuAreaOr(sink->text_sink.paint->clip, &area);
691 next.y = ctx->text.lt.info[line + 1].y;
692 XmuAreaOr(sink->text_sink.paint->clip, &area);
696 paint->width = x - segment.x1;
701 /* pass 3: bearing clipping */
703 CalculateBearing(ctx, from - 1, xl, y, ascent, descent, highlight, True);
704 if (ctx->text.s.left < ctx->text.s.right) {
705 if (ctx->text.s.right == from)
706 CalculateBearing(ctx, from, xl, y, ascent, descent, True, False);
707 else if (ctx->text.s.left == from)
708 CalculateBearing(ctx, from, xl, y, ascent, descent, False, False);
711 right = XawMin(right, ctx->text.lastPos);
712 if (right >= to && to > from) {
714 CalculateBearing(ctx, to, xr, y, ascent, descent, highlight, False);
715 if (ctx->text.s.left < ctx->text.s.right) {
716 if (ctx->text.s.right == to)
717 CalculateBearing(ctx, to - 1, xr, y, ascent, descent, False, True);
718 else if (ctx->text.s.left == to)
719 CalculateBearing(ctx, to - 1, xr, y, ascent, descent, True, True);
725 qcmp_paint_struct(_Xconst void *left, _Xconst void *right)
727 return ((*(XawTextPaintStruct**)left)->property -
728 (*(XawTextPaintStruct**)right)->property);
732 AsciiDoPaint(Widget w)
734 TextWidget ctx = (TextWidget)XtParent(w);
735 AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink;
738 XawTextPaintList *list = sink->text_sink.paint;
740 XawTextPaintStruct *base, *head;
742 XawTextPaintStruct *paint = list->paint;
743 XawTextProperty *property;
744 XFontStruct *font = NULL;
746 int n_rects, i_rects;
750 int width, height, line_width = -1;
753 /* pass 1: clear clipping areas */
754 /* XXX Don't use XDrawImageString because the font may be italic, and
755 will get incorrectly drawn. Probably, it could be a good idea to
756 check if this is the case, and do special processing. But this
757 will need to be checked if required. */
758 for (scan = list->clip->scanline; scan && scan->next; scan = scan->next)
759 for (seg = scan->segment; seg; seg = seg->next)
760 _XawTextSinkClearToBackground(ctx->text.sink,
763 scan->next->y - scan->y);
765 /* pass 2: optimize drawing list to avoid too much GC change requests */
766 /* XXX this assumes there will not exist entities drawn over other
773 if (head->property == paint->property) {
774 base->next = head->next;
775 head->next = paint->next;
785 if (paint && paint->next) {
786 XawTextPaintStruct **paints;
787 int i = 0, n_paints = 0;
793 paints = (XawTextPaintStruct**)
794 XtMalloc(n_paints * sizeof(XawTextPaintStruct));
800 qsort((void*)paints, n_paints, sizeof(XawTextPaintStruct*),
802 list->paint = paints[0];
803 for (i = 0; i < n_paints - 1; i++)
804 paints[i]->next = paints[i + 1];
805 paints[i]->next = NULL;
806 XtFree((XtPointer)paints);
809 /* pass 3: clip gc */
810 gc = sink->ascii_sink.normgc;
812 rect.x = ctx->text.r_margin.left;
813 rect.y = ctx->text.r_margin.top;
814 width = (int)XtWidth(ctx) - RHMargins(ctx);
815 height = (int)XtHeight(ctx) - RVMargins(ctx);
817 rect.height = height;
818 if (width >= 0 && height >= 0)
819 XSetClipRectangles(XtDisplay((Widget)ctx), gc,
820 0, 0, &rect, 1, Unsorted);
822 XSetClipMask(XtDisplay((Widget)ctx), gc, None);
824 /* pass 4: draw backgrounds */
828 i_rects = n_rects = 0;
830 if (paint->property && (paint->property->mask & XAW_TPROP_BACKGROUND)) {
831 if (property != paint->property) {
833 XFillRectangles(XtDisplay(ctx), XtWindow(ctx), gc,
836 property = paint->property;
837 if (property->mask & XAW_TPROP_FONT)
838 font = property->font;
840 font = sink->ascii_sink.font;
841 XSetForeground(XtDisplay(ctx), gc, property->background);
843 if (i_rects <= n_rects)
844 rects = (XRectangle*)
845 XtRealloc((XtPointer)rects, sizeof(XRectangle) *
847 rects[i_rects].x = paint->x;
848 rects[i_rects].y = paint->y - font->ascent;
849 rects[i_rects].width = paint->width;
850 rects[i_rects++].height = font->ascent + font->descent;
852 if (paint->backtabs) {
853 for (scan = paint->backtabs->scanline; scan && scan->next;
855 for (seg = scan->segment; seg; seg = seg->next) {
856 if (i_rects <= n_rects)
857 rects = (XRectangle*)
858 XtRealloc((XtPointer)rects, sizeof(XRectangle) *
860 rects[i_rects].x = seg->x1;
861 rects[i_rects].y = scan->y;
862 rects[i_rects].width = seg->x2 - seg->x1;
863 rects[i_rects++].height = scan->next->y - scan->y;
872 XFillRectangles(XtDisplay(ctx), XtWindow(ctx), gc, rects, i_rects);
877 if (paint->highlight) {
879 XSetForeground(XtDisplay(ctx), gc, sink->text_sink.cursor_color);
880 if (i_rects <= n_rects)
881 rects = (XRectangle*)
882 XtRealloc((XtPointer)rects, sizeof(XRectangle) *
884 rects[i_rects].x = paint->x;
885 rects[i_rects].y = paint->y - paint->max_ascent;
886 rects[i_rects].width = paint->width;
887 rects[i_rects++].height = paint->max_ascent + paint->max_descent + 1;
891 if (list->hightabs) {
892 for (scan = list->hightabs->scanline; scan && scan->next;
894 for (seg = scan->segment; seg; seg = seg->next) {
896 XSetForeground(XtDisplay(ctx), gc,
897 sink->text_sink.cursor_color);
898 if (i_rects <= n_rects)
899 rects = (XRectangle*)
900 XtRealloc((XtPointer)rects, sizeof(XRectangle) *
902 rects[i_rects].x = seg->x1;
903 rects[i_rects].y = scan->y;
904 rects[i_rects].width = seg->x2 - seg->x1;
905 rects[i_rects++].height = scan->next->y - scan->y;
910 XFillRectangles(XtDisplay(ctx), XtWindow(ctx), gc, rects, i_rects);
912 XtFree((XtPointer)rects);
914 /* pass 5: draw text! */
916 if (paint && (property = paint->property) == NULL) {
917 font = sink->ascii_sink.font;
918 XSetFont(XtDisplay(ctx), gc, font->fid);
919 if (!paint->highlight)
920 XSetForeground(XtDisplay(ctx), gc, sink->text_sink.foreground);
926 if (!highlight && paint->highlight)
927 XSetForeground(XtDisplay(ctx), gc, sink->text_sink.background);
928 if (highlight || paint->highlight || paint->property != property) {
929 if (!paint->property || !(paint->property->mask & XAW_TPROP_FONT))
930 font = sink->ascii_sink.font;
932 font = paint->property->font;
933 XSetFont(XtDisplay(ctx), gc, font->fid);
934 if (!paint->highlight) {
935 if (!paint->property ||
936 !(paint->property->mask & XAW_TPROP_FOREGROUND))
937 XSetForeground(XtDisplay(ctx), gc,
938 sink->text_sink.foreground);
940 XSetForeground(XtDisplay(ctx), gc,
941 paint->property->foreground);
943 highlight = paint->highlight;
944 property = paint->property;
947 if (paint->x < XtWidth(ctx) && paint->x + paint->width > 0) {
948 XDrawString(XtDisplay(ctx), XtWindow(ctx), gc, paint->x, paint->y,
949 paint->text, paint->length);
951 if (property->mask & XAW_TPROP_UNDERLINE) {
952 if (line_width != property->underline_thickness) {
953 values.line_width = line_width =
954 property->underline_thickness;
955 XChangeGC(XtDisplay(ctx), gc, GCLineWidth, &values);
958 XDrawLine(XtDisplay(ctx), XtWindow(ctx), gc, paint->x,
959 paint->y + property->underline_position,
960 paint->x + paint->width,
961 paint->y + property->underline_position);
963 if (property->mask & XAW_TPROP_OVERSTRIKE) {
964 if (line_width != property->underline_thickness) {
965 values.line_width = line_width =
966 property->underline_thickness;
967 XChangeGC(XtDisplay(ctx), gc, GCLineWidth, &values);
970 XDrawLine(XtDisplay(ctx), XtWindow(ctx), gc, paint->x,
971 paint->y - (font->ascent>>1) + (font->descent>>1),
972 paint->x + paint->width,
973 paint->y - (font->ascent>>1) + (font->descent>>1));
981 /* pass 6: bearing clipping */
982 /* dont care on order of drawing or caching of state (by now) */
983 paint = list->bearings;
987 if (paint->highlight)
988 XSetForeground(XtDisplay(ctx), gc, sink->text_sink.background);
989 if (!paint->property || !(paint->property->mask & XAW_TPROP_FONT))
990 font = sink->ascii_sink.font;
992 font = paint->property->font;
993 XSetFont(XtDisplay(ctx), gc, font->fid);
994 if (!paint->highlight) {
995 if (!paint->property ||
996 !(paint->property->mask & XAW_TPROP_FOREGROUND))
997 XSetForeground(XtDisplay(ctx), gc, sink->text_sink.foreground);
999 XSetForeground(XtDisplay(ctx), gc, paint->property->foreground);
1001 if (paint->x < XtWidth(ctx) && paint->x + paint->width > 0) {
1002 rect.x = paint->x + paint->width;
1003 rect.width = XawAbs(paint->width); /* more than enough */
1004 rect.y = paint->y - font->ascent;
1005 rect.height = rect.y + font->ascent + font->descent;
1006 XSetClipRectangles(XtDisplay((Widget)ctx), gc,
1007 0, 0, &rect, 1, Unsorted);
1008 XDrawString(XtDisplay(ctx), XtWindow(ctx), gc, paint->x, paint->y,
1009 paint->text, paint->length);
1011 paint = paint->next;
1021 * w - text sink object
1022 * gc - gc to paint text with
1023 * x - location to paint the text
1025 * buf - buffer and length of text to paint.
1027 * clear_bg - clear background before drawing ?
1030 * Actually paints the text into the window.
1033 * the width of the text painted
1036 PaintText(Widget w, GC gc, int x, int y, char *buf, int len, Bool clear_bg)
1038 AsciiSinkObject sink = (AsciiSinkObject)w;
1039 TextWidget ctx = (TextWidget)XtParent(w);
1040 int width = XTextWidth(sink->ascii_sink.font, buf, len);
1042 if ((x > XtWidth(ctx)) || width <= -x) /* Don't draw if we can't see it */
1046 _XawTextSinkClearToBackground(w, x, y - sink->ascii_sink.font->ascent,
1047 width, sink->ascii_sink.font->ascent
1048 + sink->ascii_sink.font->descent);
1049 XDrawString(XtDisplay(ctx), XtWindow(ctx), gc, x, y, buf, len);
1052 XDrawImageString(XtDisplay(ctx), XtWindow(ctx), gc, x, y, buf, len);
1058 DisplayText(Widget w, int x, int y,
1059 XawTextPosition pos1, XawTextPosition pos2, Bool highlight)
1061 TextWidget ctx = (TextWidget)XtParent(w);
1062 AsciiSinkObject sink = (AsciiSinkObject)w;
1063 XFontStruct *font = sink->ascii_sink.font;
1064 Widget source = XawTextGetSource(XtParent(w));
1065 unsigned char buf[260];
1068 GC gc, invgc, tabgc;
1072 if (!sink->ascii_sink.echo || !ctx->text.lt.lines)
1075 max_x = (int)XtWidth(ctx) - ctx->text.r_margin.right;
1076 clear_bg = !highlight && ctx->core.background_pixmap != XtUnspecifiedPixmap;
1078 gc = highlight ? sink->ascii_sink.invgc : sink->ascii_sink.normgc;
1079 invgc = highlight ? sink->ascii_sink.normgc : sink->ascii_sink.invgc;
1081 if (highlight && sink->ascii_sink.xorgc)
1082 tabgc = sink->ascii_sink.xorgc;
1086 y += sink->ascii_sink.font->ascent;
1087 for (j = 0; pos1 < pos2;) {
1088 pos1 = XawTextSourceRead(source, pos1, &blk, pos2 - pos1);
1089 for (k = 0; k < blk.length; k++) {
1090 if (j >= sizeof(buf) - 4) { /* buffer full, dump the text */
1091 if ((x += PaintText(w, gc, x, y, (char*)buf, j, clear_bg))
1096 buf[j] = blk.ptr[k];
1097 if (buf[j] == XawLF) /* line feeds ('\n') are not printed */
1100 else if (buf[j] == '\t') {
1104 && (x += PaintText(w, gc, x, y, (char*)buf, j, clear_bg))
1108 if ((width = CharWidth(sink, font, x, '\t')) > -x) {
1110 _XawTextSinkClearToBackground(w, x, y-font->ascent, width,
1111 font->ascent+font->descent);
1113 XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
1114 tabgc, x, y - font->ascent, width,
1115 font->ascent + font->descent);
1118 if ((x += width) >= max_x)
1123 else if ((buf[j] & 0177) < XawSP || buf[j] == 0177) {
1124 if (sink->ascii_sink.display_nonprinting) {
1125 unsigned char c = buf[j];
1129 buf[j++] = ((c >> 6) & 7) + '0';
1130 buf[j++] = ((c >> 3) & 7) + '0';
1131 buf[j] = (c & 7) + '0';
1136 buf[j] = c == 0177 ? '?' : c;
1147 (void)PaintText(w, gc, x, y, (char*)buf, j, clear_bg);
1155 * w - text sink object
1156 * rect - X rectangle to return the cursor bounds
1159 * Returns the size and location of the cursor.
1162 GetCursorBounds(Widget w, XRectangle *rect)
1164 AsciiSinkObject sink = (AsciiSinkObject)w;
1165 XFontStruct *font = sink->ascii_sink.font;
1168 TextWidget ctx = (TextWidget)XtParent(w);
1170 XawTextAnchor *anchor;
1171 XawTextEntity *entity;
1172 XawTextProperty *property;
1174 if (XawTextSourceAnchorAndEntity(XawTextGetSource(XtParent(w)),
1175 sink->ascii_sink.cursor_position,
1176 &anchor, &entity)) {
1177 if ((property = XawTextSinkGetProperty((Widget)sink,
1178 entity->property)) != NULL &&
1179 (property->mask & XAW_TPROP_FONT))
1180 font = property->font;
1182 (void)XawTextSourceRead(XawTextGetSource((Widget)ctx),
1183 ctx->text.insertPos, &block, 1);
1184 if (!block.length || block.ptr[0] == '\n' || block.ptr[0] == '\t')
1186 else if ((*((unsigned char*)block.ptr) & 0177) < XawSP ||
1187 *(unsigned char*)block.ptr == 0177) {
1188 if (sink->ascii_sink.display_nonprinting)
1189 ch = *((unsigned char*)block.ptr) > 0177 ? '\\' : '^';
1194 ch = *(unsigned char*)block.ptr;
1199 rect->width = CharWidth(sink, font, 0, ch);
1200 rect->height = font->descent + font->ascent + 1;
1202 rect->x = sink->ascii_sink.cursor_x;
1203 rect->y = sink->ascii_sink.cursor_y - font->ascent;
1206 /* this function is required to support diferent fonts and correctly place
1207 * the cursor. There are better ways to calculate the base line, but there is
1208 * no place/code (yet) to store this information.
1211 FindCursorY(TextWidget ctx, XawTextPosition position)
1213 int y, line, ascent;
1214 AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink;
1216 XawTextAnchor *anchor;
1217 XawTextEntity *entity;
1218 XawTextProperty *property;
1219 XawTextPosition left, right;
1222 for (line = 0; line < ctx->text.lt.lines; line++)
1223 if (position < ctx->text.lt.info[line + 1].position)
1226 y = ctx->text.lt.info[line].y;
1229 left = ctx->text.lt.info[line].position;
1230 right = ctx->text.lt.info[line + 1].position;
1231 right = XawMin(right, ctx->text.lastPos + 1);
1232 while (left < right) {
1233 if (XawTextSourceAnchorAndEntity(ctx->text.source, left,
1234 &anchor, &entity)) {
1235 if ((property = XawTextSinkGetProperty((Widget)sink,
1236 entity->property)) != NULL &&
1237 (property->mask & XAW_TPROP_FONT))
1238 ascent = XawMax(property->font->ascent, ascent);
1240 ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
1241 left = anchor->position + entity->offset + entity->length;
1244 ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
1246 XawTextPosition tmp = anchor->position + entity->offset + entity->length;
1248 if (tmp > left && tmp < right) {
1250 if ((property = XawTextSinkGetProperty((Widget)sink,
1251 entity->property)) != NULL &&
1252 (property->mask & XAW_TPROP_FONT))
1253 ascent = XawMax(property->font->ascent, ascent);
1255 ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
1257 entity = entity->next;
1263 ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
1268 ascent = sink->ascii_sink.font->ascent;
1270 ascent = sink->ascii_sink.font->ascent;
1273 return (y + ascent);
1277 InsertCursor(Widget w, int x, int y, XawTextInsertState state)
1279 AsciiSinkObject sink = (AsciiSinkObject)w;
1280 XFontStruct *font = sink->ascii_sink.font;
1281 TextWidget ctx = (TextWidget)XtParent(w);
1282 XawTextPosition position = XawTextGetInsertionPoint((Widget)ctx);
1283 Boolean overflow = (x & 0xffff8000) != 0;
1285 XawTextAnchor *anchor;
1286 XawTextEntity *entity;
1287 XawTextProperty *property;
1290 if (XtIsRealized((Widget)ctx)) {
1293 XawTextPosition selection_start, selection_end;
1294 Boolean has_selection;
1296 if (!sink->ascii_sink.echo) {
1297 if (sink->ascii_sink.laststate != state) {
1298 int width = CharWidth(sink, font, 0, ' ') - 1;
1300 x = ctx->text.margin.left;
1301 y = ctx->text.margin.top;
1302 font = sink->ascii_sink.font;
1303 fheight = font->ascent + font->descent;
1304 if (state == XawisOn) {
1305 if (ctx->text.hasfocus)
1306 XFillRectangle(XtDisplay(ctx), XtWindow(ctx),
1307 sink->ascii_sink.xorgc, x, y,
1308 width + 1, fheight + 1);
1310 XDrawRectangle(XtDisplay(ctx), XtWindow(ctx),
1311 sink->ascii_sink.xorgc, x, y,
1316 _XawTextSinkClearToBackground(w, x, y,
1317 width + 1, fheight + 1);
1319 sink->ascii_sink.cursor_x = x;
1320 sink->ascii_sink.cursor_y = y;
1321 sink->ascii_sink.laststate = state;
1326 XawTextGetSelectionPos((Widget)ctx, &selection_start, &selection_end);
1327 has_selection = selection_start != selection_end;
1329 if (sink->ascii_sink.laststate != state) {
1333 if (XawTextSourceAnchorAndEntity(ctx->text.source,
1334 position, &anchor, &entity) &&
1335 (property = XawTextSinkGetProperty((Widget)sink,
1336 entity->property)) != NULL &&
1337 (property->mask & XAW_TPROP_FONT))
1338 font = property->font;
1340 font = sink->ascii_sink.font;
1343 fheight = font->ascent + font->descent;
1344 (void)XawTextSourceRead(XawTextGetSource((Widget)ctx),
1345 position, &block, 1);
1346 if (!block.length || block.ptr[0] == '\n' || block.ptr[0] == '\t')
1348 else if ((*((unsigned char*)block.ptr) & 0177) < XawSP
1349 || *(unsigned char*)block.ptr == 0177) {
1350 if (sink->ascii_sink.display_nonprinting)
1351 ch = *((unsigned char*)block.ptr) > 0177 ? '\\' : '^';
1356 ch = *(unsigned char*)block.ptr;
1358 y = FindCursorY(ctx, position);
1359 if (ctx->text.hasfocus && !has_selection)
1360 XFillRectangle(XtDisplay(ctx), XtWindow(ctx),
1361 sink->ascii_sink.xorgc, x, y - font->ascent,
1362 CharWidth(sink, font, 0, ch), fheight + 1);
1364 XDrawRectangle(XtDisplay(ctx), XtWindow(ctx),
1365 sink->ascii_sink.xorgc, x, y - font->ascent,
1366 CharWidth(sink, font, 0, ch) - 1, fheight);
1370 sink->ascii_sink.cursor_x = overflow ? -16384 : x;
1371 sink->ascii_sink.cursor_y = y;
1372 sink->ascii_sink.laststate = state;
1373 sink->ascii_sink.cursor_position = position;
1377 * Given two positions, find the distance between them
1380 FindDistance(Widget w, XawTextPosition fromPos, int fromx,
1381 XawTextPosition toPos, int *resWidth,
1382 XawTextPosition *resPos, int *resHeight)
1385 AsciiSinkObject sink = (AsciiSinkObject)w;
1386 TextWidget ctx = (TextWidget)XtParent(w);
1387 XFontStruct *font = sink->ascii_sink.font;
1388 Widget source = ctx->text.source;
1389 XawTextPosition idx, pos;
1392 int i, rWidth, ascent = 0, descent = 0;
1393 XawTextAnchor *anchor;
1394 XawTextEntity *entity;
1395 XawTextProperty *property;
1399 pos = idx = fromPos;
1404 if (XawTextSourceAnchorAndEntity(source, pos, &anchor, &entity)) {
1405 length = anchor->position + entity->offset + entity->length;
1406 length = XawMin(toPos, length) - pos;
1407 if ((property = XawTextSinkGetProperty((Widget)sink,
1408 entity->property)) != NULL &&
1409 (property->mask & XAW_TPROP_FONT))
1410 font = property->font;
1412 font = sink->ascii_sink.font;
1416 while (entity && anchor->position + entity->offset < pos)
1417 entity = entity->next;
1419 length = anchor->position + entity->offset;
1420 length = XawMin(toPos, length) - pos;
1423 length = XawMin(toPos - pos, 4096);
1426 length = XawMin(toPos - pos, 4096);
1427 font = sink->ascii_sink.font;
1430 ascent = XawMax(font->ascent, ascent);
1431 descent = XawMax(font->descent, descent);
1433 pos = XawTextSourceRead(source, pos, &blk, length);
1434 if (blk.length == 0 && pos == idx) /* eof reached */
1438 for (i = 0; idx < toPos; i++, idx++) {
1439 if (i >= blk.length)
1442 rWidth += CharWidth(sink, font, fromx + rWidth, c);
1455 *resHeight = ascent + descent + 1;
1457 AsciiSinkObject sink = (AsciiSinkObject)w;
1458 TextWidget ctx = (TextWidget)XtParent(w);
1459 XFontStruct *font = sink->ascii_sink.font;
1460 Widget source = ctx->text.source;
1461 XawTextPosition idx, pos;
1466 pos = XawTextSourceRead(source, fromPos, &blk, toPos - fromPos);
1468 for (i = 0, idx = fromPos; idx < toPos; i++, idx++) {
1469 if (i >= blk.length) {
1471 pos = XawTextSourceRead(source, pos, &blk, toPos - pos);
1472 if (blk.length == 0)
1476 rWidth += CharWidth(sink, font, fromx + rWidth, c);
1485 *resHeight = font->ascent + font->descent + 1;
1490 FindPosition(Widget w, XawTextPosition fromPos, int fromx, int width,
1491 Bool stopAtWordBreak, XawTextPosition *resPos,
1492 int *resWidth, int *resHeight)
1495 AsciiSinkObject sink = (AsciiSinkObject)w;
1496 TextWidget ctx = (TextWidget)XtParent(w);
1497 Widget source = ctx->text.source;
1498 XFontStruct *font = sink->ascii_sink.font;
1499 XawTextPosition idx, pos, whiteSpacePosition = 0;
1500 int i, lastWidth, whiteSpaceWidth, rWidth, ascent = 0, descent = 0;
1501 Boolean whiteSpaceSeen;
1504 XawTextAnchor *anchor;
1505 XawTextEntity *entity;
1506 XawTextProperty *property;
1510 pos = idx = fromPos;
1511 rWidth = lastWidth = whiteSpaceWidth = 0;
1512 whiteSpaceSeen = False;
1516 font = sink->ascii_sink.font;
1517 if (XawTextSourceAnchorAndEntity(source, pos, &anchor, &entity)) {
1518 length = anchor->position + entity->offset + entity->length - pos;
1519 if ((property = XawTextSinkGetProperty((Widget)sink,
1520 entity->property)) != NULL &&
1521 (property->mask & XAW_TPROP_FONT))
1522 font = property->font;
1526 while (entity && anchor->position + entity->offset < pos)
1527 entity = entity->next;
1529 length = anchor->position + entity->offset - pos;
1537 ascent = XawMax(font->ascent, ascent);
1538 descent = XawMax(font->descent, descent);
1540 pos = XawTextSourceRead(source, pos, &blk, length);
1541 if (blk.length == 0 && pos == idx) /* eof reached */
1545 for (i = 0; rWidth <= width && i < blk.length; i++, idx++) {
1548 rWidth += CharWidth(sink, font, fromx + rWidth, c);
1555 else if ((c == XawSP || c == XawTAB) && rWidth <= width) {
1556 whiteSpaceSeen = True;
1557 whiteSpacePosition = idx;
1558 whiteSpaceWidth = rWidth;
1565 if (rWidth > width && idx > fromPos) {
1568 if (stopAtWordBreak && whiteSpaceSeen) {
1569 idx = whiteSpacePosition + 1;
1570 rWidth = whiteSpaceWidth;
1574 if (idx >= ctx->text.lastPos && c != XawLF)
1575 idx = ctx->text.lastPos + 1;
1579 *resHeight = ascent + descent + 1;
1581 AsciiSinkObject sink = (AsciiSinkObject)w;
1582 TextWidget ctx = (TextWidget)XtParent(w);
1583 Widget source = ctx->text.source;
1584 XFontStruct *font = sink->ascii_sink.font;
1585 XawTextPosition idx, pos, whiteSpacePosition = 0;
1586 int i, lastWidth, whiteSpaceWidth, rWidth;
1587 Boolean whiteSpaceSeen;
1591 pos = XawTextSourceRead(source, fromPos, &blk, BUFSIZ);
1592 rWidth = lastWidth = whiteSpaceWidth = 0;
1593 whiteSpaceSeen = False;
1596 for (i = 0, idx = fromPos; rWidth <= width; i++, idx++) {
1597 if (i >= blk.length) {
1599 pos = XawTextSourceRead(source, pos, &blk, BUFSIZ);
1600 if (blk.length == 0)
1605 rWidth += CharWidth(sink, font, fromx + rWidth, c);
1611 else if ((c == XawSP || c == XawTAB) && rWidth <= width) {
1612 whiteSpaceSeen = True;
1613 whiteSpacePosition = idx;
1614 whiteSpaceWidth = rWidth;
1618 if (rWidth > width && idx > fromPos) {
1621 if (stopAtWordBreak && whiteSpaceSeen) {
1622 idx = whiteSpacePosition + 1;
1623 rWidth = whiteSpaceWidth;
1627 if (idx >= ctx->text.lastPos && c != XawLF)
1628 idx = ctx->text.lastPos + 1;
1632 *resHeight = font->ascent + font->descent + 1;
1637 Resolve(Widget w, XawTextPosition pos, int fromx, int width,
1638 XawTextPosition *pos_return)
1640 int resWidth, resHeight;
1641 Widget source = XawTextGetSource(XtParent(w));
1643 FindPosition(w, pos, fromx, width, False, pos_return, &resWidth, &resHeight);
1644 if (*pos_return > GETLASTPOS)
1645 *pos_return = GETLASTPOS;
1649 GetGC(AsciiSinkObject sink)
1651 XtGCMask valuemask = (GCFont | GCGraphicsExposures | GCClipXOrigin |
1652 GCForeground | GCBackground);
1655 /* XXX We dont want do share a gc that will change the clip-mask */
1656 values.clip_x_origin = (long)sink;
1657 values.clip_mask = None;
1658 values.font = sink->ascii_sink.font->fid;
1659 values.graphics_exposures = False;
1661 values.foreground = sink->text_sink.foreground;
1662 values.background = sink->text_sink.background;
1663 sink->ascii_sink.normgc = XtAllocateGC((Widget)sink, 0, valuemask, &values,
1664 GCClipMask | GCFont | GCForeground |
1667 values.foreground = sink->text_sink.background;
1669 values.background = sink->text_sink.cursor_color;
1671 values.background = sink->text_sink.foreground;
1673 sink->ascii_sink.invgc = XtAllocateGC((Widget)sink, 0, valuemask, &values,
1674 GCClipMask | GCFont, 0);
1676 valuemask |= GCFunction;
1677 values.function = GXxor;
1679 values.foreground = sink->text_sink.background ^ sink->text_sink.cursor_color;
1681 values.foreground = sink->text_sink.background ^ sink->text_sink.foreground;
1683 values.background = 0L;
1684 sink->ascii_sink.xorgc = XtAllocateGC((Widget)sink, 0, valuemask,
1685 &values, GCClipMask | GCFont, 0);
1687 XawAsciiSinkResize((Widget)sink);
1691 * XawAsciiSinkInitialize
1694 * request - the requested and new values for the object instance
1698 * Initializes the TextSink Object.
1702 XawAsciiSinkInitialize(Widget request, Widget cnew,
1703 ArgList args, Cardinal *num_args)
1705 AsciiSinkObject sink = (AsciiSinkObject)cnew;
1709 if (!sink->ascii_sink.font) XtError("Aborting: no font found\n");
1711 sink->ascii_sink.cursor_position = 0;
1712 sink->ascii_sink.laststate = XawisOff;
1713 sink->ascii_sink.cursor_x = sink->ascii_sink.cursor_y = 0;
1718 * XawAsciiSinkDestroy
1721 * w - AsciiSink Object
1724 * This function cleans up when the object is destroyed.
1727 XawAsciiSinkDestroy(Widget w)
1729 AsciiSinkObject sink = (AsciiSinkObject)w;
1731 XtReleaseGC(w, sink->ascii_sink.normgc);
1732 XtReleaseGC(w, sink->ascii_sink.invgc);
1733 XtReleaseGC(w, sink->ascii_sink.xorgc);
1735 sink->ascii_sink.normgc =
1736 sink->ascii_sink.invgc =
1737 sink->ascii_sink.xorgc = NULL;
1741 XawAsciiSinkResize(Widget w)
1743 TextWidget ctx = (TextWidget)XtParent(w);
1744 AsciiSinkObject sink = (AsciiSinkObject)w;
1748 if (w->core.widget_class != asciiSinkObjectClass)
1751 rect.x = ctx->text.r_margin.left;
1752 rect.y = ctx->text.r_margin.top;
1753 width = (int)XtWidth(ctx) - RHMargins(ctx);
1754 height = (int)XtHeight(ctx) - RVMargins(ctx);
1756 rect.height = height;
1758 if (sink->ascii_sink.normgc) {
1759 if (width >= 0 && height >= 0)
1760 XSetClipRectangles(XtDisplay((Widget)ctx), sink->ascii_sink.normgc,
1761 0, 0, &rect, 1, Unsorted);
1763 XSetClipMask(XtDisplay((Widget)ctx), sink->ascii_sink.normgc, None);
1765 if (sink->ascii_sink.invgc) {
1766 if (width >= 0 && height >= 0)
1767 XSetClipRectangles(XtDisplay((Widget)ctx), sink->ascii_sink.invgc,
1768 0, 0, &rect, 1, Unsorted);
1770 XSetClipMask(XtDisplay((Widget)ctx), sink->ascii_sink.invgc, None);
1772 if (sink->ascii_sink.xorgc) {
1773 if (width >= 0 && height >= 0)
1774 XSetClipRectangles(XtDisplay((Widget)ctx), sink->ascii_sink.xorgc,
1775 0, 0, &rect, 1, Unsorted);
1777 XSetClipMask(XtDisplay((Widget)ctx), sink->ascii_sink.xorgc, None);
1783 * XawAsciiSinkSetValues
1786 * current - current state of the object
1787 * request - what was requested
1788 * cnew - what the object will become
1791 * Sets the values for the AsciiSink.
1794 * True if redisplay is needed
1798 XawAsciiSinkSetValues(Widget current, Widget request, Widget cnew,
1799 ArgList args, Cardinal *num_args)
1801 AsciiSinkObject w = (AsciiSinkObject)cnew;
1802 AsciiSinkObject old_w = (AsciiSinkObject)current;
1804 if (w->ascii_sink.font != old_w->ascii_sink.font
1805 || w->text_sink.background != old_w->text_sink.background
1806 || w->text_sink.foreground != old_w->text_sink.foreground
1808 || w->text_sink.cursor_color != old_w->text_sink.cursor_color
1809 || w->text_sink.properties != old_w->text_sink.properties
1813 XtReleaseGC(cnew, w->ascii_sink.normgc);
1814 XtReleaseGC(cnew, w->ascii_sink.invgc);
1815 XtReleaseGC(cnew, w->ascii_sink.xorgc);
1818 ((TextWidget)XtParent(cnew))->text.redisplay_needed = True;
1820 else if (w->ascii_sink.echo != old_w->ascii_sink.echo
1821 || w->ascii_sink.display_nonprinting
1822 != old_w->ascii_sink.display_nonprinting)
1823 ((TextWidget)XtParent(cnew))->text.redisplay_needed = True;
1825 if (w->text_sink.properties != old_w->text_sink.properties) {
1826 XawTextProperty *property =
1827 XawTextSinkGetProperty(cnew, XrmStringToQuark("default"));
1830 if (property->mask & XAW_TPROP_FONT)
1831 w->ascii_sink.font = property->font;
1832 if (property->mask & XAW_TPROP_FOREGROUND)
1833 w->text_sink.foreground = property->foreground;
1834 if (property->mask & XAW_TPROP_BACKGROUND)
1835 w->text_sink.background = property->background;
1848 * w - AsciiSink Object
1849 * height - height to fit lines into
1852 * Finds the Maximum number of lines that will fit in a given height.
1855 * The number of lines that will fit
1859 MaxLines(Widget w, unsigned int height)
1861 AsciiSinkObject sink = (AsciiSinkObject)w;
1864 font_height = sink->ascii_sink.font->ascent + sink->ascii_sink.font->descent + 1;
1866 return ((int)height / font_height);
1874 * w - AsciiSink Object
1875 * lines - number of lines
1878 * Finds the Minium height that will contain a given number lines.
1884 MaxHeight(Widget w, int lines)
1886 AsciiSinkObject sink = (AsciiSinkObject)w;
1888 return (lines * (sink->ascii_sink.font->ascent +
1889 sink->ascii_sink.font->descent + 1));
1897 * w - AsciiSink Object
1898 * tab_count - number of tabs in the list
1899 * tabs - text positions of the tabs
1902 * Sets the Tab stops.
1905 SetTabs(Widget w, int tab_count, short *tabs)
1907 AsciiSinkObject sink = (AsciiSinkObject)w;
1909 Atom XA_FIGURE_WIDTH;
1910 unsigned long figure_width = 0;
1911 XFontStruct *font = sink->ascii_sink.font;
1914 * Find the figure width of the current font
1916 XA_FIGURE_WIDTH = XInternAtom(XtDisplayOfObject(w), "FIGURE_WIDTH", False);
1917 if (XA_FIGURE_WIDTH != None
1918 && (!XGetFontProperty(font, XA_FIGURE_WIDTH, &figure_width)
1919 || figure_width == 0)) {
1920 if (font->per_char && font->min_char_or_byte2 <= '$'
1921 && font->max_char_or_byte2 >= '$')
1922 figure_width = font->per_char['$' - font->min_char_or_byte2].width;
1924 figure_width = font->max_bounds.width;
1927 if (tab_count > sink->text_sink.tab_count) {
1928 sink->text_sink.tabs = (Position *)
1929 XtRealloc((char*)sink->text_sink.tabs, tab_count * sizeof(Position));
1930 sink->text_sink.char_tabs = (short *)
1931 XtRealloc((char*)sink->text_sink.char_tabs, tab_count * sizeof(short));
1934 for (i = 0 ; i < tab_count ; i++) {
1935 sink->text_sink.tabs[i] = tabs[i] * figure_width;
1936 sink->text_sink.char_tabs[i] = tabs[i];
1939 sink->text_sink.tab_count = tab_count;
1943 TextWidget ctx = (TextWidget)XtParent(w);
1944 ctx->text.redisplay_needed = True;
1945 _XawTextBuildLineTable(ctx, ctx->text.lt.top, True);