-- TextTestImpl.mesa
-- written by Bill Paxton, April 1981
-- last edit by Bill Paxton, 11-Jun-81 15:23:01
-- This module provides random testing for editing Text nodes
-- Initially was part of EditTestImpl.mesa
DIRECTORY
EditTest,
TextEdit,
RopeEdit,
TextNode,
RunReader,
RopeReader,
Rope,
RopeInline,
RandomLongInt;
TextTestImpl: PROGRAM
IMPORTS EditTest, TextEdit, RopeEdit,
RunReader, RopeReader, Rope,
RandomLongInt
EXPORTS EditTest =
BEGIN
OPEN
rI:Rope,
EditTest,
editI:TextEdit,
ropeI:RopeEdit,
nodeI:TextNode,
runrdrI:RunReader,
roperdrI:RopeReader,
randLI:RandomLongInt;
-- ***** Text Edit operations
ReplaceText: PUBLIC PROC = {
source, dest: Node;
destStart, destEnd, sourceStart, sourceEnd: Offset;
[source,dest] ← PickNodes[];
[destStart,destEnd] ← PickTwo[dest];
[sourceStart,sourceEnd] ← PickTwo[source];
DoReplaceText[dest, source, destStart, destEnd, sourceStart, sourceEnd];
AdjustLength[dest] };
DoReplaceText: PROC [
dest, source: Node, destStart, destEnd, sourceStart, sourceEnd: Offset] = {
destLen, sourceLen, oldPos, newPos, oldSize: Offset;
sourceRope, newRope, oldRope: Rope;
sourceRuns, newRuns, oldRuns: Runs;
sourceRope ← editI.GetRope[source];
sourceRuns ← editI.GetRuns[source];
oldSize ← editI.Size[dest];
oldRope ← editI.GetRope[dest];
oldRuns ← editI.GetRuns[dest];
editI.ReplaceText[
dest,destStart,destLen←destEnd-destStart,
source,sourceStart,sourceLen←sourceEnd-sourceStart];
newRope ← editI.GetRope[dest];
newRuns ← editI.GetRuns[dest];
CheckSize[dest,oldSize+sourceLen-destLen];
CheckRopes[newRope,0,oldRope,0,destStart];
CheckRopes[newRope,destStart,sourceRope,sourceStart,sourceLen];
oldPos ← destStart+destLen; newPos ← destStart+sourceLen;
CheckRopes[newRope,newPos,oldRope,oldPos,oldSize-oldPos];
CheckRuns[newRuns,0,oldRuns,0,destStart];
CheckRuns[newRuns,destStart,sourceRuns,sourceStart,sourceLen];
CheckRuns[newRuns,newPos,oldRuns,oldPos,oldSize-oldPos] };
DeleteText: PUBLIC PROC = {
node: Node ← PickNode[];
DeleteFromNode[node];
AdjustLength[node] };
DeleteFromNode: PUBLIC PROC [node: Node] = {
start, end: Offset;
[start,end] ← PickTwo[node];
DoReplaceText[node,NIL,start,end,0,0] };
CopyText: PUBLIC PROC = {
source, dest: Node;
destLoc, sourceStart, sourceEnd: Offset;
[source,dest] ← PickNodes[];
[sourceStart,sourceEnd] ← PickTwo[source];
destLoc ← PickOne[dest];
DoReplaceText[dest, source, destLoc, destLoc, sourceStart, sourceEnd];
AdjustLength[dest] };
MoveText: PUBLIC PROC = {
source, dest: Node;
destLoc, sourceStart, sourceEnd, sourceLen, oldSourceSize, oldDestSize: Offset;
oldSourceRope, newSourceRope, oldDestRope, newDestRope: Rope;
oldSourceRuns, newSourceRuns, oldDestRuns, newDestRuns: Runs;
moveToRight: BOOLEAN;
[source,dest] ← PickNodes[];
[sourceStart,sourceEnd] ← PickTwo[source];
IF source=dest THEN {
IF moveToRight←RandomBoolean[] THEN { -- move to right
size: Offset ← editI.Size[source];
IF size=sourceEnd THEN RETURN; -- cannot move to right
destLoc ← randLI.Choose[sourceEnd,size] }
ELSE { -- move to left
IF sourceStart=0 THEN RETURN; -- cannot move to left
destLoc ← randLI.Choose[0,sourceStart] };
oldSourceSize ← oldDestSize ← editI.Size[dest];
oldSourceRope ← oldDestRope ← editI.GetRope[dest];
oldSourceRuns ← oldDestRuns ← editI.GetRuns[dest] }
ELSE {
destLoc ← PickOne[dest];
oldSourceSize ← editI.Size[source];
oldDestSize ← editI.Size[dest];
oldDestRope ← editI.GetRope[dest];
oldSourceRope ← editI.GetRope[source];
oldDestRuns ← editI.GetRuns[dest];
oldSourceRuns ← editI.GetRuns[source] };
editI.MoveText[dest,destLoc,source,sourceStart,sourceLen←sourceEnd-sourceStart];
IF source=dest THEN {
newSourceRope ← editI.GetRope[source];
newSourceRuns ← editI.GetRuns[source];
CheckSize[source,oldSourceSize];
IF moveToRight THEN { -- switch so like moving to left
temp: Offset ← destLoc;
destLoc ← sourceStart;
sourceStart ← sourceEnd;
sourceEnd ← temp;
sourceLen ← sourceEnd-sourceStart };
CheckRopes[newSourceRope,0,oldSourceRope,0,destLoc];
CheckRopes[newSourceRope,destLoc,oldSourceRope,sourceStart,sourceLen];
CheckRopes[newSourceRope,destLoc+sourceLen,oldSourceRope,destLoc,
sourceStart-destLoc];
CheckRopes[newSourceRope,sourceEnd,oldSourceRope,sourceEnd,
oldSourceSize-sourceEnd];
CheckRuns[newSourceRuns,0,oldSourceRuns,0,destLoc];
CheckRuns[newSourceRuns,destLoc,oldSourceRuns,sourceStart,sourceLen];
CheckRuns[newSourceRuns,destLoc+sourceLen,oldSourceRuns,destLoc,
sourceStart-destLoc];
CheckRuns[newSourceRuns,sourceEnd,oldSourceRuns,sourceEnd,
oldSourceSize-sourceEnd] }
ELSE {
newDestRope ← editI.GetRope[dest];
newSourceRope ← editI.GetRope[source];
newDestRuns ← editI.GetRuns[dest];
newSourceRuns ← editI.GetRuns[source];
CheckSize[source,oldSourceSize-sourceLen];
CheckSize[dest,oldDestSize+sourceLen];
CheckRopes[newDestRope,0,oldDestRope,0,destLoc];
CheckRopes[newDestRope,destLoc,oldSourceRope,sourceStart,sourceLen];
CheckRopes[newDestRope,destLoc+sourceLen,oldDestRope,destLoc,
oldDestSize-destLoc];
CheckRopes[newSourceRope,0,oldSourceRope,0,sourceStart];
CheckRopes[newSourceRope,sourceStart,oldSourceRope,sourceEnd,
oldSourceSize-sourceEnd];
CheckRuns[newDestRuns,0,oldDestRuns,0,destLoc];
CheckRuns[newDestRuns,destLoc,oldSourceRuns,sourceStart,sourceLen];
CheckRuns[newDestRuns,destLoc+sourceLen,oldDestRuns,destLoc,
oldDestSize-destLoc];
CheckRuns[newSourceRuns,0,oldSourceRuns,0,sourceStart];
CheckRuns[newSourceRuns,sourceStart,oldSourceRuns,sourceEnd,
oldSourceSize-sourceEnd];
AdjustLengths[] }};
MoveTextOnto: PUBLIC PROC = {
source, dest: Node;
destStart, destEnd, destLen, sourceStart, sourceEnd, sourceLen,
oldSourceSize, oldDestSize: Offset;
oldSourceRope, newSourceRope, oldDestRope, newDestRope: Rope;
oldSourceRuns, newSourceRuns, oldDestRuns, newDestRuns: Runs;
[source,dest] ← PickNodes[];
[sourceStart,sourceEnd] ← PickTwo[source];
[destStart,destEnd] ← PickTwo[dest];
oldSourceSize ← editI.Size[source];
oldDestSize ← editI.Size[dest];
oldDestRope ← editI.GetRope[dest];
oldSourceRope ← editI.GetRope[source];
oldDestRuns ← editI.GetRuns[dest];
oldSourceRuns ← editI.GetRuns[source];
editI.MoveTextOnto[dest,destStart,destLen←destEnd-destStart,
source,sourceStart,sourceLen←sourceEnd-sourceStart];
IF source=dest THEN {
newSourceRope ← editI.GetRope[source];
newSourceRuns ← editI.GetRuns[source];
IF sourceStart IN [destStart..destEnd) THEN {
CheckRopes[newSourceRope,0,oldSourceRope,0,destStart];
CheckRopes[newSourceRope,destStart,oldSourceRope,sourceStart,sourceLen];
CheckRuns[newSourceRuns,0,oldSourceRuns,0,destStart];
CheckRuns[newSourceRuns,destStart,oldSourceRuns,sourceStart,sourceLen];
IF sourceEnd IN [destStart..destEnd] THEN {
CheckSize[source,oldSourceSize+sourceLen-destLen];
CheckRopes[newSourceRope,destStart+sourceLen,
oldSourceRope,destEnd,oldSourceSize-destEnd];
CheckRuns[newSourceRuns,destStart+sourceLen,
oldSourceRuns,destEnd,oldSourceSize-destEnd] }
ELSE { CheckSize[source,oldSourceSize+destStart-sourceStart];
CheckRopes[newSourceRope,destStart+sourceLen,
oldSourceRope,sourceEnd,oldSourceSize-sourceEnd];
CheckRuns[newSourceRuns,destStart+sourceLen,
oldSourceRuns,sourceEnd,oldSourceSize-sourceEnd] }}
ELSE IF sourceEnd IN [destStart..destEnd) THEN {
CheckSize[source,oldSourceSize+sourceEnd-destEnd];
CheckRopes[newSourceRope,0,oldSourceRope,0,sourceEnd];
CheckRopes[newSourceRope,sourceEnd,
oldSourceRope,destEnd,oldSourceSize-destEnd];
CheckRuns[newSourceRuns,0,oldSourceRuns,0,sourceEnd];
CheckRuns[newSourceRuns,sourceEnd,
oldSourceRuns,destEnd,oldSourceSize-destEnd] }
ELSE IF sourceStart < destStart THEN {
IF sourceEnd >= destEnd THEN {
CheckSize[source,oldSourceSize];
CheckRopes[newSourceRope,0,oldSourceRope,0,oldSourceSize];
CheckRuns[newSourceRuns,0,oldSourceRuns,0,oldSourceSize] }
ELSE { CheckSize[source,oldSourceSize-destLen];
CheckRopes[newSourceRope,0,oldSourceRope,0,sourceStart];
CheckRopes[newSourceRope,sourceStart,
oldSourceRope,sourceEnd,destStart-sourceEnd];
CheckRopes[newSourceRope,sourceStart+destStart-sourceEnd,
oldSourceRope,sourceStart,sourceLen];
CheckRopes[newSourceRope,destStart,
oldSourceRope,destEnd,oldSourceSize-destEnd];
CheckRuns[newSourceRuns,0,oldSourceRuns,0,sourceStart];
CheckRuns[newSourceRuns,sourceStart,
oldSourceRuns,sourceEnd,destStart-sourceEnd];
CheckRuns[newSourceRuns,sourceStart+destStart-sourceEnd,
oldSourceRuns,sourceStart,sourceLen];
CheckRuns[newSourceRuns,destStart,
oldSourceRuns,destEnd,oldSourceSize-destEnd] }}
ELSE { CheckSize[source,oldSourceSize-destLen];
CheckRopes[newSourceRope,0,oldSourceRope,0,destStart];
CheckRopes[newSourceRope,destStart,
oldSourceRope,sourceStart,sourceLen];
CheckRopes[newSourceRope,destStart+sourceLen,
oldSourceRope,destEnd,sourceStart-destEnd];
CheckRopes[newSourceRope,sourceEnd-destLen,
oldSourceRope,sourceEnd,oldSourceSize-sourceEnd];
CheckRuns[newSourceRuns,0,oldSourceRuns,0,destStart];
CheckRuns[newSourceRuns,destStart,
oldSourceRuns,sourceStart,sourceLen];
CheckRuns[newSourceRuns,destStart+sourceLen,
oldSourceRuns,destEnd,sourceStart-destEnd];
CheckRuns[newSourceRuns,sourceEnd-destLen,
oldSourceRuns,sourceEnd,oldSourceSize-sourceEnd] }}
ELSE { newDestRope ← editI.GetRope[dest];
newSourceRope ← editI.GetRope[source];
newDestRuns ← editI.GetRuns[dest];
newSourceRuns ← editI.GetRuns[source];
CheckSize[source,oldSourceSize-sourceLen];
CheckSize[dest,oldDestSize+sourceLen-destLen];
CheckRopes[newDestRope,0,oldDestRope,0,destStart];
CheckRopes[newDestRope,destStart,oldSourceRope,sourceStart,sourceLen];
CheckRopes[newDestRope,destStart+sourceLen,oldDestRope,destEnd,
oldDestSize-destEnd];
CheckRopes[newSourceRope,0,oldSourceRope,0,sourceStart];
CheckRopes[newSourceRope,sourceStart,oldSourceRope,sourceEnd,
oldSourceSize-sourceEnd];
CheckRuns[newDestRuns,0,oldDestRuns,0,destStart];
CheckRuns[newDestRuns,destStart,oldSourceRuns,sourceStart,sourceLen];
CheckRuns[newDestRuns,destStart+sourceLen,oldDestRuns,destEnd,
oldDestSize-destEnd];
CheckRuns[newSourceRuns,0,oldSourceRuns,0,sourceStart];
CheckRuns[newSourceRuns,sourceStart,oldSourceRuns,sourceEnd,
oldSourceSize-sourceEnd];
AdjustLengths[] }};
TransposeText: PUBLIC PROC = {
alpha, beta: Node;
alphaStart, alphaEnd, betaStart, betaEnd, oldAlphaSize, oldBetaSize,
alphaLen, betaLen: Offset;
oldAlphaRope, oldBetaRope, newAlphaRope, newBetaRope: Rope;
oldAlphaRuns, oldBetaRuns, newAlphaRuns, newBetaRuns: Runs;
betaOnRight: BOOLEAN;
[alpha,beta] ← PickNodes[];
[alphaStart,alphaEnd] ← PickTwo[alpha];
IF alpha=beta THEN {
oldAlphaSize ← oldBetaSize ← editI.Size[alpha];
oldAlphaRope ← oldBetaRope ← editI.GetRope[alpha];
oldAlphaRuns ← oldBetaRuns ← editI.GetRuns[alpha];
IF betaOnRight←RandomBoolean[] THEN {
-- pick beta section to right of alpha
IF alphaEnd=oldAlphaSize THEN RETURN; -- cannot
[betaStart,betaEnd] ← ChooseTwo[alphaEnd,oldAlphaSize] }
ELSE { -- pick beta section to left of alpha
IF alphaStart=0 THEN RETURN; -- cannot
[betaStart,betaEnd] ← ChooseTwo[0,alphaStart] }}
ELSE {
oldAlphaSize ← editI.Size[alpha];
oldBetaSize ← editI.Size[beta];
oldAlphaRope ← editI.GetRope[alpha];
oldBetaRope ← editI.GetRope[beta];
oldAlphaRuns ← editI.GetRuns[alpha];
oldBetaRuns ← editI.GetRuns[beta];
[betaStart,betaEnd] ← PickTwo[beta] };
editI.TransposeText[
alpha,alphaStart,alphaEnd-alphaStart,
beta,betaStart,betaEnd-betaStart];
IF alpha = beta THEN {
newAlphaRope ← editI.GetRope[alpha];
newAlphaRuns ← editI.GetRuns[alpha];
CheckSize[alpha,oldAlphaSize];
IF ~betaOnRight THEN { -- switch so like beta section on right
temp: Offset ← alphaStart;
alphaStart ← betaStart;
betaStart ← temp;
temp ← alphaEnd;
alphaEnd ← betaEnd;
betaEnd ← temp };
alphaLen ← alphaEnd-alphaStart;
betaLen ← betaEnd-betaStart;
CheckRopes[newAlphaRope,0,oldAlphaRope,0,alphaStart];
CheckRopes[newAlphaRope,alphaStart,oldAlphaRope,betaStart,betaLen];
CheckRopes[newAlphaRope,alphaStart+betaLen,oldAlphaRope,
alphaEnd,betaStart-alphaEnd];
CheckRopes[newAlphaRope,alphaStart+betaEnd-alphaEnd,
oldAlphaRope,alphaStart,alphaLen];
CheckRopes[newAlphaRope,betaEnd,oldAlphaRope,betaEnd,
oldAlphaSize-betaEnd];
CheckRuns[newAlphaRuns,0,oldAlphaRuns,0,alphaStart];
CheckRuns[newAlphaRuns,alphaStart,oldAlphaRuns,betaStart,betaLen];
CheckRuns[newAlphaRuns,alphaStart+betaLen,oldAlphaRuns,
alphaEnd,betaStart-alphaEnd];
CheckRuns[newAlphaRuns,alphaStart+betaEnd-alphaEnd,
oldAlphaRuns,alphaStart,alphaLen];
CheckRuns[newAlphaRuns,betaEnd,oldAlphaRuns,betaEnd,
oldAlphaSize-betaEnd] }
ELSE {
alphaLen ← alphaEnd-alphaStart;
betaLen ← betaEnd-betaStart;
newBetaRope ← editI.GetRope[beta];
newAlphaRope ← editI.GetRope[alpha];
newBetaRuns ← editI.GetRuns[beta];
newAlphaRuns ← editI.GetRuns[alpha];
CheckSize[alpha,oldAlphaSize-alphaLen+betaLen];
CheckSize[beta,oldBetaSize-betaLen+alphaLen];
CheckRopes[newAlphaRope,0,oldAlphaRope,0,alphaStart];
CheckRopes[newAlphaRope,alphaStart,oldBetaRope,betaStart,betaLen];
CheckRopes[newAlphaRope,alphaStart+betaLen,oldAlphaRope,
alphaEnd,oldAlphaSize-alphaEnd];
CheckRopes[newBetaRope,0,oldBetaRope,0,betaStart];
CheckRopes[newBetaRope,betaStart,oldAlphaRope,alphaStart,alphaLen];
CheckRopes[newBetaRope,betaStart+alphaLen,oldBetaRope,
betaEnd,oldBetaSize-betaEnd];
CheckRuns[newAlphaRuns,0,oldAlphaRuns,0,alphaStart];
CheckRuns[newAlphaRuns,alphaStart,oldBetaRuns,betaStart,betaLen];
CheckRuns[newAlphaRuns,alphaStart+betaLen,oldAlphaRuns,
alphaEnd,oldAlphaSize-alphaEnd];
CheckRuns[newBetaRuns,0,oldBetaRuns,0,betaStart];
CheckRuns[newBetaRuns,betaStart,oldAlphaRuns,alphaStart,alphaLen];
CheckRuns[newBetaRuns,betaStart+alphaLen,oldBetaRuns,
betaEnd,oldBetaSize-betaEnd];
AdjustLengths[] }};
ReplaceByChar: PUBLIC PROC = {
dest: Node ← PickNode[];
destStart, destEnd, destLen, oldSize, oldPos, newPos: Offset;
newRope, oldRope: Rope;
newRuns, oldRuns: Runs;
inherit: BOOLEAN ← RandomBoolean[];
looks: Looks;
IF ~inherit THEN looks ← PickLooks[];
[destStart,destEnd] ← PickTwo[dest];
oldSize ← editI.Size[dest];
oldRope ← editI.GetRope[dest];
oldRuns ← editI.GetRuns[dest];
editI.ReplaceByChar[dest,'#,destStart,destLen←destEnd-destStart,inherit,looks];
newRope ← editI.GetRope[dest];
newRuns ← editI.GetRuns[dest];
CheckSize[dest,oldSize+1-destLen];
CheckRopes[newRope,0,oldRope,0,destStart];
IF editI.FetchChar[dest,destStart] # '# THEN ERROR;
oldPos ← destStart+destLen; newPos ← destStart+1;
CheckRopes[newRope,newPos,oldRope,oldPos,oldSize-oldPos];
CheckRuns[newRuns,0,oldRuns,0,destStart];
IF ~inherit AND editI.FetchLooks[dest,destStart] # looks THEN ERROR;
CheckRuns[newRuns,newPos,oldRuns,oldPos,oldSize-oldPos];
AdjustLength[dest] };
InsertChar: PUBLIC PROC = {
dest: Node ← PickNode[];
destLoc: Offset ← PickOne[dest];
oldSize, loc, oldPos, newPos: Offset;
newRope, oldRope: Rope;
newRuns, oldRuns: Runs;
inherit: BOOLEAN ← RandomBoolean[];
looks: Looks;
num: NAT ← ChooseNAT[1,20]; -- number of chars to insert
IF ~inherit THEN looks ← PickLooks[];
oldSize ← editI.Size[dest];
oldRope ← editI.GetRope[dest];
oldRuns ← editI.GetRuns[dest];
loc ← destLoc;
FOR i:NAT IN [0..num) DO
editI.InsertChar[dest,'z-i,loc,inherit,looks];
loc ← loc+1;
ENDLOOP;
newRope ← editI.GetRope[dest];
newRuns ← editI.GetRuns[dest];
CheckSize[dest,oldSize+num];
CheckRopes[newRope,0,oldRope,0,destLoc];
loc ← destLoc;
FOR i:NAT IN [0..num) DO
IF editI.FetchChar[dest,loc] # 'z-i THEN ERROR;
IF ~inherit AND editI.FetchLooks[dest,loc] # looks THEN ERROR;
loc ← loc+1;
ENDLOOP;
oldPos ← destLoc; newPos ← destLoc+num;
CheckRopes[newRope,newPos,oldRope,oldPos,oldSize-oldPos];
CheckRuns[newRuns,0,oldRuns,0,destLoc];
CheckRuns[newRuns,newPos,oldRuns,oldPos,oldSize-oldPos];
AdjustLength[dest] };
AppendChar: PUBLIC PROC = {
dest: Node ← PickNode[];
inherit: BOOLEAN ← RandomBoolean[];
looks: Looks;
loc, oldSize: Offset;
newRope, oldRope: Rope;
newRuns, oldRuns: Runs;
num: NAT ← ChooseNAT[1,20]; -- number of chars to append
IF ~inherit THEN looks ← PickLooks[];
oldSize ← editI.Size[dest];
oldRope ← editI.GetRope[dest];
oldRuns ← editI.GetRuns[dest];
FOR i:NAT IN [0..num) DO
editI.AppendChar[dest,'Z-i,inherit,looks];
ENDLOOP;
newRope ← editI.GetRope[dest];
newRuns ← editI.GetRuns[dest];
CheckSize[dest,oldSize+num];
CheckRopes[newRope,0,oldRope,0,oldSize];
loc ← oldSize;
FOR i:NAT IN [0..num) DO
IF editI.FetchChar[dest,loc] # 'Z-i THEN ERROR;
IF ~inherit AND editI.FetchLooks[dest,loc] # looks THEN ERROR;
loc ← loc+1;
ENDLOOP;
CheckRuns[newRuns,0,oldRuns,0,oldSize];
AdjustLength[dest] };
string: REF READONLY TEXT ← "1234567890123456789012345678901234567890";
stringRope: Rope ← rI.FromString[string];
ReplaceByString: PUBLIC PROC = {
dest: Node ← PickNode[];
destStart, destEnd, destLen, oldSize, oldPos, newPos: Offset;
newRope, oldRope: Rope;
newRuns, oldRuns: Runs;
inherit: BOOLEAN ← RandomBoolean[];
looks: Looks;
strStart, strEnd, strLen: NAT;
oldSize ← editI.Size[dest];
oldRope ← editI.GetRope[dest];
oldRuns ← editI.GetRuns[dest];
IF ~inherit THEN looks ← PickLooks[];
[destStart,destEnd] ← PickTwo[dest];
[strStart,strEnd] ← ChooseTwoNATs[0,string.length];
editI.ReplaceByString[dest,string,strStart,strLen←strEnd-strStart,
destStart,destLen←destEnd-destStart,inherit,looks];
newRope ← editI.GetRope[dest];
newRuns ← editI.GetRuns[dest];
CheckSize[dest,oldSize+strLen-destLen];
CheckRopes[newRope,0,oldRope,0,destStart];
CheckRopes[newRope,destStart,stringRope,strStart,strLen];
oldPos ← destStart+destLen; newPos ← destStart+strLen;
CheckRopes[newRope,newPos,oldRope,oldPos,oldSize-oldPos];
CheckRuns[newRuns,0,oldRuns,0,destStart];
IF ~inherit AND strLen>0 AND
editI.FetchLooks[dest,destStart] # looks THEN ERROR;
CheckRuns[newRuns,newPos,oldRuns,oldPos,oldSize-oldPos];
AdjustLength[dest] };
InsertString: PUBLIC PROC = {
dest: Node ← PickNode[];
InsertStringInNode[dest];
AdjustLength[dest] };
InsertStringInNode: PUBLIC PROC [dest: Node] = {
oldSize: Offset;
destLoc: Offset ← PickOne[dest];
inherit: BOOLEAN ← RandomBoolean[];
newRope, oldRope: Rope;
newRuns, oldRuns: Runs;
looks: Looks;
strStart, strEnd, strLen: NAT;
IF ~inherit THEN looks ← PickLooks[];
[strStart,strEnd] ← ChooseTwoNATs[0,string.length];
oldSize ← editI.Size[dest];
oldRope ← editI.GetRope[dest];
oldRuns ← editI.GetRuns[dest];
editI.InsertString[dest,string,strStart,strLen←strEnd-strStart,
destLoc,inherit,looks];
newRope ← editI.GetRope[dest];
newRuns ← editI.GetRuns[dest];
CheckSize[dest,oldSize+strLen];
CheckRopes[newRope,0,oldRope,0,destLoc];
CheckRopes[newRope,destLoc,stringRope,strStart,strLen];
CheckRopes[newRope,destLoc+strLen,oldRope,destLoc,oldSize-destLoc];
CheckRuns[newRuns,0,oldRuns,0,destLoc];
IF ~inherit AND strLen>0 AND
editI.FetchLooks[dest,destLoc] # looks THEN ERROR;
CheckRuns[newRuns,destLoc+strLen,oldRuns,destLoc,oldSize-destLoc] };
AppendString: PUBLIC PROC = {
dest: Node ← PickNode[];
inherit: BOOLEAN ← RandomBoolean[];
looks: Looks;
oldSize: Offset;
newRope, oldRope: Rope;
newRuns, oldRuns: Runs;
strStart, strEnd, strLen: NAT;
IF ~inherit THEN looks ← PickLooks[];
[strStart,strEnd] ← ChooseTwoNATs[0,string.length];
oldSize ← editI.Size[dest];
oldRope ← editI.GetRope[dest];
oldRuns ← editI.GetRuns[dest];
editI.AppendString[dest,string,strStart,strLen←strEnd-strStart,
inherit,looks];
newRope ← editI.GetRope[dest];
newRuns ← editI.GetRuns[dest];
CheckSize[dest,oldSize+strLen];
CheckRopes[newRope,0,oldRope,0,oldSize];
CheckRopes[newRope,oldSize,stringRope,strStart,strLen];
CheckRuns[newRuns,0,oldRuns,0,oldSize];
IF ~inherit AND strLen>0 AND
editI.FetchLooks[dest,oldSize] # looks THEN ERROR;
AdjustLength[dest] };
ReplaceByRope: PUBLIC PROC = {
dest: Node ← PickNode[];
rope: Rope ← PickRope[];
newRope, oldRope: Rope;
newRuns, oldRuns: Runs;
destStart, destEnd, destLen, oldSize, oldPos, newPos, ropeLen: Offset;
inherit: BOOLEAN ← RandomBoolean[];
looks: Looks;
[destStart,destEnd] ← PickTwo[dest];
IF ~inherit THEN looks ← PickLooks[];
oldSize ← editI.Size[dest];
oldRope ← editI.GetRope[dest];
oldRuns ← editI.GetRuns[dest];
ropeLen ← ropeI.Size[rope];
editI.ReplaceByRope[dest,rope,destStart,destLen←destEnd-destStart,inherit,looks];
newRope ← editI.GetRope[dest];
newRuns ← editI.GetRuns[dest];
CheckSize[dest,oldSize+ropeLen-destLen];
CheckRopes[newRope,0,oldRope,0,destStart];
CheckRopes[newRope,destStart,rope,0,ropeLen];
oldPos ← destStart+destLen; newPos ← destStart+ropeLen;
CheckRopes[newRope,newPos,oldRope,oldPos,oldSize-oldPos];
CheckRuns[newRuns,0,oldRuns,0,destStart];
IF ~inherit AND ropeLen>0 AND
editI.FetchLooks[dest,destStart] # looks THEN ERROR;
CheckRuns[newRuns,newPos,oldRuns,oldPos,oldSize-oldPos];
AdjustLength[dest] };
InsertRope: PUBLIC PROC = {
dest: Node ← PickNode[];
destLoc: Offset ← PickOne[dest];
oldSize, ropeLen: Offset;
rope: Rope ← PickRope[];
newRope, oldRope: Rope;
newRuns, oldRuns: Runs;
inherit: BOOLEAN ← RandomBoolean[];
looks: Looks;
IF ~inherit THEN looks ← PickLooks[];
oldSize ← editI.Size[dest];
oldRope ← editI.GetRope[dest];
oldRuns ← editI.GetRuns[dest];
ropeLen ← ropeI.Size[rope];
editI.InsertRope[dest,rope,destLoc,inherit,looks];
newRope ← editI.GetRope[dest];
newRuns ← editI.GetRuns[dest];
CheckSize[dest,oldSize+ropeLen];
CheckRopes[newRope,0,oldRope,0,destLoc];
CheckRopes[newRope,destLoc,rope,0,ropeLen];
CheckRopes[newRope,destLoc+ropeLen,oldRope,destLoc,oldSize-destLoc];
CheckRuns[newRuns,0,oldRuns,0,destLoc];
IF ~inherit AND ropeLen>0 AND
editI.FetchLooks[dest,destLoc] # looks THEN ERROR;
CheckRuns[newRuns,destLoc+ropeLen,oldRuns,destLoc,oldSize-destLoc];
AdjustLength[dest] };
AppendRope: PUBLIC PROC = {
dest: Node ← PickNode[];
rope: Rope ← PickRope[];
oldSize, ropeLen: Offset;
newRope, oldRope: Rope;
newRuns, oldRuns: Runs;
inherit: BOOLEAN ← RandomBoolean[];
looks: Looks;
IF ~inherit THEN looks ← PickLooks[];
oldSize ← editI.Size[dest];
oldRope ← editI.GetRope[dest];
oldRuns ← editI.GetRuns[dest];
ropeLen ← ropeI.Size[rope];
editI.AppendRope[dest,rope,inherit,looks];
newRope ← editI.GetRope[dest];
newRuns ← editI.GetRuns[dest];
CheckSize[dest,oldSize+ropeLen];
CheckRopes[newRope,0,oldRope,0,oldSize];
CheckRopes[newRope,oldSize,rope,0,ropeLen];
CheckRuns[newRuns,0,oldRuns,0,oldSize];
IF ~inherit AND ropeLen>0 AND
editI.FetchLooks[dest,oldSize] # looks THEN ERROR;
AdjustLength[dest] };
END.