JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
Make line drawing work again.
[st.git] / st.c
diff --git a/st.c b/st.c
index 213541f..769de8b 100644 (file)
--- a/st.c
+++ b/st.c
 #define XEMBED_FOCUS_OUT 5
 
 /* Arbitrary sizes */
-#define ESC_BUF_SIZ   256
+#define UTF_SIZ       4
+#define ESC_BUF_SIZ   (128*UTF_SIZ)
 #define ESC_ARG_SIZ   16
-#define STR_BUF_SIZ   256
-#define STR_ARG_SIZ   16
+#define STR_BUF_SIZ   ESC_BUF_SIZ
+#define STR_ARG_SIZ   ESC_ARG_SIZ
 #define DRAW_BUF_SIZ  20*1024
-#define UTF_SIZ       4
 #define XK_ANY_MOD    UINT_MAX
 #define XK_NO_MOD     0
 
@@ -168,7 +168,7 @@ typedef struct {
        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;
 
@@ -203,7 +203,7 @@ typedef struct {
        Display *dpy;
        Colourmap cmap;
        Window win;
-       XdbeBackBuffer buf;
+       Drawable buf;
        Atom xembed, wmdeletewin;
        XIM xim;
        XIC xic;
@@ -213,8 +213,7 @@ typedef struct {
        bool isfixed; /* is fixed geometry? */
        int fx, fy, fw, fh; /* fixed geometry */
        int tw, th; /* tty width and height */
-       int w;  /* window width */
-       int h;  /* window height */
+       int w, h; /* window width and height */
        int ch; /* char height */
        int cw; /* char width  */
        char state; /* focus, redraw, visible */
@@ -284,11 +283,12 @@ typedef struct {
 typedef struct {
        Colour col[LEN(colorname) < 256 ? 256 : LEN(colorname)];
        Font font, bfont, ifont, ibfont;
+       GC gc;
 } DC;
 
 static void die(const char *, ...);
 static void draw(void);
-static void redraw(void);
+static void redraw(int);
 static void drawregion(int, int, int, int);
 static void execsh(void);
 static void sigchld(int);
@@ -414,6 +414,8 @@ static char *opt_embed = NULL;
 static char *opt_class = NULL;
 static char *opt_font = NULL;
 
+bool usedbe = False;
+
 static char *usedfont = NULL;
 static int usedfontsize = 0;
 
@@ -1508,7 +1510,7 @@ tsetmode(bool priv, bool set, int *args, int narg) {
                                mode = term.mode;
                                MODBIT(term.mode, set, MODE_REVERSE);
                                if(mode != term.mode)
-                                       redraw();
+                                       redraw(REDRAW_TIMEOUT);
                                break;
                        case 6: /* DECOM -- Origin */
                                MODBIT(term.c.state, set, CURSOR_ORIGIN);
@@ -1911,12 +1913,13 @@ tputc(char *c, int len) {
 
        if(iofd != -1) {
                if (xwrite(iofd, c, len) < 0) {
-                       fprintf(stderr, "Error writting in %s:%s\n",
+                       fprintf(stderr, "Error writing in %s:%s\n",
                                opt_io, strerror(errno));
                        close(iofd);
                        iofd = -1;
                }
        }
+
        /*
         * STR sequences must be checked before anything else
         * because it can use some control codes as part of the sequence.
@@ -1931,10 +1934,23 @@ tputc(char *c, int len) {
                        strhandle();
                        break;
                default:
-                       strescseq.buf[strescseq.len++] = ascii;
-                       if(strescseq.len+1 >= STR_BUF_SIZ) {
-                               term.esc = 0;
-                               strhandle();
+                       if(strescseq.len + len < sizeof(strescseq.buf)) {
+                               memmove(&strescseq.buf[strescseq.len], c, len);
+                               strescseq.len += len;
+                       } else {
+                       /*
+                        * Here is a bug in terminals. If the user never sends
+                        * some code to stop the str or esc command, then st
+                        * will stop responding. But this is better than
+                        * silently failing with unknown characters. At least
+                        * then users will report back.
+                        *
+                        * In the case users ever get fixed, here is the code:
+                        */
+                       /*
+                        * term.esc = 0;
+                        * strhandle();
+                        */
                        }
                }
                return;
@@ -1971,10 +1987,13 @@ tputc(char *c, int len) {
                        term.esc = ESC_START;
                        return;
                case '\016':    /* SO */
-                       term.c.attr.mode |= ATTR_GFX;
-                       return;
                case '\017':    /* SI */
-                       term.c.attr.mode &= ~ATTR_GFX;
+                       /*
+                        * Different charsets are hard to handle. Applications
+                        * should use the right alt charset escapes for the
+                        * only reason they still exist: line drawing. The
+                        * rest is incompatible history st should not support.
+                        */
                        return;
                case '\032':    /* SUB */
                case '\030':    /* CAN */
@@ -2218,6 +2237,14 @@ xresize(int col, int row) {
        xw.tw = MAX(1, col * xw.cw);
        xw.th = MAX(1, row * xw.ch);
 
+       if(!usedbe) {
+               XFreePixmap(xw.dpy, xw.buf);
+               xw.buf = XCreatePixmap(xw.dpy, xw.win, xw.w, xw.h,
+                               DefaultDepth(xw.dpy, xw.scr));
+               XSetForeground(xw.dpy, dc.gc, 0);
+               XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, xw.w, xw.h);
+       }
+
        XftDrawChange(xw.draw, xw.buf);
 }
 
@@ -2433,7 +2460,7 @@ xzoom(const Arg *arg)
        xunloadfonts();
        xloadfonts(usedfont, usedfontsize + arg->i);
        cresize(0, 0);
-       draw();
+       redraw(0);
 }
 
 void
@@ -2486,7 +2513,8 @@ xinit(void) {
                | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask;
        attrs.colormap = xw.cmap;
 
-       parent = opt_embed ? strtol(opt_embed, NULL, 0) : XRootWindow(xw.dpy, xw.scr);
+       parent = opt_embed ? strtol(opt_embed, NULL, 0) : \
+                       XRootWindow(xw.dpy, xw.scr);
        xw.win = XCreateWindow(xw.dpy, parent, xw.fx, xw.fy,
                        xw.w, xw.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput,
                        xw.vis,
@@ -2495,9 +2523,22 @@ xinit(void) {
                        &attrs);
 
        /* double buffering */
-       if(!XdbeQueryExtension(xw.dpy, &major, &minor))
-               die("Xdbe extension is not present\n");
-       xw.buf = XdbeAllocateBackBufferName(xw.dpy, xw.win, XdbeBackground);
+       /*
+       if(XdbeQueryExtension(xw.dpy, &major, &minor)) {
+               xw.buf = XdbeAllocateBackBufferName(xw.dpy, xw.win,
+                               XdbeBackground);
+               usedbe = True;
+       } else {
+       */
+               dc.gc = XCreateGC(xw.dpy, parent, 0, 0);
+               xw.buf = XCreatePixmap(xw.dpy, xw.win, xw.w, xw.h,
+                               DefaultDepth(xw.dpy, xw.scr));
+               XSetForeground(xw.dpy, dc.gc, 0);
+               XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, xw.w, xw.h);
+               //xw.buf = xw.win;
+       /*
+       }
+       */
 
        /* Xft rendering context */
        xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap);
@@ -2794,13 +2835,16 @@ xresettitle(void) {
 }
 
 void
-redraw(void) {
-       struct timespec tv = {0, REDRAW_TIMEOUT * 1000};
+redraw(int timeout) {
+       struct timespec tv = {0, timeout * 1000};
 
        tfulldirt();
        draw();
-       XSync(xw.dpy, False); /* necessary for a good tput flash */
-       nanosleep(&tv, NULL);
+
+       if(timeout > 0) {
+               nanosleep(&tv, NULL);
+               XSync(xw.dpy, False); /* necessary for a good tput flash */
+       }
 }
 
 void
@@ -2808,7 +2852,14 @@ draw(void) {
        XdbeSwapInfo swpinfo[1] = {{xw.win, XdbeCopied}};
 
        drawregion(0, 0, term.col, term.row);
-       XdbeSwapBuffers(xw.dpy, swpinfo, 1);
+       if(usedbe) {
+               XdbeSwapBuffers(xw.dpy, swpinfo, 1);
+       } else {
+               XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, xw.w,
+                               xw.h, 0, 0);
+               XSetForeground(xw.dpy, dc.gc, 0);
+               XSync(xw.dpy, False);
+       }
 }
 
 void
@@ -2867,6 +2918,7 @@ expose(XEvent *ev) {
                if(!e->count)
                        xw.state &= ~WIN_REDRAW;
        }
+       redraw(0);
 }
 
 void