-- Test1Impl.mesa -- written by Bill Paxton, April 1981 -- last edit by Bill Paxton, 28-Jul-81 11:12:03 -- This module provides random testing for editing Text nodes -- Initially was part of EditTestImpl.mesa DIRECTORY EditTest, EditSpan, TextEdit, TextNode, RunReader, RopeReader, RopeInline, RandomLongInt; Test1Impl: PROGRAM IMPORTS EditTest, EditSpan, TextEdit, RunReader, RopeReader, RandomLongInt EXPORTS EditTest = BEGIN OPEN EditTest, spanI:EditSpan, editI:TextEdit, nodeI:TextNode, runrdrI:RunReader, roperdrI:RopeReader, randLI:RandomLongInt; Span: TYPE = nodeI.Span; -- ***** 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, resultStart, resultLen: Offset; sourceRope, newRope, oldRope: Rope; sourceRuns, newRuns, oldRuns: Runs; result: Span; sourceRope _ editI.GetRope[source]; sourceRuns _ editI.GetRuns[source]; oldSize _ editI.Size[dest]; oldRope _ editI.GetRope[dest]; oldRuns _ editI.GetRuns[dest]; BeforeUndo[dest,source]; IF destStart=destEnd AND sourceStart=sourceEnd THEN RETURN; IF sourceStart=sourceEnd THEN { -- doing a delete sourceLen _ resultLen _ 0; resultStart _ destStart; spanI.Delete[TextSpan[dest,destStart,destLen_destEnd-destStart],event] } ELSE { IF destStart=destEnd THEN { -- doing a copy destLen _ 0; result _ spanI.Copy[dest: TextLoc[dest,destStart], source: TextSpan[source,sourceStart,sourceLen_sourceEnd-sourceStart], event: event] } ELSE result _ spanI.Replace[TextSpan[dest,destStart,destLen_destEnd-destStart], TextSpan[source,sourceStart,sourceLen_sourceEnd-sourceStart], FALSE, event]; resultStart _ result.start.where; resultLen _ result.end.where - resultStart + 1 }; newRope _ editI.GetRope[dest]; newRuns _ editI.GetRuns[dest]; IF resultStart # destStart OR resultLen # sourceLen THEN ERROR; 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]; TestUndo[] }; 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; resultStart, resultLen, destStart: Offset; oldSourceRope, newSourceRope, oldDestRope, newDestRope: Rope; oldSourceRuns, newSourceRuns, oldDestRuns, newDestRuns: Runs; moveToRight: BOOLEAN; result: Span; [source,dest] _ PickNodes[]; [sourceStart,sourceEnd] _ PickTwo[source]; IF sourceStart=sourceEnd THEN RETURN; 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]; BeforeUndo[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]; BeforeUndo[source,dest] }; result _ spanI.Move[TextLoc[dest,destLoc], TextSpan[source,sourceStart,sourceLen_sourceEnd-sourceStart], FALSE,after,0,event]; resultStart _ result.start.where; resultLen _ result.end.where - resultStart + 1; IF resultLen # sourceLen THEN ERROR; destStart _ IF dest=source AND destLoc > sourceStart THEN destLoc-sourceLen ELSE destLoc; IF resultStart # destStart THEN ERROR; 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]; TestUndo[] } 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]; TestUndo[]; AdjustLengths[] }}; MoveTextOnto: PUBLIC PROC = { source, dest: Node; destStart, destEnd, destLen, sourceStart, sourceEnd, sourceLen, oldSourceSize, oldDestSize, resultStart, resultLen: Offset; oldSourceRope, newSourceRope, oldDestRope, newDestRope: Rope; oldSourceRuns, newSourceRuns, oldDestRuns, newDestRuns: Runs; result: Span; [source,dest] _ PickNodes[]; [sourceStart,sourceEnd] _ PickTwo[source]; [destStart,destEnd] _ PickTwo[dest]; IF sourceStart=sourceEnd OR destStart=destEnd THEN RETURN; oldSourceSize _ editI.Size[source]; oldDestSize _ editI.Size[dest]; oldDestRope _ editI.GetRope[dest]; oldSourceRope _ editI.GetRope[source]; oldDestRuns _ editI.GetRuns[dest]; oldSourceRuns _ editI.GetRuns[source]; BeforeUndo[source,dest]; result _ spanI.MoveOnto[TextSpan[dest,destStart,destLen_destEnd-destStart], TextSpan[source,sourceStart,sourceLen_sourceEnd-sourceStart], FALSE, event]; resultStart _ result.start.where; resultLen _ result.end.where - resultStart + 1; IF source=dest THEN { newSourceRope _ editI.GetRope[source]; newSourceRuns _ editI.GetRuns[source]; IF sourceStart IN [destStart..destEnd) THEN { IF resultStart # destStart OR resultLen # sourceLen THEN ERROR; 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 { IF resultStart # sourceStart OR resultLen # sourceLen THEN ERROR; 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]; IF resultStart # sourceStart OR resultLen # sourceLen THEN ERROR; CheckRopes[newSourceRope,0,oldSourceRope,0,oldSourceSize]; CheckRuns[newSourceRuns,0,oldSourceRuns,0,oldSourceSize] } ELSE { IF resultStart # destStart-sourceLen OR resultLen # sourceLen THEN ERROR; 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 { IF resultStart # destStart OR resultLen # sourceLen THEN ERROR; 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] }; TestUndo[] } ELSE { newDestRope _ editI.GetRope[dest]; newSourceRope _ editI.GetRope[source]; newDestRuns _ editI.GetRuns[dest]; newSourceRuns _ editI.GetRuns[source]; IF resultStart # destStart OR resultLen # sourceLen THEN ERROR; 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]; TestUndo[]; AdjustLengths[] }}; TransposeText: PUBLIC PROC = { alpha, beta: Node; alphaStart, alphaEnd, betaStart, betaEnd, oldAlphaSize, oldBetaSize: Offset; alphaLen, betaLen, alphaResultStart, alphaResultLen, betaResultStart, betaResultLen: Offset; oldAlphaRope, oldBetaRope, newAlphaRope, newBetaRope: Rope; oldAlphaRuns, oldBetaRuns, newAlphaRuns, newBetaRuns: Runs; betaOnRight: BOOLEAN; alphaResult, betaResult: Span; [alpha,beta] _ PickNodes[]; [alphaStart,alphaEnd] _ PickTwo[alpha]; IF alphaStart=alphaEnd THEN RETURN; 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] }; IF betaStart=betaEnd THEN RETURN; BeforeUndo[alpha,beta]; [alphaResult,betaResult] _ spanI.Transpose[ TextSpan[alpha,alphaStart,alphaLen_alphaEnd-alphaStart], TextSpan[beta,betaStart,betaLen_betaEnd-betaStart], FALSE, event]; alphaResultStart _ alphaResult.start.where; alphaResultLen _ alphaResult.end.where - alphaResultStart + 1; betaResultStart _ betaResult.start.where; betaResultLen _ betaResult.end.where - betaResultStart + 1; IF alphaResultLen # alphaLen OR betaResultLen # betaLen THEN ERROR; 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; IF alphaResultStart # betaStart THEN ERROR; IF betaResultStart # alphaStart+alphaLen-betaLen THEN ERROR; alphaStart _ betaStart; betaStart _ temp; temp _ alphaEnd; alphaEnd _ betaEnd; betaEnd _ temp } ELSE { IF betaResultStart # alphaStart THEN ERROR; IF alphaResultStart # betaStart-alphaLen+betaLen THEN ERROR }; 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]; TestUndo[] } ELSE { IF betaResultStart # alphaStart OR alphaResultStart # betaStart THEN ERROR; 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]; TestUndo[]; AdjustLengths[] }}; END.