<<>> <> <> <> <> <> <> <> <> <<>> DIRECTORY Atom, EditSpan, EditSpanSupport, InputFocus, MessageWindow, NodeAddrs, RefTab, Rope, TEditDisplay USING [EstablishLine], TEditDocument USING [LineTable, maxClip, Selection, SelectionId, SelectionRec, SpinAndLock, TEditDocumentData, Unlock], TEditInput USING [CloseEvent, closeEvent, CloseEventNow, ComIndex, CommandProc, EditState, RecordChar, RecordRef], TEditInputBackdoor USING [EditObject, SelState, PDelState, MouseColor], TEditInputExtras USING [CommandClosure, CommandClosureProc], TEditInputOps USING [BackSpace, BackWord, Break, BufferedInsertChar, BufferedInsertText, CallWithLocks, Capitalise, ChangeCaretLooks, ChangeLooks, Copy, CopyFormat, CopyLooks, Delete, DeleteNextChar, DeleteNextWord, DoPendingDelete, ExpandAbbreviation, FindPlaceholders, GetFormat, GoToNextChar, GoToNextNode, GoToNextWord, GoToPreviousChar, GoToPreviousNode, GoToPreviousWord, InsertBrackets, InsertChar, InsertLineBreak, InsertRope, InsertTime, Join, LoadAbbreviations, MakeControlCharacter, MakeOctalCharacter, ModifyCaretLook, ModifyLook, Move, Nest, NextViewer, Paste, ReloadStyle, SaveForPaste, SelectMatchingBrackets, SetCommentProp, SetFormat, SetStyle, Transpose, TransposeFormat, TransposeLooks, UnMakeControlCharacter, UnMakeOctalCharacter, WaitForInsertToFinish, UnNest], TEditInputPrivate USING [InternalCommandCounts, InternalCommandCountsRep, InternalID, TraceProcs], TEditOps USING [CopyLoadHistory, CopyPositionHistory, RememberCurrentPosition], TEditPrivate USING [ReloadReadonlyTipTable, ReloadTipTable, ReloadTypeScriptTipTable], TEditProfile USING [CategoryOfUser, ReadProfile, userCategory], TEditScrolling USING [ScrollToPosition], TEditSelection USING [CallWithSelAndDocAndTddLocks, CancelPrimary, CancelSecondary, CaretAfterSelection, CaretBeforeSelection, Copy, Create, Extend, FakeSecondary, Find, fSel, GrowSelection, GrowSelectionToBlanks, InsertionPoint, LevelChange, LockSel, MakePointSelection, MakePrimary, MakeSecondary, MakeSelection, NotPendingDeleteSelection, oldSel, PendingDeleteSelection, pSel, SelectBranch, SelectChar, SelectEverything, SelectNode, SelectWord, ShowPosition, sSel, UnlockSel, Update], TEditSelectionOpsExtras USING [CurrentPositionMessage, GoToEndOfNode], TEditSplit USING [], TEditTouchup USING [LockAfterRefresh, UnlockAfterRefresh], TextEdit USING [Size, GetNewlineDelimiter], TextLooks USING [allLooks, noLooks], TextNode USING [FirstChild, ForwardClipped, Level, Location, NodeItself, Offset, Parent, Ref, RefTextNode, Root], TiogaOps USING [], TIPUser USING [TIPScreenCoords, TIPScreenCoordsRec], UserProfile USING [CallWhenProfileChanges, ProfileChangedProc], ViewerClasses USING [NotifyProc, Viewer], ViewerForkers, ViewerLocks, ViewerOps USING [AddProp, ComputeColumn, CreateViewer, DestroyViewer, FetchProp, MoveBelowViewer, OpenIcon, SetMenu], ViewersWorld, ViewersWorldInstance, WindowManager USING [UnWaitCursor, WaitCursor]; TEditInputImpl: CEDAR MONITOR IMPORTS Atom, EditSpan, EditSpanSupport, InputFocus, MessageWindow, NodeAddrs, RefTab, Rope, TEditDisplay, TEditDocument, TEditInput, TEditInputOps, TEditOps, TEditPrivate, TEditProfile, TEditScrolling, TEditSelection, TEditSelectionOpsExtras, TEditTouchup, TextEdit, TextNode, UserProfile, ViewerForkers, ViewerLocks, ViewerOps, ViewersWorld, ViewersWorldInstance, WindowManager EXPORTS TEditInput, TEditInputBackdoor, TEditInputExtras, TEditInputPrivate, TEditPrivate, TEditSplit, TiogaOps = BEGIN OPEN TEditInput; ROPE: TYPE ~ Rope.ROPE; <> <> <> <> < The name of a registered operation>> < Treated as user typein (but see $PARAM, below)>> < Mouse position info>> < A numeric parameter used by some of the ops in this interface. (ugh, global state)>> <<(New as of October 23, 1987) The ATOM $PARAM is treated specially, in that the immediately following item is coerced to a ROPE, and not treated as user typein, but instead is passed to the CommandClosureProc of the immediately following operation. Note that this param cannot be accessed from a CommandProc, because of interface restrictions.>> <> traceProcs: TEditInputPrivate.TraceProcs ¬ NIL; SetTraceProcs: PUBLIC PROC [procs: TEditInputPrivate.TraceProcs] ~ { traceProcs ¬ procs }; InternalCommandCounts: TYPE ~ TEditInputPrivate.InternalCommandCounts; InternalCommandCountsRep: TYPE ~ TEditInputPrivate.InternalCommandCountsRep; internalCommandCounts: InternalCommandCounts ~ NEW[InternalCommandCountsRep ¬ ALL[0]]; GetInternalCommandCounts: PUBLIC PROC RETURNS [InternalCommandCounts] ~ { RETURN[internalCommandCounts]; }; <> commandTable: RefTab.Ref ¬ RefTab.Create[mod: 101]; my, mx: INTEGER; -- global Coord param for ops below <> <> SelState: TYPE ~ TEditInputBackdoor.SelState; -- {reset, primary, secondary} selState: PUBLIC -- TEditInputBackdoor -- SelState ¬ reset; <> <> <> SelectionId: TYPE ~ TEditDocument.SelectionId; -- {primary, secondary, feedback} sel: PUBLIC -- TEditInputBackdoor -- SelectionId ¬ primary; <> <> <> <<>> PDelState: TYPE ~ TEditInputBackdoor.PDelState; -- {reset, pending, not} pdelState: PUBLIC -- TEditInputBackdoor -- PDelState ¬ reset; <> <> <> <<>> pDel: PUBLIC -- TEditInputBackdoor -- BOOL ¬ FALSE; <> <> <> <<>> LevelChange: TYPE ~ TEditSelection.LevelChange; -- {reduce, expand, same} changeLevel: LevelChange; <> <> <> <<>> EditState: TYPE ~ TEditInput.EditState; -- {reset, abort, tolimbo, toprimary, tosecondary, toboth} editState: PUBLIC EditState ¬ reset; <> <> <> EditObject: TYPE ~ TEditInputBackdoor.EditObject; -- {text, looks, format} editObject: PUBLIC -- TEditInputBackdoor -- EditObject ¬ text; <> <> <> MouseColor: TYPE ~ TEditInputBackdoor.MouseColor; -- {red, yellow, blue, dead} mouseColor: PUBLIC -- TEditInputBackdoor -- MouseColor ¬ red; <> <> <> prevPSel: TEditDocument.Selection ~ NEW[TEditDocument.SelectionRec]; <> <> <<>> interrupt: PUBLIC REF BOOL ¬ NEW[BOOL ¬ FALSE]; <> positionMessage: ROPE ¬ NIL; <> editMessage: PUBLIC -- TEditInputBackdoor -- ROPE ¬ NIL; EditMessage: PROC = { pPendingDelete: BOOL ~ TEditSelection.pSel.pendingDelete; sPendingDelete: BOOL ~ TEditSelection.sSel.pendingDelete; msg: ROPE ~ SELECT editState FROM tolimbo => "Select for delete", toprimary => SELECT editObject FROM text => SELECT TEditSelection.pSel.pendingDelete FROM FALSE => SELECT TEditSelection.sSel.pendingDelete FROM FALSE => "Select for copy to caret", TRUE => "Select for move to caret", ENDCASE => NIL, TRUE => SELECT TEditSelection.sSel.pendingDelete FROM FALSE => "Select replacement", TRUE => "Select for move onto", ENDCASE => NIL, ENDCASE => NIL, looks => "Select looks to copy", format => "Select format to copy", ENDCASE => NIL, tosecondary => SELECT editObject FROM text => SELECT TEditSelection.pSel.pendingDelete FROM FALSE => SELECT TEditSelection.sSel.pendingDelete FROM FALSE => "Select destination for copy", TRUE => "Select for replacement", ENDCASE => NIL, TRUE => SELECT TEditSelection.sSel.pendingDelete FROM FALSE => "Select destination for move", TRUE => "Select destination for move onto", ENDCASE => NIL, ENDCASE => NIL, looks => "Select destination for copy looks", format => "Select destination for copy format", ENDCASE => NIL, toboth => SELECT editObject FROM text => "Select for transpose", looks => "Select for transpose looks", format => "Select for transpose format", ENDCASE => NIL, ENDCASE => NIL; IF msg = NIL OR msg = editMessage THEN RETURN; MessageWindow.Append[msg,TRUE]; editMessage ¬ msg }; Interpret: PUBLIC PROC [viewer: ViewerClasses.Viewer, params: LIST OF REF ANY] = { InterpInput[viewer,params] }; InterpretAtom: PUBLIC PROC [viewer: ViewerClasses.Viewer, atom: ATOM] = { InterpAtom[viewer: viewer, atom: atom, param: NIL]; }; TEditNotifyProc: PUBLIC ViewerClasses.NotifyProc = { InterpInput[self, input]; }; InterpAtom: PROC [viewer: ViewerClasses.Viewer, atom: ATOM, param: REF] = { closureList: LIST OF CommandClosure ~ NARROW[RefTab.Fetch[commandTable,atom].val]; IF traceProcs#NIL THEN traceProcs.TraceAtom[viewer, atom, param, closureList]; IF closureList=NIL THEN MessageWindow.Append[Rope.Concat["Unknown atom given to Tioga: ", Atom.GetPName[atom]], TRUE] ELSE { recordAtom: BOOL ¬ FALSE; TEditInputOps.WaitForInsertToFinish[]; -- make sure previous characters have gone in FOR list: LIST OF CommandClosure ¬ closureList, list.rest UNTIL list=NIL DO record, quit: BOOL; [record, quit] ¬ list.first.proc[list.first.data, viewer, param]; IF record THEN recordAtom ¬ TRUE; IF quit THEN EXIT; ENDLOOP; IF recordAtom THEN RecordRef[atom] } }; ResetInputStuff: PUBLIC PROC = { changeLevel ¬ same }; SaveCoords: PUBLIC PROC [x, y: INTEGER] = { mx ¬ x; my ¬ y }; interpreterNesting: PUBLIC INTEGER ¬ 0; InterpInput: PUBLIC PROC [viewer: ViewerClasses.Viewer, params: LIST OF REF ANY, increaseNestingCount: BOOL ¬ TRUE] = { NormaliseSelection: PROC = INLINE --gfi saver-- { IF NOT TEditSelection.pSel.pendingDelete THEN RETURN; TEditSelection.LockSel[primary, "InterpInput"]; { ENABLE UNWIND => TEditSelection.UnlockSel[primary]; IF TEditSelection.pSel.pendingDelete THEN TEditInputOps.DoPendingDelete[]; IF NOT InsSel[] THEN TEditSelection.MakePointSelection[TEditSelection.pSel, TEditSelection.InsertionPoint[]]; }; TEditSelection.UnlockSel[primary]; }; InsSel: PROC RETURNS [BOOL] = INLINE --gfi saver-- { RETURN[TEditSelection.pSel.granularity=point AND TEditSelection.pSel.insertion=before AND TEditSelection.sSel.viewer=NIL] }; BumpNesting: ENTRY PROC = INLINE --gfi saver-- { IF (interpreterNesting ¬ interpreterNesting+1) <= 1 THEN { interpreterNesting ¬ 1; closeEvent ¬ FALSE } }; DecrementNesting: ENTRY PROC RETURNS [BOOL] = INLINE --gfi saver-- { RETURN [(interpreterNesting ¬ interpreterNesting-1) <= 0] }; AllText: PROC [LIST OF REF ANY] RETURNS [BOOL] = INLINE --gfi saver-- { FOR input: LIST OF REF ANY ¬ params, input.rest UNTIL input=NIL DO WITH input.first SELECT FROM z: REF CHAR => NULL; z: ROPE => NULL; z: REF TEXT => NULL; ENDCASE => RETURN [FALSE]; ENDLOOP; RETURN [TRUE] }; IF traceProcs#NIL THEN traceProcs.TraceInput[viewer, params, increaseNestingCount]; ResetInputStuff[]; IF interpreterNesting=0 AND NOT TEditSelection.pSel.pendingDelete AND AllText[params] THEN { <> FOR input: LIST OF REF ANY ¬ params, input.rest UNTIL input=NIL DO NormaliseSelection[]; WITH input.first SELECT FROM z: REF CHAR => { TEditInputOps.BufferedInsertChar[z­]; RecordChar[z­] }; z: ROPE => { TEditInputOps.BufferedInsertText[z]; RecordRef[z] }; z: REF TEXT => { TEditInputOps.BufferedInsertText[Rope.FromRefText[z]]; RecordRef[z] }; ENDCASE => ERROR; ENDLOOP; } ELSE { param: REF ¬ NIL; paramIsNext: BOOL ¬ FALSE; IF increaseNestingCount THEN BumpNesting[]; FOR input: LIST OF REF ANY ¬ params, input.rest UNTIL input=NIL DO thisIsParam: BOOL = paramIsNext; IF thisIsParam THEN param ¬ NIL; paramIsNext ¬ FALSE; WITH input.first SELECT FROM z: ATOM => { IF thisIsParam THEN { param ¬ z; RecordRef[z] } ELSE { IF z = $PARAM THEN { paramIsNext ¬ TRUE }; InterpAtom[viewer, z, param ! BadMouse, DontDoIt => EXIT]; }; }; z: TIPUser.TIPScreenCoords => { IF thisIsParam THEN RecordRef[param ¬ NEW[TIPUser.TIPScreenCoordsRec ¬ z­] ] ELSE SaveCoords[z.mouseX, viewer.ch-z.mouseY]; }; z: REF CHAR => { IF thisIsParam THEN RecordRef[param ¬ NEW[CHAR ¬ z­]] ELSE { TEditInputOps.InsertChar[z­]; RecordChar[z­] }; }; z: REF INT => { param ¬ NEW[INT ¬ z­]; -- is the copy needed? RecordRef[param] }; z: ROPE => { IF thisIsParam THEN param ¬ z ELSE TEditInputOps.InsertRope[z]; RecordRef[z] }; z: REF TEXT => { rope: ROPE ~ Rope.FromRefText[z]; IF thisIsParam THEN param ¬ rope ELSE TEditInputOps.InsertRope[rope]; RecordRef[rope]; }; ENDCASE => MessageWindow.Append["Unknown input given to Tioga.", TRUE]; IF thisIsParam AND param=NIL THEN MessageWindow.Append["Illegal PARAM input given to Tioga.", TRUE]; ENDLOOP; IF increaseNestingCount AND DecrementNesting[] AND closeEvent THEN CloseEventNow[]; }; }; NumberToLook: PROC [n: INT] RETURNS [l: CHAR] = { < ['a..'z];>> RETURN['a+n]; }; <> Normalize: PUBLIC CommandProc = { DoIt: PROC [tdd: TEditDocument.TEditDocumentData, tSel: TEditDocument.Selection] = { NormalizeViewer[viewer, IF tSel.viewer=NIL THEN [NIL,0] ELSE TEditSelection.InsertionPoint[tSel], tdd, tSel] }; TEditSelection.CallWithSelAndDocAndTddLocks[viewer, primary, DoIt] }; savedSelA: TEditDocument.Selection ¬ TEditSelection.Create[]; savedSelB: TEditDocument.Selection ¬ TEditSelection.Create[]; RestoreSelectionA: PUBLIC CommandProc = { IF CheckSelection[savedSelA] THEN TEditSelection.MakeSelection[selection: primary, new: savedSelA] }; SaveSelectionA: PUBLIC CommandProc = { IF TEditSelection.pSel # NIL THEN TEditSelection.Copy[source: TEditSelection.pSel, dest: savedSelA] }; RestoreSelectionB: PUBLIC CommandProc = { IF CheckSelection[savedSelB] THEN TEditSelection.MakeSelection[selection: primary, new: savedSelB] }; SaveSelectionB: PUBLIC CommandProc = { IF TEditSelection.pSel # NIL THEN TEditSelection.Copy[source: TEditSelection.pSel, dest: savedSelB] }; AllLevels: PUBLIC CommandProc = { WITH viewer.data SELECT FROM tdd: TEditDocument.TEditDocumentData => { IF tdd.clipLevel # TEditDocument.maxClip THEN { [] ¬ TEditDocument.SpinAndLock[tdd, "AllLevels", TRUE]; tdd.clipLevel ¬ TEditDocument.maxClip; ForkPaint[viewer]; TEditDocument.Unlock[tdd]; }; }; ENDCASE; RETURN [FALSE]; }; FirstLevelOnly: PUBLIC CommandProc = { WITH viewer.data SELECT FROM tdd: TEditDocument.TEditDocumentData => { IF tdd.clipLevel # 1 THEN { [] ¬ TEditDocument.SpinAndLock[tdd, "FirstLevelOnly", TRUE]; tdd.clipLevel ¬ 1; CheckFirstLevel[tdd]; ForkPaint[viewer]; TEditDocument.Unlock[tdd]; }; }; ENDCASE; RETURN [FALSE]; }; MoreLevels: PUBLIC CommandProc = { WITH viewer.data SELECT FROM tdd: TEditDocument.TEditDocumentData => { IF tdd.clipLevel < TEditDocument.maxClip THEN { ENABLE UNWIND => TEditTouchup.UnlockAfterRefresh[tdd]; [] ¬ TEditDocument.SpinAndLock[tdd, "MoreLevels", TRUE]; tdd.clipLevel ¬ MaxLevelShown[tdd]+1; ForkPaint[viewer]; TEditDocument.Unlock[tdd]; }; }; ENDCASE; }; FewerLevels: PUBLIC CommandProc = { WITH viewer.data SELECT FROM tdd: TEditDocument.TEditDocumentData => IF tdd.clipLevel # 1 THEN { IF TEditTouchup.LockAfterRefresh[tdd, "FewerLevels"] THEN { ENABLE UNWIND => TEditTouchup.UnlockAfterRefresh[tdd]; level: INTEGER ¬ tdd.clipLevel; IF level = TEditDocument.maxClip THEN level ¬ MaxLevelShown[tdd]; IF level # 1 THEN { tdd.clipLevel ¬ level-1; CheckFirstLevel[tdd]; ForkPaint[viewer]; }; TEditTouchup.UnlockAfterRefresh[tdd]; }; }; ENDCASE; RETURN [FALSE]; }; DoEdit: CommandProc = { SELECT TRUE FROM (TEditSelection.pSel.viewer = NIL) => { IF TEditSelection.sSel.viewer # NIL THEN TEditSelection.MakeSelection[NIL, secondary]; -- get rid of secondary recordAtom ¬ FALSE }; (editState = tolimbo) => { recordAtom ¬ FALSE; RecordRef[$Delete]; TEditInputOps.Delete[TRUE]; }; (TEditSelection.sSel.viewer = NIL) => {recordAtom ¬ FALSE}; ENDCASE => { RecordEditObject: PROC = INLINE --gfi saver-- { RecordRef[SELECT editObject FROM text => $EditText, looks => $EditLooks, format => $EditFormat, ENDCASE => ERROR]; }; recordAtom ¬ TRUE; SELECT editState FROM reset, abort => recordAtom ¬ FALSE; toprimary => { RecordRef[$GetSecondary]; RecordRef[$ToPrimary]; RecordEditObject[]; SELECT editObject FROM text => { IF TEditSelection.pSel.pendingDelete THEN RecordRef[$MakePDel]; TEditInputOps.Copy[primary] }; looks => TEditInputOps.CopyLooks[primary]; format => TEditInputOps.CopyFormat[primary]; ENDCASE => ERROR }; tosecondary => { RecordRef[$GetSecondary]; RecordRef[$ToSecondary]; RecordEditObject[]; SELECT editObject FROM text => { IF TEditSelection.pSel.pendingDelete THEN RecordRef[$MakePDel]; TEditInputOps.Copy[secondary] }; looks => TEditInputOps.CopyLooks[secondary]; format => TEditInputOps.CopyFormat[secondary]; ENDCASE => ERROR }; toboth => { RecordRef[$GetSecondary]; RecordRef[$ToBoth]; RecordEditObject[]; SELECT editObject FROM text => TEditInputOps.Transpose[]; looks => TEditInputOps.TransposeLooks[]; format => TEditInputOps.TransposeFormat[]; ENDCASE => ERROR }; ENDCASE => ERROR }; editState ¬ reset; editObject ¬ text; pdelState ¬ reset; pDel ¬ FALSE; selState ¬ reset; sel ¬ primary; mouseColor ¬ red; -- put these back to normal IF editMessage # NIL THEN MessageWindow.Clear[]; editMessage ¬ NIL }; MakePointSelection: PUBLIC CommandProc = { TEditSelection.LockSel[primary, "MakePointSelection"]; IF TEditSelection.pSel.viewer#NIL THEN TEditSelection.MakePointSelection[TEditSelection.pSel, IF TEditSelection.pSel.insertion=before THEN TEditSelection.pSel.start.pos ELSE [TEditSelection.pSel.end.pos.node, TEditSelection.pSel.end.pos.where+1]]; TEditSelection.UnlockSel[primary]; }; <> Split: PUBLIC PROC [old: ViewerClasses.Viewer] = { -- Export to TEditSplit tddNew, tddOld: TEditDocument.TEditDocumentData; new: ViewerClasses.Viewer; paintCaption: BOOL ¬ FALSE; selectionHistory: TEditDocument.Selection; lines: TEditDocument.LineTable; loc: TextNode.Location; tddOld ¬ NARROW[old.data]; IF tddOld = NIL THEN RETURN; new ¬ ViewerOps.CreateViewer[flavor: old.class.flavor, info: [name: old.name, column: old.column, iconic: TRUE], paint: FALSE]; ViewerOps.OpenIcon[icon: new, paint: FALSE]; ViewerOps.MoveBelowViewer[altered: new, static: old, paint: FALSE]; tddNew ¬ NARROW[new.data]; IF tddNew = NIL THEN RETURN; -- How this could happen is beyond me, but paranoia is cheap. [McGregor] selectionHistory ¬ NARROW[ViewerOps.FetchProp[old, $SelectionHistory]]; new.link ¬ old; IF old.link=NIL THEN { old.link ¬ new; paintCaption ¬ TRUE } ELSE FOR v: ViewerClasses.Viewer ¬ old.link, v.link UNTIL v.link=old DO REPEAT FINISHED => v.link ¬ new; ENDLOOP; new.newVersion ¬ old.newVersion; new.newFile ¬ old.newFile; new.file ¬ old.file; ViewerOps.ComputeColumn[column: new.column, paint: FALSE]; -- to find new height { inner: PROC = { [] ¬ TEditDocument.SpinAndLock[tddOld, "Split"]; -- must ComputeColumn before lock tdd tddNew.text ¬ tddOld.text; tddNew.tsInfo ¬ tddOld.tsInfo; tddNew.clipLevel ¬ tddOld.clipLevel; tddNew.commentFilter ¬ tddOld.commentFilter; ViewerOps.SetMenu[new, old.menu, FALSE]; IF selectionHistory # NIL THEN { -- copy it newSelectionHistory: TEditDocument.Selection ¬ NEW[TEditDocument.SelectionRec]; newSelectionHistory­ ¬ selectionHistory­; ViewerOps.AddProp[new, $SelectionHistory, newSelectionHistory]; }; TEditOps.CopyPositionHistory[from: old, to: new]; TEditOps.CopyLoadHistory[from: old, to: new]; lines ¬ tddOld.lineTable; loc ¬ lines[lines.lastLine].pos; -- in case loop doesn't find anything FOR n: INTEGER IN [0..lines.lastLine] DO -- find line that goes past new bottom IF lines[n].yOffset+lines[n].descent >= old.ch THEN { loc ¬ lines[n].pos; EXIT }; ENDLOOP; TEditDocument.Unlock[tddOld]; }; ViewerLocks.CallUnderWriteLocks[inner, old, new]; <> }; TEditDisplay.EstablishLine[tddNew, loc]; ViewerOps.ComputeColumn[column: new.column, paint: TRUE]; -- now do the painting FOR v: ViewerClasses.Viewer ¬ new.link, v.link WHILE v # NIL DO IF v = new THEN EXIT; IF v.iconic THEN { -- get rid of it -- ViewerOps.DestroyViewer[v]; EXIT }; IF paintCaption THEN <> ViewerForkers.ForkPaint[viewer: v, hint: caption, tryShortCuts: TRUE]; ENDLOOP; }; UpdateSavedSelections: PROC [ node: TextNode.RefTextNode, new: PROC [old: TextNode.Offset] RETURNS [TextNode.Offset]] = { Check: PROC [loc: TextNode.Location] RETURNS [TextNode.Location] = INLINE --gfi saver-- { IF loc.node # node THEN RETURN [loc]; RETURN [[loc.node, new[loc.where]]] }; <> TEditSelection.oldSel.start.pos ¬ Check[TEditSelection.oldSel.start.pos]; TEditSelection.oldSel.end.pos ¬ Check[TEditSelection.oldSel.end.pos]; <> savedSelA.start.pos ¬ Check[savedSelA.start.pos]; savedSelA.end.pos ¬ Check[savedSelA.end.pos]; <> savedSelB.start.pos ¬ Check[savedSelB.start.pos]; savedSelB.end.pos ¬ Check[savedSelB.end.pos]; <> TEditSelection.fSel.start.pos ¬ Check[TEditSelection.fSel.start.pos]; TEditSelection.fSel.end.pos ¬ Check[TEditSelection.fSel.end.pos]; }; CheckSelection: PUBLIC PROC [sel: TEditDocument.Selection] RETURNS [BOOL] = { root, first, last: TextNode.Ref; t1, t2: TextNode.RefTextNode; tdd: TEditDocument.TEditDocumentData; IF sel=NIL THEN RETURN [FALSE]; IF sel.viewer=NIL OR sel.viewer.destroyed THEN GOTO Failed; IF (first ¬ sel.start.pos.node)=NIL OR (last ¬ sel.end.pos.node)=NIL THEN GOTO Failed; IF (tdd ¬ NARROW[sel.viewer.data])=NIL THEN GOTO Failed; IF (root ¬ tdd.text)=NIL THEN GOTO Failed; IF TextNode.Root[first] # root THEN GOTO Failed; -- make sure still in the tree IF first # last THEN { <> IF EditSpan.CompareNodeOrder[first,last] # before THEN GOTO Failed; }; IF sel.start.pos.where # TextNode.NodeItself THEN { <> IF (t1 ¬ first)=NIL OR sel.start.pos.where NOT IN [0..TextEdit.Size[t1]] THEN GOTO Failed; }; IF sel.end.pos.where # TextNode.NodeItself THEN { <> IF (t2 ¬ last)=NIL OR sel.end.pos.where NOT IN [0..TextEdit.Size[t2]] THEN GOTO Failed; }; IF t1 # NIL AND t1 = t2 THEN { <> IF sel.start.pos.where > sel.end.pos.where THEN GOTO Failed; }; RETURN [TRUE]; EXITS Failed => { sel.viewer ¬ NIL; RETURN [FALSE] }; }; NormalizeViewer: PROC [viewer: ViewerClasses.Viewer, loc: TextNode.Location, tdd: TEditDocument.TEditDocumentData, tSel: TEditDocument.Selection] = { IF loc.node = NIL OR tdd.text # TextNode.Root[loc.node] THEN { <> loc ¬ [TextNode.FirstChild[tdd.text],0]; }; TEditOps.RememberCurrentPosition[viewer]; TEditScrolling.ScrollToPosition[viewer, loc] }; BadMouse: PUBLIC SIGNAL = CODE; AbortSecondary: PROC = { MessageWindow.Append["Make a primary selection first.",TRUE]; MessageWindow.Blink[]; editState ¬ abort; mouseColor ¬ dead }; Extend: PROC [viewer: ViewerClasses.Viewer, saveEnds: BOOL] = { tdd: TEditDocument.TEditDocumentData ~ NARROW[viewer.data]; IF tdd = NIL THEN RETURN; interpreterNesting ¬ 0; IF editState=abort THEN RETURN; IF mouseColor # blue THEN { IF mouseColor = dead THEN SIGNAL BadMouse; mouseColor ¬ blue; TEditSelection.Copy[source: TEditSelection.pSel, dest: prevPSel]; saveEnds ¬ TRUE; }; TEditSelection.Extend[viewer,tdd,mx,my,sel,pDel,changeLevel,saveEnds]; IF sel=secondary THEN EditMessage[] ELSE IF sel=primary THEN CloseEvent[] }; DontDoIt: PUBLIC SIGNAL = CODE; -- raised if user category is too low CheckUser: PROC [category: TEditProfile.CategoryOfUser] = INLINE --gfi saver-- { IF TEditProfile.userCategory < category THEN SIGNAL DontDoIt }; ForkPaint: PROC [viewer: ViewerClasses.Viewer] = TRUSTED { ViewerForkers.ForkPaint[viewer: viewer, hint: client, tryShortCuts: TRUE]; }; CheckFirstLevel: PROC [tdd: TEditDocument.TEditDocumentData] = { node: TextNode.Ref; delta: INTEGER; pos: TextNode.Location; [] ¬ TEditDocument.SpinAndLock[tdd, "CheckFirstLevel", TRUE]; -- ok to interrupt repaint pos ¬ tdd.lineTable.lines[0].pos; -- the start of the first line delta ¬ TextNode.Level[pos.node]-tdd.clipLevel; -- how much too deep it is, if any IF delta > 0 THEN { FOR i:INTEGER IN [0..delta) DO -- only do this if pos is too deep pos ¬ [TextNode.Parent[pos.node],0]; ENDLOOP; IF (node ¬ TextNode.ForwardClipped[pos.node,0].nx) # NIL THEN pos ¬ [node,0]; TEditDisplay.EstablishLine[tdd, pos] }; TEditDocument.Unlock[tdd]; }; MaxLevelShown: PUBLIC PROC [tdd: TEditDocument.TEditDocumentData] RETURNS [level: INTEGER] = { node, n: TextNode.Ref; max: INTEGER ¬ 0; IF tdd = NIL THEN RETURN [0]; FOR l: INTEGER IN [0..tdd.lineTable.lastLine] DO IF (n ¬ tdd.lineTable.lines[l].pos.node) # node THEN { node ¬ n; max ¬ MAX[TextNode.Level[node], max] }; ENDLOOP; level ¬ max; }; ReadTipTables: PUBLIC PROC = { WindowManager.WaitCursor[]; TEditPrivate.ReloadTipTable[]; TEditPrivate.ReloadReadonlyTipTable[]; TEditPrivate.ReloadTypeScriptTipTable[]; InputFocus.SetInputFocus[]; -- kill selection; force ChangeTIPContext WindowManager.UnWaitCursor[]; }; ComArray: TYPE = ARRAY ComIndex OF LIST OF REF ANY; coms: REF ComArray = NEW [ComArray]; SetCommand: PUBLIC PROC [num: ComIndex, params: LIST OF REF ANY] = { coms[num] ¬ params; }; GetCommand: PUBLIC PROC [num: ComIndex] RETURNS [params: LIST OF REF ANY] = { RETURN [coms[num]]; }; DoCommand: PROC [viewer: ViewerClasses.Viewer, num: ComIndex] = { Interpret[viewer,coms[num]]; }; <> InternalID: TYPE ~ TEditInputPrivate.InternalID; RegisterInternal: PROC [name: ATOM, id: InternalID] ~ { RegisterClosure[[name: name, proc: DispatchInternalCommand, data: NEW[InternalID ¬ id]]]; }; CopyToWorld: PROC [delete: BOOL ¬ FALSE] ~ { vWorld: ViewersWorld.Ref ~ ViewersWorldInstance.GetWorld[]; rope: Rope.ROPE ¬ NIL; DoSelChars: PROC [root: TextNode.RefTextNode, tSel: TEditDocument.Selection] = { SelConcat: PROC [node: TextNode.RefTextNode, start, len: TextNode.Offset] RETURNS [stop: BOOL] = { rope ¬ IF rope = NIL THEN Rope.Substr[node.rope, start, len] ELSE Rope.Cat[rope, "\n", Rope.Substr[node.rope, start, len]]; RETURN [FALSE]; }; IF tSel.viewer # NIL AND tSel.granularity # point THEN EditSpanSupport.Apply[[tSel.start.pos, tSel.end.pos], SelConcat]; IF rope=NIL THEN rope ¬ ""; }; TEditInputOps.CallWithLocks[DoSelChars, read]; ViewersWorld.SetCutBuffer[vWorld, $Ascii, rope]; IF delete THEN TEditInputOps.Delete[saveForPaste: FALSE]; }; PasteFromWorld: PROC [] ~ { vWorld: ViewersWorld.Ref ~ ViewersWorldInstance.GetWorld[]; rope: Rope.ROPE ~ ViewersWorld.GetCutBuffer[vWorld, $Ascii]; TEditInputOps.InsertRope[rope]; }; DispatchInternalCommand: PUBLIC CommandClosureProc ~ { n: INT ~ WITH param SELECT FROM n: REF INT => n­ ENDCASE => 1; WITH data SELECT FROM refID: REF InternalID => { id: InternalID ~ refID­; internalCommandCounts[id] ¬ internalCommandCounts[id]+1; SELECT id FROM CopyToWorld => CopyToWorld[delete: FALSE]; CutToWorld => CopyToWorld[delete: TRUE]; PasteFromWorld => PasteFromWorld[]; CutToWorldFormatted => { }; CopyToWorldFormatted => { }; PasteFromWorldFormatted => { }; ApplyCaretLook => { TEditInputOps.ModifyCaretLook[NumberToLook[n], add] }; ApplyLook => { TEditInputOps.ModifyLook[NumberToLook[n], add] }; ClearCaretLooks => { TEditInputOps.ChangeCaretLooks[add: TextLooks.noLooks, remove: TextLooks.allLooks] }; ClearLooks => { TEditInputOps.ChangeLooks[add: TextLooks.noLooks, remove: TextLooks.allLooks] }; BackSpace => { TEditInputOps.BackSpace[n] }; BackWord => { TEditInputOps.BackWord[n] }; DeleteNextChar => { TEditInputOps.DeleteNextChar[n] }; DeleteNextWord => { TEditInputOps.DeleteNextWord[n] }; GoToPreviousWord => { TEditInputOps.GoToPreviousWord[n] }; GoToNextWord => { TEditInputOps.GoToNextWord[n] }; GoToPreviousChar => { TEditInputOps.GoToPreviousChar[n] }; GoToNextChar => { TEditInputOps.GoToNextChar[n] }; GoToPreviousNode => { TEditInputOps.GoToPreviousNode[n] }; GoToNextNode => { TEditInputOps.GoToNextNode[n] }; GoToEndOfNode => { TEditSelectionOpsExtras.GoToEndOfNode[n] }; GoToBeginningOfNode => { TEditSelectionOpsExtras.GoToEndOfNode[-n] }; Copy => { IF TEditSelection.sSel.viewer#NIL THEN { TEditInputOps.Copy[sel]; RecordRef[$GetSecondary] }; }; Delete => { TEditInputOps.Delete[saveForPaste: TRUE] }; ExpandAbbrev => { TEditInputOps.ExpandAbbreviation[] }; Move => { IF TEditSelection.sSel.viewer#NIL THEN { TEditInputOps.Move[sel]; RecordRef[$GetSecondary]; }; }; RemoveCaretLook => { TEditInputOps.ModifyCaretLook[NumberToLook[n], remove]; }; RemoveLook => { TEditInputOps.ModifyLook[NumberToLook[n], remove]; }; SetStyle => { TEditInputOps.SetStyle[] }; Time => { TEditInputOps.InsertTime[] }; RedSplit, YellowSplit, BlueSplit => { Split[viewer]; RETURN[FALSE] }; Transpose => { IF TEditSelection.sSel.viewer#NIL THEN { TEditInputOps.Transpose[sel]; RecordRef[$GetSecondary] }; }; ToBoth => { IF editState=reset OR editState=tolimbo THEN { editState ¬ toboth; EditMessage[] }; RETURN [FALSE] }; ToLimbo => { IF editState=reset THEN editState ¬ tolimbo; RETURN [FALSE] }; ToPrimary => { IF editState=reset OR editState=tolimbo THEN editState ¬ toprimary; RETURN [FALSE] }; ToSecondary => { IF editState=reset OR editState=tolimbo THEN { editState ¬ tosecondary; EditMessage[] }; RETURN [FALSE] }; EditText => { editObject ¬ text; RETURN [FALSE] }; EditLooks => { editObject ¬ looks; EditMessage[]; RETURN [FALSE] }; EditFormat => { editObject ¬ format; EditMessage[]; RETURN [FALSE] }; EditReset => { editState ¬ reset; editObject ¬ text; selState ¬ reset; pdelState ¬ reset; RETURN [FALSE] }; EditAbort => { interrupt­ ¬ TRUE; IF viewer#NIL AND TEditSelection.pSel.viewer=viewer AND TEditSelection.pSel.granularity=point AND TEditSelection.sSel.viewer=NIL THEN ViewerOps.AddProp[viewer, $Abort, NEW[BOOL ¬ FALSE]]; MessageWindow.Append["Cancelled",TRUE]; TEditSelection.MakeSelection[NIL,secondary]; TEditSelection.MakeSelection[IF CheckSelection[prevPSel] THEN prevPSel ELSE NIL, primary]; editState ¬ abort; editObject ¬ text; mouseColor ¬ dead; -- stop tracking the mouse RETURN [FALSE] }; GetSecondary => { IF TEditSelection.sSel.viewer=NIL AND CheckSelection[TEditSelection.oldSel] THEN TEditSelection.FakeSecondary[TEditSelection.oldSel]; RETURN [FALSE] }; MakePDel => { TEditSelection.pSel.pendingDelete ¬ TRUE; RETURN [FALSE] }; NormalizeToStart => { DoIt: PROC [tdd: TEditDocument.TEditDocumentData, tSel: TEditDocument.Selection] = { NormalizeViewer[viewer, IF tSel.viewer=NIL THEN [NIL,0] ELSE tSel.start.pos, tdd, tSel] }; TEditSelection.CallWithSelAndDocAndTddLocks[viewer, primary, DoIt] }; NormalizeToEnd => { DoIt: PROC [tdd: TEditDocument.TEditDocumentData, tSel: TEditDocument.Selection] = { NormalizeViewer[viewer, IF tSel.viewer=NIL THEN [NIL,0] ELSE tSel.end.pos, tdd, tSel] }; TEditSelection.CallWithSelAndDocAndTddLocks[viewer, primary, DoIt] }; FindNext => { TEditSelection.Find[viewer: viewer, findWhere: forwards]; CloseEvent[]; RETURN [FALSE] }; FindAny => { TEditSelection.Find[viewer: viewer, findWhere: anywhere]; CloseEvent[]; RETURN [FALSE] }; FindPrev => { TEditSelection.Find[viewer: viewer, findWhere: backwards]; CloseEvent[]; RETURN [FALSE] }; FindNextWord => { TEditSelection.Find[viewer: viewer, findWhere: forwards, def: FALSE, word: TRUE]; CloseEvent[]; RETURN [FALSE] }; FindAnyWord => { TEditSelection.Find[viewer: viewer, findWhere: anywhere, def: FALSE, word: TRUE]; CloseEvent[]; RETURN [FALSE] }; FindPrevWord => { TEditSelection.Find[viewer: viewer, findWhere: backwards, def: FALSE, word: TRUE]; CloseEvent[]; RETURN [FALSE] }; FindNextDef => { TEditSelection.Find[viewer: viewer, findWhere: forwards, def: TRUE, word: TRUE]; CloseEvent[]; RETURN [FALSE] }; FindAnyDef => { TEditSelection.Find[viewer: viewer, findWhere: anywhere, def: TRUE, word: TRUE]; CloseEvent[]; RETURN [FALSE] }; FindPrevDef => { TEditSelection.Find[viewer: viewer, findWhere: backwards, def: TRUE, word: TRUE]; CloseEvent[]; RETURN [FALSE] }; FindNextCaseless => { TEditSelection.Find[viewer: viewer, findWhere: forwards, case: FALSE]; CloseEvent[]; RETURN [FALSE] }; FindAnyCaseless => { TEditSelection.Find[viewer: viewer, findWhere: anywhere, case: FALSE]; CloseEvent[]; RETURN [FALSE] }; FindPrevCaseless => { TEditSelection.Find[viewer: viewer, findWhere: backwards, case: FALSE]; CloseEvent[]; RETURN [FALSE] }; FindNextWordCaseless => { TEditSelection.Find[viewer: viewer, findWhere: forwards, def: FALSE, word: TRUE, case: FALSE]; CloseEvent[]; RETURN [FALSE] }; FindAnyWordCaseless => { TEditSelection.Find[viewer: viewer, findWhere: anywhere, def: FALSE, word: TRUE, case: FALSE]; CloseEvent[]; RETURN [FALSE] }; FindPrevWordCaseless => { TEditSelection.Find[viewer: viewer, findWhere: backwards, def: FALSE, word: TRUE, case: FALSE]; CloseEvent[]; RETURN [FALSE] }; FindNextDefCaseless => { TEditSelection.Find[viewer: viewer, findWhere: forwards, def: TRUE, word: TRUE, case: FALSE]; CloseEvent[]; RETURN [FALSE] }; FindAnyDefCaseless => { TEditSelection.Find[viewer: viewer, findWhere: anywhere, def: TRUE, word: TRUE, case: FALSE]; CloseEvent[]; RETURN [FALSE] }; FindPrevDefCaseless => { TEditSelection.Find[viewer: viewer, findWhere: backwards, def: TRUE, word: TRUE, case: FALSE]; CloseEvent[]; RETURN [FALSE] }; Position => { CloseEvent[]; TEditSelection.ShowPosition[viewer: viewer, skipCommentNodes: TRUE]; RETURN[FALSE] }; PositionIncludingComments => { CloseEvent[]; TEditSelection.ShowPosition[viewer: viewer, skipCommentNodes: FALSE]; RETURN[FALSE] }; MsgPosition => { positionMessage ¬ TEditSelectionOpsExtras.CurrentPositionMessage[viewer, TRUE]; MessageWindow.Append[Rope.Concat["Current position is ", positionMessage], TRUE]; }; MsgPositionIncludingComments => { positionMessage ¬ TEditSelectionOpsExtras.CurrentPositionMessage[viewer, FALSE]; MessageWindow.Append[Rope.Concat["Current position is ", positionMessage], TRUE]; }; StuffPosition => { TEditInputOps.InsertRope[positionMessage]; }; RedMouse => { IF mouseColor = dead THEN SIGNAL BadMouse; mouseColor ¬ red; TEditSelection.Copy[source: TEditSelection.pSel, dest: prevPSel]; RETURN [FALSE] }; YellowMouse => { IF mouseColor = dead THEN SIGNAL BadMouse; mouseColor ¬ yellow; TEditSelection.Copy[source: TEditSelection.pSel, dest: prevPSel]; RETURN [FALSE] }; BlueMouse => { IF mouseColor = dead THEN SIGNAL BadMouse; mouseColor ¬ blue; TEditSelection.Copy[source: TEditSelection.pSel, dest: prevPSel]; RETURN [FALSE] }; RedDown => { IF mouseColor # red THEN SIGNAL BadMouse; RETURN [FALSE] }; YellowDown => { IF mouseColor # yellow THEN SIGNAL BadMouse; RETURN [FALSE] }; BlueDown => { IF mouseColor # blue THEN SIGNAL BadMouse; RETURN [FALSE] }; SelBranch => { tdd: TEditDocument.TEditDocumentData ~ NARROW[viewer.data]; IF tdd = NIL THEN RETURN; interpreterNesting ¬ 0; IF editState=abort THEN RETURN; IF sel=secondary AND TEditSelection.pSel.viewer = NIL THEN { AbortSecondary[]; RETURN }; TEditSelection.SelectBranch[viewer, tdd, mx, my, sel, pDel]; IF editState=tolimbo OR sel=secondary THEN EditMessage[]; IF sel=primary THEN CloseEvent[]; RETURN [FALSE] }; SelChar => { tdd: TEditDocument.TEditDocumentData ~ NARROW[viewer.data]; IF tdd = NIL THEN RETURN; interpreterNesting ¬ 0; IF editState=abort THEN RETURN; IF sel=secondary AND TEditSelection.pSel.viewer = NIL THEN { AbortSecondary[]; RETURN }; TEditSelection.SelectChar[viewer, tdd, mx, my, sel, pDel]; IF editState=tolimbo OR sel=secondary THEN EditMessage[]; IF sel=primary THEN CloseEvent[]; RETURN [FALSE] }; SelExpand => { changeLevel ¬ expand; IF sel=primary THEN CloseEvent[]; RETURN [FALSE] }; SelExtend => { Extend[viewer, FALSE]; RETURN [FALSE] }; SelStartExtend => { Extend[viewer, TRUE]; RETURN [FALSE] }; SelNode => { tdd: TEditDocument.TEditDocumentData ~ NARROW[viewer.data]; IF tdd = NIL THEN RETURN; interpreterNesting ¬ 0; IF editState=abort THEN RETURN; IF sel=secondary AND TEditSelection.pSel.viewer = NIL THEN { AbortSecondary[]; RETURN }; TEditSelection.SelectNode[viewer, tdd, mx, my, sel, pDel]; IF editState=tolimbo OR sel=secondary THEN EditMessage[]; IF sel=primary THEN CloseEvent[]; RETURN [FALSE] }; SelNotPendDel => { IF pdelState=reset THEN { pdelState ¬ not; pDel ¬ FALSE; IF sel=primary THEN CloseEvent[] }; RETURN [FALSE] }; SelPendDel => { IF pdelState=reset THEN { pdelState ¬ pending; pDel ¬ TRUE; IF sel=primary THEN CloseEvent[] }; RETURN [FALSE] }; ForceSelPendDel => { -- force pending delete pdelState ¬ pending; pDel ¬ TRUE; IF sel=primary THEN CloseEvent[]; RETURN [FALSE] }; ForceSelNotPendDel => { -- force not pending delete pdelState ¬ not; pDel ¬ FALSE; IF sel=primary THEN CloseEvent[]; RETURN [FALSE] }; SelSamePendDel => { IF sel=primary THEN CloseEvent[]; RETURN [FALSE] }; SelPrimary => { IF selState=reset THEN { selState ¬ primary; sel ¬ primary; CloseEvent[] }; RETURN [FALSE] }; SelReduce => { changeLevel ¬ reduce; IF sel=primary THEN CloseEvent[]; RETURN [FALSE] }; SelSame => { -- this is no longer needed. delete it after release new TIP tables }; SelSameEnd => { -- get rid of this when change Tioga.Tip RETURN [FALSE] }; SelSecondary => { IF selState=reset THEN { selState ¬ secondary; sel ¬ secondary }; RETURN [FALSE] }; SelUpdate => { tdd: TEditDocument.TEditDocumentData ~ NARROW[viewer.data]; IF tdd = NIL THEN RETURN; IF editState=abort THEN RETURN; IF sel=secondary AND TEditSelection.pSel.viewer = NIL THEN { AbortSecondary[]; RETURN }; TEditSelection.Update[viewer, tdd, mx, my, sel, pDel]; IF sel=secondary THEN EditMessage[]; IF sel=primary THEN CloseEvent[]; RETURN [FALSE] }; SelWord => { tdd: TEditDocument.TEditDocumentData ~ NARROW[viewer.data]; IF tdd = NIL THEN RETURN; interpreterNesting ¬ 0; IF editState=abort THEN RETURN; IF sel=secondary AND TEditSelection.pSel.viewer = NIL THEN { AbortSecondary[]; RETURN }; TEditSelection.SelectWord[viewer, tdd, mx, my, sel, pDel]; IF editState=tolimbo OR sel=secondary THEN EditMessage[]; IF sel=primary THEN CloseEvent[]; RETURN [FALSE] }; IntermediateUser => { CheckUser[intermediate]; RETURN [FALSE] }; AdvancedUser => { CheckUser[advanced]; RETURN [FALSE] }; ExpertUser => { CheckUser[expert]; RETURN [FALSE] }; Break => { TEditInputOps.Break[] }; Join => { TEditInputOps.Join[] }; Nest => { TEditInputOps.Nest[] }; Paste => { TEditInputOps.Paste[] }; SaveForPaste => { TEditInputOps.SaveForPaste[] }; SetFormat => { TEditInputOps.SetFormat[] }; GetFormat => { TEditInputOps.GetFormat[] }; UnNest => { TEditInputOps.UnNest[] }; AllCaps => { TEditInputOps.Capitalise[allCaps] }; AllLower => { TEditInputOps.Capitalise[allLower] }; FirstCap => { TEditInputOps.Capitalise[firstCap] }; InitialCaps => { TEditInputOps.Capitalise[initCaps] }; CaretAfter => { TEditSelection.CaretAfterSelection[] }; CaretBefore => { TEditSelection.CaretBeforeSelection[] }; Everything => { TEditSelection.SelectEverything[] }; GrowSel => { TEditSelection.GrowSelection[] }; GrowSelToBlanks => { TEditSelection.GrowSelectionToBlanks[] }; InsertLineBreak => { TEditInputOps.InsertLineBreak[] }; InsertNewline => { tdd: TEditDocument.TEditDocumentData ~ NARROW[viewer.data]; IF tdd = NIL THEN RETURN; TEditInputOps.InsertRope[TextEdit.GetNewlineDelimiter[tdd.text]] }; MakeNotPendingDelete => { TEditSelection.NotPendingDeleteSelection[] }; MakePendingDelete => { TEditSelection.PendingDeleteSelection[] }; MakeControlCharacter => { TEditInputOps.MakeControlCharacter[] }; MakeOctalCharacter => { TEditInputOps.MakeOctalCharacter[] }; UnMakeControlCharacter => { TEditInputOps.UnMakeControlCharacter[] }; UnMakeOctalCharacter => { TEditInputOps.UnMakeOctalCharacter[] }; MakePrimaryOp => { TEditSelection.MakePrimary[] }; MakeSecondaryOp => { TEditSelection.MakeSecondary[] }; CancelPrimaryOp => { TEditSelection.CancelPrimary[] }; CancelSecondaryOp => { TEditSelection.CancelSecondary[] }; Paint => { ForkPaint[viewer] }; PlaceholderBrackets => { TEditInputOps.InsertBrackets[1C,2C] }; ReadTip => { ReadTipTables[] }; ReloadStyle => { TEditInputOps.ReloadStyle[] }; SelectMatchingPlaceholderBrackets => { TEditInputOps.SelectMatchingBrackets[1C,2C]; }; SelectMatchingSingleQuotes => { <> TEditInputOps.SelectMatchingBrackets['\140,'']; }; SelectMatchingDoubleQuotes => { TEditInputOps.SelectMatchingBrackets['",'"] }; SelectMatchingDashBrackets => { TEditInputOps.SelectMatchingBrackets['-,'-] }; PreviousPlaceholder => { TEditInputOps.FindPlaceholders[FALSE] }; PreviousViewer => { TEditInputOps.NextViewer[FALSE] }; NextPlaceholder => { TEditInputOps.FindPlaceholders[TRUE] }; NextViewer => { TEditInputOps.NextViewer[TRUE] }; ReadAbbreviations => { TEditInputOps.LoadAbbreviations["Default"] }; < {>> <> <> <> <> <<};>> SelectMatchingParens => { TEditInputOps.SelectMatchingBrackets['(,')] }; SelectMatchingAngleBrackets => { TEditInputOps.SelectMatchingBrackets['<,'>] }; SelectMatchingCurlyBrackets => { TEditInputOps.SelectMatchingBrackets['{,'}] }; SelectMatchingSquareBrackets => { TEditInputOps.SelectMatchingBrackets['[,']] }; ParenBrackets => { TEditInputOps.InsertBrackets['(,')] }; DashBrackets => { TEditInputOps.InsertBrackets['-,'-] }; DoubleQuoteBrackets => { TEditInputOps.InsertBrackets['",'"] }; AngleBrackets => { TEditInputOps.InsertBrackets['<,'>] }; SingleQuoteBrackets => { <> TEditInputOps.InsertBrackets['\140,'']; }; CurlyBrackets => { TEditInputOps.InsertBrackets['{,'}] }; SquareBrackets => { TEditInputOps.InsertBrackets['[,']] }; Command0 => { DoCommand[viewer,0] }; Command1 => { DoCommand[viewer,1] }; Command2 => { DoCommand[viewer,2] }; Command3 => { DoCommand[viewer,3] }; Command4 => { DoCommand[viewer,4] }; Command5 => { DoCommand[viewer,5] }; Command6 => { DoCommand[viewer,6] }; Command7 => { DoCommand[viewer,7] }; Command8 => { DoCommand[viewer,8] }; Command9 => { DoCommand[viewer,9] }; SetComment => { TEditInputOps.SetCommentProp[TRUE] }; SetNotComment => { TEditInputOps.SetCommentProp[FALSE] }; PARAM => { -- Already processed in dispatch loop -- }; ENDCASE => ERROR; }; ENDCASE => ERROR; }; <> DispatchCommandProc: PUBLIC CommandClosureProc ~ { WITH data SELECT FROM c: REF CommandProc => [recordAtom: recordAtom, quit: quit] ¬ c­[viewer]; ENDCASE => ERROR; }; Register: PUBLIC PROC [name: ATOM, proc: CommandProc, before: BOOL ¬ TRUE] = { RegisterClosure[commandClosure: [name: name, proc: DispatchCommandProc, data: NEW[CommandProc ¬ proc]], before: before]; }; UnRegister: PUBLIC PROC [name: ATOM, proc: CommandProc] = { Match: PROC [data: REF] RETURNS [BOOL] ~ { WITH data SELECT FROM c: REF CommandProc => RETURN [c­ = proc]; ENDCASE => ERROR; }; UnRegisterClosure[name, DispatchCommandProc, Match]; }; IsRegistered: PUBLIC ENTRY PROC [name: ATOM, proc: CommandProc] RETURNS [BOOL] = { ENABLE UNWIND => NULL; p: REF ANY = RefTab.Fetch[commandTable, name].val; closureList: LIST OF CommandClosure ¬ NARROW[p]; FOR l: LIST OF CommandClosure ¬ closureList, l.rest UNTIL l=NIL DO IF l.first.proc=DispatchCommandProc THEN { WITH l.first.data SELECT FROM c: REF CommandProc => IF c­ = proc THEN RETURN [TRUE]; ENDCASE => NULL; }; ENDLOOP; RETURN [FALSE] }; CommandClosure: TYPE ~ TEditInputExtras.CommandClosure; CommandClosureProc: TYPE ~ TEditInputExtras.CommandClosureProc; RegisterClosure: PUBLIC ENTRY PROC [commandClosure: CommandClosure, before: BOOL ¬ TRUE] = { ENABLE UNWIND => NULL; p: REF ANY = RefTab.Fetch[commandTable, commandClosure.name].val; list: LIST OF CommandClosure ¬ NARROW[p]; IF before OR list=NIL THEN list ¬ CONS[commandClosure, list] ELSE { FOR l: LIST OF CommandClosure ¬ list, l.rest DO IF l.rest=NIL THEN { l.rest ¬ LIST[commandClosure]; EXIT }; ENDLOOP; }; [] ¬ RefTab.Store[commandTable, commandClosure.name, list]; }; UnRegisterClosure: PUBLIC ENTRY PROC [name: ATOM, proc: CommandClosureProc, match: PROC [REF] RETURNS [BOOL]] = { ENABLE UNWIND => NULL; p: REF ANY = RefTab.Fetch[commandTable, name].val; head: LIST OF CommandClosure = CONS[[NIL, NIL, NIL], NARROW[p]]; prev: LIST OF CommandClosure ¬ head; FOR rem: LIST OF CommandClosure ¬ prev.rest, prev.rest UNTIL rem=NIL DO IF rem.first.name # name THEN ERROR; IF rem.first.proc = proc AND (match=NIL OR match[rem.first.data]) THEN { prev.rest ¬ rem.rest } ELSE { prev ¬ rem }; ENDLOOP; IF head.rest = NIL THEN { [] ¬ RefTab.Delete[commandTable, name] } ELSE { [] ¬ RefTab.Store[commandTable, name, head.rest] }; }; GetCommandNames: PUBLIC ENTRY PROC RETURNS [list: LIST OF ATOM ¬ NIL] ~ { ENABLE UNWIND => NULL; EachPair: RefTab.EachPairAction = { <<[key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOL _ FALSE]>> list ¬ CONS[NARROW[key], list]; }; [] ¬ RefTab.Pairs[x: commandTable, action: EachPair]; }; <> RegisterCommandAtoms: PROC = { RegisterInternal[$ApplyCaretLook, ApplyCaretLook]; RegisterInternal[$ApplyLook, ApplyLook]; RegisterInternal[$ClearCaretLooks, ClearCaretLooks]; RegisterInternal[$ClearLooks, ClearLooks]; RegisterInternal[$BackSpace, BackSpace]; RegisterInternal[$BackWord, BackWord]; RegisterInternal[$DeleteNextChar, DeleteNextChar]; RegisterInternal[$DeleteNextWord, DeleteNextWord]; RegisterInternal[$GoToPreviousWord, GoToPreviousWord]; RegisterInternal[$GoToNextWord, GoToNextWord]; RegisterInternal[$GoToPreviousChar, GoToPreviousChar]; RegisterInternal[$GoToNextChar, GoToNextChar]; RegisterInternal[$GoToPreviousNode, GoToPreviousNode]; RegisterInternal[$GoToNextNode, GoToNextNode]; RegisterInternal[$GoToEndOfNode, GoToEndOfNode]; RegisterInternal[$GoToBeginningOfNode, GoToBeginningOfNode]; RegisterInternal[$Copy, Copy]; RegisterInternal[$Delete, Delete]; Register [$DoEdit, DoEdit]; RegisterInternal[$ExpandAbbrev, ExpandAbbrev]; RegisterInternal[$Move, Move]; RegisterInternal[$NormalizeToStart, NormalizeToStart]; Register [$NormalizeToCaret, Normalize]; RegisterInternal[$NormalizeToEnd, NormalizeToEnd]; RegisterInternal[$RemoveCaretLook, RemoveCaretLook]; RegisterInternal[$RemoveLook, RemoveLook]; RegisterInternal[$SetStyle, SetStyle]; RegisterInternal[$Time, Time]; RegisterInternal[$RedSplit, RedSplit]; RegisterInternal[$YellowSplit, YellowSplit]; RegisterInternal[$BlueSplit, BlueSplit]; RegisterInternal[$Transpose, Transpose]; RegisterInternal[$ToBoth, ToBoth]; RegisterInternal[$ToLimbo, ToLimbo]; RegisterInternal[$ToPrimary, ToPrimary]; RegisterInternal[$ToSecondary, ToSecondary]; RegisterInternal[$CutToWorld, CutToWorld]; RegisterInternal[$CutToWorldFormatted, CutToWorldFormatted]; RegisterInternal[$CopyToWorld, CopyToWorld]; RegisterInternal[$CopyToWorldFormatted, CopyToWorldFormatted]; RegisterInternal[$Paste, Paste]; RegisterInternal[$PasteFromWorld, PasteFromWorld]; RegisterInternal[$PasteFromWorldFormatted, PasteFromWorldFormatted]; RegisterInternal[$EditReset, EditReset]; RegisterInternal[$EditAbort, EditAbort]; RegisterInternal[$EditText, EditText]; RegisterInternal[$EditFormat, EditFormat]; RegisterInternal[$EditType, EditFormat]; -- For compatability RegisterInternal[$EditLooks, EditLooks]; RegisterInternal[$GetSecondary, GetSecondary]; RegisterInternal[$MakePDel, MakePDel]; RegisterInternal[$FindNext, FindNext]; RegisterInternal[$FindAny, FindAny]; RegisterInternal[$FindPrev, FindPrev]; RegisterInternal[$FindNextDef, FindNextDef]; RegisterInternal[$FindAnyDef, FindAnyDef]; RegisterInternal[$FindPrevDef, FindPrevDef]; RegisterInternal[$FindNextWord, FindNextWord]; RegisterInternal[$FindAnyWord, FindAnyWord]; RegisterInternal[$FindPrevWord, FindPrevWord]; RegisterInternal[$FindNextCaseless, FindNextCaseless]; RegisterInternal[$FindAnyCaseless, FindAnyCaseless]; RegisterInternal[$FindPrevCaseless, FindPrevCaseless]; RegisterInternal[$FindNextDefCaseless, FindNextDefCaseless]; RegisterInternal[$FindAnyDefCaseless, FindAnyDefCaseless]; RegisterInternal[$FindPrevDefCaseless, FindPrevDefCaseless]; RegisterInternal[$FindNextWordCaseless, FindNextWordCaseless]; RegisterInternal[$FindAnyWordCaseless, FindAnyWordCaseless]; RegisterInternal[$FindPrevWordCaseless, FindPrevWordCaseless]; Register [$PushSelection, SaveSelectionA]; Register [$PopSelection, RestoreSelectionA]; Register [$SaveSelection, SaveSelectionA]; Register [$RestoreSelection, RestoreSelectionA]; Register [$SaveSelectionA, SaveSelectionA]; Register [$RestoreSelectionA, RestoreSelectionA]; Register [$SaveSelectionB, SaveSelectionB]; Register [$RestoreSelectionB, RestoreSelectionB]; RegisterInternal[$Position, Position]; RegisterInternal[$PositionIncludingComments, PositionIncludingComments]; RegisterInternal[$MsgPosition, MsgPosition]; RegisterInternal[$MsgPositionIncludingComments, MsgPositionIncludingComments]; RegisterInternal[$StuffPosition, StuffPosition]; RegisterInternal[$StuffPositionIncludingComments, StuffPosition]; RegisterInternal[$RedMouse, RedMouse]; RegisterInternal[$YellowMouse, YellowMouse]; RegisterInternal[$BlueMouse, BlueMouse]; RegisterInternal[$RedDown, RedDown]; RegisterInternal[$YellowDown, YellowDown]; RegisterInternal[$BlueDown, BlueDown]; RegisterInternal[$SelBranch, SelBranch]; RegisterInternal[$SelChar, SelChar]; RegisterInternal[$SelExpand, SelExpand]; RegisterInternal[$SelExtend, SelExtend]; RegisterInternal[$SelStartExtend, SelStartExtend]; RegisterInternal[$SelNode, SelNode]; RegisterInternal[$SelNotPendDel, SelNotPendDel]; RegisterInternal[$SelPendDel, SelPendDel]; RegisterInternal[$ForceSelPendDel, ForceSelPendDel]; RegisterInternal[$ForceSelNotPendDel, ForceSelNotPendDel]; RegisterInternal[$SelSamePendDel, SelSamePendDel]; RegisterInternal[$SelPrimary, SelPrimary]; RegisterInternal[$SelReduce, SelReduce]; RegisterInternal[$SelSame, SelSame]; RegisterInternal[$SelSameEnd, SelSameEnd]; RegisterInternal[$SelSecondary, SelSecondary]; RegisterInternal[$SelUpdate, SelUpdate]; RegisterInternal[$SelWord, SelWord]; RegisterInternal[$IntermediateUser, IntermediateUser]; RegisterInternal[$AdvancedUser, AdvancedUser]; RegisterInternal[$ExpertUser, ExpertUser]; RegisterInternal[$Break, Break]; RegisterInternal[$Join, Join]; RegisterInternal[$Nest, Nest]; RegisterInternal[$SaveForPaste, SaveForPaste]; RegisterInternal[$SetFormat, SetFormat]; RegisterInternal[$SetType, SetFormat]; -- For compatability RegisterInternal[$GetFormat, GetFormat]; RegisterInternal[$GetType, GetFormat]; -- For compatability RegisterInternal[$UnNest, UnNest]; RegisterInternal[$AllCaps, AllCaps]; RegisterInternal[$AllLower, AllLower]; RegisterInternal[$FirstCap, FirstCap]; RegisterInternal[$InitialCaps, InitialCaps]; Register [$AllLevels, AllLevels]; Register [$FewerLevels, FewerLevels]; Register [$MoreLevels, MoreLevels]; Register [$FirstLevelOnly, FirstLevelOnly]; RegisterInternal[$CaretAfter, CaretAfter]; RegisterInternal[$CaretBefore, CaretBefore]; RegisterInternal[$Everything, Everything]; RegisterInternal[$GrowSelection, GrowSel]; RegisterInternal[$GrowSelectionToBlanks, GrowSelToBlanks]; RegisterInternal[$InsertLineBreak, InsertLineBreak]; RegisterInternal[$InsertNewline, InsertNewline]; RegisterInternal[$MakeNotPendingDelete, MakeNotPendingDelete]; RegisterInternal[$MakePendingDelete, MakePendingDelete]; Register [$MakePointSelection, MakePointSelection]; RegisterInternal[$MakeControlCharacter, MakeControlCharacter]; RegisterInternal[$MakeOctalCharacter, MakeOctalCharacter]; RegisterInternal[$UnMakeControlCharacter, UnMakeControlCharacter]; RegisterInternal[$UnMakeOctalCharacter, UnMakeOctalCharacter]; RegisterInternal[$MakePrimary, MakePrimaryOp]; RegisterInternal[$MakeSecondary, MakeSecondaryOp]; RegisterInternal[$CancelPrimary, CancelPrimaryOp]; RegisterInternal[$CancelSecondary, CancelSecondaryOp]; RegisterInternal[$Paint, Paint]; RegisterInternal[$PlaceholderBrackets, PlaceholderBrackets]; RegisterInternal[$PreviousPlaceholder, PreviousPlaceholder]; RegisterInternal[$PreviousViewer, PreviousViewer]; RegisterInternal[$ReadProfile, ReadTip]; RegisterInternal[$ReloadStyle, ReloadStyle]; RegisterInternal[$SelectMatchingPlaceholderBrackets, SelectMatchingPlaceholderBrackets]; RegisterInternal[$NextPlaceholder, NextPlaceholder]; RegisterInternal[$NextViewer, NextViewer]; RegisterInternal[$ReadAbbreviations, ReadAbbreviations]; <> RegisterInternal[$SelectMatchingParens, SelectMatchingParens]; RegisterInternal[$SelectMatchingAngleBrackets, SelectMatchingAngleBrackets]; RegisterInternal[$SelectMatchingCurlyBrackets, SelectMatchingCurlyBrackets]; RegisterInternal[$SelectMatchingSquareBrackets, SelectMatchingSquareBrackets]; RegisterInternal[$SelectMatchingSingleQuotes, SelectMatchingSingleQuotes]; RegisterInternal[$SelectMatchingDoubleQuotes, SelectMatchingDoubleQuotes]; RegisterInternal[$SelectMatchingDashBrackets, SelectMatchingDashBrackets]; RegisterInternal[$ParenBrackets, ParenBrackets]; RegisterInternal[$DashBrackets, DashBrackets]; RegisterInternal[$AngleBrackets, AngleBrackets]; RegisterInternal[$DoubleQuoteBrackets, DoubleQuoteBrackets]; RegisterInternal[$SingleQuoteBrackets, SingleQuoteBrackets]; RegisterInternal[$CurlyBrackets, CurlyBrackets]; RegisterInternal[$SquareBrackets, SquareBrackets]; RegisterInternal[$Command0, Command0]; RegisterInternal[$Command1, Command1]; RegisterInternal[$Command2, Command2]; RegisterInternal[$Command3, Command3]; RegisterInternal[$Command4, Command4]; RegisterInternal[$Command5, Command5]; RegisterInternal[$Command6, Command6]; RegisterInternal[$Command7, Command7]; RegisterInternal[$Command8, Command8]; RegisterInternal[$Command9, Command9]; RegisterInternal[$SetComment, SetComment]; RegisterInternal[$SetNotComment, SetNotComment]; RegisterInternal[$PARAM, PARAM]; }; justRegistered: BOOL ¬ TRUE; ProfileChanged: UserProfile.ProfileChangedProc = { IF NOT justRegistered THEN TEditProfile.ReadProfile[]; justRegistered ¬ FALSE; }; <> <> <> <> <> <> <> <> <<>> RegisterCommandAtoms[]; NodeAddrs.AddNotifyProc[UpdateSavedSelections]; UserProfile.CallWhenProfileChanges[ProfileChanged]; SetCommand[9, LIST[$MakePointSelection, $ParenBrackets]]; SetCommand[0, LIST[$SelectMatchingParens, $CaretAfter]]; END.