TextEdit.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
written by Bill Paxton, February 1981
last edit by Bill Paxton, April 23, 1982 6:14 am
last edit by Russ Atkinson, July 22, 1983 9:51 am
Doug Wyatt, March 2, 1985 2:56:18 pm PST
Michael Plass, April 1, 1985 4:05:55 pm PST
=
BEGIN
RefTextNode: TYPE = TextNode.Ref;
ROPE: TYPE = Rope.ROPE;
Looks: TYPE = TextLooks.Looks;
noLooks: Looks = TextLooks.noLooks;
allLooks: Looks = TextLooks.allLooks;
Offset: TYPE = INT;
MaxLen, MaxOffset: INT = LAST[INT];
MaxNat: NAT = LAST[NAT];
Event: TYPE = UndoEvent.Ref;
CharSet:
TYPE ~ [0..256);
-- for XNS 16-bit character set; use in conjunction with 8-bit
CHAR
Note: Character properties are implemented using a ROSARY (an immutable sequence of REFs; see Rosary.mesa), appearing in the CharSets property of the node. The values in this ROSARY are of type REF CharSet.
General operations
FetchChar:
PROC [text: RefTextNode, index:
INT]
RETURNS [charSet: CharSet, char:
CHAR];
fetches the indexed information
use rope readers if want characters from contiguous locations
FetchLooks:
PROC [text: RefTextNode, index:
INT]
RETURNS [Looks];
returns the looks for the character at the given location
use readers if getting looks for sequence of locations
Fetch:
PROC [text: RefTextNode, index:
INT]
RETURNS [charSet: CharSet, char:
CHAR, looks: Looks];
fetches the indexed information, except for character properties
use rope & looks readers if want info from contiguous locations
GetRope:
PROC [text: RefTextNode]
RETURNS [
ROPE];
GetRuns:
PROC [text: RefTextNode]
RETURNS [TextLooks.Runs];
Size:
PROC [text: RefTextNode]
RETURNS [
INT];
Flatten:
PROC [text: RefTextNode]
RETURNS [
BOOL];
returns true if it decides to flatten rope & runs
this is done automatically after a certain number of edits to the node
Operations to add or delete looks
ChangeLooks:
PROC [root: RefTextNode, text: RefTextNode, remove, add: Looks,
start:
INT ← 0, len:
INT ← MaxOffset, event: Event ←
NIL];
first remove then add in the given range
AddLooks:
PROC [root: RefTextNode, text: RefTextNode, add: Looks,
start:
INT ← 0, len:
INT ← MaxOffset, event: Event ←
NIL];
RemoveLooks:
PROC [root: RefTextNode, text: RefTextNode, remove: Looks ← allLooks,
start:
INT ← 0, len:
INT ← MaxOffset, event: Event ←
NIL];
SetLooks:
PROC [root: RefTextNode, text: RefTextNode, new: Looks,
start:
INT ← 0, len:
INT ← MaxOffset, event: Event ←
NIL];
ClearLooks:
PROC [root: RefTextNode, text: RefTextNode,
start:
INT ← 0, len:
INT ← MaxOffset, event: Event ←
NIL];
Character Properties
GetCharProp:
PROC [node: RefTextNode, index:
INT, name:
ATOM]
RETURNS [value:
REF];
PutCharProp:
PROC [node: RefTextNode, index:
INT, name:
ATOM, value:
REF, nChars:
INT ← 1,
event: Event ←
NIL, root: RefTextNode ←
NIL];
Places the value on the character property lists of the chars in the specified range.
Use value = NIL to remove a character property.
MapCharProps:
PROC [node: RefTextNode, index:
INT, action: MapPropsAction]
RETURNS [quit:
BOOL];
Used for traversing all the properites attached to a particular character.
MapPropsAction:
TYPE ~
PROC [name:
ATOM, value:
REF]
RETURNS [quit:
BOOL ←
FALSE];
ModifyCharProps:
PROC [node: RefTextNode, name:
ATOM, index:
INT ← 0, nChars:
INT ←
INT.
LAST, action: ModifyPropsAction, event: Event ←
NIL, root: RefTextNode ←
NIL]
RETURNS [quit:
BOOL];
Used for traversing and altering the values of a character property ofer a range of characters; the action procedure is called for runs of properties, but adjacent runs are not necessarily merged.
ModifyPropsAction:
TYPE ~
PROC [value:
REF, index:
INT, nChars:
INT]
RETURNS [quit:
BOOL ←
FALSE, newValue:
REF];
PropList:
TYPE ~ Atom.PropList;
This property list mechanism regards a PropList as an immutable value.
GetCharPropList: PROC [node: RefTextNode, index: INT] RETURNS [PropList ← NIL];
PutCharPropList:
PROC [node: RefTextNode, index:
INT, propList: PropList, nChars:
INT ← 1, event: Event ←
NIL, root: RefTextNode ←
NIL];
GetPropFromList: PROC [propList: PropList, key: ATOM] RETURNS [value: REF];
PutPropOnList: PROC [propList: PropList, key: ATOM, value: REF] RETURNS [new: PropList];
Editing Operations for text
NOTE: edit operations do not create or delete addrs,
but they can change their locations within the text
TwoSpanProc:
TYPE =
PROC [destRoot, sourceRoot: RefTextNode,
dest: RefTextNode, destStart:
INT ← 0, destLen:
INT ← MaxLen,
source: RefTextNode, sourceStart:
INT ← 0, sourceLen:
INT ← MaxLen,
event: Event ←
NIL]
RETURNS [resultStart, resultLen:
INT];
DestSpanProc:
TYPE =
PROC [destRoot, sourceRoot: RefTextNode,
dest: RefTextNode, destLoc:
INT ← 0,
source: RefTextNode, start:
INT ← 0, len:
INT ← MaxLen,
event: Event ←
NIL]
RETURNS [resultStart, resultLen:
INT];
OneSpanProc:
TYPE =
PROC [root: RefTextNode,
text: RefTextNode, start:
INT ← 0, len:
INT ← MaxLen,
event: Event ←
NIL];
TransposeProc:
TYPE =
PROC [alphaRoot, betaRoot: RefTextNode,
alpha: RefTextNode, alphaStart:
INT ← 0, alphaLen:
INT ← MaxLen,
beta: RefTextNode, betaStart:
INT ← 0, betaLen:
INT ← MaxLen,
event: Event ←
NIL
]
RETURNS [alphaResultStart, alphaResultLen, betaResultStart, betaResultLen:
INT];
ReplaceText: TwoSpanProc;
replace the dest text by a copy of the source text
addrs that are in the replaced text move to destStart
addrs that are after the replaced text are adjusted
DeleteText: OneSpanProc;
delete the specified range of text
addrs that are in the deleted section move to start
CopyText: DestSpanProc;
copy the specified text
add length of inserted text to addrs that are beyond destLoc
MoveText: DestSpanProc;
move [start..start+len) in source to destLoc in dest
no-op if dest=source and destLoc IN [start..start+len]
addrs that are in the moved text do one of the following:
move with the text if dest = source,
or move to start if dest # source
MoveTextOnto: TwoSpanProc;
move [start..start+len) onto [destStart..destStart+destLen)
implemented by appropriate calls on MoveText and DeleteText
TransposeText: TransposeProc;
transpose the alpha text and the beta text
addrs treated same as in Move
move with the text if alpha = beta,
or move to respective starts if alpha # beta
ReplaceByChar:
PROC [root: RefTextNode, dest: RefTextNode, char:
CHAR,
start:
INT ← 0, len:
INT ← MaxLen,
inherit:
BOOL ←
TRUE, looks: Looks ← noLooks,
charSet: CharSet ← 0,
event: Event ←
NIL]
RETURNS [resultStart, resultLen:
INT];
replacement characters don't get any character properties
if inherit is false, char gets specifed looks
if inherit is true, char gets looks in following manner:
if dest length is 0, then gets looks from argument list, else
if start > 0, then gets looks from previous char,
else gets looks from char following replacement
ReplaceByString:
PROC [root: RefTextNode, dest: RefTextNode, string:
REF
READONLY
TEXT,
stringStart:
NAT ← 0, stringNum:
NAT ← MaxNat,
start:
INT ← 0, len:
INT ← MaxLen,
inherit:
BOOL ←
TRUE, looks: Looks ← noLooks,
charSet: CharSet ← 0,
event: Event ←
NIL]
RETURNS [resultStart, resultLen:
INT];
ReplaceByRope:
PROC [root: RefTextNode, dest: RefTextNode, rope:
ROPE,
start:
INT ← 0, len:
INT ← MaxLen,
inherit:
BOOL ←
TRUE, looks: Looks ← noLooks,
charSet: CharSet ← 0,
event: Event ←
NIL]
RETURNS [resultStart, resultLen:
INT];
InsertChar:
PROC [root: RefTextNode, dest: RefTextNode, char:
CHAR, destLoc:
INT ← 0,
inherit:
BOOL ←
TRUE, looks: Looks ← noLooks,
charSet: CharSet ← 0,
event: Event ←
NIL]
RETURNS [resultStart, resultLen:
INT];
AppendChar:
PROC [root: RefTextNode, dest: RefTextNode, char:
CHAR,
inherit:
BOOL ←
TRUE, looks: Looks ← noLooks,
charSet: CharSet ← 0,
event: Event ←
NIL]
RETURNS [resultStart, resultLen:
INT];
InsertString:
PROC [root: RefTextNode, dest: RefTextNode, string:
REF
READONLY
TEXT,
stringStart:
NAT ← 0, stringNum:
NAT ← MaxNat, destLoc:
INT ← 0,
inherit:
BOOL ←
TRUE, looks: Looks ← noLooks,
charSet: CharSet ← 0,
event: Event ←
NIL]
RETURNS [resultStart, resultLen:
INT];
AppendString:
PROC [root: RefTextNode, dest: RefTextNode, string:
REF
READONLY
TEXT,
stringStart:
NAT ← 0, stringNum:
NAT ← MaxNat,
inherit:
BOOL ←
TRUE, looks: Looks ← noLooks,
charSet: CharSet ← 0,
event: Event ←
NIL]
RETURNS [resultStart, resultLen:
INT];
InsertRope:
PROC [root: RefTextNode, dest: RefTextNode, rope:
ROPE, destLoc:
INT ← 0,
inherit:
BOOL ←
TRUE, looks: Looks ← noLooks,
charSet: CharSet ← 0,
event: Event ←
NIL]
RETURNS [resultStart, resultLen:
INT];
AppendRope:
PROC [root: RefTextNode, dest: RefTextNode, rope:
ROPE,
inherit:
BOOL ←
TRUE, looks: Looks ← noLooks,
charSet: CharSet ← 0,
event: Event ←
NIL]
RETURNS [resultStart, resultLen:
INT];
Caps and Lowercase
CapChange:
TYPE = {allCaps, allLower, initCaps, firstCap};
ChangeCaps:
PROC [root: RefTextNode, dest: RefTextNode,
start:
INT ← 0, len:
INT ← MaxLen,
how: CapChange ← allCaps, event: Event ←
NIL];
AllCaps:
PROC [root: RefTextNode, dest: RefTextNode, start:
INT𡤀, len:
INT←MaxLen, event: Event←
NIL];
force specified span to all uppercase
AllLower:
PROC [root: RefTextNode, dest: RefTextNode, start:
INT𡤀, len:
INT←MaxLen, event: Event←
NIL];
force specified span to all lowercase
InitialCaps:
PROC [root: RefTextNode, dest: RefTextNode, start:
INT ← 0, len:
INT ← MaxLen, event: Event ←
NIL];
force first letter of words uppercase