DIRECTORY RopeEdit, TextLooks, TextNode, UndoEvent; TextEdit: CEDAR DEFINITIONS IMPORTS TextLooks, RopeEdit = 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; FetchChar: PROC [text: RefTextNode, index: Offset] RETURNS [CHAR]; FetchLooks: PROC [text: RefTextNode, index: Offset] RETURNS [Looks]; Fetch: PROC [text: RefTextNode, index: Offset] RETURNS [CHAR, Looks]; 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]; AlreadySaved: PROC [text: RefTextNode, event: Event] RETURNS [BOOLEAN]; FromRope: PROC [rope: ROPE] RETURNS [RefTextNode]; FromString: PROC [string: REF READONLY TEXT] RETURNS [RefTextNode]; DocFromNode: PROC [child: Ref] RETURNS [root: Ref]; ChangeLooks: PROC [ root: Ref, text: RefTextNode, remove, add: Looks, start: Offset _ 0, len: Offset _ MaxOffset, event: Event _ NIL]; 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] }; 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]; PutProp: PROC [ node: Ref, name: ROPE, value: REF, event: Event _ NIL, root: Ref _ NIL]; GetProp: PROC [node: Ref, name: ROPE] RETURNS [value: REF]; 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; OneSpanProc: TYPE = PROC [ root: Ref, text: RefTextNode, start: Offset _ 0, len: Offset _ MaxLen, event: Event _ NIL]; DeleteText: OneSpanProc; CopyText: DestSpanProc; MoveText: DestSpanProc; MoveTextOnto: TwoSpanProc; 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; 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]; ReplaceWords: TwoSpanProc; DeleteWords: OneSpanProc; CopyWords: DestSpanProc; MoveWords: DestSpanProc; MoveWordsOnto: TwoSpanProc; TransposeWords: TransposeProc; 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]; 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] }; AllCaps: PROC [ root: Ref, dest: RefTextNode, start: Offset _ 0, len: Offset _ MaxLen, event: Event _ NIL] = INLINE { ChangeCaps[root,dest,start,len,allCaps,event] }; AllLower: PROC [ root: Ref, dest: RefTextNode, start: Offset _ 0, len: Offset _ MaxLen, event: Event _ NIL] = INLINE { ChangeCaps[root,dest,start,len,allLower,event] }; InitialCaps: PROC [ root: Ref, dest: RefTextNode, start: Offset _ 0, len: Offset _ MaxLen, event: Event _ NIL] = INLINE { ChangeCaps[root,dest,start,len,initCaps,event] }; CapChange: TYPE = {allCaps, allLower, initCaps, firstCap}; ChangeCaps: PROC [ root: Ref, dest: RefTextNode, start: Offset _ 0, len: Offset _ MaxLen, how: CapChange _ allCaps, event: Event _ NIL]; Start: PROC; -- for initialization only END. -- TextEdit.mesa -- written by Bill Paxton, February 1981 -- last edit by Bill Paxton, April 23, 1982 6:14 am -- 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 -- **** General operations **** -- fetches the indexed information -- use rope readers if want characters from contiquous locations -- returns the looks for the character at the given location -- use reader's if getting looks for sequence of locations -- fetches the indexed information -- use rope & looks readers if want info from contiquous locations -- returns true if it decides to flatten rope & runs -- this is done automatically after a certain number of edits to the node -- returns TRUE if there is already a ChangingText record for given node in the event -- **** Operations to create a text node **** -- create a text node with looks from a normal rope -- copies the contents of the string -- returns root node which has one child -- child typically created by FromRope or FromString -- **** Operations to add or delete looks **** -- first remove then add in the given range -- **** Changing Style / Type / Property of node **** -- appends style to end of node prefix -- **** Editing Operations for text **** -- NOTE: edit operations do not create or delete addrs, -- but they can change their locations within the text -- 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 -- delete the specified range of text -- addrs that are in the deleted section move to start -- copy the specified text -- add length of inserted text to addrs that are beyond destLoc -- 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 -- move [start..start+len) onto [destStart..destStart+destLen) -- implemented by appropriate calls on MoveText and DeleteText -- 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 -- like ReplaceText, except give rope and runs as source instead of node -- 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 -- delete the specified words -- copy the specified words -- move the words in [start..start+len) onto those in [destStart..destStart+destLen) -- adjusts appropriately to retain proper spacing -- 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 -- 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 -- ***** Cap's and Lowercase -- force specified span to all uppercase -- force specified span to all lowercase -- force first letter of words uppercase -- ***** Initialization Ê _˜JšÏc™Jš(™(Jš3™3J˜šU™UJš0™0Jš/™/JšD™DJšK™KJš6™6Jš;™;J˜—š™š=™=Jš8™8JšC™C—š!™!Jš?™?—š ™ JšK™K—š™JšQ™Q—šJ™JJš(™(Jš.™.Jš(™(—š=™=Jš!™!J˜——š)™)JšH™HJšJ™JJšF™FJš>™>J˜—š™Jš8™8Jš<™<šB™BJš4™4—Jš6™6J˜—š ™ JšE™Eš>™>š)™)Jš?™?——JšN™NJšC™CJ˜—š™JšC™CšF™FJš2™2—Jš+™+J˜—š™JšM™Mš;™;Jš=™=Jš$™$—Jš!™!J˜—š™Jš™Jš6™6Jš ™ J˜J˜—JšÏk ˜ J˜ J˜ J˜ J˜ J˜šœ ž˜Jšžœ˜—Jšž˜J˜Jšœžœ˜Jšœ žœ˜)Jšžœžœ žœ˜J˜Jšœžœ˜J˜#J˜%Jšœžœ˜ Jšœžœ ˜)Jšœžœžœžœ˜Jšœžœ˜J˜J˜Jš™J˜šÏn œžœ$žœžœ˜BJš"™"Jš@™@J˜—šŸ œžœ$žœ ˜DJš<™˜FJ˜—šŸ œžœ˜J˜7Jšœ;žœ˜?JšœžœA˜IJ˜—šŸœžœ˜J˜)Jšœ;žœ˜?Jšœžœ?˜GJ˜—šŸ œžœ˜JšœYžœ˜]JšœžœC˜KJ˜J˜—Jš5™5J˜JšŸ œžœ9žœžœ˜_J˜šŸ œžœ˜Jšœžœžœžœ˜™>Jš>™>J˜—šŸ œžœžœ˜J˜J˜FJšœSžœ˜WJšžœL˜SJ˜—˜Jš-™-š ™ Jš&™&Jš/™/J˜——šŸ œžœ˜J˜ J˜CJšœ žœ˜-JšœDžœ˜HJšžœ"˜)JšH™HJ˜—˜Jš7™7Jš1™1Jš8™8J˜—˜Jš™J˜—˜Jš™J˜—J˜J˜˜JšT™TJš1™1J˜—˜Jš/™/Jš1™1š!™!JšL™LJšI™IJ˜——šŸ œžœ˜J˜ Jšœžœ˜J˜(Jšœ žœžœ)žœ˜DJšžœ"˜)Jš2™2š;™;Jš@™@Jš-™-Jš+™+J˜——šŸ œžœ˜J˜ Jšœžœ˜3Jšœ žœžœ)žœ˜DJšžœ$žœ˜3J˜_J˜—šŸ œžœ˜J˜ Jšœžœ˜Jšœ žœžœ)žœ˜DJšžœ$žœ˜3J˜XJ˜—šŸœžœ˜J˜ Jšœžœžœžœ˜-Jšœ žœžœ ˜.J˜(Jšœ žœžœ)žœ˜DJšžœ"˜)J˜—šŸ œžœ˜J˜ Jšœžœžœžœ˜-Jšœ žœžœ ˜.J˜Jšœ žœžœ)žœ˜DJšžœ$žœ˜3˜QJ˜!J˜——šŸ œžœ˜J˜ Jšœžœžœžœ˜-Jšœ žœžœ ˜.Jšœ žœžœ)žœ˜DJšžœ$žœ˜3˜NJ˜J˜——šŸ œžœ˜J˜ Jšœžœ˜J˜(Jšœ žœžœ)žœ˜DJšžœ"˜)J˜—šŸ œžœ˜J˜ Jšœžœ˜3Jšœ žœžœ)žœ˜DJšžœ$žœ˜3J˜XJ˜—šŸ œžœ˜J˜ Jšœžœ˜Jšœ žœžœ)žœ˜DJšžœ$žœ˜3J˜RJ˜J˜—Jš™J˜šŸœžœ˜J˜ JšœKžœ˜QJšžœ3˜9Jš(™(J˜—šŸœžœ˜J˜ JšœKžœ˜QJšžœ4˜:Jš(™(J˜—šŸ œžœ˜J˜ JšœKžœ˜QJšžœ4˜:Jš(™(J˜—Jšœ žœ+˜:J˜šŸ œžœ˜J˜ J˜;Jšœ)žœ˜.J˜J˜—Jš™J˜JšŸœžœ˜'J˜Jšžœ˜J˜—…—N@=