File:  [Research Unix] / researchv9 / X11 / src / X.V11R1 / lib / oldXtk / AsciiSink.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:22:00 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

/* $Header: /var/lib/cvsd/repos/research/researchv9/X11/src/X.V11R1/lib/oldXtk/AsciiSink.c,v 1.1.1.1 2018/04/24 17:22:00 root Exp $ */
#ifndef lint
static char *sccsid = "@(#)AsciiSink.c	1.9	2/24/87";
#endif lint

/*
 * Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital Equipment
 * Corporation 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 "Xlib.h"
#include "Xatom.h"
#include "Intrinsic.h"
#include "Text.h"
#include "TextDisp.h"

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

static unsigned bufferSize = 200;

typedef struct _AsciiSinkData {
    GC normgc, invgc, xorgc;
    XFontStruct *font;
    int tabwidth;
    Pixmap insertCursorOn;
    Pixmap insertCursorOff;
    InsertState laststate;
} AsciiSinkData;

static char *buf;

/* Utilities */

static int CharWidth (data, x, c)
  AsciiSinkData *data;
  int x;
  char c;
{
    int     width, nonPrinting;
    XFontStruct *font = data->font;

    if (c == '\t')
        /* This is totally bogus!! need to know tab settings etc.. */
	return data->tabwidth - (x % data->tabwidth);
    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(data, x, '^');

    return width;
}

/* Sink Object Functions */

#define LBEARING(x) \
    ((font->per_char != NULL && \
      ((x) >= font->min_char_or_byte2 && (x) <= font->max_char_or_byte2)) \
	? font->per_char[(x) - font->min_char_or_byte2].lbearing \
	: font->min_bounds.lbearing)

static int AsciiDisplayText (sink, source, w, x, y, pos1, pos2, highlight)
  XtTextSink *sink;
  XtTextSource *source;
  Window w;
  Position x, y;
  int highlight;
  XtTextPosition pos1, pos2;
{
    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(sink->dpy, w, gc, x - LBEARING(*buf), y, buf, j);
		buf[j] = 0;
		x += XTextWidth(data->font, buf, j);
		width = CharWidth(data, x, '\t');
		XFillRectangle(sink->dpy, 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(sink->dpy, w, gc, x - LBEARING(*buf), y, buf, j);
}


static Pixmap CreateInsertCursor(dpy, d, gc, state)
Display *dpy;
Drawable d;
GC gc;
InsertState state;
{
    XImage image;
    Pixmap insertCursor;

    /* stuff for the text insertion cursor */

#   define insertCursor_width 6
#   define insertCursor_height 3

    static short insertCursor_bits[] = {0x000c, 0x001e, 0x0033};
/*    static short insertCursor_bits[] = {0xfff3, 0xffe1, 0xffcc}; */
    static short blank_bits[] = {0x0000, 0x0000, 0x0000};

    image.height = insertCursor_height;
    image.width = insertCursor_width;
    image.xoffset = 0;
    image.format = XYBitmap;
    image.data = (char *) ((state == XtisOn) ? insertCursor_bits : blank_bits);
/*    image.data = (char *) insertCursor_bits;*/
    image.byte_order = LSBFirst;
    image.bitmap_unit = 16;
    image.bitmap_bit_order = LSBFirst;
    image.bitmap_pad = 16;
    image.depth = 1;
    image.bytes_per_line = ((insertCursor_width+15) / 16) * 2;
    image.bits_per_pixel = 1;
    image.obdata = NULL;
    insertCursor = XCreatePixmap(dpy, d, (Dimension) image.width,
				 (Dimension) image.height,
				 DefaultDepth(dpy, DefaultScreen(dpy)));
    /* !!! BOGUS -- should otherwise figure out the depth; this code may not
       work on multiple screen displays. ||| */
    XPutImage(dpy, insertCursor, gc, &image, 0, 0, 0, 0,
	      (Dimension)image.width, (Dimension)image.height);
    return insertCursor;
}

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

static AsciiInsertCursor (sink, w, x, y, state)
  XtTextSink *sink;
  Window w;
  Position x, y;
  InsertState state;
{
    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)
	XCopyArea(sink->dpy,
		  data->insertCursorOn, w,
		  data->xorgc, 0, 0, insertCursor_width, insertCursor_height,
		  x - (insertCursor_width >> 1), y - (insertCursor_height));
    data->laststate = state;
}

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

