term: autocr should not be set at startup
[fbpad.git] / fbpad.c
blobe7c10fa3bbf5df403f226f05d1b016c4ea1b40d6
1 /*
2 * fbpad - A small linux framebuffer virtual terminal
4 * Copyright (C) 2009 Ali Gholami Rudi
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License, as published by the
8 * Free Software Foundation.
9 */
10 #include <ctype.h>
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <poll.h>
14 #include <pty.h>
15 #include <signal.h>
16 #include <string.h>
17 #include <sys/wait.h>
18 #include <unistd.h>
19 #include <linux/vt.h>
20 #include <locale.h>
21 #include "config.h"
22 #include "pad.h"
23 #include "term.h"
24 #include "util.h"
26 #define CTRLKEY(x) ((x) - 96)
27 #define BADPOLLFLAGS (POLLHUP | POLLERR | POLLNVAL)
28 #define NTAGS sizeof(tags)
30 static char tags[] = TAGS;
31 static struct term terms[NTAGS * 2];
32 static int cterm; /* current tag */
33 static int lterm; /* last tag */
34 static int exitit;
36 static int readchar(void)
38 char b;
39 if (read(STDIN_FILENO, &b, 1) > 0)
40 return (int) b;
41 return -1;
44 static void showterm(int n)
46 if (cterm % NTAGS != n % NTAGS)
47 lterm = cterm;
48 term_save(&terms[cterm]);
49 cterm = n;
50 term_load(&terms[cterm], TERM_REDRAW);
53 static struct term *mainterm(void)
55 if (terms[cterm].fd)
56 return &terms[cterm];
57 return NULL;
60 static void exec_cmd(char *file)
62 if (!mainterm())
63 term_exec(file);
66 static int altterm(int n)
68 return n < NTAGS ? n + NTAGS : n - NTAGS;
71 static void nextterm(void)
73 int n = (cterm + 1) % ARRAY_SIZE(terms);
74 while (n != cterm) {
75 if (terms[n].fd) {
76 showterm(n);
77 break;
79 n = (n + 1) % ARRAY_SIZE(terms);
83 static void showterms(void)
85 int colors[] = {FGCOLOR, 4, 2, 5};
86 int c = 0;
87 int r = pad_rows() - 1;
88 int i;
89 pad_put('T', r, c++, FGCOLOR, BGCOLOR);
90 pad_put('A', r, c++, FGCOLOR, BGCOLOR);
91 pad_put('G', r, c++, FGCOLOR, BGCOLOR);
92 pad_put('S', r, c++, FGCOLOR, BGCOLOR);
93 pad_put(':', r, c++, FGCOLOR, BGCOLOR);
94 pad_put(' ', r, c++, FGCOLOR, BGCOLOR);
95 for (i = 0; i < NTAGS; i++) {
96 int nt = 0;
97 int shown = i == cterm || altterm(i) == cterm;
98 if (terms[i].fd)
99 nt = 1;
100 if (terms[altterm(i)].fd)
101 nt = nt ? 2 : 3;
102 pad_put(shown ? '(' : ' ', r, c++, FGCOLOR, BGCOLOR);
103 pad_put(tags[i], r, c++, colors[nt], 7);
104 pad_put(shown ? ')' : ' ', r, c++, FGCOLOR, BGCOLOR);
108 static void directkey(void)
110 int c = readchar();
111 if (c == ESC) {
112 switch ((c = readchar())) {
113 case 'c':
114 exec_cmd(SHELL);
115 return;
116 case 'm':
117 exec_cmd(MAIL);
118 return;
119 case 'e':
120 exec_cmd(EDITOR);
121 return;
122 case 'j':
123 case 'k':
124 showterm(altterm(cterm));
125 return;
126 case 'o':
127 showterm(lterm);
128 return;
129 case 'p':
130 showterms();
131 return;
132 case '\t':
133 nextterm();
134 return;
135 case CTRLKEY('q'):
136 exitit = 1;
137 return;
138 default:
139 if (strchr(tags, c)) {
140 showterm(strchr(tags, c) - tags);
141 return;
143 if (mainterm())
144 term_send(ESC);
147 if (c != -1 && mainterm())
148 term_send(c);
151 static int find_by_fd(int fd)
153 int i;
154 for (i = 0; i < ARRAY_SIZE(terms); i++)
155 if (terms[i].fd == fd)
156 return i;
157 return -1;
160 static int fill_ufds(struct pollfd *ufds)
162 int n = 1;
163 int i;
164 ufds[0].fd = STDIN_FILENO;
165 ufds[0].events = POLLIN;
166 for (i = 0; i < ARRAY_SIZE(terms); i++) {
167 if (terms[i].fd) {
168 ufds[n].fd = terms[i].fd;
169 ufds[n].events = POLLIN;
170 n++;
173 return n;
176 static void temp_switch(int termid)
178 if (termid != cterm) {
179 term_save(&terms[cterm]);
180 term_load(&terms[termid], TERM_HIDDEN);
184 static void switch_back(int termid)
186 if (termid != cterm) {
187 term_save(&terms[termid]);
188 term_load(&terms[cterm], TERM_VISIBLE);
192 static void check_ufds(struct pollfd *ufds, int n)
194 int i;
195 for (i = 1; i < n; i++) {
196 int idx = find_by_fd(ufds[i].fd);
197 if (ufds[i].revents & BADPOLLFLAGS) {
198 temp_switch(idx);
199 term_end();
200 switch_back(idx);
202 if (ufds[i].revents & POLLIN) {
203 temp_switch(idx);
204 term_read();
205 switch_back(idx);
210 static void mainloop(void)
212 struct pollfd ufds[ARRAY_SIZE(terms) + 1];
213 struct termios oldtermios, termios;
214 int rv;
215 int n;
216 tcgetattr(STDIN_FILENO, &termios);
217 oldtermios = termios;
218 cfmakeraw(&termios);
219 tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios);
220 memset(ufds, 0, sizeof(ufds));
221 term_load(&terms[cterm], TERM_REDRAW);
222 n = fill_ufds(ufds);
223 while (!exitit) {
224 rv = poll(ufds, n, 1000);
225 if (rv == -1 && errno != EINTR)
226 break;
227 if (ufds[0].revents & BADPOLLFLAGS)
228 break;
229 if (ufds[0].revents & POLLIN)
230 directkey();
231 check_ufds(ufds, n);
232 n = fill_ufds(ufds);
234 tcsetattr(STDIN_FILENO, 0, &oldtermios);
237 static void signalreceived(int n)
239 if (exitit)
240 return;
241 switch (n) {
242 case SIGUSR1:
243 term_save(&terms[cterm]);
244 ioctl(STDIN_FILENO, VT_RELDISP, 1);
245 break;
246 case SIGUSR2:
247 pad_shown();
248 term_load(&terms[cterm], TERM_REDRAW);
249 break;
250 case SIGCHLD:
251 waitpid(-1, 0, WNOHANG);
252 break;
256 static void setupsignals(void)
258 struct vt_mode vtm;
259 vtm.mode = VT_PROCESS;
260 vtm.waitv = 0;
261 vtm.relsig = SIGUSR1;
262 vtm.acqsig = SIGUSR2;
263 vtm.frsig = 0;
264 ioctl(STDIN_FILENO, VT_SETMODE, &vtm);
266 signal(SIGUSR1, signalreceived);
267 signal(SIGUSR2, signalreceived);
268 signal(SIGCHLD, signalreceived);
271 int main(void)
273 char *hide = "\x1b[?25l";
274 char *clear = "\x1b[2J\x1b[H";
275 char *show = "\x1b[?25h";
276 setlocale(LC_ALL, "");
277 write(STDIN_FILENO, clear, strlen(clear));
278 write(STDIN_FILENO, hide, strlen(hide));
279 pad_init();
280 setupsignals();
281 fcntl(STDIN_FILENO, F_SETFL,
282 fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK);
283 mainloop();
284 pad_free();
285 write(STDIN_FILENO, show, strlen(show));
286 return 0;