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 "<cm + " ELSE "<cm to ";
msg ← msg.Cat[IF doLine THEN IO.PutFR["%g,", IO.int[line]] ELSE ".,"];
msg ← msg.Cat[IF doCol THEN IO.PutFR["%g>", 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 => "<clr eol>",
EndOfScreen => "<clr eos>",
ENDCASE => ERROR;
dd.toD.PutF[msg];
NoteDelta[dd, msg.Length[]];
};
DClearAll:
PROC [cd: CharDisplay] = {
dd: DebuggingDisplay ← NARROW[cd.otherInstanceData];
dd.toD.PutF["<clear all>"];
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 "<insert line>" ELSE "<delete line>";
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["<dc>"];
NoteDelta[dd, 4];
};
DFlash:
PROC [cd: CharDisplay] = {
dd: DebuggingDisplay ← NARROW[cd.otherInstanceData];
dd.toD.PutF["<flash>"];
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];
}.