<<>> <> <> <> DIRECTORY Ascii, Atom, CharDisplays, EditedStream, IO, RefText, Rope, TEditLocks, TextEdit, TextLooks, TextNode, TiogaOps, TypeScript, ViewerClasses, ViewerIO; TypescriptDisplays: CEDAR PROGRAM IMPORTS Atom, EditedStream, IO, RefText, Rope, TEditLocks, TextEdit, TextLooks, TextNode, TiogaOps, TypeScript, ViewerIO = {OPEN CharDisplays; REFTEXT: TYPE = REF TEXT; ROPE: TYPE = Rope.ROPE; Viewer: TYPE = ViewerClasses.Viewer; typescriptDisplay: CharDisplayClass ¬ NEW [CharDisplayClassRep ¬ [ Init: InitTSDisplay, TakeChar: TSTakeChar, CursorMove: TSCursorMove, ClearAll: TSClearAll]]; TSDisplay: TYPE = REF TSDisplayRep; TSDisplayRep: PUBLIC TYPE = RECORD [ ts: Viewer, fromDisplay: IO.STREAM, TORoot, TONode: TiogaOps.Ref, TNRoot: TextNode.Ref, TNNode: TextNode.RefTextNode, looks: TextLooks.Looks, spaces: REFTEXT, lineS: SEQUENCE length: NAT OF Line ]; Line: TYPE = RECORD [ tiogaCount: NAT, key: ATOM]; InitTSDisplay: PROC [cd: CharDisplay, initData: REF ANY] = { tsd: TSDisplay ¬ NEW [TSDisplayRep[cd.class.lines]]; cd.otherInstanceData ¬ tsd; tsd.ts ¬ TypeScript.Create[info: [name: cd.name, iconic: FALSE]]; TypeScript.ChangeLooks[tsd.ts, 'f]; [in: cd.fromDisplay] ¬ ViewerIO.CreateViewerStreams[name: cd.name, viewer: tsd.ts, editedStream: FALSE]; EditedStream.SetEcho[cd.fromDisplay, NIL]; tsd.TORoot ¬ TiogaOps.ViewerDoc[tsd.ts]; tsd.TNRoot ¬ TiogaOpsRefToTextNodeRef[tsd.TORoot]; tsd.looks ¬ TextLooks.RopeToLooks["f"]; tsd.spaces ¬ RefText.New[cd.class.columns]; FOR l: NAT IN [0 .. cd.class.lines) DO TypeScript.PutChar[tsd.ts, '\n]; tsd.lineS[l] ¬ [ tiogaCount: 0, key: Atom.MakeAtom[IO.PutFR["Before%g", IO.int[l]]] ]; ENDLOOP; SetLines[cd, tsd]; }; SetLines: PROC [cd: CharDisplay, tsd: TSDisplay] = { IsBegin: PROC [ci: INT] RETURNS [is: BOOL] = INLINE {is ¬ ci = 0 OR nr.Fetch[ci-1] = '\n}; nr: ROPE; lineNum, prevCI: INT; TypeScript.Flush[tsd.ts]; tsd.TONode ¬ TiogaOps.LastChild[tsd.TORoot]; tsd.TNNode ¬ TextNode.NarrowToTextNode[TiogaOpsRefToTextNodeRef[tsd.TONode]]; nr ¬ TiogaOps.GetRope[tsd.TONode]; lineNum ¬ cd.class.lines; prevCI ¬ nr.Length[]; FOR ci: INT ¬ nr.Length[]-1, ci-1 WHILE lineNum > 0 DO IF ci < 0 THEN ERROR; IF IsBegin[ci] THEN { lineNum ¬ lineNum - 1; TiogaOps.PutTextKey[node: tsd.TONode, where: ci, key: tsd.lineS[lineNum].key]; tsd.lineS[lineNum].tiogaCount ¬ prevCI - ci - 1; prevCI ¬ ci; }; ENDLOOP; }; TiogaOpsRefToTextNodeRef: PROC [tor: TiogaOps.Ref] RETURNS [tnr: TextNode.Ref] = TRUSTED {tnr ¬ LOOPHOLE[tor] --TiogaOpsImpl says TiogaOpsDefs.NodeBody = TextNode.Body--}; TSTakeChar: PROC [cd: CharDisplay, char: CHAR, insert: BOOL ¬ FALSE] = { tsd: TSDisplay ¬ NARROW[cd.otherInstanceData]; lock: TEditLocks.LockRef ¬ NIL; squash: [0 .. 1] ¬ IF insert THEN 0 ELSE 1; base: INT ¬ TiogaOps.GetTextKey[node: tsd.TONode, key: tsd.lineS[cd.line].key].where; wasEmpty: BOOL; wasEmpty ¬ tsd.lineS[cd.line].tiogaCount = 0; EnsureLineTo[cd, tsd, cd.line, cd.col+squash]; lock ¬ TEditLocks.Lock[doc: tsd.TNRoot, who: "Char Displays"]; { ENABLE UNWIND => IF lock # NIL THEN TEditLocks.Unlock[tsd.TNRoot]; [] ¬ TextEdit.ReplaceByChar[root: tsd.TNRoot, dest: tsd.TNNode, char: char, start: base + cd.col, len: squash, looks: tsd.looks]; tsd.lineS[cd.line].tiogaCount ¬ tsd.lineS[cd.line].tiogaCount + 1 - squash; TEditLocks.Unlock[doc: tsd.TNRoot]; }; IF wasEmpty OR cd.col = 0 THEN SetLines[cd, tsd]; TSCursorMove[cd, 0, 1, TRUE]; }; EnsureLineTo: PROC [cd: CharDisplay, tsd: TSDisplay, line, col: INT] = { diff: INT ¬ col - tsd.lineS[line].tiogaCount; lock: TEditLocks.LockRef ¬ NIL; base: INT ¬ TiogaOps.GetTextKey[node: tsd.TONode, key: tsd.lineS[cd.line].key].where; IF tsd.spaces.maxLength < diff THEN tsd.spaces ¬ RefText.New[diff]; WHILE tsd.spaces.length < diff DO tsd.spaces ¬ RefText.InlineAppendChar[tsd.spaces, Ascii.SP]; ENDLOOP; IF diff <= 0 THEN RETURN; lock ¬ TEditLocks.Lock[doc: tsd.TNRoot, who: "Char Displays"]; { ENABLE UNWIND => IF lock # NIL THEN TEditLocks.Unlock[tsd.TNRoot]; [] ¬ TextEdit.ReplaceByString[root: tsd.TNRoot, dest: tsd.TNNode, string: tsd.spaces, stringStart: 0, stringNum: diff, start: base + tsd.lineS[line].tiogaCount, len: 0, looks: tsd.looks]; tsd.lineS[line].tiogaCount ¬ tsd.lineS[line].tiogaCount + diff; TEditLocks.Unlock[doc: tsd.TNRoot]; }; }; TSCursorMove: PROC [cd: CharDisplay, line, col: INT, relative: BOOL ¬ FALSE] = { tsd: TSDisplay ¬ NARROW[cd.otherInstanceData]; IF relative THEN {line ¬ line + cd.line; col ¬ col + cd.col}; IF cd.class.autoMargins THEN { dl: INT ¬ col / cd.class.columns; line ¬ line + dl; col ¬ col - dl * cd.class.columns; } ELSE col ¬ MIN[col, cd.class.columns-1]; IF line < 0 THEN ERROR; IF line >= cd.class.lines THEN { delta: INT ¬ line - (cd.class.lines-1); FOR i: INT IN [0 .. delta) DO TypeScript.PutChar[tsd.ts, '\n] ENDLOOP; line ¬ line - delta; SetLines[cd, tsd]; }; cd.line ¬ line; cd.col ¬ col; }; <<>> TSClearAll: PROC [cd: CharDisplay] = { TSCursorMove[cd: cd, col: 0, line: cd.class.lines*2]; TSCursorMove[cd: cd, col: 0, line: 0]; }; }.