jim

Simple, lightweight, modal, vim-inspired text editor
git clone git://git.janpasierb.com/jim.git
Log | Files | Refs | README | LICENSE

term.c (2529B)


      1 #include"term.h"
      2 #include"jim.h"
      3 #include"output.h"
      4 #include<unistd.h>
      5 #include<stdlib.h>
      6 #include<stdio.h>
      7 #include<errno.h>
      8 #include<sys/ioctl.h>
      9 
     10 #define CLEAR_SCRN 		"\x1b[2J"
     11 #define CURSOR_FWD_DOWN "\x1B[999C\x1B[999B"
     12 #define TERM_STAT_INFO  "\x1B[6n"
     13 
     14 void editorClearAndResetScreen() {
     15     write(STDOUT_FILENO, CLEAR_SCRN, 4);
     16     write(STDOUT_FILENO, CURSOR_TOP, 3);
     17 }
     18 
     19 void die(const char* s) {
     20     editorClearAndResetScreen();
     21 
     22     perror(s);
     23     exit(1);
     24 }
     25 
     26 void disableRawMode() {
     27     if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &E.orig_termios) == -1)
     28         die("tcsetattr");
     29 }
     30 
     31 void enableRawMode() {
     32     if(tcgetattr(STDIN_FILENO, &E.orig_termios) == -1) die("tcgetattr");
     33     atexit(disableRawMode);
     34 
     35     struct termios raw = E.orig_termios;
     36     raw.c_iflag &= ~(ICRNL | IXON | BRKINT | INPCK | ISTRIP);
     37     raw.c_oflag &= ~(OPOST);
     38     raw.c_cflag |= (CS8);
     39     raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
     40     raw.c_cc[VMIN] = 0;
     41     raw.c_cc[VTIME] = 1;
     42 
     43     if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) die("tcsetattr");
     44 }
     45 
     46 char editorReadKey() {
     47     int nread;
     48     char c;
     49 
     50     while((nread = read(STDIN_FILENO, &c, 1)) != 1) {
     51         if(nread == -1 && errno != EAGAIN) die("read");
     52 
     53         if(getWindowSize(&E.screenrows, &E.screencols) == -1) die("getWindowSize");
     54         E.screenrows--;
     55         editorRefreshScreen();
     56     }
     57 
     58     if(c == ESCAPE) {
     59         char seq[2];
     60 
     61         if(read(STDIN_FILENO, &seq[0], 1) != 1) return ESCAPE;
     62         if(read(STDIN_FILENO, &seq[1], 1) != 1) return ESCAPE;
     63 
     64         if(seq[0] == '[') {
     65             switch(seq[1]) {
     66                 case 'P':
     67                     return DEL;
     68             }
     69         }
     70 
     71         return ESCAPE;
     72     } else {
     73         return c;
     74     }
     75 }
     76 
     77 int getCursorPosition(int* rows, int* cols) {
     78     char buf[32];
     79     unsigned int i = 0;
     80 
     81     if(write(STDOUT_FILENO, TERM_STAT_INFO, 4) != 4) return -1;
     82 
     83     while(i < sizeof(buf) - 1) {
     84         if(read(STDIN_FILENO, &buf[i], 1) != 1) break;
     85         if(buf[i] == 'R') break;
     86         i++;
     87     }
     88 
     89     buf[i] = '\0';
     90 
     91     if(buf[0] != ESCAPE || buf[1] != '[') return -1;
     92     if(sscanf(&buf[2], "%d;%d", rows, cols) != 2) return -1;
     93 
     94     return 0;
     95 }
     96 
     97 int getWindowSize(int* rows, int* cols) {
     98     struct winsize ws;
     99 
    100     if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {
    101         if(write(STDOUT_FILENO, CURSOR_FWD_DOWN, 12) != 12) return -1;
    102         return getCursorPosition(rows, cols);
    103     } else {
    104         *cols = ws.ws_col;
    105         *rows = ws.ws_row;
    106         return 0;
    107     }
    108 }