Enable blinking in st. - st - Personal fork of st
 (HTM) git clone git://git.drkhsh.at/st.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 1e09726518b84091e80dfaf96632c122f6f446a6
 (DIR) parent 1b2751f5c24ca06afbb68e41e73fc9fce6c6b521
 (HTM) Author: Christoph Lohmann <20h@r-36.net>
       Date:   Fri, 26 Apr 2013 18:41:54 +0200
       
       Enable blinking in st.
       
       Diffstat:
         M config.def.h                        |       3 +++
         M st.c                                |      83 ++++++++++++++++++++++++++-----
         M st.info                             |       2 +-
       
       3 files changed, 74 insertions(+), 14 deletions(-)
       ---
 (DIR) diff --git a/config.def.h b/config.def.h
       @@ -20,6 +20,9 @@ static bool allowaltscreen = true;
        static unsigned int xfps = 60;
        static unsigned int actionfps = 30;
        
       +/* blinking timeout (set to 0 to disable blinking) */
       +static unsigned int blinktimeout = 800;
       +
        /* TERM value */
        static char termname[] = "st-256color";
        
 (DIR) diff --git a/st.c b/st.c
       @@ -116,6 +116,8 @@ enum term_mode {
                MODE_APPCURSOR         = 2048,
                MODE_MOUSESGR    = 4096,
                MODE_8BIT         = 8192,
       +        MODE_BLINK         = 16384,
       +        MODE_FBLINK         = 32768,
        };
        
        enum escape_state {
       @@ -313,6 +315,7 @@ static void strhandle(void);
        static void strparse(void);
        static void strreset(void);
        
       +static int tattrset(int);
        static void tclearregion(int, int, int, int);
        static void tcursor(int);
        static void tdeletechar(int);
       @@ -334,6 +337,7 @@ static void tsetchar(char *, Glyph *, int, int);
        static void tsetscroll(int, int);
        static void tswapscreen(void);
        static void tsetdirt(int, int);
       +static void tsetdirtattr(int);
        static void tsetmode(bool, bool, int *, int);
        static void tfulldirt(void);
        static void techo(char *, int);
       @@ -1175,6 +1179,20 @@ ttyresize(void) {
                        fprintf(stderr, "Couldn't set window size: %s\n", SERRNO);
        }
        
       +int
       +tattrset(int attr) {
       +        int i, j;
       +
       +        for(i = 0; i < term.row-1; i++) {
       +                for(j = 0; j < term.col-1; j++) {
       +                        if(term.line[i][j].mode & attr)
       +                                return 1;
       +                }
       +        }
       +
       +        return 0;
       +}
       +
        void
        tsetdirt(int top, int bot) {
                int i;
       @@ -1187,6 +1205,20 @@ tsetdirt(int top, int bot) {
        }
        
        void
       +tsetdirtattr(int attr) {
       +        int i, j;
       +
       +        for(i = 0; i < term.row-1; i++) {
       +                for(j = 0; j < term.col-1; j++) {
       +                        if(term.line[i][j].mode & attr) {
       +                                tsetdirt(i, i);
       +                                break;
       +                        }
       +                }
       +        }
       +}
       +
       +void
        tfulldirt(void) {
                tsetdirt(0, term.row-1);
        }
       @@ -2838,6 +2870,9 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
                        bg = temp;
                }
        
       +        if(base.mode & ATTR_BLINK && term.mode & MODE_BLINK)
       +                fg = bg;
       +
                /* Intelligent cleaning up of the borders. */
                if(x == 0) {
                        xclear(0, (y == 0)? 0 : winy, borderpx,
       @@ -3345,34 +3380,55 @@ void
        run(void) {
                XEvent ev;
                fd_set rfd;
       -        int xfd = XConnectionNumber(xw.dpy), xev;
       -        struct timeval drawtimeout, *tv = NULL, now, last;
       +        int xfd = XConnectionNumber(xw.dpy), xev, blinkset = 0, dodraw = 0;
       +        struct timeval drawtimeout, *tv = NULL, now, last, lastblink;
        
       +        gettimeofday(&lastblink, NULL);
                gettimeofday(&last, NULL);
        
                for(xev = actionfps;;) {
                        FD_ZERO(&rfd);
                        FD_SET(cmdfd, &rfd);
                        FD_SET(xfd, &rfd);
       -                if(select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, tv) < 0) {
       +
       +                switch(select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, tv) < 0) {
       +                case -1:
                                if(errno == EINTR)
                                        continue;
                                die("select failed: %s\n", SERRNO);
       -                }
       +                default:
       +                        if(FD_ISSET(cmdfd, &rfd)) {
       +                                ttyread();
       +                                if(blinktimeout) {
       +                                        blinkset = tattrset(ATTR_BLINK);
       +                                        if(!blinkset && term.mode & ATTR_BLINK)
       +                                                term.mode &= ~(MODE_BLINK);
       +                                }
       +                        }
        
       +                        if(FD_ISSET(xfd, &rfd))
       +                                xev = actionfps;
       +                        break;
       +                }
                        gettimeofday(&now, NULL);
                        drawtimeout.tv_sec = 0;
                        drawtimeout.tv_usec = (1000/xfps) * 1000;
                        tv = &drawtimeout;
        
       -                if(FD_ISSET(cmdfd, &rfd))
       -                        ttyread();
       -
       -                if(FD_ISSET(xfd, &rfd))
       -                        xev = actionfps;
       +                dodraw = 0;
       +                if(blinktimeout && TIMEDIFF(now, lastblink) > blinktimeout) {
       +                        tsetdirtattr(ATTR_BLINK);
       +                        term.mode ^= MODE_BLINK;
       +                        gettimeofday(&lastblink, NULL);
       +                        dodraw = 1;
       +                }
       +                if(TIMEDIFF(now, last) \
       +                                > (xev? (1000/xfps) : (1000/actionfps))) {
       +                        dodraw = 1;
       +                        last = now;
       +                }
        
       -                if(TIMEDIFF(now, last) > \
       -                                (xev ? (1000/xfps) : (1000/actionfps))) {
       +                if(dodraw) {
                                while(XPending(xw.dpy)) {
                                        XNextEvent(xw.dpy, &ev);
                                        if(XFilterEvent(&ev, None))
       @@ -3383,12 +3439,13 @@ run(void) {
        
                                draw();
                                XFlush(xw.dpy);
       -                        last = now;
        
                                if(xev && !FD_ISSET(xfd, &rfd))
                                        xev--;
       -                        if(!FD_ISSET(cmdfd, &rfd) && !FD_ISSET(xfd, &rfd))
       +                        if(!FD_ISSET(cmdfd, &rfd) && !FD_ISSET(xfd, &rfd) \
       +                                        && !blinkset) {
                                        tv = NULL;
       +                        }
                        }
                }
        }
 (DIR) diff --git a/st.info b/st.info
       @@ -5,7 +5,7 @@ st| simpleterm,
                am,
                bce,
                bel=^G,
       -#        blink=\E[5m,
       +        blink=\E[5m,
                bold=\E[1m,
                cbt=\E[Z,
                cvvis=\E[?25h,