|
|
1.1 ! root 1: #ifndef lint ! 2: static char rcs_id[] = "$Header: ps.c,v 1.8 87/09/11 08:22:10 toddb Exp $"; ! 3: #endif ! 4: ! 5: /* ! 6: * COPYRIGHT 1987 ! 7: * DIGITAL EQUIPMENT CORPORATION ! 8: * MAYNARD, MASSACHUSETTS ! 9: * ALL RIGHTS RESERVED. ! 10: * ! 11: * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND ! 12: * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. ! 13: * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ! 14: * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ! 15: * ! 16: * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS, ! 17: * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT ! 18: * SET FORTH ABOVE. ! 19: * ! 20: * ! 21: * Permission to use, copy, modify, and distribute this software and its ! 22: * documentation for any purpose and without fee is hereby granted, provided ! 23: * that the above copyright notice appear in all copies and that both that ! 24: * copyright notice and this permission notice appear in supporting documentation, ! 25: * and that the name of Digital Equipment Corporation not be used in advertising ! 26: * or publicity pertaining to distribution of the software without specific, ! 27: * written prior permission. ! 28: */ ! 29: ! 30: /* J. Gringorten */ ! 31: ! 32: #include <sys/types.h> ! 33: #include <sys/stat.h> ! 34: #include <sys/file.h> ! 35: #include <ctype.h> ! 36: #include "xedit.h" ! 37: ! 38: XtTextPosition PSgetLastPos(); ! 39: ! 40: #define PieceSize(qp) (qp->endPos - qp->begPos) ! 41: ! 42: typedef struct _qp{ ! 43: struct _qp *flink, *blink; ! 44: XtTextSource **src; ! 45: int begPos, endPos; ! 46: } PieceQueueElement; ! 47: ! 48: typedef struct _cb{ ! 49: struct _cb *flink, *blink; ! 50: PieceQueueElement *retiredQHead, *retiredQTail; ! 51: PieceQueueElement *addedPtrFirst, *addedPtrLast, *where, *Rptr, *Lptr; ! 52: XtTextPosition Rfix, Lfix, deletedPos; ! 53: }ChangeBlock; ! 54: ! 55: typedef struct { ! 56: XtTextSource *ro, *ao; ! 57: PieceQueueElement *PTQHead, *PTQTail, *lastAddedPiece, *LocatedPiece; ! 58: int endPos; ! 59: XtTextPosition aoPos, lastReplaceEndPos, LocatedPiecePos; ! 60: ChangeBlock *CQHead, *CQTail, *LastUndid; ! 61: } PSContext; ! 62: ! 63: static PieceQueueElement *getQp() ! 64: { ! 65: return((PieceQueueElement *)calloc(sizeof(PieceQueueElement), 1)); ! 66: } ! 67: ! 68: static PieceQueueElement *remqueue(head, tail, this) ! 69: PieceQueueElement **head, **tail, *this; ! 70: { ! 71: PieceQueueElement *prev = this->blink; ! 72: PieceQueueElement *next = this->flink; ! 73: if (this == *head){ ! 74: if(this == *tail) { ! 75: *head = 0; ! 76: *tail = 0; ! 77: } else { ! 78: *head = next; ! 79: next->blink = 0; ! 80: } ! 81: } else { ! 82: if(this == *tail){ ! 83: *tail = prev; ! 84: prev->flink = 0; ! 85: } else { ! 86: prev->flink = next; ! 87: next->blink = prev; ! 88: } ! 89: } ! 90: this->blink = 0; ! 91: this->flink = 0; ! 92: return (this); ! 93: } ! 94: ! 95: static freeQp(this) ! 96: PieceQueueElement* this; ! 97: { ! 98: free((int*)this); ! 99: } ! 100: ! 101: /* ! 102: * insert 'new' queue element on 'where' ! 103: */ ! 104: static PieceQueueElement *insert(head, tail, new, where) ! 105: PieceQueueElement **head, **tail, *new, *where; ! 106: { ! 107: if(!where){ ! 108: new->flink = *head; ! 109: *head = new; ! 110: } else { ! 111: new->flink = where->flink; ! 112: new->blink = where; ! 113: where->flink = new; ! 114: } ! 115: if(new->flink == 0) ! 116: *tail = new; ! 117: else ! 118: new->flink->blink = new; ! 119: return(new); ! 120: } ! 121: ! 122: retire(ctx, qp) ! 123: PSContext *ctx; ! 124: PieceQueueElement *qp; ! 125: { ! 126: remqueue(&ctx->PTQHead, &ctx->PTQTail, qp); ! 127: insert(&(ctx->CQTail->retiredQHead), &(ctx->CQTail->retiredQTail), ! 128: qp, ctx->CQTail->retiredQTail); ! 129: ctx->endPos -= (PieceSize(qp)); ! 130: } ! 131: static total; ! 132: static PieceQueueElement *locate(ctx, skew, pos) ! 133: XtTextPosition pos; ! 134: int *skew; ! 135: PSContext *ctx; ! 136: { ! 137: /* referential locality optimizations go here */ ! 138: XtTextPosition t; ! 139: PieceQueueElement *qp; ! 140: /*printf("locate %d %d\n", total++, pos); */ ! 141: if ((pos == ctx->endPos) && (ctx->PTQTail)){ ! 142: qp = ctx->PTQTail; ! 143: *skew = PieceSize(qp); ! 144: ctx->LocatedPiece = qp; ! 145: ctx->LocatedPiecePos = pos - *skew; ! 146: return qp; ! 147: } ! 148: if( (ctx->LocatedPiece) && ! 149: (qp = ctx->LocatedPiece->flink) && ! 150: (pos >= (t = ctx->LocatedPiecePos + PieceSize(ctx->LocatedPiece))) && ! 151: (pos < PieceSize(qp) + t)){ ! 152: /* do nothing more! */ ! 153: } else { ! 154: t = 0; ! 155: for(qp = ctx->PTQHead; qp; qp = qp->flink){ ! 156: if (t + PieceSize(qp) > pos) ! 157: break; ! 158: t += (PieceSize(qp)); ! 159: } ! 160: } ! 161: *skew = pos - t; ! 162: ctx->LocatedPiece = qp; ! 163: ctx->LocatedPiecePos = t; ! 164: return qp; ! 165: } ! 166: ! 167: /* ! 168: * split begin and end pieces and delete if necessary unused pieces. ! 169: * return queue pointer of position to be inserted in back of. ! 170: */ ! 171: PieceQueueElement *deleteRange(ctx, startPos, endPos) ! 172: PSContext *ctx; ! 173: XtTextPosition startPos, endPos; ! 174: { ! 175: PieceQueueElement *qp, *beg, *end, *victim; ! 176: XtTextPosition t, skew, range = endPos - startPos; ! 177: ChangeBlock *cb = ctx->CQTail; ! 178: if(endPos == 0) ! 179: return 0; ! 180: qp = locate(ctx, &skew, startPos); ! 181: t = startPos - skew; ! 182: if (!skew){ ! 183: if( t + PieceSize(qp) == endPos){ ! 184: /* desired range is contained in the one piece exactly */ ! 185: beg = qp->blink; ! 186: retire(ctx, qp); ! 187: return beg; ! 188: } else if( t + PieceSize(qp) > endPos){ ! 189: /* desired range is front portion of one piece */ ! 190: beg = qp->blink; ! 191: cb->Rptr = qp; ! 192: cb->Rfix = qp->begPos; ! 193: qp->begPos += range; ! 194: ctx->endPos -= range; ! 195: return beg; ! 196: } ! 197: } else { ! 198: if( t + PieceSize(qp) == endPos){ ! 199: /* range is the back portion of one piece */ ! 200: cb->Lptr = qp; ! 201: cb->Lfix = qp->endPos; ! 202: qp->endPos -= range; ! 203: ctx->endPos -= range; ! 204: return qp; ! 205: } ! 206: } ! 207: if(skew){ ! 208: if( t + PieceSize(qp) < endPos){ ! 209: /* deleted range extends off this piece, so lop off end of it */ ! 210: t += PieceSize(qp); ! 211: beg = qp->flink; ! 212: cb->Lptr = qp; ! 213: cb->Lfix = qp->endPos; ! 214: ctx->endPos -= PieceSize(qp) - skew; ! 215: qp->endPos = qp->begPos + skew; ! 216: } else { ! 217: /* enter a new piece by splitting the first piece */ ! 218: beg = insert(&ctx->PTQHead, &ctx->PTQTail, getQp(), qp); ! 219: beg->endPos = qp->endPos; ! 220: cb->Lfix = qp->endPos; ! 221: cb->Lptr = qp; ! 222: qp->endPos = qp->begPos + (startPos - t); ! 223: beg->begPos = qp->endPos; ! 224: beg->src = qp->src; ! 225: cb->addedPtrFirst = cb->addedPtrLast = beg; ! 226: if (!range) ! 227: return (qp); ! 228: t += PieceSize(qp); /* bump 't' up to beg*/ ! 229: if( t + PieceSize(beg) > endPos){ ! 230: /* range size < sizof(beg) */ ! 231: ctx->endPos -= (endPos - t); ! 232: beg->begPos += (endPos - t); ! 233: return qp; ! 234: } ! 235: } ! 236: } else ! 237: beg = qp; ! 238: /* locate queue entry that contains the last position, deleting others on the way*/ ! 239: victim = 0; ! 240: for(qp = beg; qp; qp = qp->flink){ ! 241: if (victim){ ! 242: retire(ctx, victim); ! 243: victim = 0; ! 244: } ! 245: if( t + (PieceSize(qp)) >= endPos) ! 246: break; ! 247: t += (PieceSize(qp)); ! 248: victim = qp; ! 249: } ! 250: if( t + (PieceSize(qp)) == endPos){ ! 251: end = qp->blink; ! 252: retire(ctx, qp); ! 253: return (end); ! 254: } ! 255: /* implied split and delete first half of last piece */ ! 256: cb->Rfix = qp->begPos; ! 257: cb->Rptr = qp; ! 258: ctx->endPos -= (endPos - t); ! 259: qp->begPos += (endPos - t); ! 260: return (qp->blink); ! 261: } ! 262: ! 263: ! 264: static PSContext *ctx_public; /* debug hack **************************XXX */ ! 265: ! 266: DoQ() ! 267: { ! 268: XtTextBlock t, *text; ! 269: int i; ! 270: char c; ! 271: int end, count; ! 272: PieceQueueElement *qp; ! 273: PSContext *ctx = ctx_public; ! 274: text = &t; ! 275: text->length = 1; ! 276: text->firstPos = 0; ! 277: count = 0; ! 278: for(qp = ctx->PTQHead; qp; qp = qp->flink){ ! 279: printf("%d\t%d\t%s\t", qp->begPos, qp->endPos, (*qp->src == ctx-> ao) ? ! 280: "ao":"ro", *qp->src); ! 281: end = (PieceSize(qp)>20)?(qp->begPos)+20:qp->endPos; ! 282: for(i=qp->begPos; i<end; i++){ ! 283: (*(*qp->src)->read)(*qp->src, i, text, 1); ! 284: c = text->ptr[0]; ! 285: if (isprint(c)) ! 286: putchar(c); ! 287: else ! 288: printf("/%d/", c); ! 289: } ! 290: printf("\n"); ! 291: count++; ! 292: } ! 293: printf("%d piece%c\n", count, (count>1)?'s':' '); ! 294: if(!fork()) ! 295: abort(); ! 296: } ! 297: ! 298: ! 299: #define RightPiece(qp, s2Pos) \ ! 300: { \ ! 301: s2Pos += (PieceSize(qp)); \ ! 302: qp = qp->flink; \ ! 303: } ! 304: ! 305: #define LeftPiece(qp, s2Pos) \ ! 306: { \ ! 307: qp = qp->blink; \ ! 308: s2Pos -= (PieceSize(qp)); \ ! 309: } ! 310: static XtTextPosition PSscan (src, pos, sType, dir, count, include) ! 311: XtTextSource *src; ! 312: XtTextPosition pos; ! 313: ScanType sType; ! 314: ScanDirection dir; ! 315: int count, include; ! 316: { ! 317: int skew, index, ddir,i; ! 318: XtTextPosition s2Pos, rightmost, leftmost; ! 319: PSContext *ctx = (PSContext *)src->data; ! 320: PieceQueueElement *qp; ! 321: index = pos; ! 322: if(sType == XtstPositions){ ! 323: ddir = (dir == XtsdRight) ? 1 : -1; ! 324: if (!include && count > 0) ! 325: count--; ! 326: index = (index + count * ddir); ! 327: index = (index < 0) ? 0 : ((index > ctx->endPos) ? ctx->endPos : index); ! 328: return index; ! 329: } ! 330: if(sType == XtstFile){ ! 331: if(dir == XtsdRight) ! 332: return PSgetLastPos(src); ! 333: else ! 334: return 0; ! 335: } ! 336: qp = locate(ctx, &skew, pos); ! 337: s2Pos = pos - skew; ! 338: if(dir == XtsdRight){ ! 339: for(i=0; i<count; i++){ ! 340: if(!qp) ! 341: return(ctx->endPos); ! 342: if (!scan_right(&s2Pos, &skew, &leftmost, &rightmost, &qp, sType)){ ! 343: rightmost = leftmost = ctx->endPos; ! 344: } ! 345: } ! 346: return ((include) ? rightmost : leftmost); ! 347: } else { ! 348: if(!qp) ! 349: return 0; ! 350: if(!skew){ ! 351: LeftPiece(qp, s2Pos); ! 352: if(!qp) ! 353: return 0; ! 354: skew = PieceSize(qp); ! 355: } ! 356: for(i=0; i<count; i++){ ! 357: if(!qp) ! 358: return(0); ! 359: if (!scan_left(&s2Pos, &skew, &leftmost, &rightmost, &qp, sType)){ ! 360: rightmost = leftmost = 0; ! 361: } ! 362: } ! 363: return ((!include) ? rightmost : leftmost); ! 364: } ! 365: } ! 366: ! 367: scan_right(_s2Pos, _skew, _leftmost, _rightmost, _qp, sType) ! 368: XtTextPosition *_s2Pos; /* s2 pos of begin this qp (bi) */ ! 369: XtTextPosition *_skew; /* offset of actual s2 loc into qp (bi) */ ! 370: XtTextPosition *_rightmost; /* s2 pos of end of target+1 (ret) */ ! 371: XtTextPosition *_leftmost; /* s2 pos of begin this qp (ret) */ ! 372: PieceQueueElement **_qp; /* piece to start at. */ ! 373: ScanType sType; ! 374: { ! 375: PieceQueueElement *qp = *_qp; ! 376: XtTextPosition s2Pos = *_s2Pos; ! 377: XtTextPosition leftmost = *_leftmost; ! 378: XtTextPosition rightmost = *_rightmost; ! 379: XtTextPosition skew = *_skew; ! 380: XtTextPosition actual, ppos, res; ! 381: ppos = qp->begPos + skew; ! 382: while(qp){ ! 383: res = (*(*qp->src)->scan)(*qp->src, ppos, sType, XtsdRight, 1, 0); ! 384: if(res < qp->endPos){ ! 385: break; ! 386: } ! 387: RightPiece(qp, s2Pos); ! 388: if(qp) ! 389: ppos = qp->begPos; ! 390: else ! 391: return(0); ! 392: } ! 393: leftmost = s2Pos + (res - qp->begPos); ! 394: res = (*(*qp->src)->scan)(*qp->src, ppos, sType, XtsdRight, 1, 1); ! 395: if(res < qp->endPos){ ! 396: rightmost = s2Pos + (res - qp->begPos); ! 397: skew = (res - qp->begPos); ! 398: } else { ! 399: RightPiece(qp, s2Pos); ! 400: while(qp){ ! 401: res = (*(*qp->src)->scan)(*qp->src, qp->begPos, sType, XtsdRight, 1, 0); ! 402: if(res != qp->begPos){ ! 403: rightmost = s2Pos; ! 404: skew = 0; ! 405: break; ! 406: } ! 407: res = (*(*qp->src)->scan)(*qp->src, qp->begPos, sType, XtsdRight, 1, 1); ! 408: if(res < qp->endPos){ ! 409: rightmost = s2Pos + (res - qp->begPos); ! 410: skew = (res - qp->begPos); ! 411: break; ! 412: } ! 413: RightPiece(qp, s2Pos); ! 414: rightmost = s2Pos; ! 415: } ! 416: } ! 417: *_s2Pos = s2Pos; ! 418: *_skew = skew; ! 419: *_leftmost = leftmost; ! 420: *_rightmost = rightmost; ! 421: *_qp = qp; ! 422: return 1; ! 423: } ! 424: ! 425: ! 426: scan_left(_s2Pos, _skew, _leftmost, _rightmost, _qp, sType) ! 427: XtTextPosition *_s2Pos; /* s2 pos of begin this qp (bi) */ ! 428: XtTextPosition *_skew; /* offset of actual s2 loc into qp (bi) */ ! 429: XtTextPosition *_rightmost; /* s2 pos of end of target+1 (ret) */ ! 430: XtTextPosition *_leftmost; /* s2 pos of begin this qp (ret) */ ! 431: PieceQueueElement **_qp; /* piece to start at. */ ! 432: ScanType sType; ! 433: { ! 434: PieceQueueElement *qp = *_qp; ! 435: XtTextPosition s2Pos = *_s2Pos; ! 436: XtTextPosition leftmost = *_leftmost; ! 437: XtTextPosition rightmost = *_rightmost; ! 438: XtTextPosition skew = *_skew; ! 439: XtTextPosition ppos, res; ! 440: leftmost = 0; ! 441: ppos = qp->begPos + skew; ! 442: while(qp){ ! 443: res = (*(*qp->src)->scan)(*qp->src, ppos, sType, XtsdLeft, 1, 0); ! 444: if(res > qp->begPos){ ! 445: break; ! 446: } ! 447: LeftPiece(qp, s2Pos); ! 448: if(qp) ! 449: ppos = qp->endPos; ! 450: else ! 451: return(0); ! 452: } ! 453: rightmost = s2Pos + (res - qp->begPos); ! 454: res = (*(*qp->src)->scan)(*qp->src, ppos, sType, XtsdLeft, 1, 1); ! 455: if(res > qp->begPos){ ! 456: leftmost = s2Pos + (res - qp->begPos); ! 457: skew = (res - qp->begPos); ! 458: } else { ! 459: LeftPiece(qp, s2Pos); ! 460: while(qp){ ! 461: res = (*(*qp->src)->scan)(*qp->src, qp->endPos, sType, XtsdLeft, 1, 0); ! 462: if(res != qp->endPos){ ! 463: leftmost = s2Pos + (PieceSize(qp)); ! 464: skew = (PieceSize(qp)); ! 465: break; ! 466: } ! 467: res = (*(*qp->src)->scan)(*qp->src, qp->endPos, sType, XtsdLeft, 1, 1); ! 468: if(res > qp->begPos){ ! 469: leftmost = s2Pos + (res - qp->begPos); ! 470: skew = (res - qp->begPos); ! 471: break; ! 472: } ! 473: leftmost = s2Pos; ! 474: LeftPiece(qp, s2Pos); ! 475: } ! 476: } ! 477: *_s2Pos = s2Pos; ! 478: *_skew = skew; ! 479: *_leftmost = leftmost; ! 480: *_rightmost = rightmost; ! 481: *_qp = qp; ! 482: return 1; ! 483: } ! 484: ! 485: static int PSread (src, pos, text, maxRead) ! 486: XtTextSource *src; ! 487: int pos; ! 488: XtTextBlock *text; ! 489: int maxRead; ! 490: { ! 491: int pieceSize, skew; ! 492: PSContext *ctx = (PSContext *)src->data; ! 493: PieceQueueElement *qp; ! 494: if (maxRead == 0){ ! 495: text->length = 0; ! 496: return(pos); ! 497: } ! 498: qp = locate(ctx, &skew, pos); ! 499: if (!qp){ ! 500: text->length = 0; ! 501: return pos; ! 502: } ! 503: pieceSize = (PieceSize(qp)) - skew; ! 504: if (pieceSize == 0){ ! 505: text->length = 0; ! 506: return pos; ! 507: } ! 508: text->length = (maxRead > pieceSize) ? pieceSize : maxRead; ! 509: (*(*qp->src)->read)(*qp->src, (qp->begPos)+skew, text, text->length); ! 510: text->firstPos = pos; ! 511: return(pos + text->length); ! 512: } ! 513: ! 514: ! 515: static ChangeBlock *getChangeBlock() ! 516: { ! 517: return((ChangeBlock *)calloc(sizeof(ChangeBlock), 1)); ! 518: } ! 519: ! 520: XtTextPosition backoutChange(ctx, change) ! 521: ChangeBlock *change; ! 522: PSContext *ctx; ! 523: { ! 524: ChangeBlock *newcb; ! 525: PieceQueueElement *where, *qp, *next; ! 526: if(!change) ! 527: return -1; ! 528: newcb = (ChangeBlock*) ! 529: insert(&ctx->CQHead, &ctx->CQTail, getChangeBlock(), ctx->CQTail); ! 530: newcb->where = change->where; ! 531: newcb->deletedPos = change->deletedPos; ! 532: qp = change->addedPtrFirst; ! 533: while(qp){ ! 534: next = qp->flink; ! 535: retire(ctx, qp); ! 536: if(qp == change->addedPtrLast) ! 537: break; ! 538: qp = next; ! 539: } ! 540: /* where is the PieceQueue element to put the old stuff back in after */ ! 541: where = change->where; ! 542: /* remqueue the deleted pieces of the retired list, and queue 'em back in PieceQ*/ ! 543: if(change->Lptr){ ! 544: ctx->endPos += change->Lfix - change->Lptr->endPos; ! 545: newcb->Lfix = change->Lptr->endPos; ! 546: change->Lptr->endPos = change->Lfix; ! 547: newcb->Lptr = change->Lptr; ! 548: } ! 549: qp = change->retiredQHead; ! 550: while(qp){ ! 551: next = qp->flink; ! 552: where = insert(&ctx->PTQHead, &ctx->PTQTail, qp, where); ! 553: if(!newcb->addedPtrFirst) ! 554: newcb->addedPtrFirst = where; ! 555: ctx->endPos += PieceSize(qp); ! 556: if(qp == change->retiredQTail) ! 557: break; ! 558: qp = next; ! 559: } ! 560: if(change->Rptr){ ! 561: ctx->endPos += change->Rptr->begPos - change->Rfix; ! 562: newcb->Rfix = change->Rptr->begPos; ! 563: change->Rptr->begPos = change->Rfix; ! 564: newcb->Rptr = change->Rptr; ! 565: } ! 566: if(newcb->addedPtrFirst) ! 567: newcb->addedPtrLast = where; ! 568: return(change->deletedPos); ! 569: } ! 570: ! 571: static int PSreplace(src, startPos, endPos, text, delta) ! 572: XtTextSource *src; ! 573: XtTextPosition startPos, endPos; ! 574: XtTextBlock *text; ! 575: int *delta; ! 576: { ! 577: int wrote, delLength = endPos - startPos; ! 578: PSContext *ctx = (PSContext *)src->data; ! 579: PieceQueueElement *here; ! 580: ChangeBlock *cb; ! 581: ctx->LocatedPiece = 0; ! 582: if(startPos < 0){ ! 583: if(!ctx->CQTail) ! 584: return -1; ! 585: ctx->LastUndid = ctx->CQTail; ! 586: return(backoutChange(ctx, ctx->CQTail)); ! 587: } else if(endPos < 0){ ! 588: if(!ctx->LastUndid) ! 589: return -1; ! 590: ctx->LastUndid = ctx->LastUndid->blink; ! 591: return(backoutChange(ctx, ctx->LastUndid)); ! 592: } ! 593: /* ! 594: switch (ctx->editMode) { ! 595: case XttextAppend: ! 596: if (startPos != endPos != data->length) ! 597: return (POSITIONERROR); ! 598: break; ! 599: case XttextRead: ! 600: return (EDITERROR); ! 601: case XttextEdit: ! 602: break; ! 603: default: ! 604: return (EDITERROR); ! 605: } ! 606: */ ! 607: *delta = 0; ! 608: if(startPos > ctx->endPos) ! 609: return (EDITERROR); ! 610: ctx->LastUndid = 0; ! 611: if(text->length) ! 612: (*ctx->ao->replace)(ctx->ao, ctx->aoPos, ctx->aoPos, text, &wrote); ! 613: else { ! 614: wrote = 0; ! 615: if(!endPos) ! 616: return 0; ! 617: } ! 618: if((!delLength)&& (startPos==ctx->lastReplaceEndPos) && (ctx->lastAddedPiece)){ ! 619: here = ctx->lastAddedPiece; ! 620: if(!((here->endPos == ctx->aoPos) && (here->src == &ctx->ao))) ! 621: printf("replace optimize panic 1 \n"); ! 622: here->endPos += wrote; ! 623: } else { ! 624: cb = (ChangeBlock*)insert(&ctx->CQHead, &ctx->CQTail, getChangeBlock(), ctx->CQTail); ! 625: cb->deletedPos = startPos; ! 626: here = deleteRange(ctx, startPos, endPos); ! 627: cb->where = here; ! 628: if(text->length == 0){ ! 629: *delta = (startPos - endPos); ! 630: return (EDITDONE); ! 631: } ! 632: here = insert(&ctx->PTQHead, &ctx->PTQTail, getQp(), here); ! 633: ctx->lastAddedPiece = here; ! 634: here->begPos = ctx->aoPos; ! 635: here->endPos = ctx->aoPos + wrote; ! 636: here->src = &ctx->ao; ! 637: cb->addedPtrFirst = here; ! 638: if(!cb->addedPtrLast) ! 639: cb->addedPtrLast = here; ! 640: } ! 641: ctx->lastReplaceEndPos = startPos + wrote; ! 642: ctx->aoPos += wrote; ! 643: ctx->endPos += wrote; ! 644: *delta = wrote - delLength; ! 645: return (EDITDONE); ! 646: } ! 647: ! 648: static XtTextPosition PSgetLastPos(src) ! 649: XtTextSource *src; ! 650: { ! 651: PSContext *ctx = (PSContext *)src->data; ! 652: /* ! 653: int t; ! 654: PieceQueueElement *qp; ! 655: t = 0; ! 656: for(qp = ctx->PTQHead; qp; qp = qp->flink){ ! 657: t += (PieceSize(qp)); ! 658: } ! 659: if (t != ctx->endPos){ ! 660: printf("piece queue length discrepancy %d <> %d\n", t, ctx->endPos); ! 661: ctx->endPos = t; ! 662: } ! 663: return t; ! 664: */ ! 665: return ctx->endPos; ! 666: } ! 667: ! 668: static PSsetLastPos(src, lastPos) ! 669: XtTextSource *src; ! 670: XtTextPosition lastPos; ! 671: { ! 672: PSContext *ctx = (PSContext *)src->data; ! 673: ctx->endPos = lastPos; ! 674: } ! 675: ! 676: static InitPieceTable(ctx) ! 677: PSContext *ctx; ! 678: { ! 679: XtTextSource **ro = &(ctx->ro); ! 680: PieceQueueElement *qp; ! 681: XtTextPosition beg, end; ! 682: beg = (*(*ro)->scan)(*ro, 0, XtstFile, XtsdLeft, 0,0); ! 683: end = (*(*ro)->scan)(*ro, 0, XtstFile, XtsdRight, 0,0); ! 684: if(beg != end){ ! 685: qp = insert(&ctx->PTQHead, &ctx->PTQTail, getQp(), 0); ! 686: qp->begPos = beg; ! 687: qp->endPos = end; ! 688: qp->src = ro; ! 689: ctx->endPos = PieceSize(qp); ! 690: } ! 691: } ! 692: static XtEditType PSGetEditType(src) ! 693: XtTextSource *src; ! 694: { ! 695: /* ! 696: StringSourcePtr data; ! 697: data = (StringSourcePtr) src->data; ! 698: return(data->editMode); ! 699: */ ! 700: return(XttextEdit); ! 701: } ! 702: ! 703: /*** Public routines ***/ ! 704: ! 705: XtTextSource *CreatePSource (ro, ao) ! 706: XtTextSource *ro, *ao; ! 707: { ! 708: XtTextSource *src; ! 709: PSContext *ctx; ! 710: int i; ! 711: src = (XtTextSource *) malloc(sizeof(XtTextSource)); ! 712: src->read = PSread; ! 713: src->replace = PSreplace; ! 714: src->getLastPos = PSgetLastPos; ! 715: src->setLastPos = PSsetLastPos; ! 716: src->scan = PSscan; ! 717: src->editType = PSGetEditType; ! 718: ctx = (PSContext *)(calloc(sizeof(PSContext),1)); ! 719: ctx->ro = ro; ! 720: ctx->ao = ao; ! 721: InitPieceTable(ctx); ! 722: src->data = (int *)ctx; ! 723: ctx_public = ctx; ! 724: return src; ! 725: } ! 726: ! 727: PSsetROsource(src, ro) ! 728: XtTextSource *src, *ro; ! 729: { ! 730: PSContext *ctx = (PSContext *)src->data; ! 731: ctx->ro = ro; ! 732: } ! 733: ! 734: ! 735: DestroyPSource(src) ! 736: XtTextSource *src; ! 737: { ! 738: PieceQueueElement *qp, *qp_victim; ! 739: ChangeBlock *cb, *cb_victim; ! 740: PSContext *ctx = (PSContext *)src->data; ! 741: cb = ctx->CQHead; ! 742: while(cb){ ! 743: qp = cb->retiredQHead; ! 744: while(qp){ ! 745: qp_victim = qp; ! 746: qp = qp->flink; ! 747: free(qp_victim); ! 748: } ! 749: cb_victim = cb; ! 750: cb = cb->flink; ! 751: free(cb_victim); ! 752: } ! 753: qp = ctx->PTQHead; ! 754: while(qp){ ! 755: qp_victim = qp; ! 756: qp = qp->flink; ! 757: free(qp_victim); ! 758: } ! 759: free(ctx); ! 760: free(src); ! 761: } ! 762: ! 763: PSchanges(src) ! 764: XtTextSource *src; ! 765: { ! 766: PSContext *ctx = (PSContext *)src->data; ! 767: ChangeBlock *cb = ctx->CQHead; ! 768: int i; ! 769: i = 0; ! 770: while(cb){ ! 771: i++; ! 772: cb = cb->flink; ! 773: } ! 774: return i; ! 775: } ! 776: PSbreakInput(src) ! 777: XtTextSource *src; ! 778: { ! 779: PSContext *ctx = (PSContext *)src->data; ! 780: ctx->lastReplaceEndPos = -1; ! 781: } ! 782: ! 783: ! 784:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.