Re: [dev] [OT] announcing fbpad

From: Ali Gholami Rudi <aliqrudi_AT_gmail.com>
Date: Wed, 22 Jul 2009 09:58:09 +0430

Ali Gholami Rudi <aliqrudi_AT_gmail.com> wrote:
> Ammar James <lone.nomad_AT_gmail.com> wrote:
> >> Fbpad is a small framebuffer virtual terminal that uses libfreetype to
> >> render truetype fonts. It manages many terminals through tags. The tag
> >> management is intentionally minimal and simple. A tag is represented
> >> with a single letter (or digit if you prefer) and each tag has a main
> >> and an alt terminal. Something like dwm monocle layout where each tag
> >> can hold at most two windows (that was how I used dwm on a laptop
> >> screen). If someone prefers tiled windows, he can run dvtm inside
> >
> > You might be interested in dvtm.
>
> Why? What I needed was a terminal with truetype fonts on linux
> framebuffer, I'm not sure how dvtm can help. The tag management of
> fbpad is very minimal and was an afterthought; "fbpad is a framebuffer

If someone prefers separating terminal management, from terminal
emulation, this patch changes fbpad to handle only one terminal; it
executes the given command and exits as soon as the command exits.

        Ali

 config.h | 5 --
 fbpad.c | 200 ++++++++------------------------------------------------------
 term.c | 103 +++++++++++++++-----------------
 term.h | 28 +--------
 vt102.c | 4 +-
 5 files changed, 76 insertions(+), 264 deletions(-)

diff --git a/config.h b/config.h
index 62545c2..c48422d 100644
--- a/config.h
+++ b/config.h
@@ -1,8 +1,3 @@
-#define TAGS "xnlhtrv-"
-#define SHELL "/bin/bash"
-#define MAIL "mutt"
-#define EDITOR "vim"
-
 #define FONTFACE "/usr/lib/X11/fonts/TTF/DejaVuSansMono.ttf"
 #define FONTSIZE 10
 #define DPI 196
diff --git a/fbpad.c b/fbpad.c
index 3c2bd77..6e8caa8 100644
--- a/fbpad.c
+++ b/fbpad.c
@@ -13,6 +13,7 @@
 #include <poll.h>
 #include <pty.h>
 #include <signal.h>
+#include <stdio.h>
 #include <string.h>
 #include <sys/wait.h>
 #include <unistd.h>
@@ -27,12 +28,7 @@
 #define BADPOLLFLAGS (POLLHUP | POLLERR | POLLNVAL)
 #define NTAGS sizeof(tags)
 
-static char tags[] = TAGS;
-static struct term terms[NTAGS * 2];
-static int cterm; /* current tag */
-static int lterm; /* last tag */
 static int exitit;
-static int hidden;
 
 static int readchar(void)
 {
@@ -42,194 +38,45 @@ static int readchar(void)
         return -1;
 }
 
