EMVT100.mesa
Last Edited by: Neil Gunther, November 1, 1985 2:58:57 pm PST
DIRECTORY CharDisplays, DisplayControllers, DisplayControllerSteps, Rope, TermProgs;
Emulates a VT100.
EmVT100: CEDAR PROGRAM
IMPORTS DisplayControllers, DisplayControllerSteps, TermProgs = BEGIN
OPEN DisplayControllers, DisplayControllerSteps, TermProgs;
CurrentCursor: TYPE = REF CurrentCursorRec;
CurrentCursorRec: TYPE = RECORD [line: INT, column: INT];
cursor: CurrentCursor ← NIL;
attributes: TYPE = {bold, uScore, blink, neg};
Attribute: TYPE = ARRAY attributes OF BOOLALL[FALSE];
att, storedAtts: Attribute;
vt52Mode: BOOLFALSE;
MakeVT100: PROC RETURNS [t: Term] = {
cursor ← NEW[CurrentCursorRec];
t ← NEW [TermRep ← [cp: NewControlProgram[]]];
AddInstruction[t.cp, LIST["\000"], [Naught]];
AddInstruction[t.cp, LIST["\007"], [Flash]];
AddInstruction[t.cp, LIST["\010"], [SkipCursor, $left]];
AddInstruction[t.cp, LIST["\011"], [Tab, $dontTouch]];
AddInstruction[t.cp, LIST["\012"], [SkipCursor, $down]];
AddInstruction[t.cp, LIST["\015"], [CarriageReturn]];
AddInstruction[t.cp, LIST["\033[H"], [Home]];
AddInstruction[t.cp, LIST["\033f"], [Home]];
AddInstruction[t.cp, LIST["\033[f"], [Home]];
AddInstruction[t.cp, LIST["\033[A"], [SkipCursor, $up]];
AddInstruction[t.cp, LIST["\033A"], [Vt52CU]];
AddInstruction[t.cp, LIST["\033[B"], [SkipCursor, $down]];
AddInstruction[t.cp, LIST["\033B"], [Vt52CD]];
AddInstruction[t.cp, LIST["\033[C"], [SkipCursor, $right]];
AddInstruction[t.cp, LIST["\033C"], [Vt52CR]];
AddInstruction[t.cp, LIST["\033[D"], [SkipCursor, $left]];
AddInstruction[t.cp, LIST["\033D"], [Vt52CL]];
AddInstruction[t.cp, LIST["\033H"], [Vt52CH]];
AddInstruction[t.cp, LIST["\033I"], [Vt52RLF]];
AddInstruction[t.cp, LIST["\033[J"], [ClrTo, $eos]];
AddInstruction[t.cp, LIST["\033J"], [Vt52EOS]];
AddInstruction[t.cp, LIST["\033[K"], [ClrTo, $eol]];
AddInstruction[t.cp, LIST["\033K"], [Vt52EOL]];
AddInstruction[t.cp, LIST["\0337"], [SaveAll]];
AddInstruction[t.cp, LIST["\0338"], [RestoreAll]];
AddInstruction[t.cp, LIST["\033[m"], [AttsOff]];
AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ← [reg: line]], "J"], [JDecode]];
AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ← [reg: line]], "K"], [KDecode]];
AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ← [reg: line]], "m"], [Att1Decode]];
AddInstruction[t.cp, LIST["\033[",
NEW [DecodeRep ← [reg: line]], ";",
NEW [DecodeRep ← [reg: col]],
"m"], [Att2Decode]];
AddInstruction[t.cp, LIST["\033[",
NEW [DecodeRep ← [reg: line]], ";",
NEW [DecodeRep ← [reg: col]], ";",
NEW [DecodeRep ← [reg: aux1]], ";",
"m"], [Att3Decode]];
AddInstruction[t.cp, LIST["\033[",
NEW [DecodeRep ← [reg: line]], ";",
NEW [DecodeRep ← [reg: col]], ";",
NEW [DecodeRep ← [reg: aux1]], ";",
NEW [DecodeRep ← [reg: aux2]], ";",
"m"], [Att4Decode]];
AddInstruction[t.cp, LIST["\033[",
NEW [DecodeRep ← [reg: line]], ";",
NEW [DecodeRep ← [reg: col]], ";",
NEW [DecodeRep ← [reg: aux1]], ";",
NEW [DecodeRep ← [reg: aux2]], ";",
NEW [DecodeRep ← [reg: aux3]], ";",
"m"], [Att5Decode]];
AddInstruction[t.cp,LIST["\033[", NEW [DecodeRep ← [reg: line]], ";",
NEW [DecodeRep ← [reg: col]], "H"], [NormCursor]];
AddInstruction[t.cp,
LIST["\033Y",
NEW [DecodeRep ← [reg: line, base: NumChars, org: ' , len: 1]],
NEW [DecodeRep ← [reg: col, base: NumChars, org: ' , len: 1]]],
[Vt52CA]];
AddInstruction[t.cp,LIST["\033[", NEW [DecodeRep ← [reg: line]], ";",
NEW [DecodeRep ← [reg: col]], "f"], [NormCursor]];
AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ← [reg: line]], "A"], [JumpCursor, $v]];
AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ← [reg: line]], "B"], [JumpCursor, $v]];
AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ← [reg: line]], "C"], [CursorHn]];
AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ← [reg: line]], "D"], [CursorHn]];
-- *** NoOp Traps *** --
-- Programmable LEDs
AddInstruction[t.cp, LIST["\033[q"], [Naught]];
-- Line Size
AddInstruction[t.cp, LIST["\033#", NEW [DecodeRep ← [reg: line, len: 1]]], [Naught]];
-- Indexing
AddInstruction[t.cp, LIST["\033D"], [Naught]];
AddInstruction[t.cp, LIST["\033E"], [Naught]];
AddInstruction[t.cp, LIST["\033M"], [Naught]];
-- Alternate Characters/Keys
AddInstruction[t.cp, LIST["\033F"], [Naught]];
AddInstruction[t.cp, LIST["\033G"], [Naught]];
AddInstruction[t.cp, LIST["\033>"], [Naught]];
AddInstruction[t.cp, LIST["\033<"], [Naught]];
AddInstruction[t.cp, LIST["\033="], [Naught]];
AddInstruction[t.cp, LIST["\033(A"], [Naught]];
AddInstruction[t.cp, LIST["\033(B"], [Naught]];
AddInstruction[t.cp, LIST["\033(", NEW [DecodeRep ← [reg: line, len: 1]]], [Naught]];
AddInstruction[t.cp, LIST["\033)A"], [Naught]];
AddInstruction[t.cp, LIST["\033)B"], [Naught]];
AddInstruction[t.cp, LIST["\033)", NEW [DecodeRep ← [reg: line, len: 1]]], [Naught]];
-- Scrolling Region
AddInstruction[t.cp, LIST["\033[",
NEW [DecodeRep ← [reg: line]], ";",
NEW [DecodeRep ← [reg: col]],
"r"], [Naught]];
-- Tabbing
AddInstruction[t.cp, LIST["\033H"], [Naught]];
AddInstruction[t.cp, LIST["\033[g"], [Naught]];
AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ← [reg: line, len: 1]], "g"], [Naught]];
-- Status Report
AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ← [reg: line, len: 1]], "n"], [Naught]];
-- Interrogation
AddInstruction[t.cp, LIST["\033c"], [Naught]];
AddInstruction[t.cp, LIST["\033Z"], [Naught]];
AddInstruction[t.cp, LIST["\033[c"], [Naught]];
AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ← [reg: line, len: 1]], "c"], [Naught]];
AddInstruction[t.cp, LIST["\033[?l", NEW [DecodeRep ← [reg: line, len: 1]], "c"], [Naught]];
-- Tests
AddInstruction[t.cp, LIST["\033[2", NEW [DecodeRep ← [reg: line, len: 1]], "y"], [Naught]];
-- Modes
AddInstruction[t.cp, LIST["\033[?", NEW [DecodeRep ← [reg: line, len: 1]], "h"], [hDecode]];
AddInstruction[t.cp, LIST["\033[?", NEW [DecodeRep ← [reg: line, len: 1]], "l"], [lDecode]];
AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ← [reg: line, len: 2]], "h"], [Naught]];
AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ← [reg: line, len: 2]], "l"], [Naught]];
};
NormCursor: ActionProc = {
--to ranges of line[0..23] & col[0..79]
dc.cps.regs[line] ← dc.cps.regs[line]-1;
dc.cps.regs[col] ← dc.cps.regs[col]-1;
JumpCursor[dc, $hv];
};
Att1Decode: ActionProc = {
SELECT dc.cps.regs[line] FROM
0 => {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
FOR a: attributes IN [bold..neg] DO att[a] ← FALSE ENDLOOP;
};
1 => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
4 => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
5 => {--no-op-- att[blink] ← TRUE};
7 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
};
Att2Decode: ActionProc = {
SELECT dc.cps.regs[line] FROM
0 => {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
FOR a: attributes IN [bold..neg] DO att[a] ← FALSE ENDLOOP;
};
1 => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
4 => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
5 => {--no-op-- att[blink] ← TRUE};
7 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
SELECT dc.cps.regs[col] FROM
0 => {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
FOR a: attributes IN [bold..neg] DO att[a] ← FALSE ENDLOOP;
};
1 => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
4 => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
5 => {--no-op-- att[blink] ← TRUE};
7 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
};
Att3Decode: ActionProc = {
SELECT dc.cps.regs[line] FROM
0 => {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
FOR a: attributes IN [bold..neg] DO att[a] ← FALSE ENDLOOP;
};
1 => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
4 => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
5 => {--no-op-- att[blink] ← TRUE};
7 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
SELECT dc.cps.regs[col] FROM
0 => {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
FOR a: attributes IN [bold..neg] DO att[a] ← FALSE ENDLOOP;
};
1 => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
4 => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
5 => {--no-op-- att[blink] ← TRUE};
7 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
SELECT dc.cps.regs[aux1] FROM
0 => {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
FOR a: attributes IN [bold..neg] DO att[a] ← FALSE ENDLOOP;
};
1 => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
4 => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
5 => {--no-op-- att[blink] ← TRUE};
7 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
};
Att4Decode: ActionProc = {
SELECT dc.cps.regs[line] FROM
0 => {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
FOR a: attributes IN [bold..neg] DO att[a] ← FALSE ENDLOOP;
};
1 => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
4 => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
5 => {--no-op-- att[blink] ← TRUE};
7 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
SELECT dc.cps.regs[col] FROM
0 => {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
FOR a: attributes IN [bold..neg] DO att[a] ← FALSE ENDLOOP;
};
1 => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
4 => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
5 => {--no-op-- att[blink] ← TRUE};
7 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
SELECT dc.cps.regs[aux1] FROM
0 => {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
FOR a: attributes IN [bold..neg] DO att[a] ← FALSE ENDLOOP;
};
1 => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
4 => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
5 => {--no-op-- att[blink] ← TRUE};
7 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
SELECT dc.cps.regs[aux2] FROM
0 => {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
FOR a: attributes IN [bold..neg] DO att[a] ← FALSE ENDLOOP;
};
1 => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
4 => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
5 => {--no-op-- att[blink] ← TRUE};
7 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
};
Att5Decode: ActionProc = {
SELECT dc.cps.regs[line] FROM
0 => {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
FOR a: attributes IN [bold..neg] DO att[a] ← FALSE ENDLOOP;
};
1 => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
4 => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
5 => {--no-op-- att[blink] ← TRUE};
7 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
SELECT dc.cps.regs[col] FROM
0 => {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
FOR a: attributes IN [bold..neg] DO att[a] ← FALSE ENDLOOP;
};
1 => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
4 => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
5 => {--no-op-- att[blink] ← TRUE};
7 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
SELECT dc.cps.regs[aux1] FROM
0 => {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
FOR a: attributes IN [bold..neg] DO att[a] ← FALSE ENDLOOP;
};
1 => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
4 => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
5 => {--no-op-- att[blink] ← TRUE};
7 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
SELECT dc.cps.regs[aux2] FROM
0 => {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
FOR a: attributes IN [bold..neg] DO att[a] ← FALSE ENDLOOP;
};
1 => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
4 => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
5 => {--no-op-- att[blink] ← TRUE};
7 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
SELECT dc.cps.regs[aux3] FROM
0 => {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
FOR a: attributes IN [bold..neg] DO att[a] ← FALSE ENDLOOP;
};
1 => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
4 => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
5 => {--no-op-- att[blink] ← TRUE};
7 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
};
SaveAll: ActionProc = {
cursor.line ← dc.cps.regs[line];
cursor.column ← dc.cps.regs[col];
FOR a: attributes IN [bold..neg] DO storedAtts[a] ← att[a] ENDLOOP;
};
RestoreAll: ActionProc = {
dc.cd.class.CursorMove[dc.cd, cursor.line, cursor.column];
FOR a: attributes IN [bold..neg] DO
SELECT TRUE FROM
storedAtts[bold] => {SetEmph[dc, $boldOn]; att[bold] ← TRUE};
storedAtts[uScore] => {SetEmph[dc, $underlineOn]; att[uScore] ← TRUE};
storedAtts[blink] => {--no-op-- att[blink] ← TRUE};
storedAtts[neg] => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
ENDCASE;
ENDLOOP;
};
CursorHn: ActionProc = {
dc.cps.regs[col] ← dc.cps.regs[line];
JumpCursor[dc, $h];
};
JDecode: ActionProc = {
SELECT dc.cps.regs[line] FROM
0 => {ClrTo[dc, $eos]};
1 => { --clear from Home to cursor-- };
2 => {ClearScreen[dc, clientData]};
ENDCASE;
};
KDecode: ActionProc = {
SELECT dc.cps.regs[line] FROM
0 => {ClrTo[dc, $eol]};
1 => { --clear from line start to cursor-- };
2 => {Line[dc, $del]};
ENDCASE;
};
hDecode: ActionProc = {
SELECT dc.cps.regs[line] FROM
1 => { --cursor off-- };
2 => {vt52Mode ← FALSE};
3 => {--132 col--};
4 => {--smooth scroll--};
5 => {SetEmph[dc, $inverseOn]; att[neg] ← TRUE};
6 => {--no-op--};
7 => {--line-wrap--};
8 => {--auto repeat--};
9 => {--no-op--};
ENDCASE;
};
lDecode: ActionProc = {
SELECT dc.cps.regs[line] FROM
1 => { --cursor on-- };
2 => {vt52Mode ← TRUE};
3 => {-- 80 col--};
4 => {--jump scroll--};
5 => {SetEmph[dc, $inverseOff]; att[neg] ← FALSE};
6 => {--no-op--};
7 => {--line-wrap off--};
8 => {--auto repeat off--};
9 => {--no-op--};
ENDCASE;
};
AttsOff: ActionProc = {
SetEmph[dc, $boldOff];
SetEmph[dc, $underlineOff];
SetEmph[dc, $inverseOff];
};
Vt52CU: ActionProc = {IF vt52Mode THEN SkipCursor[dc, $up]};
Vt52CD: ActionProc = {IF vt52Mode THEN SkipCursor[dc, $down]};
Vt52CR: ActionProc = {IF vt52Mode THEN SkipCursor[dc, $right]};
Vt52CL: ActionProc = {IF vt52Mode THEN SkipCursor[dc, $left]};
Vt52CH: ActionProc = {IF vt52Mode THEN Home[dc, clientData]};
Vt52RLF: ActionProc = {IF vt52Mode THEN ScrollBack[dc, clientData]};
Vt52EOS: ActionProc = {IF vt52Mode THEN ClrTo[dc, $eos]};
Vt52EOL: ActionProc = {IF vt52Mode THEN ClrTo[dc, $eol]};
Vt52CA: ActionProc = {IF vt52Mode THEN JumpCursor[dc, $hv]};
RegTerm["vt100", MakeVT100[]];
END...