|
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); }