diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b4723b5 --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +SYSTEM_LIBRARY_SUBPATH:=compiled/native/$(shell racket -e '(display (path->string (system-library-subpath)))') + +all: $(SYSTEM_LIBRARY_SUBPATH)/tty-raw-extension.so + +clean: + rm -rf compiled + +$(SYSTEM_LIBRARY_SUBPATH): + mkdir -p $@ + +$(SYSTEM_LIBRARY_SUBPATH)/%.so: %.c $(SYSTEM_LIBRARY_SUBPATH) + mzc --xform $*.c + mzc --3m --cc $*.3m.c + mzc --3m --ld $@ $*_3m.o + rm -f $*.3m.c + rm -f $*_3m.o diff --git a/test-raw.rkt b/test-raw.rkt new file mode 100644 index 0000000..1fe48da --- /dev/null +++ b/test-raw.rkt @@ -0,0 +1,15 @@ +#lang racket/base + +(require "tty-raw-extension") + +(define (main) + (tty-raw!) + (let loop () + (define ch (read-byte)) + (printf "Byte: ~v\015\012" ch) + ;;(flush-output) + (if (member ch '(4 8 127)) ;; EOF, C-h, DEL + (exit) + (loop)))) + +(main) diff --git a/tty-raw-extension.c b/tty-raw-extension.c new file mode 100644 index 0000000..5e613de --- /dev/null +++ b/tty-raw-extension.c @@ -0,0 +1,76 @@ +/* PLT Racket extension for selecting "raw" TTY mode */ + +#include "escheme.h" + +#include +#include +#include +#include +#include + +#define STDIN_FD 0 + +static int is_raw = 0; +static struct termios saved; + +static int ttyraw(void) { + /* Based on the settings given in http://www.minek.com/files/unix_examples/raw.html */ + struct termios t; + + if (is_raw) return 0; + + if (tcgetattr(STDIN_FD, &saved) < 0) return -1; + t = saved; + + t.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + t.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + t.c_cflag &= ~(CSIZE | PARENB); + t.c_cflag |= CS8; + t.c_oflag &= ~(OPOST); + t.c_cc[VMIN] = 1; + t.c_cc[VTIME] = 0; + + if (tcsetattr(STDIN_FD, TCSAFLUSH, &t) < 0) return -1; + + is_raw = 1; + return 0; +} + +static int ttyrestore(void) { + if (!is_raw) return 0; + + if (tcsetattr(STDIN_FD, TCSAFLUSH, &saved) < 0) return -1; + + is_raw = 0; + return 0; +} + +static Scheme_Object *sch_ttyraw(int argc, Scheme_Object **argv) { + return ttyraw() == 0 ? scheme_true : scheme_false; +} + +static Scheme_Object *sch_ttyrestore(int argc, Scheme_Object **argv) { + return ttyrestore() == 0 ? scheme_true : scheme_false; +} + +Scheme_Object *scheme_reload(Scheme_Env *env) { + Scheme_Env *mod_env; + mod_env = scheme_primitive_module(scheme_intern_symbol("tty-raw-extension"), env); + scheme_add_global("tty-raw!", + scheme_make_prim_w_arity(sch_ttyraw, "tty-raw!", 0, 0), + mod_env); + scheme_add_global("tty-restore!", + scheme_make_prim_w_arity(sch_ttyrestore, "tty-restore!", 0, 0), + mod_env); + scheme_finish_primitive_module(mod_env); + return scheme_void; +} + +Scheme_Object *scheme_initialize(Scheme_Env *env) { + atexit(ttyrestore); + return scheme_reload(env); +} + +Scheme_Object *scheme_module_name(void) { + return scheme_intern_symbol("tty-raw-extension"); +}