fbpterm: fix computing escape arguments
[fbpad.git] / fbpterm.c
blob36f3fa4ca6c1d4ae2797c25af4156a755faf4494
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <sys/types.h>
4 #include <poll.h>
5 #include <unistd.h>
6 #include <ctype.h>
7 #include <pty.h>
8 #include "pad.h"
9 #include "util.h"
11 #define SHELL "/bin/bash"
12 #define ESC 27
13 #define MAXESCARGS 32
14 #define FGCOLOR 0
15 #define BGCOLOR 7
17 static pid_t pid;
18 static int fd;
20 static void execshell(void)
22 if ((pid = forkpty(&fd, NULL, NULL, NULL)) == -1)
23 xerror("failed to create a pty");
24 if (!pid) {
25 setenv("TERM", "linux", 1);
26 execl(SHELL, SHELL, NULL);
27 exit(1);
31 static void setsize(void)
33 struct winsize size;
34 size.ws_col = pad_cols();
35 size.ws_row = pad_rows();
36 size.ws_xpixel = 0;
37 size.ws_ypixel = 0;
38 ioctl(fd, TIOCSWINSZ, &size);
41 static int readpty(void)
43 char b;
44 if (read(fd, &b, 1) > 0)
45 return (int) b;
46 return -1;
49 static int readchar(void)
51 char b;
52 if (read(STDIN_FILENO, &b, 1) > 0)
53 return (int) b;
54 return -1;
57 static void writechar(int c)
59 unsigned char b = (unsigned char) c;
60 write(fd, &b, 1);
63 static void writepty(int c)
65 pad_add(c);
68 static void setmode(int m)
70 if (m == 0) {
71 pad_fg(FGCOLOR);
72 pad_bg(BGCOLOR);
74 if (m >= 30 && m <= 37)
75 pad_fg(m - 30);
76 if (m >= 40 && m <= 47)
77 pad_bg(m - 40);
80 static void kill_line(void)
82 int i;
83 for (i = pad_col(); i < pad_cols(); i++)
84 pad_put('\0', pad_row(), i);
85 pad_move(pad_row(), pad_col());
88 static void escape_bracket(void)
90 int args[MAXESCARGS] = {0};
91 int i;
92 int n = -1;
93 int c = 0;
94 for (i = 0; i < ARRAY_SIZE(args) && !isalpha(c); i++) {
95 int arg = 0;
96 while (isdigit((c = readpty())))
97 arg = arg * 10 + (c - '0');
98 args[++n] = arg;
100 switch (c) {
101 case 'H':
102 case 'f':
103 pad_move(MAX(0, args[0] - 1), MAX(0, args[1] - 1));
104 break;
105 case 'J':
106 pad_blank();
107 pad_move(0, 0);
108 break;
109 case 'A':
110 pad_move(pad_row() - MAX(1, args[0]), pad_col());
111 break;
112 case 'B':
113 pad_move(pad_row() + MAX(1, args[0]), pad_col());
114 break;
115 case 'C':
116 pad_move(pad_row(), pad_col() + MAX(1, args[0]));
117 break;
118 case 'D':
119 pad_move(pad_row(), pad_col() - MAX(1, args[0]));
120 break;
121 case 'K':
122 kill_line();
123 break;
124 case 'm':
125 for (i = 0; i < n; i++)
126 setmode(args[i]);
127 if (!n)
128 setmode(0);
129 break;
130 default:
131 printf("unknown escape bracket char <%c>\n", c);
135 static void escape(void)
137 int c = readpty();
138 if (c == '[') {
139 escape_bracket();
140 } else {
141 printf("unknown escape char <%c>\n", c);
142 writepty(ESC);
143 writepty(c);
144 return;
148 static void shcmds(void)
150 int c = readpty();
151 if (c == ESC)
152 escape();
153 else
154 writepty(c);
157 static void directkey(void)
159 int c = readchar();
160 writechar(c);
163 static void mainloop(void)
165 struct pollfd ufds[2];
166 int rv;
167 struct termios oldtermios, termios;
168 tcgetattr(STDIN_FILENO, &termios);
169 oldtermios = termios;
170 cfmakeraw(&termios);
171 tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios);
172 ufds[0].fd = STDIN_FILENO;
173 ufds[0].events = POLLIN;
174 ufds[1].fd = fd;
175 ufds[1].events = POLLIN;
176 while ((rv = poll(ufds, 2, 1000)) != -1) {
177 if ((ufds[0].revents | ufds[1].revents) &
178 (POLLHUP | POLLERR | POLLNVAL))
179 break;
180 if (ufds[0].revents & POLLIN)
181 directkey();
182 if (ufds[1].revents & POLLIN)
183 shcmds();
185 tcsetattr(STDIN_FILENO, 0, &oldtermios);
188 int main(void)
190 execshell();
191 pad_init();
192 setsize();
193 setmode(0);
194 pad_blank();
195 mainloop();
196 pad_free();
197 return 0;