DIRECTORY EditSpan, EditSpanSupport, EditGroup, EditNotify, NodeProps, Rope, UndoEvent, TextEdit, TreeSlice, TiogaLooks, TiogaNode, TiogaNodeOps, TiogaTreeOps; EditNodeImpl: CEDAR PROGRAM IMPORTS NodeProps, TextEdit, EditGroup, TiogaNodeOps, TiogaTreeOps, UndoEvent, EditSpan, EditNotify EXPORTS EditSpan SHARES TiogaNode = BEGIN OPEN EditSpan, EditSpanSupport, TreeSlice, EditNotify; Slice: TYPE = TreeSlice.Slice; nullSpan: TreeSpan = TiogaTreeOps.nullSpan; nullBranchSpan: BranchSpan = TiogaTreeOps.nullBranchSpan; Insert: PUBLIC PROC [root: RefBranchNode, old: Ref, where: Place _ after, event: Event _ NIL] RETURNS [new: Ref] = TRUSTED { IF old=NIL THEN RETURN [NIL]; new _ WITH old SELECT FROM br: RefBranchNode => TiogaNodeOps.NewBranchNode[], tx: RefTextNode => TiogaNodeOps.NewTextNode[tx.class], bx: TiogaNode.RefBoxNode => TiogaNodeOps.NewBoxNode[bx.class], ls: TiogaNode.RefListNode => TiogaNodeOps.NewListNode[ls.class], bs: TiogaNode.RefBasicNode => TiogaNodeOps.NewBasicNode[bs.class], ENDCASE => ERROR; Inherit[old, new]; DoInsertNode[root, old, new, where, event] }; InsertTextNode: PUBLIC PROC [root: RefBranchNode, old: Ref, class: TiogaNode.ItemClassID _ TiogaNode.defaultTextClassID, where: Place _ after, inherit: BOOL _ FALSE, event: Event _ NIL] RETURNS [new: RefTextNode] = BEGIN IF old=NIL THEN RETURN [NIL]; new _ TiogaNodeOps.NewTextNode[class]; IF inherit THEN Inherit[old, new]; DoInsertNode[root, old, new, where, event]; END; InsertBranchNode: PUBLIC PROC [ root: RefBranchNode, old: Ref, where: Place _ after, inherit: BOOL _ FALSE, event: Event _ NIL] RETURNS [new: TiogaNode.RefBranchNode] = BEGIN IF old=NIL THEN RETURN [NIL]; new _ TiogaNodeOps.NewBranchNode[]; IF inherit THEN Inherit[old, new]; DoInsertNode[root, old, new, where, event]; END; InsertBoxNode: PUBLIC PROC [ root: RefBranchNode, old: Ref, class: TiogaNode.ItemClassID, where: Place _ after, inherit: BOOL _ FALSE, event: Event _ NIL] RETURNS [new: TiogaNode.RefBoxNode] = BEGIN IF old=NIL THEN RETURN [NIL]; new _ TiogaNodeOps.NewBoxNode[class]; IF inherit THEN Inherit[old, new]; DoInsertNode[root, old, new, where, event]; END; InsertListNode: PUBLIC PROC [ root: RefBranchNode, old: Ref, class: TiogaNode.ItemClassID, where: Place _ after, inherit: BOOL _ FALSE, event: Event _ NIL] RETURNS [new: TiogaNode.RefListNode] = BEGIN IF old=NIL THEN RETURN [NIL]; new _ TiogaNodeOps.NewListNode[class]; IF inherit THEN Inherit[old, new]; DoInsertNode[root, old, new, where, event]; END; InsertBasicNode: PUBLIC PROC [ root: RefBranchNode, old: Ref, class: TiogaNode.BasicClassID, where: Place _ after, inherit: BOOL _ FALSE, event: Event _ NIL] RETURNS [new: TiogaNode.RefBasicNode] = BEGIN IF old=NIL THEN RETURN [NIL]; new _ TiogaNodeOps.NewBasicNode[class]; IF inherit THEN Inherit[old, new]; DoInsertNode[root, old, new, where, event]; END; Inherit: PUBLIC PROC [old, new: Ref, allprops: BOOL _ FALSE] = { CopyProp: PROC [name: ATOM, value: REF] RETURNS [BOOL] = { newvalue: REF; IF ~allprops THEN SELECT name FROM $Prefix, $Postfix, $StyleDef => NULL; -- these control formatting ENDCASE => RETURN [FALSE]; -- don't copy anything else IF (newvalue _ NodeProps.CopyInfo[name: name, value: value, from: old, to: new]) # NIL THEN NodeProps.PutProp[new, name, newvalue]; RETURN [FALSE] }; new.format _ old.format; new.comment _ old.comment; IF old.hasPropList AND (allprops OR old.hasprefix OR old.haspostfix OR old.hasstyledef) THEN [] _ NodeProps.MapProps[old, CopyProp, FALSE, FALSE] }; DoInsertNode: PROC [root: RefBranchNode, old, new: Ref, where: Place, event: Event] = { notify: REF InsertingNode Change; oldBr, newBr: RefBranchNode; Link: PROC [node, sib: Ref] = INLINE { sib.next _ node.next; sib.last _ node.last; node.last _ FALSE; node.next _ sib }; NotifyBefore: PROC = INLINE { new.new _ TRUE; notify _ NEW[InsertingNode Change _ [InsertingNode[root, new, old, where]]]; Notify[notify, before] }; IF new = NIL OR old = NIL THEN RETURN; IF where = before THEN { -- convert to other kind of insert prev: Ref; IF TiogaNodeOps.IsBranch[old] # TiogaNodeOps.IsBranch[new] THEN ERROR CannotDoEdit; IF (prev _ TiogaTreeOps.Previous[old]) # NIL THEN { where _ sibling; old _ prev } ELSE { where _ child; old _ TiogaTreeOps.Parent[old] }}; SELECT where FROM sibling => { IF TiogaNodeOps.IsBranch[old] # TiogaNodeOps.IsBranch[new] THEN ERROR CannotDoEdit; NotifyBefore[]; Link[old, new] }; after => { oldBr _ TiogaNodeOps.NarrowToBranchNode[old]; newBr _ TiogaNodeOps.NarrowToBranchNode[new]; IF (oldBr=NIL) # (newBr=NIL) THEN ERROR CannotDoEdit; NotifyBefore[]; Link[old, new]; IF oldBr # NIL AND oldBr.child # NIL THEN {-- adopt oldBr's children newBr.child _ oldBr.child; TiogaTreeOps.LastSibling[newBr.child].next _ newBr; oldBr.child _ NIL }}; child => WITH old SELECT FROM br: RefBranchNode => { NotifyBefore[]; newBr _ TiogaNodeOps.NarrowToBranchNode[new]; IF newBr # NIL THEN { -- insert new branch as child of old branch IF br.child # NIL THEN { new.next _ br.child; new.last _ FALSE } ELSE { new.next _ br; new.last _ TRUE }; br.child _ newBr } ELSE { -- insert new as contents of old IF br.contents # NIL THEN { new.next _ br.contents; new.last _ FALSE } ELSE { new.next _ br; new.last _ TRUE }; br.contents _ TiogaNodeOps.NarrowToItemNode[new] }}; bx: TiogaNode.RefBoxNode => { NotifyBefore[]; IF bx.contents # NIL THEN { new.next _ bx.contents; new.last _ FALSE } ELSE { new.next _ bx; new.last _ TRUE }; bx.contents _ new }; ls: TiogaNode.RefListNode => { NotifyBefore[]; IF ls.contents # NIL THEN { new.next _ ls.contents; new.last _ FALSE } ELSE { new.next _ ls; new.last _ TRUE }}; ENDCASE => ERROR CannotDoEdit; ENDCASE => ERROR; Notify[notify, after]; UndoEvent.Note[event, UndoInsertNode, notify] }; UndoInsertNode: PROC [undoRef: REF, currentEvent: Event] = TRUSTED { saved: REF Change _ NARROW[undoRef]; WITH x:saved SELECT FROM InsertingNode => { [] _ EditGroup.DeleteGroup[x.root, x.new, x.new, FALSE, currentEvent] }; ENDCASE => ERROR }; JoinStatements: PUBLIC PROC [root, statement: RefBranchNode, event: Event _ NIL] RETURNS [loc: TreeLoc] = { pred: RefBranchNode _ TiogaTreeOps.Backward[statement].back; dest, source: Ref; IF pred = NIL OR TiogaTreeOps.Parent[pred] = NIL THEN ERROR CannotDoEdit; dest _ TiogaTreeOps.Contents[pred]; IF (source _ TiogaTreeOps.Contents[statement])=NIL THEN IF dest=NIL THEN loc _ [pred, NodeItself] ELSE { dest _ TiogaTreeOps.LastSibling[dest]; loc _ [dest, IF ~TiogaNodeOps.IsText[dest] THEN NodeItself ELSE TiogaNodeOps.Size[TiogaNodeOps.NarrowToTextNode[dest]]] } ELSE -- move source contents to end of pred contents IF dest=NIL THEN { -- pred doesn't have contents yet loc _ [source, IF TiogaNodeOps.IsText[source] THEN 0 ELSE NodeItself]; EditGroup.MoveGroup[ destRoot: root, sourceRoot: root, dest: pred, contents: TRUE, sourceStart: source, sourceEnd: TiogaTreeOps.LastSibling[source], event: event] } ELSE { -- move to end of contents of pred destText, sourceText: RefTextNode; dest _ TiogaTreeOps.LastSibling[dest]; EditGroup.MoveGroup[ destRoot: root, sourceRoot: root, dest: dest, contents: FALSE, sourceStart: source, sourceEnd: TiogaTreeOps.LastSibling[source], event: event]; IF (destText _ TiogaNodeOps.NarrowToTextNode[dest]) # NIL AND (sourceText _ TiogaNodeOps.NarrowToTextNode[source]) # NIL THEN { loc.node _ dest; loc.where _ TextEdit.CopyText[root, root, destText, MaxLen, sourceText, 0, MaxLen, event].resultStart; [] _ EditGroup.DeleteGroup[root, sourceText, sourceText, FALSE, event] } ELSE loc _ [source, NodeItself] }; [] _ EditGroup.DeleteGroup[root, statement, statement, FALSE, event] }; BreakTextNode: PUBLIC PROC [root: RefBranchNode, loc: TreeLoc, event: Event _ NIL] RETURNS [new: Ref] = { old: Ref _ loc.node; oldTxt, newTxt: RefTextNode; IF (oldTxt _ TiogaNodeOps.NarrowToTextNode[old]) = NIL THEN RETURN [NIL]; new _ Insert[root, old, after, event]; IF loc.where = NodeItself THEN RETURN; newTxt _ TiogaNodeOps.NarrowToTextNode[new]; [] _ TextEdit.MoveText[destRoot: root, sourceRoot: root, dest: newTxt, destLoc: 0, source: oldTxt, start: loc.where, event: event] }; BreakParent: PUBLIC PROC [root: RefBranchNode, node: Ref, before: BOOL _ TRUE, event: Event _ NIL] RETURNS [parent: Ref] = { move, new: Ref; IF node=NIL THEN RETURN [NIL]; IF (parent _ TiogaTreeOps.Parent[node])=NIL THEN ERROR CannotDoEdit; IF TiogaNodeOps.IsBranch[node] AND TiogaNodeOps.IsBranch[parent] THEN ERROR CannotDoEdit; new _ Insert[root, parent, after, event]; IF before THEN { move _ node; parent _ new } ELSE move _ TiogaTreeOps.Next[node]; IF move#NIL THEN EditGroup.MoveGroup[ destRoot: root, sourceRoot: root, dest: new, contents: TRUE, sourceStart: move, sourceEnd: TiogaTreeOps.LastSibling[move], event: event] }; BreakStatement: PUBLIC PROC [root: RefBranchNode, node: Ref, before: BOOL _ TRUE, event: Event _ NIL] RETURNS [RefBranchNode] = { IF node=NIL THEN RETURN [NIL]; UNTIL TiogaNodeOps.IsBranch[node] DO node _ BreakParent[root, node, before, event]; ENDLOOP; RETURN [TiogaNodeOps.NarrowToBranchNode[node]] }; END.... tEditNodeImpl.mesa; written by Bill Paxton, June 1981 edited by Bill Paxton, August 30, 1983 10:03 am edited by McGregor, August 12, 1983 10:06 am ***** New nodes empty copy of old node is inserted in tree in position determined by "where" ***** split & merge moves contents of statement to end of previous one and then deletes statement Inserts copy of parent as next sibling of parent. If before is true, moves children starting with node to be contents of new. Otherwise, moves children starting with next sibling of node. Returns the parent of node after the break. loc points somewhere in the contents of a statement. This works its way up breaking nodes until contents from node on have been moved to a new statement. If before is true, node moves to the new statement; otherwise, it stays in the old one. Returns the statement which contains node after doing the break. Ê ˜Jšœ Ïc(™4Jš/™/Jš,™,J˜JšÏk ˜ J˜ J˜J˜ J˜ J˜ J˜J˜ J˜ J˜ J˜ J˜ J˜ J˜ J˜šœž œ˜Jšžœ\˜cJšžœ ˜Jšžœ ˜—Jšž˜Jšžœ2˜6J˜Jšœžœ˜J˜+J˜9J˜Jšœ™˜šÏnœžœžœFžœ˜]Jšžœžœ˜JšœL™LJš žœžœžœžœžœ˜šœžœžœž˜Jšœ2˜2Jšœ6˜6Jšœ>˜>Jšœ@˜@JšœB˜BJšžœžœ˜—J˜J˜-J˜—šŸœžœž˜Jšœ\˜\Jšœžœžœžœ˜@Jšžœž˜"Jš žœžœžœžœžœ˜Jšœ&˜&Jšžœ žœ˜"J˜+Jšžœ˜J˜—šŸœžœžœ˜Jšœ>žœžœžœ˜_Jšžœ"ž˜.Jš žœžœžœžœžœ˜Jšœ#˜#Jšžœ žœ˜"J˜+Jšžœ˜J˜—šŸ œžœžœ˜Jšœ<˜———šžœ/˜4šžœžœžœ!˜4Jšœžœžœžœ ˜Fšœ˜Jšœ8žœ˜=JšœQ˜Q——šžœ"˜)J˜"Jšœ&˜&šœ˜Jšœ8žœ˜>JšœP˜P—šžœ4žœž˜=Jšœ7žœžœ˜AJšœ˜Jšœf˜fJšœ:žœ ˜H—Jšžœ˜"——Jšœ7žœ ˜GJ˜—š Ÿ œžœžœ4žœžœ˜iJ˜J˜Jš žœ1žœžœžœžœ˜IJ˜&Jšžœžœžœ˜&J˜,˜R˜2J˜———š Ÿ œžœžœ*žœžœžœ˜bJšžœ˜J™1J™KJ™=J™+J˜Jš žœžœžœžœžœ˜Jšžœ&žœžœžœ˜DJšžœžœžœžœ˜YJ˜)Jšžœžœ˜,Jšžœ ˜$šžœžœžœ˜%Jšœ7žœ˜