-- RopeReaderGetImpl.mesa -- written by Bill Paxton, January 1981 -- last edit by Bill Paxton, December 22, 1981 9:37 am DIRECTORY RopeReader, RopeEditingBLT, Rope, RopeInline; RopeReaderGetImpl: PROGRAM IMPORTS RopeReader, Rope, RopeInline, RopeEditingBLT EXPORTS RopeReader SHARES RopeReader, Rope = BEGIN OPEN RopeReader, RopeInline; GetText: PUBLIC PROC [reader: Ref, txt: Text, length: NAT _ LAST[NAT]] RETURNS [count: NAT] = { rope: ROPE; start: Offset; offset: NAT _ txt.length; [rope, start] _ Position[reader]; count _ Short[MIN[length, InlineSize[rope]-start, txt.max-offset]]; GTxt[rope, start, txt, offset, count]; SetPosition[reader, rope, start+count]; txt.length _ txt.length+count}; BackwardsGetText: PUBLIC PROC [reader: Ref, txt: Text, length: NAT _ LAST[NAT]] RETURNS [count: NAT] = { rope: ROPE; start: Offset; offset: NAT _ txt.length; [rope, start] _ Position[reader]; count _ Short[MIN[length, start, txt.max-offset]]; GTxt[rope, start _ start-count, txt, offset, count]; SetPosition[reader, rope, start]; txt.length _ txt.length+count}; GetString: PUBLIC PROC [reader: Ref, str: String, length: NAT _ LAST[NAT]] RETURNS [count: NAT] = { rope: ROPE; start: Offset; offset: NAT _ str.length; [rope, start] _ Position[reader]; count _ Short[MIN[length, InlineSize[rope]-start, str.maxLength-offset]]; GTxt[rope, start, str, offset, count]; SetPosition[reader, rope, start+count]; str.length _ str.length+count;}; BackwardsGetString: PUBLIC PROC [reader: Ref, str: String, length: NAT _ LAST[NAT]] RETURNS [count: NAT] = { rope: ROPE; start: Offset; offset: NAT _ str.length; [rope, start] _ Position[reader]; count _ Short[MIN[length, start, str.maxLength-offset]]; GTxt[rope, start _ start-count, str, offset, count]; SetPosition[reader, rope, start]; str.length _ str.length+count}; GetChars: PUBLIC PROC [ reader: Ref, chars: REF CharsArray, length: NAT _ LAST[NAT], offset: NAT _ 0] RETURNS [count: NAT] = { rope: ROPE; start: Offset; [rope, start] _ Position[reader]; count _ Short[MIN[length, InlineSize[rope]-start, charsPerArray-offset]]; GTxt[rope, start, chars, offset, count]; SetPosition[reader, rope, start+count]}; BackwardsGetChars: PUBLIC PROC [ reader: Ref, chars: REF CharsArray, length: NAT _ LAST[NAT], offset: NAT _ 0] RETURNS [count: NAT] = { rope: ROPE; start: Offset; [rope, start] _ Position[reader]; count _ Short[MIN[length, start, charsPerArray-offset]]; GTxt[rope, start _ start-count, chars, offset, count]; SetPosition[reader, rope, start]}; GTxt: PROC [base: ROPE, start: Offset, b: REF, offset, len: NAT] = { loc: NAT _ offset; WHILE len # 0 DO WITH x:base SELECT FROM text => { st: NAT _ Short[start]; rem: NAT _ Short[x.length]-st; IF rem > len THEN rem _ QShort[len]; WITH b SELECT FROM chars: REF CharsArray => RopeEditingBLT.TextToArrayBlt[to:chars, toLoc:loc, nChars:rem, from:@x, fromLoc:st]; txt: Text => RopeEditingBLT.TextToTextBlt[to:txt, toLoc:loc, nChars:rem, from:@x, fromLoc:st]; str: String => RopeEditingBLT.TextToStringBlt[to:str, toLoc:loc, nChars:rem, from:@x, fromLoc:st]; ENDCASE => ERROR; RETURN }; node => WITH x:x SELECT FROM object => WITH x.base SELECT FROM y: Chars => { st: NAT _ Short[start]; rem: NAT _ Short[x.size]-st; IF rem > len THEN rem _ QShort[len]; WITH b SELECT FROM chars: REF CharsArray => RopeEditingBLT.ArrayToArrayBlt[to:chars, toLoc:loc, nChars:rem, from:y, fromLoc:st]; txt: Text => RopeEditingBLT.ArrayToTextBlt[to:txt, toLoc:loc, nChars:rem, from:y, fromLoc:st]; str: String => RopeEditingBLT.ArrayToStringBlt[to:str, toLoc:loc, nChars:rem, from:y, fromLoc:st]; ENDCASE => ERROR; RETURN }; ENDCASE => { piecemap: Rope.PieceMapType _ x.pieceMap; data: REF _ x.base; fetch: Rope.FetchType _ x.fetch; rem: Offset _ NonNeg[x.size-start]; IF rem < len THEN { IF rem = 0 THEN EXIT ELSE len _ QShort[rem]}; IF piecemap # NIL THEN { action: PROC [r:ROPE, st: Offset, pl: Offset] RETURNS [BOOLEAN] = { ln: NAT _ Short[pl]; GTxt[r, st, b, loc, ln]; loc _ loc + ln; RETURN [FALSE]}; [] _ piecemap[data, start, len, action]} ELSE WITH b SELECT FROM txt: Text => FOR i: Offset IN [start..start+len) DO txt[loc] _ fetch[data,i]; loc _ loc+1; ENDLOOP; chars: REF CharsArray => FOR i: Offset IN [start..start+len) DO chars[loc] _ fetch[data,i]; loc _ loc+1; ENDLOOP; str: String => FOR i: Offset IN [start..start+len) DO str[loc] _ fetch[data,i]; loc _ loc+1; ENDLOOP; ENDCASE => ERROR; EXIT}; substr => { rem: Offset _ NonNeg[x.size-start]; IF rem < len THEN { IF rem = 0 THEN EXIT ELSE len _ QShort[rem]}; start _ start + x.start; base _ x.base; LOOP}; concat => { xpos: Offset _ x.pos; rem: Offset _ NonNeg[x.size-start]; IF rem < len THEN { IF rem = 0 THEN EXIT ELSE len _ QShort[rem]}; IF start+len <= xpos THEN {base _ x.base; LOOP}; IF start < xpos THEN { subLen: NAT _ Short[xpos-start]; GTxt[x.base, start, b, loc, subLen]; start _ 0; len _ len - subLen; loc _ loc + subLen} ELSE start _ start - xpos; base _ x.rest; LOOP }; replace => { xstart: Offset _ x.start; xnew: Offset _ x.newPos; rem: Offset _ NonNeg[x.size-start]; IF rem < len THEN {IF rem = 0 THEN EXIT ELSE len _ QShort[rem]}; IF start < xstart THEN {subLen: NAT; IF xstart-start >= len THEN {base _ x.base; LOOP}; subLen _ Short[xstart-start]; GTxt[x.base, start, b, loc, subLen]; start _ xstart; len _ len - subLen; loc _ loc + subLen}; IF start < xnew THEN {subLen: NAT; st: Offset _ start - xstart; IF xnew-start >= len THEN {start _ st; base _ x.replace; LOOP}; subLen _ Short[xnew-start]; GTxt[x.replace, st, b, loc, subLen]; start _ xnew; len _ len - subLen; loc _ loc + subLen}; start _ start - xnew + x.oldPos; base _ x.base; LOOP}; ENDCASE => { IF base # NIL THEN ERROR Rope.NoRope; IF len = 0 THEN EXIT ELSE ERROR}; ENDCASE => { IF base # NIL THEN ERROR Rope.NoRope; IF len = 0 THEN EXIT ELSE ERROR}; ENDLOOP}; -- ***** Initialization StartRopeReaderGet: PUBLIC PROC = {}; END.