X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=st.c;h=9ad4f89d3d8433d1506b94c859f673b30916c600;hb=588ba51a539d18de5f9497a38ab7875e7b3e1429;hp=4b7e4ebd1b87e2123029f34737165553b0d72b32;hpb=93901ca4fee8a1ab71cb8b918f3d65404460f9ce;p=st.git diff --git a/st.c b/st.c index 4b7e4eb..9ad4f89 100644 --- a/st.c +++ b/st.c @@ -43,9 +43,10 @@ #define XEMBED_FOCUS_OUT 5 /* Arbitrary sizes */ -#define ESC_TITLE_SIZ 256 #define ESC_BUF_SIZ 256 #define ESC_ARG_SIZ 16 +#define STR_BUF_SIZ 256 +#define STR_ARG_SIZ 16 #define DRAW_BUF_SIZ 1024 #define UTF_SIZ 4 #define XK_NO_MOD UINT_MAX @@ -96,11 +97,11 @@ enum glyph_state { }; enum term_mode { - MODE_WRAP = 1, + MODE_WRAP = 1, MODE_INSERT = 2, MODE_APPKEYPAD = 4, MODE_ALTSCREEN = 8, - MODE_CRLF = 16, + MODE_CRLF = 16, MODE_MOUSEBTN = 32, MODE_MOUSEMOTION = 64, MODE_MOUSE = 32|64, @@ -109,10 +110,10 @@ enum term_mode { enum escape_state { ESC_START = 1, - ESC_CSI = 2, - ESC_OSC = 4, - ESC_TITLE = 8, - ESC_ALTCHARSET = 16 + ESC_CSI = 2, + ESC_STR = 4, /* DSC, OSC, PM, APC */ + ESC_ALTCHARSET = 8, + ESC_STR_END = 16, /* a final string was encountered */ }; enum window_state { @@ -151,13 +152,23 @@ typedef struct { /* ESC '[' [[ [] [;]] ] */ typedef struct { char buf[ESC_BUF_SIZ]; /* raw string */ - int len; /* raw string length */ + int len; /* raw string length */ char priv; int arg[ESC_ARG_SIZ]; - int narg; /* nb of args */ + int narg; /* nb of args */ char mode; } CSIEscape; +/* STR Escape sequence structs */ +/* ESC type [[ [] [;]] ] ESC '\' */ +typedef struct { + char type; /* ESC type ... */ + char buf[STR_BUF_SIZ]; /* raw string */ + int len; /* raw string length */ + char *args[STR_ARG_SIZ]; + int narg; /* nb of args */ +} STREscape; + /* Internal representation of the screen */ typedef struct { int row; /* nb row */ @@ -170,8 +181,6 @@ typedef struct { int bot; /* bottom scroll limit */ int mode; /* terminal mode flags */ int esc; /* escape state flags */ - char title[ESC_TITLE_SIZ]; - int titlelen; bool *tabs; } Term; @@ -239,6 +248,10 @@ static void csidump(void); static void csihandle(void); static void csiparse(void); static void csireset(void); +static void strdump(void); +static void strhandle(void); +static void strparse(void); +static void strreset(void); static void tclearregion(int, int, int, int); static void tcursor(int); @@ -249,7 +262,7 @@ static void tinsertblankline(int); static void tmoveto(int, int); static void tnew(int, int); static void tnewline(int); -static void tputtab(void); +static void tputtab(bool); static void tputc(char*); static void treset(void); static int tresize(int, int); @@ -260,6 +273,7 @@ static void tsetchar(char*); static void tsetscroll(int, int); static void tswapscreen(void); static void tsetdirt(int, int); +static void tsetmode(bool, bool, int *, int); static void tfulldirt(void); static void ttynew(void); @@ -323,7 +337,8 @@ static void (*handler[LASTEvent])(XEvent *) = { static DC dc; static XWindow xw; static Term term; -static CSIEscape escseq; +static CSIEscape csiescseq; +static STREscape strescseq; static int cmdfd; static pid_t pid; static Selection sel; @@ -968,22 +983,22 @@ tnewline(int first_col) { void csiparse(void) { /* int noarg = 1; */ - char *p = escseq.buf; + char *p = csiescseq.buf; - escseq.narg = 0; + csiescseq.narg = 0; if(*p == '?') - escseq.priv = 1, p++; + csiescseq.priv = 1, p++; - while(p < escseq.buf+escseq.len) { + while(p < csiescseq.buf+csiescseq.len) { while(isdigit(*p)) { - escseq.arg[escseq.narg] *= 10; - escseq.arg[escseq.narg] += *p++ - '0'/*, noarg = 0 */; + csiescseq.arg[csiescseq.narg] *= 10; + csiescseq.arg[csiescseq.narg] += *p++ - '0'/*, noarg = 0 */; } - if(*p == ';' && escseq.narg+1 < ESC_ARG_SIZ) - escseq.narg++, p++; + if(*p == ';' && csiescseq.narg+1 < ESC_ARG_SIZ) + csiescseq.narg++, p++; else { - escseq.mode = *p; - escseq.narg++; + csiescseq.mode = *p; + csiescseq.narg++; return; } } @@ -1113,7 +1128,7 @@ tsetattr(int *attr, int l) { fprintf(stderr, "erresc: bad fgcolor %d\n", attr[i]); } else - fprintf(stderr, "erresc: gfx attr %d unknown\n", attr[i]); + fprintf(stderr, "erresc(38): gfx attr %d unknown\n", attr[i]); break; case 39: term.c.attr.fg = DefaultFG; @@ -1127,7 +1142,7 @@ tsetattr(int *attr, int l) { fprintf(stderr, "erresc: bad bgcolor %d\n", attr[i]); } else - fprintf(stderr, "erresc: gfx attr %d unknown\n", attr[i]); + fprintf(stderr, "erresc(48): gfx attr %d unknown\n", attr[i]); break; case 49: term.c.attr.bg = DefaultBG; @@ -1142,8 +1157,7 @@ tsetattr(int *attr, int l) { else if(BETWEEN(attr[i], 100, 107)) term.c.attr.fg = attr[i] - 100 + 8; else - fprintf(stderr, "erresc: gfx attr %d unknown\n", attr[i]), csidump(); - + fprintf(stderr, "erresc(default): gfx attr %d unknown\n", attr[i]), csidump(); break; } } @@ -1164,9 +1178,82 @@ tsetscroll(int t, int b) { term.bot = b; } +#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) + +void +tsetmode(bool priv, bool set, int *args, int narg) { + int *lim, mode; + + for (lim = args + narg; args < lim; ++args) { + if(priv) { + switch(*args) { + case 1: + MODBIT(term.mode, set, MODE_APPKEYPAD); + break; + case 5: /* DECSCNM -- Reverve video */ + mode = term.mode; + MODBIT(term.mode,set, MODE_REVERSE); + if (mode != term.mode) + draw(); + break; + case 7: + MODBIT(term.mode, set, MODE_WRAP); + break; + case 20: + MODBIT(term.mode, set, MODE_CRLF); + break; + case 12: /* att610 -- Start blinking cursor (IGNORED) */ + break; + case 25: + MODBIT(term.c.state, !set, CURSOR_HIDE); + break; + case 1000: /* 1000,1002: enable xterm mouse report */ + MODBIT(term.mode, set, MODE_MOUSEBTN); + break; + case 1002: + MODBIT(term.mode, set, MODE_MOUSEMOTION); + break; + case 1049: /* = 1047 and 1048 */ + case 47: + case 1047: + if(IS_SET(MODE_ALTSCREEN)) + tclearregion(0, 0, term.col-1, term.row-1); + if ((set && !IS_SET(MODE_ALTSCREEN)) || + (!set && IS_SET(MODE_ALTSCREEN))) { + tswapscreen(); + } + if (*args != 1049) + break; + /* pass through */ + case 1048: + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + break; + default: + fprintf(stderr, + "erresc: unknown private set/reset mode %d\n", + *args); + break; + } + } else { + switch(*args) { + case 4: + MODBIT(term.mode, set, MODE_INSERT); + break; + default: + fprintf(stderr, + "erresc: unknown set/reset mode %d\n", + *args); + break; + } + } + } +} +#undef MODBIT + + void csihandle(void) { - switch(escseq.mode) { + switch(csiescseq.mode) { default: unknown: fprintf(stderr, "erresc: unknown csi "); @@ -1174,49 +1261,66 @@ csihandle(void) { /* die(""); */ break; case '@': /* ICH -- Insert blank char */ - DEFAULT(escseq.arg[0], 1); - tinsertblank(escseq.arg[0]); + DEFAULT(csiescseq.arg[0], 1); + tinsertblank(csiescseq.arg[0]); break; case 'A': /* CUU -- Cursor Up */ case 'e': - DEFAULT(escseq.arg[0], 1); - tmoveto(term.c.x, term.c.y-escseq.arg[0]); + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); break; case 'B': /* CUD -- Cursor Down */ - DEFAULT(escseq.arg[0], 1); - tmoveto(term.c.x, term.c.y+escseq.arg[0]); + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); break; case 'C': /* CUF -- Cursor Forward */ case 'a': - DEFAULT(escseq.arg[0], 1); - tmoveto(term.c.x+escseq.arg[0], term.c.y); + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x+csiescseq.arg[0], term.c.y); break; case 'D': /* CUB -- Cursor Backward */ - DEFAULT(escseq.arg[0], 1); - tmoveto(term.c.x-escseq.arg[0], term.c.y); + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x-csiescseq.arg[0], term.c.y); break; case 'E': /* CNL -- Cursor Down and first col */ - DEFAULT(escseq.arg[0], 1); - tmoveto(0, term.c.y+escseq.arg[0]); + DEFAULT(csiescseq.arg[0], 1); + tmoveto(0, term.c.y+csiescseq.arg[0]); break; case 'F': /* CPL -- Cursor Up and first col */ - DEFAULT(escseq.arg[0], 1); - tmoveto(0, term.c.y-escseq.arg[0]); + DEFAULT(csiescseq.arg[0], 1); + tmoveto(0, term.c.y-csiescseq.arg[0]); + break; + case 'g': /* TBC -- Tabulation clear */ + switch (csiescseq.arg[0]) { + case 0: /* clear current tab stop */ + term.tabs[term.c.x] = 0; + break; + case 3: /* clear all the tabs */ + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); + break; + default: + goto unknown; + } break; case 'G': /* CHA -- Move to */ case '`': /* XXX: HPA -- same? */ - DEFAULT(escseq.arg[0], 1); - tmoveto(escseq.arg[0]-1, term.c.y); + DEFAULT(csiescseq.arg[0], 1); + tmoveto(csiescseq.arg[0]-1, term.c.y); break; case 'H': /* CUP -- Move to */ case 'f': /* XXX: HVP -- same? */ - DEFAULT(escseq.arg[0], 1); - DEFAULT(escseq.arg[1], 1); - tmoveto(escseq.arg[1]-1, escseq.arg[0]-1); + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], 1); + tmoveto(csiescseq.arg[1]-1, csiescseq.arg[0]-1); + break; + case 'I': /* CHT -- Cursor Forward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + while (csiescseq.arg[0]--) + tputtab(1); break; case 'J': /* ED -- Clear screen */ sel.bx = -1; - switch(escseq.arg[0]) { + switch(csiescseq.arg[0]) { case 0: /* below */ tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); if(term.c.y < term.row-1) @@ -1235,7 +1339,7 @@ csihandle(void) { } break; case 'K': /* EL -- Clear line */ - switch(escseq.arg[0]) { + switch(csiescseq.arg[0]) { case 0: /* right */ tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); break; @@ -1248,152 +1352,54 @@ csihandle(void) { } break; case 'S': /* SU -- Scroll line up */ - DEFAULT(escseq.arg[0], 1); - tscrollup(term.top, escseq.arg[0]); + DEFAULT(csiescseq.arg[0], 1); + tscrollup(term.top, csiescseq.arg[0]); break; case 'T': /* SD -- Scroll line down */ - DEFAULT(escseq.arg[0], 1); - tscrolldown(term.top, escseq.arg[0]); + DEFAULT(csiescseq.arg[0], 1); + tscrolldown(term.top, csiescseq.arg[0]); break; case 'L': /* IL -- Insert blank lines */ - DEFAULT(escseq.arg[0], 1); - tinsertblankline(escseq.arg[0]); + DEFAULT(csiescseq.arg[0], 1); + tinsertblankline(csiescseq.arg[0]); break; case 'l': /* RM -- Reset Mode */ - if(escseq.priv) { - switch(escseq.arg[0]) { - case 1: - term.mode &= ~MODE_APPKEYPAD; - break; - case 5: /* DECSCNM -- Remove reverse video */ - if(IS_SET(MODE_REVERSE)) { - term.mode &= ~MODE_REVERSE; - draw(); - } - break; - case 7: - term.mode &= ~MODE_WRAP; - break; - case 12: /* att610 -- Stop blinking cursor (IGNORED) */ - break; - case 20: - term.mode &= ~MODE_CRLF; - break; - case 25: - term.c.state |= CURSOR_HIDE; - break; - case 1000: /* disable X11 xterm mouse reporting */ - term.mode &= ~MODE_MOUSEBTN; - break; - case 1002: - term.mode &= ~MODE_MOUSEMOTION; - break; - case 1049: /* = 1047 and 1048 */ - case 47: - case 1047: - if(IS_SET(MODE_ALTSCREEN)) { - tclearregion(0, 0, term.col-1, term.row-1); - tswapscreen(); - } - if(escseq.arg[0] != 1049) - break; - case 1048: - tcursor(CURSOR_LOAD); - break; - default: - goto unknown; - } - } else { - switch(escseq.arg[0]) { - case 4: - term.mode &= ~MODE_INSERT; - break; - default: - goto unknown; - } - } + tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); break; case 'M': /* DL -- Delete lines */ - DEFAULT(escseq.arg[0], 1); - tdeleteline(escseq.arg[0]); + DEFAULT(csiescseq.arg[0], 1); + tdeleteline(csiescseq.arg[0]); break; case 'X': /* ECH -- Erase char */ - DEFAULT(escseq.arg[0], 1); - tclearregion(term.c.x, term.c.y, term.c.x + escseq.arg[0], term.c.y); + DEFAULT(csiescseq.arg[0], 1); + tclearregion(term.c.x, term.c.y, term.c.x + csiescseq.arg[0], term.c.y); break; case 'P': /* DCH -- Delete char */ - DEFAULT(escseq.arg[0], 1); - tdeletechar(escseq.arg[0]); + DEFAULT(csiescseq.arg[0], 1); + tdeletechar(csiescseq.arg[0]); + break; + case 'Z': /* CBT -- Cursor Backward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + while (csiescseq.arg[0]--) + tputtab(0); break; - /* XXX: (CSI n Z) CBT -- Cursor Backward Tabulation tab stops */ case 'd': /* VPA -- Move to */ - DEFAULT(escseq.arg[0], 1); - tmoveto(term.c.x, escseq.arg[0]-1); + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, csiescseq.arg[0]-1); break; case 'h': /* SM -- Set terminal mode */ - if(escseq.priv) { - switch(escseq.arg[0]) { - case 1: - term.mode |= MODE_APPKEYPAD; - break; - case 5: /* DECSCNM -- Reverve video */ - if(!IS_SET(MODE_REVERSE)) { - term.mode |= MODE_REVERSE; - draw(); - } - break; - case 7: - term.mode |= MODE_WRAP; - break; - case 20: - term.mode |= MODE_CRLF; - break; - case 12: /* att610 -- Start blinking cursor (IGNORED) */ - /* fallthrough for xterm cvvis = CSI [ ? 12 ; 25 h */ - if(escseq.narg > 1 && escseq.arg[1] != 25) - break; - case 25: - term.c.state &= ~CURSOR_HIDE; - break; - case 1000: /* 1000,1002: enable xterm mouse report */ - term.mode |= MODE_MOUSEBTN; - break; - case 1002: - term.mode |= MODE_MOUSEMOTION; - break; - case 1049: /* = 1047 and 1048 */ - case 47: - case 1047: - if(IS_SET(MODE_ALTSCREEN)) - tclearregion(0, 0, term.col-1, term.row-1); - else - tswapscreen(); - if(escseq.arg[0] != 1049) - break; - case 1048: - tcursor(CURSOR_SAVE); - break; - default: goto unknown; - } - } else { - switch(escseq.arg[0]) { - case 4: - term.mode |= MODE_INSERT; - break; - default: goto unknown; - } - }; + tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); break; case 'm': /* SGR -- Terminal attribute (color) */ - tsetattr(escseq.arg, escseq.narg); + tsetattr(csiescseq.arg, csiescseq.narg); break; case 'r': /* DECSTBM -- Set Scrolling Region */ - if(escseq.priv) + if(csiescseq.priv) goto unknown; else { - DEFAULT(escseq.arg[0], 1); - DEFAULT(escseq.arg[1], term.row); - tsetscroll(escseq.arg[0]-1, escseq.arg[1]-1); + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], term.row); + tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); tmoveto(0, 0); } break; @@ -1410,8 +1416,8 @@ void csidump(void) { int i; printf("ESC["); - for(i = 0; i < escseq.len; i++) { - uint c = escseq.buf[i] & 0xff; + for(i = 0; i < csiescseq.len; i++) { + uint c = csiescseq.buf[i] & 0xff; if(isprint(c)) putchar(c); else if(c == '\n') printf("(\\n)"); else if(c == '\r') printf("(\\r)"); @@ -1423,15 +1429,99 @@ csidump(void) { void csireset(void) { - memset(&escseq, 0, sizeof(escseq)); + memset(&csiescseq, 0, sizeof(csiescseq)); } void -tputtab(void) { - unsigned x; +strhandle(void) { + char *p; + + /* + * TODO: make this being useful in case of color palette change. + */ + strparse(); + + p = strescseq.buf; - for (x = term.c.x + 1; x < term.col && !term.tabs[x]; ++x) - /* nothing */ ; + switch(strescseq.type) { + case ']': /* OSC -- Operating System Command */ + switch(p[0]) { + case '0': + case '1': + case '2': + /* + * TODO: Handle special chars in string, like umlauts. + */ + if(p[1] == ';') { + XStoreName(xw.dpy, xw.win, strescseq.buf+2); + } + break; + case ';': + XStoreName(xw.dpy, xw.win, strescseq.buf+1); + break; + case '4': /* TODO: Set color (arg0) to "rgb:%hexr/$hexg/$hexb" (arg1) */ + break; + default: + fprintf(stderr, "erresc: unknown str "); + strdump(); + break; + } + break; + case 'P': /* DSC -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + default: + fprintf(stderr, "erresc: unknown str "); + strdump(); + /* die(""); */ + break; + } +} + +void +strparse(void) { + /* + * TODO: Implement parsing like for CSI when required. + * Format: ESC type cmd ';' arg0 [';' argn] ESC \ + */ + return; +} + +void +strdump(void) { + int i; + printf("ESC%c", strescseq.type); + for(i = 0; i < strescseq.len; i++) { + uint c = strescseq.buf[i] & 0xff; + if(isprint(c)) putchar(c); + else if(c == '\n') printf("(\\n)"); + else if(c == '\r') printf("(\\r)"); + else if(c == 0x1b) printf("(\\e)"); + else printf("(%02x)", c); + } + printf("ESC\\\n"); +} + +void +strreset(void) { + memset(&strescseq, 0, sizeof(strescseq)); +} + +void +tputtab(bool forward) { + unsigned x = term.c.x; + + if (forward) { + if (x == term.col) + return; + for (++x; x < term.col && !term.tabs[x]; ++x) + /* nothing */ ; + } else { + if (x == 0) + return; + for (--x; x > 0 && !term.tabs[x]; --x) + /* nothing */ ; + } tmoveto(x, term.c.y); } @@ -1440,25 +1530,31 @@ tputc(char *c) { char ascii = *c; if(term.esc & ESC_START) { if(term.esc & ESC_CSI) { - escseq.buf[escseq.len++] = ascii; - if(BETWEEN(ascii, 0x40, 0x7E) || escseq.len >= ESC_BUF_SIZ) { + csiescseq.buf[csiescseq.len++] = ascii; + if(BETWEEN(ascii, 0x40, 0x7E) || csiescseq.len >= ESC_BUF_SIZ) { term.esc = 0; csiparse(), csihandle(); } - /* TODO: handle other OSC */ - } else if(term.esc & ESC_OSC) { - if(ascii == ';') { - term.titlelen = 0; - term.esc = ESC_START | ESC_TITLE; - } - } else if(term.esc & ESC_TITLE) { - if(ascii == '\a' || term.titlelen+1 >= ESC_TITLE_SIZ) { + } else if(term.esc & ESC_STR) { + switch(ascii) { + case '\033': + term.esc = ESC_START | ESC_STR_END; + break; + case '\a': /* backwards compatibility to xterm */ term.esc = 0; - term.title[term.titlelen] = '\0'; - XStoreName(xw.dpy, xw.win, term.title); - } else { - term.title[term.titlelen++] = ascii; + strhandle(); + break; + default: + strescseq.buf[strescseq.len++] = ascii; + if (strescseq.len+1 >= STR_BUF_SIZ) { + term.esc = 0; + strhandle(); + } } + } else if(term.esc & ESC_STR_END) { + term.esc = 0; + if(ascii == '\\') + strhandle(); } else if(term.esc & ESC_ALTCHARSET) { switch(ascii) { case '0': /* Line drawing crap */ @@ -1476,8 +1572,13 @@ tputc(char *c) { case '[': term.esc |= ESC_CSI; break; - case ']': - term.esc |= ESC_OSC; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + case ']': /* OSC -- Operating System Command */ + strreset(); + strescseq.type = ascii; + term.esc |= ESC_STR; break; case '(': term.esc |= ESC_ALTCHARSET; @@ -1524,6 +1625,9 @@ tputc(char *c) { tcursor(CURSOR_LOAD); term.esc = 0; break; + case '\\': /* ST -- Stop */ + term.esc = 0; + break; default: fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", (uchar) ascii, isprint(ascii)?ascii:'.'); @@ -1535,7 +1639,7 @@ tputc(char *c) { sel.bx = -1; switch(ascii) { case '\t': - tputtab(); + tputtab(1); break; case '\b': tmoveto(term.c.x-1, term.c.y); @@ -1691,8 +1795,8 @@ void xclear(int x1, int y1, int x2, int y2) { XSetForeground(xw.dpy, dc.gc, dc.col[IS_SET(MODE_REVERSE) ? DefaultFG : DefaultBG]); XFillRectangle(xw.dpy, xw.buf, dc.gc, - BORDER + x1 * xw.cw, BORDER + y1 * xw.ch, - (x2-x1+1) * xw.cw, (y2-y1+1) * xw.ch); + BORDER + x1 * xw.cw, BORDER + y1 * xw.ch, + (x2-x1+1) * xw.cw, (y2-y1+1) * xw.ch); } void @@ -1867,8 +1971,8 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { /* copy buffer pixmap to screen pixmap */ void xcopy() { - XdbeSwapInfo swpinfo[1] = {{xw.win, XdbeCopied}}; - XdbeSwapBuffers(xw.dpy, swpinfo, 1); + XdbeSwapInfo swpinfo[1] = {{xw.win, XdbeCopied}}; + XdbeSwapBuffers(xw.dpy, swpinfo, 1); } @@ -1965,8 +2069,8 @@ expose(XEvent *ev) { if(xw.state & WIN_REDRAW) { if(!e->count) xw.state &= ~WIN_REDRAW; - } - xcopy(); + } + xcopy(); } void