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.
17 #include <sys/ioctl.h>
27 #define CTRLKEY(x) ((x) - 96)
28 #define BADPOLLFLAGS (POLLHUP | POLLERR | POLLNVAL)
29 #define NTAGS sizeof(tags)
31 static char tags
[] = TAGS
;
32 static struct term terms
[NTAGS
* 2];
33 static int tops
[NTAGS
]; /* top terms of tags */
34 static int ctag
; /* current tag */
35 static int ltag
; /* the last tag */
39 static int readchar(void)
42 if (read(STDIN_FILENO
, &b
, 1) > 0)
47 static int cterm(void)
49 return tops
[ctag
] * NTAGS
+ ctag
;
52 static void showterm(int n
)
56 if (ctag
!= n
% NTAGS
)
58 term_save(&terms
[cterm()]);
60 tops
[ctag
] = n
/ NTAGS
;
61 term_load(&terms
[n
], hidden
? TERM_HIDDEN
: TERM_REDRAW
);
64 static void showtag(int n
)
66 showterm(tops
[n
] * NTAGS
+ n
);
69 static struct term
*mainterm(void)
71 if (terms
[cterm()].fd
)
72 return &terms
[cterm()];
76 static void exec_cmd(char *file
)
82 static int altterm(int n
)
84 return n
< NTAGS
? n
+ NTAGS
: n
- NTAGS
;
87 static void nextterm(void)
89 int n
= (cterm() + 1) % ARRAY_SIZE(terms
);
90 while (n
!= cterm()) {
95 n
= (n
+ 1) % ARRAY_SIZE(terms
);
99 static void showtags(void)
101 int colors
[] = {15, 4, 2};
103 int r
= pad_rows() - 1;
105 pad_put('T', r
, c
++, FGCOLOR
, BGCOLOR
);
106 pad_put('A', r
, c
++, FGCOLOR
, BGCOLOR
);
107 pad_put('G', r
, c
++, FGCOLOR
, BGCOLOR
);
108 pad_put('S', r
, c
++, FGCOLOR
, BGCOLOR
);
109 pad_put(':', r
, c
++, FGCOLOR
, BGCOLOR
);
110 pad_put(' ', r
, c
++, FGCOLOR
, BGCOLOR
);
111 for (i
= 0; i
< NTAGS
; i
++) {
115 if (terms
[altterm(i
)].fd
)
117 pad_put(i
== ctag
? '(' : ' ', r
, c
++, FGCOLOR
, BGCOLOR
);
118 pad_put(tags
[i
], r
, c
++, colors
[nt
], 7);
119 pad_put(i
== ctag
? ')' : ' ', r
, c
++, FGCOLOR
, BGCOLOR
);
123 static void directkey(void)
127 switch ((c
= readchar())) {
139 showterm(altterm(cterm()));
157 if (strchr(tags
, c
)) {
158 showtag(strchr(tags
, c
) - tags
);
165 if (c
!= -1 && mainterm())
169 static int find_by_fd(int fd
)
172 for (i
= 0; i
< ARRAY_SIZE(terms
); i
++)
173 if (terms
[i
].fd
== fd
)
178 static int fill_ufds(struct pollfd
*ufds
)
182 ufds
[0].fd
= STDIN_FILENO
;
183 ufds
[0].events
= POLLIN
;
184 for (i
= 0; i
< ARRAY_SIZE(terms
); i
++) {
186 ufds
[n
].fd
= terms
[i
].fd
;
187 ufds
[n
].events
= POLLIN
;
194 static void temp_switch(int termid
)
196 if (termid
!= cterm()) {
197 term_save(&terms
[cterm()]);
198 term_load(&terms
[termid
], TERM_HIDDEN
);
202 static void switch_back(int termid
)
204 if (termid
!= cterm()) {
205 term_save(&terms
[termid
]);
206 term_load(&terms
[cterm()], hidden
? TERM_HIDDEN
: TERM_VISIBLE
);
210 static void check_ufds(struct pollfd
*ufds
, int n
)
213 for (i
= 1; i
< n
; i
++) {
214 int idx
= find_by_fd(ufds
[i
].fd
);
215 if (ufds
[i
].revents
& BADPOLLFLAGS
) {
219 } else if (ufds
[i
].revents
& POLLIN
) {
227 static void mainloop(void)
229 struct pollfd ufds
[ARRAY_SIZE(terms
) + 1];
230 struct termios oldtermios
, termios
;
233 tcgetattr(STDIN_FILENO
, &termios
);
234 oldtermios
= termios
;
236 tcsetattr(STDIN_FILENO
, TCSAFLUSH
, &termios
);
237 memset(ufds
, 0, sizeof(ufds
));
238 term_load(&terms
[cterm()], TERM_REDRAW
);
241 rv
= poll(ufds
, n
, 1000);
242 if (rv
== -1 && errno
!= EINTR
)
244 if (ufds
[0].revents
& BADPOLLFLAGS
)
246 if (ufds
[0].revents
& POLLIN
)
251 tcsetattr(STDIN_FILENO
, 0, &oldtermios
);
254 static void signalreceived(int n
)
261 term_save(&terms
[cterm()]);
262 term_load(&terms
[cterm()], TERM_HIDDEN
);
263 ioctl(STDIN_FILENO
, VT_RELDISP
, 1);
268 term_save(&terms
[cterm()]);
269 term_load(&terms
[cterm()], TERM_REDRAW
);
272 while (waitpid(-1, 0, WNOHANG
) > 0)
278 static void setupsignals(void)
281 vtm
.mode
= VT_PROCESS
;
283 vtm
.relsig
= SIGUSR1
;
284 vtm
.acqsig
= SIGUSR2
;
286 ioctl(STDIN_FILENO
, VT_SETMODE
, &vtm
);
288 signal(SIGUSR1
, signalreceived
);
289 signal(SIGUSR2
, signalreceived
);
290 signal(SIGCHLD
, signalreceived
);
295 char *hide
= "\x1b[?25l";
296 char *clear
= "\x1b[2J\x1b[H";
297 char *show
= "\x1b[?25h";
298 setlocale(LC_ALL
, "");
299 write(STDOUT_FILENO
, clear
, strlen(clear
));
300 write(STDIN_FILENO
, hide
, strlen(hide
));
303 fcntl(STDIN_FILENO
, F_SETFL
,
304 fcntl(STDIN_FILENO
, F_GETFL
) | O_NONBLOCK
);
307 write(STDIN_FILENO
, show
, strlen(show
));