-static void showterm(int n)
-{
- if (cterm % NTAGS != n % NTAGS)
- lterm = cterm;
- term_save(&terms[cterm]);
- cterm = n;
- term_load(&terms[cterm], hidden ? TERM_HIDDEN : TERM_REDRAW);
-}
-
-static struct term *mainterm(void)
-{
- if (terms[cterm].fd)
- return &terms[cterm];
- return NULL;
-}
-
-static void exec_cmd(char *file)
-{
- if (!mainterm())
- term_exec(file);
-}
-
-static int altterm(int n)
-{
- return n < NTAGS ? n + NTAGS : n - NTAGS;
-}
-
-static void nextterm(void)
-{
- int n = (cterm + 1) % ARRAY_SIZE(terms);
- while (n != cterm) {
- if (terms[n].fd) {
- showterm(n);
- break;
- }
- n = (n + 1) % ARRAY_SIZE(terms);
- }
-}
-
-static void showterms(void)
-{
- int colors[] = {FGCOLOR, 4, 2, 5};
- int c = 0;
- int r = pad_rows() - 1;
- int i;
- pad_put('T', r, c++, FGCOLOR, BGCOLOR);
- pad_put('A', r, c++, FGCOLOR, BGCOLOR);
- pad_put('G', r, c++, FGCOLOR, BGCOLOR);
- pad_put('S', r, c++, FGCOLOR, BGCOLOR);
- pad_put(':', r, c++, FGCOLOR, BGCOLOR);
- pad_put(' ', r, c++, FGCOLOR, BGCOLOR);
- for (i = 0; i < NTAGS; i++) {
- int nt = 0;
- int shown = i == cterm || altterm(i) == cterm;
- if (terms[i].fd)
- nt = 1;
- if (terms[altterm(i)].fd)
- nt = nt ? 2 : 3;
- pad_put(shown ? '(' : ' ', r, c++, FGCOLOR, BGCOLOR);
- pad_put(tags[i], r, c++, colors[nt], 7);
- pad_put(shown ? ')' : ' ', r, c++, FGCOLOR, BGCOLOR);
- }
-}
-
 static void directkey(void)
 {
- int c = readchar();
- if (c == ESC) {
- switch ((c = readchar())) {
- case 'c':
- exec_cmd(SHELL);
- return;
- case 'm':
- exec_cmd(MAIL);
- return;
- case 'e':
- exec_cmd(EDITOR);
- return;
- case 'j':
- case 'k':
- showterm(altterm(cterm));
- return;
- case 'o':
- showterm(lterm);
- return;
- case 'p':
- showterms();
- return;
- case '\t':
- nextterm();
- return;
- case CTRLKEY('q'):
- exitit = 1;
- return;
- default:
- if (strchr(tags, c)) {
- showterm(strchr(tags, c) - tags);
- return;
- }
- if (mainterm())
- term_send(ESC);
- }
- }
- if (c != -1 && mainterm())
- term_send(c);
-}
-
-static int find_by_fd(int fd)
-{
- int i;
- for (i = 0; i < ARRAY_SIZE(terms); i++)
- if (terms[i].fd == fd)
- return i;
- return -1;
+ term_send(readchar());
 }
 
-static int fill_ufds(struct pollfd *ufds)
+static void fill_ufds(struct pollfd *ufds)
 {
- int n = 1;
- int i;
         ufds[0].fd = STDIN_FILENO;
         ufds[0].events = POLLIN;
- for (i = 0; i < ARRAY_SIZE(terms); i++) {
- if (terms[i].fd) {
- ufds[n].fd = terms[i].fd;
- ufds[n].events = POLLIN;
- n++;
- }
- }
- return n;
+ ufds[1].fd = term_fd();
+ ufds[1].events = POLLIN;
 }
 
-static void temp_switch(int termid)
+static void check_ufds(struct pollfd *ufds)
 {
- if (termid != cterm) {
- term_save(&terms[cterm]);
- term_load(&terms[termid], TERM_HIDDEN);
- }
-}
-
-static void switch_back(int termid)
-{
- if (termid != cterm) {
- term_save(&terms[termid]);
- term_load(&terms[cterm], hidden ? TERM_HIDDEN : TERM_VISIBLE);
- }
-}
-
-static void check_ufds(struct pollfd *ufds, int n)
-{
- int i;
- for (i = 1; i < n; i++) {
- int idx = find_by_fd(ufds[i].fd);
- if (ufds[i].revents & BADPOLLFLAGS) {
- temp_switch(idx);
- term_end();
- switch_back(idx);
- } else if (ufds[i].revents & POLLIN) {
- temp_switch(idx);
- term_read();
- switch_back(idx);
- }
- }
+ if (ufds[0].revents & BADPOLLFLAGS || ufds[1].revents & BADPOLLFLAGS)
+ exitit = 1;
+ if (ufds[0].revents & POLLIN)
+ directkey();
+ if (ufds[1].revents & POLLIN)
+ term_read();
 }
 
 static void mainloop(void)
 {
- struct pollfd ufds[ARRAY_SIZE(terms) + 1];
+ struct pollfd ufds[2];
         struct termios oldtermios, termios;
         int rv;
- int n;
         tcgetattr(STDIN_FILENO, &termios);
         oldtermios = termios;
         cfmakeraw(&termios);
         tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios);
         memset(ufds, 0, sizeof(ufds));
- term_load(&terms[cterm], TERM_REDRAW);
- n = fill_ufds(ufds);
+ fill_ufds(ufds);
         while (!exitit) {
- rv = poll(ufds, n, 1000);
+ rv = poll(ufds, 2, 1000);
                 if (rv == -1 && errno != EINTR)
                         break;
- if (ufds[0].revents & BADPOLLFLAGS)
- break;
- if (ufds[0].revents & POLLIN)
- directkey();
- check_ufds(ufds, n);
- n = fill_ufds(ufds);
+ check_ufds(ufds);
         }
         tcsetattr(STDIN_FILENO, 0, &oldtermios);
 }
