Enable blinking in st.

This commit is contained in:
Christoph Lohmann 2013-04-26 18:41:54 +02:00
parent 1b2751f5c2
commit 1e09726518
3 changed files with 74 additions and 14 deletions

View File

@ -20,6 +20,9 @@ static bool allowaltscreen = true;
static unsigned int xfps = 60; static unsigned int xfps = 60;
static unsigned int actionfps = 30; static unsigned int actionfps = 30;
/* blinking timeout (set to 0 to disable blinking) */
static unsigned int blinktimeout = 800;
/* TERM value */ /* TERM value */
static char termname[] = "st-256color"; static char termname[] = "st-256color";

83
st.c
View File

@ -116,6 +116,8 @@ enum term_mode {
MODE_APPCURSOR = 2048, MODE_APPCURSOR = 2048,
MODE_MOUSESGR = 4096, MODE_MOUSESGR = 4096,
MODE_8BIT = 8192, MODE_8BIT = 8192,
MODE_BLINK = 16384,
MODE_FBLINK = 32768,
}; };
enum escape_state { enum escape_state {
@ -313,6 +315,7 @@ static void strhandle(void);
static void strparse(void); static void strparse(void);
static void strreset(void); static void strreset(void);
static int tattrset(int);
static void tclearregion(int, int, int, int); static void tclearregion(int, int, int, int);
static void tcursor(int); static void tcursor(int);
static void tdeletechar(int); static void tdeletechar(int);
@ -334,6 +337,7 @@ static void tsetchar(char *, Glyph *, int, int);
static void tsetscroll(int, int); static void tsetscroll(int, int);
static void tswapscreen(void); static void tswapscreen(void);
static void tsetdirt(int, int); static void tsetdirt(int, int);
static void tsetdirtattr(int);
static void tsetmode(bool, bool, int *, int); static void tsetmode(bool, bool, int *, int);
static void tfulldirt(void); static void tfulldirt(void);
static void techo(char *, int); static void techo(char *, int);
@ -1175,6 +1179,20 @@ ttyresize(void) {
fprintf(stderr, "Couldn't set window size: %s\n", SERRNO); 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 void
tsetdirt(int top, int bot) { tsetdirt(int top, int bot) {
int i; int i;
@ -1186,6 +1204,20 @@ tsetdirt(int top, int bot) {
term.dirty[i] = 1; term.dirty[i] = 1;
} }
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 void
tfulldirt(void) { tfulldirt(void) {
tsetdirt(0, term.row-1); tsetdirt(0, term.row-1);
@ -2838,6 +2870,9 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
bg = temp; bg = temp;
} }
if(base.mode & ATTR_BLINK && term.mode & MODE_BLINK)
fg = bg;
/* Intelligent cleaning up of the borders. */ /* Intelligent cleaning up of the borders. */
if(x == 0) { if(x == 0) {
xclear(0, (y == 0)? 0 : winy, borderpx, xclear(0, (y == 0)? 0 : winy, borderpx,
@ -3345,34 +3380,55 @@ void
run(void) { run(void) {
XEvent ev; XEvent ev;
fd_set rfd; fd_set rfd;
int xfd = XConnectionNumber(xw.dpy), xev; int xfd = XConnectionNumber(xw.dpy), xev, blinkset = 0, dodraw = 0;
struct timeval drawtimeout, *tv = NULL, now, last; struct timeval drawtimeout, *tv = NULL, now, last, lastblink;
gettimeofday(&lastblink, NULL);
gettimeofday(&last, NULL); gettimeofday(&last, NULL);
for(xev = actionfps;;) { for(xev = actionfps;;) {
FD_ZERO(&rfd); FD_ZERO(&rfd);
FD_SET(cmdfd, &rfd); FD_SET(cmdfd, &rfd);
FD_SET(xfd, &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) if(errno == EINTR)
continue; continue;
die("select failed: %s\n", SERRNO); 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); gettimeofday(&now, NULL);
drawtimeout.tv_sec = 0; drawtimeout.tv_sec = 0;
drawtimeout.tv_usec = (1000/xfps) * 1000; drawtimeout.tv_usec = (1000/xfps) * 1000;
tv = &drawtimeout; tv = &drawtimeout;
if(FD_ISSET(cmdfd, &rfd)) dodraw = 0;
ttyread(); 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(FD_ISSET(xfd, &rfd)) if(dodraw) {
xev = actionfps;
if(TIMEDIFF(now, last) > \
(xev ? (1000/xfps) : (1000/actionfps))) {
while(XPending(xw.dpy)) { while(XPending(xw.dpy)) {
XNextEvent(xw.dpy, &ev); XNextEvent(xw.dpy, &ev);
if(XFilterEvent(&ev, None)) if(XFilterEvent(&ev, None))
@ -3383,12 +3439,13 @@ run(void) {
draw(); draw();
XFlush(xw.dpy); XFlush(xw.dpy);
last = now;
if(xev && !FD_ISSET(xfd, &rfd)) if(xev && !FD_ISSET(xfd, &rfd))
xev--; xev--;
if(!FD_ISSET(cmdfd, &rfd) && !FD_ISSET(xfd, &rfd)) if(!FD_ISSET(cmdfd, &rfd) && !FD_ISSET(xfd, &rfd) \
&& !blinkset) {
tv = NULL; tv = NULL;
}
} }
} }
} }

View File

@ -5,7 +5,7 @@ st| simpleterm,
am, am,
bce, bce,
bel=^G, bel=^G,
# blink=\E[5m, blink=\E[5m,
bold=\E[1m, bold=\E[1m,
cbt=\E[Z, cbt=\E[Z,
cvvis=\E[?25h, cvvis=\E[?25h,