MODULE vt100; IMPORT Console, Strings; (* reference http://en.wikipedia.org/wiki/ANSI_escape_code & http://misc.flogisoft.com/bash/tip_colors_and_formatting *) CONST Escape* = 1BX; SynchronousIdle* = 16X; LeftCrotchet* = '['; (* formatting *) Bold* = "1m"; Dim* = "2m"; Underlined* = "4m"; Blink* = "5m"; (* does not work with most emulators, works in tty and xterm *) Reverse* = "7m"; (* invert the foreground and background colors *) Hidden* = "8m"; (* useful for passwords *) (* reset *) ResetAll* = "0m"; ResetBold* = "21m"; ResetDim* = "22m"; ResetUnderlined* = "24m"; ResetBlink* = "25m"; ResetReverse* = "27m"; ResetHidden* = "28m"; (* foreground colors *) Black* = "30m"; Red* = "31m"; Green* = "32m"; Yellow* = "33m"; Blue* = "34m"; Magenta* = "35m"; Cyan* = "36m"; LightGray* = "37m"; Default* = "39m"; DarkGray* = "90m"; LightRed* = "91m"; LightGreen* = "92m"; LightYellow* = "93m"; LightBlue* = "94m"; LightMagenta* = "95m"; LightCyan* = "96m"; White* = "97m"; (* background colors *) BBlack* = "40m"; BRed* = "41m"; BGreen* = "42m"; BYellow* = "43m"; BBlue* = "44m"; BMagenta* = "45m"; BCyan* = "46m"; BLightGray* = "47m"; BDefault* = "49m"; BDarkGray* = "100m"; BLightRed* = "101m"; BLightGreen* = "102m"; BLightYellow* = "103m"; BLightBlue* = "104m"; BLightMagenta*= "105m"; BLightCyan* = "106m"; BWhite* = "107m"; VAR CSI* : ARRAY 5 OF CHAR; tmpstr : ARRAY 32 OF CHAR; (* IntToStr routine taken from https://github.com/romiras/Oberon-F-components/blob/master/Ott/Mod/IntStr.cp and modified to work on 64bit system, in order to avoid using oocIntStr, which has many dependencies *) PROCEDURE Reverse0 (VAR str : ARRAY OF CHAR; start, end : INTEGER); (* Reverses order of characters in the interval [start..end]. *) VAR h : CHAR; BEGIN WHILE start < end DO h := str[start]; str[start] := str[end]; str[end] := h; INC(start); DEC(end) END END Reverse0; PROCEDURE IntToStr*(int: LONGINT; VAR str: ARRAY OF CHAR); (* Converts the value of `int' to string form and copies the possibly truncated result to `str'. *) VAR b : ARRAY 21 OF CHAR; s, e: INTEGER; maxLength : SHORTINT; (* maximum number of digits representing a LONGINT value *) BEGIN IF SIZE(LONGINT) = 4 THEN maxLength := 11 END; IF SIZE(LONGINT) = 8 THEN maxLength := 20 END; (* build representation in string 'b' *) IF int = MIN(LONGINT) THEN (* smallest LONGINT, -int is an overflow *) IF SIZE(LONGINT) = 4 THEN b := "-2147483648"; e := 11 ELSE (* SIZE(LONGINT) = 8 *) b := "-9223372036854775808"; e := 20 END ELSE IF int < 0 THEN (* negative sign *) b[0] := "-"; int := -int; s := 1 ELSE (* no sign *) s := 0 END; e := s; (* 's' holds starting position of string *) REPEAT b[e] := CHR(int MOD 10+ORD("0")); int := int DIV 10; INC(e) UNTIL int = 0; b[e] := 0X; Reverse0(b, s, e-1); END; COPY(b, str) (* truncate output if necessary *) END IntToStr; PROCEDURE EscSeq0 (letter : ARRAY OF CHAR); VAR cmd : ARRAY 9 OF CHAR; BEGIN COPY(CSI, cmd); Strings.Append (letter, cmd); Console.String (cmd); END EscSeq0; PROCEDURE EscSeq (n : INTEGER; letter : ARRAY OF CHAR); VAR nstr : ARRAY 2 OF CHAR; cmd : ARRAY 7 OF CHAR; BEGIN IntToStr (n, nstr); COPY(CSI, cmd); Strings.Append (nstr, cmd); Strings.Append (letter, cmd); Console.String (cmd); END EscSeq; PROCEDURE EscSeqSwapped (n : INTEGER; letter : ARRAY OF CHAR); VAR nstr : ARRAY 2 OF CHAR; cmd : ARRAY 7 OF CHAR; BEGIN IntToStr (n, nstr); COPY(CSI, cmd); Strings.Append (letter, cmd); Strings.Append (nstr, cmd); Console.String (cmd); END EscSeqSwapped; PROCEDURE EscSeq2(n, m : INTEGER; letter : ARRAY OF CHAR); VAR nstr, mstr : ARRAY 5 OF CHAR; cmd : ARRAY 12 OF CHAR; BEGIN IntToStr(n, nstr); IntToStr(m, mstr); COPY (CSI, cmd); Strings.Append (nstr, cmd); Strings.Append (';', cmd); Strings.Append (mstr, cmd); Strings.Append (letter, cmd); Console.String (cmd); END EscSeq2; (* Cursor up moves cursor n cells in the given direction. if the cursor is already at the edge of the screen, this has no effect *) PROCEDURE CUU*(n : INTEGER); BEGIN EscSeq (n, 'A'); END CUU; (* Cursor down moves cursor n cells in the given direction. if the cursor is already at the edge of the screen, this has no effect *) PROCEDURE CUD*(n : INTEGER); BEGIN EscSeq (n, 'B'); END CUD; (* Cursor forward moves cursor n cells in the given direction. if the cursor is already at the edge of the screen, this has no effect *) PROCEDURE CUF*(n : INTEGER); BEGIN EscSeq (n, 'C'); END CUF; (* Cursor back moves cursor n cells in the given direction. if the cursor is already at the edge of the screen, this has no effect *) PROCEDURE CUB*(n : INTEGER); BEGIN EscSeq (n, 'D'); END CUB; (* Curnser Next Line moves cursor to beginning of the line n lines down *) PROCEDURE CNL*( n: INTEGER); BEGIN EscSeq (n, 'E'); END CNL; (* Cursor Previous Line Moves cursor to beginning of the line n lines down *) PROCEDURE CPL*( n : INTEGER); BEGIN EscSeq (n, 'F'); END CPL; (* Cursor Horizontal Absolute Moves the cursor to column n *) PROCEDURE CHA*( n : INTEGER); BEGIN EscSeq (n, 'G'); END CHA; (* Cursor position, moves cursor to row n, column m *) PROCEDURE CUP*(n, m : INTEGER); BEGIN EscSeq2 (n, m, 'H'); END CUP; (* Erase Display if n = 0 then clears from cursor to end of the screen if n = 1 then clears from cursor to beginning of the screen if n = 2 then clears entire screen *) PROCEDURE ED* (n : INTEGER); BEGIN EscSeq(n, 'J'); END ED; (* Erase in Line Erases part of the line. If n is zero, clear from cursor to the end of the line. If n is one, clear from cursor to beginning of the line. If n is two, clear entire line. Cursor position does not change *) PROCEDURE EL*( n : INTEGER); BEGIN EscSeq(n, 'K'); END EL; (* Scroll Up Scroll whole page up by n lines. New lines are added at the bottom *) PROCEDURE SU*( n : INTEGER); BEGIN EscSeq(n, 'S') END SU; (* Scroll Down Scroll whole page down by n (default 1) lines. New lines are added at the top *) PROCEDURE SD*( n : INTEGER); BEGIN EscSeq(n, 'T'); END SD; (* Horizontal and Vertical Position, Moves the cursor to row n, column m. Both default to 1 if omitted. Same as CUP *) PROCEDURE HVP*(n, m : INTEGER); BEGIN EscSeq2 (n, m, 'f'); END HVP; (* Select Graphic Rendition Sets SGR parameters, including text color. After CSI can be zero or more parameters separated with ;. With no parameters, CSI m is treated as CSI 0 m (reset / normal), which is typical of most of the ANSI escape sequences *) PROCEDURE SGR*( n : INTEGER); BEGIN EscSeq(n, 'm'); END SGR; PROCEDURE SGR2*( n, m : INTEGER); BEGIN EscSeq2(n, m, 'm'); END SGR2; (* Device Status Report Reports the cursor position (CPR) to the application as (as though typed at the keyboard) ESC[n;mR, where n is the row and m is the column.) *) PROCEDURE DSR*(n : INTEGER); BEGIN EscSeq(6, 'n'); END DSR; (* Save Cursor Position *) PROCEDURE SCP*; BEGIN EscSeq0('s'); END SCP; (* Restore Cursor Position *) PROCEDURE RCP*; BEGIN EscSeq0('u'); END RCP; (* Hide the cursor *) PROCEDURE DECTCEMl*; BEGIN EscSeq0("?25l") END DECTCEMl; (* shows the cursor *) PROCEDURE DECTCEMh*; BEGIN EscSeq0("?25h") END DECTCEMh; PROCEDURE SetAttr*(attr : ARRAY OF CHAR); VAR tmpstr : ARRAY 16 OF CHAR; BEGIN COPY(CSI, tmpstr); Strings.Append(attr, tmpstr); Console.String(tmpstr); END SetAttr; BEGIN (* init CSI sequence *) COPY(Escape, CSI); Strings.Append(LeftCrotchet, CSI); (* EraseDisplay; GotoXY (0, 0); COPY(CSI, tmpstr); Strings.Append(Green, tmpstr); Strings.Append("hello", tmpstr); Console.String(tmpstr); Console.Ln; *) END vt100.