implementing spawntab(), rewriting run() - ttabbed - Simple tabbing application for X11.
       
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 92571a0887b28bb17f40d3352a6b8f2526575298
 (DIR) parent ef13e9be81e52c845314a49b2ac77690b8a35429
 (HTM) Author: Enno Boland (tox) <tox@s01.de>
       Date:   Tue,  8 Sep 2009 00:06:46 +0200
       
       implementing spawntab(), rewriting run()
       Diffstat:
         config.def.h                        |       6 +++---
         tabbed.c                            |     113 ++++++++++++++++++++++++++-----
       
       2 files changed, 98 insertions(+), 21 deletions(-)
       ---
 (DIR) diff --git a/config.def.h b/config.def.h
       @@ -3,13 +3,13 @@ static const char normbgcolor[]     = "#202020";
        static const char normfgcolor[]     = "#c0c0c0";
        static const char selbgcolor[]      = "#884400";
        static const char selfgcolor[]      = "#f0f0f0";
       -static const char *surfexec[]       = { "surf", "-x" };
        
       +#define SURF "surf", "-x"
        #define MODKEY ControlMask
        Key keys[] = { \
                /* modifier                     key        function        argument */
       -        { MODKEY|ShiftMask,             XK_Return, newtab,         { 0 } },
       -        { MODKEY,                       XK_t,      newtab,         { 0 } },
       +        { MODKEY|ShiftMask,             XK_Return, spawntab,       { .v = (char*[]){ SURF, NULL} } },
       +        { MODKEY|ShiftMask,             XK_t,      spawntab,       { .v = (char*[]){ SURF, NULL} } },
                { MODKEY|ShiftMask,             XK_l,      rotate,         { .i = +1 } },
                { MODKEY|ShiftMask,             XK_h,      rotate,         { .i = -1 } },
                { MODKEY,                       XK_1,      move,           { .i = 1 } },
 (DIR) diff --git a/tabbed.c b/tabbed.c
       @@ -2,22 +2,26 @@
         *
         * To understand tabbed, start reading main().
         */
       +#include <sys/select.h>
       +#include <sys/types.h>
       +#include <sys/wait.h>
        #include <locale.h>
        #include <stdarg.h>
       +#include <unistd.h>
       +#include <signal.h>
        #include <stdio.h>
        #include <string.h>
        #include <stdlib.h>
        #include <X11/keysym.h>
        #include <X11/Xatom.h>
        #include <X11/Xlib.h>
       -#include <X11/Xutil.h>
       -#include <X11/Xproto.h>
       -#include <X11/extensions/XTest.h>
       +#include <errno.h>
        
        /* macros */
        #define MAX(a, b)       ((a) > (b) ? (a) : (b))
        #define LENGTH(x)       (sizeof x / sizeof x[0])
        #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask))
       +#define TEXTW(x)        (textnw(x, strlen(x)) + dc.font.height)
        
        enum { ColFG, ColBG, ColLast };              /* color */
        
       @@ -72,7 +76,7 @@ static void initfont(const char *fontstr);
        static void keypress(XEvent *e);
        static void killclient(const Arg *arg);
        static void move(const Arg *arg);
       -static void newtab(const Arg *arg);
       +static void spawntab(const Arg *arg);
        static void rotate(const Arg *arg);
        static void run(void);
        static void setup(void);
       @@ -93,15 +97,12 @@ static DC dc;
        static Window root, win;
        static Bool running = True;
        static unsigned int numlockmask = 0;
       +Client *clients, *sel;
       +Listener *listeners;
        /* configuration, allows nested code to access above variables */
        #include "config.h"
        
        void
       -buttonrelease(XEvent *e) {
       -        //XButtonPressedEvent *ev = &e->xbutton;
       -}
       -
       -void
        cleanup(void) {
                if(dc.font.set)
                        XFreeFontSet(dpy, dc.font.set);
       @@ -136,9 +137,13 @@ die(const char *errstr, ...) {
                exit(EXIT_FAILURE);
        }
        
       -void
       -unmapnotify(XEvent *e) {
       -        running = False;
       +void *
       +emallocz(size_t size) {
       +        void *p;
       +
       +        if(!(p = calloc(1, size)))
       +                die(0, "Cannot Malloc");
       +        return p;
        }
        
        void
       @@ -222,8 +227,36 @@ move(const Arg *arg) {
        }
        
        void
       -newtab(const Arg *arg) {
       -        puts("opening new tab");
       +sigchld(int signal) {
       +        while(0 < waitpid(-1, NULL, WNOHANG));
       +}
       +
       +void
       +spawntab(const Arg *arg) {
       +        int fd[2];
       +        Listener *l;
       +
       +        if(pipe(fd)) {
       +                perror("tabbed: pipe failed");
       +                return;
       +        }
       +        l = emallocz(sizeof(Listener));
       +        l->fd = fd[0];
       +        l->next = listeners;
       +        listeners = l;
       +        signal(SIGCHLD, sigchld);
       +        if(fork() == 0) {
       +                if(dpy)
       +                        close(ConnectionNumber(dpy));
       +                setsid();
       +                dup2(fd[1], STDOUT_FILENO);
       +                close(fd[0]);
       +                execvp(((char **)arg->v)[0], (char **)arg->v);
       +                fprintf(stderr, "tabbed: execvp %s", ((char **)arg->v)[0]);
       +                perror(" failed");
       +                exit(0);
       +        }
       +        close(fd[1]);
        }
        
        void
       @@ -233,13 +266,52 @@ rotate(const Arg *arg) {
        
        void
        run(void) {
       +        char buf[32], *p;
       +        fd_set rd;
       +        int r, xfd;
       +        unsigned int offset;
                XEvent ev;
       +        Listener *l;
        
       +        /* main event loop, also reads status text from stdin */
                XSync(dpy, False);
       +        xfd = ConnectionNumber(dpy);
       +        buf[LENGTH(buf) - 1] = '\0'; /* 0-terminator is never touched */
                while(running) {
       -                XNextEvent(dpy, &ev);
       -                if(handler[ev.type])
       -                        (handler[ev.type])(&ev); /* call handler */
       +                FD_ZERO(&rd);
       +                for(l = listeners; l; l = l->next) {
       +                        printf("setting %i\n", l->fd);
       +                        FD_SET(l->fd, &rd);
       +                }
       +                FD_SET(xfd, &rd);
       +                if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) {
       +                        if(errno == EINTR)
       +                                continue;
       +                        die("select failed\n");
       +                }
       +                for(l = listeners; l; l = l->next) {
       +                        printf("testing %i\n", l->fd);
       +                        if(!FD_ISSET(l->fd, &rd))
       +                                continue;
       +                        switch((r = read(l->fd, buf + offset, LENGTH(buf) - 1 - offset))) {
       +                        case -1:
       +                        case 0:
       +                                break;
       +                        default:
       +                                for(p = buf + offset; r > 0; p++, r--, offset++)
       +                                        if(*p == '\n' || *p == '\0') {
       +                                                *p = '\0';
       +                                                printf("Got somthing: %s\n", buf);
       +                                                break;
       +                                        }
       +                                break;
       +                        }
       +                }
       +                while(XPending(dpy)) {
       +                        XNextEvent(dpy, &ev);
       +                        if(handler[ev.type])
       +                                (handler[ev.type])(&ev); /* call handler */
       +                }
                }
        }
        
       @@ -283,6 +355,11 @@ textnw(const char *text, unsigned int len) {
        }
        
        void
       +unmapnotify(XEvent *e) {
       +        running = False;
       +}
       +
       +void
        updatenumlockmask(void) {
                unsigned int i, j;
                XModifierKeymap *modmap;
       @@ -313,6 +390,6 @@ main(int argc, char *argv[]) {
                cleanup();
                XCloseDisplay(dpy);
                return 0;
       -        textnw(surfexec[0], strlen(surfexec[0]));
       +        textnw(" ", 1);
                updatenumlockmask();
        }