ref: 738a6ef63e019cfd6262b4418f5aa9d8c7c3a1d9
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; }