<> <> <> <> <<-- This package provides editing, filing, and various other operations for text nodes>> <<-- a text node contains a rope and runs of looks>> <<-- looks are represented by a vector of 32 bits>> <<-- each character in a text node has looks vector associated with it>> <<-- run encoding is used to reduce the storage needed to represent the looks>> <<-- see TextLooks.Mesa for more information about looks>> <<-- see TextNode.Mesa for the details of text node structure>> <<-- Text editing>> <<-- operations are provided to edit the contents of text nodes>> <<-- unlike ropes or runs of looks, text nodes are mutable>> <<-- i.e., the edit changes the node rather than returning a new node>> <<-- the looks related commands are>> <<-- AddLooks, RemoveLooks, SetLooks, ClearLooks, and ChangeLooks>> <<-- the text related commands are>> <<-- ReplaceText, DeleteText, CopyText, MoveText, MoveTextOnto, TransposeText>> <<-- the word commands are>> <<-- ReplaceWords, DeleteWords, CopyWords, MoveWords, MoveWordsOnto, TransposeWords>> <<-- in addition there are commands taking a character/string/rope as source>> <<-- ReplaceByChar, InsertChar, AppendChar>> <<-- ReplaceByString, InsertString, AppendString>> <<-- ReplaceByRope, InsertRope, AppendRope>> <<-- several commands are available for changing capitalization>> <<-- AllCaps, AllLower, InitialCaps>> <<-- Persistent addresses in text of a node>> <<-- You can associate an address with a character location in a text node>> <<-- the address persists with the same character even if the text is edited>> <<-- the address is an arbitrary REF ANY supplied by the client program >> <<-- see NodeAddrs.Mesa for the persistent addressing operations>> <<-- Property lists>> <<-- Each node includes a property list of key-value pairs>> <<-- The keys are ATOMs and the values are arbitrary REF ANY's>> <<-- Clients can register routines to read/write properties to files>> <<-- and to copy property values when nodes are copied>> <<-- see NodeProps.Mesa for the property list operations>> <<-- Filing>> <<-- There are operations to read and write files containing text nodes>> <<-- The characters go at the front of the file, followed by 0's>> <<-- then the information about looks, etc.>> <<-- and finally a password and a pointer to the end of the text.>> <<-- Thus programs that simply want to look at the characters can read up to 0's>> <<-- operations to read/write nodes to files are found in PutGet.Mesa>> <<-- Edit notification procedures>> <<-- Client's can register procedures to be called before/after edits>> <<-- the client procedure is called with the node(s) changed by the edit>> <<-- and a record describing the details of the edit>> <<-- see EditNotify.Mesa for more information>> <<-- Other kinds of nodes>> <<-- clients can create their own varieties in addition to the basic text nodes>> <<-- simply need to provide routines to write specs to files,>> <<-- take specs read from file and create a corresponding node,>> <<-- and to copy when nodes are copied>> <<-- see OtherNode.Mesa for details>> <<-- Tree editing>> <<-- nodes can have children>> <<-- there is a set of tree editing operations available>> <<-- see EditSpan.Mesa for details>> DIRECTORY RopeEdit, TextLooks, TextNode, UndoEvent; TextEdit: CEDAR DEFINITIONS = BEGIN Ref: TYPE = TextNode.Ref; RefTextNode: TYPE = TextNode.RefTextNode; ROPE: TYPE = RopeEdit.ROPE; Looks: TYPE = TextLooks.Looks; noLooks: Looks = TextLooks.noLooks; allLooks: Looks = TextLooks.allLooks; Offset: TYPE = TextLooks.Offset; MaxLen, MaxOffset: Offset = LAST[Offset]; MaxNat: NAT = LAST[NAT]; Event: TYPE = UndoEvent.Ref; <<-- **** General operations ****>> FetchChar: PROC [text: RefTextNode, index: Offset] RETURNS [CHAR]; <<-- fetches the indexed information>> <<-- use rope readers if want characters from contiquous locations>> FetchLooks: PROC [text: RefTextNode, index: Offset] RETURNS [Looks]; <<-- returns the looks for the character at the given location>> <<-- use reader's if getting looks for sequence of locations>> Fetch: PROC [text: RefTextNode, index: Offset] RETURNS [CHAR, Looks]; <<-- fetches the indexed information>> <<-- use rope & looks readers if want info from contiquous locations>> GetRope: PROC [text: RefTextNode] RETURNS [ROPE]; GetRuns: PROC [text: RefTextNode] RETURNS [TextLooks.Runs]; Size: PROC [text: RefTextNode] RETURNS [Offset]; Flatten: PROC [text: RefTextNode] RETURNS [BOOLEAN]; <<-- returns true if it decides to flatten rope & runs>> <<-- this is done automatically after a certain number of edits to the node>> AlreadySaved: PROC [text: RefTextNode, event: Event] RETURNS [BOOLEAN]; <<-- returns TRUE if there is already a ChangingText record for given node in the event >> <<-- **** Operations to create a text node ****>> FromRope: PROC [rope: ROPE] RETURNS [RefTextNode]; <<-- create a text node with looks from a normal rope>> FromString: PROC [string: REF READONLY TEXT] RETURNS [RefTextNode]; <<-- copies the contents of the string>> DocFromNode: PROC [child: Ref] RETURNS [root: Ref]; <<-- returns root node which has one child>> <<-- child typically created by FromRope or FromString>> <<-- **** Operations to add or delete looks ****>> ChangeLooks: PROC [ root: Ref, text: RefTextNode, remove, add: Looks, start: Offset _ 0, len: Offset _ MaxOffset, event: Event _ NIL]; <<-- first remove then add in the given range>> AddLooks: PROC [ root: Ref, text: RefTextNode, add: Looks, start: Offset _ 0, len: Offset _ MaxOffset, event: Event _ NIL] = INLINE { ChangeLooks[root, text, noLooks, add, start, len, event] }; RemoveLooks: PROC [ root: Ref, text: RefTextNode, remove: Looks _ allLooks, start: Offset _ 0, len: Offset _ MaxOffset, event: Event _ NIL] = INLINE { ChangeLooks[root, text, remove, noLooks, start, len, event] }; SetLooks: PROC [ root: Ref, text: RefTextNode, new: Looks, start: Offset _ 0, len: Offset _ MaxOffset, event: Event _ NIL] = INLINE { ChangeLooks[root, text, allLooks, new, start, len, event] }; ClearLooks: PROC [ root: Ref, text: RefTextNode, start: Offset _ 0, len: Offset _ MaxOffset, event: Event _ NIL] = INLINE { ChangeLooks[root, text, allLooks, noLooks, start, len, event] }; <<-- **** Changing Style / Type / Property of node ****>> ChangeType: PROC [node: Ref, typeName: TextNode.TypeName, event: Event _ NIL, root: Ref _ NIL]; ChangeStyle: PROC [ node: Ref, name: ROPE, event: Event _ NIL, root: Ref _ NIL]; <<-- appends style to end of node prefix>> PutProp: PROC [ node: Ref, name: ROPE, value: REF, event: Event _ NIL, root: Ref _ NIL]; GetProp: PROC [node: Ref, name: ROPE] RETURNS [value: REF]; <<-- **** 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: Ref, dest: RefTextNode, destStart: Offset _ 0, destLen: Offset _ MaxLen, source: RefTextNode, sourceStart: Offset _ 0, sourceLen: Offset _ MaxLen, event: Event _ NIL] RETURNS [resultStart, resultLen: Offset]; DestSpanProc: TYPE = PROC [ destRoot, sourceRoot: Ref, dest: RefTextNode, destLoc: Offset _ 0, source: RefTextNode, start: Offset _ 0, len: Offset _ MaxLen, event: Event _ NIL] RETURNS [resultStart, resultLen: Offset]; 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>> OneSpanProc: TYPE = PROC [ root: Ref, text: RefTextNode, start: Offset _ 0, len: Offset _ MaxLen, event: Event _ NIL]; 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>> TransposeProc: TYPE = PROC [ alphaRoot, betaRoot: Ref, alpha: RefTextNode, alphaStart: Offset _ 0, alphaLen: Offset _ MaxLen, beta: RefTextNode, betaStart: Offset _ 0, betaLen: Offset _ MaxLen, event: Event _ NIL] RETURNS [alphaResultStart, alphaResultLen, betaResultStart, betaResultLen: Offset]; 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>> ReplaceByText: PROC [ root: Ref, dest: RefTextNode, destStart: Offset _ 0, destLen: Offset _ MaxLen, sourceRope: ROPE, sourceRuns: TextLooks.Runs, sourceStart: Offset _ 0, sourceLen: Offset _ MaxLen, event: Event _ NIL] RETURNS [resultStart, resultLen: Offset]; <<-- like ReplaceText, except give rope and runs as source instead of node>> ReplaceWords: TwoSpanProc; <<-- replace the dest words by a copy of the source words>> <<-- adjusts appropriately to retain proper spacing>> <<-- returns the start location and length of the new text>> DeleteWords: OneSpanProc; <<-- delete the specified words>> CopyWords: DestSpanProc; <<-- copy the specified words>> MoveWords: DestSpanProc; MoveWordsOnto: TwoSpanProc; <<-- move the words in [start..start+len) onto those in [destStart..destStart+destLen)>> <<-- adjusts appropriately to retain proper spacing>> TransposeWords: TransposeProc; <<-- transpose the alpha words and the beta words>> <<-- adjusts appropriately to retain proper spacing>> <<-- returns new starts and lengths>> <<-- alphaResultStart, alphaResultLen are new start and length for alpha words>> <<-- betaResultStart, betaResultLen are new start and length for beta words>> ReplaceByChar: PROC [ root: Ref, dest: RefTextNode, char: CHAR, start: Offset _ 0, len: Offset _ MaxLen, inherit: BOOLEAN _ TRUE, looks: Looks _ noLooks, event: Event _ NIL] RETURNS [resultStart, resultLen: Offset]; <<-- 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 looks of previous char,>> <<-- else looks of char following replacement>> InsertChar: PROC [ root: Ref, dest: RefTextNode, char: CHAR, destLoc: Offset _ 0, inherit: BOOLEAN _ TRUE, looks: Looks _ noLooks, event: Event _ NIL] RETURNS [resultStart, resultLen: Offset] = INLINE { [resultStart,resultLen] _ ReplaceByChar[root, dest, char, destLoc, 0, inherit, looks, event] }; AppendChar: PROC [ root: Ref, dest: RefTextNode, char: CHAR, inherit: BOOLEAN _ TRUE, looks: Looks _ noLooks, event: Event _ NIL] RETURNS [resultStart, resultLen: Offset] = INLINE { [resultStart,resultLen] _ InsertChar[root, dest, char, MaxLen, inherit, looks, event] }; ReplaceByString: PROC [ root: Ref, dest: RefTextNode, string: REF READONLY TEXT, stringStart: NAT _ 0, stringNum: NAT _ MaxNat, start: Offset _ 0, len: Offset _ MaxLen, inherit: BOOLEAN _ TRUE, looks: Looks _ noLooks, event: Event _ NIL] RETURNS [resultStart, resultLen: Offset]; InsertString: PROC [ root: Ref, dest: RefTextNode, string: REF READONLY TEXT, stringStart: NAT _ 0, stringNum: NAT _ MaxNat, destLoc: Offset _ 0, inherit: BOOLEAN _ TRUE, looks: Looks _ noLooks, event: Event _ NIL] RETURNS [resultStart, resultLen: Offset] = INLINE { [resultStart,resultLen] _ ReplaceByString[root,dest,string,stringStart,stringNum, destLoc,0,inherit,looks,event] }; AppendString: PROC [ root: Ref, dest: RefTextNode, string: REF READONLY TEXT, stringStart: NAT _ 0, stringNum: NAT _ MaxNat, inherit: BOOLEAN _ TRUE, looks: Looks _ noLooks, event: Event _ NIL] RETURNS [resultStart, resultLen: Offset] = INLINE { [resultStart,resultLen] _ InsertString[root,dest,string,stringStart,stringNum, MaxLen,inherit,looks,event] }; ReplaceByRope: PROC [ root: Ref, dest: RefTextNode, rope: ROPE, start: Offset _ 0, len: Offset _ MaxLen, inherit: BOOLEAN _ TRUE, looks: Looks _ noLooks, event: Event _ NIL] RETURNS [resultStart, resultLen: Offset]; InsertRope: PROC [ root: Ref, dest: RefTextNode, rope: ROPE, destLoc: Offset _ 0, inherit: BOOLEAN _ TRUE, looks: Looks _ noLooks, event: Event _ NIL] RETURNS [resultStart, resultLen: Offset] = INLINE { [resultStart,resultLen] _ ReplaceByRope[root,dest,rope,destLoc,0,inherit,looks,event] }; AppendRope: PROC [ root: Ref, dest: RefTextNode, rope: ROPE, inherit: BOOLEAN _ TRUE, looks: Looks _ noLooks, event: Event _ NIL] RETURNS [resultStart, resultLen: Offset] = INLINE { [resultStart,resultLen] _ InsertRope[root,dest,rope,MaxLen,inherit,looks,event] }; <<-- ***** Cap's and Lowercase>> AllCaps: PROC [ root: Ref, dest: RefTextNode, start: Offset _ 0, len: Offset _ MaxLen, event: Event _ NIL] = INLINE { ChangeCaps[root,dest,start,len,allCaps,event] }; <<-- force specified span to all uppercase>> AllLower: PROC [ root: Ref, dest: RefTextNode, start: Offset _ 0, len: Offset _ MaxLen, event: Event _ NIL] = INLINE { ChangeCaps[root,dest,start,len,allLower,event] }; <<-- force specified span to all lowercase>> InitialCaps: PROC [ root: Ref, dest: RefTextNode, start: Offset _ 0, len: Offset _ MaxLen, event: Event _ NIL] = INLINE { ChangeCaps[root,dest,start,len,initCaps,event] }; <<-- force first letter of words uppercase>> CapChange: TYPE = {allCaps, allLower, initCaps, firstCap}; ChangeCaps: PROC [ root: Ref, dest: RefTextNode, start: Offset _ 0, len: Offset _ MaxLen, how: CapChange _ allCaps, event: Event _ NIL]; <<-- ***** Initialization>> Start: PROC; -- for initialization only END.