Ali Gholami Rudi <aliqr...@gmail.com> wrote:
> Ammar James <lone.no...@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);

Reply via email to