<<-- TiogaMiscOps2Impl.mesa Edited by Paxton on December 28, 1982 2:23 pm>> <> DIRECTORY AbbrevExpand USING [Expand, Load], CIFS USING [Error], EditSpan USING [ChangeCaps], Inline USING [BITAND], MessageWindow USING [Append, Blink], NameSymbolTable USING [MakeName, Name, RopeFromName], NodeProps USING [false, true], NodeStyle USING [Name, ReloadStyle, StyleNameForNode], NodeStyleExtra USING [ForEachAttachedStyle], Rope USING [Concat, Fetch, Flatten, FromProc, Lower, ROPE, Size, Substr], RopeEdit USING [AlphaNumericChar, Substr], RopeReader USING [FreeRopeReader, Get, GetIndex, GetRopeReader, Ref, SetPosition], TextEdit USING [CapChange, ChangeFormat, ChangeStyle, FetchChar, FetchLooks, GetRope, PutProp, ReplaceByChar], TiogaNode USING [Location, NodeItself, nullName, Offset, Ref, RefBranchNode, RefTextNode, Name], TiogaNodeOps USING [NarrowToTextNode, Root, StepForwardNode], TiogaDocument USING [BeforeAfter, Selection, SelectionId, SelectionPoint], TiogaInput USING [currentEvent, Interpret], TiogaInputOps, TiogaLocks USING [Lock, Unlock], TiogaOps, TiogaSelection USING [Alloc, Copy, Free, CaretAfterSelection, Deselect, InsertionPoint, LockSel, MakePointSelection, MakeSelection, oldSel, pSel, SelectionRoot, sSel, UnlockSel], TiogaTouchup USING [fullUpdate], ViewerClasses USING [Viewer], ViewerOps USING [PaintViewer]; TiogaMiscOps2Impl: CEDAR PROGRAM IMPORTS AbbrevExpand, CIFS, EditSpan, Inline, MessageWindow, NameSymbolTable, NodeProps, NodeStyle, NodeStyleExtra, Rope, RopeEdit, RopeReader, TiogaInput, TiogaInputOps, TiogaLocks, TiogaSelection, TiogaTouchup, TextEdit, TiogaNodeOps, ViewerOps EXPORTS TiogaInputOps = BEGIN OPEN TiogaDocument, TiogaSelection, TiogaOps, TiogaInputOps; Capitalise: PUBLIC PROCEDURE [flavor: TextEdit.CapChange] = { DoCapitalise: PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = { Deselect[]; EditSpan.ChangeCaps[root, [tSel.start.pos, tSel.end.pos], flavor, TiogaInput.currentEvent]; tSel.pendingDelete _ FALSE; MakeSelection[tSel,primary] }; CallWithLocks[DoCapitalise] }; ControlChar: PROC [make: BOOLEAN] = { DoControlChar: PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = { caret: TiogaNode.Location _ InsertionPoint[tSel]; node: TiogaNode.RefTextNode; where: TiogaNode.Offset; char: CHAR; IF caret.where=TiogaNode.NodeItself OR caret.where=0 THEN GOTO Bad; IF (node _ TiogaNodeOps.NarrowToTextNode[caret.node]) = NIL THEN GOTO Bad; where _ caret.where-1; char _ TextEdit.FetchChar[node,where]; IF ~make AND char > 37C THEN GOTO Bad; char _ IF ~make THEN 'A+LOOPHOLE[char-1,CARDINAL] ELSE LOOPHOLE[Inline.BITAND[char,37B],CHAR]; Deselect[]; [] _ TextEdit.ReplaceByChar[ root: root, dest:node, char:char, start:where, len:1, inherit:FALSE, looks:TextEdit.FetchLooks[node,where], event:TiogaInput.currentEvent]; MakePointSelection[tSel, caret]; EXITS Bad => EditFailed[] }; CallWithLocks[DoControlChar] }; MakeControlCharacter: PUBLIC PROC = { ControlChar[TRUE] }; UnMakeControlCharacter: PUBLIC PROC = { ControlChar[FALSE] }; UnMakeOctalCharacter: PUBLIC PROC = { DoUnMakeOctalCharacter: PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = { caret: TiogaNode.Location _ InsertionPoint[tSel]; node: TiogaNode.RefTextNode; char: CARDINAL; IF caret.where=TiogaNode.NodeItself OR caret.where=0 THEN GOTO Bad; IF (node _ TiogaNodeOps.NarrowToTextNode[caret.node]) = NIL THEN GOTO Bad; char _ LOOPHOLE[TextEdit.FetchChar[node,caret.where-1]]; BackSpace[1]; InsertChar[char/64 + '0]; InsertChar[(char/8) MOD 8 + '0]; InsertChar[char MOD 8 + '0]; EXITS Bad => EditFailed[] }; CallWithLocks[DoUnMakeOctalCharacter] }; MakeOctalCharacter: PUBLIC PROC = { DoMakeOctalCharacter: PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = { caret: TiogaNode.Location _ InsertionPoint[tSel]; node: TiogaNode.RefTextNode; where: TiogaNode.Offset; char: CHAR; d: CARDINAL; IF caret.where=TiogaNode.NodeItself OR caret.where<3 THEN GOTO Bad; IF (node _ TiogaNodeOps.NarrowToTextNode[caret.node]) = NIL THEN GOTO Bad; where _ caret.where-3; char _ TextEdit.FetchChar[node,where]; IF char NOT IN ['0..'3] THEN GOTO Bad; d _ char-'0; IF (char _ TextEdit.FetchChar[node,where+1]) NOT IN ['0..'7] THEN GOTO Bad; d _ d*8 + char-'0; IF (char _ TextEdit.FetchChar[node,where+2]) NOT IN ['0..'7] THEN GOTO Bad; d _ d*8 + char-'0; Deselect[]; [] _ TextEdit.ReplaceByChar[ root:root, dest:node, char:LOOPHOLE[d], start:where, len:3, inherit:FALSE, looks:TextEdit.FetchLooks[node,where], event:TiogaInput.currentEvent]; caret.where _ where+1; MakePointSelection[tSel, caret]; EXITS Bad => EditFailed[] }; CallWithLocks[DoMakeOctalCharacter] }; NameFromRope: PROC [name: Rope.ROPE] RETURNS [NameSymbolTable.Name] = TRUSTED INLINE { RETURN [NameSymbolTable.MakeName[LOOPHOLE[Rope.Flatten[name]]]]}; GetWord: PROC RETURNS [word: Rope.ROPE] = { tSel: Selection; start: TiogaNode.Offset; pos: TiogaNode.Location; node: TiogaNode.RefTextNode; nChars: CARDINAL _ 0; CaretAfterSelection; pos _ InsertionPoint[]; IF (node _ TiogaNodeOps.NarrowToTextNode[pos.node])=NIL THEN RETURN [NIL]; IF pos.where = TiogaNode.NodeItself THEN RETURN [NIL]; start _ pos.where-1; WHILE start>=0 AND RopeEdit.AlphaNumericChar[TextEdit.FetchChar[node,start]] DO start _ start - 1; nChars _ nChars + 1; ENDLOOP; IF nChars = 0 THEN RETURN [NIL]; start _ pos.where-nChars; word _ RopeEdit.Substr[node.rope, start, nChars]; tSel _ Alloc[]; TiogaSelection.Copy[source: pSel, dest: tSel]; tSel.start.pos _ [node,start]; tSel.end.pos _ [node,start+nChars-1]; tSel.granularity _ char; MakeSelection[tSel, primary]; Free[tSel]; Delete[]; }; SetStyle: PUBLIC PROC = { DoSetStyle: PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = { name: Rope.ROPE _ GetWord[]; IF name=NIL THEN { EditFailed[]; RETURN }; SetStyleName[name] }; CallWithLocks[DoSetStyle] }; ForceLower: PROC [r: Rope.ROPE] RETURNS [Rope.ROPE] = { Force: PROC RETURNS [c: CHAR] = { c _ Rope.Lower[Rope.Fetch[r,i]]; i _ i+1 }; i: INT _ 0; RETURN [Rope.FromProc[Rope.Size[r], Force]] }; SetStyleName: PUBLIC PROC [name: Rope.ROPE, node: TiogaNode.Ref _ NIL] = BEGIN root: TiogaNode.RefBranchNode; IF node=NIL THEN node _ IF pSel.insertion=before THEN pSel.start.pos.node ELSE pSel.end.pos.node; root _ TiogaNodeOps.Root[node]; [] _ TiogaLocks.Lock[root, "SetStyleName"]; TextEdit.ChangeStyle[node, ForceLower[name], TiogaInput.currentEvent, root ! UNWIND => TiogaLocks.Unlock[root]]; TiogaLocks.Unlock[root]; END; ReloadStyle: PUBLIC PROC = BEGIN styleName: NodeStyle.Name _ NodeStyle.StyleNameForNode[InsertionPoint[].node]; IF ~NodeStyle.ReloadStyle[styleName] THEN CannotReload[styleName] ELSE ViewerOps.PaintViewer[pSel.viewer, client, FALSE, TiogaTouchup.fullUpdate]; END; ReloadStyleName: PUBLIC PROC [name: Rope.ROPE] = BEGIN styleName: NodeStyle.Name; IF Rope.Size[name]=0 THEN RETURN; styleName _ NameFromRope[name]; IF ~NodeStyle.ReloadStyle[styleName] THEN CannotReload[styleName]; END; CannotReload: PROC [styleName: NodeStyle.Name] = { OPEN MessageWindow; Append["Failed in attempt to load style named ", TRUE]; Append[NameSymbolTable.RopeFromName[styleName]]; Blink[] }; SetFormat: PUBLIC PROC = { DoSetFormat: PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = { name: Rope.ROPE _ GetWord[]; IF name=NIL THEN { EditFailed[]; RETURN }; SetFormatName[name] }; CallWithLocks[DoSetFormat] }; GetFormat: PUBLIC PROC = { DoGetFormat: PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = { name: Rope.ROPE; format: TiogaNode.Name _ InsertionPoint[].node.format; name _ IF format=TiogaNode.nullName THEN "default" ELSE NameSymbolTable.RopeFromName[format]; InsertRope[name] }; CallWithLocks[DoGetFormat] }; TransposeFormat: PUBLIC PROC [target: SelectionId _ primary] = { <<-- Transpose the formats of the primary and secondary selections>> targetSel: Selection _ IF target=primary THEN pSel ELSE sSel; srcSel: Selection _ IF target=primary THEN sSel ELSE pSel; DoTransFormat: PROC [ sourceRoot, destRoot: TiogaNode.RefBranchNode, tSel, srcSel, targetSel: Selection] = { targetFormat, srcFormat: TiogaNode.Name; targetNode, srcNode: TiogaNode.Ref; srcNode _ IF srcSel.insertion=before THEN srcSel.start.pos.node ELSE srcSel.end.pos.node; srcFormat _ srcNode.format; targetNode _ IF targetSel.insertion=before THEN targetSel.start.pos.node ELSE targetSel.end.pos.node; targetFormat _ targetNode.format; TiogaSelection.Copy[source: targetSel, dest: oldSel]; -- save for Repeat's FOR node: TiogaNode.Ref _ targetSel.start.pos.node, TiogaNodeOps.StepForwardNode[node] DO TextEdit.ChangeFormat[node, srcFormat, TiogaInput.currentEvent, destRoot]; IF node = targetSel.end.pos.node THEN EXIT; ENDLOOP; FOR node: TiogaNode.Ref _ srcSel.start.pos.node, TiogaNodeOps.StepForwardNode[node] DO TextEdit.ChangeFormat[node, targetFormat, TiogaInput.currentEvent, sourceRoot]; IF node = srcSel.end.pos.node THEN EXIT; ENDLOOP; MakeSelection[IF target=primary THEN targetSel ELSE srcSel, primary] }; CallWithBothLocked[DoTransFormat, targetSel, srcSel, write] }; CopyFormat: PUBLIC PROCEDURE [target: SelectionId _ primary] = { targetSel: Selection _ IF target=primary THEN pSel ELSE sSel; srcSel: Selection _ IF target=primary THEN sSel ELSE pSel; DoCopyFormat: PROC [ sourceRoot, destRoot: TiogaNode.RefBranchNode, tSel, srcSel, targetSel: Selection] = { srcNode: TiogaNode.Ref _ IF srcSel.insertion=before THEN srcSel.start.pos.node ELSE srcSel.end.pos.node; format: TiogaNode.Name _ srcNode.format; TiogaSelection.Copy[source: srcSel, dest: oldSel]; -- save for Repeat's FOR node: TiogaNode.Ref _ targetSel.start.pos.node, TiogaNodeOps.StepForwardNode[node] DO TextEdit.ChangeFormat[node, format, TiogaInput.currentEvent, destRoot]; IF node = targetSel.end.pos.node THEN EXIT; ENDLOOP; MakeSelection[IF target=primary THEN targetSel ELSE srcSel, primary] }; CallWithBothLocked[DoCopyFormat, targetSel, srcSel, read] }; SetFormatName: PUBLIC PROC [name: Rope.ROPE, node: TiogaNode.Ref _ NIL] = { root: TiogaNode.RefBranchNode; lockSel: BOOL = (node=NIL); format: TiogaNode.Name _ IF name=NIL THEN TiogaNode.nullName ELSE NameFromRope[ForceLower[name]]; IF lockSel THEN { LockSel[primary, "SetFormatName"]; IF ~CheckReadonly[pSel] OR (root _ SelectionRoot[pSel])=NIL THEN { UnlockSel[primary]; RETURN }; node _ InsertionPoint[].node } ELSE root _ TiogaNodeOps.Root[node]; { ENABLE UNWIND => IF lockSel THEN UnlockSel[primary]; [] _ TiogaLocks.Lock[root, "SetFormatName"]; TextEdit.ChangeFormat[node, format, TiogaInput.currentEvent, root]; TiogaLocks.Unlock[root]; IF lockSel THEN UnlockSel[primary] }}; SetSelFormatName: PROC [name: Rope.ROPE, sel: Selection] = { DoSetSelFormatName: PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = { format: TiogaNode.Name _ IF name=NIL THEN TiogaNode.nullName ELSE NameFromRope[ForceLower[name]]; FOR node: TiogaNode.Ref _ tSel.start.pos.node, TiogaNodeOps.StepForwardNode[node] DO TextEdit.ChangeFormat[node, format, TiogaInput.currentEvent, root]; IF node = tSel.end.pos.node THEN EXIT; ENDLOOP }; CallWithLocks[DoSetSelFormatName] }; SetCommentProp: PUBLIC PROC [flag: BOOLEAN] = { DoSetCommentProp: PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = { FOR node: TiogaNode.Ref _ tSel.start.pos.node, TiogaNodeOps.StepForwardNode[node] DO n: TiogaNode.RefTextNode _ TiogaNodeOps.NarrowToTextNode[node]; IF n # NIL THEN TextEdit.PutProp[n, "Comment", IF flag THEN NodeProps.true ELSE NodeProps.false, TiogaInput.currentEvent]; IF node = tSel.end.pos.node THEN EXIT; ENDLOOP }; CallWithLocks[DoSetCommentProp] }; abbrevFailedProc: PROC RETURNS [BOOL] _ NIL; RegisterAbbrevFailedProc: PUBLIC PROC [proc: PROC RETURNS [BOOL]] = { abbrevFailedProc _ proc }; ExpandAbbreviation: PUBLIC PROC = { DoExpand: PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = { pos: TiogaNode.Location; node: TiogaNode.RefTextNode; offset: TiogaNode.Offset; done, keyDeterminesDict: BOOLEAN _ FALSE; clearedMessageWindow: BOOLEAN _ FALSE; keyStart, keyLen, resultLen: TiogaNode.Offset; rdr: RopeReader.Ref; commands: LIST OF REF ANY; styleName: NameSymbolTable.Name; Try: PROC [name: NameSymbolTable.Name] RETURNS [stop: BOOLEAN] = { dict: Rope.ROPE = NameSymbolTable.RopeFromName[name]; [done,keyDeterminesDict,keyStart,keyLen,resultLen,commands] _ AbbrevExpand.Expand[node,offset,dict,TiogaInput.currentEvent]; IF ~done AND ~keyDeterminesDict THEN NodeStyleExtra.ForEachAttachedStyle[name,Try]; RETURN [done] }; CaretAfterSelection; pos _ InsertionPoint[]; node _ TiogaNodeOps.NarrowToTextNode[pos.node]; offset _ pos.where; styleName _ NodeStyle.StyleNameForNode[node]; Deselect[]; IF ~Try[styleName] THEN { OPEN MessageWindow; MakeSelection[tSel, primary]; IF abbrevFailedProc # NIL AND abbrevFailedProc[] THEN RETURN; Append[Rope.Substr[TextEdit.GetRope[node], keyStart, keyLen], ~clearedMessageWindow]; Append["? Unknown abbreviation."]; RETURN }; tSel.end.pos.node _ tSel.start.pos.node _ node; tSel.start.pos.where _ keyStart; tSel.pendingDelete _ FALSE; IF resultLen = 0 THEN { -- make a caret tSel.end.pos.where _ keyStart; tSel.insertion _ before; tSel.granularity _ point } ELSE { tSel.end.pos.where _ keyStart+resultLen-1; tSel.insertion _ after; tSel.granularity _ char }; MakeSelection[tSel, primary]; rdr _ RopeReader.GetRopeReader[]; RopeReader.SetPosition[rdr, TextEdit.GetRope[node], keyStart]; FOR i: INT IN [0..resultLen) DO -- check for placeholder IF RopeReader.Get[rdr] = 1C THEN { -- found one MakePointSelection[tSel,[node,keyStart+i]]; FindPlaceholders[TRUE]; EXIT }; ENDLOOP; RopeReader.FreeRopeReader[rdr]; IF commands # NIL THEN TiogaInput.Interpret[pSel.viewer, commands] }; CallWithLocks[DoExpand] }; LoadAbbreviations: PUBLIC PROC [dictName: Rope.ROPE] = { count: LONG INTEGER _ 0; fileName: Rope.ROPE; IF Rope.Size[dictName]=0 THEN RETURN; fileName _ Rope.Concat[dictName,".Abbreviations"]; count _ AbbrevExpand.Load[fileName, dictName ! CIFS.Error => {CONTINUE}]; IF count = 0 THEN { -- something went wrong OPEN MessageWindow; Append["The file named <", TRUE]; Append[fileName]; Append["> was not found or was not an abbreviation dictionary"] }}; END.