Annotation of researchv9/X11/src/X.V11R1/lib/oldXtk/Text.c, revision 1.1

1.1     ! root        1: /* $Header: Text.c,v 1.1 87/09/11 07:58:30 toddb Exp $ */
        !             2: #ifndef lint
        !             3: static char *sccsid = "@(#)Text.c      1.27    2/25/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: 
        !            30: /* File: Text.c */
        !            31: 
        !            32: #include "Xlib.h"
        !            33: #include "Intrinsic.h"
        !            34: #include "Text.h"
        !            35: #include "Scroll.h"
        !            36: #include "Atoms.h"
        !            37: #include "TextDisp.h"          /** all text subwindow programs include **/
        !            38: #include <strings.h>
        !            39: 
        !            40: /* ||| Kludge, should be in header file somewhere */
        !            41: extern caddr_t XtSetTextEventBindings();
        !            42: 
        !            43: extern void bcopy();
        !            44: 
        !            45: #define BufMax 1000
        !            46: #define abs(x) (((x) < 0) ? (-(x)) : (x))
        !            47: #define min(x,y)       ((x) < (y) ? (x) : (y))
        !            48: #define max(x,y)       ((x) > (y) ? (x) : (y))
        !            49: #define GETLASTPOS  (*(ctx->source->scan)) (ctx->source, 0, XtstFile, XtsdRight, 1, TRUE)
        !            50: #define BUTTONMASK 0x143d
        !            51: 
        !            52: #define  yMargin 2
        !            53: #define zeroPosition ((XtTextPosition) 0)
        !            54: 
        !            55: 
        !            56: static XContext textContext;
        !            57: 
        !            58: static TextContext glob, globinit;
        !            59: 
        !            60: static Resource resources[] = {
        !            61:     {XtNwindow, XtCWindow, XrmRWindow, sizeof (Window),
        !            62:         (caddr_t) &glob.w, NULL},
        !            63:     {XtNwidth, XtCWidth, XrmRInt, sizeof (int),
        !            64:          (caddr_t) &glob.width, NULL},
        !            65:     {XtNheight, XtCHeight, XrmRInt, sizeof (int),
        !            66:          (caddr_t) &glob.height, NULL},
        !            67:     {XtNbackground, XtCColor, XrmRPixel, sizeof (int),
        !            68:         (caddr_t) &glob.background, (caddr_t) &XtDefaultBGPixel},
        !            69:     {XtNborder, XtCColor, XrmRPixmap, sizeof (int),
        !            70:         (caddr_t) &glob.border, (caddr_t) &XtDefaultFGPixel},
        !            71:     {XtNborderWidth, XtCBorderWidth, XrmRInt, sizeof (int), 
        !            72:         (caddr_t) &glob.borderWidth, NULL},
        !            73:     {XtNdisplayPosition, XtCTextPosition, XrmRInt,
        !            74:         sizeof (XtTextPosition), (caddr_t) &glob.lt.top, NULL},
        !            75:     {XtNselection, XtCSelection, XrmRPointer, sizeof(caddr_t),
        !            76:         (caddr_t) &glob.s, NULL},
        !            77:     {XtNselectionArray, XtCSelectionArray, XrmRPointer, 
        !            78:         sizeof(SelectionArray), (caddr_t) glob.sarray, NULL},
        !            79:     {XtNtextOptions, XtCTextOptions, XrmRInt, sizeof (int),
        !            80:         (caddr_t) &glob.options, NULL},
        !            81:     {XtNleftMargin, XtCMargin, XrmRInt, sizeof (int), 
        !            82:         (caddr_t) &glob.leftmargin, NULL},
        !            83: /* |||   {XtNrightMargin, XtCMargin, XtRint, sizeof (int),
        !            84:          (caddr_t) &rightMargin, NULL}, */
        !            85:     {XtNinsertPosition, XtCTextPosition, XtRTextPosition, 
        !            86:         sizeof(XtTextPosition), (caddr_t) &glob.insertPos, NULL},
        !            87:     {XtNtextSink, XtCTextSink, XrmRPointer, sizeof (caddr_t),
        !            88:          (caddr_t) &glob.sink, NULL},
        !            89:     {XtNtextSource, XtCTextSource, XrmRPointer, sizeof (caddr_t), 
        !            90:          (caddr_t) &glob.source, NULL},
        !            91:     {XtNeventBindings, XtCEventBindings, XtREventBindings,
        !            92:          sizeof (caddr_t), (caddr_t) &glob.eventTable, NULL},
        !            93: };
        !            94: 
        !            95: static Boolean initialized = FALSE;
        !            96: 
        !            97: static void TextInitialize()
        !            98: {
        !            99:     if (initialized)
        !           100:        return;
        !           101:     initialized = TRUE;
        !           102: 
        !           103:     textContext = XUniqueContext();
        !           104:     globinit.source = NULL;
        !           105:     globinit.sink = NULL;
        !           106:     globinit.lt.top = 0;
        !           107:     globinit.lt.lines = 0;
        !           108:     globinit.lt.info = NULL;
        !           109:     globinit.insertPos = 0;
        !           110:     globinit.s.left = globinit.s.right = 0;
        !           111:     globinit.s.type = XtselectPosition;
        !           112:     globinit.width = 100;
        !           113:     globinit.height = 0;
        !           114:     globinit.leftmargin = 2;
        !           115:     globinit.options = 0;
        !           116:     globinit.sbar = globinit.outer = globinit.w = NULL;
        !           117:     globinit.sarray[0] = XtselectPosition;
        !           118:     globinit.sarray[1] = XtselectWord;
        !           119:     globinit.sarray[2] = XtselectLine;
        !           120:     globinit.sarray[3] = XtselectParagraph;
        !           121:     globinit.sarray[4] = XtselectAll;
        !           122:     globinit.sarray[5] = XtselectNull;
        !           123:     globinit.showposition = TRUE;
        !           124:     globinit.lastPos = 0;
        !           125:     globinit.dialog = NULL;
        !           126:     globinit.borderWidth = 1;
        !           127:     globinit.eventTable = NULL;        /* This is WRONG; should be some nice */
        !           128:                                /* default table. */
        !           129: }
        !           130: 
        !           131: /* Utility routines for support of Text */
        !           132: 
        !           133: 
        !           134: /*
        !           135:  * Procedure to manage insert cursor visibility for editable text.  It uses
        !           136:  * the value of ctx->insertPos and an implicit argument. In the event that
        !           137:  * position is immediately preceded by an eol graphic, then the insert cursor
        !           138:  * is displayed at the beginning of the next line.
        !           139: */
        !           140: static void InsertCursor (ctx, state)
        !           141:   TextContext *ctx;
        !           142:   InsertState state;
        !           143: {
        !           144:     Position x, y;
        !           145:     int dy, line, visible;
        !           146:     XtTextBlock text;
        !           147: 
        !           148:     if (ctx->lt.lines < 1) return;
        !           149:     visible = LineAndXYForPosition(ctx, ctx->insertPos, &line, &x, &y);
        !           150:     if (line < ctx->lt.lines)
        !           151:        dy = (ctx->lt.info[line + 1].y - ctx->lt.info[line].y) + 1;
        !           152:     else
        !           153:        dy = (ctx->lt.info[line].y - ctx->lt.info[line - 1].y) + 1;
        !           154: 
        !           155:     /** If the insert position is just after eol then put it on next line **/
        !           156:     if (x > ctx->leftmargin &&
        !           157:        ctx->insertPos > 0 &&
        !           158:        ctx->insertPos >= ctx->lastPos) {
        !           159:           /* reading the source is bogus and this code should use scan */
        !           160:           (*(ctx->source->read)) (ctx->source, ctx->insertPos - 1, &text, 1);
        !           161:           if (text.ptr[0] == '\n') {
        !           162:               x = ctx->leftmargin;
        !           163:               y += dy;
        !           164:           }
        !           165:     }
        !           166:     y += dy;
        !           167:     if (visible)
        !           168:        (*(ctx->sink->insertCursor))(ctx->sink, ctx->w, x, y, state);
        !           169: }
        !           170: 
        !           171: 
        !           172: /*
        !           173:  * Procedure to register a span of text that is no longer valid on the display
        !           174:  * It is used to avoid a number of small, and potentially overlapping, screen
        !           175:  * updates. [note: this is really a private procedure but is used in
        !           176:  * multiple modules].
        !           177: */
        !           178: _XtTextNeedsUpdating(ctx, left, right)
        !           179:   TextContext *ctx;
        !           180:   XtTextPosition left, right;
        !           181: {
        !           182:     int     i;
        !           183:     if (left < right) {
        !           184:        for (i = 0; i < ctx->numranges; i++) {
        !           185:            if (left <= ctx->updateTo[i] && right >= ctx->updateFrom[i]) {
        !           186:                ctx->updateFrom[i] = min(left, ctx->updateFrom[i]);
        !           187:                ctx->updateTo[i] = max(right, ctx->updateTo[i]);
        !           188:                return;
        !           189:            }
        !           190:        }
        !           191:        ctx->numranges++;
        !           192:        if (ctx->numranges > ctx->maxranges) {
        !           193:            ctx->maxranges = ctx->numranges;
        !           194:            i = ctx->maxranges * sizeof(XtTextPosition);
        !           195:            ctx->updateFrom = (XtTextPosition *) 
        !           196:                XtRealloc((char *)ctx->updateFrom, (unsigned) i);
        !           197:            ctx->updateTo = (XtTextPosition *) 
        !           198:                XtRealloc((char *)ctx->updateTo, (unsigned) i);
        !           199:        }
        !           200:        ctx->updateFrom[ctx->numranges - 1] = left;
        !           201:        ctx->updateTo[ctx->numranges - 1] = right;
        !           202:     }
        !           203: }
        !           204: 
        !           205: 
        !           206: /*
        !           207:  * Procedure to read a span of text in Ascii form. This is purely a hack and
        !           208:  * we probably need to add a function to sources to provide this functionality.
        !           209:  * [note: this is really a private procedure but is used in multiple modules].
        !           210: */
        !           211: char *_XtTextGetText(ctx, left, right)
        !           212:   TextContext *ctx;
        !           213:   XtTextPosition left, right;
        !           214: {
        !           215:     char   *result, *tempResult;
        !           216:     int length, resultLength;
        !           217:     XtTextBlock text;
        !           218:     XtTextPosition end, nend;
        !           219:     
        !           220:     resultLength = right - left + 10;  /* Bogus? %%% */
        !           221:     result = (char *)XtMalloc((unsigned) resultLength);
        !           222:     end = (*(ctx->source->read))(ctx->source, left, &text, right - left);
        !           223:     (void) strncpy(result, text.ptr, text.length);
        !           224:     length = text.length;
        !           225:     while (end < right) {
        !           226:         nend = (*(ctx->source->read))(ctx->source, end, &text, right - end);
        !           227:        tempResult = result + length;
        !           228:         (void) strncpy(tempResult, text.ptr, text.length);
        !           229:        length += text.length;
        !           230:         end = nend;
        !           231:     }
        !           232:     result[length] = 0;
        !           233:     return result;
        !           234: }
        !           235: 
        !           236: 
        !           237: 
        !           238: /* 
        !           239:  * This routine maps an x and y position in a window that is displaying text
        !           240:  * into the corresponding position in the source.
        !           241:  */
        !           242: static XtTextPosition PositionForXY (ctx, x, y)
        !           243:   TextContext *ctx;
        !           244:   Position x,y;
        !           245: {
        !           246:  /* it is illegal to call this routine unless there is a valid line table! */
        !           247:     int     width, fromx, line;
        !           248:     XtTextPosition position, resultstart, resultend;
        !           249: 
        !           250:     /*** figure out what line it is on ***/
        !           251:     for (line = 0; line < ctx->lt.lines - 1; line++) {
        !           252:        if (y <= ctx->lt.info[line + 1].y)
        !           253:            break;
        !           254:     }
        !           255:     position = ctx->lt.info[line].position;
        !           256:     if (position >= ctx->lastPos)
        !           257:        return ctx->lastPos;
        !           258:     fromx = ctx->lt.info[line].x;      /* starting x in line */
        !           259:     width = x - fromx;                 /* num of pix from starting of line */
        !           260:     (*(ctx->sink->resolve)) (ctx->sink, ctx->source, position, fromx, width,
        !           261:            &resultstart, &resultend);
        !           262:     if (resultstart >= ctx->lt.info[line + 1].position)
        !           263:        resultstart = (*(ctx->source->scan))(ctx->source,
        !           264:                ctx->lt.info[line + 1].position, XtstPositions, XtsdLeft, 1, TRUE);
        !           265:     return resultstart;
        !           266: }
        !           267: 
        !           268: /*
        !           269:  * This routine maps a source position in to the corresponding line number
        !           270:  * of the text that is displayed in the window.
        !           271: */
        !           272: int LineForPosition (ctx, position)
        !           273:   TextContext *ctx;
        !           274:   XtTextPosition position;
        !           275:   /* it is illegal to call this routine unless there is a valid line table!*/
        !           276: {
        !           277:     int     line;
        !           278: 
        !           279:     if (position <= ctx->lt.info[0].position)
        !           280:        return 0;
        !           281:     for (line = 0; line < ctx->lt.lines; line++)
        !           282:        if (position < ctx->lt.info[line + 1].position)
        !           283:            break;
        !           284:     return line;
        !           285: }
        !           286: 
        !           287: /*
        !           288:  * This routine maps a source position into the corresponding line number
        !           289:  * and the x, y coordinates of the text that is displayed in the window.
        !           290: */
        !           291: static int LineAndXYForPosition (ctx, pos, line, x, y)
        !           292:   TextContext *ctx;
        !           293:   XtTextPosition pos;
        !           294:   int *line;
        !           295:   Position *x, *y;
        !           296:   /* it is illegal to call this routine unless there is a valid line table!*/
        !           297: {
        !           298:     XtTextPosition linePos, endPos;
        !           299:     int     visible, realW, realH;
        !           300: 
        !           301:     *line = 0;
        !           302:     *x = ctx->leftmargin;
        !           303:     *y = yMargin;
        !           304:     visible = IsPositionVisible(ctx, pos);
        !           305:     if (visible) {
        !           306:        *line = LineForPosition(ctx, pos);
        !           307:        *y = ctx->lt.info[*line].y;
        !           308:        *x = ctx->lt.info[*line].x;
        !           309:        linePos = ctx->lt.info[*line].position;
        !           310:        (*(ctx->sink->findDistance))(ctx->sink, ctx->source, linePos,
        !           311:                                      *x, pos, &realW, &endPos, &realH);
        !           312:        *x = *x + realW;
        !           313:     }
        !           314:     return visible;
        !           315: }
        !           316: 
        !           317: /*
        !           318:  * This routine builds a line table. It does this by starting at the
        !           319:  * specified position and measuring text to determine the staring position
        !           320:  * of each line to be displayed. It also determines and saves in the
        !           321:  * linetable all the required metrics for displaying a given line (e.g.
        !           322:  * x offset, y offset, line length, etc.).
        !           323: */
        !           324: static void BuildLineTable (ctx, position)
        !           325:   TextContext *ctx;
        !           326:   XtTextPosition position;
        !           327: {
        !           328:     Position x, y;
        !           329:     Dimension width, realW, realH;
        !           330:     int line, lines;
        !           331:     XtTextPosition startPos, endPos;
        !           332:     Boolean     rebuild;
        !           333: 
        !           334:     rebuild = (Boolean) (position != ctx->lt.top);
        !           335:     lines = (*(ctx->sink->maxLines))(ctx->sink, ctx->height);
        !           336:     if (ctx->lt.info != NULL && lines != ctx->lt.lines) {
        !           337:        XtFree((char *) ctx->lt.info);
        !           338:        ctx->lt.info = NULL;
        !           339:     }
        !           340:     if (ctx->lt.info == NULL) {
        !           341:        ctx->lt.info = (LineTableEntry *)
        !           342:            XtMalloc((unsigned)sizeof(LineTableEntry) * (lines + 1));
        !           343:        for (line = 0; line < lines; line++) {
        !           344:            ctx->lt.info[line].position = 0;
        !           345:            ctx->lt.info[line].y = 0;
        !           346:        }
        !           347:        rebuild = TRUE;
        !           348:     }
        !           349:     else
        !           350:        lines = ctx->lt.lines;
        !           351:     if (rebuild) {
        !           352:        ctx->lt.top = position;
        !           353:        ctx->lt.lines = lines;
        !           354:        startPos = position;
        !           355:        y = yMargin;
        !           356:        for (line = 0; line <= ctx->lt.lines; line++) {
        !           357:            x = ctx->leftmargin;
        !           358:            ctx->lt.info[line].x = x;
        !           359:            ctx->lt.info[line].y = y;
        !           360:            ctx->lt.info[line].position = startPos;
        !           361:            if (startPos <= ctx->lastPos) {
        !           362:                width = (ctx->options & resizeWidth) ? 9999 : ctx->width - x;
        !           363:                (*(ctx->sink->findPosition))(ctx->sink, ctx->source, 
        !           364:                         startPos, x,
        !           365:                        width, (ctx->options & wordBreak),
        !           366:                        &endPos, &realW, &realH);
        !           367:                if (!(ctx->options & wordBreak) && endPos < ctx->lastPos) {
        !           368:                    endPos = (*(ctx->source->scan))(ctx->source, startPos,
        !           369:                            XtstEOL, XtsdRight, 1, TRUE);
        !           370:                    if (endPos == startPos)
        !           371:                        endPos = ctx->lastPos + 1;
        !           372:                }
        !           373:                ctx->lt.info[line].endX = realW + x;
        !           374:                startPos = endPos;
        !           375:            }
        !           376:            else ctx->lt.info[line].endX = x;
        !           377:            y = y + realH;
        !           378:        }
        !           379:     }
        !           380: }
        !           381: 
        !           382: /*
        !           383:  * This routine is used to re-display the entire window, independent of
        !           384:  * its current state.
        !           385: */
        !           386: void ForceBuildLineTable(ctx)
        !           387:     TextContext *ctx;
        !           388: {
        !           389:     XtTextPosition position;
        !           390: 
        !           391:     position = ctx->lt.top;
        !           392:     ctx->lt.top++; /* ugly, but it works */
        !           393:     BuildLineTable(ctx, position);
        !           394: }
        !           395: 
        !           396: /*
        !           397:  * This routine is used by Text to notify an associated scrollbar of the
        !           398:  * correct metrics (position and shown fraction) for the text being currently
        !           399:  * displayed in the window.
        !           400: */
        !           401: static void SetScrollBar(ctx)
        !           402:     TextContext *ctx;
        !           403: {
        !           404:     float   first, last;
        !           405:     if (ctx->sbar) {
        !           406:        if ((ctx->lastPos > 0)  &&  (ctx->lt.lines > 0)) {
        !           407:            first = ctx->lt.top;
        !           408:            first /= ctx->lastPos; 
        !           409:                                        /* Just an approximation */
        !           410:            last = ctx->lt.info[ctx->lt.lines].position;
        !           411:            last /= ctx->lastPos;
        !           412:        }
        !           413:        else {
        !           414:            first = 0.0;
        !           415:            last = 1.0;
        !           416:        }
        !           417:        XtScrollBarSetThumb(ctx->dpy, ctx->sbar, first, last - first);
        !           418:     }
        !           419: }
        !           420: 
        !           421: 
        !           422: /*
        !           423:  * The routine will scroll the displayed text by lines.  If the arg  is
        !           424:  * positive, move up; otherwise, move down. [note: this is really a private
        !           425:  * procedure but is used in multiple modules].
        !           426: */
        !           427: _XtTextScroll(ctx, n)
        !           428:   TextContext *ctx;
        !           429:   int n;
        !           430: {
        !           431:     XtTextPosition top, target;
        !           432:     if (n >= 0) {
        !           433:        top = min(ctx->lt.info[n].position, ctx->lastPos);
        !           434:        BuildLineTable(ctx, top);
        !           435:        if (top >= ctx->lastPos)
        !           436:            DisplayTextWindow(ctx);
        !           437:        else {
        !           438:            XCopyArea(ctx->dpy, ctx->w, ctx->w, ctx->gc,
        !           439:                      0, ctx->lt.info[n].y,
        !           440:                      9999, (Dimension)ctx->height - ctx->lt.info[n].y,
        !           441:                      0, ctx->lt.info[0].y);
        !           442:            (*(ctx->sink->clearToBackground))(ctx->sink, ctx->w, 0,
        !           443:                ctx->lt.info[0].y + ctx->height - ctx->lt.info[n].y,
        !           444:                9999, 9999);
        !           445:            if (n < ctx->lt.lines) n++;
        !           446:            _XtTextNeedsUpdating(ctx,
        !           447:                    ctx->lt.info[ctx->lt.lines - n].position, ctx->lastPos);
        !           448:            SetScrollBar(ctx);
        !           449:        }
        !           450:     } else {
        !           451:        Dimension tempHeight;
        !           452:        n = -n;
        !           453:        target = ctx->lt.top;
        !           454:        top = (*(ctx->source->scan))(ctx->source, target, XtstEOL,
        !           455:                                     XtsdLeft, n+1, FALSE);
        !           456:        tempHeight = ctx->lt.info[ctx->lt.lines-n].y;
        !           457:        BuildLineTable(ctx, top);
        !           458:        if (ctx->lt.info[n].position == target) {
        !           459:            XCopyArea(ctx->dpy, ctx->w, ctx->w, ctx->gc,
        !           460:                      0, ctx->lt.info[0].y, 9999, tempHeight,
        !           461:                      0, ctx->lt.info[n].y);
        !           462:            _XtTextNeedsUpdating(ctx, 
        !           463:                    ctx->lt.info[0].position, ctx->lt.info[n].position);
        !           464:            SetScrollBar(ctx);
        !           465:        } else if (ctx->lt.top != target) DisplayTextWindow(ctx);
        !           466:     }
        !           467: }
        !           468: 
        !           469: /*
        !           470:  * The routine will scroll the displayed text by pixels.  If the arg is
        !           471:  * positive, move up; otherwise, move down.
        !           472: */
        !           473: /*ARGSUSED*/ /* keep lint happy */
        !           474: static int ScrollUpDownProc (dpy, sbar, w, pix)
        !           475:   Display *dpy;
        !           476:   Window sbar, w;
        !           477:   int pix;
        !           478: {
        !           479:     TextContextPtr ctx;
        !           480:     int     apix, line;
        !           481:     if (XFindContext(dpy, w, textContext, (caddr_t *)&ctx))
        !           482:        return;
        !           483:     _XtTextPrepareToUpdate(ctx);
        !           484:     apix = abs(pix);
        !           485:     for (line = 1;
        !           486:            line < ctx->lt.lines && apix > ctx->lt.info[line + 1].y;
        !           487:            line++);
        !           488:     if (pix >= 0)
        !           489:        _XtTextScroll(ctx, line);
        !           490:     else
        !           491:        _XtTextScroll(ctx, -line);
        !           492:     _XtTextExecuteUpdate(ctx);
        !           493: }
        !           494: 
        !           495: /*
        !           496:  * The routine "thumbs" the displayed text. Thumbing means reposition the
        !           497:  * displayed view of the source to a new position determined by a fraction
        !           498:  * of the way from beginning to end. Ideally, this should be determined by
        !           499:  * the number of displayable lines in the source. This routine does it as a
        !           500:  * fraction of the first position and last position and then normalizes to
        !           501:  * the start of the line containing the position.
        !           502: */
        !           503: /*ARGSUSED*/ /* keep lint happy */
        !           504: static int ThumbProc (dpy, sbar, w, where)
        !           505:   Display *dpy;
        !           506:   Window sbar, w;
        !           507:   float where;
        !           508:   /* BUG/deficiency: The normalize to line portion of this routine will
        !           509:    * cause thumbing to always position to the start of the source.
        !           510:    */
        !           511: {
        !           512:   
        !           513:     TextContextPtr ctx;
        !           514:     XtTextPosition position;
        !           515:     if (XFindContext(dpy, w, textContext, (caddr_t *)&ctx))
        !           516:        return;
        !           517:     _XtTextPrepareToUpdate(ctx);
        !           518:     position = where * ctx->lastPos;
        !           519:     position = (*(ctx->source->scan))(ctx->source, position, XtstEOL, XtsdLeft,
        !           520:            1, FALSE);
        !           521:     BuildLineTable(ctx, position);
        !           522:     DisplayTextWindow(ctx);
        !           523:     _XtTextExecuteUpdate(ctx);
        !           524: }
        !           525: 
        !           526: 
        !           527: int _XtTextSetNewSelection(ctx, left, right)
        !           528:   TextContext *ctx;
        !           529:   XtTextPosition left, right;
        !           530: {
        !           531:     XtTextPosition pos;
        !           532: 
        !           533:     if (left < ctx->s.left) {
        !           534:        pos = min(right, ctx->s.left);
        !           535:        _XtTextNeedsUpdating(ctx, left, pos);
        !           536:     }
        !           537:     if (left > ctx->s.left) {
        !           538:        pos = min(left, ctx->s.right);
        !           539:        _XtTextNeedsUpdating(ctx, ctx->s.left, pos);
        !           540:     }
        !           541:     if (right < ctx->s.right) {
        !           542:        pos = max(right, ctx->s.left);
        !           543:        _XtTextNeedsUpdating(ctx, pos, ctx->s.right);
        !           544:     }
        !           545:     if (right > ctx->s.right) {
        !           546:        pos = max(left, ctx->s.right);
        !           547:        _XtTextNeedsUpdating(ctx, pos, right);
        !           548:     }
        !           549: 
        !           550:     ctx->s.left = left;
        !           551:     ctx->s.right = right;
        !           552: }
        !           553: 
        !           554: 
        !           555: 
        !           556: /*
        !           557:  * This internal routine deletes the text from pos1 to pos2 in a source and
        !           558:  * then inserts, at pos1, the text that was passed. As a side effect it
        !           559:  * "invalidates" that portion of the displayed text (if any).
        !           560: */
        !           561: int ReplaceText (ctx, pos1, pos2, text)
        !           562:   TextContext *ctx;
        !           563:   XtTextPosition pos1, pos2;
        !           564:   XtTextBlock *text;
        !           565: 
        !           566:  /* it is illegal to call this routine unless there is a valid line table!*/
        !           567: {
        !           568:     int i, line1, line2, visible, delta, error;
        !           569:     Position x, y;
        !           570:     Dimension realW, realH, width;
        !           571:     XtTextPosition startPos, endPos, updateFrom;
        !           572: 
        !           573:     /* the insertPos may not always be set to the right spot in XttextAppend */
        !           574:     if ((pos1 == ctx->insertPos) && 
        !           575:         ((*(ctx->source->editType))(ctx->source) == XttextAppend)) {
        !           576:       ctx->insertPos = GETLASTPOS;
        !           577:       pos2 = pos2 - pos1 + ctx->insertPos;
        !           578:       pos1 = ctx->insertPos;
        !           579:     }
        !           580:     updateFrom = (*(ctx->source->scan))(ctx->source, pos1, XtstWhiteSpace, XtsdLeft,
        !           581:            1, TRUE);
        !           582:     updateFrom = (*(ctx->source->scan))(ctx->source, updateFrom, XtstPositions, XtsdLeft,
        !           583:            1, TRUE);
        !           584:     startPos = max(updateFrom, ctx->lt.top);
        !           585:     visible = LineAndXYForPosition(ctx, startPos, &line1, &x, &y);
        !           586:     error = (*(ctx->source->replace))(ctx->source, pos1, pos2, text, &delta);
        !           587:     if (error) return error;
        !           588:     ctx->lastPos = GETLASTPOS;
        !           589:     if (ctx->lt.top >= ctx->lastPos) {
        !           590:        BuildLineTable(ctx, ctx->lastPos);
        !           591:        ClearWindow(ctx);
        !           592:        SetScrollBar(ctx);
        !           593:        return error;
        !           594:     }
        !           595:     if (delta < ctx->lastPos) {
        !           596:        for (i = 0; i < ctx->numranges; i++) {
        !           597:            if (ctx->updateFrom[i] > pos1)
        !           598:                ctx->updateFrom[i] += delta;
        !           599:            if (ctx->updateTo[i] >= pos1)
        !           600:                ctx->updateTo[i] += delta;
        !           601:        }
        !           602:     }
        !           603: 
        !           604:     line2 = LineForPosition(ctx, pos1);
        !           605:     /* 
        !           606:      * fixup all current line table entries to reflect edit.
        !           607:      * BUG: it is illegal to do arithmetic on positions. This code should
        !           608:      * either use scan or the source needs to provide a function for doing
        !           609:      * position arithmetic.
        !           610:     */
        !           611:     for (i = line2 + 1; i <= ctx->lt.lines; i++)
        !           612:        ctx->lt.info[i].position += delta;
        !           613: 
        !           614:     endPos = pos1;
        !           615:     /*
        !           616:      * Now process the line table and fixup in case edits caused
        !           617:      * changes in line breaks. If we are breaking on word boundaries,
        !           618:      * this code checks for moving words to and from lines.
        !           619:     */
        !           620:     if (visible) {
        !           621:        for (i = line1; i < ctx->lt.lines; i++) {/* fixup line table */
        !           622:            width = (ctx->options & resizeWidth) ? 9999 : ctx->width - x;
        !           623:            if (startPos <= ctx->lastPos) {
        !           624:                (*(ctx->sink->findPosition))(ctx->sink, 
        !           625:                         ctx->source, startPos, x,
        !           626:                        width, (ctx->options & wordBreak),
        !           627:                        &endPos, &realW, &realH);
        !           628:                if (!(ctx->options & wordBreak) && endPos < ctx->lastPos) {
        !           629:                    endPos = (*(ctx->source->scan))(ctx->source, startPos,
        !           630:                            XtstEOL, XtsdRight, 1, TRUE);
        !           631:                    if (endPos == startPos)
        !           632:                        endPos = ctx->lastPos + 1;
        !           633:                }
        !           634:                ctx->lt.info[i].endX = realW + x;
        !           635:                ctx->lt.info[i + 1].y = realH + ctx->lt.info[i].y;
        !           636:                if ((endPos > pos1) &&
        !           637:                        (endPos == ctx->lt.info[i + 1].position))
        !           638:                    break;
        !           639:                startPos = endPos;
        !           640:            }
        !           641:            if (startPos > ctx->lastPos)
        !           642:                ctx->lt.info[i + 1].endX = ctx->leftmargin;
        !           643:            ctx->lt.info[i + 1].position = startPos;
        !           644:            x = ctx->lt.info[i + 1].x;
        !           645:        }
        !           646:     }
        !           647:     if (delta >= ctx->lastPos)
        !           648:        endPos = ctx->lastPos;
        !           649:     if (delta >= ctx->lastPos || pos2 >= ctx->lt.top)
        !           650:        _XtTextNeedsUpdating(ctx, updateFrom, endPos);
        !           651:     SetScrollBar(ctx);
        !           652:     return error;
        !           653: }
        !           654: 
        !           655: 
        !           656: /*
        !           657:  * This routine will display text between two arbitrary source positions.
        !           658:  * In the event that this span contains highlighted text for the selection, 
        !           659:  * only that portion will be displayed highlighted.
        !           660:  */
        !           661: static void DisplayText(ctx, pos1, pos2)
        !           662:   TextContext *ctx;
        !           663:   XtTextPosition pos1, pos2;
        !           664:   /* it is illegal to call this routine unless there is a valid line table!*/
        !           665: {
        !           666:     Position x, y;
        !           667:     Dimension height;
        !           668:     int line, i, visible;
        !           669:     XtTextPosition startPos, endPos;
        !           670: 
        !           671:     if (pos1 < ctx->lt.top)
        !           672:        pos1 = ctx->lt.top;
        !           673:     if (pos2 > ctx->lastPos) 
        !           674:        pos2 = ctx->lastPos;
        !           675:     if (pos1 >= pos2) return;
        !           676:     visible = LineAndXYForPosition(ctx, pos1, &line, &x, &y);
        !           677:     if (!visible)
        !           678:        return;
        !           679:     startPos = pos1;
        !           680:     height = ctx->lt.info[1].y - ctx->lt.info[0].y;
        !           681:     for (i = line; i < ctx->lt.lines; i++) {
        !           682:        endPos = ctx->lt.info[i + 1].position;
        !           683:        if (endPos > pos2)
        !           684:            endPos = pos2;
        !           685:        if (endPos > startPos) {
        !           686:            if (x == ctx->leftmargin)
        !           687:                 (*(ctx->sink->clearToBackground))(ctx->sink, ctx->w,
        !           688:                     0, y, ctx->leftmargin, height);
        !           689:            if (startPos >= ctx->s.right || endPos <= ctx->s.left) {
        !           690:                (*(ctx->sink->display))(ctx->sink, ctx->source, ctx->w, x, y,
        !           691:                        startPos, endPos, FALSE);
        !           692:            } else if (startPos >= ctx->s.left && endPos <= ctx->s.right) {
        !           693:                (*(ctx->sink->display))(ctx->sink, ctx->source, ctx->w, x, y,
        !           694:                        startPos, endPos, TRUE);
        !           695:            } else {
        !           696:                DisplayText(ctx, startPos, ctx->s.left);
        !           697:                DisplayText(ctx, max(startPos, ctx->s.left), 
        !           698:                        min(endPos, ctx->s.right));
        !           699:                DisplayText(ctx, ctx->s.right, endPos);
        !           700:            }
        !           701:        }
        !           702:        startPos = endPos;
        !           703:        height = ctx->lt.info[i + 1].y - ctx->lt.info[i].y;
        !           704:         (*(ctx->sink->clearToBackground))(ctx->sink, ctx->w,
        !           705:            ctx->lt.info[i].endX, y, 999, height);
        !           706:        x = ctx->leftmargin;
        !           707:        y = ctx->lt.info[i + 1].y;
        !           708:        if ((endPos == pos2) && (endPos != ctx->lastPos))
        !           709:            break;
        !           710:     }
        !           711: }
        !           712: 
        !           713: /*
        !           714:  * This routine implements multi-click selection in a hardwired manner.
        !           715:  * It supports multi-click entity cycling (char, word, line, file) and mouse
        !           716:  * motion adjustment of the selected entitie (i.e. select a word then, with
        !           717:  * button still down, adjust wich word you really meant by moving the mouse).
        !           718:  * [NOTE: This routine is to be replaced by a set of procedures that
        !           719:  * will allows clients to implements a wide class of draw through and
        !           720:  * multi-click selection user interfaces.]
        !           721: */
        !           722: static void DoSelection (ctx, position, time, motion)
        !           723:   TextContext *ctx;
        !           724:   XtTextPosition position;
        !           725:   unsigned short time;
        !           726:   Boolean motion;
        !           727: {
        !           728:     int     delta;
        !           729:     XtTextPosition newLeft, newRight;
        !           730:     XtSelectType newType;
        !           731:     XtSelectType *sarray;
        !           732: 
        !           733:     delta = (time < ctx->lasttime) ?
        !           734:        ctx->lasttime - time : time - ctx->lasttime;
        !           735:     if (motion)
        !           736:        newType = ctx->s.type;
        !           737:     else {
        !           738:        if ((delta < 500) && ((position >= ctx->s.left)
        !           739:                    && (position <= ctx->s.right))) { /* multi-click event */
        !           740:            sarray = ctx->sarray;
        !           741:            for (sarray = ctx->sarray;
        !           742:                *sarray != XtselectNull && *sarray != ctx->s.type;
        !           743:                sarray++) ;
        !           744:            if (*sarray != XtselectNull) sarray++;
        !           745:            if (*sarray == XtselectNull) sarray = ctx->sarray;
        !           746:            newType = *sarray;
        !           747:        } else {                        /* single-click event */
        !           748:            newType = *(ctx->sarray);
        !           749:        }
        !           750:         ctx->lasttime = time;
        !           751:     }
        !           752:     switch (newType) {
        !           753:        case XtselectPosition: 
        !           754:             newLeft = newRight = position;
        !           755:            break;
        !           756:        case XtselectChar: 
        !           757:             newLeft = position;
        !           758:             newRight = (*(ctx->source->scan))(
        !           759:                     ctx->source, position, position, XtsdRight, 1, FALSE);
        !           760:            break;
        !           761:        case XtselectWord: 
        !           762:            newLeft = (*(ctx->source->scan))(
        !           763:                    ctx->source, position, XtstWhiteSpace, XtsdLeft, 1, FALSE);
        !           764:            newRight = (*(ctx->source->scan))(
        !           765:                    ctx->source, position, XtstWhiteSpace, XtsdRight, 1, FALSE);
        !           766:            break;
        !           767:        case XtselectLine: 
        !           768:        case XtselectParagraph:  /* need "para" scan mode to implement pargraph */
        !           769:            newLeft = (*(ctx->source->scan))(
        !           770:                    ctx->source, position, XtstEOL, XtsdLeft, 1, FALSE);
        !           771:            newRight = (*(ctx->source->scan))(
        !           772:                    ctx->source, position, XtstEOL, XtsdRight, 1, FALSE);
        !           773:            break;
        !           774:        case XtselectAll: 
        !           775:            newLeft = (*(ctx->source->scan))(
        !           776:                    ctx->source, position, XtstFile, XtsdLeft, 1, FALSE);
        !           777:            newRight = (*(ctx->source->scan))(
        !           778:                    ctx->source, position, XtstFile, XtsdRight, 1, FALSE);
        !           779:            break;
        !           780:     }
        !           781:     if ((newLeft != ctx->s.left) || (newRight != ctx->s.right)
        !           782:            || (newType != ctx->s.type)) {
        !           783:        _XtTextSetNewSelection(ctx, newLeft, newRight);
        !           784:        ctx->s.type = newType;
        !           785:        if (position - ctx->s.left < ctx->s.right - position)
        !           786:            ctx->insertPos = newLeft;
        !           787:        else 
        !           788:            ctx->insertPos = newRight;
        !           789:     }
        !           790:     if (!motion) { /* setup so we can freely mix select extend calls*/
        !           791:        ctx->origSel.type = ctx->s.type;
        !           792:        ctx->origSel.left = ctx->s.left;
        !           793:        ctx->origSel.right = ctx->s.right;
        !           794:        if (position >= ctx->s.left + ((ctx->s.right - ctx->s.left) / 2))
        !           795:            ctx->extendDir = XtsdRight;
        !           796:        else
        !           797:            ctx->extendDir = XtsdLeft;
        !           798:     }
        !           799: }
        !           800: 
        !           801: /*
        !           802:  * This routine implements extension of the currently selected text in
        !           803:  * the "current" mode (i.e. char word, line, etc.). It worries about
        !           804:  * extending from either end of the selection and handles the case when you
        !           805:  * cross through the "center" of the current selection (e.g. switch which
        !           806:  * end you are extending!).
        !           807:  * [NOTE: This routine will be replaced by a set of procedures that
        !           808:  * will allows clients to implements a wide class of draw through and
        !           809:  * multi-click selection user interfaces.]
        !           810: */
        !           811: static void ExtendSelection (ctx, position, motion)
        !           812:   TextContext *ctx;
        !           813:   XtTextPosition position;
        !           814:   Boolean motion;
        !           815: {
        !           816:     XtTextPosition newLeft, newRight;
        !           817:        
        !           818: 
        !           819:     if (!motion) {             /* setup for extending selection */
        !           820:        ctx->origSel.type = ctx->s.type;
        !           821:        ctx->origSel.left = ctx->s.left;
        !           822:        ctx->origSel.right = ctx->s.right;
        !           823:        if (position >= ctx->s.left + ((ctx->s.right - ctx->s.left) / 2))
        !           824:            ctx->extendDir = XtsdRight;
        !           825:        else
        !           826:            ctx->extendDir = XtsdLeft;
        !           827:     }
        !           828:     else /* check for change in extend direction */
        !           829:        if ((ctx->extendDir == XtsdRight && position < ctx->origSel.left) ||
        !           830:                (ctx->extendDir == XtsdLeft && position > ctx->origSel.right)) {
        !           831:            ctx->extendDir = (ctx->extendDir == XtsdRight)? XtsdLeft : XtsdRight;
        !           832:            _XtTextSetNewSelection(ctx, ctx->origSel.left, ctx->origSel.right);
        !           833:        }
        !           834:     newLeft = ctx->s.left;
        !           835:     newRight = ctx->s.right;
        !           836:     switch (ctx->s.type) {
        !           837:        case XtselectPosition: 
        !           838:            if (ctx->extendDir == XtsdRight)
        !           839:                newRight = position;
        !           840:            else
        !           841:                newLeft = position;
        !           842:            break;
        !           843:        case XtselectWord: 
        !           844:            if (ctx->extendDir == XtsdRight)
        !           845:                newRight = position = (*(ctx->source->scan))(
        !           846:                        ctx->source, position, XtstWhiteSpace, XtsdRight, 1, FALSE);
        !           847:            else
        !           848:                newLeft = position = (*(ctx->source->scan))(
        !           849:                        ctx->source, position, XtstWhiteSpace, XtsdLeft, 1, FALSE);
        !           850:            break;
        !           851:         case XtselectLine:
        !           852:        case XtselectParagraph: /* need "para" scan mode to implement pargraph */
        !           853:            if (ctx->extendDir == XtsdRight)
        !           854:                newRight = position = (*(ctx->source->scan))(
        !           855:                        ctx->source, position, XtstEOL, XtsdRight, 1, TRUE);
        !           856:            else
        !           857:                newLeft = position = (*(ctx->source->scan))(
        !           858:                        ctx->source, position, XtstEOL, XtsdLeft, 1, FALSE);
        !           859:            break;
        !           860:        case XtselectAll: 
        !           861:            position = ctx->insertPos;
        !           862:            break;
        !           863:     }
        !           864:     _XtTextSetNewSelection(ctx, newLeft, newRight);
        !           865:     ctx->insertPos = position;
        !           866: }
        !           867: 
        !           868: 
        !           869: /*
        !           870:  * Clear the window to background color.
        !           871: */
        !           872: static ClearWindow (ctx)
        !           873:   TextContext *ctx;
        !           874: {
        !           875:     (*(ctx->sink->clearToBackground))(ctx->sink, ctx->w, 0, 0, ctx->width,
        !           876:                                      ctx->height);
        !           877: }
        !           878: 
        !           879: 
        !           880: /*
        !           881:  * Internal redisplay entire window.
        !           882: */
        !           883: DisplayTextWindow (ctx)
        !           884:   TextContext *ctx;
        !           885: {
        !           886:     ClearWindow(ctx);
        !           887:     BuildLineTable(ctx, ctx->lt.top);
        !           888:     _XtTextNeedsUpdating(ctx, zeroPosition, ctx->lastPos);
        !           889:     SetScrollBar(ctx);
        !           890: }
        !           891: 
        !           892: /*
        !           893:  * This routine checks to see if the window should be resized (grown or
        !           894:  * shrunk) or scrolled then text to be painted overflows to the right or
        !           895:  * the bottom of the window. It is used by the keyboard input routine.
        !           896: */
        !           897: CheckResizeOrOverflow(ctx)
        !           898:   TextContext *ctx;
        !           899: {
        !           900:     XtTextPosition posToCheck;
        !           901:     int     visible, line, width;
        !           902:     WindowBox rbox, abox;
        !           903:     if (ctx->options & resizeWidth) {
        !           904:        width = 0;
        !           905:        for (line=0 ; line<ctx->lt.lines ; line++)
        !           906:            if (width < ctx->lt.info[line].endX)
        !           907:                width = ctx->lt.info[line].endX;
        !           908:        width += ctx->leftmargin;
        !           909:        if (width > ctx->width) {
        !           910:            rbox.x = rbox.y = 0;
        !           911:            rbox.width = width;
        !           912:            rbox.height = ctx->height;
        !           913:            (void) XtMakeGeometryRequest(ctx->dpy, ctx->w, XtgeometryResize, &rbox, &abox);
        !           914:        }
        !           915:     }
        !           916:     if ((ctx->options & resizeHeight) || (ctx->options & scrollOnOverflow)) {
        !           917:        if (ctx->options & scrollOnOverflow)
        !           918:            posToCheck = ctx->insertPos;
        !           919:        else
        !           920:            posToCheck = ctx->lastPos;
        !           921:        visible = IsPositionVisible(ctx, posToCheck);
        !           922:        if (visible)
        !           923:            line = LineForPosition(ctx, posToCheck);
        !           924:        else
        !           925:            line = ctx->lt.lines;
        !           926:        if ((ctx->options & scrollOnOverflow) && (line + 1 > ctx->lt.lines)) {
        !           927:            BuildLineTable(ctx, ctx->lt.info[1].position);
        !           928:            XCopyArea(ctx->dpy, ctx->w, ctx->w, ctx->gc,
        !           929:                      (Position)ctx->leftmargin, ctx->lt.info[1].y, 9999, 9999,
        !           930:                      (Position)ctx->leftmargin, ctx->lt.info[0].y);
        !           931:        }
        !           932:        else
        !           933:            if ((ctx->options & resizeHeight) && (line + 1 != ctx->lt.lines)) {
        !           934:                rbox.x = 0;
        !           935:                rbox.y = 0;
        !           936:                rbox.width = ctx->width;
        !           937:                rbox.height = (*(ctx->sink->maxHeight))
        !           938:                                        (ctx->sink, line + 1) + (2*yMargin)+2;
        !           939:                (void) XtMakeGeometryRequest(ctx->dpy, ctx->w, XtgeometryResize, &rbox, &abox);
        !           940:            }
        !           941:     }
        !           942: }
        !           943: 
        !           944: /* 
        !           945:  * This routine processes all keyboard, button and mouse XEvents. It is
        !           946:  * responsible for performing any key/button to function mapping (with the
        !           947:  * help of the translation manager) as well as doing any edits of editable
        !           948:  * sources. 
        !           949:  */
        !           950: static void ProcessKeysAndButtons (event, ctx)
        !           951:   XEvent *event;
        !           952:   TextContext *ctx;
        !           953: {
        !           954:     Boolean     more;
        !           955:     XtTextBlock text;
        !           956:     XEvent ev;
        !           957:     XtActionTokenPtr actionList;
        !           958:     ActionProc proc;
        !           959: 
        !           960:     if (event->type == MotionNotify) {
        !           961:        while (QLength(ctx->dpy)) {
        !           962:            XPeekEvent(ctx->dpy, &ev);
        !           963:            if (ev.type == MotionNotify) {
        !           964:                XNextEvent(ctx->dpy, &ev);
        !           965:                event = &ev;
        !           966:            } else break;
        !           967:        }
        !           968:     }
        !           969:                
        !           970:     ctx->time = event->xbutton.time;
        !           971:     ctx->x = event->xbutton.x;
        !           972:     ctx->y = event->xbutton.y;
        !           973:     do {
        !           974:        actionList = (XtActionTokenPtr) XtTranslateEvent(
        !           975:                event, (TranslationPtr) ctx->state);
        !           976:        if (actionList == NULL)
        !           977:            return;
        !           978:        while (actionList != NULL) {
        !           979:            switch (actionList->type) {
        !           980:                case XttokenAction: 
        !           981:                    proc = (ActionProc) XtInterpretAction(ctx->dpy, 
        !           982:                            (TranslationPtr) ctx->state, actionList->value.action);
        !           983:                    (*(proc))(ctx);
        !           984:                    break;
        !           985:                case XttokenChar: 
        !           986:                case XttokenString: 
        !           987:                    if (actionList->type == XttokenString) {
        !           988:                        text.ptr = actionList->value.str;
        !           989:                        text.length = strlen(actionList->value.str);
        !           990:                    }
        !           991:                    else {
        !           992:                        text.ptr = &actionList->value.c;
        !           993:                        text.length = 1;
        !           994:                    }
        !           995:                    text.firstPos = 0;
        !           996:                    if (ReplaceText(ctx, ctx->insertPos, ctx->insertPos,
        !           997:                                &text)) {
        !           998:                        XBell(ctx->dpy, 50);
        !           999:                        break;
        !          1000:                    }
        !          1001:                    ctx->insertPos =
        !          1002:                        (*(ctx->source->scan))(ctx->source, ctx->insertPos,
        !          1003:                            XtstPositions, XtsdRight, text.length, TRUE);
        !          1004:                    _XtTextSetNewSelection(ctx,
        !          1005:                            ctx->insertPos, ctx->insertPos);
        !          1006:                    break;
        !          1007:            }
        !          1008:            actionList = actionList->next;
        !          1009:        }
        !          1010:        more = FALSE;
        !          1011:        if (QLength(ctx->dpy)) {
        !          1012:            XPeekEvent(ctx->dpy, &ev);
        !          1013:            if (ev.type == KeyPress) {
        !          1014:                XNextEvent(ctx->dpy, &ev);
        !          1015:                event = &ev;
        !          1016:                more = TRUE;
        !          1017:            }
        !          1018:        }
        !          1019:     } while (more);
        !          1020:     CheckResizeOrOverflow(ctx);
        !          1021: }
        !          1022: 
        !          1023: /*
        !          1024:  * This routine is used to perform various selection functions. The goal is
        !          1025:  * to be able to specify all the more popular forms of draw-through and
        !          1026:  * multi-click selection user interfaces from the outside.
        !          1027:  */
        !          1028: void AlterSelection (ctx, mode, action)
        !          1029:     TextContext     *ctx;
        !          1030:     SelectionMode   mode;      /* {XtsmTextSelect, XtsmTextExtend}               */
        !          1031:     SelectionAction action;    /* {XtactionStart, XtactionAdjust, XtactionEnd} */
        !          1032: {
        !          1033:     XtTextPosition position;
        !          1034:     char   *ptr;
        !          1035: 
        !          1036:     position = PositionForXY (ctx, (int) ctx->x, (int) ctx->y);
        !          1037:     if (action == XtactionStart) {
        !          1038:        switch (mode) {
        !          1039:        case XtsmTextSelect: 
        !          1040:            DoSelection (ctx, position, ctx->time, FALSE);
        !          1041:            break;
        !          1042:        case XtsmTextExtend: 
        !          1043:            ExtendSelection (ctx, position, FALSE);
        !          1044:            break;
        !          1045:        }
        !          1046:     }
        !          1047:     else {
        !          1048:        switch (mode) {
        !          1049:        case XtsmTextSelect: 
        !          1050:            DoSelection (ctx, position, ctx->time, TRUE);
        !          1051:            break;
        !          1052:        case XtsmTextExtend: 
        !          1053:            ExtendSelection (ctx, position, TRUE);
        !          1054:            break;
        !          1055:        }
        !          1056:     }
        !          1057:     if (action == XtactionEnd && ctx->s.left < ctx->s.right) {
        !          1058:        ptr = _XtTextGetText (ctx, ctx->s.left, ctx->s.right);
        !          1059:        XStoreBuffer (ctx->dpy, ptr, min (strlen (ptr), MAXCUT), 0);
        !          1060:        XtFree (ptr);
        !          1061:     }
        !          1062: }
        !          1063: 
        !          1064: /*
        !          1065:  * This routine processes all "expose region" XEvents. In general, its job
        !          1066:  * is to the best job at minimal re-paint of the text, displayed in the
        !          1067:  * window, that it can.
        !          1068: */
        !          1069: static ProcessExposeRegion(event, ctx)
        !          1070:   XEvent *event;
        !          1071:   TextContextPtr ctx;
        !          1072: {
        !          1073:     XtTextPosition pos1, pos2, resultend;
        !          1074:     int line;
        !          1075:     int x = event->xexpose.x;
        !          1076:     int y = event->xexpose.y;
        !          1077:     int width = event->xexpose.width;
        !          1078:     int height = event->xexpose.height;
        !          1079:     LineTableEntryPtr info;
        !          1080:     if (x < ctx->leftmargin) /* stomp on caret tracks */
        !          1081:         (*(ctx->sink->clearToBackground))(ctx->sink, ctx->w, x, y,
        !          1082:                                          width, height);
        !          1083:    /* figure out starting line that was exposed */
        !          1084:     line = LineForPosition(ctx, PositionForXY(ctx, x, y));
        !          1085:     while (line < ctx->lt.lines && ctx->lt.info[line + 1].y < y)
        !          1086:        line++;
        !          1087:     while (line < ctx->lt.lines) {
        !          1088:        info = &(ctx->lt.info[line]);
        !          1089:        if (info->y >= y + height)
        !          1090:            break;
        !          1091:        (*(ctx->sink->resolve))(ctx->sink, ctx->source, 
        !          1092:                                 info->position, info->x,
        !          1093:                                x - info->x, &pos1, &resultend);
        !          1094:        (*(ctx->sink->resolve))(ctx->sink, ctx->source, 
        !          1095:                                 info->position, info->x,
        !          1096:                                x + width - info->x, &pos2, 
        !          1097:                                 &resultend);
        !          1098:        pos2 = (*(ctx->source->scan))(ctx->source, pos2, XtstPositions, 
        !          1099:                                       XtsdRight, 1, TRUE);
        !          1100:        _XtTextNeedsUpdating(ctx, pos1, pos2);
        !          1101:        line++;
        !          1102:     }
        !          1103: }
        !          1104: 
        !          1105: 
        !          1106: static int oldinsert = -1;
        !          1107: 
        !          1108: /*
        !          1109:  * This routine does all setup required to syncronize batched screen updates
        !          1110: */
        !          1111: int _XtTextPrepareToUpdate(ctx)
        !          1112:   TextContext *ctx;
        !          1113: {
        !          1114:     if (oldinsert < 0) {
        !          1115:        InsertCursor(ctx, XtisOff);
        !          1116:        ctx->numranges = 0;
        !          1117:        ctx->showposition = FALSE;
        !          1118:        oldinsert = ctx->insertPos;
        !          1119:     }
        !          1120: }
        !          1121: 
        !          1122: 
        !          1123: /*
        !          1124:  * This is a private utility routine used by _XtTextExecuteUpdate. It
        !          1125:  * processes all the outstanding update requests and merges update
        !          1126:  * ranges where possible.
        !          1127: */
        !          1128: static FlushUpdate(ctx)
        !          1129:   TextContext *ctx;
        !          1130: {
        !          1131:     int     i, w;
        !          1132:     XtTextPosition updateFrom, updateTo;
        !          1133:     while (ctx->numranges > 0) {
        !          1134:        updateFrom = ctx->updateFrom[0];
        !          1135:        w = 0;
        !          1136:        for (i=1 ; i<ctx->numranges ; i++) {
        !          1137:            if (ctx->updateFrom[i] < updateFrom) {
        !          1138:                updateFrom = ctx->updateFrom[i];
        !          1139:                w = i;
        !          1140:            }
        !          1141:        }
        !          1142:        updateTo = ctx->updateTo[w];
        !          1143:        ctx->numranges--;
        !          1144:        ctx->updateFrom[w] = ctx->updateFrom[ctx->numranges];
        !          1145:        ctx->updateTo[w] = ctx->updateTo[ctx->numranges];
        !          1146:        for (i=ctx->numranges-1 ; i>=0 ; i--) {
        !          1147:            while (ctx->updateFrom[i] <= updateTo && i < ctx->numranges) {
        !          1148:                updateTo = ctx->updateTo[i];
        !          1149:                ctx->numranges--;
        !          1150:                ctx->updateFrom[i] = ctx->updateFrom[ctx->numranges];
        !          1151:                ctx->updateTo[i] = ctx->updateTo[ctx->numranges];
        !          1152:            }
        !          1153:        }
        !          1154:        DisplayText(ctx, updateFrom, updateTo);
        !          1155:     }
        !          1156: }
        !          1157: 
        !          1158: 
        !          1159: /*
        !          1160:  * This is a private utility routine used by _XtTextExecuteUpdate. This routine
        !          1161:  * worries about edits causing new data or the insertion point becoming
        !          1162:  * invisible (off the screen). Currently it always makes it visible by
        !          1163:  * scrolling. It probably needs generalization to allow more options.
        !          1164: */
        !          1165: _XtTextShowPosition(ctx)
        !          1166:   TextContext *ctx;
        !          1167: {
        !          1168:     XtTextPosition top, first, second;
        !          1169:     if (ctx->insertPos < ctx->lt.top ||
        !          1170:                ctx->insertPos >= ctx->lt.info[ctx->lt.lines].position) {
        !          1171:        if (ctx->lt.lines > 0 && (ctx->insertPos < ctx->lt.top ||
        !          1172:                ctx->lt.info[ctx->lt.lines].position <= ctx->lastPos)) {
        !          1173:            first = ctx->lt.top;
        !          1174:            second = ctx->lt.info[1].position;
        !          1175:            if (ctx->insertPos < first)
        !          1176:                top = (*(ctx->source->scan))(ctx->source, ctx->insertPos, XtstEOL,
        !          1177:                        XtsdLeft, 1, FALSE);
        !          1178:            else
        !          1179:                top = (*(ctx->source->scan))(ctx->source, ctx->insertPos, XtstEOL,
        !          1180:                        XtsdLeft, ctx->lt.lines, FALSE);
        !          1181:            BuildLineTable(ctx, top);
        !          1182:            while (ctx->insertPos >= ctx->lt.info[ctx->lt.lines].position) {
        !          1183:                if (ctx->lt.info[ctx->lt.lines].position > ctx->lastPos)
        !          1184:                    break;
        !          1185:                BuildLineTable(ctx, ctx->lt.info[1].position);
        !          1186:            }
        !          1187:            if (ctx->lt.top == second) {
        !          1188:                BuildLineTable(ctx, first);
        !          1189:                _XtTextScroll(ctx, 1);
        !          1190:            } else if (ctx->lt.info[1].position == first) {
        !          1191:                BuildLineTable(ctx, first);
        !          1192:                _XtTextScroll(ctx, -1);
        !          1193:            } else {
        !          1194:                ctx->numranges = 0;
        !          1195:                if (ctx->lt.top != first)
        !          1196:                    DisplayTextWindow(ctx);
        !          1197:            }
        !          1198:        }
        !          1199:     }
        !          1200: }
        !          1201: 
        !          1202: 
        !          1203: 
        !          1204: /*
        !          1205:  * This routine causes all batched screen updates to be performed
        !          1206: */
        !          1207: _XtTextExecuteUpdate(ctx)
        !          1208:   TextContext *ctx;
        !          1209: {
        !          1210:     if (oldinsert >= 0) {
        !          1211:        if (oldinsert != ctx->insertPos || ctx->showposition)
        !          1212:            _XtTextShowPosition(ctx);
        !          1213:        FlushUpdate(ctx);
        !          1214:        InsertCursor(ctx, XtisOn);
        !          1215:        oldinsert = -1;
        !          1216:     }
        !          1217: }
        !          1218: 
        !          1219: 
        !          1220: static HandleDestroyNotify(ctx)
        !          1221: TextContext *ctx;
        !          1222: {
        !          1223:     if (ctx->dialog)
        !          1224:        (void) XtSendDestroyNotify(ctx->dpy, ctx->dialog);
        !          1225:     (void) XDeleteContext(ctx->dpy, ctx->w, textContext);
        !          1226:     if (ctx->outer)
        !          1227:        (void) XDeleteContext(ctx->dpy, ctx->outer, textContext);
        !          1228:     XtFree((char *)ctx->updateFrom);
        !          1229:     XtFree((char *)ctx->updateTo);
        !          1230:     XtFree((char *)ctx);
        !          1231: }
        !          1232: 
        !          1233: 
        !          1234: /*
        !          1235:  * This is the main routine for handling all selected XEvents. It is normally
        !          1236:  * the routine to be registered with the Xtoolkit Event dispatcher. It is
        !          1237:  * currently private and should probably be made public to allow interposition
        !          1238:  * programming techniques
        !          1239: */
        !          1240: static XtEventReturnCode ProcessTextEvent(event, eventdata)
        !          1241:   XEvent *event;
        !          1242:   caddr_t eventdata;
        !          1243: {
        !          1244:     TextContext *ctx = (TextContext *) eventdata;
        !          1245:     XtEventReturnCode returnCode;
        !          1246: 
        !          1247:     if (event->type != DestroyNotify && event->type != FocusIn &&
        !          1248:            event->type != FocusOut && event->type != EnterNotify &&
        !          1249:            event->type != LeaveNotify)
        !          1250:        _XtTextPrepareToUpdate(ctx);
        !          1251:     returnCode = XteventHandled;
        !          1252:     switch (event->type) {
        !          1253:        case ButtonPress:
        !          1254:            if (!ctx->hasfocus)
        !          1255:                XSetInputFocus(ctx->dpy, ctx->w, RevertToPointerRoot,
        !          1256:                               CurrentTime);
        !          1257:            /* Fall through. */
        !          1258:        case ButtonRelease: 
        !          1259:        case MotionNotify: 
        !          1260:        case KeyPress:
        !          1261:            ProcessKeysAndButtons(event, ctx);
        !          1262:            break;
        !          1263:        case ConfigureNotify:
        !          1264:            ctx->width = event->xconfigure.width;
        !          1265:            ctx->height = event->xconfigure.height;
        !          1266:            ForceBuildLineTable(ctx);
        !          1267:            break;
        !          1268:        case Expose:
        !          1269:        case GraphicsExpose:
        !          1270:            ProcessExposeRegion(event, ctx);
        !          1271:            break;
        !          1272:        case DestroyNotify:
        !          1273:            HandleDestroyNotify(ctx);
        !          1274:            return XteventHandled; /* Avoid the call to _XtTextExecuteUpdate!*/
        !          1275:        case FocusIn:
        !          1276:            ctx->hasfocus = TRUE;
        !          1277:            return(returnCode);
        !          1278:        case FocusOut:
        !          1279:            ctx->hasfocus = FALSE;
        !          1280:            return(returnCode);
        !          1281:        case EnterNotify:
        !          1282:        case LeaveNotify:
        !          1283:            ctx->hasfocus = event->xcrossing.focus;
        !          1284:            return(returnCode);
        !          1285:        default: 
        !          1286:            returnCode = XteventNotHandled;
        !          1287:     }
        !          1288:     _XtTextExecuteUpdate(ctx);
        !          1289:     return(returnCode);
        !          1290: }
        !          1291: 
        !          1292: /* Public routines */
        !          1293: 
        !          1294: Window XtTextCreate(dpy, parent, args, argCount)
        !          1295:     Display  *dpy;
        !          1296:     Window   parent;
        !          1297:     ArgList  args;
        !          1298:     int      argCount;
        !          1299: {
        !          1300:     TextContext *ctx;
        !          1301:     XrmNameList        names;
        !          1302:     XrmClassList classes;
        !          1303: 
        !          1304:     /* stuff for scroll bars */
        !          1305:     static Arg scrollMgrArgs[] = {
        !          1306:        {XtNwindow, NULL},
        !          1307:     };
        !          1308: 
        !          1309:     static Arg scrollBarArgs[] = {
        !          1310:        {XtNvalue, NULL},
        !          1311:        {XtNorientation, (XtArgVal) XtorientVertical},
        !          1312:        {XtNscrollUpDownProc, (XtArgVal)ScrollUpDownProc},
        !          1313:        {XtNthumbProc, (XtArgVal)ThumbProc},
        !          1314:     };
        !          1315: 
        !          1316: 
        !          1317:     if (!initialized) TextInitialize();
        !          1318: 
        !          1319:     ctx = (TextContext *) XtMalloc(sizeof(TextContext));
        !          1320:     glob = globinit;
        !          1321:     glob.dpy = dpy;
        !          1322:     XtGetResources(dpy, resources, XtNumber(resources), args, argCount, parent,
        !          1323:                   "text", "Text", &names, &classes);
        !          1324:     *ctx = glob;
        !          1325:     ctx->state = XtSetTextEventBindings(ctx->dpy, ctx->eventTable);
        !          1326:     ctx->lastPos = GETLASTPOS;
        !          1327:     ctx->updateFrom = (XtTextPosition *) XtMalloc(1);
        !          1328:     ctx->updateTo = (XtTextPosition *) XtMalloc(1);
        !          1329:     ctx->numranges = ctx->maxranges = 0;
        !          1330:     if (ctx->height == 0)
        !          1331:        ctx->height = (*(ctx->sink->maxHeight))(ctx->sink, 1) + (2*yMargin) +2;
        !          1332:     if (ctx->w == NULL)
        !          1333:        ctx->w = XCreateSimpleWindow(ctx->dpy, parent, 0, 0,
        !          1334:                         ctx->width, ctx->height,
        !          1335:                         ctx->borderWidth, ctx->border, ctx->background);
        !          1336:     /*
        !          1337:      * Note that if the client passed a window, no checks are made to
        !          1338:      * ensure the size, border, borderWidth and background are consistent
        !          1339:      */
        !          1340:     XtSetNameAndClass(ctx->dpy, ctx->w, names, classes);
        !          1341:     XrmFreeNameList(names);
        !          1342:     XrmFreeClassList(classes);
        !          1343: 
        !          1344:     if (ctx->options & scrollVertical) {
        !          1345:        scrollMgrArgs[0].value =
        !          1346:            scrollBarArgs[0].value = (caddr_t)(ctx->w);
        !          1347:        ctx->outer = 
        !          1348:           XtScrollMgrCreate(ctx->dpy, parent, scrollMgrArgs, XtNumber(scrollMgrArgs));
        !          1349:        ctx->w = XtScrollMgrGetChild(ctx->dpy, ctx->outer);
        !          1350:        ctx->sbar =
        !          1351:            XtScrollMgrAddBar(ctx->dpy, ctx->outer, scrollBarArgs, XtNumber(scrollBarArgs));
        !          1352:        XMapSubwindows(ctx->dpy, ctx->outer);
        !          1353:        (void) XSaveContext(ctx->dpy, ctx->outer, textContext, (caddr_t)ctx);
        !          1354:        (void) XtSetEventHandler(ctx->dpy, ctx->outer, ProcessTextEvent,
        !          1355:         StructureNotifyMask, (caddr_t) ctx);
        !          1356:     }
        !          1357:     (void) XSaveContext(ctx->dpy, ctx->w, textContext, (caddr_t)ctx);
        !          1358:     (void) XtSetEventHandler(ctx->dpy, ctx->w, ProcessTextEvent,
        !          1359:                        ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
        !          1360:                        | KeyPressMask | ExposureMask | StructureNotifyMask
        !          1361:                        | FocusChangeMask | EnterWindowMask | LeaveWindowMask,
        !          1362:                        (caddr_t) ctx);
        !          1363:     ctx->gc = DefaultGC(ctx->dpy, DefaultScreen(ctx->dpy));
        !          1364:     BuildLineTable(ctx, ctx->lt.top);
        !          1365:     if (ctx->outer) return ctx->outer;
        !          1366:     else return ctx->w;
        !          1367: }
        !          1368: 
        !          1369: 
        !          1370: /*
        !          1371:  * This routine allow the application program to Get attributes.
        !          1372:  */
        !          1373: 
        !          1374: void XtTextGetValues(dpy, window, args, argCount)
        !          1375: Display *dpy;
        !          1376: Window window;
        !          1377: ArgList args;
        !          1378: int argCount;
        !          1379: {
        !          1380:     TextContext *ctx;
        !          1381:     if (!XFindContext(dpy, window, textContext, (caddr_t *)&ctx)) {
        !          1382:        glob = *ctx;
        !          1383:        XtGetValues(resources, XtNumber(resources), args, argCount);
        !          1384:     }
        !          1385: }
        !          1386: 
        !          1387: 
        !          1388: /*
        !          1389:  * This routine allow the application program to Set attributes.
        !          1390:  */
        !          1391: 
        !          1392: void XtTextSetValues(dpy, window, args, argCount)
        !          1393: Display *dpy;
        !          1394: Window window;
        !          1395: ArgList args;
        !          1396: int argCount;
        !          1397: {
        !          1398:     TextContext *ctx;
        !          1399:     Boolean    redisplay = FALSE;
        !          1400:     if (XFindContext(dpy, window, textContext, (caddr_t *)&ctx)) return;
        !          1401: 
        !          1402:     _XtTextPrepareToUpdate(ctx);
        !          1403:     glob = *ctx;
        !          1404:     XtSetValues(resources, XtNumber(resources), args, argCount);
        !          1405:     
        !          1406:     if (ctx->sink != glob.sink) {
        !          1407:        ctx->sink = glob.sink;
        !          1408:        redisplay = TRUE;
        !          1409:     }
        !          1410:     if (ctx->source != glob.source) {
        !          1411:         ctx->source = glob.source;
        !          1412:        ForceBuildLineTable(ctx);
        !          1413:        redisplay = TRUE;
        !          1414:     }
        !          1415:     if (ctx->insertPos != glob.insertPos) {
        !          1416:         ctx->insertPos = glob.insertPos;
        !          1417:        ctx->showposition = TRUE;
        !          1418:     }
        !          1419:     if (ctx->lt.top != glob.lt.top) {
        !          1420:        ctx->lt.top = glob.lt.top;
        !          1421:        redisplay = TRUE;
        !          1422:     }
        !          1423:     ctx->s = glob.s;
        !          1424:     ctx->options = glob.options;
        !          1425:     if (ctx->leftmargin != glob.leftmargin) {
        !          1426:        ctx->leftmargin = glob.leftmargin;
        !          1427:        redisplay = TRUE;
        !          1428:     }
        !          1429:     bcopy(glob.sarray, ctx->sarray, sizeof(SelectionArray));
        !          1430:     ctx->background = glob.background;
        !          1431: 
        !          1432:     if (redisplay) 
        !          1433:        DisplayTextWindow(ctx);
        !          1434:     _XtTextExecuteUpdate(ctx);
        !          1435: }
        !          1436: 
        !          1437: 
        !          1438: 
        !          1439: void XtTextDestroy(dpy, w)
        !          1440:     Display *dpy;
        !          1441:     Window w;
        !          1442: {
        !          1443:     TextContext *ctx;
        !          1444: 
        !          1445:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx)) {
        !          1446:        HandleDestroyNotify(ctx);
        !          1447:        XDestroyWindow(ctx->dpy, w);
        !          1448:     }
        !          1449: }
        !          1450: 
        !          1451: void XtTextDisplay (dpy, w)
        !          1452:     Display *dpy;
        !          1453:     Window w;
        !          1454: {
        !          1455:     TextContext *ctx;
        !          1456: 
        !          1457:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx)) {
        !          1458:        _XtTextPrepareToUpdate(ctx);
        !          1459:        DisplayTextWindow(ctx);
        !          1460:        _XtTextExecuteUpdate(ctx);
        !          1461:     }
        !          1462: }
        !          1463: 
        !          1464: /*******************************************************************
        !          1465: The following routines provide procedural interfaces to Text window state
        !          1466: setting and getting. They need to be redone so than the args code can use
        !          1467: them. I suggest we create a complete set that takes the context as an
        !          1468: argument and then have the public version lookup the context and call the
        !          1469: internal one. The major value of this set is that they have actual application
        !          1470: clients and therefore the functionality provided is required for any future
        !          1471: version of Text.
        !          1472: ********************************************************************/
        !          1473: 
        !          1474: void XtTextSetSelectionArray(dpy, w, sarray)
        !          1475:     Display *dpy;
        !          1476:     Window w;
        !          1477:     XtSelectType *sarray;
        !          1478: {
        !          1479:     TextContext *ctx;
        !          1480:     XtSelectType *s2;
        !          1481:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx)) {
        !          1482:        s2 = ctx->sarray;
        !          1483:        while (XtselectNull != (*s2++ = *sarray++)) ;
        !          1484:     }
        !          1485: }
        !          1486: 
        !          1487: void XtTextSetLastPos (dpy, w, lastPos)
        !          1488:     Display *dpy;
        !          1489:   Window w;
        !          1490:   XtTextPosition lastPos;
        !          1491: {
        !          1492:     TextContext * ctx;
        !          1493: 
        !          1494:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx)) {
        !          1495:        _XtTextPrepareToUpdate(ctx);
        !          1496:        (*(ctx->source->setLastPos))(ctx->source, lastPos);
        !          1497:        ctx->lastPos = GETLASTPOS;
        !          1498:        ForceBuildLineTable(ctx);
        !          1499:        DisplayTextWindow(ctx);
        !          1500:        _XtTextExecuteUpdate(ctx);
        !          1501:     }
        !          1502: }
        !          1503: 
        !          1504: 
        !          1505: void XtTextGetSelectionPos(dpy, w, left, right)
        !          1506:   Display *dpy;
        !          1507:   Window w;
        !          1508:   XtTextPosition *left, *right;
        !          1509: {
        !          1510:     TextContext *ctx;
        !          1511:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx)){
        !          1512:        *left = ctx->s.left;
        !          1513:        *right = ctx->s.right;
        !          1514:     }
        !          1515: }
        !          1516: 
        !          1517: 
        !          1518: void XtTextNewSource(dpy, w, source, startPos)
        !          1519:     Display       *dpy;
        !          1520:     Window        w;
        !          1521:     XtTextSource   *source;
        !          1522:     XtTextPosition startPos;
        !          1523: {
        !          1524:     TextContext *ctx;
        !          1525: 
        !          1526:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx)) {
        !          1527:        ctx->source = source;
        !          1528:        ctx->lt.top = startPos;
        !          1529:        ctx->s.left = ctx->s.right = 0;
        !          1530:        ctx->insertPos = startPos;
        !          1531:        ctx->lastPos = GETLASTPOS;
        !          1532:        ForceBuildLineTable(ctx);
        !          1533:        _XtTextPrepareToUpdate(ctx);
        !          1534:        DisplayTextWindow(ctx);
        !          1535:        _XtTextExecuteUpdate(ctx);
        !          1536:     }
        !          1537: }
        !          1538: 
        !          1539: /*
        !          1540:  * This public routine deletes the text from startPos to endPos in a source and
        !          1541:  * then inserts, at startPos, the text that was passed. As a side effect it
        !          1542:  * "invalidates" that portion of the displayed text (if any), so that things
        !          1543:  * will be repainted properly.
        !          1544:  */
        !          1545: int XtTextReplace(dpy, w, startPos, endPos, text)
        !          1546:     Display        *dpy;
        !          1547:     Window         w;
        !          1548:     XtTextPosition  startPos, endPos;
        !          1549:     XtTextBlock     *text;
        !          1550: {
        !          1551:     TextContext *ctx;
        !          1552:     int result;
        !          1553:     result = EDITERROR;
        !          1554:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx)) {
        !          1555:        _XtTextPrepareToUpdate(ctx);
        !          1556:        result = ReplaceText(ctx, startPos, endPos, text);
        !          1557:        _XtTextExecuteUpdate(ctx);
        !          1558:     }
        !          1559:     return result;
        !          1560: }
        !          1561: 
        !          1562: 
        !          1563: XtTextPosition XtTextTopPosition(dpy, w)
        !          1564:     Display *dpy;
        !          1565:     Window w;
        !          1566: {
        !          1567:     TextContext *ctx;
        !          1568: 
        !          1569:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx))
        !          1570:         return ctx->lt.top;
        !          1571:     return 0;
        !          1572: }
        !          1573: 
        !          1574: 
        !          1575: void XtTextSetInsertionPoint(dpy, w, position)
        !          1576:     Display       *dpy;
        !          1577:     Window        w;
        !          1578:     XtTextPosition position;
        !          1579: {
        !          1580:     TextContext *ctx;
        !          1581: 
        !          1582:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx)) {
        !          1583:        _XtTextPrepareToUpdate(ctx);
        !          1584:        ctx->insertPos = position;
        !          1585:        ctx->showposition = TRUE;
        !          1586:        _XtTextExecuteUpdate(ctx);
        !          1587:     }
        !          1588: }
        !          1589: 
        !          1590: 
        !          1591: XtTextPosition XtTextGetInsertionPoint(dpy, w)
        !          1592:     Display       *dpy;
        !          1593:     Window w;
        !          1594: {
        !          1595:     XtTextPosition position;
        !          1596:     TextContext *ctx;
        !          1597: 
        !          1598:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx)) {
        !          1599:         position = ctx->insertPos;
        !          1600:     } else {
        !          1601:         position = 0;
        !          1602:     }
        !          1603:     return(position);
        !          1604: }
        !          1605: 
        !          1606: 
        !          1607: void XtTextUnsetSelection(dpy, w)
        !          1608:     Display       *dpy;
        !          1609:     Window w;
        !          1610: {
        !          1611:     TextContext *ctx;
        !          1612: 
        !          1613:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx)) {
        !          1614:        _XtTextPrepareToUpdate(ctx);
        !          1615:        _XtTextSetNewSelection(ctx, zeroPosition, zeroPosition);
        !          1616:        _XtTextExecuteUpdate(ctx);
        !          1617:     }
        !          1618: }
        !          1619: 
        !          1620: 
        !          1621: void XtTextChangeOptions(dpy, w, options)
        !          1622:     Display       *dpy;
        !          1623:   Window w;
        !          1624:   int    options;
        !          1625: {
        !          1626:     TextContext *ctx;
        !          1627: 
        !          1628:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx))
        !          1629:        ctx->options = options;
        !          1630: }
        !          1631: 
        !          1632: 
        !          1633: int XtTextGetOptions(dpy, w)
        !          1634:     Display       *dpy;
        !          1635:   Window w;
        !          1636: {
        !          1637:     TextContext *ctx;
        !          1638: 
        !          1639:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx))
        !          1640:        return ctx->options;
        !          1641:         else return 0;
        !          1642: }
        !          1643: 
        !          1644: void XtTextSetNewSelection (dpy, w, left, right)
        !          1645:     Display       *dpy;
        !          1646:     Window        w;
        !          1647:     XtTextPosition left, right;
        !          1648: {
        !          1649:     TextContextPtr ctx;
        !          1650: 
        !          1651:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx)){
        !          1652:        _XtTextPrepareToUpdate(ctx);
        !          1653:         _XtTextSetNewSelection(ctx, left, right);
        !          1654:        _XtTextExecuteUpdate(ctx);
        !          1655:     }
        !          1656: }
        !          1657: 
        !          1658: void XtTextInvalidate(dpy, w, from, to)
        !          1659:     Display       *dpy;
        !          1660:     Window        w;
        !          1661:     XtTextPosition from,to;
        !          1662: {
        !          1663:     TextContextPtr ctx;
        !          1664: 
        !          1665:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx)) {
        !          1666:         ctx->lastPos = (*(ctx->source->getLastPos))(ctx->source);
        !          1667:         _XtTextPrepareToUpdate(ctx);
        !          1668:         _XtTextNeedsUpdating(ctx, from, to);
        !          1669:         ForceBuildLineTable(ctx);
        !          1670:         _XtTextExecuteUpdate(ctx);
        !          1671:     }
        !          1672: }
        !          1673: 
        !          1674: 
        !          1675: /* Returns the window actually containing the text (which is not the same
        !          1676:    as the given window if the text window has scrollbars.) */
        !          1677: 
        !          1678: Window XtTextGetInnerWindow(dpy, w)
        !          1679: Display *dpy;
        !          1680: Window w;
        !          1681: {
        !          1682:     TextContextPtr ctx;
        !          1683:     if (!XFindContext(dpy, w, textContext, (caddr_t *)&ctx)) {
        !          1684:        return ctx->w;
        !          1685:     }
        !          1686: }

unix.superglobalmegacorp.com

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