5bd90ef54109e49a989a9b4a11aa9a525bd52dca
2 * fbpad - a small framebuffer virtual terminal
4 * Copyright (C) 2009-2013 Ali Gholami Rudi <ali at rudi dot ir>
6 * This program is released under the Modified BSD license.
14 #include <sys/ioctl.h>
23 #define CTRLKEY(x) ((x) - 96)
24 #define POLLFLAGS (POLLIN | POLLHUP | POLLERR | POLLNVAL)
25 #define NTAGS (sizeof(tags) - 1)
26 #define NTERMS (NTAGS * 2)
27 #define TERMOPEN(i) (terms[i].fd)
28 #define TERMSNAP(i) (strchr(TAGS_SAVED, tags[(i) % NTAGS]))
30 static char tags
[] = TAGS
;
31 static struct term terms
[NTERMS
];
32 static int tops
[NTAGS
]; /* top terms of tags */
33 static int ctag
; /* current tag */
34 static int ltag
; /* the last tag */
36 static int hidden
; /* do not touch the framebuffer */
38 static char pass
[1024];
40 static int cmdmode
; /* execute a command and exit */
41 static int histpos
; /* scrolling history */
43 static int readchar(void)
46 if (read(0, &b
, 1) > 0)
51 static int cterm(void)
53 return tops
[ctag
] * NTAGS
+ ctag
;
56 static int altterm(int n
)
58 return n
< NTAGS
? n
+ NTAGS
: n
- NTAGS
;
61 static int nextterm(void)
63 int n
= (cterm() + 1) % NTERMS
;
64 while (n
!= cterm()) {
72 static struct term
*mainterm(void)
74 return TERMOPEN(cterm()) ? &terms
[cterm()] : NULL
;
77 static void histscrl(int pos
)
84 static void switchterm(int oidx
, int nidx
, int show
, int save
, int load
)
88 if (save
&& TERMOPEN(oidx
) && TERMSNAP(oidx
))
89 scr_snap(&terms
[oidx
]);
90 term_save(&terms
[oidx
]);
91 term_load(&terms
[nidx
], show
);
93 term_redraw(!TERMOPEN(nidx
) || !TERMSNAP(nidx
) || scr_load(&terms
[nidx
]));
96 static void showterm(int n
)
98 if (cterm() == n
|| cmdmode
)
100 if (ctag
!= n
% NTAGS
)
102 switchterm(cterm(), n
, !hidden
, !hidden
, !hidden
);
104 tops
[ctag
] = n
/ NTAGS
;
107 static void showtag(int n
)
109 showterm(tops
[n
] * NTAGS
+ n
);
112 static void execterm(char **args
)
118 static void listtags(void)
120 /* colors for tags based on their number of terminals */
121 int colors
[] = {252, FGCOLOR
, FGCOLOR
| FN_B
};
123 int r
= pad_rows() - 1;
125 pad_put('T', r
, c
++, FGCOLOR
, BGCOLOR
);
126 pad_put('A', r
, c
++, FGCOLOR
, BGCOLOR
);
127 pad_put('G', r
, c
++, FGCOLOR
, BGCOLOR
);
128 pad_put('S', r
, c
++, FGCOLOR
, BGCOLOR
);
129 pad_put(':', r
, c
++, FGCOLOR
, BGCOLOR
);
130 pad_put(' ', r
, c
++, FGCOLOR
, BGCOLOR
);
131 for (i
= 0; i
< NTAGS
; i
++) {
135 if (TERMOPEN(altterm(i
)))
137 pad_put(i
== ctag
? '(' : ' ', r
, c
++, FGCOLOR
, BGCOLOR
);
139 pad_put(tags
[i
], r
, c
++, !nt
? BGCOLOR
: colors
[nt
], colors
[0]);
141 pad_put(tags
[i
], r
, c
++, colors
[nt
], BGCOLOR
);
142 pad_put(i
== ctag
? ')' : ' ', r
, c
++, FGCOLOR
, BGCOLOR
);
146 static void directkey(void)
148 char *shell
[32] = SHELL
;
149 char *mail
[32] = MAIL
;
150 char *editor
[32] = EDITOR
;
152 if (PASS
&& locked
) {
154 pass
[passlen
] = '\0';
155 if (!strcmp(PASS
, pass
))
160 if (isprint(c
) && passlen
+ 1 < sizeof(pass
))
165 switch ((c
= readchar())) {
177 showterm(altterm(cterm()));
186 if (nextterm() != cterm())
187 showterm(nextterm());
203 histscrl(MIN(NHIST
, histpos
+ pad_rows() / 2));
206 histscrl(MAX(0, histpos
- pad_rows() / 2));
209 if (strchr(tags
, c
)) {
210 showtag(strchr(tags
, c
) - tags
);
218 if (c
!= -1 && mainterm())
222 static void peepterm(int termid
)
224 if (termid
!= cterm())
225 switchterm(cterm(), termid
, 0, 0, 0);
228 static void peepback(int termid
)
230 if (termid
!= cterm())
231 switchterm(termid
, cterm(), !hidden
, 0, 0);
234 static int pollterms(void)
236 struct pollfd ufds
[NTERMS
+ 1];
237 int term_idx
[NTERMS
+ 1];
241 ufds
[0].events
= POLLIN
;
242 for (i
= 0; i
< NTERMS
; i
++) {
244 ufds
[n
].fd
= terms
[i
].fd
;
245 ufds
[n
].events
= POLLIN
;
249 if (poll(ufds
, n
, 1000) < 1)
251 if (ufds
[0].revents
& (POLLFLAGS
& ~POLLIN
))
253 if (ufds
[0].revents
& POLLIN
)
255 for (i
= 1; i
< n
; i
++) {
256 if (!(ufds
[i
].revents
& POLLFLAGS
))
258 peepterm(term_idx
[i
]);
259 if (ufds
[i
].revents
& POLLIN
) {
262 scr_free(&terms
[term_idx
[i
]]);
267 peepback(term_idx
[i
]);
272 static void mainloop(char **args
)
274 struct termios oldtermios
, termios
;
275 tcgetattr(0, &termios
);
276 oldtermios
= termios
;
278 tcsetattr(0, TCSAFLUSH
, &termios
);
279 term_load(&terms
[cterm()], 1);
288 tcsetattr(0, 0, &oldtermios
);
291 static void signalreceived(int n
);
292 static void signalregister(void)
294 signal(SIGUSR1
, signalreceived
);
295 signal(SIGUSR2
, signalreceived
);
296 signal(SIGCHLD
, signalreceived
);
299 static void signalreceived(int n
)
303 /* racy, new signals may arrive before re-registeration */
308 switchterm(cterm(), cterm(), 0, 1, 0);
309 ioctl(0, VT_RELDISP
, 1);
314 switchterm(cterm(), cterm(), 1, 0, 1);
317 while (waitpid(-1, NULL
, WNOHANG
) > 0)
323 static void signalsetup(void)
326 vtm
.mode
= VT_PROCESS
;
328 vtm
.relsig
= SIGUSR1
;
329 vtm
.acqsig
= SIGUSR2
;
332 ioctl(0, VT_SETMODE
, &vtm
);
335 int main(int argc
, char **argv
)
337 char *hide
= "\x1b[?25l";
338 char *clear
= "\x1b[2J\x1b[H";
339 char *show
= "\x1b[?25h";
340 char **args
= argv
+ 1;
341 write(1, clear
, strlen(clear
));
342 write(1, hide
, strlen(hide
));
346 fcntl(0, F_SETFL
, fcntl(0, F_GETFL
) | O_NONBLOCK
);
347 while (args
[0] && args
[0][0] == '-')
349 mainloop(args
[0] ? args
: NULL
);
352 write(1, show
, strlen(show
));