NodeAddrs
AddrsProp: PROC RETURNS [ATOM];
PutTextAddr:
PROC [n: Node, addr:
REF, location:
INT, pin:
BOOL ←
FALSE];
assigns addr to location in text
ok if addr was previously assigned elsewhere in the text
location automatically updated when text is edited
RemTextAddr:
PROC [n: Node, addr:
REF];
removes the given addr
if addr has been moved, does RemTextAddr on new location also
PinTextAddr:
PROC [n: Node, addr:
REF];
don't modify location when edits take place
UnpinTextAddr:
PROC [n: Node, addr:
REF];
UnpinAllAddrs:
PROC [n: Node];
MoveTextAddr:
PROC [from, to: Node, addr:
REF, location:
INT];
does RemTextAddr[from, addr]; PutTextAddr[to, addr, location];
add leaves forwarding address for use by GetTextAddr
GetTextAddr:
PROC [n: Node, addr:
REF]
RETURNS [node: Node, location:
INT];
generates ERROR TextAddrNotFound if the addr is not in the mapping
node may be different than n if addr has been moved
TryGetTextAddr:
PROC [n: Node, addr:
REF]
RETURNS [found:
BOOL, node: Node, location:
INT];
MapTextAddrs:
PROC [n: Node, action: TextAddrsAction]
RETURNS [
BOOL];
apply the action to each addr&location pair for the text
returns true if&when an action returns true
skips pinned or moved addresses
TextAddrsAction:
TYPE =
PROC [addr:
REF, location:
INT]
RETURNS [
BOOL];
Notify proc registration
AddAddrNotifyProc: PROC [proc: AddrNotifyProc];
RemoveAddrNotifyProc:
PROC [proc: AddrNotifyProc];
AddrNotifyProc:
TYPE =
PROC [node: Node, new:
PROC [old:
INT]
RETURNS [
INT]];
Editing Operations for persistent addrs
AddrReplace:
PROC [node: Node, start, len, newlen:
INT];
replace chars in [start..start+len) by newlen chars
addrs that are in the replaced section move to start
add (newlen-len) to addrs that are after the replaced section
Update Functions for persistent addrs
AfterReplace: PROC [initLoc, start, len, newlen: INT] RETURNS [newLoc: INT];
UndoEvent
Event: TYPE = REF EventBody;
EventBody: TYPE = RECORD [subevents: SubEvent];
SubEvent: TYPE = REF SubEventBody;
SubEventBody:
TYPE =
RECORD [
next: SubEvent,
undoProc: UndoProc,
undoRef: REF Change
];
UndoProc:
TYPE ~
PROC [world: World, undoRef:
REF Change];
procedure supplied by client to undo the effects of a particular subevent
CreateEvent:
PROC
RETURNS [Event];
NoteEvent:
PROC [world: World, undoProc: UndoProc, undoRef:
REF Change];
adds <undoProc, undoRef> to list of subevents
UndoEvent:
PROC [world: World, undoEvent: Event];
calls undoProc[world, undoRef] for each subevent
in reverse order that subevents originally happened
world arg is to record the effects of Undo so it too will be undoable
ResetEvent:
PROC [event: Event];
resets the list of subevents to NIL
Undo automatically does a Reset when it is finished
EmptyEvent:
PROC [event: Event]
RETURNS [
BOOL];
returns true if subevents list is empty
EditSpanSupport
Slice: TYPE = REF SliceArray;
SliceArray:
TYPE =
RECORD [
next: Slice, -- for free list
length: NAT ← 0,
nodes: SEQUENCE maxLength: NAT OF Node
];
SliceKind:
TYPE = { before, after };
GetSlice:
PROC [len:
NAT]
RETURNS [slice: Slice];
FreeSlice:
PROC [slice: Slice];
SliceLength:
PROC [slice: Slice]
RETURNS [
NAT]
= INLINE { RETURN [slice.length] };
SliceNode:
PROC [slice: Slice, index:
NAT]
RETURNS [Node]
= INLINE { RETURN [slice[index]] };
LastOfSlice:
PROC [slice: Slice]
RETURNS [Node]
= INLINE { RETURN [slice[slice.length-1]] };
KindOfSlice:
PROC [slice: Slice]
RETURNS [SliceKind]
= INLINE { RETURN [IF slice[0]#NIL THEN before ELSE after] };
Splice:
PROC [before, after: Slice, beforeStart, afterStart:
NAT ← 0];
ReplaceBand:
PROC [before, after, top, bottom: Slice, nesting:
INTEGER];
DescribeBand:
PROC [first, last: Node]
RETURNS [before, after, top, bottom: Slice, nesting:
INTEGER, depth:
NAT];
DeletePrefix:
PROC [slice: Slice, depth:
NAT];
DestSlices:
PROC [dest: Node, where: Place]
RETURNS [before, after: Slice, nesting:
INTEGER];
CreateDest:
PROC [depth:
NAT]
RETURNS [dest: Location];
CopySpan:
PROC [span: Span]
RETURNS [result: Span];
NeededNestingChange:
TYPE = { needNest, needUnNest, ok };
NeedNestingChange:
PROC [before, after, top, bottom: Slice,
nesting:
INTEGER, depth:
NAT]
RETURNS [NeededNestingChange];
CompareSliceOrder:
PROC [s1, s2: Slice]
RETURNS [order: Order];
DoSplits:
PROC [world: World, alpha, beta: Span]
RETURNS [Span, Span];
DoSplits2:
PROC [world: World, dest: Location, source: Span, where: Place, nesting:
INTEGER]
RETURNS [Location, Span, Place,
INTEGER];
UndoSplits:
PROC [world: World, alpha, beta: Span]
RETURNS [Span, Span];
UndoSplits2:
PROC [world: World, dest: Location, source: Span]
RETURNS [Location, Span];
ReMerge:
PROC [world: World, alpha, beta: Span, merge: Node, tail:
BOOL ←
FALSE]
RETURNS [Span, Span];
SliceOrder:
PROC [alpha, beta: Span, aBefore, aBottom, bBefore, bBottom: Slice]
RETURNS [overlap:
BOOL, head, tail: Span, startOrder, endOrder: Order];
ApplyToSpanProc:
TYPE =
PROC [node: Node, start, len:
INT]
RETURNS [stop:
BOOL];
ApplyToSpan:
PROC [span: Span, proc: ApplyToSpanProc];
ForwardLoc:
PROC [loc: Location]
RETURNS [new: Location];
BackLoc:
PROC [loc: Location]
RETURNS [new: Location];
World info
EditNotifyData: TYPE ~ REF EditNotifyDataRep;
EditNotifyDataRep: TYPE; -- see EditNotifyImpl
World: TYPE ~ REF WorldRep;
WorldRep:
TYPE ~
RECORD [
editNotify: EditNotifyData,
currentEvent: Event,
paste: REF Change.ChangingSpanForPaste,
afterMoved1, afterMoved2: Location
];