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.
14 #include <sys/ioctl.h>
26 #define CTRLKEY(x) ((x) - 96)
27 #define BADPOLLFLAGS (POLLHUP | POLLERR | POLLNVAL)
28 #define NTAGS (sizeof(tags) - 1)
29 #define NTERMS (NTAGS * 2)
30 #define TERMOPEN(i) (terms[i].fd)
31 #define TERMSNAP(i) (strchr(TAGS_SAVED, tags[(i) % NTAGS]))
33 static char tags
[] = TAGS
;
34 static struct term terms
[NTERMS
];
35 static int tops
[NTAGS
]; /* top terms of tags */
36 static int ctag
; /* current tag */
37 static int ltag
; /* the last tag */
38 static int fonts
[NTERMS
]; /* term fonts */
39 static int setfont
; /* the next character is font */
43 static int readchar(void)
46 if (read(STDIN_FILENO
, &b
, 1) > 0)
51 static int cterm(void)
53 return tops
[ctag
] * NTAGS
+ ctag
;
56 static void term_switch(int oidx
, int nidx
, int show
, int save
, int load
)
58 int flags
= show
? (load
? TERM_REDRAW
: TERM_VISIBLE
) : TERM_HIDDEN
;
59 if (save
&& TERMOPEN(oidx
) && TERMSNAP(oidx
))
60 scr_snap(&terms
[oidx
]);
61 term_save(&terms
[oidx
]);
62 if (show
&& load
&& TERMOPEN(nidx
) && TERMSNAP(nidx
))
63 flags
= scr_load(&terms
[nidx
]) ? TERM_REDRAW
: TERM_VISIBLE
;
65 pad_font(fonts
[nidx
]);
66 term_load(&terms
[nidx
], flags
);
69 static void showterm(int n
)
73 if (ctag
!= n
% NTAGS
)
75 term_switch(cterm(), n
, !hidden
, !hidden
, !hidden
);
77 tops
[ctag
] = n
/ NTAGS
;
80 static void showtag(int n
)
82 showterm(tops
[n
] * NTAGS
+ n
);
85 static struct term
*mainterm(void)
87 if (TERMOPEN(cterm()))
88 return &terms
[cterm()];
92 static void exec_cmd(char *file
)
98 static int altterm(int n
)
100 return n
< NTAGS
? n
+ NTAGS
: n
- NTAGS
;
103 static void nextterm(void)
105 int n
= (cterm() + 1) % NTERMS
;
106 while (n
!= cterm()) {
111 n
= (n
+ 1) % NTERMS
;
115 static void showtags(void)
117 int colors
[] = {15, 4, 2};
119 int r
= pad_rows() - 1;
121 pad_put('T', r
, c
++, FGCOLOR
, BGCOLOR
);
122 pad_put('A', r
, c
++, FGCOLOR
, BGCOLOR
);
123 pad_put('G', r
, c
++, FGCOLOR
, BGCOLOR
);
124 pad_put('S', r
, c
++, FGCOLOR
, BGCOLOR
);
125 pad_put(':', r
, c
++, FGCOLOR
, BGCOLOR
);
126 pad_put(' ', r
, c
++, FGCOLOR
, BGCOLOR
);
127 for (i
= 0; i
< NTAGS
; i
++) {
131 if (TERMOPEN(altterm(i
)))
133 pad_put(i
== ctag
? '(' : ' ', r
, c
++, FGCOLOR
, BGCOLOR
);
135 pad_put(tags
[i
], r
, c
++, !nt
? BGCOLOR
: colors
[nt
], 15);
137 pad_put(tags
[i
], r
, c
++, colors
[nt
], BGCOLOR
);
138 pad_put(i
== ctag
? ')' : ' ', r
, c
++, FGCOLOR
, BGCOLOR
);
142 static void directkey(void)
145 if (setfont
&& c
!= -1) {
147 if (c
!= ESC
&& isdigit(c
)) {
148 fonts
[cterm()] = c
- '0';
149 term_switch(cterm(), cterm(), 1, 0, 1);
154 switch ((c
= readchar())) {
166 showterm(altterm(cterm()));
184 term_switch(cterm(), cterm(), 1, 0, 1);
190 if (strchr(tags
, c
)) {
191 showtag(strchr(tags
, c
) - tags
);
198 if (c
!= -1 && mainterm())
202 static void temp_switch(int termid
)
204 if (termid
!= cterm())
205 term_switch(cterm(), termid
, 0, 0, 0);
208 static void switch_back(int termid
)
210 if (termid
!= cterm())
211 term_switch(termid
, cterm(), 1, 0, 0);
214 static int poll_all(void)
216 struct pollfd ufds
[NTERMS
+ 1];
217 int term_idx
[NTERMS
+ 1];
220 ufds
[0].fd
= STDIN_FILENO
;
221 ufds
[0].events
= POLLIN
;
222 for (i
= 0; i
< NTERMS
; i
++) {
224 ufds
[n
].fd
= terms
[i
].fd
;
225 ufds
[n
].events
= POLLIN
;
229 if (poll(ufds
, n
, 1000) < 1)
231 if (ufds
[0].revents
& BADPOLLFLAGS
)
233 if (ufds
[0].revents
& POLLIN
)
235 for (i
= 1; i
< n
; i
++) {
236 temp_switch(term_idx
[i
]);
237 if (ufds
[i
].revents
& POLLIN
)
239 if (ufds
[i
].revents
& BADPOLLFLAGS
) {
240 scr_free(&terms
[cterm()]);
243 switch_back(term_idx
[i
]);
248 static void mainloop(void)
250 struct termios oldtermios
, termios
;
251 tcgetattr(STDIN_FILENO
, &termios
);
252 oldtermios
= termios
;
254 tcsetattr(STDIN_FILENO
, TCSAFLUSH
, &termios
);
255 term_load(&terms
[cterm()], TERM_REDRAW
);
259 tcsetattr(STDIN_FILENO
, 0, &oldtermios
);
262 static void signalreceived(int n
);
263 static void signalregister(void)
265 signal(SIGUSR1
, signalreceived
);
266 signal(SIGUSR2
, signalreceived
);
267 signal(SIGCHLD
, signalreceived
);
270 static void signalreceived(int n
)
274 /* racy, new signals may arrive before re-registeration */
279 term_switch(cterm(), cterm(), 0, 1, 0);
280 ioctl(STDIN_FILENO
, VT_RELDISP
, 1);
285 term_switch(cterm(), cterm(), 1, 0, 1);
288 while (waitpid(-1, NULL
, WNOHANG
) > 0)
294 static void setupsignals(void)
297 vtm
.mode
= VT_PROCESS
;
299 vtm
.relsig
= SIGUSR1
;
300 vtm
.acqsig
= SIGUSR2
;
303 ioctl(STDIN_FILENO
, VT_SETMODE
, &vtm
);
308 char *hide
= "\x1b[?25l";
309 char *clear
= "\x1b[2J\x1b[H";
310 char *show
= "\x1b[?25h";
311 write(STDOUT_FILENO
, clear
, strlen(clear
));
312 write(STDIN_FILENO
, hide
, strlen(hide
));
316 fcntl(STDIN_FILENO
, F_SETFL
,
317 fcntl(STDIN_FILENO
, F_GETFL
) | O_NONBLOCK
);
321 write(STDIN_FILENO
, show
, strlen(show
));