@@ -240,16 +87,12 @@ static void signalreceived(int n)
                 return;
         switch (n) {
         case SIGUSR1:
- hidden = 1;
- term_save(&terms[cterm]);
- term_load(&terms[cterm], TERM_HIDDEN);
+ term_hide();
                 ioctl(STDIN_FILENO, VT_RELDISP, 1);
                 break;
         case SIGUSR2:
- hidden = 0;
                 pad_shown();
- term_save(&terms[cterm]);
- term_load(&terms[cterm], TERM_REDRAW);
+ term_show();
                 break;
         case SIGCHLD:
                 waitpid(-1, 0, WNOHANG);
@@ -272,11 +115,15 @@ static void setupsignals(void)
         signal(SIGCHLD, signalreceived);
 }
 
-int main(void)
+int main(int argc, char *argv[])
 {
         char *hide = "\x1b[?25l";
         char *clear = "\x1b[2J\x1b[H";
         char *show = "\x1b[?25h";
+ if (argc < 2) {
+ printf("Usage: %s program\n", argv[0]);
+ return 0;
+ }
         setlocale(LC_ALL, "");
         write(STDIN_FILENO, clear, strlen(clear));
         write(STDIN_FILENO, hide, strlen(hide));
@@ -284,6 +131,7 @@ int main(void)
         setupsignals();
         fcntl(STDIN_FILENO, F_SETFL,
                 fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK);
+ term_exec(argv[1]);
         mainloop();
         pad_free();
         write(STDIN_FILENO, show, strlen(show));
diff --git a/term.c b/term.c
index f7bfe06..11b7385 100644
--- a/term.c
+++ b/term.c
@@ -25,12 +25,22 @@
 #define BIT_SET(i, b, val) ((val) ? ((i) | (b)) : ((i) & ~(b)))
 #define SQRADDR(r, c) (screen + (r) * pad_cols() + (c))
 
-static struct term *term;
-static struct square *screen;
 static int row, col;
 static int fg, bg;
 static int top, bot;
 static unsigned int mode;
+static pid_t pid;
+static struct term_state {
+ int row, col;
+ int fg, bg;
+ unsigned int mode;
+} sav;
+static int fd;
+static struct square {
+ int c;
+ short fg;
+ short bg;
+} screen[MAXCHARS];
 static int visible;
 
 #define MAXLINES (1 << 13)
@@ -142,14 +152,6 @@ static void lazy_flush()
         _term_show(row, col, 1);
 }
 
-static void term_redraw(void)
-{
- int i;
- for (i = 0; i < pad_rows(); i++)
- _draw_row(i);
- _term_show(row, col, 1);
-}
-
 static int origin(void)
 {
         return mode & MODE_ORIGIN;
@@ -162,7 +164,7 @@ static void setsize(void)
         size.ws_row = pad_rows();
         size.ws_xpixel = 0;
         size.ws_ypixel = 0;
- ioctl(term->fd, TIOCSWINSZ, &size);
+ ioctl(fd, TIOCSWINSZ, &size);
 }
 
 #define PTYBUFSIZE (1 << 13)
@@ -172,7 +174,7 @@ static int ptycur;
 static void waitpty(void)
 {
         struct pollfd ufds[1];
- ufds[0].fd = term->fd;
+ ufds[0].fd = fd;
         ufds[0].events = POLLIN;
         poll(ufds, 1, -1);
 }
