DIRECTORY Rope USING [ROPE], TiogaOpsDefs USING [Location, Order, Ref, SelectionGrain, WhichNodes, WhichSelection], ViewerClasses USING [Viewer]; TiogaOps: CEDAR DEFINITIONS = BEGIN ROPE: TYPE ~ Rope.ROPE; Viewer: TYPE ~ ViewerClasses.Viewer; Ref: TYPE = TiogaOpsDefs.Ref; -- points to a Tioga node Location: TYPE = TiogaOpsDefs.Location; -- RECORD [node: Ref, where: INT]; Order: TYPE = TiogaOpsDefs.Order; -- { before, same, after, disjoint } WhichNodes: TYPE = TiogaOpsDefs.WhichNodes; -- { root, selection } SelectionGrain: TYPE = TiogaOpsDefs.SelectionGrain; -- { point, char, word, node, branch } WhichSelection: TYPE = TiogaOpsDefs.WhichSelection; -- { primary, secondary, feedback } GetCaret: PROC RETURNS [loc: Location]; CaretBefore: PROC; CaretAfter: PROC; CaretOnly: PROC; GoToNextCharacter: PROC [n: INT _ 1]; GoToNextWord: PROC [n: INT _ 1]; GoToNextNode: PROC [n: INT _ 1]; GoToPreviousCharacter: PROC [n: INT _ 1]; GoToPreviousWord: PROC [n: INT _ 1]; GoToPreviousNode: PROC [n: INT _ 1]; ToPrimary: PROC; ToSecondary: PROC; Transpose: PROC; InsertRope: PROC [ROPE]; InsertChar: PROC [CHAR]; InsertLineBreak: PROC; BackSpace: PROC [n: INT _ 1]; BackWord: PROC [n: INT _ 1]; DeleteNextCharacter: PROC [n: INT _ 1]; DeleteNextWord: PROC [n: INT _ 1]; InsertTime: PROC; InsertBrackets: PROC [left, right: CHAR]; MakeControlCharacter: PROC; UnMakeControlCharacter: PROC; MakeOctalCharacter: PROC; UnMakeOctalCharacter: PROC; ExpandAbbreviation: PROC; Delete: PROC; Paste: PROC; SaveForPaste: PROC; SaveSpanForPaste: PROC [startLoc, endLoc: Location, grain: SelectionGrain _ char]; AllLower: PROC; AllCaps: PROC; InitialCaps: PROC; FirstCap: PROC; MesaFormatting: PROC; Repeat: PROC; Undo: PROC; Break: PROC; Join: PROC; Nest: PROC; UnNest: PROC; SetSelectionLooks: PROC [which: WhichSelection _ primary]; WhichLooks: TYPE = { caret, selection }; SetLooks: PROC [looks: ROPE, which: WhichLooks _ selection]; AddLooks: PROC [looks: ROPE, which: WhichLooks _ selection]; SubtractLooks: PROC [looks: ROPE, which: WhichLooks _ selection]; ClearLooks: PROC [which: WhichLooks _ selection]; CopyLooks: PROC; SetFormat: PROC [format: ROPE, which: WhichNodes _ selection]; CaretNodeFormat: PROC; InsertFormat: PROC; CopyFormat: PROC; SetStyle: PROC [style: ROPE, which: WhichNodes _ selection]; SelectMatchingBrackets: PROC [before, after: CHAR] RETURNS [found: BOOL]; NextPlaceholder: PROC [dir: Dir _ forward, gotoend: BOOL, startBoundaryNode, endBoundaryNode: Ref _ NIL, startBoundaryOffset: INT _ 0, endBoundaryOffset: INT _ LAST[INT]] RETURNS [found, wenttoend: BOOL]; NextViewer: PROC [dir: Dir _ forward] RETURNS [found: BOOL]; Dir: TYPE = { forward, backwards }; FindText: PROC [viewer: Viewer, rope: ROPE _ NIL, whichDir: SearchDir _ forwards, which: WhichSelection _ primary, case: BOOL _ TRUE -- case => case of characters is significant -- ] RETURNS [found: BOOL]; FindWord: PROC [viewer: Viewer, rope: ROPE _ NIL, whichDir: SearchDir _ forwards, which: WhichSelection _ primary, case: BOOL _ TRUE -- case => case of characters is significant -- ] RETURNS [found: BOOL]; FindDef: PROC [viewer: Viewer, rope: ROPE _ NIL, whichDir: SearchDir _ forwards, which: WhichSelection _ primary, case: BOOL _ TRUE -- case => case of characters is significant -- ] RETURNS [found: BOOL]; GetSelection: PROC [which: WhichSelection _ primary] RETURNS [viewer: Viewer, start, end: Location, level: SelectionGrain, caretBefore: BOOL, pendingDelete: BOOL]; SelectionRoot: PROC [which: WhichSelection _ primary] RETURNS [root: Ref]; SetSelection: PROC [viewer: Viewer, start, end: Location, level: SelectionGrain _ char, caretBefore: BOOL _ TRUE, pendingDelete: BOOL _ FALSE, which: WhichSelection _ primary]; SelectPoint: PROC [viewer: Viewer, caret: Location, which: WhichSelection _ primary]; SelectNodes: PROC [viewer: Viewer, start, end: Ref, level: SelectionGrain _ node, caretBefore: BOOL _ TRUE, pendingDelete: BOOL _ FALSE, which: WhichSelection _ primary]; SelectBranches: PROC [viewer: Viewer, start, end: Ref, level: SelectionGrain _ node, caretBefore: BOOL _ TRUE, pendingDelete: BOOL _ FALSE, which: WhichSelection _ primary]; SelectDocument: PROC [viewer: Viewer, level: SelectionGrain _ node, caretBefore: BOOL _ TRUE, pendingDelete: BOOL _ FALSE, which: WhichSelection _ primary]; SelectionError: ERROR [ec: SelectionErrorCode]; -- can be raised by the above procedures SelectionErrorCode: TYPE = { IllegalViewer, -- either NIL or destroyed or no document data IllegalNode, -- either start or end node is NIL WrongDoc, -- start node not part of the viewer document WrongOrder, -- start location doesn't come before end location BadStartOffset, -- not within size of start node BadEndOffset }; -- not within size of end node CancelSelection: PROC [which: WhichSelection _ primary]; SaveSelA: PROC; RestoreSelA: PROC; SaveSelB: PROC; RestoreSelB: PROC; GrowSelection: PROC; GrowSelectionToBlanks: PROC; GrowSelectionToSomething: PROC [left, right: PROC [CHAR] RETURNS [BOOL]]; LockSel: PROC [which: WhichSelection _ primary]; UnlockSel: PROC [which: WhichSelection _ primary]; GetRope: PROC [node: Ref] RETURNS [ROPE]; Parent: PROC [node: Ref] RETURNS [Ref]; Root: PROC [node: Ref] RETURNS [Ref]; Next: PROC [node: Ref] RETURNS [Ref]; Previous: PROC [node: Ref, parent: Ref _ NIL] RETURNS [nx: Ref]; StepForward: PROC [node: Ref] RETURNS [nx: Ref]; StepBackward: PROC [node: Ref, parent: Ref _ NIL] RETURNS [back: Ref]; FirstSibling: PROC [node: Ref] RETURNS [Ref]; LastSibling: PROC [node: Ref] RETURNS [Ref]; LastWithin: PROC [node: Ref] RETURNS [Ref]; FirstChild: PROC [node: Ref] RETURNS [Ref]; LastChild: PROC [node: Ref] RETURNS [Ref]; ViewerDoc: PROC [viewer: Viewer] RETURNS [Ref]; LocRelative: PROC [location: Location, count: INT, break: NAT _ 1, skipCommentNodes: BOOL _ FALSE] RETURNS [Location]; LocOffset: PROC [loc1, loc2: Location, break: NAT _ 1, skipCommentNodes: BOOL _ FALSE] RETURNS [count: INT]; BadArgs: ERROR; LastLocWithin: PROC [node: Ref] RETURNS [Location]; Jump: PROC [viewer: Viewer, loc: Location]; PutProp: PROC [n: Ref, name: ATOM, value: REF]; GetProp: PROC [n: Ref, name: ATOM] RETURNS [REF]; PutTextKey: PROC [node: Ref, where: INT, key: REF]; GetTextKey: PROC [node: Ref, key: REF] RETURNS [loc: Location]; TextKeyNotFound: ERROR; -- raised by GetTextKey FetchLooks: PROC [node: Ref, index: INT] RETURNS [ROPE]; GetFormat: PROC [node: Ref] RETURNS [ROPE]; -- NIL for default SetNodeFormat: PROC [format: ROPE, node: Ref]; GetStyle: PROC [node: Ref] RETURNS [ROPE]; -- NIL for default SetNodeStyle: PROC [style: ROPE, node: Ref]; IsComment: PROC [node: Ref] RETURNS [BOOL]; SetComment: PROC; SetNotComment: PROC; IsDirty: PROC [n: Ref] RETURNS [BOOL]; IsNew: PROC [n: Ref] RETURNS [BOOL]; ClearDirty: PROC [n: Ref]; ClearNew: PROC [n: Ref]; CompareLocOrder: PROC [loc1, loc2: Location] RETURNS [order: Order]; CompareNodeOrder: PROC [node1, node2: Ref] RETURNS [order: Order]; CallWithLocks: PROC [proc: PROC [root: Ref], root: Ref _ NIL]; NoSelection: ERROR; Lock: PROC [root: Ref]; Unlock: PROC [root: Ref]; SelectionSearch: PROC [pattern: Pattern, whichDir: SearchDir _ forwards, interrupt: REF BOOL _ NIL, startBoundaryNode, endBoundaryNode: Ref _ NIL, startBoundaryOffset: INT _ 0, endBoundaryOffset: INT _ LAST[INT]] RETURNS [found: BOOL]; NodeSearch: PROC [pattern: Pattern, whichDir: SearchDir _ forwards, startLoc, endLoc: Location, interrupt: REF BOOL _ NIL, startBoundaryNode, endBoundaryNode: Ref _ NIL, startBoundaryOffset: INT _ 0, endBoundaryOffset: INT _ LAST[INT]] RETURNS [found: BOOL, start, end: Location]; SearchDir: TYPE = { forwards, backwards, anywhere }; CreateSimplePattern: PROC [ target: ROPE, -- node from which to get the pattern case: BOOL _ TRUE, -- if true, match case literal: BOOL _ FALSE, -- if true, treat target literally rather than as a pattern word: BOOL _ FALSE, -- if true, match words only addBounds: BOOL _ FALSE] -- if true, add |'s to both ends of pattern RETURNS [pattern: Pattern]; CreateGeneralPattern: PROC [ target: Ref, -- node from which to get the pattern text: BOOL _ TRUE, -- if true, match target text looks: BOOL _ FALSE, -- if true, match target looks format: BOOL _ FALSE, -- if true, match target format style: BOOL _ FALSE, -- if true, match target style comment: BOOL _ FALSE, -- if true, match target comment property case: BOOL _ TRUE, -- if true, match case literal: BOOL _ FALSE, -- if true, treat target literally rather than as a pattern word: BOOL _ FALSE, -- if true, match words only subset: BOOL _ TRUE, -- if true, use subset for looks test, else use equality addBounds: BOOL _ FALSE] -- if true, add |'s to both ends of pattern RETURNS [pattern: Pattern]; MalformedPattern: ERROR [ec: PatternErrorCode]; PatternErrorCode: TYPE = { toobig, -- pattern too long endquote, -- pattern ends with ' endtilda, -- pattern ends with ~ boundary, -- pattern has | inside rather than at beginning or end missingNameEnd, -- pattern has < without matching > unmatchedNameEnd, -- pattern has > without previous < other -- other unspecified error in pattern }; Pattern: TYPE = REF PatternRec; PatternRec: TYPE = RECORD [ finder: Finder, text: BOOL, looks: BOOL, looksExact: BOOL, word: BOOL, commentControl: CommentControl, checkFormat: BOOL, format: ROPE, checkStyle: BOOL, style: ROPE, searchLooks: ROPE ]; Finder: TYPE = REF FinderRec; FinderRec: TYPE; CommentControl: TYPE = { includeComments, excludeComments, commentsOnly }; CommandProc: TYPE = PROC [viewer: Viewer _ NIL] RETURNS [recordAtom: BOOL _ TRUE, quit: BOOL _ FALSE]; RegisterCommand: PROC [name: ATOM, proc: CommandProc, before: BOOL _ TRUE]; Interpret: PROC [viewer: Viewer, params: LIST OF REF ANY]; RegisterAbbrevFailedProc: PROC [proc: PROC RETURNS [BOOL]]; RegisterFileNameProc: PROC [ proc: PROC [ROPE, Viewer] RETURNS [fileName: ROPE, search: ROPE] ]; END. January 9, 1983 5:16 pm moved SelectPoint, LastLocWithin here. Deleted Search, Find, LocWithin. nTiogaOps.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. written by Bill Paxton. June 1982 last written by Paxton. December 29, 1982 10:56 am last written by Teitelman. January 19, 1983 12:02 pm Michael Plass, March 15, 1985 10:56:12 am PST Rick Beach, March 15, 1985 10:22:38 am PST Doug Wyatt, April 14, 1985 5:03:43 pm PST Other operations are available in TiogaExtraOps.mesa (they don't all fit in a single interface!) Operations on/using selections Caret Operations (for primary selection) Edits requiring secondary selections Editing applying to primary selection inserts a CR and then copies blanks from front of previous line like SaveForPaste, but saves the given span rather than the selection use grain = node or branch to simulate node or branch selections span need not come from document currently in a viewer Node Editing Looks sets the selection looks from the looks of the character next to the caret copies looks from secondary selection to primary selection see LooksReader.mesa if you need to read a lot of looks Formats will delete the word to the left of the caret and make it the format of the caret node inserts the format name copies format from secondary selection to primary selection Styles Searching To search for a specified pattern, see SelectionSearch in section on Search below. If gotoend is true and doesn't find placeholder and not already at end of document, will make point selection at end and return with found=false and wenttoend=true. FindText, FindWord, and FindDef correspond to Find, Word, Def in the Places menu. if rope is NIL, uses contents of primary selection instead doesn't give user message if fails to find which parameter determines which selection to make Making/changing a selection Returns the document root for the selection. grows until procs return true. Locking a Selection Note: CallWithLocks, described below, is the recommended way of locking selections and documents. If for some reason you cannot use CallWithLocks, here are more primitive locking procedures. ensures that no other process will change primary selection. same process can re-Lock several times. make sure you UnlockSel as many times as you LockSel. Operations on nodes Basic operations the contents of the node returns next sibling of n returns NIL if n is last sibling returns previous sibling of n returns NIL if n is first sibling runs faster if can supply parent returns next node in standard tree walk order returns preceding node in standard tree walk order returns the last node within the branch i.e., goes to last child of last child of last child ... until no child Returns root node for a text or typescript viewer. Searching See NodeSearch in section on Search below Location procedures count is interpreted as a character offset from given location returns location corresponding to count adds in break at the end of each text node if skipCommentNodes is true, then ignores them in walking the tree returns character offset of location2 relative to location1 loc1 and loc2 can be in same node but loc2 must not be in node before loc1 or get ERROR BadArgs if skipCommentNodes is true, then ignores them in walking the tree returns the last location within the branch Normalizes the viewer with respect to the indicated location. loc must be in the document already being displayed in the viewer. Property Lists NIL is a valid value. Use RemProp to remove property. (Although GetProp will not distinguish between property value NIL and no property present, it is useful to be able to have NIL values to avoid creating garbage. Setting to NIL doesn't release the property record, so don't need to reallocate when next set to a non-NIL value. Note: SetProp, RemProp, and MapProps are defined in TiogaExtraOps. Text keys: persistent "addresses" for characters in text nodes Associates the key with the given offset in the text node. Key moves with the text as edits take place in the node. Key can move to new node. Tells you where the key is in the node at the current time. loc node may be different if addr has been moved Note: RemoveTextKey and MapTextKeys are defined in TiogaExtrasOps. Looks, Formats, Styles will set format on a given node that need not be selected at the time will set style on a given node that need not be selected at the time Comment Property applies to all selected nodes applies to all selected nodes Dirty and New bits on nodes turns off the dirty bit on the node turns off the new bit on the node Comparing order of nodes or locations in document Locking a node This is the recommended way to take care of locking selections and documents. This procedure locks the primary selection. If root is NIL, it gets SelectionRoot[]. Then it locks the document by calling Lock[root]. After calling proc with the root, it unlocks both the document and the selection. It also takes care of unlocking them if it sees an UNWIND signal. If root is NIL and there is no selection, it raises the error NoSelection. raised by CallWithLocks If for some good reason you cannot use CallWithLocks, here are the primitive locking procedures. ensures that no other process will edit document. same process can re-Lock several times. make sure you Unlock as many times as you Lock. repaints are deferred until document is unlocked. Searching SelectionSearch searches the document that contains the current selection, and when finished, changes the current selection. NodeSearch is not tied to, nor does it change, the selection, but starts with a specified node, and traverses the tree, returning a location if the search is successful. Both take patterns which can be created as described below. startBoundaryNode and startBoundaryOffset limit how far backwards the search will go. if startBoundaryNode=NIL, search will go to start of document endBoundaryNode and endBoundaryOffset limit how far forwards the search will go. if endBoundaryNode=NIL, search will go to end of document. Similar to SelectionSearch, but doesn't change the selection. Just returns the result. startLoc and endLoc args serve to determine where to start the search just as primary selection serves in LookForPattern. This can be used to search in documents that are not currently being displayed in a viewer. CreateSimplePattern and CreateGeneralPattern can result in MalformedPattern being raised. Registering Command procedures These operations let you modify and extend the standard Tioga commands or add new commands of your own. The Tioga command interpreter keeps a table mapping each command atom to a list of CommandProc's. When it is given an atom to interpret, it gets the corresponding list of command procs and calls them one-by-one until someone returns with quit=TRUE. If any command proc returns with recordAtom=TRUE, the atom will be added to the repeat list for the current edit event (and will thus be re-interpreted if the user hits Repeat). The viewer argument to the command proc is the one passed to the interpreter which typically is the input focus viewer. For menu commands, the viewer is the one that contains the button. If before is true, proc goes at front of list, else goes at end of list. UnRegisterCommand: PROC [name: ATOM, proc: CommandProc]; Remove the proc from the list for the atom. Defined in TiogaExtraOps. Wouldn't fit here. this calls the Tioga interpreter. params can be atoms or ropes. atoms are interpreted in manner described above, ropes are inserted at the caret. Miscellaneous call-back procedures If abbreviation expansion fails (i.e., cannot find the key), calls this proc. If it returns true, then it has done something useful. Otherwise, user gets normal error message. There can only be one of these registered at a time. Call RegisterAbbrevFailedProc with NIL to un-register. If try to load/open a file and filename is unknown, call this proc to get a corrected file name. There can only be one of these registered at a time. Call RegisterFileNameProc with NIL to un-register. Κi˜codešœ ™ Kšœ Οmœ1™K˜—š’œžœ˜KšœV™VK˜—š’ œžœ˜Kšœ™K˜—š’ œžœ˜Kšœ;™;K™——šœ™Kš’œžœ žœ!˜Kšœ  ˜0Kšœ ˜.K˜—š’œžœ#˜8K˜—š’œžœ˜K˜—š’ œžœ˜K˜—š’œžœ˜K˜—š’ œžœ˜K˜—š’ œžœ˜K˜—š’œžœ˜K˜—š ’œžœžœžœžœžœ˜IK™—K™—™K™ΎK˜š’œžœ#˜0Kšœd™dK˜—š’ œžœ#˜2K™5K™———šœ™™š’œžœ žœžœ˜)Kšœ™K˜—š’œžœ žœ˜'K˜—š’œžœ žœ˜%K˜—š’œžœ žœ˜%Kšœ™Kšœ ™ K˜—š’œžœžœžœ ˜@Kšœ™Kšœ!™!Kšœ ™ K˜—š’ œžœ žœ ˜0Kšœ-™-K˜—š’ œžœžœžœ ˜FKšœ2™2K˜—š’ œžœ žœ˜-K˜—š’ œžœ žœ˜,K˜—š’ œžœ žœ˜+Kšœ(™(KšœG™GK˜—š’ œžœ žœ˜+K˜—š’ œžœ žœ˜*K˜—š’ œžœžœ˜/K™2K™——šœ ™ Kšœ)™)—šœ™š’ œžœžœ žœžœžœžœ ˜vKšœ>™>Kšœ5™5Kšœ*™*KšœB™BK˜—š’ œžœ žœžœžœžœ žœ˜mKšœ;™;Kšœ!™!Kšœ=™=KšœB™BK˜—šœ žœ˜K˜—š’ œžœ žœ ˜3Kšœ+™+K˜—š’œžœ!˜+Kšœ€™€K™——šœ™š’œžœžœ žœ˜/KšœΛ™ΛK™—Kš ’œžœžœžœžœ˜1K˜K™B—šœ>™>š’ œžœžœžœ˜3Kšœ™K˜—š’ œžœžœžœ˜?K™;K™0K˜—Kšœžœ ˜/K˜K™B—™Kš ’ œžœžœžœžœ˜8K˜š ’ œžœ žœžœ ˜>K˜—š’ œžœ žœ ˜.K™E—K˜š ’œžœ žœžœ ˜=K˜—š’ œžœ žœ ˜,KšœD™D——šœ™š’ œžœ žœžœ˜+K˜—š’ œžœ˜Kšœ™K˜—š’ œžœ˜Kšœ™K™——šœ™š’œžœ žœžœ˜&K˜—š’œžœ žœžœ˜$K˜—š’ œžœ ˜Kšœ#™#K˜—š’œžœ ˜Kšœ!™!K™——šœ1™1š’œžœžœ˜DK˜—š’œžœžœ˜BK˜——™š’ œžœžœžœ˜>K™ΉK™—šœ žœ˜Kšœ™—K™K™`K™š’œžœ ˜KšœY™YK˜—š’œžœ ˜K™bK™———šœ ™ Kšœβ™β˜š’œžœ?žœžœžœ,žœžœžœžœžœžœ žœ˜λKšœ”™”KšœŒ™Œ—K™š’ œžœ3žœ'žœžœžœžœ*žœžœžœžœžœžœžœ žœ˜˜K™VKšœΦ™Φ—K˜Kšœ žœ%˜4K˜š!’œžœ žœ %œžœžœ œ žœžœ ;œžœžœ œ žœžœ +žœ˜ήK˜—šC’œžœ %œžœžœ œžœžœ œ žœžœ œžœžœ œ žœžœ )œžœžœ œ žœžœ ;œžœžœ œ žœžœ 8œ žœžœ +žœ˜ΌK˜—K™YK™Kšœžœ˜/šœžœ˜Kšœ ˜Kšœ  ˜ Kšœ  ˜ Kšœ  7˜AKšœ #˜3Kšœ #˜5Kšœ %˜+K˜—K˜Kšœ žœžœ ˜šœ žœžœ˜Kšœ˜Kšœžœ˜ Kšœžœ˜ Kšœ žœ˜Kšœžœ˜ Kšœ˜Kšœ žœ˜Kšœžœ˜ Kšœ žœ˜Kšœžœ˜ Kšœ ž˜Kšœ˜K˜—Kšœžœžœ ˜šœ žœ˜K˜—Kšœžœ6˜J——šœ™Kšœέžœ/žœ™•™šœ žœžœžœžœžœžœžœžœ˜gK™»K˜—š ’œžœžœžœžœ˜KK™HK˜—šœ8™8K™XK™—K˜š ’ œžœžœžœžœžœ˜:K™!™K™Q—K™———šœ#™#š ’œžœžœžœžœ˜;KšœŒžœ™ŸK™—š’œžœ žœžœ žœ žœ žœ˜`Kšœ·žœ™Κ——K˜šžœ˜K˜K˜_——…—'PX'