static AsciiClearToBackground (sink, w, x, y, width, height)
  XtTextSink *sink;
  Window w;
  Position x, y;
  Dimension width, height;
{
    AsciiSinkData *data = (AsciiSinkData *) sink->data;
    XFillRectangle(sink->dpy, w, data->invgc, x, y, width, height);
}

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

static AsciiFindDistance (sink, source, fromPos, fromx, toPos,
			  resWidth, resPos, resHeight)
  XtTextSink *sink;
  XtTextSource *source;
  XtTextPosition fromPos;	/* First position. */
  int fromx;			/* Horizontal location of first position. */
  XtTextPosition toPos;		/* Second position. */
  int *resWidth;		/* Distance between fromPos and resPos. */
  int *resPos;			/* Actual second position used. */
  int *resHeight;		/* Height required. */
{
    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(data, fromx + *resWidth, SP);
	    index++;
	    break;
	}
	*resWidth += CharWidth(data, fromx + *resWidth, c);
    }
    *resPos = index;
    *resHeight = data->font->ascent + data->font->descent;
}


static AsciiFindPosition(sink, source, fromPos, fromx, width, stopAtWordBreak, 
			 resPos, resWidth, resHeight)
  XtTextSink *sink;	
  XtTextSource *source;
  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. */
{
    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(data, fromx + *resWidth, SP);
	    index++;
	    break;
	}
	*resWidth += CharWidth(data, 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 (sink, source, pos, fromx, width,
				   leftPos, rightPos)
  XtTextSink *sink;
  XtTextSource *source;
  XtTextPosition pos;
  int fromx,width;
  XtTextPosition *leftPos, *rightPos;
{
    int     resWidth, resHeight;

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


static int AsciiMaxLinesForHeight (sink, height)
  XtTextSink *sink;
  int height;
{
    AsciiSinkData *data;

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


static int AsciiMaxHeightForLines (sink, lines)
  XtTextSink *sink;
  int lines;
{
    AsciiSinkData *data;

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


/* Public routines */

static Boolean initialized = FALSE;
static XContext asciiSinkContext;

AsciiSinkInitialize()
{
    if (initialized)
    	return;
    initialized = TRUE;

    asciiSinkContext = XUniqueContext();

    buf = (char *) XtMalloc(bufferSize);
}


caddr_t XtAsciiSinkCreate (dpy, font, ink, background)
    Display *dpy;
    XFontStruct *font;
    int 	ink, background;
{
    Window window;
    XtTextSink *sink;
    AsciiSinkData *data;
    unsigned long valuemask = (GCFont | GCGraphicsExposures |
			       GCForeground | GCBackground | GCFunction);
    XGCValues values;
    unsigned long w;

    if (!initialized)
    	AsciiSinkInitialize();

    window = RootWindow(dpy, DefaultScreen(dpy));
    sink = (XtTextSink *) XtMalloc(sizeof(XtTextSink));
    sink->dpy = dpy;
    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->data = (int *) XtMalloc(sizeof(AsciiSinkData));
    data = (AsciiSinkData *) sink->data;
    values.function = GXcopy;
    values.font = font->fid;
    values.graphics_exposures = (Bool) FALSE;
    values.foreground = ink;
    values.background = background;
    data->normgc = XtGetGC(
	dpy, (XContext)asciiSinkContext, window, valuemask, &values);
    values.foreground = background;
    values.background = ink;
    data->invgc = XtGetGC(
	dpy, (XContext)asciiSinkContext, window, valuemask, &values);
    values.function = GXxor;
    values.foreground = ink ^ background;
    values.background = 0;
    data->xorgc = XtGetGC(
	dpy, (XContext)asciiSinkContext, window, valuemask, &values);

    w = -1;
    if ((!XGetFontProperty(font, XA_QUAD_WIDTH, &w)) || w <= 0) {
	if (font->per_char && font->min_char_or_byte2 <= '0' &&
	    		      font->max_char_or_byte2 >= '0')
	    w = font->per_char['0' - font->min_char_or_byte2].width;
	else
	    w = font->max_bounds.width;
    }
    if (w <= 0) w = 1;
    data->tabwidth = 8 * w;
    data->font = font;
/*    data->insertCursorOn = CreateInsertCursor(dpy, window, data->normgc, XtisOn);*/
/*    data->insertCursorOff = CreateInsertCursor(dpy, window, data->normgc, XtisOff);*/
    data->insertCursorOn = CreateInsertCursor(dpy, window, data->xorgc, XtisOn);
    data->laststate = XtisOff;
    return(caddr_t) sink;
}

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

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.