vi: repeat and execute commands
[neatvi.git] / term.c
blob769916f70f260a24fd9b6aef6c4d9cc2585d5b44
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"
11 static struct sbuf *term_sbuf;
12 static int rows, cols;
13 static struct termios termios;
15 void term_init(void)
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 = cols ? cols : win.ws_col;
30 rows = rows ? rows : win.ws_row;
32 cols = cols ? cols : 80;
33 rows = rows ? rows : 25;
36 void term_done(void)
38 term_commit();
39 tcsetattr(0, 0, &termios);
42 void term_suspend(void)
44 term_done();
45 kill(getpid(), SIGSTOP);
46 term_init();
49 void term_record(void)
51 if (!term_sbuf)
52 term_sbuf = sbuf_make();
55 void term_commit(void)
57 if (term_sbuf) {
58 write(1, sbuf_buf(term_sbuf), sbuf_len(term_sbuf));
59 sbuf_free(term_sbuf);
60 term_sbuf = NULL;
64 static void term_out(char *s)
66 if (term_sbuf)
67 sbuf_str(term_sbuf, s);
68 else
69 write(1, s, strlen(s));
72 void term_str(char *s)
74 term_out(s);
77 void term_chr(int ch)
79 char s[4] = {ch};
80 term_out(s);
83 void term_kill(void)
85 term_out("\33[K");
88 void term_pos(int r, int c)
90 char buf[32] = "\r";
91 if (c < 0)
92 c = 0;
93 if (c >= xcols)
94 c = cols - 1;
95 if (r < 0)
96 sprintf(buf, "\r\33[%d%c", abs(c), c > 0 ? 'C' : 'D');
97 else
98 sprintf(buf, "\33[%d;%dH", r + 1, c + 1);
99 term_out(buf);
102 int term_rows(void)
104 return rows;
107 int term_cols(void)
109 return cols;
112 static char ibuf[4096]; /* input character buffer */
113 static char icmd[4096]; /* read after the last term_cmd() */
114 static int ibuf_pos, ibuf_cnt; /* ibuf[] position and length */
115 static int icmd_pos; /* icmd[] position */
117 /* read s before reading from the terminal */
118 void term_push(char *s, int n)
120 n = MIN(n, sizeof(ibuf) - ibuf_cnt);
121 memcpy(ibuf + ibuf_cnt, s, n);
122 ibuf_cnt += n;
125 /* return a static buffer containing inputs read since the last term_cmd() */
126 char *term_cmd(int *n)
128 *n = icmd_pos;
129 icmd_pos = 0;
130 return icmd;
133 int term_read(int ms)
135 struct pollfd ufds[1];
136 char n, c;
137 if (ibuf_pos >= ibuf_cnt) {
138 ufds[0].fd = 0;
139 ufds[0].events = POLLIN;
140 if (poll(ufds, 1, ms * 1000) <= 0)
141 return -1;
142 /* read a single input character */
143 if ((n = read(0, ibuf, 1)) <= 0)
144 return -1;
145 ibuf_cnt = n;
146 ibuf_pos = 0;
148 c = ibuf_pos < ibuf_cnt ? (unsigned char) ibuf[ibuf_pos++] : -1;
149 if (icmd_pos < sizeof(icmd))
150 icmd[icmd_pos++] = c;
151 return c;
154 /* return a static string that changes text attributes from old to att */
155 char *term_att(int att, int old)
157 static char buf[128];
158 char *s = buf;
159 int fg = SYN_FG(att);
160 int bg = SYN_BG(att);
161 if (att == old)
162 return "";
163 s += sprintf(s, "\33[m\33[");
164 if (fg & SYN_BD)
165 s += sprintf(s, "1;");
166 if (fg & SYN_IT)
167 s += sprintf(s, "3;");
168 else if (fg & SYN_RV)
169 s += sprintf(s, "7;");
170 if ((fg & 0xff) < 8)
171 s += sprintf(s, "%d;", 30 + (fg & 0xff));
172 else
173 s += sprintf(s, "38;5;%d;", (fg & 0xff));
174 if (bg) {
175 if ((bg & 0xff) < 8)
176 s += sprintf(s, "%d;", 40 + (bg & 0xff));
177 else
178 s += sprintf(s, "48;5;%d;", (bg & 0xff));
180 s += sprintf(s, "m");
181 return buf;