DIRECTORY RopeReader, Rope, RopeInline; RopeReaderImpl: CEDAR PROGRAM IMPORTS Rope, RopeInline EXPORTS RopeReader SHARES RopeReader, Rope = BEGIN OPEN RopeReader, RopeInline; ReadOffEnd: PUBLIC ERROR = CODE; ReadChar: PUBLIC PROC [reader: Ref, mode: Mode] RETURNS [char: CHAR] = { base: ROPE _ reader.rope; index, current: Offset _ reader.index+reader.current-reader.first; after: Offset _ InlineSize[base]; first: Offset _ 0; OffEnd: PROC RETURNS [CHAR] = { IF ~reader.charForEndOfRope THEN ERROR ReadOffEnd; RETURN [reader.endChar]}; SetReader: PROC = { reader.index _ SELECT mode FROM get => index+1, backwards => index-1, peek, peekbackwards => index, ENDCASE => ERROR; reader.current _ reader.first _ reader.after _ 0}; SetInfo: PROC [txtFlag: BOOLEAN] RETURNS [c: NAT] = { c _ Short[current]; reader.first _ Short[first]; reader.after _ Short[after]; reader.txtFlag _ txtFlag; SELECT mode FROM get => { reader.current _ c+1; reader.index _ index+first-c }; peekbackwards => { reader.current _ c+1; reader.index _ index+first-c-1 }; backwards => { reader.current _ c; reader.index _ index+first-c-1 }; peek => { reader.current _ c; reader.index _ index+first-c }; ENDCASE => ERROR }; SELECT mode FROM backwards, peekbackwards => IF current=0 THEN RETURN[OffEnd[]] ELSE current _ current-1; get, peek => NULL; ENDCASE => ERROR; IF current >= after THEN RETURN[OffEnd[]]; TRUSTED {WHILE base # NIL DO WITH x:base SELECT FROM text => { reader.text _ @x; RETURN [x[SetInfo[TRUE]]] }; node => WITH x:x SELECT FROM object => IF current < x.size THEN WITH x.base SELECT FROM y: Chars => { reader.chars _ y; RETURN [y[SetInfo[FALSE]]] }; ENDCASE => { SetReader; RETURN [x.fetch[x.base, current]] }; substr => IF current < x.size THEN { offset: Offset; current _ current + (offset _ x.start); first _ first + offset; after _ after + offset; base _ x.base; LOOP }; concat => IF current < x.size THEN { xpos: Offset; IF current >= (xpos _ x.pos) THEN { current _ current - xpos; after _ after - xpos; first _ IF first <= xpos THEN 0 ELSE first - xpos; base _ x.rest; LOOP }; IF after > xpos THEN after _ xpos; base _ x.base; LOOP }; replace => IF current < x.size THEN { xstart: Offset _ x.start; newPos, oldPos: Offset; IF current < xstart THEN { IF after > xstart THEN after _ xstart; base _ x.base; LOOP }; IF current < (newPos _ x.newPos) THEN { current _ current - xstart; after _ MIN[after, newPos] - xstart; first _ IF first <= xstart THEN 0 ELSE first-xstart; base _ x.replace; LOOP }; current _ current - newPos + (oldPos _ x.oldPos); after _ after - newPos + oldPos; first _ IF first >= newPos THEN first - newPos + oldPos ELSE oldPos; base _ x.base; LOOP }; ENDCASE => ERROR Rope.NoRope; ENDCASE => ERROR Rope.NoRope; EXIT; ENDLOOP}; RETURN[OffEnd[]]}; StartRopeReader: PUBLIC PROC = {}; END. È-- RopeReaderImpl.mesa -- written by Bill Paxton, January 1981 -- last edit by Bill Paxton, December 22, 1981 10:24 am Last Edited by: Maxwell, January 5, 1983 12:05 pm -- ***** Initialization ʵ˜JšÏc™Jš(™(Jš7™7J™1šÏk ˜ J˜ J˜J˜ J˜—šœž ˜Jšžœ˜Jšžœ ˜Jšžœ˜J˜—Jšžœžœ˜"J˜Jšœ žœžœžœ˜ J˜š Ïnœžœžœžœžœ˜HJšœžœ˜J˜BJ˜!J˜J˜šŸœžœžœžœ˜Jšžœžœžœ ˜2Jšžœ˜J˜—šŸ œžœ˜šœžœž˜J˜J˜J˜Jšžœžœ˜—J˜2J˜—š Ÿœžœ žœžœžœ˜5J˜J˜J˜J˜šžœž˜J˜>J˜JJ˜DJ˜=Jšžœžœ˜J˜——Jšžœž˜š œžœ žœžœ žœ˜XJšœ žœ˜—Jšžœžœ˜Jšžœžœžœ ˜*š žœžœžœžœžœž˜4Jšœžœ žœ˜8šœžœžœž˜š œ žœžœžœžœž˜;Jšœ žœ žœ˜=Jšžœžœ˜<—šœ žœžœ˜$J˜J˜'J˜/Jšœžœ˜—šœ žœžœ˜$J˜ šžœžœ˜#J˜0Jšœžœžœžœ˜3Jšœžœ˜—Jšžœžœžœ˜9—šœ žœžœ˜%J˜J˜šžœžœ˜Jšžœžœ˜&Jšœžœ˜—šžœžœ˜'J˜Jšœžœ˜$Jšœžœžœžœ˜4Jšœžœ˜—J˜1J˜ Jšœžœžœžœ˜DJšœžœ˜—Jšžœžœ ˜—Jšžœžœ ˜Jšžœ˜—Jšžœ˜ Jšžœ ˜J˜—Jš™J˜JšŸœžœžœ˜"J˜J˜Jšžœ˜J˜—…—