stag: allow multiple tag patterns for each extension
[neatvi.git] / term.c
blob103636d39410c5a17105e0390b2dc80609564c94
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; /* output buffer if not NULL */
12 static int rows, cols; /* number of terminal rows and columns */
13 static int win_beg, win_rows; /* active window rows */
14 static struct termios termios;
16 void term_init(void)
18 struct winsize win;
19 struct termios newtermios;
20 tcgetattr(0, &termios);
21 newtermios = termios;
22 newtermios.c_lflag &= ~(ICANON | ISIG);
23 newtermios.c_lflag &= ~ECHO;
24 tcsetattr(0, TCSAFLUSH, &newtermios);
25 if (getenv("LINES"))
26 rows = atoi(getenv("LINES"));
27 if (getenv("COLUMNS"))
28 cols = atoi(getenv("COLUMNS"));
29 if (!ioctl(0, TIOCGWINSZ, &win)) {
30 cols = win.ws_col;
31 rows = win.ws_row;
33 cols = cols ? cols : 80;
34 rows = rows ? rows : 25;
35 term_str("\33[m");
36 term_window(win_beg, win_rows > 0 ? win_rows : rows);
39 void term_window(int row, int cnt)
41 char cmd[64];
42 win_beg = row;
43 win_rows = cnt;
44 if (row == 0 && win_rows == rows) {
45 term_str("\33[r");
46 } else {
47 sprintf(cmd, "\33[%d;%dr", win_beg + 1, win_beg + win_rows);
48 term_str(cmd);
52 void term_done(void)
54 term_str("\33[r");
55 term_pos(rows - 1, 0);
56 term_kill();
57 term_commit();
58 tcsetattr(0, 0, &termios);
61 void term_suspend(void)
63 term_done();
64 kill(0, SIGSTOP);
65 term_init();
68 void term_record(void)
70 if (!term_sbuf)
71 term_sbuf = sbuf_make();
74 void term_commit(void)
76 if (term_sbuf) {
77 write(1, sbuf_buf(term_sbuf), sbuf_len(term_sbuf));
78 sbuf_free(term_sbuf);
79 term_sbuf = NULL;
83 static void term_out(char *s)
85 if (term_sbuf)
86 sbuf_str(term_sbuf, s);
87 else
88 write(1, s, strlen(s));
91 void term_str(char *s)
93 term_out(s);
96 void term_chr(int ch)
98 char s[4] = {ch};
99 term_out(s);
102 void term_kill(void)
104 term_out("\33[K");
107 void term_room(int n)
109 char cmd[16];
110 if (n < 0)
111 sprintf(cmd, "\33[%dM", -n);
112 if (n > 0)
113 sprintf(cmd, "\33[%dL", n);
114 if (n)
115 term_out(cmd);
118 void term_pos(int r, int c)
120 char buf[32] = "\r";
121 if (c < 0)
122 c = 0;
123 if (c >= term_cols())
124 c = cols - 1;
125 if (r < 0)
126 sprintf(buf, "\r\33[%d%c", abs(c), c > 0 ? 'C' : 'D');
127 else
128 sprintf(buf, "\33[%d;%dH", win_beg + r + 1, c + 1);
129 term_out(buf);
132 int term_rowx(void)
134 return rows;
137 int term_rows(void)
139 return win_rows;
142 int term_cols(void)
144 return cols;
147 static char ibuf[4096]; /* input character buffer */
148 static char icmd[4096]; /* read after the last term_cmd() */
149 static int ibuf_pos, ibuf_cnt; /* ibuf[] position and length */
150 static int icmd_pos; /* icmd[] position */
152 /* read s before reading from the terminal */
153 void term_push(char *s, int n)
155 n = MIN(n, sizeof(ibuf) - ibuf_cnt);
156 memcpy(ibuf + ibuf_cnt, s, n);
157 ibuf_cnt += n;
160 /* return a static buffer containing inputs read since the last term_cmd() */
161 char *term_cmd(int *n)
163 *n = icmd_pos;
164 icmd_pos = 0;
165 return icmd;
168 int term_read(void)
170 struct pollfd ufds[1];
171 int n, c;
172 if (ibuf_pos >= ibuf_cnt) {
173 ufds[0].fd = 0;
174 ufds[0].events = POLLIN;
175 if (poll(ufds, 1, -1) <= 0)
176 return -1;
177 /* read a single input character */
178 if ((n = read(0, ibuf, 1)) <= 0)
179 return -1;
180 ibuf_cnt = n;
181 ibuf_pos = 0;
183 c = ibuf_pos < ibuf_cnt ? (unsigned char) ibuf[ibuf_pos++] : -1;
184 if (icmd_pos < sizeof(icmd))
185 icmd[icmd_pos++] = c;
186 return c;
189 /* return a static string that changes text attributes from old to att */
190 char *term_att(int att, int old)
192 static char buf[128];
193 char *s = buf;
194 int fg = SYN_FG(att);
195 int bg = SYN_BG(att);
196 if (att == old)
197 return "";
198 s += sprintf(s, "\33[");
199 if (att & SYN_BD)
200 s += sprintf(s, ";1");
201 if (att & SYN_IT)
202 s += sprintf(s, ";3");
203 else if (att & SYN_RV)
204 s += sprintf(s, ";7");
205 if (SYN_FGSET(att)) {
206 if ((fg & 0xff) < 8)
207 s += sprintf(s, ";%d", 30 + (fg & 0xff));
208 else
209 s += sprintf(s, ";38;5;%d", (fg & 0xff));
211 if (SYN_BGSET(att)) {
212 if ((bg & 0xff) < 8)
213 s += sprintf(s, ";%d", 40 + (bg & 0xff));
214 else
215 s += sprintf(s, ";48;5;%d", (bg & 0xff));
217 s += sprintf(s, "m");
218 return buf;