EditSpan.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
written by Bill Paxton, June 1981
last edit by Bill Paxton, October 13, 1982 2:22 pm
last edit by Russ Atkinson, July 22, 1983 9:50 am
Doug Wyatt, March 3, 1985 5:04:12 pm PST
Michael Plass, March 18, 1985 5:23:07 pm PST
DIRECTORY
TextEdit USING [CapChange],
TextLooks USING [allLooks, Looks, noLooks],
TextNode USING [Location, nullLocation, nullSpan, Ref, RefTextNode, Span],
UndoEvent USING [Ref];
EditSpan: CEDAR DEFINITIONS
= BEGIN
Ref: TYPE = TextNode.Ref;
RefTextNode: TYPE = TextNode.RefTextNode;
Location: TYPE = TextNode.Location;
nullLocation: Location = TextNode.nullLocation;
Span: TYPE = TextNode.Span;
nullSpan: Span = TextNode.nullSpan;
Event: TYPE = UndoEvent.Ref;
Operations to add or delete looks
Looks: TYPE = TextLooks.Looks;
noLooks: Looks = TextLooks.noLooks;
allLooks: Looks = TextLooks.allLooks;
ChangeLooks: PROC [root: Ref, span: Span, remove, add: Looks, event: Event ← NIL];
first remove then add in the given span
AddLooks: PROC [root: Ref, span: Span, add: Looks, event: Event ← NIL]
= INLINE { ChangeLooks[root, span, noLooks, add, event] };
RemoveLooks: PROC [root: Ref, span: Span, remove: Looks, event: Event ← NIL]
= INLINE { ChangeLooks[root, span, remove, noLooks, event] };
SetLooks: PROC [root: Ref, span: Span, new: Looks, event: Event ← NIL]
= INLINE { ChangeLooks[root, span, allLooks, new, event] };
ClearLooks: PROC [root: Ref, span: Span, event: Event ← NIL]
= INLINE { ChangeLooks[root, span, allLooks, noLooks, event] };
Editing operations on spans
Replace: PROC [destRoot, sourceRoot: Ref, dest, source: Span,
saveForPaste: BOOLTRUE,
event: Event ← NIL] RETURNS [result: Span];
replace dest span by copy of source span
result is the new copy of source
Delete: PROC [root: Ref, del: Span, event: Event ← NIL, saveForPaste: BOOLTRUE];
SaveForPaste: PROC [span: Span, event: Event ← NIL];
SavedForPaste: PROC RETURNS [span: Span];
result is last thing deleted or explicitly saved for Paste
Place: TYPE = { before, after, sibling, child };
these are modifiers for the destination of a Move or Copy or Insert
only apply when destination is an entire node (i.e., dest.where = NodeItself)
place = before means insert as sibling before dest
place = after means insert as sibling after dest; inherit children of dest
place = sibling means insert as sibling after dest; don't inherit children of dest
place = child means insert as first child of dest
Copy: PROC [destRoot, sourceRoot: Ref, dest: Location, source: Span,
where: Place ← after, nesting: INTEGER ← 0,
event: Event ← NIL] RETURNS [result: Span];
result is the new copy of source
Move: PROC [destRoot, sourceRoot: Ref, dest: Location, source: Span,
where: Place ← after, nesting: INTEGER ← 0,
event: Event ← NIL] RETURNS [result: Span];
dest cannot be within source or get error BadMove
result is moved span
nesting is relative to dest
e.g., where=after and nesting=1 makes source be child of dest
MoveOnto: PROC [destRoot, sourceRoot: Ref, dest, source: Span,
saveForPaste: BOOLTRUE,
event: Event ← NIL] RETURNS [result: Span];
like Replace, but moves source instead of copying it
result is moved span
Transpose: PROC [alphaRoot, betaRoot: Ref, alpha, beta: Span,
event: Event ← NIL] RETURNS [newAlpha, newBeta: Span];
alpha and beta must not overlap or get error BadTranspose
newAlpha is new location of alpha span; ditto for newBeta
New nodes; split & merge
Insert: PROC [root, old: Ref, where: Place ← after, event: Event ← NIL] RETURNS [new: Ref];
empty copy of old node is inserted in tree in position determined by "where"
Inherit: PROC [old, new: Ref, allprops: BOOLFALSE];
InsertTextNode: PROC [root, old: Ref, where: Place ← after,
inherit: BOOLFALSE, event: Event ← NIL] RETURNS [new: RefTextNode];
empty text node is inserted in tree
Split: PROC [root: Ref, loc: Location, event: Event ← NIL] RETURNS [new: Ref];
inserts copy of loc.node is inserted directly before loc.node (as sibling)
new adopts children of old (if any)
if loc.where # NodeItself and loc.node is a text node, then
text after loc.where moves to new node
text before loc.where stays in old node
returns the new node
Merge: PROC [root, node: Ref, event: Event ← NIL] RETURNS [loc: Location];
copies text of node to end of previous node
then deletes node
Nesting
ChangeNesting: PROC [root: Ref, span: Span, change: INTEGER,
event: Event ← NIL] RETURNS [new: Span];
moves all nodes of span, even if don't have entire node selected
Nest: PROC [root: Ref, span: Span, event: Event ← NIL] RETURNS [new: Span]
= INLINE { new ← ChangeNesting[root, span, +1, event] };
moves span to a deeper nesting level in tree
UnNest: PROC [root: Ref, span: Span, event: Event ← NIL] RETURNS [new: Span]
= INLINE { new ← ChangeNesting[root, span, -1, event] };
moves span to a shallower nesting level in tree
Caps and Lowercase
CapChange: TYPE = TextEdit.CapChange;
ChangeCaps: PROC [root: Ref, span: Span, how: CapChange ← allCaps, event: Event ← NIL];
AllCaps: PROC [root: Ref, span: Span, event: Event ← NIL]
= INLINE { ChangeCaps[root, span, allCaps, event] };
force specified span to all uppercase
AllLower: PROC [root: Ref, span: Span, event: Event ← NIL]
= INLINE { ChangeCaps[root, span, allLower, event] };
force specified span to all lowercase
InitialCaps: PROC [root: Ref, span: Span, event: Event ← NIL]
= INLINE { ChangeCaps[root, span, initCaps, event] };
force first letter of words uppercase
Miscellaneous
NodeOrder: TYPE = { before, same, after, disjoint };
CompareNodeOrder: PROC [node1, node2: Ref] RETURNS [order: NodeOrder];
determines relative order in tree of the nodes
returns "same" if node1 = node2
returns "before" if node1 comes before node2
returns "after" if node1 comes after node2
returns "disjoint" if nodes are not from the same tree
CannotDoEdit: ERROR;
afterMoved1, afterMoved2: Location;
hints for repaint set by Move, MoveOnto, and Transpose
gives pointers to locs after the moved spans
END.