Annotation of researchv9/X11/src/X.V11R1/lib/Xtk/AsciiSink.c, revision 1.1.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.