749N/A/* $XConsortium: MultiSink.c,v 1.5 94/04/17 20:12:22 kaleb Exp $ */
749N/A
749N/A/*
749N/A * Copyright 1991 by OMRON Corporation
749N/A *
749N/A * Permission to use, copy, modify, distribute, and sell this software and its
749N/A * documentation for any purpose is hereby granted without fee, provided that
749N/A * the above copyright notice appear in all copies and that both that
749N/A * copyright notice and this permission notice appear in supporting
749N/A * documentation, and that the name of OMRON not be used in advertising
749N/A * or publicity pertaining to distribution of the software without specific,
749N/A * written prior permission. OMRON makes no representations about the
749N/A * suitability of this software for any purpose. It is provided "as is"
749N/A * without express or implied warranty.
749N/A *
749N/A * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
749N/A * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
749N/A * EVENT SHALL OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
749N/A * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
749N/A * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
749N/A * TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
749N/A * PERFORMANCE OF THIS SOFTWARE.
749N/A *
749N/A * Author: Li Yuhong OMRON Corporation
749N/A */
749N/A
749N/A/***********************************************************
749N/A
749N/ACopyright (c) 1987, 1988, 1994 X Consortium
749N/A
749N/APermission is hereby granted, free of charge, to any person obtaining a copy
749N/Aof this software and associated documentation files (the "Software"), to deal
749N/Ain the Software without restriction, including without limitation the rights
749N/Ato use, copy, modify, merge, publish, distribute, sublicense, and/or sell
749N/Acopies of the Software, and to permit persons to whom the Software is
749N/Afurnished to do so, subject to the following conditions:
749N/A
749N/AThe above copyright notice and this permission notice shall be included in
749N/Aall copies or substantial portions of the Software.
749N/A
749N/ATHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
749N/AIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
749N/AFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
749N/AX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
749N/AAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
749N/ACONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
749N/A
749N/AExcept as contained in this notice, the name of the X Consortium shall not be
749N/Aused in advertising or otherwise to promote the sale, use or other dealings
749N/Ain this Software without prior written authorization from the X Consortium.
749N/A
749N/A
749N/ACopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
749N/A
749N/A All Rights Reserved
749N/A
749N/APermission to use, copy, modify, and distribute this software and its
749N/Adocumentation for any purpose and without fee is hereby granted,
749N/Aprovided that the above copyright notice appear in all copies and that
749N/Aboth that copyright notice and this permission notice appear in
749N/Asupporting documentation, and that the name of Digital not be
749N/Aused in advertising or publicity pertaining to distribution of the
749N/Asoftware without specific, written prior permission.
749N/A
749N/ADIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
749N/AALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
749N/ADIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
749N/AANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
749N/AWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
749N/AARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
749N/ASOFTWARE.
749N/A
749N/A******************************************************************/
749N/A
749N/A#include <X11/IntrinsicP.h>
749N/A#include <X11/StringDefs.h>
749N/A#include <X11/Xatom.h>
749N/A#include <X11/Xaw/XawInit.h>
749N/A#include "MultiSinkP.h"
749N/A#include <X11/Xaw/MultiSrcP.h>
749N/A#include <X11/Xaw/TextP.h>
749N/A#include "XawI18n.h"
749N/A#include <stdio.h>
749N/A#include <stdlib.h>
749N/A#include <ctype.h>
749N/A
749N/A#ifdef GETLASTPOS
749N/A#undef GETLASTPOS /* We will use our own GETLASTPOS. */
749N/A#endif
749N/A
749N/A#define GETLASTPOS XawTextSourceScan(source, (XawTextPosition) 0, XawstAll, XawsdRight, 1, TRUE)
749N/A
749N/Astatic void Initialize(), Destroy();
749N/Astatic Boolean SetValues();
749N/Astatic int MaxLines(), MaxHeight();
749N/Astatic void SetTabs();
749N/A
749N/Astatic void DisplayText(), InsertCursor(), FindPosition();
749N/Astatic void FindDistance(), Resolve(), GetCursorBounds();
749N/A
749N/A#define offset(field) XtOffsetOf(MultiSinkRec, multi_sink.field)
749N/A
749N/Astatic XtResource resources[] = {
749N/A {XtNfontSet, XtCFontSet, XtRFontSet, sizeof (XFontSet),
749N/A offset(fontset), XtRString, XtDefaultFontSet},
749N/A {XtNecho, XtCOutput, XtRBoolean, sizeof(Boolean),
749N/A offset(echo), XtRImmediate, (XtPointer) True},
749N/A {XtNdisplayNonprinting, XtCOutput, XtRBoolean, sizeof(Boolean),
749N/A offset(display_nonprinting), XtRImmediate, (XtPointer) True},
749N/A};
749N/A#undef offset
749N/A
749N/A#define SuperClass (&textSinkClassRec)
749N/AMultiSinkClassRec multiSinkClassRec = {
749N/A { /* core_class fields */
749N/A /* superclass */ (WidgetClass) SuperClass,
749N/A /* class_name */ "MultiSink",
749N/A /* widget_size */ sizeof(MultiSinkRec),
749N/A /* class_initialize */ XawInitializeWidgetSet,
749N/A /* class_part_initialize */ NULL,
749N/A /* class_inited */ FALSE,
749N/A /* initialize */ Initialize,
749N/A /* initialize_hook */ NULL,
749N/A /* obj1 */ NULL,
749N/A /* obj2 */ NULL,
749N/A /* obj3 */ 0,
749N/A /* resources */ resources,
749N/A /* num_resources */ XtNumber(resources),
749N/A /* xrm_class */ NULLQUARK,
749N/A /* obj4 */ FALSE,
749N/A /* obj5 */ FALSE,
749N/A /* obj6 */ FALSE,
749N/A /* obj7 */ FALSE,
749N/A /* destroy */ Destroy,
749N/A /* obj8 */ NULL,
749N/A /* obj9 */ NULL,
749N/A /* set_values */ SetValues,
749N/A /* set_values_hook */ NULL,
749N/A /* obj10 */ NULL,
749N/A /* get_values_hook */ NULL,
749N/A /* obj11 */ NULL,
749N/A /* version */ XtVersion,
749N/A /* callback_private */ NULL,
749N/A /* obj12 */ NULL,
749N/A /* obj13 */ NULL,
749N/A /* obj14 */ NULL,
749N/A /* extension */ NULL
749N/A },
749N/A { /* text_sink_class fields */
749N/A /* DisplayText */ DisplayText,
749N/A /* InsertCursor */ InsertCursor,
749N/A /* ClearToBackground */ XtInheritClearToBackground,
749N/A /* FindPosition */ FindPosition,
749N/A /* FindDistance */ FindDistance,
749N/A /* Resolve */ Resolve,
749N/A /* MaxLines */ MaxLines,
749N/A /* MaxHeight */ MaxHeight,
749N/A /* SetTabs */ SetTabs,
749N/A /* GetCursorBounds */ GetCursorBounds
749N/A },
749N/A { /* multi_sink_class fields */
749N/A /* unused */ 0
749N/A }
749N/A};
749N/A
749N/AWidgetClass multiSinkObjectClass = (WidgetClass)&multiSinkClassRec;
749N/A
749N/A/* Utilities */
749N/A
749N/Astatic int
749N/ACharWidth (w, x, c)
749N/A Widget w;
749N/A int x;
749N/A wchar_t c;
749N/A{
749N/A int i, width;
749N/A MultiSinkObject sink = (MultiSinkObject) w;
749N/A XFontSet fontset = sink->multi_sink.fontset;
749N/A Position *tab;
749N/A
749N/A if ( c == _Xaw_atowc(XawLF) ) return(0);
749N/A
749N/A if (c == _Xaw_atowc(XawTAB)) {
749N/A /* Adjust for Left Margin. */
749N/A x -= ((TextWidget) XtParent(w))->text.margin.left;
749N/A
749N/A if (x >= (int)XtParent(w)->core.width) return 0;
749N/A for (i = 0, tab = sink->text_sink.tabs ;
749N/A i < sink->text_sink.tab_count ; i++, tab++) {
749N/A if (x < *tab) {
749N/A if (*tab < (int)XtParent(w)->core.width)
749N/A return *tab - x;
749N/A else
749N/A return 0;
749N/A }
749N/A }
749N/A return 0;
749N/A }
749N/A
749N/A if (XwcTextEscapement (fontset, &c, 1) == 0)
749N/A if (sink->multi_sink.display_nonprinting)
749N/A c = _Xaw_atowc('@');
749N/A else {
749N/A c = _Xaw_atowc(XawSP);
749N/A }
749N/A
749N/A /*
749N/A * if more efficiency(suppose one column is one ASCII char)
749N/A
749N/A width = XwcGetColumn(fontset->font_charset, fontset->num_of_fonts, c) *
749N/A fontset->font_struct_list[0]->min_bounds.width;
749N/A *
749N/A * WARNING: Very Slower!!!
749N/A *
749N/A * Li Yuhong.
749N/A */
749N/A
749N/A width = XwcTextEscapement(fontset, &c, 1);
749N/A
749N/A return width;
749N/A}
749N/A
749N/A/* Function Name: PaintText
749N/A * Description: Actually paints the text into the windoe.
749N/A * Arguments: w - the text widget.
749N/A * gc - gc to paint text with.
749N/A * x, y - location to paint the text.
749N/A * buf, len - buffer and length of text to paint.
749N/A * Returns: the width of the text painted, or 0.
749N/A *
749N/A * NOTE: If this string attempts to paint past the end of the window
749N/A * then this function will return zero.
749N/A */
749N/A
749N/Astatic Dimension
749N/APaintText(w, gc, x, y, buf, len)
749N/A Widget w;
749N/A GC gc;
749N/A Position x, y;
749N/A wchar_t* buf;
749N/A int len;
749N/A{
749N/A MultiSinkObject sink = (MultiSinkObject) w;
749N/A TextWidget ctx = (TextWidget) XtParent(w);
749N/A
749N/A XFontSet fontset = sink->multi_sink.fontset;
749N/A Position max_x;
749N/A Dimension width = XwcTextEscapement(fontset, buf, len);
749N/A XFontSetExtents *ext = XExtentsOfFontSet(fontset);
749N/A max_x = (Position) ctx->core.width;
749N/A
749N/A if ( ((int) width) <= -x) /* Don't draw if we can't see it. */
749N/A return(width);
749N/A
749N/A XwcDrawImageString(XtDisplay(ctx), XtWindow(ctx), fontset, gc,
749N/A (int) x, (int) y, buf, len);
749N/A if ( (((Position) width + x) > max_x) && (ctx->text.margin.right != 0) ) {
749N/A x = ctx->core.width - ctx->text.margin.right;
749N/A width = ctx->text.margin.right;
749N/A XFillRectangle(XtDisplay((Widget) ctx), XtWindow( (Widget) ctx),
749N/A sink->multi_sink.normgc, (int) x,
749N/A (int) y - abs(ext->max_logical_extent.y),
749N/A (unsigned int) width,
749N/A (unsigned int) ext->max_logical_extent.height);
749N/A return(0);
749N/A }
749N/A return(width);
749N/A}
749N/A
749N/A/* Sink Object Functions */
749N/A
749N/A/*
749N/A * This function does not know about drawing more than one line of text.
749N/A */
749N/A
749N/Astatic void
749N/ADisplayText(w, x, y, pos1, pos2, highlight)
749N/A Widget w;
749N/A Position x, y;
749N/A Boolean highlight;
749N/A XawTextPosition pos1, pos2;
749N/A{
749N/A MultiSinkObject sink = (MultiSinkObject) w;
749N/A Widget source = XawTextGetSource(XtParent(w));
749N/A wchar_t buf[BUFSIZ];
749N/A XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
749N/A
749N/A int j, k;
749N/A XawTextBlock blk;
749N/A GC gc = highlight ? sink->multi_sink.invgc : sink->multi_sink.normgc;
749N/A GC invgc = highlight ? sink->multi_sink.normgc : sink->multi_sink.invgc;
749N/A
749N/A if (!sink->multi_sink.echo) return;
749N/A
749N/A y += abs(ext->max_logical_extent.y);
749N/A for ( j = 0 ; pos1 < pos2 ; ) {
749N/A pos1 = XawTextSourceRead(source, pos1, &blk, (int) (pos2 - pos1));
749N/A for (k = 0; k < blk.length; k++) {
749N/A if (j >= BUFSIZ) { /* buffer full, dump the text. */
749N/A x += PaintText(w, gc, x, y, buf, j);
749N/A j = 0;
749N/A }
749N/A buf[j] = ((wchar_t *)blk.ptr)[k];
749N/A if (buf[j] == _Xaw_atowc(XawLF))
749N/A continue;
749N/A
749N/A else if (buf[j] == _Xaw_atowc(XawTAB)) {
749N/A Position temp = 0;
749N/A Dimension width;
749N/A
749N/A if ((j != 0) && ((temp = PaintText(w, gc, x, y, buf, j)) == 0))
749N/A return;
749N/A
749N/A x += temp;
749N/A width = CharWidth(w, x, _Xaw_atowc(XawTAB));
749N/A XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
749N/A invgc, (int) x,
749N/A (int) y - abs(ext->max_logical_extent.y),
749N/A (unsigned int)width,
749N/A (unsigned int)ext->max_logical_extent.height);
749N/A x += width;
749N/A j = -1;
749N/A }
749N/A else if (XwcTextEscapement (sink->multi_sink.fontset, &buf[j], 1 == 0)) {
749N/A if (sink->multi_sink.display_nonprinting)
749N/A buf[j] = _Xaw_atowc('@');
749N/A else
749N/A buf[j] = _Xaw_atowc(' ');
749N/A }
749N/A j++;
749N/A }
749N/A }
749N/A if (j > 0)
749N/A (void) PaintText(w, gc, x, y, buf, j);
749N/A}
749N/A
749N/A#define insertCursor_width 6
749N/A#define insertCursor_height 3
749N/Astatic char insertCursor_bits[] = {0x0c, 0x1e, 0x33};
749N/A
749N/Astatic Pixmap
749N/ACreateInsertCursor(s)
749N/A Screen *s;
749N/A{
749N/A return (XCreateBitmapFromData (DisplayOfScreen(s), RootWindowOfScreen(s),
749N/A insertCursor_bits, insertCursor_width, insertCursor_height));
749N/A}
749N/A
749N/A/* Function Name: GetCursorBounds
749N/A * Description: Returns the size and location of the cursor.
749N/A * Arguments: w - the text object.
749N/A * RETURNED rect - an X rectangle to return the cursor bounds in.
749N/A * Returns: none.
749N/A */
749N/A
749N/Astatic void
749N/AGetCursorBounds(w, rect)
749N/A Widget w;
749N/A XRectangle * rect;
749N/A{
749N/A MultiSinkObject sink = (MultiSinkObject) w;
749N/A
749N/A rect->width = (unsigned short) insertCursor_width;
749N/A rect->height = (unsigned short) insertCursor_height;
749N/A rect->x = sink->multi_sink.cursor_x - (short) (rect->width / 2);
749N/A rect->y = sink->multi_sink.cursor_y - (short) rect->height;
749N/A}
749N/A
749N/A/*
749N/A * The following procedure manages the "insert" cursor.
749N/A */
749N/A
749N/Astatic void
749N/AInsertCursor (w, x, y, state)
749N/A Widget w;
749N/A Position x, y;
749N/A XawTextInsertState state;
749N/A{
749N/A MultiSinkObject sink = (MultiSinkObject) w;
749N/A Widget text_widget = XtParent(w);
749N/A XRectangle rect;
749N/A
749N/A sink->multi_sink.cursor_x = x;
749N/A sink->multi_sink.cursor_y = y;
749N/A
749N/A GetCursorBounds(w, &rect);
749N/A if (state != sink->multi_sink.laststate && XtIsRealized(text_widget))
749N/A XCopyPlane(XtDisplay(text_widget),
749N/A sink->multi_sink.insertCursorOn,
749N/A XtWindow(text_widget), sink->multi_sink.xorgc,
749N/A 0, 0, (unsigned int) rect.width, (unsigned int) rect.height,
749N/A (int) rect.x, (int) rect.y, 1);
749N/A sink->multi_sink.laststate = state;
749N/A}
749N/A
749N/A/*
749N/A * Given two positions, find the distance between them.
749N/A */
749N/A
749N/Astatic void
749N/AFindDistance (w, fromPos, fromx, toPos, resWidth, resPos, resHeight)
749N/A Widget w;
749N/A XawTextPosition fromPos; /* First position. */
749N/A int fromx; /* Horizontal location of first position. */
749N/A XawTextPosition toPos; /* Second position. */
749N/A int* resWidth; /* Distance between fromPos and resPos. */
749N/A XawTextPosition* resPos; /* Actual second position used. */
749N/A int* resHeight; /* Height required. */
749N/A{
749N/A MultiSinkObject sink = (MultiSinkObject) w;
749N/A Widget source = XawTextGetSource(XtParent(w));
749N/A
749N/A XawTextPosition index, lastPos;
749N/A wchar_t c;
749N/A XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
749N/A XawTextBlock blk;
749N/A
749N/A /* we may not need this */
749N/A lastPos = GETLASTPOS;
749N/A XawTextSourceRead(source, fromPos, &blk, (int) (toPos - fromPos));
749N/A *resWidth = 0;
749N/A for (index = fromPos; index != toPos && index < lastPos; index++) {
749N/A if (index - blk.firstPos >= blk.length)
749N/A XawTextSourceRead(source, index, &blk, (int) (toPos - fromPos));
749N/A c = ((wchar_t *)blk.ptr)[index - blk.firstPos];
749N/A *resWidth += CharWidth(w, fromx + *resWidth, c);
749N/A if (c == _Xaw_atowc(XawLF)) {
749N/A index++;
749N/A break;
749N/A }
749N/A }
749N/A *resPos = index;
749N/A *resHeight = ext->max_logical_extent.height;
749N/A}
749N/A
749N/A
749N/Astatic void
749N/AFindPosition(w, fromPos, fromx, width, stopAtWordBreak, resPos, resWidth, resHeight)
749N/A Widget w;
749N/A XawTextPosition fromPos; /* Starting position. */
749N/A int fromx; /* Horizontal location of starting position.*/
749N/A int width; /* Desired width. */
749N/A int stopAtWordBreak; /* Whether the resulting position should be at
749N/A a word break. */
749N/A XawTextPosition *resPos; /* Resulting position. */
749N/A int* resWidth; /* Actual width used. */
749N/A int* resHeight; /* Height required. */
749N/A{
749N/A MultiSinkObject sink = (MultiSinkObject) w;
749N/A Widget source = XawTextGetSource(XtParent(w));
749N/A
749N/A XawTextPosition lastPos, index, whiteSpacePosition;
749N/A int lastWidth, whiteSpaceWidth;
749N/A Boolean whiteSpaceSeen;
749N/A wchar_t c;
749N/A XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
749N/A XawTextBlock blk;
749N/A
749N/A lastPos = GETLASTPOS;
749N/A
749N/A XawTextSourceRead(source, fromPos, &blk, BUFSIZ);
749N/A *resWidth = 0;
749N/A whiteSpaceSeen = FALSE;
749N/A c = 0;
749N/A for (index = fromPos; *resWidth <= width && index < lastPos; index++) {
749N/A lastWidth = *resWidth;
749N/A if (index - blk.firstPos >= blk.length)
749N/A XawTextSourceRead(source, index, &blk, BUFSIZ);
749N/A c = ((wchar_t *)blk.ptr)[index - blk.firstPos];
749N/A *resWidth += CharWidth(w, fromx + *resWidth, c);
749N/A
749N/A if ((c == _Xaw_atowc(XawSP) || c == _Xaw_atowc(XawTAB)) &&
749N/A *resWidth <= width) {
749N/A whiteSpaceSeen = TRUE;
749N/A whiteSpacePosition = index;
749N/A whiteSpaceWidth = *resWidth;
749N/A }
749N/A if (c == _Xaw_atowc(XawLF)) {
749N/A index++;
749N/A break;
749N/A }
749N/A }
749N/A if (*resWidth > width && index > fromPos) {
749N/A *resWidth = lastWidth;
749N/A index--;
749N/A if (stopAtWordBreak && whiteSpaceSeen) {
749N/A index = whiteSpacePosition + 1;
749N/A *resWidth = whiteSpaceWidth;
749N/A }
749N/A }
749N/A if (index == lastPos && c != _Xaw_atowc(XawLF)) index = lastPos + 1;
749N/A *resPos = index;
749N/A *resHeight = ext->max_logical_extent.height;
749N/A}
749N/A
749N/Astatic void
749N/AResolve (w, pos, fromx, width, leftPos, rightPos)
749N/A Widget w;
749N/A XawTextPosition pos;
749N/A int fromx, width;
749N/A XawTextPosition *leftPos, *rightPos;
749N/A{
749N/A int resWidth, resHeight;
749N/A Widget source = XawTextGetSource(XtParent(w));
749N/A
749N/A FindPosition(w, pos, fromx, width, FALSE, leftPos, &resWidth, &resHeight);
749N/A if (*leftPos > GETLASTPOS)
749N/A *leftPos = GETLASTPOS;
749N/A *rightPos = *leftPos;
749N/A}
749N/A
749N/Astatic void
749N/AGetGC(sink)
749N/A MultiSinkObject sink;
749N/A{
749N/A XtGCMask valuemask = (GCGraphicsExposures | GCForeground | GCBackground );
749N/A XGCValues values;
749N/A
749N/A values.graphics_exposures = (Bool) FALSE;
749N/A
749N/A values.foreground = sink->text_sink.foreground;
749N/A values.background = sink->text_sink.background;
749N/A
749N/A sink->multi_sink.normgc = XtAllocateGC( (Widget)sink, 0, valuemask, &values, GCFont, 0 );
749N/A
749N/A values.foreground = sink->text_sink.background;
749N/A values.background = sink->text_sink.foreground;
749N/A sink->multi_sink.invgc = XtAllocateGC( (Widget)sink, 0, valuemask, &values, GCFont, 0 );
749N/A
749N/A values.function = GXxor;
749N/A values.background = (unsigned long) 0L; /* (pix ^ 0) = pix */
749N/A values.foreground = (sink->text_sink.background ^
749N/A sink->text_sink.foreground);
749N/A valuemask = GCGraphicsExposures | GCFunction | GCForeground | GCBackground;
749N/A
749N/A /* if this GC is not used for fontset rendering then AllocateGC aint needed. Dont hurt tho.*/
749N/A sink->multi_sink.xorgc = XtAllocateGC( (Widget)sink, 0, valuemask, &values, GCFont, 0 );
749N/A}
749N/A
749N/A
749N/A/***** Public routines *****/
749N/A
749N/A/* Function Name: Initialize
749N/A * Description: Initializes the TextSink Object.
749N/A * Arguments: request, new - the requested and new values for the object
749N/A * instance.
749N/A * Returns: none.
749N/A *
749N/A */
749N/A
749N/A/* ARGSUSED */
749N/Astatic void
749N/AInitialize(request, new, args, num_args)
749N/A Widget request, new;
749N/A ArgList args;
749N/A Cardinal* num_args;
749N/A{
749N/A MultiSinkObject sink = (MultiSinkObject) new;
749N/A
749N/A GetGC(sink);
749N/A
749N/A sink->multi_sink.insertCursorOn= CreateInsertCursor(XtScreenOfObject(new));
749N/A sink->multi_sink.laststate = XawisOff;
749N/A sink->multi_sink.cursor_x = sink->multi_sink.cursor_y = 0;
749N/A}
749N/A
749N/A/* Function Name: Destroy
749N/A * Description: This function cleans up when the object is
749N/A * destroyed.
749N/A * Arguments: w - the MultiSink Object.
749N/A * Returns: none.
749N/A */
749N/A
749N/Astatic void
749N/ADestroy(w)
749N/A Widget w;
749N/A{
749N/A MultiSinkObject sink = (MultiSinkObject) w;
749N/A
749N/A XtReleaseGC(w, sink->multi_sink.normgc);
749N/A XtReleaseGC(w, sink->multi_sink.invgc);
749N/A XtReleaseGC(w, sink->multi_sink.xorgc);
749N/A
749N/A XFreePixmap(XtDisplayOfObject(w), sink->multi_sink.insertCursorOn);
749N/A}
749N/A
749N/A/* Function Name: SetValues
749N/A * Description: Sets the values for the MultiSink
749N/A * Arguments: current - current state of the object.
749N/A * request - what was requested.
749N/A * new - what the object will become.
749N/A * Returns: True if redisplay is needed.
749N/A */
749N/A
749N/A/* ARGSUSED */
749N/Astatic Boolean
749N/ASetValues(current, request, new, args, num_args)
749N/A Widget current, request, new;
749N/A ArgList args;
749N/A Cardinal* num_args;
749N/A{
749N/A MultiSinkObject w = (MultiSinkObject) new;
749N/A MultiSinkObject old_w = (MultiSinkObject) current;
749N/A
749N/A /* Font set is not in the GC! Do not make a new GC when font set changes! */
749N/A
749N/A if ( w->multi_sink.fontset != old_w->multi_sink.fontset ) {
749N/A ((TextWidget)XtParent(new))->text.redisplay_needed = True;
749N/A#ifndef NO_TAB_FIX
749N/A SetTabs( w, w->text_sink.tab_count, w->text_sink.char_tabs );
749N/A#endif
749N/A }
749N/A
749N/A if ( w->text_sink.background != old_w->text_sink.background ||
749N/A w->text_sink.foreground != old_w->text_sink.foreground ) {
749N/A
749N/A XtReleaseGC((Widget)w, w->multi_sink.normgc);
749N/A XtReleaseGC((Widget)w, w->multi_sink.invgc);
749N/A XtReleaseGC((Widget)w, w->multi_sink.xorgc);
749N/A GetGC(w);
749N/A ((TextWidget)XtParent(new))->text.redisplay_needed = True;
749N/A } else {
749N/A if ( (w->multi_sink.echo != old_w->multi_sink.echo) ||
749N/A (w->multi_sink.display_nonprinting !=
749N/A old_w->multi_sink.display_nonprinting) )
749N/A ((TextWidget)XtParent(new))->text.redisplay_needed = True;
749N/A }
749N/A
749N/A return False;
749N/A}
749N/A
749N/A/* Function Name: MaxLines
749N/A * Description: Finds the Maximum number of lines that will fit in
749N/A * a given height.
749N/A * Arguments: w - the MultiSink Object.
749N/A * height - height to fit lines into.
749N/A * Returns: the number of lines that will fit.
749N/A */
749N/A
749N/A/* ARGSUSED */
749N/Astatic int
749N/AMaxLines(w, height)
749N/A Widget w;
749N/A Dimension height;
749N/A{
749N/A MultiSinkObject sink = (MultiSinkObject) w;
749N/A int font_height;
749N/A XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
749N/A
749N/A font_height = ext->max_logical_extent.height;
749N/A return( ((int) height) / font_height );
749N/A}
749N/A
749N/A/* Function Name: MaxHeight
749N/A * Description: Finds the Minium height that will contain a given number
749N/A * lines.
749N/A * Arguments: w - the MultiSink Object.
749N/A * lines - the number of lines.
749N/A * Returns: the height.
749N/A */
749N/A
749N/A/* ARGSUSED */
749N/Astatic int
749N/A#if NeedFunctionPrototypes
749N/AMaxHeight(
749N/A Widget w,
749N/A int lines )
749N/A#else
749N/AMaxHeight( w, lines )
749N/A Widget w;
749N/A int lines;
749N/A#endif
749N/A{
749N/A MultiSinkObject sink = (MultiSinkObject) w;
749N/A XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
749N/A
749N/A return(lines * ext->max_logical_extent.height);
749N/A}
749N/A
749N/A/* Function Name: SetTabs
749N/A * Description: Sets the Tab stops.
749N/A * Arguments: w - the MultiSink Object.
749N/A * tab_count - the number of tabs in the list.
749N/A * tabs - the text positions of the tabs.
749N/A * Returns: none
749N/A */
749N/A
749N/Astatic void
749N/A#if NeedFunctionPrototypes
749N/ASetTabs(
749N/A Widget w,
749N/A int tab_count,
749N/A short* tabs )
749N/A#else
749N/ASetTabs( w, tab_count, tabs )
749N/A Widget w;
749N/A int tab_count;
749N/A short* tabs;
749N/A#endif
749N/A{
749N/A MultiSinkObject sink = (MultiSinkObject) w;
749N/A int i;
749N/A Atom XA_FIGURE_WIDTH;
749N/A unsigned long figure_width = 0;
749N/A XFontStruct *font;
749N/A
749N/A /*
749N/A * Bug:
749N/A * Suppose the first font of fontset stores the unit of column.
749N/A *
749N/A * By Li Yuhong, Mar. 14, 1991
749N/A */
749N/A { XFontStruct **f_list;
749N/A char **f_name;
749N/A
749N/A (void) XFontsOfFontSet(sink->multi_sink.fontset, &f_list, &f_name);
749N/A font = f_list[0];
749N/A }
749N/A
749N/A/*
749N/A * Find the figure width of the current font.
749N/A */
749N/A
749N/A XA_FIGURE_WIDTH = XInternAtom(XtDisplayOfObject(w), "FIGURE_WIDTH", FALSE);
749N/A if ( (XA_FIGURE_WIDTH != None) &&
749N/A ( (!XGetFontProperty(font, XA_FIGURE_WIDTH, &figure_width)) ||
749N/A (figure_width == 0)) )
749N/A if (font->per_char && font->min_char_or_byte2 <= '$' &&
749N/A font->max_char_or_byte2 >= '$')
749N/A figure_width = font->per_char['$' - font->min_char_or_byte2].width;
749N/A else
749N/A figure_width = font->max_bounds.width;
749N/A
749N/A if (tab_count > sink->text_sink.tab_count) {
749N/A sink->text_sink.tabs = (Position *)
749N/A XtRealloc((char *) sink->text_sink.tabs,
749N/A (Cardinal) (tab_count * sizeof(Position)));
749N/A sink->text_sink.char_tabs = (short *)
749N/A XtRealloc((char *) sink->text_sink.char_tabs,
749N/A (Cardinal) (tab_count * sizeof(short)));
749N/A }
749N/A
749N/A for ( i = 0 ; i < tab_count ; i++ ) {
749N/A sink->text_sink.tabs[i] = tabs[i] * figure_width;
749N/A sink->text_sink.char_tabs[i] = tabs[i];
749N/A }
749N/A
749N/A sink->text_sink.tab_count = tab_count;
749N/A
749N/A#ifndef NO_TAB_FIX
749N/A ((TextWidget)XtParent(w))->text.redisplay_needed = True;
749N/A#endif
749N/A}
749N/A
749N/Avoid
749N/A#if NeedFunctionPrototypes
749N/A_XawMultiSinkPosToXY(
749N/A Widget w,
749N/A XawTextPosition pos,
749N/A Position *x,
749N/A Position *y )
749N/A#else
749N/A_XawMultiSinkPosToXY( w, pos, x, y )
749N/A Widget w;
749N/A XawTextPosition pos;
749N/A Position *x, *y;
749N/A#endif
749N/A{
749N/A MultiSinkObject sink = (MultiSinkObject) ((TextWidget)w)->text.sink;
749N/A XFontSetExtents *ext = XExtentsOfFontSet( sink->multi_sink.fontset );
749N/A
749N/A _XawTextPosToXY( w, pos, x, y );
749N/A *y += abs( ext->max_logical_extent.y );
749N/A}