DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400 Tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400 Tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ A T

⟦9cf3ea9d2⟧ TextFile

    Length: 15251 (0x3b93)
    Types: TextFile
    Names: »AsciiSink.c«

Derivation

└─⟦5f3412b64⟧ Bits:30000745 8mm tape, Rational 1000, ENVIRONMENT 12_6_5 TOOLS 
    └─ ⟦91c658230⟧ »DATA« 
        └─⟦5d656759a⟧ 
            └─⟦8fb0c967c⟧ 
└─⟦d10a02448⟧ Bits:30000409 8mm tape, Rational 1000, ENVIRONMENT, D_12_7_3
    └─ ⟦fc9b38f02⟧ »DATA« 
        └─⟦8e9e227a9⟧ 
            └─⟦8fb0c967c⟧ 
                └─ ⟦this⟧ »X11/AsciiSink.c« 

TextFile

#ifndef lint
static char Xrcsid[] = "$XConsortium: AsciiSink.c,v 1.26 88/10/19 20:08:51 swick Exp $";
#endif lint


/***********************************************************
Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its 
documentation for any purpose and without fee is hereby granted, 
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in 
supporting documentation, and that the names of Digital or MIT not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.  

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

******************************************************************/

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/TextP.h>


#define GETLASTPOS (*source->Scan)(source, 0, XtstAll, XtsdRight, 1, TRUE)
/* Private Ascii TextSink Definitions */

static unsigned bufferSize = 200;

typedef struct _AsciiSinkData {
    Pixel foreground;
    GC normgc, invgc, xorgc;
    XFontStruct *font;
    int em;
    Pixmap insertCursorOn;
    XtTextInsertState laststate;
    int tab_count;
    Position *tabs;
} AsciiSinkData, *AsciiSinkPtr;

static char *buf = NULL;

/* XXX foreground default should be XtDefaultFGPixel. How do i do that?? */

static XtResource SinkResources[] = {
    {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
        XtOffset(AsciiSinkPtr, font), XtRString, "Fixed"},
    {XtNforeground, XtCForeground, XtRPixel, sizeof (int),
        XtOffset(AsciiSinkPtr, foreground), XtRString, "Black"},    
};

/* Utilities */

static int CharWidth (w, x, c)
  Widget w;
  int x;
  char c;
{
    AsciiSinkData *data = (AsciiSinkData*) ((TextWidget)w)->text.sink->data;
    int     width, nonPrinting;
    XFontStruct *font = data->font;

    if (c == '\t') {
	int i;
	Position *tab;
	if (x >= w->core.width) return 0;
	for (i=0, tab=data->tabs; i<data->tab_count; i++, tab++) {
	    if (x < *tab) {
		if (*tab < w->core.width)
		    return *tab - x;
		else
		    return 0;
	    }
	}
	return 0;
    }
    if (c == LF)
	c = SP;
    nonPrinting = (c < SP);
    if (nonPrinting) c += '@';

    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;

    if (nonPrinting)
	width += CharWidth(w, x, '^');

    return width;
}

/* Sink Object Functions */

static int AsciiDisplayText (w, x, y, pos1, pos2, highlight)
  Widget w;
  Position x, y;
  int highlight;
  XtTextPosition pos1, pos2;
{
    XtTextSink sink = ((TextWidget)w)->text.sink;
    XtTextSource source = ((TextWidget)w)->text.source;
    AsciiSinkData *data = (AsciiSinkData *) sink->data ;

    XFontStruct *font = data->font;
    int     j, k;
    Dimension width;
    XtTextBlock blk;
    GC gc = highlight ? data->invgc : data->normgc;
    GC invgc = highlight ? data->normgc : data->invgc;

    y += font->ascent;
    j = 0;
    while (pos1 < pos2) {
	pos1 = (*source->Read)(source, pos1, &blk, pos2 - pos1);
	for (k = 0; k < blk.length; k++) {
	    if (j >= bufferSize - 5) {
		bufferSize *= 2;
		buf = XtRealloc(buf, bufferSize);
	    }
	    buf[j] = blk.ptr[k];
	    if (buf[j] == LF)
		buf[j] = ' ';
	    else if (buf[j] == '\t') {
	        XDrawImageString(XtDisplay(w), XtWindow(w),
			gc, x, y, buf, j);
		buf[j] = 0;
		x += XTextWidth(data->font, buf, j);
		width = CharWidth(w, x, '\t');
		XFillRectangle(XtDisplay(w), XtWindow(w), invgc, x,
			       y - font->ascent, width,
			       (Dimension) (data->font->ascent +
					    data->font->descent));
		x += width;
		j = -1;
	    }
	    else
		if (buf[j] < ' ') {
		    buf[j + 1] = buf[j] + '@';
		    buf[j] = '^';
		    j++;
		}
	    j++;
	}
    }
    XDrawImageString(XtDisplay(w), XtWindow(w), gc, x, y, buf, j);
}


