<> <> DIRECTORY Ascii, Atom, CharDisplays, EditedStream, IO, IOClasses, List, Rope, ViewerClasses, ViewerIO; CharDisplaysImpl: CEDAR PROGRAM IMPORTS Atom, EditedStream, IO, IOClasses, List, Rope, ViewerIO EXPORTS CharDisplays = {OPEN CharDisplays; REFTEXT: TYPE = REF TEXT; classes: List.AList _ NIL; GetClass: PUBLIC PROC [name: ROPE] RETURNS [cdc: CharDisplayClass] = { a: ATOM _ Atom.MakeAtom[name]; cdc _ NARROW[List.Assoc[key: a, aList: classes]]; IF NOT name.Equal[cdc.name] THEN ERROR; }; RegClass: PUBLIC PROC [cdc: CharDisplayClass] = { a: ATOM _ Atom.MakeAtom[cdc.name]; classes _ List.PutAssoc[key: a, val: cdc, aList: classes]; }; Create: PUBLIC PROC [class: CharDisplayClass, name: ROPE _ NIL, det: DisplayDetails _ [], initData: REF ANY _ NIL] RETURNS [cd: CharDisplay] = { cd _ NEW [CharDisplayRep _ [class: class, det: det, name: name]]; class.Init[cd, initData]; }; debuggingDisplay: CharDisplayClass _ NEW [CharDisplayClassRep _ [ name: "Debug", Init: DInit, DeleteChar: DDeleteChar, TakeChar: DTakeChar, CursorMove: DCursorMove, Line: DLine, ClearTo: DClearTo, ClearAll: DClearAll, SetMode: DSetMode, Emphasize: DEmphasize, Flash: DFlash]]; DebuggingDisplay: TYPE = REF DebuggingDisplayRep; DebuggingDisplayRep: TYPE = RECORD [ fromD, toD: IO.STREAM _ NIL, charsOnLine: NAT _ 0 ]; DInit: PROC [cd: CharDisplay, initData: REF ANY] = { dd: DebuggingDisplay _ NEW [DebuggingDisplayRep _ []]; cd.otherInstanceData _ dd; [dd.fromD, dd.toD] _ ViewerIO.CreateViewerStreams[name: cd.name, editedStream: FALSE]; cd.fromDisplay _ dd.fromD; cd.viewer _ ViewerIO.GetViewerFromStream[dd.fromD]; EditedStream.SetEcho[dd.fromD, NIL]; }; DTakeChar: PROC [cd: CharDisplay, char: CHAR] = { dd: DebuggingDisplay _ NARROW[cd.otherInstanceData]; SELECT char FROM IN [Ascii.SP .. Ascii.DEL) => {dd.toD.PutChar[char]; NoteDelta[dd, 1]}; ENDCASE => {dd.toD.PutF["<%h>", IO.char[char]]; NoteDelta[dd, 4]}; MoveDCursor[cd, 0, 1, TRUE, TRUE, TRUE, FALSE]; }; DCursorMove: PROC [cd: CharDisplay, line, col: INT, relative: BOOL _ FALSE, doLine, doCol: BOOL _ TRUE] = {MoveDCursor[cd, line, col, relative, doLine, doCol, TRUE]}; MoveDCursor: PROC [cd: CharDisplay, line, col: INT, relative, doLine, doCol, report: BOOL _ FALSE] = { dd: DebuggingDisplay _ NARROW[cd.otherInstanceData]; IF report THEN { msg: ROPE _ IF relative THEN "", IO.int[col]] ELSE ".>"]; dd.toD.PutRope[msg]; dd.toD.PutRope["\n"]; dd.charsOnLine _ 0; }; IF relative THEN {line _ line + cd.line; col _ col + cd.col}; IF NOT doLine THEN line _ cd.line; IF NOT doCol THEN col _ cd.col; IF cd.det.autoMargins THEN { dl: INT _ col / cd.det.columns; line _ line + dl; col _ col - dl * cd.det.columns; } ELSE col _ MIN[col, cd.det.columns-1]; cd.line _ line; cd.col _ col; }; DClearTo: PROC [cd: CharDisplay, where: Where] = { dd: DebuggingDisplay _ NARROW[cd.otherInstanceData]; msg: ROPE _ SELECT where FROM EndOfLine => "", EndOfScreen => "", ENDCASE => ERROR; dd.toD.PutF[msg]; NoteDelta[dd, msg.Length[]]; }; DClearAll: PROC [cd: CharDisplay] = { dd: DebuggingDisplay _ NARROW[cd.otherInstanceData]; dd.toD.PutF[""]; NoteDelta[dd, 11]; }; DSetMode: PROC [cd: CharDisplay, mode: Mode, on: BOOL] = { dd: DebuggingDisplay _ NARROW[cd.otherInstanceData]; msg: ROPE _ IO.PutFR["<%g %g>", IO.rope[ModeNames[mode]], IO.bool[on]]; dd.toD.PutF[msg]; NoteDelta[dd, msg.Length[]]; }; DLine: PROC [cd: CharDisplay, insert: BOOL] = { dd: DebuggingDisplay _ NARROW[cd.otherInstanceData]; msg: ROPE _ IF insert THEN "" ELSE ""; dd.toD.PutRope[msg]; NoteDelta[dd, msg.Length[]]; }; DEmphasize: PROC [cd: CharDisplay, emph: Emph, on: BOOL] = { dd: DebuggingDisplay _ NARROW[cd.otherInstanceData]; msg: ROPE _ IO.PutFR["<%g %g@>", IO.rope[ModeNames[emph]], IO.bool[on]]; dd.toD.PutF[msg]; NoteDelta[dd, msg.Length[]]; }; DDeleteChar: PROC [cd: CharDisplay] = { dd: DebuggingDisplay _ NARROW[cd.otherInstanceData]; dd.toD.PutF[""]; NoteDelta[dd, 4]; }; DFlash: PROC [cd: CharDisplay] = { dd: DebuggingDisplay _ NARROW[cd.otherInstanceData]; dd.toD.PutF[""]; NoteDelta[dd, 7]; }; ModeNames: ARRAY Mode OF ROPE _ [ insertChar: "insertChar", underline: "underline", standout: "standout"]; lineLength: NAT _ 95; NoteDelta: PROC [dd: DebuggingDisplay, dc: INT] = { dd.charsOnLine _ dd.charsOnLine + dc; IF dd.charsOnLine > lineLength THEN { dd.toD.PutRope["\n"]; dd.charsOnLine _ 0}; }; Split: PUBLIC PROC [l: CharDisplayList, name: ROPE _ NIL] RETURNS [s: CharDisplay] = { s _ Create[class: splitClass, name: name, initData: l]; }; splitClass: CharDisplayClass _ NEW [CharDisplayClassRep _ [ name: "Split", Init: SInit, TakeChar: STakeChar, CursorMove: SCursorMove, ClearAll: SClearAll]]; SInit: PROC [cd: CharDisplay, initData: REF ANY] = { l: CharDisplayList _ NARROW[initData]; cd.otherInstanceData _ l; cd.fromDisplay _ NIL; FOR l _ l, l.rest WHILE l # NIL DO cd.fromDisplay _ IF cd.fromDisplay = NIL THEN l.first.fromDisplay ELSE IOClasses.CreateCatInputStream[cd.fromDisplay, l.first.fromDisplay]; ENDLOOP; }; STakeChar: PROC [cd: CharDisplay, char: CHAR] = { l: CharDisplayList _ NARROW[cd.otherInstanceData]; FOR l _ l, l.rest WHILE l # NIL DO l.first.class.TakeChar[l.first, char]; cd.line _ l.first.line; cd.col _ l.first.col; ENDLOOP}; SCursorMove: PROC [cd: CharDisplay, line, col: INT, relative: BOOL _ FALSE, doLine, doCol: BOOL _ TRUE] = { l: CharDisplayList _ NARROW[cd.otherInstanceData]; FOR l _ l, l.rest WHILE l # NIL DO l.first.class.CursorMove[l.first, line, col, relative, doLine, doCol]; cd.line _ l.first.line; cd.col _ l.first.col; ENDLOOP}; SClearAll: PROC [cd: CharDisplay] = { l: CharDisplayList _ NARROW[cd.otherInstanceData]; FOR l _ l, l.rest WHILE l # NIL DO l.first.class.ClearAll[l.first]; cd.line _ l.first.line; cd.col _ l.first.col; ENDLOOP}; RegClass[debuggingDisplay]; RegClass[splitClass]; }.