DIRECTORY TextEdit, RopeEdit, TiogaNodeOps; WordEditImpl: CEDAR PROGRAM IMPORTS TextEdit, RopeEdit, TiogaNodeOps EXPORTS TextEdit = BEGIN OPEN TextEdit; ReplaceWords: PUBLIC PROC [ destRoot, sourceRoot: RefBranchNode, dest: RefTextNode, destStart: Offset _ 0, destLen: Offset _ MaxLen, source: RefTextNode, sourceStart: Offset _ 0, sourceLen: Offset _ MaxLen, event: Event] RETURNS [resultStart, resultLen: Offset] = { wantLeading, hasLeading, wantTrailing, hasTrailing: BOOLEAN; destSize, sourceSize: Offset; IF source # NIL THEN { sourceSize _ Size[source]; sourceStart _ MIN[MAX[0,sourceStart],sourceSize]; sourceLen _ MIN[MAX[0,sourceLen],sourceSize-sourceStart] } ELSE sourceSize _ sourceStart _ sourceLen _ 0; destSize _ IF dest=source THEN sourceSize ELSE Size[dest]; destStart _ MIN[MAX[0,destStart],destSize]; destLen _ MIN[MAX[0,destLen],destSize-destStart]; IF destLen=0 AND sourceLen=0 THEN RETURN [destStart,0]; [wantLeading,hasLeading,wantTrailing,hasTrailing] _ CheckSpaces[dest,destStart,destLen,destSize,source,sourceStart,sourceLen]; IF hasTrailing AND ~wantTrailing THEN { -- get rid of trailing space sourceLen _ sourceLen-1; hasTrailing _ FALSE }; IF hasLeading AND ~wantLeading THEN { -- get rid of leading space sourceStart _ sourceStart+1; sourceLen _ sourceLen-1; hasLeading _ FALSE }; [] _ ReplaceText[destRoot,sourceRoot, dest,destStart,destLen,source,sourceStart,sourceLen,event]; resultStart _ destStart; resultLen _ sourceLen + AdjustSpaces[wantLeading,hasLeading,wantTrailing,hasTrailing, dest,destStart,sourceLen,event]; [resultStart,resultLen] _ AdjustResults[dest,resultStart,resultLen] }; DeleteWords: PUBLIC OneSpanProc = { [] _ ReplaceWords[root,NIL,text,start,len,NIL,0,MaxLen,event] }; CopyWords: PUBLIC DestSpanProc = { [resultStart,resultLen] _ ReplaceWords[destRoot,sourceRoot, dest,destLoc,0,source,start,len,event] }; MoveWordsOnto: PUBLIC PROC [ destRoot, sourceRoot: RefBranchNode, dest: RefTextNode, destStart: Offset _ 0, destLen: Offset _ MaxLen, source: RefTextNode, sourceStart: Offset _ 0, sourceLen: Offset _ MaxLen, event: Event _ NIL] RETURNS [resultStart, resultLen: Offset] = { sourceSize, destSize, start, len, end, destEnd: Offset; start _ sourceStart; len _ sourceLen; sourceSize _ Size[source]; start _ MIN[MAX[0,start],sourceSize]; len _ MIN[MAX[0,len],sourceSize-start]; end _ start+len; destSize _ IF dest=source THEN sourceSize ELSE Size[dest]; destStart _ MIN[MAX[0,destStart],destSize]; destLen _ MIN[MAX[0,destLen],destSize-destStart]; destEnd _ destStart+destLen; resultStart _ destStart; resultLen _ len; IF source=dest THEN { -- check for overlapping or adjacent IF start IN [destStart..destEnd) THEN { IF end < destEnd THEN [] _ DeleteText[sourceRoot,source,end,destEnd-end,event]; IF start > destStart THEN [] _ DeleteText[sourceRoot,source,destStart,start-destStart,event]; RETURN }; IF end IN (destStart..destEnd) THEN { [] _ DeleteText[sourceRoot,source,end,destEnd-end,event]; RETURN [start,len] }; IF start <= destStart AND end >= destEnd THEN RETURN [start,len]; IF end=destStart THEN { [] _ DeleteText[sourceRoot,source,destStart,destLen,event]; RETURN [start,len] }; IF start=destEnd THEN { [] _ DeleteText[sourceRoot,source,destStart,destLen,event]; RETURN }}; [] _ DeleteText[destRoot,dest,destStart,destLen,event]; IF source=dest AND start > destStart THEN start _ start-destLen; [resultStart,resultLen] _ MoveWords[destRoot,sourceRoot,dest,destStart,source,start,len,event] }; MoveWords: PUBLIC PROC [ destRoot, sourceRoot: RefBranchNode, dest: RefTextNode, destLoc: Offset _ 0, source: RefTextNode, start: Offset _ 0, len: Offset _ MaxLen, event: Event] RETURNS [resultStart, resultLen: Offset] = { wantLeading, hasLeading, wantTrailing, hasTrailing: BOOLEAN; destSize, sourceSize: Offset; sourceSize _ Size[source]; start _ MIN[MAX[0,start],sourceSize]; len _ MIN[MAX[0,len],sourceSize-start]; IF len=0 THEN RETURN [destLoc,0]; destSize _ IF source=dest THEN sourceSize ELSE Size[dest]; IF source=dest AND destLoc IN [start..start+len] THEN RETURN [start,len]; [wantLeading,hasLeading,wantTrailing,hasTrailing] _ CheckSpaces[dest,destLoc,0,destSize,source,start,len]; IF wantTrailing AND ~hasTrailing AND hasLeading AND ~wantLeading AND start+len < sourceSize AND Fetch[source,start]=Fetch[source,start+len] THEN { start _ start+1; hasLeading _ FALSE; hasTrailing _ TRUE }; IF wantLeading AND ~hasLeading AND hasTrailing AND ~wantTrailing AND start > 0 AND Fetch[source,start-1]=Fetch[source,start+len-1] THEN { start _ start-1; hasLeading _ TRUE; hasTrailing _ FALSE }; [] _ MoveText[destRoot,sourceRoot,dest,destLoc,source,start,len,event]; IF source=dest AND destLoc > start THEN destLoc _ destLoc-len; resultStart _ destLoc; resultLen _ len + AdjustSpaces[wantLeading,hasLeading,wantTrailing,hasTrailing, dest,destLoc,len,event]; [resultStart,resultLen] _ AdjustResults[dest,resultStart,resultLen] }; TransposeWords: PUBLIC PROC [ alphaRoot, betaRoot: RefBranchNode, alpha: RefTextNode, alphaStart: Offset _ 0, alphaLen: Offset _ MaxLen, beta: RefTextNode, betaStart: Offset _ 0, betaLen: Offset _ MaxLen, event: Event] RETURNS [alphaResultStart, alphaResultLen, betaResultStart, betaResultLen: Offset] = { SwitchResults: PROC = { start, len: Offset; start _ betaResultStart; len _ betaResultLen; betaResultStart _ alphaResultStart; betaResultLen _ alphaResultLen; alphaResultStart _ start; alphaResultLen _ len }; wantLeadingAlpha, hasLeadingAlpha, wantTrailingAlpha, hasTrailingAlpha: BOOLEAN; wantLeadingBeta, hasLeadingBeta, wantTrailingBeta, hasTrailingBeta: BOOLEAN; alphaSize, betaSize: Offset; alphaCnt, betaCnt: INTEGER; switched: BOOLEAN _ FALSE; alphaSize _ Size[alpha]; alphaStart _ MIN[MAX[0,alphaStart],alphaSize]; alphaLen _ MIN[MAX[0,alphaLen],alphaSize-alphaStart]; betaSize _ IF beta=alpha THEN alphaSize ELSE Size[beta]; betaStart _ MIN[MAX[0,betaStart],betaSize]; betaLen _ MIN[MAX[0,betaLen],betaSize-betaStart]; IF alpha=beta THEN { alphaEnd: Offset; IF alphaStart > betaStart THEN { -- switch them start: Offset _ alphaStart; len: Offset _ alphaLen; root: RefBranchNode _ alphaRoot; alphaStart _ betaStart; betaStart _ start; alphaResultLen _ alphaLen _ betaLen; betaResultLen _ betaLen _ len; alphaRoot _ betaRoot; betaRoot _ root; switched _ TRUE }; alphaEnd _ alphaStart+alphaLen; IF alphaEnd = betaStart THEN { -- turn into a Move instead [betaResultStart,betaResultLen] _ MoveWords[alphaRoot,betaRoot,alpha,alphaStart,alpha,betaStart,betaLen,event]; alphaResultStart _ betaStart+betaResultLen-betaLen; alphaResultLen _ alphaLen; [alphaResultStart,alphaResultLen] _ AdjustResults[alpha,alphaResultStart,alphaResultLen]; IF switched THEN SwitchResults; RETURN }; IF alphaEnd > betaStart THEN { -- overlapping overlap, alphaHeadLen, betaTailLen: Offset; alphaHeadLen _ betaStart-alphaStart; betaTailLen _ betaStart+betaLen-alphaEnd; IF alphaHeadLen < 0 OR betaTailLen < 0 THEN RETURN [alphaStart,alphaLen,betaStart,betaLen]; overlap _ alphaEnd-betaStart; [alphaResultStart,alphaResultLen,betaResultStart,betaResultLen] _ TransposeWords[alphaRoot,betaRoot,alpha,alphaStart,alphaHeadLen, alpha,alphaEnd,betaTailLen,event]; betaResultLen _ betaResultLen+overlap; alphaResultStart _ alphaResultStart-overlap; alphaResultLen _ alphaResultLen+overlap; IF switched THEN SwitchResults; RETURN }}; [wantLeadingAlpha,hasLeadingAlpha,wantTrailingAlpha,hasTrailingAlpha] _ CheckSpaces[alpha,alphaStart,alphaLen,alphaSize,beta,betaStart,betaLen]; [wantLeadingBeta,hasLeadingBeta,wantTrailingBeta,hasTrailingBeta] _ CheckSpaces[beta, betaStart,betaLen,betaSize,alpha,alphaStart,alphaLen]; [] _ TransposeText[alphaRoot,betaRoot,alpha,alphaStart,alphaLen,beta,betaStart,betaLen,event]; betaCnt _ AdjustSpaces[ wantLeadingAlpha,hasLeadingAlpha,wantTrailingAlpha,hasTrailingAlpha, alpha,alphaStart,betaLen,event]; IF alpha=beta THEN betaStart _ betaStart+betaLen-alphaLen+betaCnt; alphaCnt _ AdjustSpaces[wantLeadingBeta,hasLeadingBeta,wantTrailingBeta,hasTrailingBeta, beta,betaStart,alphaLen,event]; alphaResultStart _ betaStart; alphaResultLen _ alphaLen+alphaCnt; [alphaResultStart,alphaResultLen] _ AdjustResults[beta,alphaResultStart,alphaResultLen]; betaResultStart _ alphaStart; betaResultLen _ betaLen+betaCnt; [betaResultStart,betaResultLen] _ AdjustResults[alpha,betaResultStart,betaResultLen]; IF switched THEN SwitchResults }; CheckSpaces: PROC [dest: RefTextNode, destStart, destLen, destSize: Offset, source: RefTextNode, sourceStart, sourceLen: Offset] RETURNS [wantLeading, hasLeading, wantTrailing, hasTrailing: BOOLEAN] = { wantLeading _ WantLeadingSpace[dest,destStart]; wantTrailing _ WantTrailingSpace[dest,destStart+destLen,destSize]; hasLeading _ HasLeadingSpace[source,sourceStart,sourceLen]; hasTrailing _ HasTrailingSpace[source,sourceStart,sourceLen] }; AdjustSpaces: PROC [wantLeading, hasLeading, wantTrailing, hasTrailing: BOOLEAN, dest: RefTextNode, start, len: Offset, event: Event] RETURNS [cnt: INTEGER] = { root: RefBranchNode = TiogaNodeOps.Root[dest]; cnt _ 0; IF hasTrailing AND ~wantTrailing THEN { [] _ DeleteText[root,dest,start+len-1,1,event]; cnt_cnt-1 }; IF ~hasTrailing AND wantTrailing THEN { [] _ InsertChar[root,dest,' ,start+len,TRUE,noLooks,event]; cnt_cnt+1 }; IF hasLeading AND ~wantLeading THEN { [] _ DeleteText[root,dest,start,1,event]; cnt_cnt-1 }; IF ~hasLeading AND wantLeading THEN { [] _ InsertChar[root,dest,' ,start,TRUE,noLooks,event]; cnt_cnt+1 }}; WantLeadingSpace: PROC [dest: RefTextNode, destStart: Offset] RETURNS [BOOLEAN] = INLINE { RETURN [destStart > 0 AND RopeEdit.AlphaNumericChar[FetchChar[dest,destStart-1]]] }; WantTrailingSpace: PROC [dest: RefTextNode, destEnd, destSize: Offset] RETURNS [BOOLEAN] = INLINE { RETURN [destEnd < destSize AND RopeEdit.AlphaNumericChar[FetchChar[dest,destEnd]]] }; HasLeadingSpace: PROC [source: RefTextNode, start, len: Offset] RETURNS [BOOLEAN] = INLINE { RETURN [len > 0 AND RopeEdit.BlankChar[FetchChar[source,start]]] }; HasTrailingSpace: PROC [source: RefTextNode, start, len: Offset] RETURNS [BOOLEAN] = INLINE { RETURN [len > 0 AND RopeEdit.BlankChar[FetchChar[source,start+len-1]]] }; HasFollowingSpace: PROC [source: RefTextNode, end, size: Offset] RETURNS [BOOLEAN] = INLINE { RETURN [end < size AND RopeEdit.BlankChar[FetchChar[source,end]]] }; HasPreceedingSpace: PROC [source: RefTextNode, start: Offset] RETURNS [BOOLEAN] = INLINE { RETURN [start > 0 AND RopeEdit.BlankChar[FetchChar[source,start-1]]] }; AdjustResults: PROC [dest: RefTextNode, start, len: Offset] RETURNS [resultStart, resultLen: Offset] = { size: Offset _ Size[dest]; following: BOOLEAN _ HasFollowingSpace[dest,start+len,size]; preceeding: BOOLEAN _ HasPreceedingSpace[dest,start]; leading: BOOLEAN _ HasLeadingSpace[dest,start,size]; trailing: BOOLEAN _ HasTrailingSpace[dest,start,len]; resultStart _ start; resultLen _ len; IF leading THEN IF trailing THEN { resultLen _ resultLen-1; resultStart _ resultStart+1 } ELSE IF following THEN resultStart _ resultStart+1 ELSE NULL ELSE IF ~trailing THEN IF following THEN resultLen _ resultLen+1 ELSE IF preceeding THEN { resultStart _ resultStart-1; resultLen _ resultLen+1 } ELSE NULL ELSE NULL }; END. ÔWordEditImpl.mesa; written by Bill Paxton, March 1981 edited by McGregor, February 8, 1983 10:00 am edited by Bill Paxton, May 5, 1982 8:27 am ***** Word Editing Operations **** replace the dest words by a copy of the source words delete the specified words copy the specified words move the specified words transpose the alpha words and the beta words returns true if char before destStart is a letter/digit returns true if char after destEnd is a letter/digit Ê ˜Jšœ5™5Jšœ-™-Jšœ*™*J˜šÏk ˜ J˜ J˜ J˜ —J˜šœ ˜Jšœ!˜(Jšœ ˜—Jš˜Jšœ ˜J˜J˜Jšœ"™"J˜šÏn œœœ˜J˜$J˜CJ˜IJ˜ Jšœ%˜,Jšœ4™4Jšœ4œ˜J˜˜OJ˜—J˜FJ˜—šžœœœ˜J˜#J˜FJ˜QJšœO˜VJšœ,™,šž œœ˜J˜J˜-J˜CJ˜1—JšœHœ˜PJšœDœ˜LJ˜Jšœœ˜Jšœ œœ˜J˜Jšœ œœ˜.Jšœ œœ#˜5Jšœ œ œ œ ˜8Jšœ œœ˜+Jšœ œœ ˜1šœ œ˜J˜šœœŸ˜/J˜J˜J˜ J˜*J˜$J˜J˜&Jšœ œ˜—J˜šœœŸ˜:˜!J˜M—J˜3J˜˜#J˜5—Jšœ œ˜Jšœ˜ —šœœŸ˜-J˜+J˜$J˜)šœœ˜+Jšœ)˜/—J˜˜A˜@J˜"——J˜&J˜,J˜(Jšœ œ˜Jšœ˜ ——˜GJ˜H—˜CJ˜H—J˜^˜J˜DJ˜ —Jšœ œ0˜B˜XJ˜—J˜J˜#J˜XJ˜J˜ J˜UJšœ œ˜!J˜—šž œœ:˜KJ˜4Jšœ6œ˜IJ˜/J˜BJ˜;J˜?J˜—šž œœ6œ˜PJšœ5œœ˜OJ˜.J˜šœ œœ˜'J˜<—šœœœ˜'Jšœ'œ˜H—šœ œœ˜%J˜6—šœ œ œ˜%Jšœ#œ˜EJ˜——šžœœ'˜=Jšœœœ˜Jšœ7™7Jšœœ;˜TJ˜—šžœœ/˜FJšœœœ˜Jšœ4™4Jšœœ7˜UJ˜—šžœœ*˜?Jšœœœ˜Jšœ œ0˜CJ˜—šžœœ*˜@Jšœœœ˜Jšœ œ6˜IJ˜—šžœœ)˜@Jšœœœ˜Jšœ œ.˜DJ˜—šžœœ%˜=Jšœœœ˜Jšœ œ2˜GJ˜—šž œœ(˜;Jšœ%˜,J˜Jšœ œ*˜