|
|
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.