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>
24 #define CTRLKEY(x) ((x) - 96)
25 #define BADPOLLFLAGS (POLLHUP | POLLERR | POLLNVAL)
26 #define NTAGS sizeof(tags)
27 #define NTERMS (NTAGS * 2)
29 static char tags
[] = TAGS
;
30 static struct term terms
[NTERMS
];
31 static int tops
[NTAGS
]; /* top terms of tags */
32 static int ctag
; /* current tag */
33 static int ltag
; /* the last tag */
37 static int readchar(void)
40 if (read(STDIN_FILENO
, &b
, 1) > 0)
45 static int cterm(void)
47 return tops
[ctag
] * NTAGS
+ ctag
;
50 static void showterm(int n
)
54 if (ctag
!= n
% NTAGS
)
56 term_save(&terms
[cterm()]);
58 tops
[ctag
] = n
/ NTAGS
;
59 term_load(&terms
[n
], hidden
? TERM_HIDDEN
: TERM_REDRAW
);
62 static void showtag(int n
)
64 showterm(tops
[n
] * NTAGS
+ n
);
67 static struct term
*mainterm(void)
69 if (terms
[cterm()].fd
)
70 return &terms
[cterm()];
74 static void exec_cmd(char *file
)
80 static int altterm(int n
)
82 return n
< NTAGS
? n
+ NTAGS
: n
- NTAGS
;
85 static void nextterm(void)
87 int n
= (cterm() + 1) % NTERMS
;
88 while (n
!= cterm()) {
97 static void showtags(void)
99 int colors
[] = {15, 4, 2};
101 int r
= pad_rows() - 1;
103 pad_put('T', r
, c
++, FGCOLOR
, BGCOLOR
);
104 pad_put('A', r
, c
++, FGCOLOR
, BGCOLOR
);
105 pad_put('G', r
, c
++, FGCOLOR
, BGCOLOR
);
106 pad_put('S', r
, c
++, FGCOLOR
, BGCOLOR
);
107 pad_put(':', r
, c
++, FGCOLOR
, BGCOLOR
);
108 pad_put(' ', r
, c
++, FGCOLOR
, BGCOLOR
);
109 for (i
= 0; i
< NTAGS
; i
++) {
113 if (terms
[altterm(i
)].fd
)
115 pad_put(i
== ctag
? '(' : ' ', r
, c
++, FGCOLOR
, BGCOLOR
);
116 pad_put(tags
[i
], r
, c
++, colors
[nt
], 7);
117 pad_put(i
== ctag
? ')' : ' ', r
, c
++, FGCOLOR
, BGCOLOR
);
121 static void directkey(void)
125 switch ((c
= readchar())) {
137 showterm(altterm(cterm()));
155 if (strchr(tags
, c
)) {
156 showtag(strchr(tags
, c
) - tags
);
163 if (c
!= -1 && mainterm())
167 static void temp_switch(int termid
)
169 if (termid
!= cterm()) {
170 term_save(&terms
[cterm()]);
171 term_load(&terms
[termid
], TERM_HIDDEN
);
175 static void switch_back(int termid
)
177 if (termid
!= cterm()) {
178 term_save(&terms
[termid
]);
179 term_load(&terms
[cterm()], hidden
? TERM_HIDDEN
: TERM_VISIBLE
);
183 static int poll_all(void)
185 struct pollfd ufds
[NTERMS
+ 1];
186 int term_idx
[NTERMS
+ 1];
189 ufds
[0].fd
= STDIN_FILENO
;
190 ufds
[0].events
= POLLIN
;
191 for (i
= 0; i
< NTERMS
; i
++) {
193 ufds
[n
].fd
= terms
[i
].fd
;
194 ufds
[n
].events
= POLLIN
;
198 if (poll(ufds
, n
, 1000) < 1)
200 if (ufds
[0].revents
& BADPOLLFLAGS
)
202 if (ufds
[0].revents
& POLLIN
)
204 for (i
= 1; i
< n
; i
++) {
205 temp_switch(term_idx
[i
]);
206 if (ufds
[i
].revents
& POLLIN
)
208 if (ufds
[i
].revents
& BADPOLLFLAGS
)
210 switch_back(term_idx
[i
]);
215 static void mainloop(void)
217 struct termios oldtermios
, termios
;
218 tcgetattr(STDIN_FILENO
, &termios
);
219 oldtermios
= termios
;
221 tcsetattr(STDIN_FILENO
, TCSAFLUSH
, &termios
);
222 term_load(&terms
[cterm()], TERM_REDRAW
);
226 tcsetattr(STDIN_FILENO
, 0, &oldtermios
);
229 static void signalreceived(int n
);
230 static void signalregister(void)
232 signal(SIGUSR1
, signalreceived
);
233 signal(SIGUSR2
, signalreceived
);
234 signal(SIGCHLD
, signalreceived
);
237 static void signalreceived(int n
)
241 /* racy, new signals may arrive before re-registeration */
246 term_save(&terms
[cterm()]);
247 term_load(&terms
[cterm()], TERM_HIDDEN
);
248 ioctl(STDIN_FILENO
, VT_RELDISP
, 1);
253 term_save(&terms
[cterm()]);
254 term_load(&terms
[cterm()], TERM_REDRAW
);
257 while (waitpid(-1, NULL
, WNOHANG
) > 0)
263 static void setupsignals(void)
266 vtm
.mode
= VT_PROCESS
;
268 vtm
.relsig
= SIGUSR1
;
269 vtm
.acqsig
= SIGUSR2
;
272 ioctl(STDIN_FILENO
, VT_SETMODE
, &vtm
);
277 char *hide
= "\x1b[?25l";
278 char *clear
= "\x1b[2J\x1b[H";
279 char *show
= "\x1b[?25h";
280 write(STDOUT_FILENO
, clear
, strlen(clear
));
281 write(STDIN_FILENO
, hide
, strlen(hide
));
285 fcntl(STDIN_FILENO
, F_SETFL
,
286 fcntl(STDIN_FILENO
, F_GETFL
) | O_NONBLOCK
);
290 write(STDIN_FILENO
, show
, strlen(show
));