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