#define insertCursor_width 6
#define insertCursor_height 3
static char insertCursor_bits[] = {0x0c, 0x1e, 0x33};

#ifdef SERVERNOTBROKEN
static Pixmap CreateInsertCursor(s)
Screen *s;
{
    return (XCreateBitmapFromData (DisplayOfScreen(s), RootWindowOfScreen(s),
        insertCursor_bits, insertCursor_width, insertCursor_height));
}
#endif

/*
 * The following procedure manages the "insert" cursor.
 */

static AsciiInsertCursor (w, x, y, state)
  Widget w;
  Position x, y;
  XtTextInsertState state;
{
    XtTextSink sink = ((TextWidget)w)->text.sink;
    AsciiSinkData *data = (AsciiSinkData *) sink->data;

/*
    XCopyArea(sink->dpy,
	      (state == XtisOn) ? data->insertCursorOn : data->insertCursorOff,
	      w, data->normgc, 0, 0, insertCursor_width, insertCursor_height,
	      x - (insertCursor_width >> 1), y - (insertCursor_height));
*/

    if (state != data->laststate && XtIsRealized(w)) {
#ifdef SERVERNOTBROKEN
	XCopyPlane(XtDisplay(w),
		  data->insertCursorOn, XtWindow(w),
		  data->xorgc, 0, 0, insertCursor_width, insertCursor_height,
		  x - (insertCursor_width >> 1), y - (insertCursor_height), 1);
#else /* SERVER is BROKEN */
	/*
	 * See the comment down at the bottom where the pixmap gets built
	 * for why we are doing this this way.
	 */
	XCopyArea (XtDisplay(w), data->insertCursorOn, XtWindow (w),
		   data->xorgc, 0, 0, insertCursor_width, insertCursor_height,
		   x - (insertCursor_width >> 1), y - (insertCursor_height));
#endif /* SERVERNOTBROKEN */
    }
    data->laststate = state;
}

/*
 * Clear the passed region to the background color.
 */

static AsciiClearToBackground (w, x, y, width, height)
  Widget w;
  Position x, y;
  Dimension width, height;
{
#ifndef USE_CLEAR_AREA
    XFillRectangle(XtDisplay(w), XtWindow(w),
		   ((AsciiSinkData*)((TextWidget)w)->text.sink->data)->invgc,
		   x, y, width, height);
#else
    XClearArea(XtDisplay(w), XtWindow(w), x, y, width, height, False);
#endif /*USE_CLEAR_AREA*/
}

/*
 * Given two positions, find the distance between them.
 */

static AsciiFindDistance (w, fromPos, fromx, toPos,
			  resWidth, resPos, resHeight)
  Widget w;
  XtTextPosition fromPos;	/* First position. */
  int fromx;			/* Horizontal location of first position. */
  XtTextPosition toPos;		/* Second position. */
  int *resWidth;		/* Distance between fromPos and resPos. */
  XtTextPosition *resPos;	/* Actual second position used. */
  int *resHeight;		/* Height required. */
{
    XtTextSink sink = ((TextWidget)w)->text.sink;
    XtTextSource source = ((TextWidget)w)->text.source;

    AsciiSinkData *data;
    register    XtTextPosition index, lastPos;
    register char   c;
    XtTextBlock blk;

    data = (AsciiSinkData *) sink->data;
    /* we may not need this */
    lastPos = GETLASTPOS;
    (*source->Read)(source, fromPos, &blk, toPos - fromPos);
    *resWidth = 0;
    for (index = fromPos; index != toPos && index < lastPos; index++) {
	if (index - blk.firstPos >= blk.length)
	    (*source->Read)(source, index, &blk, toPos - fromPos);
	c = blk.ptr[index - blk.firstPos];
	if (c == LF) {
	    *resWidth += CharWidth(w, fromx + *resWidth, SP);
	    index++;
	    break;
	}
	*resWidth += CharWidth(w, fromx + *resWidth, c);
    }
    *resPos = index;
    *resHeight = data->font->ascent + data->font->descent;
}


