-- NodeAddrs.Mesa -- written by Paxton. March 1981 -- last written by Paxton. March 20, 1981 2:42 PM -- **** Persistent addressing for nodes **** DIRECTORY CardAddrs, NodeProps, TextNode; NodeAddrs: DEFINITIONS IMPORTS NodeProps, CardAddrs = BEGIN OPEN nodeI: TextNode, addrsI: CardAddrs, propsI: NodeProps; Card: TYPE = LONG CARDINAL; Ref: TYPE = nodeI.Ref; RefTextNode: TYPE = nodeI.RefTextNode; -- **** Text Addr operations PutTextAddr: PROC [n: RefTextNode, addr: REF, location: Card] = INLINE { -- assigns addr to location in node -- ok if addr was previously assigned elsewhere in the node addrs: addrsI.Ref; IF (addrs _ propsI.GetTextAddrs[n]) = NIL THEN propsI.PutTextAddrs[n, addrs _ addrsI.Create[]]; addrsI.PutAddr[addrs, addr, location] }; RemTextAddr: PROC [n: RefTextNode, addr: REF] = INLINE -- removes the given addr { addrsI.RemAddr[propsI.GetTextAddrs[n], addr] }; GetTextAddr: PROC [n: RefTextNode, addr: REF] RETURNS [location: Card] = -- generates ERROR addrsI.AddrNotFound if the addr is not in the mapping INLINE { RETURN [addrsI.GetAddr[propsI.GetTextAddrs[n], addr]] }; TryGetTextAddr: PROC [n: RefTextNode, addr: REF] RETURNS [found: BOOLEAN, location: Card] = INLINE { [found, location] _ addrsI.TryGetAddr[propsI.GetTextAddrs[n], addr] }; MapTextAddrs: PROC [n: RefTextNode, action: TextAddrsAction] RETURNS [BOOLEAN] = INLINE -- apply the action to each addr&location pair for the node -- returns true if&when an action returns true { RETURN [addrsI.MapAddrs[propsI.GetTextAddrs[n], action]] }; TextAddrsAction: TYPE = addrsI.MapAddrsAction; -- = PROC [addr: REF, location: Card] RETURNS [BOOLEAN]; -- **** Editing Operations for text addrs **** Replace: PROC [n: RefTextNode, start, len, newlen: Card] = INLINE -- 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 { addrsI.Replace[propsI.GetTextAddrs[n], start, len, newlen] }; Insert: PROC [n: RefTextNode, start, length: Card] = INLINE { -- adds len to addrs at or beyond start Replace[n, start, 0, length] }; Delete: PROC [n: RefTextNode, start, length: Card] = INLINE { Replace[n, start, length, 0] }; Move: PROC [n: RefTextNode, dest, start, len: Card] = INLINE -- dest must not be in [start..start+len) -- or get ERROR BadMove { addrsI.Move[propsI.GetTextAddrs[n], dest, start, len] }; Transpose: PROC [n: RefTextNode, astart, alen, bstart, blen: Card] = INLINE -- [astart..astart+alen) must not intersect [bstart..bstart+blen) -- or get ERROR BadTranspose { addrsI.Transpose[propsI.GetTextAddrs[n], astart, alen, bstart, blen] }; -- **** Child Addr operations PutChildAddr: PROC [n: Ref, addr: REF, location: Card] = INLINE { -- assigns addr to location in node -- ok if addr was previously assigned elsewhere in the node addrs: addrsI.Ref; IF (addrs _ propsI.GetChildAddrs[n]) = NIL THEN propsI.PutChildAddrs[n, addrs _ addrsI.Create[]]; addrsI.PutAddr[addrs, addr, location] }; RemChildAddr: PROC [n: Ref, addr: REF] = INLINE -- removes the given addr { addrsI.RemAddr[propsI.GetChildAddrs[n], addr] }; GetChildAddr: PROC [n: Ref, addr: REF] RETURNS [location: Card] = -- generates ERROR addrsI.AddrNotFound if the addr is not in the mapping INLINE { RETURN [addrsI.GetAddr[propsI.GetChildAddrs[n], addr]] }; TryGetChildAddr: PROC [n: Ref, addr: REF] RETURNS [found: BOOLEAN, location: Card] = INLINE { [found, location] _ addrsI.TryGetAddr[propsI.GetChildAddrs[n], addr] }; FollowChildAddrs: PROC [node: Ref, addr: REF] RETURNS [Ref]; MapChildAddrs: PROC [n: Ref, action: ChildAddrsAction] RETURNS [BOOLEAN] = INLINE -- apply the action to each addr&location pair for the node -- returns true if&when an action returns true { RETURN [addrsI.MapAddrs[propsI.GetChildAddrs[n], action]] }; ChildAddrsAction: TYPE = addrsI.MapAddrsAction; -- = PROC [addr: REF, location: Card] RETURNS [BOOLEAN]; -- **** Editing Operations for child addrs **** ReplaceNodes: PROC [n: Ref, start, len, newlen: Card] = INLINE -- 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 { addrsI.Replace[propsI.GetChildAddrs[n], start, len, newlen] }; MoveNodes: PROC [n: Ref, dest, start, len: Card] = INLINE -- dest must not be in [start..start+len) -- or get ERROR BadMove { addrsI.Move[propsI.GetChildAddrs[n], dest, start, len] }; InsertNode: PROC [n: Ref, start, length: Card] = INLINE { -- adds len to addrs at or beyond start ReplaceNodes[n, start, 0, length] }; TransposeNodes: PROC [n: Ref, astart, alen, bstart, blen: Card] = INLINE -- [astart..astart+alen) must not intersect [bstart..bstart+blen) -- or get ERROR BadTranspose { addrsI.Transpose[propsI.GetChildAddrs[n], astart, alen, bstart, blen] }; END.