Annotation of researchv9/X11/src/X.V11R1/clients/xedit/ps.c, revision 1.1.1.1

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:  

unix.superglobalmegacorp.com

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