|
|
1.1 ! root 1: /* $Header: AsciiSink.c,v 1.2 87/08/06 14:35:30 toddb Exp $ */ ! 2: #ifndef lint ! 3: static char *sccsid = "@(#)AsciiSink.c 1.9 2/24/87"; ! 4: #endif lint ! 5: ! 6: /* ! 7: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. ! 8: * ! 9: * All Rights Reserved ! 10: * ! 11: * Permission to use, copy, modify, and distribute this software and its ! 12: * documentation for any purpose and without fee is hereby granted, ! 13: * provided that the above copyright notice appear in all copies and that ! 14: * both that copyright notice and this permission notice appear in ! 15: * supporting documentation, and that the name of Digital Equipment ! 16: * Corporation not be used in advertising or publicity pertaining to ! 17: * distribution of the software without specific, written prior permission. ! 18: * ! 19: * ! 20: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 21: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 22: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 23: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 24: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 25: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 26: * SOFTWARE. ! 27: */ ! 28: ! 29: #include "Xlib.h" ! 30: #include "Xatom.h" ! 31: #include "Intrinsic.h" ! 32: #include "Text.h" ! 33: #include "TextDisp.h" ! 34: ! 35: #define GETLASTPOS (*(source->scan))(source, 0, XtstFile, XtsdRight, 1, TRUE) ! 36: /* Private Ascii TextSink Definitions */ ! 37: ! 38: static unsigned bufferSize = 200; ! 39: ! 40: typedef struct _AsciiSinkData { ! 41: GC normgc, invgc, xorgc; ! 42: XFontStruct *font; ! 43: int tabwidth; ! 44: Pixmap insertCursorOn; ! 45: Pixmap insertCursorOff; ! 46: InsertState laststate; ! 47: } AsciiSinkData; ! 48: ! 49: static char *buf; ! 50: ! 51: /* Utilities */ ! 52: ! 53: static int CharWidth (data, x, c) ! 54: AsciiSinkData *data; ! 55: int x; ! 56: char c; ! 57: { ! 58: int width, nonPrinting; ! 59: XFontStruct *font = data->font; ! 60: ! 61: if (c == '\t') ! 62: /* This is totally bogus!! need to know tab settings etc.. */ ! 63: return data->tabwidth - (x % data->tabwidth); ! 64: if (c == LF) ! 65: c = SP; ! 66: nonPrinting = (c < SP); ! 67: if (nonPrinting) c += '@'; ! 68: ! 69: if (font->per_char && ! 70: (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2)) ! 71: width = font->per_char[c - font->min_char_or_byte2].width; ! 72: else ! 73: width = font->min_bounds.width; ! 74: ! 75: if (nonPrinting) ! 76: width += CharWidth(data, x, '^'); ! 77: ! 78: return width; ! 79: } ! 80: ! 81: /* Sink Object Functions */ ! 82: ! 83: #define LBEARING(x) \ ! 84: ((font->per_char != NULL && \ ! 85: ((x) >= font->min_char_or_byte2 && (x) <= font->max_char_or_byte2)) \ ! 86: ? font->per_char[(x) - font->min_char_or_byte2].lbearing \ ! 87: : font->min_bounds.lbearing) ! 88: ! 89: static int AsciiDisplayText (sink, source, w, x, y, pos1, pos2, highlight) ! 90: XtTextSink *sink; ! 91: XtTextSource *source; ! 92: Window w; ! 93: Position x, y; ! 94: int highlight; ! 95: XtTextPosition pos1, pos2; ! 96: { ! 97: AsciiSinkData *data = (AsciiSinkData *) sink->data ; ! 98: XFontStruct *font = data->font; ! 99: int j, k; ! 100: Dimension width; ! 101: XtTextBlock blk; ! 102: GC gc = highlight ? data->invgc : data->normgc; ! 103: GC invgc = highlight ? data->normgc : data->invgc; ! 104: ! 105: y += font->ascent; ! 106: j = 0; ! 107: while (pos1 < pos2) { ! 108: pos1 = (*(source->read))(source, pos1, &blk, pos2 - pos1); ! 109: for (k = 0; k < blk.length; k++) { ! 110: if (j >= bufferSize - 5) { ! 111: bufferSize *= 2; ! 112: buf = XtRealloc(buf, bufferSize); ! 113: } ! 114: buf[j] = blk.ptr[k]; ! 115: if (buf[j] == LF) ! 116: buf[j] = ' '; ! 117: else if (buf[j] == '\t') { ! 118: XDrawImageString(sink->dpy, w, gc, x - LBEARING(*buf), y, buf, j); ! 119: buf[j] = 0; ! 120: x += XTextWidth(data->font, buf, j); ! 121: width = CharWidth(data, x, '\t'); ! 122: XFillRectangle(sink->dpy, w, invgc, x, ! 123: y - font->ascent, width, ! 124: (Dimension) (data->font->ascent + ! 125: data->font->descent)); ! 126: x += width; ! 127: j = -1; ! 128: } ! 129: else ! 130: if (buf[j] < ' ') { ! 131: buf[j + 1] = buf[j] + '@'; ! 132: buf[j] = '^'; ! 133: j++; ! 134: } ! 135: j++; ! 136: } ! 137: } ! 138: XDrawImageString(sink->dpy, w, gc, x - LBEARING(*buf), y, buf, j); ! 139: } ! 140: ! 141: ! 142: static Pixmap CreateInsertCursor(dpy, d, gc, state) ! 143: Display *dpy; ! 144: Drawable d; ! 145: GC gc; ! 146: InsertState state; ! 147: { ! 148: XImage image; ! 149: Pixmap insertCursor; ! 150: ! 151: /* stuff for the text insertion cursor */ ! 152: ! 153: # define insertCursor_width 6 ! 154: # define insertCursor_height 3 ! 155: ! 156: static short insertCursor_bits[] = {0x000c, 0x001e, 0x0033}; ! 157: /* static short insertCursor_bits[] = {0xfff3, 0xffe1, 0xffcc}; */ ! 158: static short blank_bits[] = {0x0000, 0x0000, 0x0000}; ! 159: ! 160: image.height = insertCursor_height; ! 161: image.width = insertCursor_width; ! 162: image.xoffset = 0; ! 163: image.format = XYBitmap; ! 164: image.data = (char *) ((state == XtisOn) ? insertCursor_bits : blank_bits); ! 165: /* image.data = (char *) insertCursor_bits;*/ ! 166: image.byte_order = LSBFirst; ! 167: image.bitmap_unit = 16; ! 168: image.bitmap_bit_order = LSBFirst; ! 169: image.bitmap_pad = 16; ! 170: image.depth = 1; ! 171: image.bytes_per_line = ((insertCursor_width+15) / 16) * 2; ! 172: image.bits_per_pixel = 1; ! 173: image.obdata = NULL; ! 174: insertCursor = XCreatePixmap(dpy, d, (Dimension) image.width, ! 175: (Dimension) image.height, ! 176: DefaultDepth(dpy, DefaultScreen(dpy))); ! 177: /* !!! BOGUS -- should otherwise figure out the depth; this code may not ! 178: work on multiple screen displays. ||| */ ! 179: XPutImage(dpy, insertCursor, gc, &image, 0, 0, 0, 0, ! 180: (Dimension)image.width, (Dimension)image.height); ! 181: return insertCursor; ! 182: } ! 183: ! 184: /* ! 185: * The following procedure manages the "insert" cursor. ! 186: */ ! 187: ! 188: static AsciiInsertCursor (sink, w, x, y, state) ! 189: XtTextSink *sink; ! 190: Window w; ! 191: Position x, y; ! 192: InsertState state; ! 193: { ! 194: AsciiSinkData *data = (AsciiSinkData *) sink->data; ! 195: ! 196: /* ! 197: XCopyArea(sink->dpy, ! 198: (state == XtisOn) ? data->insertCursorOn : data->insertCursorOff, w, ! 199: data->normgc, 0, 0, insertCursor_width, insertCursor_height, ! 200: x - (insertCursor_width >> 1), y - (insertCursor_height)); ! 201: */ ! 202: if (state != data->laststate) ! 203: XCopyArea(sink->dpy, ! 204: data->insertCursorOn, w, ! 205: data->xorgc, 0, 0, insertCursor_width, insertCursor_height, ! 206: x - (insertCursor_width >> 1), y - (insertCursor_height)); ! 207: data->laststate = state; ! 208: } ! 209: ! 210: /* ! 211: * Clear the passed region to the background color. ! 212: */ ! 213: ! 214: static AsciiClearToBackground (sink, w, x, y, width, height) ! 215: XtTextSink *sink; ! 216: Window w; ! 217: Position x, y; ! 218: Dimension width, height; ! 219: { ! 220: AsciiSinkData *data = (AsciiSinkData *) sink->data; ! 221: XFillRectangle(sink->dpy, w, data->invgc, x, y, width, height); ! 222: } ! 223: ! 224: /* ! 225: * Given two positions, find the distance between them. ! 226: */ ! 227: ! 228: static AsciiFindDistance (sink, source, fromPos, fromx, toPos, ! 229: resWidth, resPos, resHeight) ! 230: XtTextSink *sink; ! 231: XtTextSource *source; ! 232: XtTextPosition fromPos; /* First position. */ ! 233: int fromx; /* Horizontal location of first position. */ ! 234: XtTextPosition toPos; /* Second position. */ ! 235: int *resWidth; /* Distance between fromPos and resPos. */ ! 236: int *resPos; /* Actual second position used. */ ! 237: int *resHeight; /* Height required. */ ! 238: { ! 239: AsciiSinkData *data; ! 240: register XtTextPosition index, lastPos; ! 241: register char c; ! 242: XtTextBlock blk; ! 243: ! 244: data = (AsciiSinkData *) sink->data; ! 245: /* we may not need this */ ! 246: lastPos = GETLASTPOS; ! 247: (*(source->read))(source, fromPos, &blk, toPos - fromPos); ! 248: *resWidth = 0; ! 249: for (index = fromPos; index != toPos && index < lastPos; index++) { ! 250: if (index - blk.firstPos >= blk.length) ! 251: (*(source->read))(source, index, &blk, toPos - fromPos); ! 252: c = blk.ptr[index - blk.firstPos]; ! 253: if (c == LF) { ! 254: *resWidth += CharWidth(data, fromx + *resWidth, SP); ! 255: index++; ! 256: break; ! 257: } ! 258: *resWidth += CharWidth(data, fromx + *resWidth, c); ! 259: } ! 260: *resPos = index; ! 261: *resHeight = data->font->ascent + data->font->descent; ! 262: } ! 263: ! 264: ! 265: static AsciiFindPosition(sink, source, fromPos, fromx, width, stopAtWordBreak, ! 266: resPos, resWidth, resHeight) ! 267: XtTextSink *sink; ! 268: XtTextSource *source; ! 269: XtTextPosition fromPos; /* Starting position. */ ! 270: int fromx; /* Horizontal location of starting position. */ ! 271: int width; /* Desired width. */ ! 272: int stopAtWordBreak; /* Whether the resulting position should be at ! 273: a word break. */ ! 274: XtTextPosition *resPos; /* Resulting position. */ ! 275: int *resWidth; /* Actual width used. */ ! 276: int *resHeight; /* Height required. */ ! 277: { ! 278: AsciiSinkData *data; ! 279: XtTextPosition lastPos, index, whiteSpacePosition; ! 280: int lastWidth, whiteSpaceWidth; ! 281: Boolean whiteSpaceSeen; ! 282: char c; ! 283: XtTextBlock blk; ! 284: data = (AsciiSinkData *) sink->data; ! 285: lastPos = GETLASTPOS; ! 286: (*(source->read))(source, fromPos, &blk, bufferSize); ! 287: *resWidth = 0; ! 288: whiteSpaceSeen = FALSE; ! 289: c = 0; ! 290: for (index = fromPos; *resWidth <= width && index < lastPos; index++) { ! 291: lastWidth = *resWidth; ! 292: if (index - blk.firstPos >= blk.length) ! 293: (*(source->read))(source, index, &blk, bufferSize); ! 294: c = blk.ptr[index - blk.firstPos]; ! 295: if (c == LF) { ! 296: *resWidth += CharWidth(data, fromx + *resWidth, SP); ! 297: index++; ! 298: break; ! 299: } ! 300: *resWidth += CharWidth(data, fromx + *resWidth, c); ! 301: if ((c == SP || c == TAB) && *resWidth <= width) { ! 302: whiteSpaceSeen = TRUE; ! 303: whiteSpacePosition = index; ! 304: whiteSpaceWidth = *resWidth; ! 305: } ! 306: } ! 307: if (*resWidth > width && index > fromPos) { ! 308: *resWidth = lastWidth; ! 309: index--; ! 310: if (stopAtWordBreak && whiteSpaceSeen) { ! 311: index = whiteSpacePosition + 1; ! 312: *resWidth = whiteSpaceWidth; ! 313: } ! 314: } ! 315: if (index == lastPos && c != LF) index = lastPos + 1; ! 316: *resPos = index; ! 317: *resHeight = data->font->ascent + data->font->descent; ! 318: } ! 319: ! 320: ! 321: static int AsciiResolveToPosition (sink, source, pos, fromx, width, ! 322: leftPos, rightPos) ! 323: XtTextSink *sink; ! 324: XtTextSource *source; ! 325: XtTextPosition pos; ! 326: int fromx,width; ! 327: XtTextPosition *leftPos, *rightPos; ! 328: { ! 329: int resWidth, resHeight; ! 330: ! 331: AsciiFindPosition(sink, source, pos, fromx, width, FALSE, ! 332: leftPos, &resWidth, &resHeight); ! 333: if (*leftPos > GETLASTPOS) ! 334: *leftPos = GETLASTPOS; ! 335: *rightPos = *leftPos; ! 336: } ! 337: ! 338: ! 339: static int AsciiMaxLinesForHeight (sink, height) ! 340: XtTextSink *sink; ! 341: int height; ! 342: { ! 343: AsciiSinkData *data; ! 344: ! 345: data = (AsciiSinkData *) sink->data; ! 346: return(height / (data->font->ascent + data->font->descent)); ! 347: } ! 348: ! 349: ! 350: static int AsciiMaxHeightForLines (sink, lines) ! 351: XtTextSink *sink; ! 352: int lines; ! 353: { ! 354: AsciiSinkData *data; ! 355: ! 356: data = (AsciiSinkData *) sink->data; ! 357: return(lines * (data->font->ascent + data->font->descent)); ! 358: } ! 359: ! 360: ! 361: /* Public routines */ ! 362: ! 363: static Boolean initialized = FALSE; ! 364: static XContext asciiSinkContext; ! 365: ! 366: AsciiSinkInitialize() ! 367: { ! 368: if (initialized) ! 369: return; ! 370: initialized = TRUE; ! 371: ! 372: asciiSinkContext = XUniqueContext(); ! 373: ! 374: buf = (char *) XtMalloc(bufferSize); ! 375: } ! 376: ! 377: ! 378: caddr_t XtAsciiSinkCreate (dpy, font, ink, background) ! 379: Display *dpy; ! 380: XFontStruct *font; ! 381: int ink, background; ! 382: { ! 383: Window window; ! 384: XtTextSink *sink; ! 385: AsciiSinkData *data; ! 386: unsigned long valuemask = (GCFont | GCGraphicsExposures | ! 387: GCForeground | GCBackground | GCFunction); ! 388: XGCValues values; ! 389: unsigned long w; ! 390: ! 391: if (!initialized) ! 392: AsciiSinkInitialize(); ! 393: ! 394: window = RootWindow(dpy, DefaultScreen(dpy)); ! 395: sink = (XtTextSink *) XtMalloc(sizeof(XtTextSink)); ! 396: sink->dpy = dpy; ! 397: sink->display = AsciiDisplayText; ! 398: sink->insertCursor = AsciiInsertCursor; ! 399: sink->clearToBackground = AsciiClearToBackground; ! 400: sink->findPosition = AsciiFindPosition; ! 401: sink->findDistance = AsciiFindDistance; ! 402: sink->resolve = AsciiResolveToPosition; ! 403: sink->maxLines = AsciiMaxLinesForHeight; ! 404: sink->maxHeight = AsciiMaxHeightForLines; ! 405: sink->data = (int *) XtMalloc(sizeof(AsciiSinkData)); ! 406: data = (AsciiSinkData *) sink->data; ! 407: values.function = GXcopy; ! 408: values.font = font->fid; ! 409: values.graphics_exposures = (Bool) FALSE; ! 410: values.foreground = ink; ! 411: values.background = background; ! 412: data->normgc = XtGetGC( ! 413: dpy, (XContext)asciiSinkContext, window, valuemask, &values); ! 414: values.foreground = background; ! 415: values.background = ink; ! 416: data->invgc = XtGetGC( ! 417: dpy, (XContext)asciiSinkContext, window, valuemask, &values); ! 418: values.function = GXxor; ! 419: values.foreground = ink ^ background; ! 420: values.background = 0; ! 421: data->xorgc = XtGetGC( ! 422: dpy, (XContext)asciiSinkContext, window, valuemask, &values); ! 423: ! 424: w = -1; ! 425: if ((!XGetFontProperty(font, XA_QUAD_WIDTH, &w)) || w <= 0) { ! 426: if (font->per_char && font->min_char_or_byte2 <= '0' && ! 427: font->max_char_or_byte2 >= '0') ! 428: w = font->per_char['0' - font->min_char_or_byte2].width; ! 429: else ! 430: w = font->max_bounds.width; ! 431: } ! 432: if (w <= 0) w = 1; ! 433: data->tabwidth = 8 * w; ! 434: data->font = font; ! 435: /* data->insertCursorOn = CreateInsertCursor(dpy, window, data->normgc, XtisOn);*/ ! 436: /* data->insertCursorOff = CreateInsertCursor(dpy, window, data->normgc, XtisOff);*/ ! 437: data->insertCursorOn = CreateInsertCursor(dpy, window, data->xorgc, XtisOn); ! 438: data->laststate = XtisOff; ! 439: return(caddr_t) sink; ! 440: } ! 441: ! 442: void XtAsciiSinkDestroy (sink) ! 443: XtTextSink *sink; ! 444: { ! 445: AsciiSinkData *data; ! 446: ! 447: data = (AsciiSinkData *) sink->data; ! 448: XtFree((char *) data); ! 449: XtFree((char *) sink); ! 450: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.