teleray.sl 7.6 KB

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