JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
Move unsupported sequences to ignored.
[st.git] / st.c
diff --git a/st.c b/st.c
index 8ef1346..8059b16 100644 (file)
--- a/st.c
+++ b/st.c
@@ -72,8 +72,6 @@
 #define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (b).bg)
 #define IS_SET(flag) (term.mode & (flag))
 #define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + (t1.tv_usec-t2.tv_usec)/1000)
-#define X2COL(x) (((x) - borderpx)/xw.cw)
-#define Y2ROW(y) (((y) - borderpx)/xw.ch)
 
 #define VT102ID "\033[?6c"
 
@@ -98,8 +96,8 @@ enum cursor_movement {
 
 enum cursor_state {
        CURSOR_DEFAULT  = 0,
-       CURSOR_HIDE     = 1,
-       CURSOR_WRAPNEXT = 2
+       CURSOR_WRAPNEXT = 1,
+       CURSOR_ORIGIN   = 2
 };
 
 enum glyph_state {
@@ -117,7 +115,8 @@ enum term_mode {
        MODE_MOUSEMOTION = 64,
        MODE_MOUSE       = 32|64,
        MODE_REVERSE     = 128,
-       MODE_KBDLOCK     = 256
+       MODE_KBDLOCK     = 256,
+       MODE_HIDE      = 512
 };
 
 enum escape_state {
@@ -302,6 +301,7 @@ static void tdeleteline(int);
 static void tinsertblank(int);
 static void tinsertblankline(int);
 static void tmoveto(int, int);
+static void tmoveato(int x, int y);
 static void tnew(int, int);
 static void tnewline(int);
 static void tputtab(bool);
@@ -582,6 +582,22 @@ selinit(void) {
                sel.xtarget = XA_STRING;
 }
 
+static int
+x2col(int x) {
+       x -= borderpx;
+       x /= xw.cw;
+
+       return LIMIT(x, 0, term.col-1);
+}
+
+static int
+y2row(int y) {
+       y -= borderpx;
+       y /= xw.ch;
+
+       return LIMIT(y, 0, term.row-1);
+}
+
 static inline bool
 selected(int x, int y) {
        int bx, ex;
@@ -603,8 +619,9 @@ getbuttoninfo(XEvent *e, int *b, int *x, int *y) {
        if(b)
                *b = e->xbutton.button;
 
-       *x = X2COL(e->xbutton.x);
-       *y = Y2ROW(e->xbutton.y);
+       *x = x2col(e->xbutton.x);
+       *y = y2row(e->xbutton.y);
+
        sel.b.x = sel.by < sel.ey ? sel.bx : sel.ex;
        sel.b.y = MIN(sel.by, sel.ey);
        sel.e.x = sel.by < sel.ey ? sel.ex : sel.bx;
@@ -613,8 +630,8 @@ getbuttoninfo(XEvent *e, int *b, int *x, int *y) {
 
 void
 mousereport(XEvent *e) {
-       int x = X2COL(e->xbutton.x);
-       int y = Y2ROW(e->xbutton.y);
+       int x = x2col(e->xbutton.x);
+       int y = y2row(e->xbutton.y);
        int button = e->xbutton.button;
        int state = e->xbutton.state;
        char buf[] = { '\033', '[', 'M', 0, 32+x+1, 32+y+1 };
@@ -656,8 +673,12 @@ bpress(XEvent *e) {
                        draw();
                }
                sel.mode = 1;
-               sel.ex = sel.bx = X2COL(e->xbutton.x);
-               sel.ey = sel.by = Y2ROW(e->xbutton.y);
+               sel.ex = sel.bx = x2col(e->xbutton.x);
+               sel.ey = sel.by = y2row(e->xbutton.y);
+       } else if(e->xbutton.button == Button4) {
+               ttywrite("\031", 1);
+       } else if(e->xbutton.button == Button5) {
+               ttywrite("\005", 1);
        }
 }
 
@@ -1057,6 +1078,8 @@ treset(void) {
        term.mode = MODE_WRAP;
 
        tclearregion(0, 0, term.col-1, term.row-1);
+       tmoveto(0, 0);
+       tcursor(CURSOR_SAVE);
 }
 
 void
@@ -1190,10 +1213,25 @@ csiparse(void) {
        }
 }
 
+/* for absolute user moves, when decom is set */
+void
+tmoveato(int x, int y) {
+       tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top: 0));
+}
+
 void
 tmoveto(int x, int y) {
+       int miny, maxy;
+
+       if(term.c.state & CURSOR_ORIGIN) {
+               miny = term.top;
+               maxy = term.bot;
+       } else {
+               miny = 0;
+               maxy = term.row - 1;
+       }
        LIMIT(x, 0, term.col-1);
-       LIMIT(y, 0, term.row-1);
+       LIMIT(y, miny, maxy);
        term.c.state &= ~CURSOR_WRAPNEXT;
        term.c.x = x;
        term.c.y = y;
@@ -1435,18 +1473,25 @@ tsetmode(bool priv, bool set, int *args, int narg) {
                                if(mode != term.mode)
                                        redraw();
                                break;
-                       case 6: /* XXX: DECOM -- Origin */
+                       case 6: /* DECOM -- Origin */
+                               MODBIT(term.c.state, set, CURSOR_ORIGIN);
+                               tmoveato(0, 0);
                                break;
                        case 7: /* DECAWM -- Auto wrap */
                                MODBIT(term.mode, set, MODE_WRAP);
                                break;
-                       case 8: /* XXX: DECARM -- Auto repeat */
-                               break;
                        case 0:  /* Error (IGNORED) */
+                       case 2:  /* DECANM -- ANSI/VT52 (IGNORED) */
+                       case 3:  /* DECCOLM -- Column  (IGNORED) */
+                       case 4:  /* DECSCLM -- Scroll (IGNORED) */
+                       case 8:  /* DECARM -- Auto repeat (IGNORED) */
+                       case 18: /* DECPFF -- Printer feed (IGNORED) */
+                       case 19: /* DECPEX -- Printer extent (IGNORED) */
+                       case 42: /* DECNRCM -- National characters (IGNORED) */
                        case 12: /* att610 -- Start blinking cursor (IGNORED) */
                                break;
-                       case 25:
-                               MODBIT(term.c.state, !set, CURSOR_HIDE);
+                       case 25: /* DECTCEM -- Text Cursor Enable Mode */
+                               MODBIT(term.mode, !set, MODE_HIDE);
                                break;
                        case 1000: /* 1000,1002: enable xterm mouse report */
                                MODBIT(term.mode, set, MODE_MOUSEBTN);
@@ -1456,26 +1501,20 @@ tsetmode(bool priv, bool set, int *args, int narg) {
                                break;
                        case 1049: /* = 1047 and 1048 */
                        case 47:
-                       case 1047:
-                               if(IS_SET(MODE_ALTSCREEN))
+                       case 1047: {
+                               bool alt = IS_SET(MODE_ALTSCREEN) != 0;
+                               if(alt)
                                        tclearregion(0, 0, term.col-1, term.row-1);
-                               if((set && !IS_SET(MODE_ALTSCREEN)) ||
-                                               (!set && IS_SET(MODE_ALTSCREEN))) {
+                               if(set ^ alt)           /* set is always 1 or 0 */
                                        tswapscreen();
-                               }
                                if(*args != 1049)
                                        break;
+                       }
                                /* pass through */
                        case 1048:
                                tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD);
                                break;
                        default:
-                       /* case 2:  DECANM -- ANSI/VT52 (NOT SUPPOURTED) */
-                       /* case 3:  DECCOLM -- Column  (NOT SUPPORTED) */
-                       /* case 4:  DECSCLM -- Scroll (NOT SUPPORTED) */
-                       /* case 18: DECPFF -- Printer feed (NOT SUPPORTED) */
-                       /* case 19: DECPEX -- Printer extent (NOT SUPPORTED) */
-                       /* case 42: DECNRCM -- National characters (NOT SUPPORTED) */
                                fprintf(stderr,
                                        "erresc: unknown private set/reset mode %d\n",
                                        *args);
@@ -1522,11 +1561,11 @@ csihandle(void) {
                tinsertblank(csiescseq.arg[0]);
                break;
        case 'A': /* CUU -- Cursor <n> Up */
-       case 'e':
                DEFAULT(csiescseq.arg[0], 1);
                tmoveto(term.c.x, term.c.y-csiescseq.arg[0]);
                break;
        case 'B': /* CUD -- Cursor <n> Down */
+       case 'e': /* VPR --Cursor <n> Down */
                DEFAULT(csiescseq.arg[0], 1);
                tmoveto(term.c.x, term.c.y+csiescseq.arg[0]);
                break;
@@ -1535,7 +1574,7 @@ csihandle(void) {
                        ttywrite(VT102ID, sizeof(VT102ID) - 1);
                break;
        case 'C': /* CUF -- Cursor <n> Forward */
-       case 'a':
+       case 'a': /* HPR -- Cursor <n> Forward */
                DEFAULT(csiescseq.arg[0], 1);
                tmoveto(term.c.x+csiescseq.arg[0], term.c.y);
                break;
@@ -1572,7 +1611,7 @@ csihandle(void) {
        case 'f': /* HVP */
                DEFAULT(csiescseq.arg[0], 1);
                DEFAULT(csiescseq.arg[1], 1);
-               tmoveto(csiescseq.arg[1]-1, csiescseq.arg[0]-1);
+               tmoveato(csiescseq.arg[1]-1, csiescseq.arg[0]-1);
                break;
        case 'I': /* CHT -- Cursor Forward Tabulation <n> tab stops */
                DEFAULT(csiescseq.arg[0], 1);
@@ -1646,7 +1685,7 @@ csihandle(void) {
                break;
        case 'd': /* VPA -- Move to <row> */
                DEFAULT(csiescseq.arg[0], 1);
-               tmoveto(term.c.x, csiescseq.arg[0]-1);
+               tmoveato(term.c.x, csiescseq.arg[0]-1);
                break;
        case 'h': /* SM -- Set terminal mode */
                tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg);
@@ -1661,7 +1700,7 @@ csihandle(void) {
                        DEFAULT(csiescseq.arg[0], 1);
                        DEFAULT(csiescseq.arg[1], term.row);
                        tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1);
-                       tmoveto(0, 0);
+                       tmoveato(0, 0);
                }
                break;
        case 's': /* DECSC -- Save cursor position (ANSI.SYS) */
@@ -1819,8 +1858,8 @@ tputc(char *c, int len) {
                }
        }
        /*
-        * STR sequences must be checked before of anything
-        * because it can use some control codes as part of the sequence
+        * STR sequences must be checked before anything else
+        * because it can use some control codes as part of the sequence.
         */
        if(term.esc & ESC_STR) {
                switch(ascii) {
@@ -1840,6 +1879,7 @@ tputc(char *c, int len) {
                }
                return;
        }
+
        /*
         * Actions of control codes must be performed as soon they arrive
         * because they can be embedded inside a control sequence, and
@@ -1880,11 +1920,11 @@ tputc(char *c, int len) {
                case '\030':    /* CAN */
                        csireset();
                        return;
-                case '\005':   /* ENQ (IGNORED) */
-                case '\000':   /* NUL (IGNORED) */
-                case '\021':   /* XON (IGNORED) */
-                case '\023':   /* XOFF (IGNORED) */
-                case 0177:     /* DEL (IGNORED) */
+               case '\005':    /* ENQ (IGNORED) */
+               case '\000':    /* NUL (IGNORED) */
+               case '\021':    /* XON (IGNORED) */
+               case '\023':    /* XOFF (IGNORED) */
+               case 0177:      /* DEL (IGNORED) */
                        return;
                }
        } else if(term.esc & ESC_START) {
@@ -2097,10 +2137,10 @@ tresize(int col, int row) {
        /* update terminal size */
        term.col = col;
        term.row = row;
-       /* make use of the LIMIT in tmoveto */
-       tmoveto(term.c.x, term.c.y);
        /* reset scrolling region */
        tsetscroll(0, row-1);
+       /* make use of the LIMIT in tmoveto */
+       tmoveto(term.c.x, term.c.y);
 
        return (slide > 0);
 }
@@ -2383,9 +2423,6 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
                 *temp, revfg, revbg;
        XRenderColor colfg, colbg;
 
-       if(base.mode & ATTR_REVERSE)
-               temp = fg, fg = bg, bg = temp;
-
        if(base.mode & ATTR_BOLD) {
                if(BETWEEN(base.fg, 0, 7)) {
                        /* basic system colors */
@@ -2408,7 +2445,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
 
        if(base.mode & ATTR_ITALIC)
                font = &dc.ifont;
-       if(base.mode & (ATTR_ITALIC|ATTR_BOLD))
+       if((base.mode & ATTR_ITALIC) && (base.mode & ATTR_BOLD))
                font = &dc.ibfont;
 
        if(IS_SET(MODE_REVERSE)) {
@@ -2435,6 +2472,9 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
                }
        }
 
+       if(base.mode & ATTR_REVERSE)
+               temp = fg, fg = bg, bg = temp;
+
        XftTextExtentsUtf8(xw.dpy, font->xft_set, (FcChar8 *)s, bytelen,
                        &extents);
        width = extents.xOff;
@@ -2485,7 +2525,7 @@ xdrawcursor(void) {
        }
 
        /* draw the new one */
-       if(!(term.c.state & CURSOR_HIDE)) {
+       if(!(IS_SET(MODE_HIDE))) {
                if(!(xw.state & WIN_FOCUSED))
                        g.bg = defaultucs;
 
@@ -2526,9 +2566,9 @@ drawregion(int x1, int y1, int x2, int y2) {
        int ic, ib, x, y, ox, sl;
        Glyph base, new;
        char buf[DRAW_BUF_SIZ];
-       bool ena_sel = sel.bx != -1, alt = IS_SET(MODE_ALTSCREEN);
+       bool ena_sel = sel.bx != -1, alt = IS_SET(MODE_ALTSCREEN) != 0;
 
-       if((sel.alt && !alt) || (!sel.alt && alt))
+       if((sel.alt != 0) ^ alt)
                ena_sel = 0;
        if(!(xw.state & WIN_VISIBLE))
                return;
@@ -2679,6 +2719,9 @@ kpress(XEvent *ev) {
                                selpaste();
                        break;
                case XK_Return:
+                       if(meta)
+                               ttywrite("\033", 1);
+
                        if(IS_SET(MODE_CRLF)) {
                                ttywrite("\r\n", 2);
                        } else {
@@ -2727,8 +2770,6 @@ cresize(int width, int height)
 
        col = (xw.w - 2*borderpx) / xw.cw;
        row = (xw.h - 2*borderpx) / xw.ch;
-       if(col == term.col && row == term.row)
-               return;
 
        tresize(col, row);
        xresize(col, row);