MODULE Tp3Cfg ; (* The terminal CONFIGURATOR - the TINST role, without the binary patch. TINST installs terminal escape sequences by writing them into TURBO.COM. This program writes a TEXT file, TP3.TRM, that the shell reads at startup (TermCfg.Load). Nothing here touches tpshell: edit the file by hand, copy it, version it, generate it - the shell will read whatever is there. Usage: tp3cfg list the terminals, pick one, write TP3.TRM (The sequence table below is the place to add a terminal: one Build case, one NumTerms increment. A CLI with --list/--show is a later convenience; the file it writes is plain text and can be edited or copied by hand.) The sequences are entered here as readable text and DECODED by TermCfg, so the emitted file contains the same `\e...' spelling a person can edit. *) FROM Posix IMPORT read, write, open, close ; FROM SYSTEM IMPORT ADR ; FROM TermCfg IMPORT Cfg, Default, ParseValue ; CONST STDOUT = 1 ; NumTerms = 3 ; VAR terms : ARRAY [0..NumTerms - 1] OF Cfg ; nout : LONGINT ; chbuf : CHAR ; outFd : INTEGER ; (* STDOUT normally, the file while writing it *) PROCEDURE NL ; BEGIN chbuf := CHR (10) ; nout := write (outFd, ADR (chbuf), 1) END NL ; PROCEDURE Out (s : ARRAY OF CHAR) ; VAR i : CARDINAL ; BEGIN i := 0 ; WHILE (i <= HIGH (s)) AND (s [i] # 0C) DO chbuf := s [i] ; nout := write (outFd, ADR (chbuf), 1) ; INC (i) END END Out ; PROCEDURE OutCh (ch : CHAR) ; BEGIN chbuf := ch ; nout := write (outFd, ADR (chbuf), 1) END OutCh ; PROCEDURE Copy (VAR dst : ARRAY OF CHAR ; src : ARRAY OF CHAR) ; VAR i : CARDINAL ; BEGIN i := 0 ; WHILE (i <= HIGH (dst)) AND (i <= HIGH (src)) AND (src [i] # 0C) DO dst [i] := src [i] ; INC (i) END ; IF i <= HIGH (dst) THEN dst [i] := 0C END END Copy ; PROCEDURE Build (i : CARDINAL ; VAR c : Cfg) ; BEGIN Default (c) ; IF i = 0 THEN Copy (c.name, "ANSI") (* ANSI is the default in TermCfg *) ELSIF i = 1 THEN Copy (c.name, "VT100") (* VT100 is ANSI-compatible for everything the shell emits *) ELSE Copy (c.name, "VT52") ; ParseValue ("\eH\eJ", c.clear) ; ParseValue ("\eH", c.home) ; ParseValue ("\eY%R%C", c.moveTo) ; ParseValue ("\eA", c.normal) ; ParseValue ("\eB", c.marked) ; ParseValue ("^G", c.beep) END END Build ; PROCEDURE Init ; VAR i : CARDINAL ; BEGIN i := 0 ; WHILE i < NumTerms DO Build (i, terms [i]) ; INC (i) END END Init ; PROCEDURE Find (name : ARRAY OF CHAR) : CARDINAL ; (* 0..NumTerms-1, or NumTerms when not found *) VAR i : CARDINAL ; BEGIN i := 0 ; WHILE i < NumTerms DO IF NameEq (terms [i].name, name) THEN RETURN i END ; INC (i) END ; RETURN NumTerms END Find ; PROCEDURE NameEq (a, b : ARRAY OF CHAR) : BOOLEAN ; VAR i : CARDINAL ; ca, cb : CHAR ; BEGIN i := 0 ; LOOP IF (i > HIGH (a)) OR (i > HIGH (b)) THEN RETURN FALSE END ; ca := a [i] ; cb := b [i] ; IF (ca >= 'a') AND (ca <= 'z') THEN ca := CHR (ORD (ca) - 32) END ; IF (cb >= 'a') AND (cb <= 'z') THEN cb := CHR (ORD (cb) - 32) END ; IF ca # cb THEN RETURN FALSE END ; IF ca = 0C THEN RETURN TRUE END ; INC (i) END END NameEq ; PROCEDURE EncCh (ch : CHAR) ; (* the inverse of TermCfg.Decode, so the file stays readable *) VAR o : CARDINAL ; BEGIN o := ORD (ch) ; IF o = 27 THEN Out ("\e") ELSIF o = 13 THEN Out ("\r") ELSIF o = 10 THEN NL ELSIF o = 9 THEN Out ("\t") ELSIF o = 92 THEN Out ("\\") ELSIF (o > 0) AND (o < 27) THEN Out ("^") ; OutCh (CHR (o + 64)) ELSE OutCh (ch) END END EncCh ; PROCEDURE Enc (label : ARRAY OF CHAR ; s : ARRAY OF CHAR) ; VAR i : CARDINAL ; BEGIN Out (label) ; Out ("=") ; i := 0 ; WHILE (i <= HIGH (s)) AND (s [i] # 0C) DO EncCh (s [i]) ; INC (i) END ; NL END Enc ; PROCEDURE WriteCfg (path : ARRAY OF CHAR ; c : Cfg) : BOOLEAN ; VAR fd : INTEGER ; BEGIN fd := open (ADR (path), 0241H, 420) ; (* O_WRONLY|O_CREAT|O_TRUNC, 0644 *) IF fd < 0 THEN Out ("tp3cfg: cannot write ") ; Out (path) ; NL ; RETURN FALSE END ; outFd := fd ; Out ("; TP3 terminal configuration - written by tp3cfg") ; NL ; Out ("; the shell reads it as TP3.TRM; edit freely") ; NL ; Enc ("NAME", c.name) ; Enc ("CLEAR", c.clear) ; Enc ("HOME", c.home) ; Enc ("GOTO", c.moveTo) ; Enc ("NORMAL", c.normal) ; Enc ("MARKED", c.marked) ; Enc ("BEEP", c.beep) ; outFd := STDOUT ; nout := close (fd) ; RETURN TRUE END WriteCfg ; PROCEDURE Show (i : CARDINAL) ; BEGIN Out ("NAME=") ; Out (terms [i].name) ; NL ; Enc ("CLEAR", terms [i].clear) ; Enc ("HOME", terms [i].home) ; Enc ("GOTO", terms [i].moveTo) ; Enc ("NORMAL", terms [i].normal) ; Enc ("MARKED", terms [i].marked) ; Enc ("BEEP", terms [i].beep) END Show ; (* ------------------------------------------------------------------ main *) PROCEDURE Main ; VAR i : CARDINAL ; pick : ARRAY [0..31] OF CHAR ; line : ARRAY [0..127] OF CHAR ; n : LONGINT ; k : CARDINAL ; BEGIN Init ; Out ("Terminals:") ; NL ; i := 0 ; WHILE i < NumTerms DO Out (" ") ; Out (terms [i].name) ; NL ; INC (i) END ; Out ("Write which one to TP3.TRM? ") ; k := 0 ; LOOP n := read (0, ADR (chbuf), 1) ; IF (n # 1) OR (chbuf = CHR (10)) OR (chbuf = CHR (13)) THEN EXIT END ; IF k <= HIGH (line) THEN line [k] := chbuf ; INC (k) END END ; line [k] := 0C ; i := Find (line) ; IF i = NumTerms THEN Out ("unknown terminal") ; NL ELSE IF WriteCfg ("TP3.TRM", terms [i]) THEN Out ("wrote TP3.TRM (") ; Out (terms [i].name) ; Out (")") ; NL END END END Main ; BEGIN outFd := STDOUT ; Main END Tp3Cfg.