Annotation of researchv9/X11/src/X.V11R1/lib/Xtk/Text.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char rcsid[] = "$Header: Text.c,v 1.4 87/09/13 23:32:44 newman Exp $";
                      3: #endif lint
                      4: 
                      5: /*
                      6:  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
                      7:  * 
                      8:  *                         All Rights Reserved
                      9:  * 
                     10:  * Permission to use, copy, modify, and distribute this software and its 
                     11:  * documentation for any purpose and without fee is hereby granted, 
                     12:  * provided that the above copyright notice appear in all copies and that
                     13:  * both that copyright notice and this permission notice appear in 
                     14:  * supporting documentation, and that the name of Digital Equipment
                     15:  * Corporation not be used in advertising or publicity pertaining to
                     16:  * distribution of the software without specific, written prior permission.  
                     17:  * 
                     18:  * 
                     19:  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
                     20:  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
                     21:  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
                     22:  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
                     23:  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
                     24:  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                     25:  * SOFTWARE.
                     26:  */
                     27: /* File: Text.c */
                     28: 
                     29: #include "Intrinsic.h"
                     30: #include "Text.h"
                     31: #include "TextP.h"
                     32: #include "Scroll.h"
                     33: #include "Atoms.h"
                     34: #include <sys/file.h>
                     35: #include <X11/Xutil.h>
                     36: #include <strings.h>
                     37: 
                     38: extern void bcopy();
                     39: 
                     40: #define BufMax 1000
                     41: #define abs(x) (((x) < 0) ? (-(x)) : (x))
                     42: #define min(x,y)       ((x) < (y) ? (x) : (y))
                     43: #define max(x,y)       ((x) > (y) ? (x) : (y))
                     44: #define GETLASTPOS  (*(ctx->text.source->scan)) (ctx->text.source, 0, XtstFile, XtsdRight, 1, TRUE)
                     45: #define BUTTONMASK 0x143d
                     46: 
                     47: #define  yMargin 2
                     48: #define zeroPosition ((XtTextPosition) 0)
                     49: 
                     50: extern void BuildLineTable ();
                     51: 
                     52: /****************************************************************
                     53:  *
                     54:  * Full class record constant
                     55:  *
                     56:  ****************************************************************/
                     57: 
                     58: extern caddr_t defaultTextTranslations;
                     59: 
                     60: static XtResource resources[] = {
                     61:     {XtNtextOptions, XtCTextOptions, XrmRInt, sizeof (int),
                     62:         XtOffset(TextWidget, text.options), XrmRString, "0"},
                     63:     {XtNdisplayPosition, XtCTextPosition, XrmRInt,
                     64:         sizeof (XtTextPosition), XtOffset(TextWidget, text.lt.top), 
                     65:         XrmRString, "0"},
                     66:     {XtNinsertPosition, XtCTextPosition, XtRInt, 
                     67:         sizeof(XtTextPosition), XtOffset(TextWidget, text.insertPos), 
                     68:        XrmRString, "0"},
                     69:     {XtNleftMargin, XtCMargin, XrmRInt, sizeof (int), 
                     70:         XtOffset(TextWidget, text.leftmargin), XrmRString, "2"},
                     71:     {XtNselectionArray, XtCSelectionArray, XrmRPointer, 
                     72:         sizeof(SelectionArray), XtOffset(TextWidget, text.sarray), 
                     73:        XrmRPointer, NULL},
                     74:     {XtNtextSource, XtCTextSource, XrmRPointer, sizeof (caddr_t), 
                     75:          XtOffset(TextWidget, text.source), XrmRPointer, NULL},
                     76:     {XtNtextSink, XtCTextSink, XrmRPointer, sizeof (caddr_t),
                     77:          XtOffset(TextWidget, text.sink), XrmRPointer, NULL},
                     78:     {XtNselection, XtCSelection, XrmRPointer, sizeof(caddr_t),
                     79:         XtOffset(TextWidget, text.s), XrmRPointer, NULL},
                     80:     {XtNeventBindings, XtCEventBindings, XtRStringTable, 
                     81:         sizeof(_XtTranslations), XtOffset(TextWidget, core.translations), 
                     82:        XtRStringTable, (caddr_t)&defaultTextTranslations},
                     83: };
                     84: 
                     85:   
                     86: static void Initialize(request, new)
                     87:  Widget request, new;
                     88: {
                     89:     TextWidget ctx = (TextWidget) new;
                     90: 
                     91:     if (ctx->core.width == 0)
                     92:        ctx->core.width = 200;
                     93:     if (ctx->core.height == 0)
                     94:        ctx->core.height = 200;
                     95: 
                     96:     ctx->text.lt.lines = 0;
                     97:     ctx->text.lt.info = NULL;
                     98:     ctx->text.s.left = ctx->text.s.right = 0;
                     99:     ctx->text.s.type = XtselectPosition;
                    100:     ctx->text.sbar = ctx->text.outer = NULL;
                    101:     ctx->text.sarray[0] = XtselectPosition;
                    102:     ctx->text.sarray[1] = XtselectWord;
                    103:     ctx->text.sarray[2] = XtselectLine;
                    104:     ctx->text.sarray[3] = XtselectParagraph;
                    105:     ctx->text.sarray[4] = XtselectAll;
                    106:     ctx->text.sarray[5] = XtselectNull;
                    107:     ctx->text.showposition = TRUE;
                    108:     ctx->text.lastPos = GETLASTPOS;
                    109:     ctx->text.dialog = NULL;
                    110:     ctx->text.updateFrom = (XtTextPosition *) XtMalloc(1);
                    111:     ctx->text.updateTo = (XtTextPosition *) XtMalloc(1);
                    112:     ctx->text.numranges = ctx->text.maxranges = 0;
                    113:     ctx->text.gc = DefaultGCOfScreen(XtScreen(ctx));
                    114:     BuildLineTable(ctx, ctx->text.lt.top);
                    115: /* what about this ugly scrollbar stuff?
                    116:     if (ctx->text.options & scrollVertical) {
                    117:        scrollMgrArgs[0].value =
                    118:            scrollBarArgs[0].value = (caddr_t)(XtWindow(ctx));
                    119:        ctx->text.outer = 
                    120:           XtScrollMgrCreate(ctx->core.display, parent, scrollMgrArgs, XtNumber(scrollMgrArgs));
                    121:        XtWindow(ctx) = XtScrollMgrGetChild(ctx->core.display, ctx->text.outer);
                    122:        ctx->text.sbar =
                    123:            XtCreateWidget("scrollbar", scrollbarWidgetClass, ctx->text.outer,
                    124:               scrollBarArgs, XtNumber(scrollBarArgs));
                    125:        XMapSubwindows(ctx->core.display, ctx->text.outer);
                    126:        (void) XtSetEventHandler(ctx->core.display, ctx->text.outer, ProcessTextEvent,
                    127:         StructureNotifyMask, (caddr_t) ctx);
                    128:     }
                    129: */
                    130: }
                    131: 
                    132: static void Realize( w, valueMask, attributes )
                    133:    Widget w;
                    134:    Mask valueMask;
                    135:    XSetWindowAttributes *attributes;
                    136: {
                    137:    TextWidget ctx = (TextWidget)w;
                    138:    if (ctx->text.sbar) XtRealizeWidget(ctx->text.sbar);
                    139:    ctx->core.window = 
                    140:           XCreateWindow(
                    141:                 XtDisplay(w), w->core.parent->core.window,
                    142:                 w->core.x, w->core.y,
                    143:                 w->core.width, w->core.height, w->core.border_width,
                    144:                 w->core.depth, InputOutput, (Visual *)CopyFromParent,
                    145:                 valueMask, attributes);
                    146: }
                    147: 
                    148: /* Utility routines for support of Text */
                    149: 
                    150: 
                    151: /*
                    152:  * Procedure to manage insert cursor visibility for editable text.  It uses
                    153:  * the value of ctx->insertPos and an implicit argument. In the event that
                    154:  * position is immediately preceded by an eol graphic, then the insert cursor
                    155:  * is displayed at the beginning of the next line.
                    156: */
                    157: static void InsertCursor (ctx, state)
                    158:   TextWidget ctx;
                    159:   InsertState state;
                    160: {
                    161:     Position x, y;
                    162:     int dy, line, visible;
                    163:     XtTextBlock text;
                    164: 
                    165:     if (ctx->text.lt.lines < 1) return;
                    166:     visible = LineAndXYForPosition(ctx, ctx->text.insertPos, &line, &x, &y);
                    167:     if (line < ctx->text.lt.lines)
                    168:        dy = (ctx->text.lt.info[line + 1].y - ctx->text.lt.info[line].y) + 1;
                    169:     else
                    170:        dy = (ctx->text.lt.info[line].y - ctx->text.lt.info[line - 1].y) + 1;
                    171: 
                    172:     /** If the insert position is just after eol then put it on next line **/
                    173:     if (x > ctx->text.leftmargin &&
                    174:        ctx->text.insertPos > 0 &&
                    175:        ctx->text.insertPos >= ctx->text.lastPos) {
                    176:           /* reading the source is bogus and this code should use scan */
                    177:           (*(ctx->text.source->read)) (ctx->text.source, ctx->text.insertPos - 1, &text, 1);
                    178:           if (text.ptr[0] == '\n') {
                    179:               x = ctx->text.leftmargin;
                    180:               y += dy;
                    181:           }
                    182:     }
                    183:     y += dy;
                    184:     if (visible)
                    185:        (*(ctx->text.sink->insertCursor))(ctx, x, y, state);
                    186: }
                    187: 
                    188: 
                    189: /*
                    190:  * Procedure to register a span of text that is no longer valid on the display
                    191:  * It is used to avoid a number of small, and potentially overlapping, screen
                    192:  * updates. [note: this is really a private procedure but is used in
                    193:  * multiple modules].
                    194: */
                    195: _XtTextNeedsUpdating(ctx, left, right)
                    196:   TextWidget ctx;
                    197:   XtTextPosition left, right;
                    198: {
                    199:     int     i;
                    200:     if (left < right) {
                    201:        for (i = 0; i < ctx->text.numranges; i++) {
                    202:            if (left <= ctx->text.updateTo[i] && right >= ctx->text.updateFrom[i]) {
                    203:                ctx->text.updateFrom[i] = min(left, ctx->text.updateFrom[i]);
                    204:                ctx->text.updateTo[i] = max(right, ctx->text.updateTo[i]);
                    205:                return;
                    206:            }
                    207:        }
                    208:        ctx->text.numranges++;
                    209:        if (ctx->text.numranges > ctx->text.maxranges) {
                    210:            ctx->text.maxranges = ctx->text.numranges;
                    211:            i = ctx->text.maxranges * sizeof(XtTextPosition);
                    212:            ctx->text.updateFrom = (XtTextPosition *) 
                    213:                XtRealloc((char *)ctx->text.updateFrom, (unsigned) i);
                    214:            ctx->text.updateTo = (XtTextPosition *) 
                    215:                XtRealloc((char *)ctx->text.updateTo, (unsigned) i);
                    216:        }
                    217:        ctx->text.updateFrom[ctx->text.numranges - 1] = left;
                    218:        ctx->text.updateTo[ctx->text.numranges - 1] = right;
                    219:     }
                    220: }
                    221: 
                    222: 
                    223: /*
                    224:  * Procedure to read a span of text in Ascii form. This is purely a hack and
                    225:  * we probably need to add a function to sources to provide this functionality.
                    226:  * [note: this is really a private procedure but is used in multiple modules].
                    227: */
                    228: char *_XtTextGetText(ctx, left, right)
                    229:   TextWidget ctx;
                    230:   XtTextPosition left, right;
                    231: {
                    232:     char   *result, *tempResult;
                    233:     int length, resultLength;
                    234:     XtTextBlock text;
                    235:     XtTextPosition end, nend;
                    236:     
                    237:     resultLength = right - left + 10;  /* Bogus? %%% */
                    238:     result = (char *)XtMalloc((unsigned) resultLength);
                    239:     end = (*(ctx->text.source->read))(ctx->text.source, left, &text, right - left);
                    240:     (void) strncpy(result, text.ptr, text.length);
                    241:     length = text.length;
                    242:     while (end < right) {
                    243:         nend = (*(ctx->text.source->read))(ctx->text.source, end, &text, right - end);
                    244:        tempResult = result + length;
                    245:         (void) strncpy(tempResult, text.ptr, text.length);
                    246:        length += text.length;
                    247:         end = nend;
                    248:     }
                    249:     result[length] = 0;
                    250:     return result;
                    251: }
                    252: 
                    253: 
                    254: 
                    255: /* 
                    256:  * This routine maps an x and y position in a window that is displaying text
                    257:  * into the corresponding position in the source.
                    258:  */
                    259: static XtTextPosition PositionForXY (ctx, x, y)
                    260:   TextWidget ctx;
                    261:   Position x,y;
                    262: {
                    263:  /* it is illegal to call this routine unless there is a valid line table! */
                    264:     int     width, fromx, line;
                    265:     XtTextPosition position, resultstart, resultend;
                    266: 
                    267:     /*** figure out what line it is on ***/
                    268:     for (line = 0; line < ctx->text.lt.lines - 1; line++) {
                    269:        if (y <= ctx->text.lt.info[line + 1].y)
                    270:            break;
                    271:     }
                    272:     position = ctx->text.lt.info[line].position;
                    273:     if (position >= ctx->text.lastPos)
                    274:        return ctx->text.lastPos;
                    275:     fromx = ctx->text.lt.info[line].x; /* starting x in line */
                    276:     width = x - fromx;                 /* num of pix from starting of line */
                    277:     (*(ctx->text.sink->resolve)) (ctx, position, fromx, width,
                    278:            &resultstart, &resultend);
                    279:     if (resultstart >= ctx->text.lt.info[line + 1].position)
                    280:        resultstart = (*(ctx->text.source->scan))(ctx->text.source,
                    281:                ctx->text.lt.info[line + 1].position, XtstPositions, XtsdLeft, 1, TRUE);
                    282:     return resultstart;
                    283: }
                    284: 
                    285: /*
                    286:  * This routine maps a source position in to the corresponding line number
                    287:  * of the text that is displayed in the window.
                    288: */
                    289: int LineForPosition (ctx, position)
                    290:   TextWidget ctx;
                    291:   XtTextPosition position;
                    292:   /* it is illegal to call this routine unless there is a valid line table!*/
                    293: {
                    294:     int     line;
                    295: 
                    296:     if (position <= ctx->text.lt.info[0].position)
                    297:        return 0;
                    298:     for (line = 0; line < ctx->text.lt.lines; line++)
                    299:        if (position < ctx->text.lt.info[line + 1].position)
                    300:            break;
                    301:     return line;
                    302: }
                    303: 
                    304: /*
                    305:  * This routine maps a source position into the corresponding line number
                    306:  * and the x, y coordinates of the text that is displayed in the window.
                    307: */
                    308: static int LineAndXYForPosition (ctx, pos, line, x, y)
                    309:   TextWidget ctx;
                    310:   XtTextPosition pos;
                    311:   int *line;
                    312:   Position *x, *y;
                    313:   /* it is illegal to call this routine unless there is a valid line table!*/
                    314: {
                    315:     XtTextPosition linePos, endPos;
                    316:     int     visible, realW, realH;
                    317: 
                    318:     *line = 0;
                    319:     *x = ctx->text.leftmargin;
                    320:     *y = yMargin;
                    321:     visible = IsPositionVisible(ctx, pos);
                    322:     if (visible) {
                    323:        *line = LineForPosition(ctx, pos);
                    324:        *y = ctx->text.lt.info[*line].y;
                    325:        *x = ctx->text.lt.info[*line].x;
                    326:        linePos = ctx->text.lt.info[*line].position;
                    327:        (*(ctx->text.sink->findDistance))(ctx, linePos,
                    328:                                      *x, pos, &realW, &endPos, &realH);
                    329:        *x = *x + realW;
                    330:     }
                    331:     return visible;
                    332: }
                    333: 
                    334: /*
                    335:  * This routine builds a line table. It does this by starting at the
                    336:  * specified position and measuring text to determine the staring position
                    337:  * of each line to be displayed. It also determines and saves in the
                    338:  * linetable all the required metrics for displaying a given line (e.g.
                    339:  * x offset, y offset, line length, etc.).
                    340: */
                    341: static void BuildLineTable (ctx, position)
                    342:   TextWidget ctx;
                    343:   XtTextPosition position;
                    344: {
                    345:     Position x, y;
                    346:     Dimension width, realW, realH;
                    347:     int line, lines;
                    348:     XtTextPosition startPos, endPos;
                    349:     Boolean     rebuild;
                    350: 
                    351:     rebuild = (Boolean) (position != ctx->text.lt.top);
                    352:     lines = (*(ctx->text.sink->maxLines))(ctx, ctx->core.height);
                    353:     if (ctx->text.lt.info != NULL && lines != ctx->text.lt.lines) {
                    354:        XtFree((char *) ctx->text.lt.info);
                    355:        ctx->text.lt.info = NULL;
                    356:     }
                    357:     if (ctx->text.lt.info == NULL) {
                    358:        ctx->text.lt.info = (LineTableEntry *)
                    359:            XtMalloc((unsigned)sizeof(LineTableEntry) * (lines + 1));
                    360:        for (line = 0; line < lines; line++) {
                    361:            ctx->text.lt.info[line].position = 0;
                    362:            ctx->text.lt.info[line].y = 0;
                    363:        }
                    364:        rebuild = TRUE;
                    365:     }
                    366:     else
                    367:        lines = ctx->text.lt.lines;
                    368:     if (rebuild) {
                    369:        ctx->text.lt.top = position;
                    370:        ctx->text.lt.lines = lines;
                    371:        startPos = position;
                    372:        y = yMargin;
                    373:        for (line = 0; line <= ctx->text.lt.lines; line++) {
                    374:            x = ctx->text.leftmargin;
                    375:            ctx->text.lt.info[line].x = x;
                    376:            ctx->text.lt.info[line].y = y;
                    377:            ctx->text.lt.info[line].position = startPos;
                    378:            if (startPos <= ctx->text.lastPos) {
                    379:                width = (ctx->text.options & resizeWidth) ? 9999 : ctx->core.width - x;
                    380:                (*(ctx->text.sink->findPosition))(ctx, 
                    381:                         startPos, x,
                    382:                        width, (ctx->text.options & wordBreak),
                    383:                        &endPos, &realW, &realH);
                    384:                if (!(ctx->text.options & wordBreak) && endPos < ctx->text.lastPos) {
                    385:                    endPos = (*(ctx->text.source->scan))(ctx->text.source, startPos,
                    386:                            XtstEOL, XtsdRight, 1, TRUE);
                    387:                    if (endPos == startPos)
                    388:                        endPos = ctx->text.lastPos + 1;
                    389:                }
                    390:                ctx->text.lt.info[line].endX = realW + x;
                    391:                startPos = endPos;
                    392:            }
                    393:            else ctx->text.lt.info[line].endX = x;
                    394:            y = y + realH;
                    395:        }
                    396:     }
                    397: }
                    398: 
                    399: /*
                    400:  * This routine is used to re-display the entire window, independent of
                    401:  * its current state.
                    402: */
                    403: void ForceBuildLineTable(ctx)
                    404:     TextWidget ctx;
                    405: {
                    406:     XtTextPosition position;
                    407: 
                    408:     position = ctx->text.lt.top;
                    409:     ctx->text.lt.top++; /* ugly, but it works */
                    410:     BuildLineTable(ctx, position);
                    411: }
                    412: 
                    413: /*
                    414:  * This routine is used by Text to notify an associated scrollbar of the
                    415:  * correct metrics (position and shown fraction) for the text being currently
                    416:  * displayed in the window.
                    417: */
                    418: static void SetScrollBar(ctx)
                    419:     TextWidget ctx;
                    420: {
                    421:     float   first, last;
                    422:     if (ctx->text.sbar) {
                    423:        if ((ctx->text.lastPos > 0)  &&  (ctx->text.lt.lines > 0)) {
                    424:            first = ctx->text.lt.top;
                    425:            first /= ctx->text.lastPos; 
                    426:                                        /* Just an approximation */
                    427:            last = ctx->text.lt.info[ctx->text.lt.lines].position;
                    428:            last /= ctx->text.lastPos;
                    429:        }
                    430:        else {
                    431:            first = 0.0;
                    432:            last = 1.0;
                    433:        }
                    434:        XtScrollBarSetThumb(ctx->text.sbar, first, last - first);
                    435:     }
                    436: }
                    437: 
                    438: 
                    439: /*
                    440:  * The routine will scroll the displayed text by lines.  If the arg  is
                    441:  * positive, move up; otherwise, move down. [note: this is really a private
                    442:  * procedure but is used in multiple modules].
                    443: */
                    444: _XtTextScroll(ctx, n)
                    445:   TextWidget ctx;
                    446:   int n;
                    447: {
                    448:     XtTextPosition top, target;
                    449:     if (n >= 0) {
                    450:        top = min(ctx->text.lt.info[n].position, ctx->text.lastPos);
                    451:        BuildLineTable(ctx, top);
                    452:        if (top >= ctx->text.lastPos)
                    453:            DisplayTextWindow(ctx);
                    454:        else {
                    455:            XCopyArea(XtDisplay(ctx), XtWindow(ctx), XtWindow(ctx), ctx->text.gc,
                    456:                      0, ctx->text.lt.info[n].y,
                    457:                      9999, (Dimension)ctx->core.height - ctx->text.lt.info[n].y,
                    458:                      0, ctx->text.lt.info[0].y);
                    459:            (*(ctx->text.sink->clearToBackground))(ctx, 0,
                    460:                ctx->text.lt.info[0].y + ctx->core.height - ctx->text.lt.info[n].y,
                    461:                9999, 9999);
                    462:            if (n < ctx->text.lt.lines) n++;
                    463:            _XtTextNeedsUpdating(ctx,
                    464:                    ctx->text.lt.info[ctx->text.lt.lines - n].position, ctx->text.lastPos);
                    465:            SetScrollBar(ctx);
                    466:        }
                    467:     } else {
                    468:        Dimension tempHeight;
                    469:        n = -n;
                    470:        target = ctx->text.lt.top;
                    471:        top = (*(ctx->text.source->scan))(ctx->text.source, target, XtstEOL,
                    472:                                     XtsdLeft, n+1, FALSE);
                    473:        tempHeight = ctx->text.lt.info[ctx->text.lt.lines-n].y;
                    474:        BuildLineTable(ctx, top);
                    475:        if (ctx->text.lt.info[n].position == target) {
                    476:            XCopyArea(XtDisplay(ctx), XtWindow(ctx), XtWindow(ctx), ctx->text.gc,
                    477:                      0, ctx->text.lt.info[0].y, 9999, tempHeight,
                    478:                      0, ctx->text.lt.info[n].y);
                    479:            _XtTextNeedsUpdating(ctx, 
                    480:                    ctx->text.lt.info[0].position, ctx->text.lt.info[n].position);
                    481:            SetScrollBar(ctx);
                    482:        } else if (ctx->text.lt.top != target) DisplayTextWindow(ctx);
                    483:     }
                    484: }
                    485: 
                    486: /*
                    487:  * The routine will scroll the displayed text by pixels.  If the arg is
                    488:  * positive, move up; otherwise, move down.
                    489: */
                    490: /*ARGSUSED*/ /* keep lint happy */
                    491: static int ScrollUpDownProc (w, data, pix)
                    492:   Widget w;
                    493:   int data;
                    494:   int pix;
                    495: {
                    496:     TextWidget ctx = (TextWidget)w;
                    497:     int     apix, line;
                    498:     _XtTextPrepareToUpdate(ctx);
                    499:     apix = abs(pix);
                    500:     for (line = 1;
                    501:            line < ctx->text.lt.lines && apix > ctx->text.lt.info[line + 1].y;
                    502:            line++);
                    503:     if (pix >= 0)
                    504:        _XtTextScroll(ctx, line);
                    505:     else
                    506:        _XtTextScroll(ctx, -line);
                    507:     _XtTextExecuteUpdate(ctx);
                    508: }
                    509: 
                    510: /*
                    511:  * The routine "thumbs" the displayed text. Thumbing means reposition the
                    512:  * displayed view of the source to a new position determined by a fraction
                    513:  * of the way from beginning to end. Ideally, this should be determined by
                    514:  * the number of displayable lines in the source. This routine does it as a
                    515:  * fraction of the first position and last position and then normalizes to
                    516:  * the start of the line containing the position.
                    517: */
                    518: /*ARGSUSED*/ /* keep lint happy */
                    519: static int ThumbProc (w, data, where)
                    520:   Widget w;
                    521:   int data;
                    522:   float where;
                    523:   /* BUG/deficiency: The normalize to line portion of this routine will
                    524:    * cause thumbing to always position to the start of the source.
                    525:    */
                    526: {
                    527:   
                    528:     TextWidget ctx= (TextWidget)w;
                    529:     XtTextPosition position;
                    530:     _XtTextPrepareToUpdate(ctx);
                    531:     position = where * ctx->text.lastPos;
                    532:     position = (*(ctx->text.source->scan))(ctx->text.source, position, XtstEOL, XtsdLeft,
                    533:            1, FALSE);
                    534:     BuildLineTable(ctx, position);
                    535:     DisplayTextWindow(ctx);
                    536:     _XtTextExecuteUpdate(ctx);
                    537: }
                    538: 
                    539: 
                    540: int _XtTextSetNewSelection(ctx, left, right)
                    541:   TextWidget ctx;
                    542:   XtTextPosition left, right;
                    543: {
                    544:     XtTextPosition pos;
                    545: 
                    546:     if (left < ctx->text.s.left) {
                    547:        pos = min(right, ctx->text.s.left);
                    548:        _XtTextNeedsUpdating(ctx, left, pos);
                    549:     }
                    550:     if (left > ctx->text.s.left) {
                    551:        pos = min(left, ctx->text.s.right);
                    552:        _XtTextNeedsUpdating(ctx, ctx->text.s.left, pos);
                    553:     }
                    554:     if (right < ctx->text.s.right) {
                    555:        pos = max(right, ctx->text.s.left);
                    556:        _XtTextNeedsUpdating(ctx, pos, ctx->text.s.right);
                    557:     }
                    558:     if (right > ctx->text.s.right) {
                    559:        pos = max(left, ctx->text.s.right);
                    560:        _XtTextNeedsUpdating(ctx, pos, right);
                    561:     }
                    562: 
                    563:     ctx->text.s.left = left;
                    564:     ctx->text.s.right = right;
                    565: }
                    566: 
                    567: 
                    568: 
                    569: /*
                    570:  * This internal routine deletes the text from pos1 to pos2 in a source and
                    571:  * then inserts, at pos1, the text that was passed. As a side effect it
                    572:  * "invalidates" that portion of the displayed text (if any).
                    573: */
                    574: int ReplaceText (ctx, pos1, pos2, text)
                    575:   TextWidget ctx;
                    576:   XtTextPosition pos1, pos2;
                    577:   XtTextBlock *text;
                    578: 
                    579:  /* it is illegal to call this routine unless there is a valid line table!*/
                    580: {
                    581:     int i, line1, line2, visible, delta, error;
                    582:     Position x, y;
                    583:     Dimension realW, realH, width;
                    584:     XtTextPosition startPos, endPos, updateFrom;
                    585: 
                    586:     /* the insertPos may not always be set to the right spot in XttextAppend */
                    587:     if ((pos1 == ctx->text.insertPos) && 
                    588:         ((*(ctx->text.source->editType))(ctx->text.source) == XttextAppend)) {
                    589:       ctx->text.insertPos = GETLASTPOS;
                    590:       pos2 = pos2 - pos1 + ctx->text.insertPos;
                    591:       pos1 = ctx->text.insertPos;
                    592:     }
                    593:     updateFrom = (*(ctx->text.source->scan))(ctx->text.source, pos1, XtstWhiteSpace, XtsdLeft,
                    594:            1, TRUE);
                    595:     updateFrom = (*(ctx->text.source->scan))(ctx->text.source, updateFrom, XtstPositions, XtsdLeft,
                    596:            1, TRUE);
                    597:     startPos = max(updateFrom, ctx->text.lt.top);
                    598:     visible = LineAndXYForPosition(ctx, startPos, &line1, &x, &y);
                    599:     error = (*(ctx->text.source->replace))(ctx->text.source, pos1, pos2, text, &delta);
                    600:     if (error) return error;
                    601:     ctx->text.lastPos = GETLASTPOS;
                    602:     if (ctx->text.lt.top >= ctx->text.lastPos) {
                    603:        BuildLineTable(ctx, ctx->text.lastPos);
                    604:        ClearWindow(ctx);
                    605:        SetScrollBar(ctx);
                    606:        return error;
                    607:     }
                    608:     if (delta < ctx->text.lastPos) {
                    609:        for (i = 0; i < ctx->text.numranges; i++) {
                    610:            if (ctx->text.updateFrom[i] > pos1)
                    611:                ctx->text.updateFrom[i] += delta;
                    612:            if (ctx->text.updateTo[i] >= pos1)
                    613:                ctx->text.updateTo[i] += delta;
                    614:        }
                    615:     }
                    616: 
                    617:     line2 = LineForPosition(ctx, pos1);
                    618:     /* 
                    619:      * fixup all current line table entries to reflect edit.
                    620:      * BUG: it is illegal to do arithmetic on positions. This code should
                    621:      * either use scan or the source needs to provide a function for doing
                    622:      * position arithmetic.
                    623:     */
                    624:     for (i = line2 + 1; i <= ctx->text.lt.lines; i++)
                    625:        ctx->text.lt.info[i].position += delta;
                    626: 
                    627:     endPos = pos1;
                    628:     /*
                    629:      * Now process the line table and fixup in case edits caused
                    630:      * changes in line breaks. If we are breaking on word boundaries,
                    631:      * this code checks for moving words to and from lines.
                    632:     */
                    633:     if (visible) {
                    634:        for (i = line1; i < ctx->text.lt.lines; i++) {/* fixup line table */
                    635:            width = (ctx->text.options & resizeWidth) ? 9999 : ctx->core.width - x;
                    636:            if (startPos <= ctx->text.lastPos) {
                    637:                (*(ctx->text.sink->findPosition))(ctx, startPos, x,
                    638:                        width, (ctx->text.options & wordBreak),
                    639:                        &endPos, &realW, &realH);
                    640:                if (!(ctx->text.options & wordBreak) && endPos < ctx->text.lastPos) {
                    641:                    endPos = (*(ctx->text.source->scan))(ctx->text.source, startPos,
                    642:                            XtstEOL, XtsdRight, 1, TRUE);
                    643:                    if (endPos == startPos)
                    644:                        endPos = ctx->text.lastPos + 1;
                    645:                }
                    646:                ctx->text.lt.info[i].endX = realW + x;
                    647:                ctx->text.lt.info[i + 1].y = realH + ctx->text.lt.info[i].y;
                    648:                if ((endPos > pos1) &&
                    649:                        (endPos == ctx->text.lt.info[i + 1].position))
                    650:                    break;
                    651:                startPos = endPos;
                    652:            }
                    653:            if (startPos > ctx->text.lastPos)
                    654:                ctx->text.lt.info[i + 1].endX = ctx->text.leftmargin;
                    655:            ctx->text.lt.info[i + 1].position = startPos;
                    656:            x = ctx->text.lt.info[i + 1].x;
                    657:        }
                    658:     }
                    659:     if (delta >= ctx->text.lastPos)
                    660:        endPos = ctx->text.lastPos;
                    661:     if (delta >= ctx->text.lastPos || pos2 >= ctx->text.lt.top)
                    662:        _XtTextNeedsUpdating(ctx, updateFrom, endPos);
                    663:     SetScrollBar(ctx);
                    664:     return error;
                    665: }
                    666: 
                    667: 
                    668: /*
                    669:  * This routine will display text between two arbitrary source positions.
                    670:  * In the event that this span contains highlighted text for the selection, 
                    671:  * only that portion will be displayed highlighted.
                    672:  */
                    673: static void DisplayText(ctx, pos1, pos2)
                    674:   TextWidget ctx;
                    675:   XtTextPosition pos1, pos2;
                    676:   /* it is illegal to call this routine unless there is a valid line table!*/
                    677: {
                    678:     Position x, y;
                    679:     Dimension height;
                    680:     int line, i, visible;
                    681:     XtTextPosition startPos, endPos;
                    682: 
                    683:     if (pos1 < ctx->text.lt.top)
                    684:        pos1 = ctx->text.lt.top;
                    685:     if (pos2 > ctx->text.lastPos) 
                    686:        pos2 = ctx->text.lastPos;
                    687:     if (pos1 >= pos2) return;
                    688:     visible = LineAndXYForPosition(ctx, pos1, &line, &x, &y);
                    689:     if (!visible)
                    690:        return;
                    691:     startPos = pos1;
                    692:     height = ctx->text.lt.info[1].y - ctx->text.lt.info[0].y;
                    693:     for (i = line; i < ctx->text.lt.lines; i++) {
                    694:        endPos = ctx->text.lt.info[i + 1].position;
                    695:        if (endPos > pos2)
                    696:            endPos = pos2;
                    697:        if (endPos > startPos) {
                    698:            if (x == ctx->text.leftmargin)
                    699:                 (*(ctx->text.sink->clearToBackground))(ctx,
                    700:                     0, y, ctx->text.leftmargin, height);
                    701:            if (startPos >= ctx->text.s.right || endPos <= ctx->text.s.left) {
                    702:                (*(ctx->text.sink->display))(ctx, x, y,
                    703:                        startPos, endPos, FALSE);
                    704:            } else if (startPos >= ctx->text.s.left && endPos <= ctx->text.s.right) {
                    705:                (*(ctx->text.sink->display))(ctx, x, y,
                    706:                        startPos, endPos, TRUE);
                    707:            } else {
                    708:                DisplayText(ctx, startPos, ctx->text.s.left);
                    709:                DisplayText(ctx, max(startPos, ctx->text.s.left), 
                    710:                        min(endPos, ctx->text.s.right));
                    711:                DisplayText(ctx, ctx->text.s.right, endPos);
                    712:            }
                    713:        }
                    714:        startPos = endPos;
                    715:        height = ctx->text.lt.info[i + 1].y - ctx->text.lt.info[i].y;
                    716:         (*(ctx->text.sink->clearToBackground))(ctx,
                    717:            ctx->text.lt.info[i].endX, y, 999, height);
                    718:        x = ctx->text.leftmargin;
                    719:        y = ctx->text.lt.info[i + 1].y;
                    720:        if ((endPos == pos2) && (endPos != ctx->text.lastPos))
                    721:            break;
                    722:     }
                    723: }
                    724: 
                    725: /*
                    726:  * This routine implements multi-click selection in a hardwired manner.
                    727:  * It supports multi-click entity cycling (char, word, line, file) and mouse
                    728:  * motion adjustment of the selected entitie (i.e. select a word then, with
                    729:  * button still down, adjust wich word you really meant by moving the mouse).
                    730:  * [NOTE: This routine is to be replaced by a set of procedures that
                    731:  * will allows clients to implements a wide class of draw through and
                    732:  * multi-click selection user interfaces.]
                    733: */
                    734: static void DoSelection (ctx, position, time, motion)
                    735:   TextWidget ctx;
                    736:   XtTextPosition position;
                    737:   unsigned short time;
                    738:   Boolean motion;
                    739: {
                    740:     int     delta;
                    741:     XtTextPosition newLeft, newRight;
                    742:     XtSelectType newType;
                    743:     XtSelectType *sarray;
                    744: 
                    745:     delta = (time < ctx->text.lasttime) ?
                    746:        ctx->text.lasttime - time : time - ctx->text.lasttime;
                    747:     if (motion)
                    748:        newType = ctx->text.s.type;
                    749:     else {
                    750:        if ((delta < 500) && ((position >= ctx->text.s.left)
                    751:                    && (position <= ctx->text.s.right))) { /* multi-click event */
                    752:            sarray = ctx->text.sarray;
                    753:            for (sarray = ctx->text.sarray;
                    754:                *sarray != XtselectNull && *sarray != ctx->text.s.type;
                    755:                sarray++) ;
                    756:            if (*sarray != XtselectNull) sarray++;
                    757:            if (*sarray == XtselectNull) sarray = ctx->text.sarray;
                    758:            newType = *sarray;
                    759:        } else {                        /* single-click event */
                    760:            newType = *(ctx->text.sarray);
                    761:        }
                    762:         ctx->text.lasttime = time;
                    763:     }
                    764:     switch (newType) {
                    765:        case XtselectPosition: 
                    766:             newLeft = newRight = position;
                    767:            break;
                    768:        case XtselectChar: 
                    769:             newLeft = position;
                    770:             newRight = (*(ctx->text.source->scan))(
                    771:                     ctx->text.source, position, position, XtsdRight, 1, FALSE);
                    772:            break;
                    773:        case XtselectWord: 
                    774:            newLeft = (*(ctx->text.source->scan))(
                    775:                    ctx->text.source, position, XtstWhiteSpace, XtsdLeft, 1, FALSE);
                    776:            newRight = (*(ctx->text.source->scan))(
                    777:                    ctx->text.source, position, XtstWhiteSpace, XtsdRight, 1, FALSE);
                    778:            break;
                    779:        case XtselectLine: 
                    780:        case XtselectParagraph:  /* need "para" scan mode to implement pargraph */
                    781:            newLeft = (*(ctx->text.source->scan))(
                    782:                    ctx->text.source, position, XtstEOL, XtsdLeft, 1, FALSE);
                    783:            newRight = (*(ctx->text.source->scan))(
                    784:                    ctx->text.source, position, XtstEOL, XtsdRight, 1, FALSE);
                    785:            break;
                    786:        case XtselectAll: 
                    787:            newLeft = (*(ctx->text.source->scan))(
                    788:                    ctx->text.source, position, XtstFile, XtsdLeft, 1, FALSE);
                    789:            newRight = (*(ctx->text.source->scan))(
                    790:                    ctx->text.source, position, XtstFile, XtsdRight, 1, FALSE);
                    791:            break;
                    792:     }
                    793:     if ((newLeft != ctx->text.s.left) || (newRight != ctx->text.s.right)
                    794:            || (newType != ctx->text.s.type)) {
                    795:        _XtTextSetNewSelection(ctx, newLeft, newRight);
                    796:        ctx->text.s.type = newType;
                    797:        if (position - ctx->text.s.left < ctx->text.s.right - position)
                    798:            ctx->text.insertPos = newLeft;
                    799:        else 
                    800:            ctx->text.insertPos = newRight;
                    801:     }
                    802:     if (!motion) { /* setup so we can freely mix select extend calls*/
                    803:        ctx->text.origSel.type = ctx->text.s.type;
                    804:        ctx->text.origSel.left = ctx->text.s.left;
                    805:        ctx->text.origSel.right = ctx->text.s.right;
                    806:        if (position >= ctx->text.s.left + ((ctx->text.s.right - ctx->text.s.left) / 2))
                    807:            ctx->text.extendDir = XtsdRight;
                    808:        else
                    809:            ctx->text.extendDir = XtsdLeft;
                    810:     }
                    811: }
                    812: 
                    813: /*
                    814:  * This routine implements extension of the currently selected text in
                    815:  * the "current" mode (i.e. char word, line, etc.). It worries about
                    816:  * extending from either end of the selection and handles the case when you
                    817:  * cross through the "center" of the current selection (e.g. switch which
                    818:  * end you are extending!).
                    819:  * [NOTE: This routine will be replaced by a set of procedures that
                    820:  * will allows clients to implements a wide class of draw through and
                    821:  * multi-click selection user interfaces.]
                    822: */
                    823: static void ExtendSelection (ctx, position, motion)
                    824:   TextWidget ctx;
                    825:   XtTextPosition position;
                    826:   Boolean motion;
                    827: {
                    828:     XtTextPosition newLeft, newRight;
                    829:        
                    830: 
                    831:     if (!motion) {             /* setup for extending selection */
                    832:        ctx->text.origSel.type = ctx->text.s.type;
                    833:        ctx->text.origSel.left = ctx->text.s.left;
                    834:        ctx->text.origSel.right = ctx->text.s.right;
                    835:        if (position >= ctx->text.s.left + ((ctx->text.s.right - ctx->text.s.left) / 2))
                    836:            ctx->text.extendDir = XtsdRight;
                    837:        else
                    838:            ctx->text.extendDir = XtsdLeft;
                    839:     }
                    840:     else /* check for change in extend direction */
                    841:        if ((ctx->text.extendDir == XtsdRight && position < ctx->text.origSel.left) ||
                    842:                (ctx->text.extendDir == XtsdLeft && position > ctx->text.origSel.right)) {
                    843:            ctx->text.extendDir = (ctx->text.extendDir == XtsdRight)? XtsdLeft : XtsdRight;
                    844:            _XtTextSetNewSelection(ctx, ctx->text.origSel.left, ctx->text.origSel.right);
                    845:        }
                    846:     newLeft = ctx->text.s.left;
                    847:     newRight = ctx->text.s.right;
                    848:     switch (ctx->text.s.type) {
                    849:        case XtselectPosition: 
                    850:            if (ctx->text.extendDir == XtsdRight)
                    851:                newRight = position;
                    852:            else
                    853:                newLeft = position;
                    854:            break;
                    855:        case XtselectWord: 
                    856:            if (ctx->text.extendDir == XtsdRight)
                    857:                newRight = position = (*(ctx->text.source->scan))(
                    858:                        ctx->text.source, position, XtstWhiteSpace, XtsdRight, 1, FALSE);
                    859:            else
                    860:                newLeft = position = (*(ctx->text.source->scan))(
                    861:                        ctx->text.source, position, XtstWhiteSpace, XtsdLeft, 1, FALSE);
                    862:            break;
                    863:         case XtselectLine:
                    864:        case XtselectParagraph: /* need "para" scan mode to implement pargraph */
                    865:            if (ctx->text.extendDir == XtsdRight)
                    866:                newRight = position = (*(ctx->text.source->scan))(
                    867:                        ctx->text.source, position, XtstEOL, XtsdRight, 1, TRUE);
                    868:            else
                    869:                newLeft = position = (*(ctx->text.source->scan))(
                    870:                        ctx->text.source, position, XtstEOL, XtsdLeft, 1, FALSE);
                    871:            break;
                    872:        case XtselectAll: 
                    873:            position = ctx->text.insertPos;
                    874:            break;
                    875:     }
                    876:     _XtTextSetNewSelection(ctx, newLeft, newRight);
                    877:     ctx->text.insertPos = position;
                    878: }
                    879: 
                    880: 
                    881: /*
                    882:  * Clear the window to background color.
                    883: */
                    884: static ClearWindow (ctx)
                    885:   TextWidget ctx;
                    886: {
                    887:     (*(ctx->text.sink->clearToBackground))(ctx, 0, 0, ctx->core.width, ctx->core.height);
                    888: }
                    889: 
                    890: 
                    891: /*
                    892:  * Internal redisplay entire window.
                    893: */
                    894: DisplayTextWindow (w)
                    895:   Widget w;
                    896: {
                    897:     TextWidget ctx = (TextWidget) w;
                    898:     ClearWindow(ctx);
                    899:     BuildLineTable(ctx, ctx->text.lt.top);
                    900:     _XtTextNeedsUpdating(ctx, zeroPosition, ctx->text.lastPos);
                    901:     SetScrollBar(ctx);
                    902: }
                    903: 
                    904: /*
                    905:  * This routine checks to see if the window should be resized (grown or
                    906:  * shrunk) or scrolled then text to be painted overflows to the right or
                    907:  * the bottom of the window. It is used by the keyboard input routine.
                    908: */
                    909: CheckResizeOrOverflow(ctx)
                    910:   TextWidget ctx;
                    911: {
                    912:     XtTextPosition posToCheck;
                    913:     int     visible, line, width;
                    914:     XtWidgetGeometry rbox;
                    915:     if (ctx->text.options & resizeWidth) {
                    916:        width = 0;
                    917:        for (line=0 ; line<ctx->text.lt.lines ; line++)
                    918:            if (width < ctx->text.lt.info[line].endX)
                    919:                width = ctx->text.lt.info[line].endX;
                    920:        width += ctx->text.leftmargin;
                    921:        if (width > ctx->core.width) {
                    922:            rbox.request_mode = CWWidth;
                    923:            rbox.width = width;
                    924:            if ( XtMakeGeometryRequest(ctx, &rbox, NULL) != XtGeometryNo) {
                    925:              ctx->core.width = rbox.width;
                    926:              }
                    927:        }
                    928:     }
                    929:     if ((ctx->text.options & resizeHeight) || (ctx->text.options & scrollOnOverflow)) {
                    930:        if (ctx->text.options & scrollOnOverflow)
                    931:            posToCheck = ctx->text.insertPos;
                    932:        else
                    933:            posToCheck = ctx->text.lastPos;
                    934:        visible = IsPositionVisible(ctx, posToCheck);
                    935:        if (visible)
                    936:            line = LineForPosition(ctx, posToCheck);
                    937:        else
                    938:            line = ctx->text.lt.lines;
                    939:        if ((ctx->text.options & scrollOnOverflow) && (line + 1 > ctx->text.lt.lines)) {
                    940:            BuildLineTable(ctx, ctx->text.lt.info[1].position);
                    941:            XCopyArea(XtDisplay(ctx), XtWindow(ctx), XtWindow(ctx), 
                    942:                      ctx->text.gc, (Position)ctx->text.leftmargin, 
                    943:                      ctx->text.lt.info[1].y, 9999, 9999,
                    944:                      (Position)ctx->text.leftmargin, ctx->text.lt.info[0].y);
                    945:        }
                    946:        else
                    947:            if ((ctx->text.options & resizeHeight) && (line + 1 != ctx->text.lt.lines)) {
                    948:                rbox.request_mode = CWHeight;
                    949:                rbox.height = (*(ctx->text.sink->maxHeight))
                    950:                                (ctx, line + 1) + (2*yMargin)+2;
                    951:                if (XtMakeGeometryRequest(ctx, &rbox, NULL) != XtGeometryNo) {
                    952:                        ctx->core.width = rbox.height ;
                    953:              };
                    954:            }
                    955:     }
                    956: }
                    957: 
                    958: /*
                    959:  * This routine is used to perform various selection functions. The goal is
                    960:  * to be able to specify all the more popular forms of draw-through and
                    961:  * multi-click selection user interfaces from the outside.
                    962:  */
                    963: void AlterSelection (ctx, mode, action)
                    964:     TextWidget     ctx;
                    965:     SelectionMode   mode;      /* {XtsmTextSelect, XtsmTextExtend}               */
                    966:     SelectionAction action;    /* {XtactionStart, XtactionAdjust, XtactionEnd} */
                    967: {
                    968:     XtTextPosition position;
                    969:     char   *ptr;
                    970: 
                    971:     position = PositionForXY (ctx, (int) ctx->text.ev_x, (int) ctx->text.ev_y);
                    972:     if (action == XtactionStart) {
                    973:        switch (mode) {
                    974:        case XtsmTextSelect: 
                    975:            DoSelection (ctx, position, ctx->text.time, FALSE);
                    976:            break;
                    977:        case XtsmTextExtend: 
                    978:            ExtendSelection (ctx, position, FALSE);
                    979:            break;
                    980:        }
                    981:     }
                    982:     else {
                    983:        switch (mode) {
                    984:        case XtsmTextSelect: 
                    985:            DoSelection (ctx, position, ctx->text.time, TRUE);
                    986:            break;
                    987:        case XtsmTextExtend: 
                    988:            ExtendSelection (ctx, position, TRUE);
                    989:            break;
                    990:        }
                    991:     }
                    992:     if (action == XtactionEnd && ctx->text.s.left < ctx->text.s.right) {
                    993:        ptr = _XtTextGetText (ctx, ctx->text.s.left, ctx->text.s.right);
                    994:        XStoreBuffer (XtDisplay(ctx), ptr, min (strlen (ptr), MAXCUT), 0);
                    995:        XtFree (ptr);
                    996:     }
                    997: }
                    998: 
                    999: /*
                   1000:  * This routine processes all "expose region" XEvents. In general, its job
                   1001:  * is to the best job at minimal re-paint of the text, displayed in the
                   1002:  * window, that it can.
                   1003: */
                   1004: static void ProcessExposeRegion(w, event)
                   1005:   Widget w;
                   1006:   XEvent *event;
                   1007: {
                   1008:     TextWidget ctx = (TextWidget) w;
                   1009:     XtTextPosition pos1, pos2, resultend;
                   1010:     int line;
                   1011:     int x = event->xexpose.x;
                   1012:     int y = event->xexpose.y;
                   1013:     int width = event->xexpose.width;
                   1014:     int height = event->xexpose.height;
                   1015:     LineTableEntryPtr info;
                   1016: 
                   1017:    _XtTextPrepareToUpdate(ctx);
                   1018:     if (x < ctx->text.leftmargin) /* stomp on caret tracks */
                   1019:         (*(ctx->text.sink->clearToBackground))(ctx, x, y, width, height);
                   1020:    /* figure out starting line that was exposed */
                   1021:     line = LineForPosition(ctx, PositionForXY(ctx, x, y));
                   1022:     while (line < ctx->text.lt.lines && ctx->text.lt.info[line + 1].y < y)
                   1023:        line++;
                   1024:     while (line < ctx->text.lt.lines) {
                   1025:        info = &(ctx->text.lt.info[line]);
                   1026:        if (info->y >= y + height)
                   1027:            break;
                   1028:        (*(ctx->text.sink->resolve))(ctx, 
                   1029:                                 info->position, info->x,
                   1030:                                x - info->x, &pos1, &resultend);
                   1031:        (*(ctx->text.sink->resolve))(ctx, 
                   1032:                                 info->position, info->x,
                   1033:                                x + width - info->x, &pos2, 
                   1034:                                 &resultend);
                   1035:        pos2 = (*(ctx->text.source->scan))(ctx->text.source, pos2, XtstPositions, 
                   1036:                                       XtsdRight, 1, TRUE);
                   1037:        _XtTextNeedsUpdating(ctx, pos1, pos2);
                   1038:        line++;
                   1039:     }
                   1040:     _XtTextExecuteUpdate(ctx);
                   1041: }
                   1042: 
                   1043: 
                   1044: static int oldinsert = -1;
                   1045: 
                   1046: /*
                   1047:  * This routine does all setup required to syncronize batched screen updates
                   1048: */
                   1049: int _XtTextPrepareToUpdate(ctx)
                   1050:   TextWidget ctx;
                   1051: {
                   1052:     if (oldinsert < 0) {
                   1053:        InsertCursor(ctx, XtisOff);
                   1054:        ctx->text.numranges = 0;
                   1055:        ctx->text.showposition = FALSE;
                   1056:        oldinsert = ctx->text.insertPos;
                   1057:     }
                   1058: }
                   1059: 
                   1060: 
                   1061: /*
                   1062:  * This is a private utility routine used by _XtTextExecuteUpdate. It
                   1063:  * processes all the outstanding update requests and merges update
                   1064:  * ranges where possible.
                   1065: */
                   1066: static FlushUpdate(ctx)
                   1067:   TextWidget ctx;
                   1068: {
                   1069:     int     i, w;
                   1070:     XtTextPosition updateFrom, updateTo;
                   1071:     while (ctx->text.numranges > 0) {
                   1072:        updateFrom = ctx->text.updateFrom[0];
                   1073:        w = 0;
                   1074:        for (i=1 ; i<ctx->text.numranges ; i++) {
                   1075:            if (ctx->text.updateFrom[i] < updateFrom) {
                   1076:                updateFrom = ctx->text.updateFrom[i];
                   1077:                w = i;
                   1078:            }
                   1079:        }
                   1080:        updateTo = ctx->text.updateTo[w];
                   1081:        ctx->text.numranges--;
                   1082:        ctx->text.updateFrom[w] = ctx->text.updateFrom[ctx->text.numranges];
                   1083:        ctx->text.updateTo[w] = ctx->text.updateTo[ctx->text.numranges];
                   1084:        for (i=ctx->text.numranges-1 ; i>=0 ; i--) {
                   1085:            while (ctx->text.updateFrom[i] <= updateTo && i < ctx->text.numranges) {
                   1086:                updateTo = ctx->text.updateTo[i];
                   1087:                ctx->text.numranges--;
                   1088:                ctx->text.updateFrom[i] = ctx->text.updateFrom[ctx->text.numranges];
                   1089:                ctx->text.updateTo[i] = ctx->text.updateTo[ctx->text.numranges];
                   1090:            }
                   1091:        }
                   1092:        DisplayText(ctx, updateFrom, updateTo);
                   1093:     }
                   1094: }
                   1095: 
                   1096: 
                   1097: /*
                   1098:  * This is a private utility routine used by _XtTextExecuteUpdate. This routine
                   1099:  * worries about edits causing new data or the insertion point becoming
                   1100:  * invisible (off the screen). Currently it always makes it visible by
                   1101:  * scrolling. It probably needs generalization to allow more options.
                   1102: */
                   1103: _XtTextShowPosition(ctx)
                   1104:   TextWidget ctx;
                   1105: {
                   1106:     XtTextPosition top, first, second;
                   1107:     if (ctx->text.insertPos < ctx->text.lt.top ||
                   1108:        ctx->text.insertPos >= ctx->text.lt.info[ctx->text.lt.lines].position) {
                   1109:        if (ctx->text.lt.lines > 0 && (ctx->text.insertPos < ctx->text.lt.top 
                   1110:            || ctx->text.lt.info[ctx->text.lt.lines].position <= ctx->text.lastPos)) {
                   1111:            first = ctx->text.lt.top;
                   1112:            second = ctx->text.lt.info[1].position;
                   1113:            if (ctx->text.insertPos < first)
                   1114:                top = (*(ctx->text.source->scan))(
                   1115:                        ctx->text.source, ctx->text.insertPos, XtstEOL,
                   1116:                        XtsdLeft, 1, FALSE);
                   1117:            else
                   1118:                top = (*(ctx->text.source->scan))(
                   1119:                        ctx->text.source, ctx->text.insertPos, XtstEOL,
                   1120:                        XtsdLeft, ctx->text.lt.lines, FALSE);
                   1121:            BuildLineTable(ctx, top);
                   1122:            while (ctx->text.insertPos >= ctx->text.lt.info[ctx->text.lt.lines].position) {
                   1123:                if (ctx->text.lt.info[ctx->text.lt.lines].position > ctx->text.lastPos)
                   1124:                    break;
                   1125:                BuildLineTable(ctx, ctx->text.lt.info[1].position);
                   1126:            }
                   1127:            if (ctx->text.lt.top == second) {
                   1128:                BuildLineTable(ctx, first);
                   1129:                _XtTextScroll(ctx, 1);
                   1130:            } else if (ctx->text.lt.info[1].position == first) {
                   1131:                BuildLineTable(ctx, first);
                   1132:                _XtTextScroll(ctx, -1);
                   1133:            } else {
                   1134:                ctx->text.numranges = 0;
                   1135:                if (ctx->text.lt.top != first)
                   1136:                    DisplayTextWindow(ctx);
                   1137:            }
                   1138:        }
                   1139:     }
                   1140: }
                   1141: 
                   1142: 
                   1143: 
                   1144: /*
                   1145:  * This routine causes all batched screen updates to be performed
                   1146: */
                   1147: _XtTextExecuteUpdate(ctx)
                   1148:   TextWidget ctx;
                   1149: {
                   1150:     if (oldinsert >= 0) {
                   1151:        if (oldinsert != ctx->text.insertPos || ctx->text.showposition)
                   1152:            _XtTextShowPosition(ctx);
                   1153:        FlushUpdate(ctx);
                   1154:        InsertCursor(ctx, XtisOn);
                   1155:        oldinsert = -1;
                   1156:     }
                   1157: }
                   1158: 
                   1159: 
                   1160: static void TextDestroy(ctx)
                   1161: TextWidget ctx;
                   1162: {
                   1163:     if (ctx->text.dialog)
                   1164:        (void) XtDestroyWidget(ctx->text.dialog);
                   1165:     if (ctx->text.outer)
                   1166:        (void) XtDestroyWidget(ctx->text.outer);
                   1167:     if (ctx->text.sbar)
                   1168:        (void) XtDestroyWidget(ctx->text.sbar);
                   1169:     XtFree((char *)ctx->text.updateFrom);
                   1170:     XtFree((char *)ctx->text.updateTo);
                   1171: }
                   1172: 
                   1173: 
                   1174: static void Resize(w)
                   1175:     Widget          w;
                   1176: {
                   1177:     TextWidget ctx = (TextWidget) w;
                   1178:     _XtTextPrepareToUpdate(ctx);
                   1179:     ForceBuildLineTable(ctx);
                   1180:     _XtTextExecuteUpdate(ctx);
                   1181: }
                   1182: 
                   1183: 
                   1184: /*
                   1185:  * This routine allow the application program to Set attributes.
                   1186:  */
                   1187: 
                   1188: Boolean XtTextSetValues(current, request, new, last)
                   1189: Widget current, request, new;
                   1190: Boolean last;
                   1191: {
                   1192:     TextWidget oldtw = (TextWidget) current;
                   1193:     TextWidget newtw = (TextWidget) new;
                   1194:     Boolean    redisplay = FALSE;
                   1195: 
                   1196:     _XtTextPrepareToUpdate(oldtw);
                   1197:     
                   1198:     if (oldtw->text.sink != newtw->text.sink)
                   1199:        redisplay = TRUE;
                   1200: 
                   1201:     if (oldtw->text.source != newtw->text.source) {
                   1202:        ForceBuildLineTable(oldtw);
                   1203:        redisplay = TRUE;
                   1204:     }
                   1205:     if (oldtw->text.insertPos != newtw->text.insertPos)
                   1206:        oldtw->text.showposition = TRUE;
                   1207: 
                   1208:     if (oldtw->text.lt.top != newtw->text.lt.top)
                   1209:        redisplay = TRUE;
                   1210: 
                   1211:     if (oldtw->text.leftmargin != newtw->text.leftmargin)
                   1212:        redisplay = TRUE;
                   1213: 
                   1214:     if (redisplay) 
                   1215:        DisplayTextWindow(oldtw);
                   1216:     _XtTextExecuteUpdate(oldtw);
                   1217:     return (FALSE);  /*  this needs looking at! */
                   1218: }
                   1219: 
                   1220: 
                   1221: 
                   1222: void XtTextDisplay (w)
                   1223:     Widget w;
                   1224: {
                   1225:     TextWidget ctx = (TextWidget) w;;
                   1226: 
                   1227:        _XtTextPrepareToUpdate(ctx);
                   1228:        DisplayTextWindow(ctx);
                   1229:        _XtTextExecuteUpdate(ctx);
                   1230: }
                   1231: 
                   1232: /*******************************************************************
                   1233: The following routines provide procedural interfaces to Text window state
                   1234: setting and getting. They need to be redone so than the args code can use
                   1235: them. I suggest we create a complete set that takes the context as an
                   1236: argument and then have the public version lookup the context and call the
                   1237: internal one. The major value of this set is that they have actual application
                   1238: clients and therefore the functionality provided is required for any future
                   1239: version of Text.
                   1240: ********************************************************************/
                   1241: 
                   1242: void XtTextSetSelectionArray(w, sarray)
                   1243:     Widget w;
                   1244:     XtSelectType *sarray;
                   1245: {
                   1246:     TextWidget ctx = (TextWidget) w;
                   1247:     XtSelectType *s2;
                   1248: 
                   1249:     s2 = ctx->text.sarray;
                   1250:     while (XtselectNull != (*s2++ = *sarray++)) ;
                   1251: }
                   1252: 
                   1253: void XtTextSetLastPos (w, lastPos)
                   1254:     Widget w;
                   1255:     XtTextPosition lastPos;
                   1256: {
                   1257:     TextWidget  ctx = (TextWidget) w;
                   1258: 
                   1259:        _XtTextPrepareToUpdate(ctx);
                   1260:        (*(ctx->text.source->setLastPos))(ctx->text.source, lastPos);
                   1261:        ctx->text.lastPos = GETLASTPOS;
                   1262:        ForceBuildLineTable(ctx);
                   1263:        DisplayTextWindow(ctx);
                   1264:        _XtTextExecuteUpdate(ctx);
                   1265: }
                   1266: 
                   1267: 
                   1268: void XtTextGetSelectionPos(w, left, right)
                   1269:   Widget w;
                   1270:   XtTextPosition *left, *right;
                   1271: {
                   1272:     TextWidget ctx = (TextWidget) w;
                   1273:     *left = ctx->text.s.left;
                   1274:     *right = ctx->text.s.right;
                   1275: }
                   1276: 
                   1277: 
                   1278: void XtTextNewSource(w, source, startPos)
                   1279:     Widget w;
                   1280:     XtTextSource   *source;
                   1281:     XtTextPosition startPos;
                   1282: {
                   1283:     TextWidget ctx = (TextWidget) w;
                   1284: 
                   1285:        ctx->text.source = source;
                   1286:        ctx->text.lt.top = startPos;
                   1287:        ctx->text.s.left = ctx->text.s.right = 0;
                   1288:        ctx->text.insertPos = startPos;
                   1289:        ctx->text.lastPos = GETLASTPOS;
                   1290:        ForceBuildLineTable(ctx);
                   1291:        _XtTextPrepareToUpdate(ctx);
                   1292:        DisplayTextWindow(ctx);
                   1293:        _XtTextExecuteUpdate(ctx);
                   1294: }
                   1295: 
                   1296: /*
                   1297:  * This public routine deletes the text from startPos to endPos in a source and
                   1298:  * then inserts, at startPos, the text that was passed. As a side effect it
                   1299:  * "invalidates" that portion of the displayed text (if any), so that things
                   1300:  * will be repainted properly.
                   1301:  */
                   1302: int XtTextReplace(w, startPos, endPos, text)
                   1303:     Widget         w;
                   1304:     XtTextPosition  startPos, endPos;
                   1305:     XtTextBlock     *text;
                   1306: {
                   1307:     TextWidget ctx = (TextWidget) w;
                   1308:     int result;
                   1309:     result = EDITERROR;
                   1310:        _XtTextPrepareToUpdate(ctx);
                   1311:        result = ReplaceText(ctx, startPos, endPos, text);
                   1312:        _XtTextExecuteUpdate(ctx);
                   1313:     return result;
                   1314: }
                   1315: 
                   1316: 
                   1317: XtTextPosition XtTextTopPosition(w)
                   1318:     Widget         w;
                   1319: {
                   1320:     TextWidget ctx = (TextWidget) w;
                   1321: 
                   1322:      return ctx->text.lt.top;
                   1323: }
                   1324: 
                   1325: 
                   1326: void XtTextSetInsertionPoint(w, position)
                   1327:     Widget         w;
                   1328:     XtTextPosition position;
                   1329: {
                   1330:     TextWidget ctx = (TextWidget) w;
                   1331: 
                   1332:        _XtTextPrepareToUpdate(ctx);
                   1333:        ctx->text.insertPos = position;
                   1334:        ctx->text.showposition = TRUE;
                   1335:        _XtTextExecuteUpdate(ctx);
                   1336: }
                   1337: 
                   1338: 
                   1339: XtTextPosition XtTextGetInsertionPoint(w)
                   1340:     Widget         w;
                   1341: {
                   1342:     TextWidget ctx = (TextWidget) w;
                   1343: 
                   1344:     return(ctx->text.insertPos);
                   1345: }
                   1346: 
                   1347: 
                   1348: void XtTextUnsetSelection(w)
                   1349:     Widget         w;
                   1350: {
                   1351:     TextWidget ctx = (TextWidget) w;
                   1352: 
                   1353:        _XtTextPrepareToUpdate(ctx);
                   1354:        _XtTextSetNewSelection(ctx, zeroPosition, zeroPosition);
                   1355:        _XtTextExecuteUpdate(ctx);
                   1356: }
                   1357: 
                   1358: 
                   1359: void XtTextChangeOptions(w, options)
                   1360:     Widget         w;
                   1361:     int    options;
                   1362: {
                   1363:     TextWidget ctx = (TextWidget) w;
                   1364: 
                   1365:        ctx->text.options = options;
                   1366: }
                   1367: 
                   1368: 
                   1369: int XtTextGetOptions(w)
                   1370:     Widget         w;
                   1371: {
                   1372:     TextWidget ctx = (TextWidget) w;
                   1373: 
                   1374:        return ctx->text.options;
                   1375: }
                   1376: 
                   1377: void XtTextSetNewSelection (w, left, right)
                   1378:     Widget         w;
                   1379:     XtTextPosition left, right;
                   1380: {
                   1381:     TextWidget ctx = (TextWidget) w;
                   1382: 
                   1383:        _XtTextPrepareToUpdate(ctx);
                   1384:         _XtTextSetNewSelection(ctx, left, right);
                   1385:        _XtTextExecuteUpdate(ctx);
                   1386: }
                   1387: 
                   1388: void XtTextInvalidate(w, from, to)
                   1389:     Widget         w;
                   1390:     XtTextPosition from,to;
                   1391: {
                   1392:     TextWidget ctx = (TextWidget) w;
                   1393: 
                   1394:         ctx->text.lastPos = (*(ctx->text.source->getLastPos))(ctx->text.source);
                   1395:         _XtTextPrepareToUpdate(ctx);
                   1396:         _XtTextNeedsUpdating(ctx, from, to);
                   1397:         ForceBuildLineTable(ctx);
                   1398:         _XtTextExecuteUpdate(ctx);
                   1399: }
                   1400: 
                   1401: 
                   1402: /* Returns the window actually containing the text (which is not the same
                   1403:    as the given window if the text window has scrollbars.) */
                   1404: 
                   1405: Window XtTextGetInnerWindow(w)
                   1406:     Widget         w;
                   1407: {
                   1408:     TextWidget ctx = (TextWidget) w;
                   1409:        return XtWindow(ctx);
                   1410: }
                   1411: 
                   1412: /* The following used to be a separate file, TextActs.c, but
                   1413:    is included here because textActionsTable can't be external
                   1414:    to the file declaring textClassRec */
                   1415: 
                   1416: /* Misc. routines */
                   1417: void TextAcceptFocus(w)
                   1418:     Widget          w;
                   1419: {
                   1420:     TextWidget ctx = (TextWidget) w;
                   1421:     if (!ctx->text.hasfocus)
                   1422:        XSetInputFocus(XtDisplay(ctx), XtWindow(ctx), 
                   1423:          RevertToPointerRoot,  CurrentTime);
                   1424: }
                   1425: 
                   1426: static StartAction(ctx, event)
                   1427:    TextWidget ctx;
                   1428:    XEvent *event;
                   1429: {
                   1430:     _XtTextPrepareToUpdate(ctx);
                   1431:     if (event->type == ButtonPress) TextAcceptFocus(ctx);
                   1432: /* this code is wrong if actions bound to non-button events! */
                   1433:     ctx->text.time = event->xbutton.time;
                   1434:     ctx->text.ev_x = event->xbutton.x;
                   1435:     ctx->text.ev_y = event->xbutton.y;
                   1436: }
                   1437: 
                   1438: static EndAction(ctx)
                   1439:    TextWidget ctx;
                   1440: {
                   1441:     CheckResizeOrOverflow(ctx);
                   1442:     _XtTextExecuteUpdate(ctx);
                   1443: }
                   1444: 
                   1445: /*ARGSUSED*/
                   1446: static DoFeep(ctx)
                   1447:     TextWidget ctx;
                   1448: {
                   1449:     XBell(XtDisplay(ctx), 50);
                   1450: }
                   1451: 
                   1452: static DeleteOrKill(ctx, from, to, kill)
                   1453:     TextWidget    ctx;
                   1454:     XtTextPosition from, to;
                   1455:     Boolean       kill;
                   1456: {
                   1457:     XtTextBlock text;
                   1458:     char *ptr;
                   1459: 
                   1460:     if (kill && from < to) {
                   1461:        ptr = _XtTextGetText(ctx, from, to);
                   1462:        XStoreBuffer(XtDisplay(ctx), ptr, strlen(ptr), 1);
                   1463:        XtFree(ptr);
                   1464:     }
                   1465:     text.length = 0;
                   1466:     if (ReplaceText(ctx, from, to, &text)) {
                   1467:        XBell(XtDisplay(ctx), 50);
                   1468:        return;
                   1469:     }
                   1470:     _XtTextSetNewSelection(ctx, from, from);
                   1471:     ctx->text.insertPos = from;
                   1472:     ctx->text.showposition = TRUE;
                   1473: }
                   1474: 
                   1475: 
                   1476: StuffFromBuffer(ctx, buffer)
                   1477:   TextWidget ctx;
                   1478:   int buffer;
                   1479: {
                   1480:     extern char *XFetchBuffer();
                   1481:     XtTextBlock text;
                   1482:     text.ptr = XFetchBuffer(XtDisplay(ctx), &(text.length), buffer);
                   1483:     if (ReplaceText(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) {
                   1484:        XBell(XtDisplay(ctx), 50);
                   1485:        return;
                   1486:     }
                   1487:     ctx->text.insertPos = ctx->text.source->scan(ctx->text.source, 
                   1488:        ctx->text.insertPos, XtstPositions, XtsdRight, text.length, TRUE);
                   1489:     _XtTextSetNewSelection(ctx, ctx->text.insertPos, ctx->text.insertPos);
                   1490:     XtFree(text.ptr);
                   1491: }
                   1492: 
                   1493: 
                   1494: static UnKill(ctx, event)
                   1495:   TextWidget ctx;
                   1496:    XEvent *event;
                   1497: {
                   1498:    StartAction(ctx, event);
                   1499:     StuffFromBuffer(ctx, 1);
                   1500:    EndAction(ctx);
                   1501: }
                   1502: 
                   1503: static Stuff(ctx, event)
                   1504:   TextWidget ctx;
                   1505:    XEvent *event;
                   1506: {
                   1507:    StartAction(ctx, event);
                   1508:     StuffFromBuffer(ctx, 0);
                   1509:    EndAction(ctx);
                   1510: }
                   1511: 
                   1512: 
                   1513: static XtTextPosition NextPosition(ctx, position, kind, direction)
                   1514:     TextWidget ctx;
                   1515:     XtTextPosition position;
                   1516:     ScanType kind;
                   1517:     ScanDirection direction;
                   1518: {
                   1519:     XtTextPosition pos;
                   1520: 
                   1521:      pos = ctx->text.source->scan(
                   1522:            ctx->text.source, position, kind, direction, 1, FALSE);
                   1523:      if (pos == ctx->text.insertPos) 
                   1524:          pos = ctx->text.source->scan(
                   1525:             ctx->text.source, position, kind, direction, 2, FALSE);
                   1526:      return pos;
                   1527: }
                   1528: 
                   1529: /* routines for moving around */
                   1530: 
                   1531: static MoveForwardChar(ctx, event)
                   1532:    TextWidget ctx;
                   1533:    XEvent *event;
                   1534: {
                   1535:    StartAction(ctx, event);
                   1536:    ctx->text.insertPos = ctx->text.source->scan(
                   1537:         ctx->text.source, ctx->text.insertPos, XtstPositions, XtsdRight, 1, 
                   1538:        TRUE);
                   1539:    EndAction(ctx);
                   1540: }
                   1541: 
                   1542: static MoveBackwardChar(ctx, event)
                   1543:     TextWidget ctx;
                   1544:    XEvent *event;
                   1545: {
                   1546:    StartAction(ctx, event);
                   1547:     ctx->text.insertPos = ctx->text.source->scan(
                   1548:             ctx->text.source, ctx->text.insertPos, XtstPositions, XtsdLeft,
                   1549:            1, TRUE);
                   1550:    EndAction(ctx);
                   1551: }
                   1552: 
                   1553: static MoveForwardWord(ctx, event)
                   1554:     TextWidget ctx;
                   1555:    XEvent *event;
                   1556: {
                   1557:    StartAction(ctx, event);
                   1558:     ctx->text.insertPos = NextPosition(ctx, ctx->text.insertPos, 
                   1559:       XtstWhiteSpace, XtsdRight);
                   1560:    EndAction(ctx);
                   1561: }
                   1562: 
                   1563: static MoveBackwardWord(ctx, event)
                   1564:     TextWidget ctx;
                   1565:    XEvent *event;
                   1566: {
                   1567:    StartAction(ctx, event);
                   1568:     ctx->text.insertPos = NextPosition(ctx, ctx->text.insertPos, 
                   1569:       XtstWhiteSpace, XtsdLeft);
                   1570:    EndAction(ctx);
                   1571: }
                   1572: 
                   1573: static MoveBackwardParagraph(ctx, event)
                   1574:     TextWidget ctx;
                   1575:    XEvent *event;
                   1576: {
                   1577:    StartAction(ctx, event);
                   1578:     ctx->text.insertPos = NextPosition(ctx, ctx->text.insertPos, 
                   1579:       XtstEOL, XtsdLeft);
                   1580:    EndAction(ctx);
                   1581: }
                   1582: 
                   1583: static MoveForwardParagraph(ctx, event)
                   1584:     TextWidget ctx;
                   1585:    XEvent *event;
                   1586: {
                   1587:    StartAction(ctx, event);
                   1588:     ctx->text.insertPos = NextPosition(ctx, ctx->text.insertPos, 
                   1589:       XtstEOL, XtsdRight);
                   1590:    EndAction(ctx);
                   1591: }
                   1592: 
                   1593: 
                   1594: static MoveToLineStart(ctx, event)
                   1595:   TextWidget ctx;
                   1596:    XEvent *event;
                   1597: {
                   1598:     int line;
                   1599:    StartAction(ctx, event);
                   1600:     _XtTextShowPosition(ctx);
                   1601:     line = LineForPosition(ctx, ctx->text.insertPos);
                   1602:     ctx->text.insertPos = ctx->text.lt.info[line].position;
                   1603:    EndAction(ctx);
                   1604: }
                   1605: 
                   1606: static MoveToLineEnd(ctx, event)
                   1607:   TextWidget ctx;
                   1608:    XEvent *event;
                   1609: {
                   1610:     int line;
                   1611:     XtTextPosition next;
                   1612:    StartAction(ctx, event);
                   1613:     _XtTextShowPosition(ctx);
                   1614:     line = LineForPosition(ctx, ctx->text.insertPos);
                   1615:     next = ctx->text.lt.info[line+1].position;
                   1616:     if (next > ctx->text.lastPos)
                   1617:        next = ctx->text.lastPos;
                   1618:     else
                   1619:        next = ctx->text.source->scan(ctx->text.source, next, XtstPositions, 
                   1620:          XtsdLeft, 1, TRUE);
                   1621:     ctx->text.insertPos = next;
                   1622:    EndAction(ctx);
                   1623: }
                   1624: 
                   1625: 
                   1626: static int LineLastWidth = 0;
                   1627: static XtTextPosition LineLastPosition = 0;
                   1628: 
                   1629: static MoveNextLine(ctx, event)
                   1630:   TextWidget ctx;
                   1631:    XEvent *event;
                   1632: {
                   1633:     int     width, width2, height, line;
                   1634:     XtTextPosition position, maxp;
                   1635:    StartAction(ctx, event);
                   1636:     _XtTextShowPosition(ctx);
                   1637:     line = LineForPosition(ctx, ctx->text.insertPos);
                   1638:     if (line == ctx->text.lt.lines - 1) {
                   1639:        _XtTextScroll(ctx, 1);
                   1640:        line = LineForPosition(ctx, ctx->text.insertPos);
                   1641:     }
                   1642:     if (LineLastPosition == ctx->text.insertPos)
                   1643:        width = LineLastWidth;
                   1644:     else
                   1645:        ctx->text.sink->findDistance(ctx,
                   1646:                ctx->text.lt.info[line].position, ctx->text.lt.info[line].x,
                   1647:                ctx->text.insertPos, &width, &position, &height);
                   1648:     line++;
                   1649:     if (ctx->text.lt.info[line].position > ctx->text.lastPos) {
                   1650:        ctx->text.insertPos = ctx->text.lastPos;
                   1651:        EndAction(ctx);
                   1652:        return;
                   1653:     }
                   1654:     ctx->text.sink->findPosition(ctx,
                   1655:            ctx->text.lt.info[line].position, ctx->text.lt.info[line].x,
                   1656:            width, FALSE, &position, &width2, &height);
                   1657:     maxp = ctx->text.source->scan(ctx->text.source,
                   1658:             ctx->text.lt.info[line+1].position,
                   1659:            XtstPositions, XtsdLeft, 1, TRUE);
                   1660:     if (position > maxp)
                   1661:        position = maxp;
                   1662:     ctx->text.insertPos = position;
                   1663:     LineLastWidth = width;
                   1664:     LineLastPosition = position;
                   1665:    EndAction(ctx);
                   1666: }
                   1667: 
                   1668: static MovePreviousLine(ctx, event)
                   1669:   TextWidget ctx;
                   1670:    XEvent *event;
                   1671: {
                   1672:     int     width, width2, height, line;
                   1673:     XtTextPosition position, maxp;
                   1674:    StartAction(ctx, event);
                   1675:     _XtTextShowPosition(ctx);
                   1676:     line = LineForPosition(ctx, ctx->text.insertPos);
                   1677:     if (line == 0) {
                   1678:        _XtTextScroll(ctx, -1);
                   1679:        line = LineForPosition(ctx, ctx->text.insertPos);
                   1680:     }
                   1681:     if (line > 0) {
                   1682:        if (LineLastPosition == ctx->text.insertPos)
                   1683:            width = LineLastWidth;
                   1684:        else
                   1685:            ctx->text.sink->findDistance(ctx,
                   1686:                    ctx->text.lt.info[line].position, 
                   1687:                    ctx->text.lt.info[line].x,
                   1688:                    ctx->text.insertPos, &width, &position, &height);
                   1689:        line--;
                   1690:        ctx->text.sink->findPosition(ctx,
                   1691:                ctx->text.lt.info[line].position, ctx->text.lt.info[line].x,
                   1692:                width, FALSE, &position, &width2, &height);
                   1693:        maxp = ctx->text.source->scan(ctx->text.source, 
                   1694:                ctx->text.lt.info[line+1].position,
                   1695:                XtstPositions, XtsdLeft, 1, TRUE);
                   1696:        if (position > maxp)
                   1697:            position = maxp;
                   1698:        ctx->text.insertPos = position;
                   1699:        LineLastWidth = width;
                   1700:        LineLastPosition = position;
                   1701:     }
                   1702:    EndAction(ctx);
                   1703: }
                   1704: 
                   1705: 
                   1706: 
                   1707: static MoveBeginningOfFile(ctx, event)
                   1708:   TextWidget ctx;
                   1709:    XEvent *event;
                   1710: {
                   1711:    StartAction(ctx, event);
                   1712:     ctx->text.insertPos = ctx->text.source->scan(ctx->text.source, 
                   1713:        ctx->text.insertPos, XtstFile, XtsdLeft, 1, TRUE);
                   1714:    EndAction(ctx);
                   1715: }
                   1716: 
                   1717: 
                   1718: static MoveEndOfFile(ctx, event)
                   1719:   TextWidget ctx;
                   1720:    XEvent *event;
                   1721: {
                   1722:    StartAction(ctx, event);
                   1723:     ctx->text.insertPos = ctx->text.source->scan(ctx->text.source, 
                   1724:        ctx->text.insertPos, XtstFile,  XtsdRight, 1, TRUE);
                   1725:    EndAction(ctx);
                   1726: }
                   1727: 
                   1728: static ScrollOneLineUp(ctx, event)
                   1729:   TextWidget ctx;
                   1730:    XEvent *event;
                   1731: {
                   1732:    StartAction(ctx, event);
                   1733:     _XtTextScroll(ctx, 1);
                   1734:    EndAction(ctx);
                   1735: }
                   1736: 
                   1737: static ScrollOneLineDown(ctx, event)
                   1738:   TextWidget ctx;
                   1739:    XEvent *event;
                   1740: {
                   1741:    StartAction(ctx, event);
                   1742:     _XtTextScroll(ctx, -1);
                   1743:    EndAction(ctx);
                   1744: }
                   1745: 
                   1746: static MoveNextPage(ctx, event)
                   1747:   TextWidget ctx;
                   1748:    XEvent *event;
                   1749: {
                   1750:    StartAction(ctx, event);
                   1751:     _XtTextScroll(ctx, max(1, ctx->text.lt.lines - 2));
                   1752:     ctx->text.insertPos = ctx->text.lt.top;
                   1753:    EndAction(ctx);
                   1754: }
                   1755: 
                   1756: static MovePreviousPage(ctx, event)
                   1757:   TextWidget ctx;
                   1758:    XEvent *event;
                   1759: {
                   1760:    StartAction(ctx, event);
                   1761:     _XtTextScroll(ctx, -max(1, ctx->text.lt.lines - 2));
                   1762:     ctx->text.insertPos = ctx->text.lt.top;
                   1763:    EndAction(ctx);
                   1764: }
                   1765: 
                   1766: 
                   1767: 
                   1768: 
                   1769: /* delete routines */
                   1770: 
                   1771: static DeleteForwardChar(ctx, event)
                   1772:     TextWidget ctx;
                   1773:    XEvent *event;
                   1774: {
                   1775:     XtTextPosition next;
                   1776: 
                   1777:    StartAction(ctx, event);
                   1778:     next = ctx->text.source->scan(
                   1779:             ctx->text.source, ctx->text.insertPos, XtstPositions, 
                   1780:            XtsdRight, 1, TRUE);
                   1781:     DeleteOrKill(ctx, ctx->text.insertPos, next, FALSE);
                   1782:    EndAction(ctx);
                   1783: }
                   1784: 
                   1785: static DeleteBackwardChar(ctx, event)
                   1786:     TextWidget ctx;
                   1787:    XEvent *event;
                   1788: {
                   1789:     XtTextPosition next;
                   1790: 
                   1791:    StartAction(ctx, event);
                   1792:     next = ctx->text.source->scan(
                   1793:             ctx->text.source, ctx->text.insertPos, XtstPositions, 
                   1794:            XtsdLeft, 1, TRUE);
                   1795:     DeleteOrKill(ctx, next, ctx->text.insertPos, FALSE);
                   1796:    EndAction(ctx);
                   1797: }
                   1798: 
                   1799: static DeleteForwardWord(ctx, event)
                   1800:     TextWidget ctx;
                   1801:    XEvent *event;
                   1802: {
                   1803:     XtTextPosition next;
                   1804: 
                   1805:    StartAction(ctx, event);
                   1806:     next = NextPosition(ctx, ctx->text.insertPos, XtstWhiteSpace, XtsdRight);
                   1807:     DeleteOrKill(ctx, ctx->text.insertPos, next, FALSE);
                   1808:    EndAction(ctx);
                   1809: }
                   1810: 
                   1811: static DeleteBackwardWord(ctx, event)
                   1812:     TextWidget ctx;
                   1813:    XEvent *event;
                   1814: {
                   1815:     XtTextPosition next;
                   1816: 
                   1817:    StartAction(ctx, event);
                   1818:     next = NextPosition(ctx, ctx->text.insertPos, XtstWhiteSpace, XtsdLeft);
                   1819:     DeleteOrKill(ctx, next, ctx->text.insertPos, FALSE);
                   1820:    EndAction(ctx);
                   1821: }
                   1822: 
                   1823: static KillForwardWord(ctx, event)
                   1824:     TextWidget ctx;
                   1825:    XEvent *event;
                   1826: {
                   1827:     XtTextPosition next;
                   1828: 
                   1829:    StartAction(ctx, event);
                   1830:     next = NextPosition(ctx, ctx->text.insertPos, XtstWhiteSpace, XtsdRight);
                   1831:     DeleteOrKill(ctx, ctx->text.insertPos, next, TRUE);
                   1832:    EndAction(ctx);
                   1833: }
                   1834: 
                   1835: static KillBackwardWord(ctx, event)
                   1836:     TextWidget ctx;
                   1837:    XEvent *event;
                   1838: {
                   1839:     XtTextPosition next;
                   1840: 
                   1841:    StartAction(ctx, event);
                   1842:     next = NextPosition(ctx, ctx->text.insertPos, XtstWhiteSpace, XtsdLeft);
                   1843:     DeleteOrKill(ctx, next, ctx->text.insertPos, TRUE);
                   1844:    EndAction(ctx);
                   1845: }
                   1846: 
                   1847: static KillCurrentSelection(ctx, event)
                   1848:     TextWidget ctx;
                   1849:    XEvent *event;
                   1850: {
                   1851:    StartAction(ctx, event);
                   1852:     DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, TRUE);
                   1853:    EndAction(ctx);
                   1854: }
                   1855: 
                   1856: static DeleteCurrentSelection(ctx, event)
                   1857:     TextWidget ctx;
                   1858:    XEvent *event;
                   1859: {
                   1860:    StartAction(ctx, event);
                   1861:     DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, FALSE);
                   1862:    EndAction(ctx);
                   1863: }
                   1864: 
                   1865: static KillToEndOfLine(ctx, event)
                   1866:     TextWidget ctx;
                   1867:    XEvent *event;
                   1868: {
                   1869:     int     line;
                   1870:     XtTextPosition last, next;
                   1871:    StartAction(ctx, event);
                   1872:     _XtTextShowPosition(ctx);
                   1873:     line = LineForPosition(ctx, ctx->text.insertPos);
                   1874:     last = ctx->text.lt.info[line + 1].position;
                   1875:     next = ctx->text.source->scan(ctx->text.source, ctx->text.insertPos,
                   1876:        XtstEOL, XtsdRight, 1, FALSE);
                   1877:     if (last > ctx->text.lastPos)
                   1878:        last = ctx->text.lastPos;
                   1879:     if (last > next && ctx->text.insertPos < next)
                   1880:        last = next;
                   1881:     DeleteOrKill(ctx, ctx->text.insertPos, last, TRUE);
                   1882:    EndAction(ctx);
                   1883: }
                   1884: 
                   1885: static KillToEndOfParagraph(ctx, event)
                   1886:     TextWidget ctx;
                   1887:    XEvent *event;
                   1888: {
                   1889:     XtTextPosition next;
                   1890: 
                   1891:    StartAction(ctx, event);
                   1892:     next = ctx->text.source->scan(ctx->text.source, ctx->text.insertPos, XtstEOL, XtsdRight,
                   1893:            1, FALSE);
                   1894:     if (next == ctx->text.insertPos)
                   1895:        next = ctx->text.source->scan(ctx->text.source, next, XtstEOL, XtsdRight, 1, TRUE);
                   1896:     DeleteOrKill(ctx, ctx->text.insertPos, next, TRUE);
                   1897:    EndAction(ctx);
                   1898: }
                   1899: 
                   1900: static int InsertNewLineAndBackup(ctx, event)
                   1901:   TextWidget ctx;
                   1902:    XEvent *event;
                   1903: {
                   1904:    StartAction(ctx, event);
                   1905:    InsertNewLineAndBackupInternal(ctx);
                   1906:    EndAction(ctx);
                   1907: }
                   1908: 
                   1909: static int InsertNewLineAndBackupInternal(ctx)
                   1910:   TextWidget ctx;
                   1911: {
                   1912:     XtTextBlock text;
                   1913:     text.length = 1;
                   1914:     text.ptr = "\n";
                   1915:     text.firstPos = 0;
                   1916:     if (ReplaceText(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) {
                   1917:        XBell( XtDisplay(ctx), 50);
                   1918:        return(EDITERROR);
                   1919:     }
                   1920:     _XtTextSetNewSelection(ctx, (XtTextPosition) 0, (XtTextPosition) 0);
                   1921:     ctx->text.showposition = TRUE;
                   1922:     return(EDITDONE);
                   1923: }
                   1924: 
                   1925: 
                   1926: 
                   1927: static int InsertNewLine(ctx, event)
                   1928:     TextWidget ctx;
                   1929:    XEvent *event;
                   1930: {
                   1931:     XtTextPosition next;
                   1932: 
                   1933:    StartAction(ctx, event);
                   1934:     if (InsertNewLineAndBackupInternal(ctx))
                   1935:        return(EDITERROR);
                   1936:     next = ctx->text.source->scan(ctx->text.source, ctx->text.insertPos,
                   1937:            XtstPositions, XtsdRight, 1, TRUE);
                   1938:     ctx->text.insertPos = next;
                   1939:    EndAction(ctx);
                   1940:     return(EDITDONE);
                   1941: }
                   1942: 
                   1943: 
                   1944: static InsertNewLineAndIndent(ctx, event)
                   1945:   TextWidget ctx;
                   1946:    XEvent *event;
                   1947: {
                   1948:     XtTextBlock text;
                   1949:     XtTextPosition pos1, pos2;
                   1950: 
                   1951:    StartAction(ctx, event);
                   1952:     pos1 = ctx->text.source->scan(ctx->text.source, ctx->text.insertPos, 
                   1953:        XtstEOL, XtsdLeft, 1, FALSE);
                   1954:     pos2 = ctx->text.source->scan(ctx->text.source, pos1, XtstEOL, 
                   1955:        XtsdLeft, 1, TRUE);
                   1956:     pos2 = ctx->text.source->scan(ctx->text.source, pos2, XtstWhiteSpace, 
                   1957:        XtsdRight, 1, TRUE);
                   1958:     text.ptr = _XtTextGetText(ctx, pos1, pos2);
                   1959:     text.length = strlen(text.ptr);
                   1960:     if (InsertNewLine(ctx, event)) return;
                   1961:     if (ReplaceText(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) {
                   1962:        XBell(XtDisplay(ctx), 50);
                   1963:        EndAction(ctx);
                   1964:        return;
                   1965:     }
                   1966:     ctx->text.insertPos = ctx->text.source->scan(ctx->text.source, 
                   1967:        ctx->text.insertPos, XtstPositions, XtsdRight, text.length, TRUE);
                   1968:     XtFree(text.ptr);
                   1969:    EndAction(ctx);
                   1970: }
                   1971: 
                   1972: static NewSelection(ctx, l, r)
                   1973:   TextWidget ctx;
                   1974:   XtTextPosition l, r;
                   1975: {
                   1976:     char   *ptr;
                   1977:     _XtTextSetNewSelection(ctx, l, r);
                   1978:     if (l < r) {
                   1979:        ptr = _XtTextGetText(ctx, l, r);
                   1980:        XStoreBuffer(XtDisplay(ctx), ptr, min(strlen(ptr), MAXCUT), 0);
                   1981:        XtFree(ptr);
                   1982:     }
                   1983: }
                   1984: 
                   1985: static SelectWord(ctx, event)
                   1986:   TextWidget ctx;
                   1987:    XEvent *event;
                   1988: {
                   1989:     XtTextPosition l, r;
                   1990:    StartAction(ctx, event);
                   1991:     l = ctx->text.source->scan(ctx->text.source, ctx->text.insertPos, 
                   1992:        XtstWhiteSpace, XtsdLeft, 1, FALSE);
                   1993:     r = ctx->text.source->scan(ctx->text.source, l, XtstWhiteSpace, 
                   1994:        XtsdRight, 1, FALSE);
                   1995:     NewSelection(ctx, l, r);
                   1996:    EndAction(ctx);
                   1997: }
                   1998: 
                   1999: 
                   2000: static SelectAll(ctx, event)
                   2001:   TextWidget ctx;
                   2002:    XEvent *event;
                   2003: {
                   2004:    StartAction(ctx, event);
                   2005:    NewSelection(ctx, (XtTextPosition) 0, ctx->text.lastPos);
                   2006:    EndAction(ctx);
                   2007: }
                   2008: 
                   2009: static SelectStart(ctx, event)
                   2010:   TextWidget ctx;
                   2011:    XEvent *event;
                   2012: {
                   2013:    StartAction(ctx, event);
                   2014:     AlterSelection(ctx, XtsmTextSelect, XtactionStart);
                   2015:    EndAction(ctx);
                   2016: }
                   2017: 
                   2018: static SelectAdjust(ctx, event)
                   2019:   TextWidget ctx;
                   2020:    XEvent *event;
                   2021: {
                   2022:    StartAction(ctx, event);
                   2023:     AlterSelection(ctx, XtsmTextSelect, XtactionAdjust);
                   2024:    EndAction(ctx);
                   2025: }
                   2026: 
                   2027: static SelectEnd(ctx, event)
                   2028:   TextWidget ctx;
                   2029:    XEvent *event;
                   2030: {
                   2031:    StartAction(ctx, event);
                   2032:     AlterSelection(ctx, XtsmTextSelect, XtactionEnd);
                   2033:    EndAction(ctx);
                   2034: }
                   2035: 
                   2036: static ExtendStart(ctx, event)
                   2037:   TextWidget ctx;
                   2038:    XEvent *event;
                   2039: {
                   2040:    StartAction(ctx, event);
                   2041:     AlterSelection(ctx, XtsmTextExtend, XtactionStart);
                   2042:    EndAction(ctx);
                   2043: }
                   2044: 
                   2045: static ExtendAdjust(ctx, event)
                   2046:   TextWidget ctx;
                   2047:    XEvent *event;
                   2048: {
                   2049:    StartAction(ctx, event);
                   2050:     AlterSelection(ctx, XtsmTextExtend, XtactionAdjust);
                   2051:    EndAction(ctx);
                   2052: }
                   2053: 
                   2054: static ExtendEnd(ctx, event)
                   2055:   TextWidget ctx;
                   2056:    XEvent *event;
                   2057: {
                   2058:    StartAction(ctx, event);
                   2059:     AlterSelection(ctx, XtsmTextExtend, XtactionEnd);
                   2060:    EndAction(ctx);
                   2061: }
                   2062: 
                   2063: 
                   2064: static RedrawDisplay(ctx, event)
                   2065:   TextWidget ctx;
                   2066:    XEvent *event;
                   2067: {
                   2068:    StartAction(ctx, event);
                   2069:     ForceBuildLineTable(ctx);
                   2070:     DisplayTextWindow(ctx);
                   2071:    EndAction(ctx);
                   2072: }
                   2073: 
                   2074: 
                   2075: _XtTextAbortDialog(ctx, event)
                   2076:   TextWidget ctx;
                   2077:    XEvent *event;
                   2078: {
                   2079:    StartAction(ctx, event);
                   2080:     if (ctx->text.dialog) {
                   2081:        XtDestroyWidget(ctx->text.dialog);
                   2082:        ctx->text.dialog = NULL;
                   2083:     }
                   2084:    EndAction(ctx);
                   2085: }
                   2086: 
                   2087: 
                   2088: /* Insert a file of the given name into the text.  Returns 0 if file found, 
                   2089:    -1 if not. */
                   2090: 
                   2091: static InsertFileNamed(ctx, str)
                   2092:   TextWidget ctx;
                   2093:   char *str;
                   2094: {
                   2095:     int fid;
                   2096:     XtTextBlock text;
                   2097:     char    buf[1000];
                   2098:     XtTextPosition position;
                   2099: 
                   2100:     if (str == NULL || strlen(str) == 0) return -1;
                   2101:     fid = open(str, O_RDONLY);
                   2102:     if (fid <= 0) return -1;
                   2103:     _XtTextPrepareToUpdate(ctx);
                   2104:     position = ctx->text.insertPos;
                   2105:     while ((text.length = read(fid, buf, 512)) > 0) {
                   2106:        text.ptr = buf;
                   2107:        (void) ReplaceText(ctx, position, position, &text);
                   2108:        position = ctx->text.source->scan(ctx->text.source, position, 
                   2109:                XtstPositions, XtsdRight, text.length, TRUE);
                   2110:     }
                   2111:     (void) close(fid);
                   2112:     ctx->text.insertPos = position;
                   2113:     _XtTextExecuteUpdate(ctx);
                   2114:     return 0;
                   2115: }
                   2116: 
                   2117: static DoInsert(ctx)
                   2118:   TextWidget ctx;
                   2119: {
                   2120: /* can't do dialog boxes yet
                   2121:     if (InsertFileNamed(ctx, XtDialogGetValueString(XtDisplay(ctx), ctx->text.dialog)))
                   2122:        XBell(XtDisplay(ctx), 50);
                   2123:     else
                   2124:        _XtTextAbortDialog(ctx);
                   2125: */
                   2126: }
                   2127: 
                   2128: static TextFocusIn (ctx, event)
                   2129:   TextWidget ctx;
                   2130:    XEvent *event;
                   2131: { ctx->text.hasfocus = TRUE; }
                   2132: 
                   2133: static void TextFocusOut(ctx, event)
                   2134:   TextWidget ctx;
                   2135:    XEvent *event;
                   2136: { ctx->text.hasfocus = FALSE; }
                   2137: 
                   2138: #define STRBUFSIZE 100
                   2139: 
                   2140: static XComposeStatus compose_status = {NULL, 0};
                   2141: static InsertChar(ctx, event)
                   2142:   TextWidget ctx;
                   2143:    XEvent *event;
                   2144: {
                   2145:    char strbuf[STRBUFSIZE];
                   2146:    int     keycode;
                   2147:    XtTextBlock text;
                   2148:    text.length = XLookupString (event, strbuf, STRBUFSIZE,
                   2149:                 &keycode, &compose_status);
                   2150:    if (text.length==0) return;
                   2151:    StartAction(ctx, event);
                   2152:    text.ptr = &strbuf[0];;
                   2153:    text.firstPos = 0;
                   2154:    if (ReplaceText(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) {
                   2155:        XBell(XtDisplay(ctx), 50);
                   2156:        EndAction(ctx);
                   2157:        return;
                   2158:     }
                   2159:     ctx->text.insertPos =
                   2160:        (*(ctx->text.source->scan))(ctx->text.source, ctx->text.insertPos,
                   2161:                            XtstPositions, XtsdRight, text.length, TRUE);
                   2162:         _XtTextSetNewSelection(ctx, ctx->text.insertPos, ctx->text.insertPos);
                   2163: 
                   2164:    EndAction(ctx);
                   2165: }
                   2166: 
                   2167: static InsertFile(ctx, event)
                   2168:   TextWidget ctx;
                   2169:    XEvent *event;
                   2170: {
                   2171:     char *ptr;
                   2172:     XtTextBlock text;
                   2173: 
                   2174: /* this depends on dialog boxes...
                   2175: 
                   2176:    StartAction(ctx, event);
                   2177:     if (ctx->text.source->editType(ctx->text.source) != XttextEdit) {
                   2178:        XBell(XtDisplay(ctx), 50);
                   2179:        EndAction(ctx);
                   2180:        return;
                   2181:     }
                   2182:     if (ctx->text.s.left < ctx->text.s.right) {
                   2183:        ptr = _XtTextGetText(ctx, ctx->text.s.left, ctx->text.s.right);
                   2184:        DeleteCurrentSelection(ctx);
                   2185:        if (InsertFileNamed(ctx, ptr)) {
                   2186:            XBell( XtDisplay(ctx), 50);
                   2187:            text.ptr = ptr;
                   2188:            text.length = strlen(ptr);
                   2189:            (void) ReplaceText(ctx, ctx->text.insertPos, ctx->text.insertPos, &text);
                   2190:            ctx->text.s.left = ctx->text.insertPos;
                   2191:            ctx->text.s.right = ctx->text.insertPos = 
                   2192:                ctx->text.source->scan(ctx->text.source, ctx->text.insertPos, 
                   2193:                  XtstPositions, XtsdRight, text.length, TRUE);
                   2194:        }
                   2195:        XtFree(ptr);
                   2196:        EndAction(ctx);
                   2197:        return;
                   2198:     }
                   2199:     if (ctx->text.dialog)
                   2200:        _XtTextAbortDialog(ctx);
                   2201:     ctx->text.dialog = XtDialogCreate( XtDisplay(ctx), ctx->text.w, "Insert File:", "", (ArgList)NULL, 0);
                   2202:     XtDialogAddButton( XtDisplay(ctx), ctx->text.dialog, "Abort", _XtTextAbortDialog, (caddr_t)ctx);
                   2203:     XtDialogAddButton( XtDisplay(ctx), ctx->text.dialog, "DoIt", DoInsert, (caddr_t)ctx);
                   2204:     XMapWindow( XtDisplay(ctx), ctx->text.dialog);
                   2205:    EndAction(ctx);
                   2206: */
                   2207: }
                   2208: 
                   2209: /* Actions Table */
                   2210: 
                   2211: XtActionsRec textActionsTable [] = {
                   2212: /* motion bindings */
                   2213:   {"forward-character",        (caddr_t)MoveForwardChar},
                   2214:   {"backward-character",       (caddr_t)MoveBackwardChar},
                   2215:   {"forward-word",             (caddr_t)MoveForwardWord},
                   2216:   {"backward-word",            (caddr_t)MoveBackwardWord},
                   2217:   {"forward-paragraph",        (caddr_t)MoveForwardParagraph},
                   2218:   {"backward-paragraph",       (caddr_t)MoveBackwardParagraph},
                   2219:   {"beginning-of-line",        (caddr_t)MoveToLineStart},
                   2220:   {"end-of-line",              (caddr_t)MoveToLineEnd},
                   2221:   {"next-line",                (caddr_t)MoveNextLine},
                   2222:   {"previous-line",            (caddr_t)MovePreviousLine},
                   2223:   {"next-page",                (caddr_t)MoveNextPage},
                   2224:   {"previous-page",            (caddr_t)MovePreviousPage},
                   2225:   {"beginning-of-file",        (caddr_t)MoveBeginningOfFile},
                   2226:   {"end-of-file",              (caddr_t)MoveEndOfFile},
                   2227:   {"scroll-one-line-up",       (caddr_t)ScrollOneLineUp},
                   2228:   {"scroll-one-line-down",     (caddr_t)ScrollOneLineDown},
                   2229: /* delete bindings */
                   2230:   {"delete-next-character",    (caddr_t)DeleteForwardChar},
                   2231:   {"delete-previous-character", (caddr_t)DeleteBackwardChar},
                   2232:   {"delete-next-word",                 (caddr_t)DeleteForwardWord},
                   2233:   {"delete-previous-word",     (caddr_t)DeleteBackwardWord},
                   2234:   {"delete-selection",                 (caddr_t)DeleteCurrentSelection},
                   2235: /* kill bindings */
                   2236:   {"kill-word",                (caddr_t)KillForwardWord},
                   2237:   {"backward-kill-word",       (caddr_t)KillBackwardWord},
                   2238:   {"kill-selection",           (caddr_t)KillCurrentSelection},
                   2239:   {"kill-to-end-of-line",      (caddr_t)KillToEndOfLine},
                   2240:   {"kill-to-end-of-paragraph",         (caddr_t)KillToEndOfParagraph},
                   2241: /* unkill bindings */
                   2242:   {"unkill",                   (caddr_t)UnKill},
                   2243:   {"stuff",                    (caddr_t)Stuff},
                   2244: /* new line stuff */
                   2245:   {"newline-and-indent",       (caddr_t)InsertNewLineAndIndent},
                   2246:   {"newline-and-backup",       (caddr_t)InsertNewLineAndBackup},
                   2247:   {"newline",                  (caddr_t)InsertNewLine},
                   2248: /* Selection stuff */
                   2249:   {"select-word",              (caddr_t)SelectWord},
                   2250:   {"select-all",               (caddr_t)SelectAll},
                   2251:   {"select-start",             (caddr_t)SelectStart},
                   2252:   {"select-adjust",            (caddr_t)SelectAdjust},
                   2253:   {"select-end",               (caddr_t)SelectEnd},
                   2254:   {"extend-start",             (caddr_t)ExtendStart},
                   2255:   {"extend-adjust",            (caddr_t)ExtendAdjust},
                   2256:   {"extend-end",               (caddr_t)ExtendEnd},
                   2257: /* Miscellaneous */
                   2258:   {"redraw-display",           (caddr_t)RedrawDisplay},
                   2259:   {"insert-file",              (caddr_t)InsertFile},
                   2260:   {"insert-char",              (caddr_t)InsertChar},
                   2261:   {"focus-in",                         (caddr_t)TextFocusIn},
                   2262:   {"focus-out",                (caddr_t)TextFocusOut},
                   2263:   {NULL,NULL}
                   2264: };
                   2265: 
                   2266: static char *defaultTextEventBindings[] = {
                   2267: /* motion bindings */
                   2268:     "Ctrl<Key>F:               forward-character()",
                   2269:     "<Key>0xff53:      forward-character()", 
                   2270:     "Ctrl<Key>B:               backward-character()",
                   2271:     "<Key>0xff51:      backward-character()",
                   2272:     "Meta<Key>F:               forward-word()",
                   2273:     "Meta<Key>B:               backward-word()",
                   2274:     "Meta<Key>]:               forward-paragraph()",
                   2275:     "Ctrl<Key>[:               backward-paragraph()",
                   2276:     "Ctrl<Key>A:               beginning-of-line()",
                   2277:     "Ctrl<Key>E:               end-of-line()",
                   2278:     "Ctrl<Key>N:           next-line()",
                   2279:     "<Key>0xff54:      next-line()",
                   2280:     "Ctrl<Key>P:               previous-line()",
                   2281:     "<Key>0xff52:       previous-line()",
                   2282:     "Ctrl<Key>V:               next-page()",
                   2283:     "Meta<Key>V:               previous-page()",
                   2284:     "Meta<Key>\\<:             beginning-of-file()",
                   2285:     "Meta<Key>\\>:             end-of-file()",
                   2286:     "Ctrl<Key>Z:               scroll-one-line-up()",
                   2287:     "Meta<Key>Z:               scroll-one-line-down()",
                   2288: /* delete binding*/
                   2289:     "Ctrl<Key>D:               delete-next-character()",
                   2290:     "Ctrl<Key>H:               delete-previous-character()",
                   2291:     "<Key>0xff7f:      delete-previous-character()",
                   2292:     "<Key>0xffff:      delete-previous-character()",
                   2293:     "<Key>0xff08:      delete-previous-character()",
                   2294:     "Meta<Key>D:               delete-next-word()",
                   2295:     "Meta<Key>H:               delete-previous-word()",
                   2296: /* kill bindings */
                   2297:     "Shift Meta<Key>D:         kill-word()",
                   2298:     "Shift Meta<Key>H:         backward-kill-word()",
                   2299:     "Ctrl<Key>W:               kill-selection()",
                   2300:     "Ctrl<Key>K:               kill-to-end-of-line()",
                   2301:     "Meta<Key>K:               kill-to-end-of-paragraph()",
                   2302: /* unkill bindings */
                   2303:     "Ctrl<Key>Y:               unkill()",
                   2304:     "Meta<Key>Y:               stuff()",
                   2305: /* new line stuff */
                   2306:     "Ctrl<Key>J:               newline-and-indent()",
                   2307:     "<Key>0xff0a:      newline-and-indent()",
                   2308:     "Ctrl<Key>O:               newline-and-backup()",
                   2309:     "Ctrl<Key>M:               newline()",
                   2310:     "<Key>0xff0d:      newline()",
                   2311: /* Miscellaneous */
                   2312:     "Ctrl<Key>L:               redraw-display()",
                   2313:     "Meta<Key>I:               insert-file()",
                   2314:    "<FocusIn>:         focus-in()",
                   2315:    "<FocusOut>:                focus-out()",
                   2316: /* selection stuff */
                   2317:     "<Btn1Down>:       select-start()",
                   2318:     "Button1<PtrMoved>:        extend-adjust()",
                   2319:     "<Btn1Up>:         extend-end()",
                   2320:     "<Btn2Down>:       stuff()",
                   2321:     "<Btn3Down>:       extend-start()",
                   2322:     "Button3<PtrMoved>:        extend-adjust()",
                   2323:     "<Btn3Up>:         extend-end()",
                   2324: /* default character handling */
                   2325:     "<Key>:            insert-char()",
                   2326:     
                   2327:     NULL
                   2328: };
                   2329: 
                   2330: /* grodyness needed because Xrm wants pointer to thing, not thing... */
                   2331: caddr_t defaultTextTranslations = (caddr_t)defaultTextEventBindings;
                   2332: 
                   2333: TextClassRec textClassRec = {
                   2334: /* core fields */
                   2335:     /* superclass       */      (WidgetClass) &widgetClassRec,
                   2336:     /* class_name       */      "Text",
                   2337:     /* widget_size      */      sizeof(TextRec),
                   2338:     /* class_initialize */      NULL,
                   2339:     /* class_inited     */      FALSE,
                   2340:     /* initialize       */      Initialize,
                   2341:     /* realize          */      Realize,
                   2342:     /* actions          */      textActionsTable,
                   2343:     /* num_actions      */      XtNumber(textActionsTable),
                   2344:     /* resources        */      resources,
                   2345:     /* num_ resource    */      XtNumber(resources),
                   2346:     /* xrm_class        */      NULLQUARK,
                   2347:     /* compress_motion    */    TRUE,
                   2348:     /* compress_exposure  */    FALSE,
                   2349:     /* visible_interest */      FALSE,
                   2350:     /* destroy          */      TextDestroy,
                   2351:     /* resize           */      Resize,
                   2352:     /* expose           */      ProcessExposeRegion,
                   2353:     /* set_values       */      XtTextSetValues,
                   2354:     /* accept_focus     */      TextAcceptFocus,
                   2355: };
                   2356: 
                   2357: WidgetClass textWidgetClass = (WidgetClass)&textClassRec;
                   2358: 
                   2359:  

unix.superglobalmegacorp.com

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