|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.