static AsciiFindPosition(w, fromPos, fromx, width, stopAtWordBreak, 
			 resPos, resWidth, resHeight)
  Widget w;
  XtTextPosition fromPos; 	/* Starting position. */
  int fromx;			/* Horizontal location of starting position. */
  int width;			/* Desired width. */
  int stopAtWordBreak;		/* Whether the resulting position should be at
				   a word break. */
  XtTextPosition *resPos;	/* Resulting position. */
  int *resWidth;		/* Actual width used. */
  int *resHeight;		/* Height required. */
{
    XtTextSink sink = ((TextWidget)w)->text.sink;
    XtTextSource source = ((TextWidget)w)->text.source;
    AsciiSinkData *data;
    XtTextPosition lastPos, index, whiteSpacePosition;
    int     lastWidth, whiteSpaceWidth;
    Boolean whiteSpaceSeen;
    char    c;
    XtTextBlock blk;
    data = (AsciiSinkData *) sink->data;
    lastPos = GETLASTPOS;

    (*source->Read)(source, fromPos, &blk, bufferSize);
    *resWidth = 0;
    whiteSpaceSeen = FALSE;
    c = 0;
    for (index = fromPos; *resWidth <= width && index < lastPos; index++) {
	lastWidth = *resWidth;
	if (index - blk.firstPos >= blk.length)
	    (*source->Read)(source, index, &blk, bufferSize);
	c = blk.ptr[index - blk.firstPos];
	if (c == LF) {
	    *resWidth += CharWidth(w, fromx + *resWidth, SP);
	    index++;
	    break;
	}
	*resWidth += CharWidth(w, fromx + *resWidth, c);
	if ((c == SP || c == TAB) && *resWidth <= width) {
	    whiteSpaceSeen = TRUE;
	    whiteSpacePosition = index;
	    whiteSpaceWidth = *resWidth;
	}
    }
    if (*resWidth > width && index > fromPos) {
	*resWidth = lastWidth;
	index--;
	if (stopAtWordBreak && whiteSpaceSeen) {
	    index = whiteSpacePosition + 1;
	    *resWidth = whiteSpaceWidth;
	}
    }
    if (index == lastPos && c != LF) index = lastPos + 1;
    *resPos = index;
    *resHeight = data->font->ascent + data->font->descent;
}


static int AsciiResolveToPosition (w, pos, fromx, width,
				   leftPos, rightPos)
  Widget w;
  XtTextPosition pos;
  int fromx,width;
  XtTextPosition *leftPos, *rightPos;
{
    int     resWidth, resHeight;
    XtTextSource source = ((TextWidget)w)->text.source;

    AsciiFindPosition(w, pos, fromx, width, FALSE,
	    leftPos, &resWidth, &resHeight);
    if (*leftPos > GETLASTPOS)
	*leftPos = GETLASTPOS;
    *rightPos = *leftPos;
}


static int AsciiMaxLinesForHeight (w, height)
  Widget w;
  Dimension height;
{
    AsciiSinkData *data;
    XtTextSink sink = ((TextWidget)w)->text.sink;

    data = (AsciiSinkData *) sink->data;
    return(height / (data->font->ascent + data->font->descent));
}


static int AsciiMaxHeightForLines (w, lines)
  Widget w;
  int lines;
{
    AsciiSinkData *data;
    XtTextSink sink = ((TextWidget)w)->text.sink;

    data = (AsciiSinkData *) sink->data;
    return(lines * (data->font->ascent + data->font->descent));
}


static void AsciiSetTabs (w, offset, tab_count, tabs)
  Widget w;			/* for context */
  Position offset;		/* from left, for margin */
  int tab_count;		/* count of entries in tabs */
  Position *tabs;		/* list of character positions */
{
    AsciiSinkData *data = (AsciiSinkData*)((TextWidget)w)->text.sink->data;
    int i;

    if (tab_count > data->tab_count) {
	data->tabs = (Position*)XtRealloc(data->tabs,
				    (unsigned)tab_count * sizeof(Position*));
    }
    
    for (i=0; i < tab_count; i++) {
	data->tabs[i] = offset + tabs[i] * data->em;
    }
    data->tab_count = tab_count;
}

/***** Public routines *****/

