Tp3Cfg.mod 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. MODULE Tp3Cfg ;
  2. (* The terminal CONFIGURATOR - the TINST role, without the binary patch.
  3. TINST installs terminal escape sequences by writing them into TURBO.COM.
  4. This program writes a TEXT file, TP3.TRM, that the shell reads at startup
  5. (TermCfg.Load). Nothing here touches tpshell: edit the file by hand, copy
  6. it, version it, generate it - the shell will read whatever is there.
  7. Usage:
  8. tp3cfg list the terminals, pick one, write TP3.TRM
  9. (The sequence table below is the place to add a terminal: one Build case,
  10. one NumTerms increment. A CLI with --list/--show is a later convenience;
  11. the file it writes is plain text and can be edited or copied by hand.)
  12. The sequences are entered here as readable text and DECODED by TermCfg, so
  13. the emitted file contains the same `\e...' spelling a person can edit. *)
  14. FROM Posix IMPORT read, write, open, close ;
  15. FROM SYSTEM IMPORT ADR ;
  16. FROM TermCfg IMPORT Cfg, Default, ParseValue ;
  17. CONST
  18. STDOUT = 1 ;
  19. NumTerms = 3 ;
  20. VAR
  21. terms : ARRAY [0..NumTerms - 1] OF Cfg ;
  22. nout : LONGINT ;
  23. chbuf : CHAR ;
  24. outFd : INTEGER ; (* STDOUT normally, the file while writing it *)
  25. PROCEDURE NL ;
  26. BEGIN
  27. chbuf := CHR (10) ;
  28. nout := write (outFd, ADR (chbuf), 1)
  29. END NL ;
  30. PROCEDURE Out (s : ARRAY OF CHAR) ;
  31. VAR i : CARDINAL ;
  32. BEGIN
  33. i := 0 ;
  34. WHILE (i <= HIGH (s)) AND (s [i] # 0C) DO
  35. chbuf := s [i] ;
  36. nout := write (outFd, ADR (chbuf), 1) ;
  37. INC (i)
  38. END
  39. END Out ;
  40. PROCEDURE OutCh (ch : CHAR) ;
  41. BEGIN
  42. chbuf := ch ;
  43. nout := write (outFd, ADR (chbuf), 1)
  44. END OutCh ;
  45. PROCEDURE Copy (VAR dst : ARRAY OF CHAR ; src : ARRAY OF CHAR) ;
  46. VAR i : CARDINAL ;
  47. BEGIN
  48. i := 0 ;
  49. WHILE (i <= HIGH (dst)) AND (i <= HIGH (src)) AND (src [i] # 0C) DO
  50. dst [i] := src [i] ;
  51. INC (i)
  52. END ;
  53. IF i <= HIGH (dst) THEN
  54. dst [i] := 0C
  55. END
  56. END Copy ;
  57. PROCEDURE Build (i : CARDINAL ; VAR c : Cfg) ;
  58. BEGIN
  59. Default (c) ;
  60. IF i = 0 THEN
  61. Copy (c.name, "ANSI")
  62. (* ANSI is the default in TermCfg *)
  63. ELSIF i = 1 THEN
  64. Copy (c.name, "VT100")
  65. (* VT100 is ANSI-compatible for everything the shell emits *)
  66. ELSE
  67. Copy (c.name, "VT52") ;
  68. ParseValue ("\eH\eJ", c.clear) ;
  69. ParseValue ("\eH", c.home) ;
  70. ParseValue ("\eY%R%C", c.moveTo) ;
  71. ParseValue ("\eA", c.normal) ;
  72. ParseValue ("\eB", c.marked) ;
  73. ParseValue ("^G", c.beep)
  74. END
  75. END Build ;
  76. PROCEDURE Init ;
  77. VAR i : CARDINAL ;
  78. BEGIN
  79. i := 0 ;
  80. WHILE i < NumTerms DO
  81. Build (i, terms [i]) ;
  82. INC (i)
  83. END
  84. END Init ;
  85. PROCEDURE Find (name : ARRAY OF CHAR) : CARDINAL ;
  86. (* 0..NumTerms-1, or NumTerms when not found *)
  87. VAR i : CARDINAL ;
  88. BEGIN
  89. i := 0 ;
  90. WHILE i < NumTerms DO
  91. IF NameEq (terms [i].name, name) THEN
  92. RETURN i
  93. END ;
  94. INC (i)
  95. END ;
  96. RETURN NumTerms
  97. END Find ;
  98. PROCEDURE NameEq (a, b : ARRAY OF CHAR) : BOOLEAN ;
  99. VAR i : CARDINAL ; ca, cb : CHAR ;
  100. BEGIN
  101. i := 0 ;
  102. LOOP
  103. IF (i > HIGH (a)) OR (i > HIGH (b)) THEN
  104. RETURN FALSE
  105. END ;
  106. ca := a [i] ; cb := b [i] ;
  107. IF (ca >= 'a') AND (ca <= 'z') THEN ca := CHR (ORD (ca) - 32) END ;
  108. IF (cb >= 'a') AND (cb <= 'z') THEN cb := CHR (ORD (cb) - 32) END ;
  109. IF ca # cb THEN
  110. RETURN FALSE
  111. END ;
  112. IF ca = 0C THEN
  113. RETURN TRUE
  114. END ;
  115. INC (i)
  116. END
  117. END NameEq ;
  118. PROCEDURE EncCh (ch : CHAR) ;
  119. (* the inverse of TermCfg.Decode, so the file stays readable *)
  120. VAR o : CARDINAL ;
  121. BEGIN
  122. o := ORD (ch) ;
  123. IF o = 27 THEN
  124. Out ("\e")
  125. ELSIF o = 13 THEN
  126. Out ("\r")
  127. ELSIF o = 10 THEN
  128. NL
  129. ELSIF o = 9 THEN
  130. Out ("\t")
  131. ELSIF o = 92 THEN
  132. Out ("\\")
  133. ELSIF (o > 0) AND (o < 27) THEN
  134. Out ("^") ;
  135. OutCh (CHR (o + 64))
  136. ELSE
  137. OutCh (ch)
  138. END
  139. END EncCh ;
  140. PROCEDURE Enc (label : ARRAY OF CHAR ; s : ARRAY OF CHAR) ;
  141. VAR i : CARDINAL ;
  142. BEGIN
  143. Out (label) ;
  144. Out ("=") ;
  145. i := 0 ;
  146. WHILE (i <= HIGH (s)) AND (s [i] # 0C) DO
  147. EncCh (s [i]) ;
  148. INC (i)
  149. END ;
  150. NL
  151. END Enc ;
  152. PROCEDURE WriteCfg (path : ARRAY OF CHAR ; c : Cfg) : BOOLEAN ;
  153. VAR fd : INTEGER ;
  154. BEGIN
  155. fd := open (ADR (path), 0241H, 420) ; (* O_WRONLY|O_CREAT|O_TRUNC, 0644 *)
  156. IF fd < 0 THEN
  157. Out ("tp3cfg: cannot write ") ; Out (path) ; NL ;
  158. RETURN FALSE
  159. END ;
  160. outFd := fd ;
  161. Out ("; TP3 terminal configuration - written by tp3cfg") ; NL ;
  162. Out ("; the shell reads it as TP3.TRM; edit freely") ; NL ;
  163. Enc ("NAME", c.name) ;
  164. Enc ("CLEAR", c.clear) ;
  165. Enc ("HOME", c.home) ;
  166. Enc ("GOTO", c.moveTo) ;
  167. Enc ("NORMAL", c.normal) ;
  168. Enc ("MARKED", c.marked) ;
  169. Enc ("BEEP", c.beep) ;
  170. outFd := STDOUT ;
  171. nout := close (fd) ;
  172. RETURN TRUE
  173. END WriteCfg ;
  174. PROCEDURE Show (i : CARDINAL) ;
  175. BEGIN
  176. Out ("NAME=") ; Out (terms [i].name) ; NL ;
  177. Enc ("CLEAR", terms [i].clear) ;
  178. Enc ("HOME", terms [i].home) ;
  179. Enc ("GOTO", terms [i].moveTo) ;
  180. Enc ("NORMAL", terms [i].normal) ;
  181. Enc ("MARKED", terms [i].marked) ;
  182. Enc ("BEEP", terms [i].beep)
  183. END Show ;
  184. (* ------------------------------------------------------------------ main *)
  185. PROCEDURE Main ;
  186. VAR i : CARDINAL ;
  187. pick : ARRAY [0..31] OF CHAR ;
  188. line : ARRAY [0..127] OF CHAR ;
  189. n : LONGINT ;
  190. k : CARDINAL ;
  191. BEGIN
  192. Init ;
  193. Out ("Terminals:") ;
  194. NL ;
  195. i := 0 ;
  196. WHILE i < NumTerms DO
  197. Out (" ") ; Out (terms [i].name) ; NL ;
  198. INC (i)
  199. END ;
  200. Out ("Write which one to TP3.TRM? ") ;
  201. k := 0 ;
  202. LOOP
  203. n := read (0, ADR (chbuf), 1) ;
  204. IF (n # 1) OR (chbuf = CHR (10)) OR (chbuf = CHR (13)) THEN
  205. EXIT
  206. END ;
  207. IF k <= HIGH (line) THEN
  208. line [k] := chbuf ;
  209. INC (k)
  210. END
  211. END ;
  212. line [k] := 0C ;
  213. i := Find (line) ;
  214. IF i = NumTerms THEN
  215. Out ("unknown terminal") ; NL
  216. ELSE
  217. IF WriteCfg ("TP3.TRM", terms [i]) THEN
  218. Out ("wrote TP3.TRM (") ; Out (terms [i].name) ; Out (")") ; NL
  219. END
  220. END
  221. END Main ;
  222. BEGIN
  223. outFd := STDOUT ;
  224. Main
  225. END Tp3Cfg.