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 }