term.c (3557B)
1 #include <poll.h> 2 #include <signal.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <sys/ioctl.h> 7 #include <termios.h> 8 #include <unistd.h> 9 #include "vi.h" 10 11 static struct sbuf *term_sbuf; 12 static int rows, cols; 13 static struct termios termios; 14 15 void term_init(void) 16 { 17 struct winsize win; 18 struct termios newtermios; 19 tcgetattr(0, &termios); 20 newtermios = termios; 21 newtermios.c_lflag &= ~(ICANON | ISIG); 22 newtermios.c_lflag &= ~ECHO; 23 tcsetattr(0, TCSAFLUSH, &newtermios); 24 if (getenv("LINES")) 25 rows = atoi(getenv("LINES")); 26 if (getenv("COLUMNS")) 27 cols = atoi(getenv("COLUMNS")); 28 if (!ioctl(0, TIOCGWINSZ, &win)) { 29 cols = win.ws_col; 30 rows = win.ws_row; 31 } 32 cols = cols ? cols : 80; 33 rows = rows ? rows : 25; 34 term_str("\33[m"); 35 } 36 37 void term_done(void) 38 { 39 term_commit(); 40 tcsetattr(0, 0, &termios); 41 } 42 43 void term_suspend(void) 44 { 45 term_done(); 46 kill(getpid(), SIGSTOP); 47 term_init(); 48 } 49 50 void term_record(void) 51 { 52 if (!term_sbuf) 53 term_sbuf = sbuf_make(); 54 } 55 56 void term_commit(void) 57 { 58 if (term_sbuf) { 59 write(1, sbuf_buf(term_sbuf), sbuf_len(term_sbuf)); 60 sbuf_free(term_sbuf); 61 term_sbuf = NULL; 62 } 63 } 64 65 static void term_out(char *s) 66 { 67 if (term_sbuf) 68 sbuf_str(term_sbuf, s); 69 else 70 write(1, s, strlen(s)); 71 } 72 73 void term_str(char *s) 74 { 75 term_out(s); 76 } 77 78 void term_chr(int ch) 79 { 80 char s[4] = {ch}; 81 term_out(s); 82 } 83 84 void term_kill(void) 85 { 86 term_out("\33[K"); 87 } 88 89 void term_room(int n) 90 { 91 char cmd[16]; 92 if (n < 0) 93 sprintf(cmd, "\33[%dM", -n); 94 if (n > 0) 95 sprintf(cmd, "\33[%dL", n); 96 if (n) 97 term_out(cmd); 98 } 99 100 void term_pos(int r, int c) 101 { 102 char buf[32] = "\r"; 103 if (c < 0) 104 c = 0; 105 if (c >= xcols) 106 c = cols - 1; 107 if (r < 0) 108 sprintf(buf, "\r\33[%d%c", abs(c), c > 0 ? 'C' : 'D'); 109 else 110 sprintf(buf, "\33[%d;%dH", r + 1, c + 1); 111 term_out(buf); 112 } 113 114 int term_rows(void) 115 { 116 return rows; 117 } 118 119 int term_cols(void) 120 { 121 return cols; 122 } 123 124 static char ibuf[4096]; /* input character buffer */ 125 static char icmd[4096]; /* read after the last term_cmd() */ 126 static int ibuf_pos, ibuf_cnt; /* ibuf[] position and length */ 127 static int icmd_pos; /* icmd[] position */ 128 129 /* read s before reading from the terminal */ 130 void term_push(char *s, int n) 131 { 132 n = MIN(n, sizeof(ibuf) - ibuf_cnt); 133 memcpy(ibuf + ibuf_cnt, s, n); 134 ibuf_cnt += n; 135 } 136 137 /* return a static buffer containing inputs read since the last term_cmd() */ 138 char *term_cmd(int *n) 139 { 140 *n = icmd_pos; 141 icmd_pos = 0; 142 return icmd; 143 } 144 145 int term_read(void) 146 { 147 struct pollfd ufds[1]; 148 int n, c; 149 if (ibuf_pos >= ibuf_cnt) { 150 ufds[0].fd = 0; 151 ufds[0].events = POLLIN; 152 if (poll(ufds, 1, -1) <= 0) 153 return -1; 154 /* read a single input character */ 155 if ((n = read(0, ibuf, 1)) <= 0) 156 return -1; 157 ibuf_cnt = n; 158 ibuf_pos = 0; 159 } 160 c = ibuf_pos < ibuf_cnt ? (unsigned char) ibuf[ibuf_pos++] : -1; 161 if (icmd_pos < sizeof(icmd)) 162 icmd[icmd_pos++] = c; 163 return c; 164 } 165 166 /* return a static string that changes text attributes from old to att */ 167 char *term_att(int att, int old) 168 { 169 static char buf[128]; 170 char *s = buf; 171 int fg = SYN_FG(att); 172 int bg = SYN_BG(att); 173 if (att == old) 174 return ""; 175 s += sprintf(s, "\33["); 176 if (att & SYN_BD) 177 s += sprintf(s, ";1"); 178 if (att & SYN_IT) 179 s += sprintf(s, ";3"); 180 else if (att & SYN_RV) 181 s += sprintf(s, ";7"); 182 if (SYN_FGSET(att)) { 183 if ((fg & 0xff) < 8) 184 s += sprintf(s, ";%d", 30 + (fg & 0xff)); 185 else 186 s += sprintf(s, ";38;5;%d", (fg & 0xff)); 187 } 188 if (SYN_BGSET(att)) { 189 if ((bg & 0xff) < 8) 190 s += sprintf(s, ";%d", 40 + (bg & 0xff)); 191 else 192 s += sprintf(s, ";48;5;%d", (bg & 0xff)); 193 } 194 s += sprintf(s, "m"); 195 return buf; 196 }