vt52x.sl 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2. %
  3. % VT52X.SL - Terminal Interface
  4. %
  5. % Author: Alan Snyder
  6. % Hewlett-Packard/CRC
  7. % Date: 6 October 1982
  8. %
  9. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  10. (BothTimes (load objects))
  11. (CompileTime (load display-char fast-int fast-vectors))
  12. (defflavor vt52x (
  13. (height 24) % number of rows (0 indexed)
  14. (maxrow 23) % highest numbered row
  15. (width 80) % number of columns (0 indexed)
  16. (maxcol 79) % highest numbered column
  17. (cursor-row 0) % cursor position
  18. (cursor-column 0) % cursor position
  19. (raw-mode NIL)
  20. (terminal-enhancement 0) % current enhancement (applies to most output)
  21. (terminal-blank #\space) % character used by ClearEOL
  22. )
  23. ()
  24. (gettable-instance-variables height width maxrow maxcol raw-mode)
  25. )
  26. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  27. (CompileTime
  28. (defmacro out-n (n)
  29. `(progn
  30. (if (> ,n 9)
  31. (PBOUT (+ (char 0) (/ ,n 10))))
  32. (PBOUT (+ (char 0) (// ,n 10))))))
  33. (CompileTime
  34. (defmacro out-char (ch)
  35. `(PBOUT (char ,ch))))
  36. (CompileTime
  37. (dm out-chars (form)
  38. (for (in ch (cdr form))
  39. (with L)
  40. (collect (list 'out-char ch) L)
  41. (returns (cons 'progn L)))))
  42. (CompileTime
  43. (defmacro out-move (row col)
  44. `(progn
  45. (out-chars ESC Y)
  46. (PBOUT (+ ,row 32))
  47. (PBOUT (+ ,col 32)))))
  48. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  49. (defmethod (vt52x get-character) ()
  50. (& (PBIN) 8#377)
  51. )
  52. (defmethod (vt52x ring-bell) ()
  53. (out-char BELL)
  54. )
  55. (defmethod (vt52x move-cursor) (row column)
  56. (cond ((< row 0) (setf row 0))
  57. ((>= row height) (setf row maxrow)))
  58. (cond ((< column 0) (setf column 0))
  59. ((>= column width) (setf column maxcol)))
  60. (cond ((and (= row cursor-row) (= column cursor-column))) % no action needed
  61. ((and (= row 0) (= column 0))
  62. (out-chars ESC H)) % cursor HOME
  63. ((= row cursor-row) % movement on current row
  64. (cond ((= column 0)
  65. (out-char CR)) % move to left margin
  66. ((= column (- cursor-column 1))
  67. (out-chars ESC D)) % move LEFT
  68. ((= column (+ cursor-column 1))
  69. (out-chars ESC C)) % move RIGHT
  70. (t (out-move row column))))
  71. ((= column cursor-column) % movement on same column
  72. (cond ((= row (- cursor-row 1))
  73. (out-chars ESC A)) % move UP
  74. ((= row (+ cursor-row 1))
  75. (out-char LF)) % move DOWN
  76. (t (out-move row column))))
  77. (t % arbitrary movement
  78. (out-move row column)))
  79. (setf cursor-row row)
  80. (setf cursor-column column)
  81. )
  82. (defmethod (vt52x enter-raw-mode) ()
  83. (when (not raw-mode)
  84. (EchoOff)
  85. % Enable Keypad?
  86. (setf raw-mode T)))
  87. (defmethod (vt52x leave-raw-mode) ()
  88. (when raw-mode
  89. (=> self &set-terminal-enhancement 0)
  90. (setf raw-mode NIL)
  91. % Disable Keypad?
  92. (EchoOn)))
  93. (defmethod (vt52x erase) ()
  94. % This method should be invoked to initialize the screen to a known state.
  95. (out-chars ESC H ESC J)
  96. (setf cursor-row 0)
  97. (setf cursor-column 0)
  98. (setf terminal-enhancement NIL) % force resetting when needed
  99. )
  100. (defmethod (vt52x clear-line) ()
  101. (out-chars ESC K)
  102. )
  103. (defmethod (vt52x convert-character) (ch)
  104. (setq ch (& ch (display-character-cons
  105. (dc-make-enhancement-mask INVERSE-VIDEO
  106. BLINK
  107. UNDERLINE
  108. INTENSIFY)
  109. (dc-make-font-mask 0)
  110. 16#FF)))
  111. (let ((code (dc-character-code ch)))
  112. (if (or (< code #\space) (= code (char rubout)))
  113. (setq ch #\space)))
  114. ch)
  115. (defmethod (vt52x normal-enhancement) ()
  116. (dc-make-enhancement-mask)
  117. )
  118. (defmethod (vt52x highlighted-enhancement) ()
  119. (dc-make-enhancement-mask INVERSE-VIDEO)
  120. )
  121. (defmethod (vt52x supported-enhancements) ()
  122. (dc-make-enhancement-mask INVERSE-VIDEO BLINK UNDERLINE INTENSIFY)
  123. )
  124. (defmethod (vt52x update-line) (row old-line new-line columns)
  125. % Old-Line is updated.
  126. (let ((first-col (car columns))
  127. (last-col (cdr columns))
  128. (last-nonblank-column NIL)
  129. )
  130. % Find out the minimal actual bounds:
  131. (while (and (<= first-col last-col)
  132. (= (vector-fetch new-line last-col)
  133. (vector-fetch old-line last-col)))
  134. (setf last-col (- last-col 1))
  135. )
  136. (while (and (<= first-col last-col)
  137. (= (vector-fetch new-line first-col)
  138. (vector-fetch old-line first-col)))
  139. (setf first-col (+ first-col 1))
  140. )
  141. % The purpose of the following code is to determine whether or not to use
  142. % ClearEOL. If we decide to use ClearEOL, then we will set the variable
  143. % LAST-NONBLANK-COLUMN to the obvious index; otherwise, we will set it to
  144. % NIL. If we decide to use ClearEOL, then we will clear out the OLD-LINE
  145. % now, but do the actual ClearEOL later.
  146. % Use of ClearEOL is appropriate if the rightmost changed character has
  147. % been changed to a space, and the remainder of the line is blank. It
  148. % is appropriate only if it replaces writing at least 3 blanks.
  149. (when (= (vector-fetch new-line last-col) terminal-blank)
  150. (setf last-nonblank-column (vector-upper-bound new-line))
  151. (while (and (>= last-nonblank-column 0)
  152. (= (vector-fetch new-line last-nonblank-column)
  153. terminal-blank)
  154. )
  155. (setf last-nonblank-column (- last-nonblank-column 1))
  156. )
  157. % We have computed the column containing the rightmost non-blank
  158. % character. Now, we can decide whether we want to do a ClearEOL or not.
  159. (if (and (< last-nonblank-column (- last-col 2)))
  160. % then
  161. (while (> last-col last-nonblank-column)
  162. (vector-store old-line last-col terminal-blank)
  163. (setf last-col (- last-col 1))
  164. )
  165. % else
  166. (setf last-nonblank-column NIL)
  167. ))
  168. % Output all changed characters (except those ClearEOL will do):
  169. (if (not (and (= cursor-row row) (<= cursor-column first-col)))
  170. (=> self move-cursor row first-col))
  171. % The VT52X will scroll if we write to the bottom right position.
  172. % This (hopefully temporary) hack will avoid writing there.
  173. (if (and (= row maxrow) (= last-col maxcol))
  174. (setf last-col (- maxcol 1))
  175. )
  176. (for (from col first-col last-col)
  177. (do
  178. (let ((old (vector-fetch old-line col))
  179. (new (vector-fetch new-line col))
  180. )
  181. (when (~= old new)
  182. (let ((new-enhancement (dc-enhancement-mask new))
  183. (new-code (dc-character-code new))
  184. )
  185. % Do we need to change the terminal enhancement?
  186. (if (~= terminal-enhancement new-enhancement)
  187. (=> self &set-terminal-enhancement new-enhancement)
  188. )
  189. (=> self &move-cursor-forward col old-line)
  190. (PBOUT new-code)
  191. (if (< cursor-column maxcol)
  192. (setf cursor-column (+ cursor-column 1))
  193. % otherwise
  194. % (pretend we don't know the cursor position...
  195. % the two versions of the emulator differ at this point!)
  196. (setf cursor-column 10000)
  197. (setf cursor-row 10000)
  198. )
  199. (vector-store old-line col new)
  200. )))))
  201. % Do the ClearEOL, if that's what we decided to do.
  202. (when last-nonblank-column
  203. (=> self &move-cursor-forward (+ last-nonblank-column 1) old-line)
  204. (=> self clear-line)
  205. )
  206. ))
  207. % The following methods are provided for INTERNAL use only!
  208. (defmethod (vt52x init) ()
  209. )
  210. (defmethod (vt52x &move-cursor-forward) (column line)
  211. (cond ((> (- column cursor-column) 4)
  212. (out-move cursor-row column)
  213. (setf cursor-column column))
  214. (t (while (< cursor-column column)
  215. (PBOUT (dc-character-code (vector-fetch line cursor-column)))
  216. (setf cursor-column (+ cursor-column 1))
  217. ))))
  218. (defmethod (vt52x &set-terminal-enhancement) (enh)
  219. (setf terminal-enhancement enh)
  220. (out-char ESC)
  221. (PBOUT 3)
  222. (PBOUT (dc-enhancement-index enh))
  223. )