config.h: rename SCREENSHOT to SCRSHOT
[fbpad.git] / fbpad.c
blob3f6272e00054844aedb7aab89e0083d75a998445
1 /*
2 * fbpad - a small framebuffer virtual terminal
4 * Copyright (C) 2009-2011 Ali Gholami Rudi <ali at rudi dot ir>
6 * This program is released under GNU GPL version 2.
7 */
8 #include <ctype.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <poll.h>
12 #include <signal.h>
13 #include <string.h>
14 #include <sys/ioctl.h>
15 #include <sys/wait.h>
16 #include <termios.h>
17 #include <unistd.h>
18 #include <linux/vt.h>
19 #include "config.h"
20 #include "pad.h"
21 #include "term.h"
22 #include "util.h"
23 #include "draw.h"
25 #define CTRLKEY(x) ((x) - 96)
26 #define BADPOLLFLAGS (POLLHUP | POLLERR | POLLNVAL)
27 #define NTAGS (sizeof(tags) - 1)
28 #define NTERMS (NTAGS * 2)
29 #define TERMOPEN(i) (terms[i].fd)
31 static char tags[] = TAGS;
32 static struct term terms[NTERMS];
33 static int tops[NTAGS]; /* top terms of tags */
34 static int ctag; /* current tag */
35 static int ltag; /* the last tag */
36 static int exitit;
37 static int hidden;
39 static int readchar(void)
41 char b;
42 if (read(STDIN_FILENO, &b, 1) > 0)
43 return (int) b;
44 return -1;
47 static int cterm(void)
49 return tops[ctag] * NTAGS + ctag;
52 static void term_switch(int oidx, int nidx, int show, int save, int load)
54 int flags = show ? (load ? TERM_REDRAW : TERM_VISIBLE) : TERM_HIDDEN;
55 term_save(&terms[oidx]);
56 term_load(&terms[nidx], flags);
59 static void showterm(int n)
61 if (cterm() == n)
62 return;
63 if (ctag != n % NTAGS)
64 ltag = ctag;
65 term_switch(cterm(), n, !hidden, !hidden, !hidden);
66 ctag = n % NTAGS;
67 tops[ctag] = n / NTAGS;
70 static void showtag(int n)
72 showterm(tops[n] * NTAGS + n);
75 static struct term *mainterm(void)
77 if (TERMOPEN(cterm()))
78 return &terms[cterm()];
79 return NULL;
82 static void exec_cmd(char *file)
84 if (!mainterm())
85 term_exec(file);
88 static int altterm(int n)
90 return n < NTAGS ? n + NTAGS : n - NTAGS;
93 static void nextterm(void)
95 int n = (cterm() + 1) % NTERMS;
96 while (n != cterm()) {
97 if (TERMOPEN(n)) {
98 showterm(n);
99 break;
101 n = (n + 1) % NTERMS;
105 static void showtags(void)
107 int colors[] = {15, 4, 2};
108 int c = 0;
109 int r = pad_rows() - 1;
110 int i;
111 pad_put('T', r, c++, FGCOLOR, BGCOLOR);
112 pad_put('A', r, c++, FGCOLOR, BGCOLOR);
113 pad_put('G', r, c++, FGCOLOR, BGCOLOR);
114 pad_put('S', r, c++, FGCOLOR, BGCOLOR);
115 pad_put(':', r, c++, FGCOLOR, BGCOLOR);
116 pad_put(' ', r, c++, FGCOLOR, BGCOLOR);
117 for (i = 0; i < NTAGS; i++) {
118 int nt = 0;
119 if (TERMOPEN(i))
120 nt++;
121 if (TERMOPEN(altterm(i)))
122 nt++;
123 pad_put(i == ctag ? '(' : ' ', r, c++, FGCOLOR, BGCOLOR);
124 pad_put(tags[i], r, c++, colors[nt], BGCOLOR);
125 pad_put(i == ctag ? ')' : ' ', r, c++, FGCOLOR, BGCOLOR);
129 static void directkey(void)
131 int c = readchar();
132 if (c == ESC) {
133 switch ((c = readchar())) {
134 case 'c':
135 exec_cmd(SHELL);
136 return;
137 case 'm':
138 exec_cmd(MAIL);
139 return;
140 case 'e':
141 exec_cmd(EDITOR);
142 return;
143 case 'j':
144 case 'k':
145 showterm(altterm(cterm()));
146 return;
147 case 'o':
148 showtag(ltag);
149 return;
150 case 'p':
151 showtags();
152 return;
153 case '\t':
154 nextterm();
155 return;
156 case CTRLKEY('q'):
157 exitit = 1;
158 return;
159 case 's':
160 term_screenshot();
161 return;
162 default:
163 if (strchr(tags, c)) {
164 showtag(strchr(tags, c) - tags);
165 return;
167 if (mainterm())
168 term_send(ESC);
171 if (c != -1 && mainterm())
172 term_send(c);
175 static void temp_switch(int termid)
177 if (termid != cterm())
178 term_switch(cterm(), termid, 0, 0, 0);
181 static void switch_back(int termid)
183 if (termid != cterm())
184 term_switch(termid, cterm(), 1, 0, 0);
187 static int poll_all(void)
189 struct pollfd ufds[NTERMS + 1];
190 int term_idx[NTERMS + 1];
191 int i;
192 int n = 1;
193 ufds[0].fd = STDIN_FILENO;
194 ufds[0].events = POLLIN;
195 for (i = 0; i < NTERMS; i++) {
196 if (TERMOPEN(i)) {
197 ufds[n].fd = terms[i].fd;
198 ufds[n].events = POLLIN;
199 term_idx[n++] = i;
202 if (poll(ufds, n, 1000) < 1)
203 return 0;
204 if (ufds[0].revents & BADPOLLFLAGS)
205 return 1;
206 if (ufds[0].revents & POLLIN)
207 directkey();
208 for (i = 1; i < n; i++) {
209 temp_switch(term_idx[i]);
210 if (ufds[i].revents & POLLIN)
211 term_read();
212 if (ufds[i].revents & BADPOLLFLAGS)
213 term_end();
214 switch_back(term_idx[i]);
216 return 0;
219 static void mainloop(void)
221 struct termios oldtermios, termios;
222 tcgetattr(STDIN_FILENO, &termios);
223 oldtermios = termios;
224 cfmakeraw(&termios);
225 tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios);
226 term_load(&terms[cterm()], TERM_REDRAW);
227 while (!exitit)
228 if (poll_all())
229 break;
230 tcsetattr(STDIN_FILENO, 0, &oldtermios);
233 static void signalreceived(int n);
234 static void signalregister(void)
236 signal(SIGUSR1, signalreceived);
237 signal(SIGUSR2, signalreceived);
238 signal(SIGCHLD, signalreceived);
241 static void signalreceived(int n)
243 if (exitit)
244 return;
245 /* racy, new signals may arrive before re-registeration */
246 signalregister();
247 switch (n) {
248 case SIGUSR1:
249 hidden = 1;
250 term_switch(cterm(), cterm(), 0, 1, 0);
251 ioctl(STDIN_FILENO, VT_RELDISP, 1);
252 break;
253 case SIGUSR2:
254 hidden = 0;
255 fb_cmap();
256 term_switch(cterm(), cterm(), 1, 0, 1);
257 break;
258 case SIGCHLD:
259 while (waitpid(-1, NULL, WNOHANG) > 0)
261 break;
265 static void setupsignals(void)
267 struct vt_mode vtm;
268 vtm.mode = VT_PROCESS;
269 vtm.waitv = 0;
270 vtm.relsig = SIGUSR1;
271 vtm.acqsig = SIGUSR2;
272 vtm.frsig = 0;
273 signalregister();
274 ioctl(STDIN_FILENO, VT_SETMODE, &vtm);
277 int main(void)
279 char *hide = "\x1b[?25l";
280 char *clear = "\x1b[2J\x1b[H";
281 char *show = "\x1b[?25h";
282 write(STDOUT_FILENO, clear, strlen(clear));
283 write(STDIN_FILENO, hide, strlen(hide));
284 if (pad_init())
285 goto failed;
286 setupsignals();
287 fcntl(STDIN_FILENO, F_SETFL,
288 fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK);
289 mainloop();
290 pad_free();
291 failed:
292 write(STDIN_FILENO, show, strlen(show));
293 return 0;