Annotation of researchv9/X11/src/X.V11R1/lib/Xtk/AsciiSink.c, revision 1.1

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

unix.superglobalmegacorp.com

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