ref: 7f66c7fdabc180c1f1c44cc5e3a8741a9ebae125
dir: /terminal_posix.c/
#include "llt.h"
#include "flisp.h"
#include <sys/ioctl.h>
#include <termios.h>
static bool inraw = false;
static struct termios tios;
static int
termsetraw(bool raw)
{
if(raw && !inraw){
if(tcgetattr(STDIN_FILENO, &tios) < 0)
return -1;
struct termios t;
memcpy(&t, &tios, sizeof(t));
t.c_iflag &= ~(BRKINT | ICRNL | IXON);
t.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
t.c_oflag &= ~(OPOST);
t.c_cc[VMIN] = 0;
if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t) < 0)
return -1;
inraw = true;
}else if(!raw && inraw){
if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &tios) < 0)
return -1;
inraw = false;
}
return 0;
}
BUILTIN("terminal-enter-raw-mode", terminal_enter_raw_mode)
{
USED(args);
argcount(nargs, 0);
return termsetraw(true) == 0 ? FL_T : FL_F;
}
BUILTIN("terminal-leave-raw-mode", terminal_leave_raw_mode)
{
USED(args);
argcount(nargs, 0);
return termsetraw(false) == 0 ? FL_T : FL_F;
}
BUILTIN("terminal-get-size", terminal_get_size)
{
USED(args);
argcount(nargs, 0);
struct winsize s;
if(ioctl(STDIN_FILENO, TIOCGWINSZ, &s) < 0)
return FL_F;
value_t v = mk_cons(), tex, pix;
car_(v) = tex = mk_cons();
car_(tex) = fixnum(s.ws_col);
cdr_(tex) = mk_cons(); car_(cdr_(tex)) = fixnum(s.ws_row); cdr_(cdr_(tex)) = NIL;
int x = s.ws_xpixel, y = s.ws_ypixel;
bool wasraw = inraw;
if((x == 0 || y == 0) && isatty(STDOUT_FILENO) && termsetraw(true) == 0){
// FIXME(sigrid): read everything out of stdin first
write(STDOUT_FILENO, "\x1b[14t", 5);
/* make sure not to hang if nothing is returned */
struct timeval t;
t.tv_sec = 0;
t.tv_usec = 100;
fd_set f;
FD_ZERO(&f);
FD_SET(STDIN_FILENO, &f);
int r;
while((r = select(STDIN_FILENO+1, &f, nil, nil, &t)) == EINTR);
if(r > 0 && FD_ISSET(STDIN_FILENO, &f)){
char buf[64];
if((r = read(STDIN_FILENO, buf, sizeof(buf)-1)) >= 8){
buf[r] = 0;
if(buf[0] == 0x1b && buf[1] == '[' && buf[2] == '4' && buf[3] == ';'){ /* CSI 4 */
x = atoi(buf+5);
char *s = strchr(buf+5, ';');
if(s != nil)
y = atoi(s+1);
while(strchr(buf, 't') == nil){
if((r = read(STDIN_FILENO, buf, sizeof(buf)-1)) <= 0)
break;
buf[r] = 0;
}
}
}
}
if(!wasraw)
termsetraw(false);
}
cdr_(v) = pix = mk_cons(); cdr_(pix) = NIL;
car_(pix) = mk_cons(); pix = car_(pix);
car_(pix) = fixnum(x);
cdr_(pix) = mk_cons(); car_(cdr_(pix)) = fixnum(y); cdr_(cdr_(pix)) = NIL;
return v;
}