Re: A problem with read-char



Pascal Bourguignon <pjb@xxxxxxxxxxxxxxxxx> wrote:
+---------------
| meta.person@xxxxxxxxx writes:
| > Is it possible to make read-char behave like getch in С when working
| > with interactive stream (*standard-input*)?
....
| No. It is not possible.
|
| That is, it's not possible with COMMON-LISP:READ-CHAR and neither with
| COMMON-LISP:READ-CHAR-NO-HANG.
....
| The difference is that curses puts the terminal in raw mode to be able
| to receive the characters from the keyboard one at a time, instead of
| leaving the terminal in cooked mode, where the unix driver bufferize
| lines and handles backspace, amongst other niceties.
|
| Now, I don't know about SBCL, (check the manual of SBCL). I only have
| the Implementation Notes of CLISP loaded in my wetware. In CLISP you
| can use the EXT:WITH-KEYBOARD macro (while the basic output features
| of curses are provided by the SCREEN package).
+---------------

If it helps, "meta.person", I once wrote the following for CMUCL
for an application that wanted to be able to type a single character
response to a prompt without messing up the terminal screen:

(use-package :alien)
(use-package :unix)
...
(defun read-char-no-echo-cbreak (&optional (stream *query-io*))
(with-alien ((old (struct termios))
(new (struct termios)))
(let ((e0 (unix-tcgetattr 0 old))
(e1 (unix-tcgetattr 0 new))
(bits (logior tty-icanon tty-echo tty-echoe
tty-echok tty-echonl)))
(declare (ignorable e0 e1)) ;[probably should test for error here]
(unwind-protect
(progn
(setf (slot new 'c-lflag) (logandc2 (slot old 'c-lflag) bits))
(setf (deref (slot new 'c-cc) vmin) 1)
(setf (deref (slot new 'c-cc) vtime) 0)
(unix-tcsetattr 0 tcsadrain new)
(read-char stream))
(unix-tcsetattr 0 tcsadrain old)))))

SBCL has probably diverged considerably from CMUCL in this area,
but something similar should be doable with SBCL. Start by looking
in the SB-UNIX or maybe the SB-POSIX packages...


-Rob

-----
Rob Warnock <rpw3@xxxxxxxx>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

.