|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: A T
Length: 10081 (0x2761)
Types: TextFile
Names: »AsciiSink.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦526ad3590⟧ »EUUGD11/gnu-31mar87/X.V10.R4.tar.Z«
└─⟦2109abc41⟧
└─⟦this⟧ »./X.V10R4/Toolkit/DECToolkit/src/AsciiSink.c«
/*
* $Source: /u1/X/DECToolkit/src/RCS/AsciiSink.c,v $
* $Header: AsciiSink.c,v 1.1 86/12/17 09:00:16 swick Exp $
*/
#ifndef lint
static char *rcsid_AsciiSink_c = "$Header: AsciiSink.c,v 1.1 86/12/17 09:00:16 swick Exp $";
#endif lint
#ifndef lint
static char *sccsid = "@(#)AsciiSink.c 1.6 12/11/86";
#endif lint
/*
* COPYRIGHT 1986
* DIGITAL EQUIPMENT CORPORATION
* MAYNARD, MASSACHUSETTS
* ALL RIGHTS RESERVED.
*
* THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
* SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
* DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR
* ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
*
* IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS,
* APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT
* SET FORTH ABOVE.
*
*
* 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.
*/
/* File: AsciiSink.c */
#include <X/Xlib.h>
#include "Toolkit.h"
#include "TextDisplay.h"
/* Private Ascii TextSink Definitions */
static int bufferSize = 200;
typedef struct _AsciiSinkData {
FontInfo *font;
} AsciiSinkData;
static char *buf;
static initialized = 0;
/* Utilities */
/***
*** given a character this function determines its width in pixels
***/
static int CharWidth (data, x, c)
AsciiSinkData *data; /*** need the font info from this ***/
int x; /*** starting spot of character -needed for tabs ***/
char c; /*** character ***/
{
int width, nonPrinting;
FontInfo *info = data->font;
if (c == '\t')
return (info->width * 8) - ((x - xMargin) % (info->width * 8));
if (c == LF)
c = SP;
if (c < SP || c > info->lastchar)
nonPrinting = TRUE;
else
nonPrinting = FALSE;
if (info->fixedwidth != 0) {
if (nonPrinting)
width = 2 * info->width;
else
width = info->width;
}
else {
if (nonPrinting)
width = info->widths['^' - info->firstchar] +
info->widths[c + '@' - info->firstchar];
else
width = info->widths[c - info->firstchar];
}
return width;
}
/* Sink Object Functions */
/***
*** given the source and the positions within the source to be displayed,
*** this routine puts the text onto the screen. What should go on
*** each line has already been determined by the source routines.
***/
static int AsciiDisplayText (sink, source, w, x, y, pos1, pos2, highlight)
TTextSink *sink; /* pointer to sink for window */
TTextSource *source; /* pointer to source for window */
Window w;
int x, y; /* starting x and y pixel coordinates */
TTextPosition pos1, pos2; /* starting and ending byte offsets */
int highlight; /* true if reverse video desired */
{
AsciiSinkData * data;
int ink, background;
int j, k, width;
TTextPosition nextPos;
TTextBlock blk;
data = (AsciiSinkData *) sink->data;
j = 0;
while (pos1 < pos2) {
pos1 = (*(source->read))
(source, pos1, &blk, pos2 - pos1); /* get the text*/
ink = (highlight) ? WhitePixel : BlackPixel; /* foreground */
background = (highlight) ? BlackPixel : WhitePixel; /* background */
/** for each character in the text to be displayed **/
for (k = 0; k < blk.length; k++) {
if (j >= bufferSize - 5)
buf = (char *) Trealloc(buf, bufferSize *= 2);
buf[j] = blk.ptr[k];
if (buf[j] == LF)
buf[j] = ' ';
else if (buf[j] == '\t') {
/** if it's a tab then display what you have so far, **
** color in the tab, and move x over to after the tab. **/
XText(w, x, y, buf, j, data->font->id, ink, background);
buf[j] = 0;
x += XStringWidth(buf, data->font, 0, 0);
width = CharWidth(data, x, '\t');
XPixSet(w, x, y, width, data->font->height, background);
x += width;
j = -1;
}
else
if (buf[j] < ' ') {
buf[j + 1] = buf[j] + '@';
buf[j] = '^';
j = j + 1;
}
j = j + 1;
}
}
XText(w, x, y, buf, j, data->font->id, ink, background);
}
/***
*** Given two byte positions, find the distance in pixels between them.
***/
static AsciiFindDistance (sink, source, fromPos, fromx, toPos,
resWidth, resPos, resHeight)
TTextSink *sink;
TTextSource *source;
TTextPosition fromPos; /* First position. */
int fromx; /* Horizontal location of first position. */
TTextPosition toPos; /* Second position. */
int *resWidth; /* Distance between fromPos and resPos. */
int *resPos; /* Actual second position used. */
int *resHeight; /* Height required. */
{
AsciiSinkData *data;
register TTextPosition index, lastPos;
register char c;
TTextBlock blk;
data = (AsciiSinkData *) sink->data;
lastPos = (*(source->getLastPos)) (source);
(*(source->read)) (source, fromPos, &blk, toPos - fromPos);
*resWidth = 0;
/*** for each byte between the 2 positions ***/
for (index = fromPos; index != toPos && index < lastPos; index++) {
/** get the character **/
if (index - fromPos >= blk.length)
(*(source->read)) (source, index, &blk, toPos - fromPos);
c = blk.ptr[index-fromPos];
/** compute the width in pixels **/
if (c == LF) {
*resWidth += CharWidth(data, fromx + *resWidth, SP);
index++;
break;
}
*resWidth += CharWidth(data, fromx + *resWidth, c);
}
if (index == lastPos && c != LF) index = lastPos + 1;
*resPos = index;
*resHeight = data->font->height;
}
/***
*** given a starting positions and the x coordinate of the starting
*** position, this function will return the position of the last byte to
*** be on that line. If stopatWordBreak is false, it waits for a \n.
***/
static AsciiFindPosition(sink, source, fromPos, fromx, width, stopAtWordBreak,
resPos, resWidth, resHeight)
TTextSink *sink;
TTextSource *source;
TTextPosition 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. */
TTextPosition *resPos; /* RETURNED: end position for line. */
int *resWidth; /* RETURNED: Actual width in pixels used. */
int *resHeight; /* RETURNED: Height required. */
{
AsciiSinkData *data;
TTextPosition lastPos, index, whiteSpacePosition;
int lastWidth, whiteSpaceSeen, whiteSpaceWidth;
char c;
TTextBlock blk;
data = (AsciiSinkData *) sink->data;
lastPos = (*(source->getLastPos)) (source);
(*(source->read)) (source, fromPos, &blk, bufferSize);
*resWidth = 0;
whiteSpaceSeen = FALSE;
/** for each character that will fit on the line **/
for (index = fromPos; *resWidth <= width && index < lastPos; index++) {
lastWidth = *resWidth;
/** get the character **/
if (index - fromPos >= blk.length)
(*(source->read)) (source, index, &blk, bufferSize);
c = blk.ptr[index - fromPos];
/** find the width of the character **/
if (c == LF) {
*resWidth += CharWidth(data, fromx + *resWidth, SP);
index++;
break;
}
*resWidth += CharWidth(data, fromx + *resWidth, c);
/** check for white space **/
if ((c == SP || c == TAB) && *resWidth <= width) {
whiteSpaceSeen = TRUE;
whiteSpacePosition = index;
whiteSpaceWidth = *resWidth;
}
}
/*** if width too big to fit on line, backup to last position ***/
if (*resWidth > width && index > fromPos) {
*resWidth = lastWidth;
index--;
if (stopAtWordBreak && whiteSpaceSeen) {
index = whiteSpacePosition + 1;
*resWidth = whiteSpaceWidth;
}
}
*resPos = index;
*resHeight = data->font->height;
}
static int AsciiResolveToPosition (sink, source, pos, fromx, width,
leftPos, rightPos)
TTextSink *sink;
TTextSource *source;
TTextPosition pos;
int fromx,width;
TTextPosition *leftPos, *rightPos;
{
int resWidth, resHeight;
AsciiFindPosition(sink, source, pos, fromx, width, FALSE,
leftPos, &resWidth, &resHeight);
if (*leftPos > source->getLastPos(source))
*leftPos = source->getLastPos(source);
*rightPos = *leftPos;
}
/***
*** given font info and window height, this routine routines the max
*** number of lines that will fit in the window.
***/
static int AsciiMaxLinesForHeight (sink, height)
TTextSink *sink;
int height;
{
AsciiSinkData *data;
data = (AsciiSinkData *) sink->data;
return(height / data->font->height);
}
/***
*** Given the font info and the number of lines, this routine returns
*** the number of pixels needed for the height.
***/
static int AsciiMaxHeightForLines (sink, lines)
TTextSink *sink;
int lines;
{
AsciiSinkData *data;
data = (AsciiSinkData *) sink->data;
return(lines*data->font->height);
}
/* Public routines */
int *TCreateAsciiSink (font)
FontInfo *font;
{
TTextSink *sink;
AsciiSinkData *data;
if (initialized == 0) {
buf = (char *) Tmalloc(bufferSize);
initialized = 1;
}
sink = (TTextSink *) Tmalloc(sizeof(TTextSink));
sink->display = AsciiDisplayText;
sink->findPosition = AsciiFindPosition;
sink->findDistance = AsciiFindDistance;
sink->resolve = AsciiResolveToPosition;
sink->maxLines = AsciiMaxLinesForHeight;
sink->maxHeight = AsciiMaxHeightForLines;
sink->data = (int *) Tmalloc(sizeof(AsciiSinkData));
data = (AsciiSinkData *) sink->data;
data->font = font;
return(int *) sink;
}
void TDestroyAsciiSink (sink)
TTextSink *sink;
{
AsciiSinkData *data;
data = (AsciiSinkData *) sink->data;
free(data);
free(sink);
}