Files
ueforth/posix/termios.fs
Brad Nelson eaa8a3c4c3 Made posix terminal IO avoid spin looping.
Using raw mode + delay in the right places to
allow tasks to work while also supporting key?
2024-02-24 12:10:47 -08:00

94 lines
2.3 KiB
Forth

\ Copyright 2021 Bradley D. Nelson
\
\ Licensed under the Apache License, Version 2.0 (the "License");
\ you may not use this file except in compliance with the License.
\ You may obtain a copy of the License at
\
\ http://www.apache.org/licenses/LICENSE-2.0
\
\ Unless required by applicable law or agreed to in writing, software
\ distributed under the License is distributed on an "AS IS" BASIS,
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\ See the License for the specific language governing permissions and
\ limitations under the License.
( Terminal Handling )
vocabulary termios termios definitions also posix
z" tcgetattr" 2 sysfunc tcgetattr
z" tcsetattr" 3 sysfunc tcsetattr
z" ioctl" 3 sysfunc ioctl
( Blocking )
: nodelay-mode stdin F_SETFL FNDELAY fcntl throw ;
: delay-mode stdin F_SETFL 0 fcntl throw ;
( Raw Mode )
4 16 * 20 + constant sizeof(termios)
create old-termios sizeof(termios) allot
create new-termios sizeof(termios) allot
: .c_lflag 3 4 * + ;
: .c_cc[] 4 4 * + + ;
2 constant ICANON
8 constant _ECHO
2 constant TCSAFLUSH
5 constant VTIME
6 constant VMIN
: termios@ ( a -- ) stdin swap tcgetattr drop ;
: termios! ( a -- ) stdin TCSAFLUSH rot tcsetattr throw ;
old-termios termios@
: raw-mode stdin isatty 0= if exit then
new-termios termios@
_ECHO ICANON or invert new-termios .c_lflag sl@ and new-termios .c_lflag l!
0 VTIME new-termios .c_cc[] c!
0 VMIN new-termios .c_cc[] c!
new-termios termios! ;
: normal-mode stdin isatty 0= if exit then
old-termios termios! ;
( Screen Size )
$5413 constant TIOCGWINSZ
4 2 * constant sizeof(winsize)
create winsize sizeof(winsize) allot
: form ( -- h w ) stdin TIOCGWINSZ winsize ioctl throw
winsize sl@ dup $ffff and swap $10000 / ;
0 value pending
: termios-key? ( -- f )
pending if
-1
else
nodelay-mode
stdin-key to pending
pending 0<>
then
;
: termios-key ( -- n )
begin termios-key? 0= while
pause? if
pause
else
delay-mode
stdin-key to pending
then
repeat
pending 0 to pending
;
raw-mode
: termios-terminate ( n -- )
normal-mode
sysexit
;
' termios-key is key
' termios-key? is key?
' termios-terminate is terminate
forth definitions
: form form ;
only forth definitions