@@ -181,12 +183,12 @@ static int readpty(void)
 {
         if (ptycur < ptylen)
                 return ptybuf[ptycur++];
- if (!term->fd)
+ if (!fd)
                 return -1;
- ptylen = read(term->fd, ptybuf, PTYBUFSIZE);
+ ptylen = read(fd, ptybuf, PTYBUFSIZE);
         if (ptylen == -1 && errno == EAGAIN) {
                 waitpty();
- ptylen = read(term->fd, ptybuf, PTYBUFSIZE);
+ ptylen = read(fd, ptybuf, PTYBUFSIZE);
         }
         if (ptylen > 0) {
                 ptycur = 1;
@@ -277,14 +279,14 @@ static void advance(int dr, int dc, int scrl)
 void term_send(int c)
 {
         unsigned char b = (unsigned char) c;
- if (term->fd)
- write(term->fd, &b, 1);
+ if (fd)
+ write(fd, &b, 1);
 }
 
 static void term_sendstr(char *s)
 {
- if (term->fd)
- write(term->fd, s, strlen(s));
+ if (fd)
+ write(fd, s, strlen(s));
 }
 
 static void setattr(int m)
@@ -370,22 +372,22 @@ void term_read(void)
 
 void term_exec(char *cmd)
 {
- memset(term, 0, sizeof(*term));
- term->bot = pad_rows();
- term->cur.mode = term->sav.mode = MODE_DEFAULT;
- term_load(term, visible);
- if ((term->pid = forkpty(&term->fd, NULL, NULL, NULL)) == -1) {
+ bot = pad_rows();
+ visible = 1;
+ mode = MODE_DEFAULT;
+ sav.mode = MODE_DEFAULT;
+ if ((pid = forkpty(&fd, NULL, NULL, NULL)) == -1) {
                 perror("failed to fork");
- term->fd = 0;
+ fd = 0;
                 return;
         }
- if (!term->pid) {
+ if (!pid) {
                 setenv("TERM", "linux", 1);
                 execlp(cmd, cmd, NULL);
                 exit(1);
         }
- fcntl(term->fd, F_SETFD, fcntl(term->fd, F_GETFD) | FD_CLOEXEC);
- fcntl(term->fd, F_SETFL, fcntl(term->fd, F_GETFL) | O_NONBLOCK);
+ fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
         setsize();
         setattr(0);
         term_blank();
@@ -409,36 +411,10 @@ static void misc_load(struct term_state *state)
         mode = state->mode;
 }
 
-void term_save(struct term *term)
-{
- visible = 0;
- misc_save(&term->cur);
- term->top = top;
- term->bot = bot;
-}
-
-void term_load(struct term *t, int flags)
-{
- term = t;
- misc_load(&term->cur);
- screen = term->screen;
- visible = flags;
- top = term->top;
- bot = term->bot;
- if (flags == TERM_REDRAW) {
- if (term->fd)
- term_redraw();
- else
- pad_blank(0);
- }
-}
-
 void term_end(void)
 {
- if (term->fd)
- close(term->fd);
- memset(term, 0, sizeof(*term));
- term_load(term, visible ? TERM_REDRAW : TERM_HIDDEN);
+ if (fd)
+ close(fd);
 }
 
 static void set_region(int t, int b)
@@ -449,4 +425,19 @@ static void set_region(int t, int b)
                 move_cursor(top, 0);
 }
 
+int term_fd(void)
+{
+ return fd;
+}
+
+void term_hide(void)
+{
+ visible = 0;
+}
+
+void term_show(void)
+{
+ visible = 1;
+}
+
 #include "vt102.c"
diff --git a/term.h b/term.h
index 4b73c68..7e23e24 100644
--- a/term.h
+++ b/term.h
@@ -1,31 +1,9 @@
 #define ESC 27
 
-struct term_state {
- int row, col;
- int fg, bg;
- unsigned int mode;
-};
-
-struct term {
- int fd;
- int pid;
- int top, bot;
- struct term_state cur, sav;
- struct square {
- int c;
- short fg;
- short bg;
- } screen[MAXCHARS];
-};
-
-#define TERM_HIDDEN 0
-#define TERM_VISIBLE 1
-#define TERM_REDRAW 2
-
-void term_load(struct term *term, int visible);
-void term_save(struct term *term);
-
 void term_read(void);
 void term_send(int c);
 void term_exec(char *cmd);
 void term_end(void);
+int term_fd(void);
+void term_hide(void);
+void term_show(void);
diff --git a/vt102.c b/vt102.c
index c505c65..fcee560 100644
--- a/vt102.c
+++ b/vt102.c
@@ -97,10 +97,10 @@ static void escseq(void)
                 escseq_g3();
                 break;
         case '7': /* DECSC save state (position, charset, attributes) */
- misc_save(&term->sav);
+ misc_save(&sav);
                 break;
         case '8': /* DECRC restore most recently saved state */
- misc_load(&term->sav);
+ misc_load(&sav);
                 break;
         case 'M': /* RI reverse line feed */
                 advance(-1, 0, 1);
Received on Wed Jul 22 2009 - 05:28:09 UTC

This archive was generated by hypermail 2.2.0 : Wed Jul 22 2009 - 05:36:01 UTC