XtTextSink XtAsciiSinkCreate (parent, args, num_args)
    Widget	parent;
    ArgList 	args;
    Cardinal 	num_args;
{
    XtTextSink sink;
    AsciiSinkData *data;
    unsigned long valuemask = (GCFont | GCGraphicsExposures |
			       GCForeground | GCBackground | GCFunction);
    XGCValues values;
    long wid;
    XFontStruct *font;

    if (!buf) buf = XtMalloc(bufferSize);

    sink = XtNew(XtTextSinkRec);
    sink->Display = AsciiDisplayText;
    sink->InsertCursor = AsciiInsertCursor;
    sink->ClearToBackground = AsciiClearToBackground;
    sink->FindPosition = AsciiFindPosition;
    sink->FindDistance = AsciiFindDistance;
    sink->Resolve = AsciiResolveToPosition;
    sink->MaxLines = AsciiMaxLinesForHeight;
    sink->MaxHeight = AsciiMaxHeightForLines;
    sink->SetTabs = AsciiSetTabs;
    data = XtNew(AsciiSinkData);
    sink->data = (caddr_t)data;

    XtGetSubresources (parent, (caddr_t)data, XtNtextSink, XtCTextSink, 
		       SinkResources, XtNumber(SinkResources),
		       args, num_args);

    font = data->font;
    values.function = GXcopy;
    values.font = font->fid;
    values.graphics_exposures = (Bool) FALSE;
    values.foreground = data->foreground;
    values.background = parent->core.background_pixel;
    data->normgc = XtGetGC(parent, valuemask, &values);
    values.foreground = parent->core.background_pixel;
    values.background = data->foreground;
    data->invgc = XtGetGC(parent, valuemask, &values);
    values.function = GXxor;
    values.foreground = data->foreground ^ parent->core.background_pixel;
    values.background = 0;
    data->xorgc = XtGetGC(parent, valuemask, &values);


    wid = -1;
    if ((!XGetFontProperty(font, XA_QUAD_WIDTH, &wid)) || wid <= 0) {
	if (font->per_char && font->min_char_or_byte2 <= '0' &&
	    		      font->max_char_or_byte2 >= '0')
	    wid = font->per_char['0' - font->min_char_or_byte2].width;
	else
	    wid = font->max_bounds.width;
    }
    if (wid <= 0)
	data->em = 1;
    else
	data->em = wid;

    data->font = font;
#ifdef SERVERNOTBROKEN
    data->insertCursorOn = CreateInsertCursor(XtScreen(parent));
#else
    /*
     * This is the work around for not being able to do CopyPlane with XOR.
     * However, there is another bug which doesn't let us use the new
     * CreatePixmapFromBitmapData routine to build the pixmap that we will
     * use CopyArea with.
     */
#ifdef SERVERNOTBROKEN2
    data->insertCursorOn =
      XCreatePixmapFromBitmapData (XtDisplay (parent), 
				   RootWindowOfScreen(XtScreen(parent)),
				   insertCursor_bits, insertCursor_width,
				   insertCursor_height, data->foreground,
				   parent->core.background_pixel,
				   parent->core.depth);
#else /* SERVER is BROKEN the second way */
    {
	Screen *screen = XtScreen (parent);
	Display *dpy = XtDisplay (parent);
	Window root = RootWindowOfScreen(screen);
	Pixmap bitmap = XCreateBitmapFromData (dpy, root, insertCursor_bits,
					       insertCursor_width,
					       insertCursor_height);
	Pixmap pixmap = XCreatePixmap (dpy, root, insertCursor_width,
				       insertCursor_height,
				       DefaultDepthOfScreen (screen));
	XGCValues gcv;
	GC gc;

	gcv.function = GXcopy;
	gcv.foreground = data->foreground ^ parent->core.background_pixel;
	gcv.background = 0;
	gcv.graphics_exposures = False;
	gc = XtGetGC (parent, (GCFunction | GCForeground | GCBackground |
			       GCGraphicsExposures), &gcv);
	XCopyPlane (dpy, bitmap, pixmap, gc, 0, 0, insertCursor_width,
		    insertCursor_height, 0, 0, 1);
	XtDestroyGC (gc);
	data->insertCursorOn = pixmap;
    }
#endif /* SERVERNOTBROKEN2 */
#endif /* SERVERNOTBROKEN */
    data->laststate = XtisOff;
    data->tab_count = 0;
    data->tabs = NULL;
    return sink;
}

void XtAsciiSinkDestroy (sink)
    XtTextSink sink;
{
    AsciiSinkData *data;

    data = (AsciiSinkData *) sink->data;
    XtFree((char *) data->tabs);
    XtFree((char *) data);
    XtFree((char *) sink);
}