From 9a3d6a6639d5a454ecc5dfc1118d887dd8737fa5 Mon Sep 17 00:00:00 2001 From: = <=> Date: Fri, 15 Jan 2021 15:52:04 -0500 Subject: [PATCH] Add focus patch --- config.def.h | 5 +- config.def.h.orig | 6 +- config.h | 11 +- st | Bin 0 -> 98624 bytes st-focus-20200731-patch_alpha.diff | 167 ++ st.c | 1 - st.c.orig | 2597 ++++++++++++++++++++++++++++ st.h | 3 +- st.h.orig | 1 + st.o | Bin 0 -> 72936 bytes x.c | 44 +- x.c.orig | 40 +- x.o | Bin 0 -> 74304 bytes 13 files changed, 2841 insertions(+), 34 deletions(-) create mode 100755 st create mode 100644 st-focus-20200731-patch_alpha.diff create mode 100644 st.c.orig create mode 100644 st.o create mode 100644 x.o diff --git a/config.def.h b/config.def.h index b4fff92..56dc300 100644 --- a/config.def.h +++ b/config.def.h @@ -94,7 +94,7 @@ char *termname = "st-256color"; unsigned int tabspaces = 8; /* bg opacity */ -float alpha = 0.8; +float alpha = 0.8, alphaUnfocused = 0.6; /* Terminal colors (16 first used in escape sequence) */ static const char *colorname[] = { @@ -132,9 +132,10 @@ static const char *colorname[] = { * foreground, background, cursor, reverse cursor */ unsigned int defaultfg = 7; -unsigned int defaultbg = 258; +unsigned int defaultbg = 0; static unsigned int defaultcs = 256; static unsigned int defaultrcs = 257; +unsigned int bg = 17, bgUnfocused = 16; /* * Default shape of cursor diff --git a/config.def.h.orig b/config.def.h.orig index 6f05dce..b4fff92 100644 --- a/config.def.h.orig +++ b/config.def.h.orig @@ -93,6 +93,9 @@ char *termname = "st-256color"; */ unsigned int tabspaces = 8; +/* bg opacity */ +float alpha = 0.8; + /* Terminal colors (16 first used in escape sequence) */ static const char *colorname[] = { /* 8 normal colors */ @@ -120,6 +123,7 @@ static const char *colorname[] = { /* more colors can be added after 255 to use with DefaultXX */ "#cccccc", "#555555", + "black", }; @@ -128,7 +132,7 @@ static const char *colorname[] = { * foreground, background, cursor, reverse cursor */ unsigned int defaultfg = 7; -unsigned int defaultbg = 0; +unsigned int defaultbg = 258; static unsigned int defaultcs = 256; static unsigned int defaultrcs = 257; diff --git a/config.h b/config.h index b4fff92..fc5e685 100644 --- a/config.h +++ b/config.h @@ -5,7 +5,7 @@ * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; +static char *font = "SauceCodePro NF:pixelsize=12:antialias=true:autohint=true"; static int borderpx = 2; /* @@ -53,8 +53,8 @@ int allowwindowops = 0; * near minlatency, but it waits longer for slow updates to avoid partial draw. * low minlatency will tear/flicker more, as it can "detect" idle too early. */ -static double minlatency = 8; -static double maxlatency = 33; +static double minlatency = 22; +static double maxlatency = 66; /* * blinking timeout (set to 0 to disable blinking) for the terminal blinking @@ -94,7 +94,7 @@ char *termname = "st-256color"; unsigned int tabspaces = 8; /* bg opacity */ -float alpha = 0.8; +float alpha = 0.5, alphaUnfocused = 0.3; /* Terminal colors (16 first used in escape sequence) */ static const char *colorname[] = { @@ -132,9 +132,10 @@ static const char *colorname[] = { * foreground, background, cursor, reverse cursor */ unsigned int defaultfg = 7; -unsigned int defaultbg = 258; +unsigned int defaultbg = 0; static unsigned int defaultcs = 256; static unsigned int defaultrcs = 257; +unsigned int bg = 16, bgUnfocused = 16; /* * Default shape of cursor diff --git a/st b/st new file mode 100755 index 0000000000000000000000000000000000000000..9cac99d288d7ea1200dcb339bbfee786261dbda9 GIT binary patch literal 98624 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 Z-V=SPcomMwJ;^)yeW$@X0o|ka{{WEF9c%yq literal 0 HcmV?d00001 diff --git a/st-focus-20200731-patch_alpha.diff b/st-focus-20200731-patch_alpha.diff new file mode 100644 index 0000000..42166b7 --- /dev/null +++ b/st-focus-20200731-patch_alpha.diff @@ -0,0 +1,167 @@ +From 3307b33b60adb4e1b5db4dd9849c78fce72b6ca4 Mon Sep 17 00:00:00 2001 +From: Julius Huelsmann +Date: Fri, 31 Jul 2020 10:13:30 +0200 +Subject: [PATCH] patch: focus + +--- + config.def.h | 5 +++-- + st.c | 1 - + st.h | 3 ++- + x.c | 44 ++++++++++++++++++++++++++++++-------------- + 4 files changed, 35 insertions(+), 18 deletions(-) + +diff --git a/config.def.h b/config.def.h +index b94b23c..577d1f1 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -85,7 +85,7 @@ char *termname = "st-256color"; + unsigned int tabspaces = 8; + + /* bg opacity */ +-float alpha = 0.8; ++float alpha = 0.8, alphaUnfocused = 0.6; + + /* Terminal colors (16 first used in escape sequence) */ + static const char *colorname[] = { +@@ -123,9 +123,10 @@ static const char *colorname[] = { + * foreground, background, cursor, reverse cursor + */ + unsigned int defaultfg = 7; +-unsigned int defaultbg = 258; ++unsigned int defaultbg = 0; + static unsigned int defaultcs = 256; + static unsigned int defaultrcs = 257; ++unsigned int bg = 17, bgUnfocused = 16; + + /* + * Default shape of cursor +diff --git a/st.c b/st.c +index 0ce6ac2..c7f40c8 100644 +--- a/st.c ++++ b/st.c +@@ -194,7 +194,6 @@ static void tsetscroll(int, int); + static void tswapscreen(void); + static void tsetmode(int, int, int *, int); + static int twrite(const char *, int, int); +-static void tfulldirt(void); + static void tcontrolcode(uchar ); + static void tdectest(char ); + static void tdefutf8(char); +diff --git a/st.h b/st.h +index 2c656af..44cb3fd 100644 +--- a/st.h ++++ b/st.h +@@ -79,6 +79,7 @@ typedef union { + + void die(const char *, ...); + void redraw(void); ++void tfulldirt(void); + void draw(void); + + void printscreen(const Arg *); +@@ -122,4 +123,4 @@ extern char *termname; + extern unsigned int tabspaces; + extern unsigned int defaultfg; + extern unsigned int defaultbg; +-extern float alpha; ++extern float alpha, alphaUnfocused; +diff --git a/x.c b/x.c +index 50da23c..a2e820f 100644 +--- a/x.c ++++ b/x.c +@@ -254,6 +254,8 @@ static char *opt_line = NULL; + static char *opt_name = NULL; + static char *opt_title = NULL; + ++static int focused = 0; ++ + static int oldbutton = 3; /* button event on startup: 3 = release */ + + void +@@ -774,35 +776,38 @@ xloadcolor(int i, const char *name, Color *ncolor) + return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); + } + ++void ++xloadalpha(void) ++{ ++ float const usedAlpha = focused ? alpha : alphaUnfocused; ++ if (opt_alpha) alpha = strtof(opt_alpha, NULL); ++ dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * usedAlpha); ++ dc.col[defaultbg].pixel &= 0x00FFFFFF; ++ dc.col[defaultbg].pixel |= (unsigned char)(0xff * usedAlpha) << 24; ++} ++ + void + xloadcols(void) + { +- int i; + static int loaded; + Color *cp; + +- if (loaded) { +- for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) +- XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); +- } else { +- dc.collen = MAX(LEN(colorname), 256); +- dc.col = xmalloc(dc.collen * sizeof(Color)); ++ if (!loaded) { ++ dc.collen = 1 + (defaultbg = MAX(LEN(colorname), 256)); ++ dc.col = xmalloc((dc.collen) * sizeof(Color)); + } + +- for (i = 0; i < dc.collen; i++) ++ for (int i = 0; i+1 < dc.collen; ++i) + if (!xloadcolor(i, NULL, &dc.col[i])) { + if (colorname[i]) + die("could not allocate color '%s'\n", colorname[i]); + else + die("could not allocate color %d\n", i); + } ++ if (dc.collen) // cannot die, as the color is already loaded. ++ xloadcolor(focused ?bg :bgUnfocused, NULL, &dc.col[defaultbg]); + +- /* set alpha value of bg color */ +- if (opt_alpha) +- alpha = strtof(opt_alpha, NULL); +- dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); +- dc.col[defaultbg].pixel &= 0x00FFFFFF; +- dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; ++ xloadalpha(); + loaded = 1; + } + +@@ -1747,12 +1752,22 @@ focus(XEvent *ev) + xseturgency(0); + if (IS_SET(MODE_FOCUS)) + ttywrite("\033[I", 3, 0); ++ if (!focused) { ++ focused = 1; ++ xloadcols(); ++ tfulldirt(); ++ } + } else { + if (xw.ime.xic) + XUnsetICFocus(xw.ime.xic); + win.mode &= ~MODE_FOCUSED; + if (IS_SET(MODE_FOCUS)) + ttywrite("\033[O", 3, 0); ++ if (focused) { ++ focused = 0; ++ xloadcols(); ++ tfulldirt(); ++ } + } + } + +@@ -2065,6 +2080,7 @@ run: + XSetLocaleModifiers(""); + cols = MAX(cols, 1); + rows = MAX(rows, 1); ++ defaultbg = MAX(LEN(colorname), 256); + tnew(cols, rows); + xinit(cols, rows); + xsetenv(); +-- +2.28.0 + diff --git a/st.c b/st.c index 76b7e0d..83c42af 100644 --- a/st.c +++ b/st.c @@ -193,7 +193,6 @@ static void tsetscroll(int, int); static void tswapscreen(void); static void tsetmode(int, int, int *, int); static int twrite(const char *, int, int); -static void tfulldirt(void); static void tcontrolcode(uchar ); static void tdectest(char ); static void tdefutf8(char); diff --git a/st.c.orig b/st.c.orig new file mode 100644 index 0000000..76b7e0d --- /dev/null +++ b/st.c.orig @@ -0,0 +1,2597 @@ +/* See LICENSE for license details. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "st.h" +#include "win.h" + +#if defined(__linux) + #include +#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) + #include +#elif defined(__FreeBSD__) || defined(__DragonFly__) + #include +#endif + +/* Arbitrary sizes */ +#define UTF_INVALID 0xFFFD +#define UTF_SIZ 4 +#define ESC_BUF_SIZ (128*UTF_SIZ) +#define ESC_ARG_SIZ 16 +#define STR_BUF_SIZ ESC_BUF_SIZ +#define STR_ARG_SIZ ESC_ARG_SIZ + +/* macros */ +#define IS_SET(flag) ((term.mode & (flag)) != 0) +#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f) +#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) +#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) +#define ISDELIM(u) (u && wcschr(worddelimiters, u)) + +enum term_mode { + MODE_WRAP = 1 << 0, + MODE_INSERT = 1 << 1, + MODE_ALTSCREEN = 1 << 2, + MODE_CRLF = 1 << 3, + MODE_ECHO = 1 << 4, + MODE_PRINT = 1 << 5, + MODE_UTF8 = 1 << 6, +}; + +enum cursor_movement { + CURSOR_SAVE, + CURSOR_LOAD +}; + +enum cursor_state { + CURSOR_DEFAULT = 0, + CURSOR_WRAPNEXT = 1, + CURSOR_ORIGIN = 2 +}; + +enum charset { + CS_GRAPHIC0, + CS_GRAPHIC1, + CS_UK, + CS_USA, + CS_MULTI, + CS_GER, + CS_FIN +}; + +enum escape_state { + ESC_START = 1, + ESC_CSI = 2, + ESC_STR = 4, /* DCS, OSC, PM, APC */ + ESC_ALTCHARSET = 8, + ESC_STR_END = 16, /* a final string was encountered */ + ESC_TEST = 32, /* Enter in test mode */ + ESC_UTF8 = 64, +}; + +typedef struct { + Glyph attr; /* current char attributes */ + int x; + int y; + char state; +} TCursor; + +typedef struct { + int mode; + int type; + int snap; + /* + * Selection variables: + * nb – normalized coordinates of the beginning of the selection + * ne – normalized coordinates of the end of the selection + * ob – original coordinates of the beginning of the selection + * oe – original coordinates of the end of the selection + */ + struct { + int x, y; + } nb, ne, ob, oe; + + int alt; +} Selection; + +/* Internal representation of the screen */ +typedef struct { + int row; /* nb row */ + int col; /* nb col */ + Line *line; /* screen */ + Line *alt; /* alternate screen */ + int *dirty; /* dirtyness of lines */ + TCursor c; /* cursor */ + int ocx; /* old cursor col */ + int ocy; /* old cursor row */ + int top; /* top scroll limit */ + int bot; /* bottom scroll limit */ + int mode; /* terminal mode flags */ + int esc; /* escape state flags */ + char trantbl[4]; /* charset table translation */ + int charset; /* current charset */ + int icharset; /* selected charset for sequence */ + int *tabs; + Rune lastc; /* last printed char outside of sequence, 0 if control */ +} Term; + +/* CSI Escape sequence structs */ +/* ESC '[' [[ [] [;]] []] */ +typedef struct { + char buf[ESC_BUF_SIZ]; /* raw string */ + size_t len; /* raw string length */ + char priv; + int arg[ESC_ARG_SIZ]; + int narg; /* nb of args */ + char mode[2]; +} CSIEscape; + +/* STR Escape sequence structs */ +/* ESC type [[ [] [;]] ] ESC '\' */ +typedef struct { + char type; /* ESC type ... */ + char *buf; /* allocated raw string */ + size_t siz; /* allocation size */ + size_t len; /* raw string length */ + char *args[STR_ARG_SIZ]; + int narg; /* nb of args */ +} STREscape; + +static void execsh(char *, char **); +static void stty(char **); +static void sigchld(int); +static void ttywriteraw(const char *, size_t); + +static void csidump(void); +static void csihandle(void); +static void csiparse(void); +static void csireset(void); +static int eschandle(uchar); +static void strdump(void); +static void strhandle(void); +static void strparse(void); +static void strreset(void); + +static void tprinter(char *, size_t); +static void tdumpsel(void); +static void tdumpline(int); +static void tdump(void); +static void tclearregion(int, int, int, int); +static void tcursor(int); +static void tdeletechar(int); +static void tdeleteline(int); +static void tinsertblank(int); +static void tinsertblankline(int); +static int tlinelen(int); +static void tmoveto(int, int); +static void tmoveato(int, int); +static void tnewline(int); +static void tputtab(int); +static void tputc(Rune); +static void treset(void); +static void tscrollup(int, int); +static void tscrolldown(int, int); +static void tsetattr(int *, int); +static void tsetchar(Rune, Glyph *, int, int); +static void tsetdirt(int, int); +static void tsetscroll(int, int); +static void tswapscreen(void); +static void tsetmode(int, int, int *, int); +static int twrite(const char *, int, int); +static void tfulldirt(void); +static void tcontrolcode(uchar ); +static void tdectest(char ); +static void tdefutf8(char); +static int32_t tdefcolor(int *, int *, int); +static void tdeftran(char); +static void tstrsequence(uchar); + +static void drawregion(int, int, int, int); + +static void selnormalize(void); +static void selscroll(int, int); +static void selsnap(int *, int *, int); + +static size_t utf8decode(const char *, Rune *, size_t); +static Rune utf8decodebyte(char, size_t *); +static char utf8encodebyte(Rune, size_t); +static size_t utf8validate(Rune *, size_t); + +static char *base64dec(const char *); +static char base64dec_getc(const char **); + +static ssize_t xwrite(int, const char *, size_t); + +/* Globals */ +static Term term; +static Selection sel; +static CSIEscape csiescseq; +static STREscape strescseq; +static int iofd = 1; +static int cmdfd; +static pid_t pid; + +static uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; +static Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; + +ssize_t +xwrite(int fd, const char *s, size_t len) +{ + size_t aux = len; + ssize_t r; + + while (len > 0) { + r = write(fd, s, len); + if (r < 0) + return r; + len -= r; + s += r; + } + + return aux; +} + +void * +xmalloc(size_t len) +{ + void *p; + + if (!(p = malloc(len))) + die("malloc: %s\n", strerror(errno)); + + return p; +} + +void * +xrealloc(void *p, size_t len) +{ + if ((p = realloc(p, len)) == NULL) + die("realloc: %s\n", strerror(errno)); + + return p; +} + +char * +xstrdup(char *s) +{ + if ((s = strdup(s)) == NULL) + die("strdup: %s\n", strerror(errno)); + + return s; +} + +size_t +utf8decode(const char *c, Rune *u, size_t clen) +{ + size_t i, j, len, type; + Rune udecoded; + + *u = UTF_INVALID; + if (!clen) + return 0; + udecoded = utf8decodebyte(c[0], &len); + if (!BETWEEN(len, 1, UTF_SIZ)) + return 1; + for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); + if (type != 0) + return j; + } + if (j < len) + return 0; + *u = udecoded; + utf8validate(u, len); + + return len; +} + +Rune +utf8decodebyte(char c, size_t *i) +{ + for (*i = 0; *i < LEN(utfmask); ++(*i)) + if (((uchar)c & utfmask[*i]) == utfbyte[*i]) + return (uchar)c & ~utfmask[*i]; + + return 0; +} + +size_t +utf8encode(Rune u, char *c) +{ + size_t len, i; + + len = utf8validate(&u, 0); + if (len > UTF_SIZ) + return 0; + + for (i = len - 1; i != 0; --i) { + c[i] = utf8encodebyte(u, 0); + u >>= 6; + } + c[0] = utf8encodebyte(u, len); + + return len; +} + +char +utf8encodebyte(Rune u, size_t i) +{ + return utfbyte[i] | (u & ~utfmask[i]); +} + +size_t +utf8validate(Rune *u, size_t i) +{ + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) + *u = UTF_INVALID; + for (i = 1; *u > utfmax[i]; ++i) + ; + + return i; +} + +static const char base64_digits[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, + 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, -1, 0, 0, 0, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +char +base64dec_getc(const char **src) +{ + while (**src && !isprint(**src)) + (*src)++; + return **src ? *((*src)++) : '='; /* emulate padding if string ends */ +} + +char * +base64dec(const char *src) +{ + size_t in_len = strlen(src); + char *result, *dst; + + if (in_len % 4) + in_len += 4 - (in_len % 4); + result = dst = xmalloc(in_len / 4 * 3 + 1); + while (*src) { + int a = base64_digits[(unsigned char) base64dec_getc(&src)]; + int b = base64_digits[(unsigned char) base64dec_getc(&src)]; + int c = base64_digits[(unsigned char) base64dec_getc(&src)]; + int d = base64_digits[(unsigned char) base64dec_getc(&src)]; + + /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ + if (a == -1 || b == -1) + break; + + *dst++ = (a << 2) | ((b & 0x30) >> 4); + if (c == -1) + break; + *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); + if (d == -1) + break; + *dst++ = ((c & 0x03) << 6) | d; + } + *dst = '\0'; + return result; +} + +void +selinit(void) +{ + sel.mode = SEL_IDLE; + sel.snap = 0; + sel.ob.x = -1; +} + +int +tlinelen(int y) +{ + int i = term.col; + + if (term.line[y][i - 1].mode & ATTR_WRAP) + return i; + + while (i > 0 && term.line[y][i - 1].u == ' ') + --i; + + return i; +} + +void +selstart(int col, int row, int snap) +{ + selclear(); + sel.mode = SEL_EMPTY; + sel.type = SEL_REGULAR; + sel.alt = IS_SET(MODE_ALTSCREEN); + sel.snap = snap; + sel.oe.x = sel.ob.x = col; + sel.oe.y = sel.ob.y = row; + selnormalize(); + + if (sel.snap != 0) + sel.mode = SEL_READY; + tsetdirt(sel.nb.y, sel.ne.y); +} + +void +selextend(int col, int row, int type, int done) +{ + int oldey, oldex, oldsby, oldsey, oldtype; + + if (sel.mode == SEL_IDLE) + return; + if (done && sel.mode == SEL_EMPTY) { + selclear(); + return; + } + + oldey = sel.oe.y; + oldex = sel.oe.x; + oldsby = sel.nb.y; + oldsey = sel.ne.y; + oldtype = sel.type; + + sel.oe.x = col; + sel.oe.y = row; + selnormalize(); + sel.type = type; + + if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SEL_EMPTY) + tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); + + sel.mode = done ? SEL_IDLE : SEL_READY; +} + +void +selnormalize(void) +{ + int i; + + if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { + sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; + sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; + } else { + sel.nb.x = MIN(sel.ob.x, sel.oe.x); + sel.ne.x = MAX(sel.ob.x, sel.oe.x); + } + sel.nb.y = MIN(sel.ob.y, sel.oe.y); + sel.ne.y = MAX(sel.ob.y, sel.oe.y); + + selsnap(&sel.nb.x, &sel.nb.y, -1); + selsnap(&sel.ne.x, &sel.ne.y, +1); + + /* expand selection over line breaks */ + if (sel.type == SEL_RECTANGULAR) + return; + i = tlinelen(sel.nb.y); + if (i < sel.nb.x) + sel.nb.x = i; + if (tlinelen(sel.ne.y) <= sel.ne.x) + sel.ne.x = term.col - 1; +} + +int +selected(int x, int y) +{ + if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || + sel.alt != IS_SET(MODE_ALTSCREEN)) + return 0; + + if (sel.type == SEL_RECTANGULAR) + return BETWEEN(y, sel.nb.y, sel.ne.y) + && BETWEEN(x, sel.nb.x, sel.ne.x); + + return BETWEEN(y, sel.nb.y, sel.ne.y) + && (y != sel.nb.y || x >= sel.nb.x) + && (y != sel.ne.y || x <= sel.ne.x); +} + +void +selsnap(int *x, int *y, int direction) +{ + int newx, newy, xt, yt; + int delim, prevdelim; + Glyph *gp, *prevgp; + + switch (sel.snap) { + case SNAP_WORD: + /* + * Snap around if the word wraps around at the end or + * beginning of a line. + */ + prevgp = &term.line[*y][*x]; + prevdelim = ISDELIM(prevgp->u); + for (;;) { + newx = *x + direction; + newy = *y; + if (!BETWEEN(newx, 0, term.col - 1)) { + newy += direction; + newx = (newx + term.col) % term.col; + if (!BETWEEN(newy, 0, term.row - 1)) + break; + + if (direction > 0) + yt = *y, xt = *x; + else + yt = newy, xt = newx; + if (!(term.line[yt][xt].mode & ATTR_WRAP)) + break; + } + + if (newx >= tlinelen(newy)) + break; + + gp = &term.line[newy][newx]; + delim = ISDELIM(gp->u); + if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim + || (delim && gp->u != prevgp->u))) + break; + + *x = newx; + *y = newy; + prevgp = gp; + prevdelim = delim; + } + break; + case SNAP_LINE: + /* + * Snap around if the the previous line or the current one + * has set ATTR_WRAP at its end. Then the whole next or + * previous line will be selected. + */ + *x = (direction < 0) ? 0 : term.col - 1; + if (direction < 0) { + for (; *y > 0; *y += direction) { + if (!(term.line[*y-1][term.col-1].mode + & ATTR_WRAP)) { + break; + } + } + } else if (direction > 0) { + for (; *y < term.row-1; *y += direction) { + if (!(term.line[*y][term.col-1].mode + & ATTR_WRAP)) { + break; + } + } + } + break; + } +} + +char * +getsel(void) +{ + char *str, *ptr; + int y, bufsize, lastx, linelen; + Glyph *gp, *last; + + if (sel.ob.x == -1) + return NULL; + + bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; + ptr = str = xmalloc(bufsize); + + /* append every set & selected glyph to the selection */ + for (y = sel.nb.y; y <= sel.ne.y; y++) { + if ((linelen = tlinelen(y)) == 0) { + *ptr++ = '\n'; + continue; + } + + if (sel.type == SEL_RECTANGULAR) { + gp = &term.line[y][sel.nb.x]; + lastx = sel.ne.x; + } else { + gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; + lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; + } + last = &term.line[y][MIN(lastx, linelen-1)]; + while (last >= gp && last->u == ' ') + --last; + + for ( ; gp <= last; ++gp) { + if (gp->mode & ATTR_WDUMMY) + continue; + + ptr += utf8encode(gp->u, ptr); + } + + /* + * Copy and pasting of line endings is inconsistent + * in the inconsistent terminal and GUI world. + * The best solution seems like to produce '\n' when + * something is copied from st and convert '\n' to + * '\r', when something to be pasted is received by + * st. + * FIXME: Fix the computer world. + */ + if ((y < sel.ne.y || lastx >= linelen) && + (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) + *ptr++ = '\n'; + } + *ptr = 0; + return str; +} + +void +selclear(void) +{ + if (sel.ob.x == -1) + return; + sel.mode = SEL_IDLE; + sel.ob.x = -1; + tsetdirt(sel.nb.y, sel.ne.y); +} + +void +die(const char *errstr, ...) +{ + va_list ap; + + va_start(ap, errstr); + vfprintf(stderr, errstr, ap); + va_end(ap); + exit(1); +} + +void +execsh(char *cmd, char **args) +{ + char *sh, *prog, *arg; + const struct passwd *pw; + + errno = 0; + if ((pw = getpwuid(getuid())) == NULL) { + if (errno) + die("getpwuid: %s\n", strerror(errno)); + else + die("who are you?\n"); + } + + if ((sh = getenv("SHELL")) == NULL) + sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; + + if (args) { + prog = args[0]; + arg = NULL; + } else if (scroll) { + prog = scroll; + arg = utmp ? utmp : sh; + } else if (utmp) { + prog = utmp; + arg = NULL; + } else { + prog = sh; + arg = NULL; + } + DEFAULT(args, ((char *[]) {prog, arg, NULL})); + + unsetenv("COLUMNS"); + unsetenv("LINES"); + unsetenv("TERMCAP"); + setenv("LOGNAME", pw->pw_name, 1); + setenv("USER", pw->pw_name, 1); + setenv("SHELL", sh, 1); + setenv("HOME", pw->pw_dir, 1); + setenv("TERM", termname, 1); + + signal(SIGCHLD, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGALRM, SIG_DFL); + + execvp(prog, args); + _exit(1); +} + +void +sigchld(int a) +{ + int stat; + pid_t p; + + if ((p = waitpid(pid, &stat, WNOHANG)) < 0) + die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); + + if (pid != p) + return; + + if (WIFEXITED(stat) && WEXITSTATUS(stat)) + die("child exited with status %d\n", WEXITSTATUS(stat)); + else if (WIFSIGNALED(stat)) + die("child terminated due to signal %d\n", WTERMSIG(stat)); + _exit(0); +} + +void +stty(char **args) +{ + char cmd[_POSIX_ARG_MAX], **p, *q, *s; + size_t n, siz; + + if ((n = strlen(stty_args)) > sizeof(cmd)-1) + die("incorrect stty parameters\n"); + memcpy(cmd, stty_args, n); + q = cmd + n; + siz = sizeof(cmd) - n; + for (p = args; p && (s = *p); ++p) { + if ((n = strlen(s)) > siz-1) + die("stty parameter length too long\n"); + *q++ = ' '; + memcpy(q, s, n); + q += n; + siz -= n + 1; + } + *q = '\0'; + if (system(cmd) != 0) + perror("Couldn't call stty"); +} + +int +ttynew(char *line, char *cmd, char *out, char **args) +{ + int m, s; + + if (out) { + term.mode |= MODE_PRINT; + iofd = (!strcmp(out, "-")) ? + 1 : open(out, O_WRONLY | O_CREAT, 0666); + if (iofd < 0) { + fprintf(stderr, "Error opening %s:%s\n", + out, strerror(errno)); + } + } + + if (line) { + if ((cmdfd = open(line, O_RDWR)) < 0) + die("open line '%s' failed: %s\n", + line, strerror(errno)); + dup2(cmdfd, 0); + stty(args); + return cmdfd; + } + + /* seems to work fine on linux, openbsd and freebsd */ + if (openpty(&m, &s, NULL, NULL, NULL) < 0) + die("openpty failed: %s\n", strerror(errno)); + + switch (pid = fork()) { + case -1: + die("fork failed: %s\n", strerror(errno)); + break; + case 0: + close(iofd); + setsid(); /* create a new process group */ + dup2(s, 0); + dup2(s, 1); + dup2(s, 2); + if (ioctl(s, TIOCSCTTY, NULL) < 0) + die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); + close(s); + close(m); +#ifdef __OpenBSD__ + if (pledge("stdio getpw proc exec", NULL) == -1) + die("pledge\n"); +#endif + execsh(cmd, args); + break; + default: +#ifdef __OpenBSD__ + if (pledge("stdio rpath tty proc", NULL) == -1) + die("pledge\n"); +#endif + close(s); + cmdfd = m; + signal(SIGCHLD, sigchld); + break; + } + return cmdfd; +} + +size_t +ttyread(void) +{ + static char buf[BUFSIZ]; + static int buflen = 0; + int ret, written; + + /* append read bytes to unprocessed bytes */ + ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); + + switch (ret) { + case 0: + exit(0); + case -1: + die("couldn't read from shell: %s\n", strerror(errno)); + default: + buflen += ret; + written = twrite(buf, buflen, 0); + buflen -= written; + /* keep any incomplete UTF-8 byte sequence for the next call */ + if (buflen > 0) + memmove(buf, buf + written, buflen); + return ret; + } +} + +void +ttywrite(const char *s, size_t n, int may_echo) +{ + const char *next; + + if (may_echo && IS_SET(MODE_ECHO)) + twrite(s, n, 1); + + if (!IS_SET(MODE_CRLF)) { + ttywriteraw(s, n); + return; + } + + /* This is similar to how the kernel handles ONLCR for ttys */ + while (n > 0) { + if (*s == '\r') { + next = s + 1; + ttywriteraw("\r\n", 2); + } else { + next = memchr(s, '\r', n); + DEFAULT(next, s + n); + ttywriteraw(s, next - s); + } + n -= next - s; + s = next; + } +} + +void +ttywriteraw(const char *s, size_t n) +{ + fd_set wfd, rfd; + ssize_t r; + size_t lim = 256; + + /* + * Remember that we are using a pty, which might be a modem line. + * Writing too much will clog the line. That's why we are doing this + * dance. + * FIXME: Migrate the world to Plan 9. + */ + while (n > 0) { + FD_ZERO(&wfd); + FD_ZERO(&rfd); + FD_SET(cmdfd, &wfd); + FD_SET(cmdfd, &rfd); + + /* Check if we can write. */ + if (pselect(cmdfd+1, &rfd, &wfd, NULL, NULL, NULL) < 0) { + if (errno == EINTR) + continue; + die("select failed: %s\n", strerror(errno)); + } + if (FD_ISSET(cmdfd, &wfd)) { + /* + * Only write the bytes written by ttywrite() or the + * default of 256. This seems to be a reasonable value + * for a serial line. Bigger values might clog the I/O. + */ + if ((r = write(cmdfd, s, (n < lim)? n : lim)) < 0) + goto write_error; + if (r < n) { + /* + * We weren't able to write out everything. + * This means the buffer is getting full + * again. Empty it. + */ + if (n < lim) + lim = ttyread(); + n -= r; + s += r; + } else { + /* All bytes have been written. */ + break; + } + } + if (FD_ISSET(cmdfd, &rfd)) + lim = ttyread(); + } + return; + +write_error: + die("write error on tty: %s\n", strerror(errno)); +} + +void +ttyresize(int tw, int th) +{ + struct winsize w; + + w.ws_row = term.row; + w.ws_col = term.col; + w.ws_xpixel = tw; + w.ws_ypixel = th; + if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) + fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); +} + +void +ttyhangup() +{ + /* Send SIGHUP to shell */ + kill(pid, SIGHUP); +} + +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; + + LIMIT(top, 0, term.row-1); + LIMIT(bot, 0, term.row-1); + + for (i = top; i <= bot; i++) + 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 +tfulldirt(void) +{ + tsetdirt(0, term.row-1); +} + +void +tcursor(int mode) +{ + static TCursor c[2]; + int alt = IS_SET(MODE_ALTSCREEN); + + if (mode == CURSOR_SAVE) { + c[alt] = term.c; + } else if (mode == CURSOR_LOAD) { + term.c = c[alt]; + tmoveto(c[alt].x, c[alt].y); + } +} + +void +treset(void) +{ + uint i; + + term.c = (TCursor){{ + .mode = ATTR_NULL, + .fg = defaultfg, + .bg = defaultbg + }, .x = 0, .y = 0, .state = CURSOR_DEFAULT}; + + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); + for (i = tabspaces; i < term.col; i += tabspaces) + term.tabs[i] = 1; + term.top = 0; + term.bot = term.row - 1; + term.mode = MODE_WRAP|MODE_UTF8; + memset(term.trantbl, CS_USA, sizeof(term.trantbl)); + term.charset = 0; + + for (i = 0; i < 2; i++) { + tmoveto(0, 0); + tcursor(CURSOR_SAVE); + tclearregion(0, 0, term.col-1, term.row-1); + tswapscreen(); + } +} + +void +tnew(int col, int row) +{ + term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultbg } } }; + tresize(col, row); + treset(); +} + +void +tswapscreen(void) +{ + Line *tmp = term.line; + + term.line = term.alt; + term.alt = tmp; + term.mode ^= MODE_ALTSCREEN; + tfulldirt(); +} + +void +tscrolldown(int orig, int n) +{ + int i; + Line temp; + + LIMIT(n, 0, term.bot-orig+1); + + tsetdirt(orig, term.bot-n); + tclearregion(0, term.bot-n+1, term.col-1, term.bot); + + for (i = term.bot; i >= orig+n; i--) { + temp = term.line[i]; + term.line[i] = term.line[i-n]; + term.line[i-n] = temp; + } + + selscroll(orig, n); +} + +void +tscrollup(int orig, int n) +{ + int i; + Line temp; + + LIMIT(n, 0, term.bot-orig+1); + + tclearregion(0, orig, term.col-1, orig+n-1); + tsetdirt(orig+n, term.bot); + + for (i = orig; i <= term.bot-n; i++) { + temp = term.line[i]; + term.line[i] = term.line[i+n]; + term.line[i+n] = temp; + } + + selscroll(orig, -n); +} + +void +selscroll(int orig, int n) +{ + if (sel.ob.x == -1) + return; + + if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { + selclear(); + } else if (BETWEEN(sel.nb.y, orig, term.bot)) { + sel.ob.y += n; + sel.oe.y += n; + if (sel.ob.y < term.top || sel.ob.y > term.bot || + sel.oe.y < term.top || sel.oe.y > term.bot) { + selclear(); + } else { + selnormalize(); + } + } +} + +void +tnewline(int first_col) +{ + int y = term.c.y; + + if (y == term.bot) { + tscrollup(term.top, 1); + } else { + y++; + } + tmoveto(first_col ? 0 : term.c.x, y); +} + +void +csiparse(void) +{ + char *p = csiescseq.buf, *np; + long int v; + + csiescseq.narg = 0; + if (*p == '?') { + csiescseq.priv = 1; + p++; + } + + csiescseq.buf[csiescseq.len] = '\0'; + while (p < csiescseq.buf+csiescseq.len) { + np = NULL; + v = strtol(p, &np, 10); + if (np == p) + v = 0; + if (v == LONG_MAX || v == LONG_MIN) + v = -1; + csiescseq.arg[csiescseq.narg++] = v; + p = np; + if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) + break; + p++; + } + csiescseq.mode[0] = *p++; + csiescseq.mode[1] = (p < csiescseq.buf+csiescseq.len) ? *p : '\0'; +} + +/* 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; + } + term.c.state &= ~CURSOR_WRAPNEXT; + term.c.x = LIMIT(x, 0, term.col-1); + term.c.y = LIMIT(y, miny, maxy); +} + +void +tsetchar(Rune u, Glyph *attr, int x, int y) +{ + static char *vt100_0[62] = { /* 0x41 - 0x7e */ + "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ + 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ + 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ + 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */ + "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */ + "␤", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */ + "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */ + "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */ + }; + + /* + * The table is proudly stolen from rxvt. + */ + if (term.trantbl[term.charset] == CS_GRAPHIC0 && + BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41]) + utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ); + + if (term.line[y][x].mode & ATTR_WIDE) { + if (x+1 < term.col) { + term.line[y][x+1].u = ' '; + term.line[y][x+1].mode &= ~ATTR_WDUMMY; + } + } else if (term.line[y][x].mode & ATTR_WDUMMY) { + term.line[y][x-1].u = ' '; + term.line[y][x-1].mode &= ~ATTR_WIDE; + } + + term.dirty[y] = 1; + term.line[y][x] = *attr; + term.line[y][x].u = u; +} + +void +tclearregion(int x1, int y1, int x2, int y2) +{ + int x, y, temp; + Glyph *gp; + + if (x1 > x2) + temp = x1, x1 = x2, x2 = temp; + if (y1 > y2) + temp = y1, y1 = y2, y2 = temp; + + LIMIT(x1, 0, term.col-1); + LIMIT(x2, 0, term.col-1); + LIMIT(y1, 0, term.row-1); + LIMIT(y2, 0, term.row-1); + + for (y = y1; y <= y2; y++) { + term.dirty[y] = 1; + for (x = x1; x <= x2; x++) { + gp = &term.line[y][x]; + if (selected(x, y)) + selclear(); + gp->fg = term.c.attr.fg; + gp->bg = term.c.attr.bg; + gp->mode = 0; + gp->u = ' '; + } + } +} + +void +tdeletechar(int n) +{ + int dst, src, size; + Glyph *line; + + LIMIT(n, 0, term.col - term.c.x); + + dst = term.c.x; + src = term.c.x + n; + size = term.col - src; + line = term.line[term.c.y]; + + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(term.col-n, term.c.y, term.col-1, term.c.y); +} + +void +tinsertblank(int n) +{ + int dst, src, size; + Glyph *line; + + LIMIT(n, 0, term.col - term.c.x); + + dst = term.c.x + n; + src = term.c.x; + size = term.col - dst; + line = term.line[term.c.y]; + + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(src, term.c.y, dst - 1, term.c.y); +} + +void +tinsertblankline(int n) +{ + if (BETWEEN(term.c.y, term.top, term.bot)) + tscrolldown(term.c.y, n); +} + +void +tdeleteline(int n) +{ + if (BETWEEN(term.c.y, term.top, term.bot)) + tscrollup(term.c.y, n); +} + +int32_t +tdefcolor(int *attr, int *npar, int l) +{ + int32_t idx = -1; + uint r, g, b; + + switch (attr[*npar + 1]) { + case 2: /* direct color in RGB space */ + if (*npar + 4 >= l) { + fprintf(stderr, + "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + r = attr[*npar + 2]; + g = attr[*npar + 3]; + b = attr[*npar + 4]; + *npar += 4; + if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) + fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", + r, g, b); + else + idx = TRUECOLOR(r, g, b); + break; + case 5: /* indexed color */ + if (*npar + 2 >= l) { + fprintf(stderr, + "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + *npar += 2; + if (!BETWEEN(attr[*npar], 0, 255)) + fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); + else + idx = attr[*npar]; + break; + case 0: /* implemented defined (only foreground) */ + case 1: /* transparent */ + case 3: /* direct color in CMY space */ + case 4: /* direct color in CMYK space */ + default: + fprintf(stderr, + "erresc(38): gfx attr %d unknown\n", attr[*npar]); + break; + } + + return idx; +} + +void +tsetattr(int *attr, int l) +{ + int i; + int32_t idx; + + for (i = 0; i < l; i++) { + switch (attr[i]) { + case 0: + term.c.attr.mode &= ~( + ATTR_BOLD | + ATTR_FAINT | + ATTR_ITALIC | + ATTR_UNDERLINE | + ATTR_BLINK | + ATTR_REVERSE | + ATTR_INVISIBLE | + ATTR_STRUCK ); + term.c.attr.fg = defaultfg; + term.c.attr.bg = defaultbg; + break; + case 1: + term.c.attr.mode |= ATTR_BOLD; + break; + case 2: + term.c.attr.mode |= ATTR_FAINT; + break; + case 3: + term.c.attr.mode |= ATTR_ITALIC; + break; + case 4: + term.c.attr.mode |= ATTR_UNDERLINE; + break; + case 5: /* slow blink */ + /* FALLTHROUGH */ + case 6: /* rapid blink */ + term.c.attr.mode |= ATTR_BLINK; + break; + case 7: + term.c.attr.mode |= ATTR_REVERSE; + break; + case 8: + term.c.attr.mode |= ATTR_INVISIBLE; + break; + case 9: + term.c.attr.mode |= ATTR_STRUCK; + break; + case 22: + term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); + break; + case 23: + term.c.attr.mode &= ~ATTR_ITALIC; + break; + case 24: + term.c.attr.mode &= ~ATTR_UNDERLINE; + break; + case 25: + term.c.attr.mode &= ~ATTR_BLINK; + break; + case 27: + term.c.attr.mode &= ~ATTR_REVERSE; + break; + case 28: + term.c.attr.mode &= ~ATTR_INVISIBLE; + break; + case 29: + term.c.attr.mode &= ~ATTR_STRUCK; + break; + case 38: + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.fg = idx; + break; + case 39: + term.c.attr.fg = defaultfg; + break; + case 48: + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.bg = idx; + break; + case 49: + term.c.attr.bg = defaultbg; + break; + default: + if (BETWEEN(attr[i], 30, 37)) { + term.c.attr.fg = attr[i] - 30; + } else if (BETWEEN(attr[i], 40, 47)) { + term.c.attr.bg = attr[i] - 40; + } else if (BETWEEN(attr[i], 90, 97)) { + term.c.attr.fg = attr[i] - 90 + 8; + } else if (BETWEEN(attr[i], 100, 107)) { + term.c.attr.bg = attr[i] - 100 + 8; + } else { + fprintf(stderr, + "erresc(default): gfx attr %d unknown\n", + attr[i]); + csidump(); + } + break; + } + } +} + +void +tsetscroll(int t, int b) +{ + int temp; + + LIMIT(t, 0, term.row-1); + LIMIT(b, 0, term.row-1); + if (t > b) { + temp = t; + t = b; + b = temp; + } + term.top = t; + term.bot = b; +} + +void +tsetmode(int priv, int set, int *args, int narg) +{ + int alt, *lim; + + for (lim = args + narg; args < lim; ++args) { + if (priv) { + switch (*args) { + case 1: /* DECCKM -- Cursor key */ + xsetmode(set, MODE_APPCURSOR); + break; + case 5: /* DECSCNM -- Reverse video */ + xsetmode(set, MODE_REVERSE); + break; + 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 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: /* DECTCEM -- Text Cursor Enable Mode */ + xsetmode(!set, MODE_HIDE); + break; + case 9: /* X10 mouse compatibility mode */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEX10); + break; + case 1000: /* 1000: report button press */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEBTN); + break; + case 1002: /* 1002: report motion on button press */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEMOTION); + break; + case 1003: /* 1003: enable all mouse motions */ + xsetpointermotion(set); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEMANY); + break; + case 1004: /* 1004: send focus events to tty */ + xsetmode(set, MODE_FOCUS); + break; + case 1006: /* 1006: extended reporting mode */ + xsetmode(set, MODE_MOUSESGR); + break; + case 1034: + xsetmode(set, MODE_8BIT); + break; + case 1049: /* swap screen & set/restore cursor as xterm */ + if (!allowaltscreen) + break; + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + /* FALLTHROUGH */ + case 47: /* swap screen */ + case 1047: + if (!allowaltscreen) + break; + alt = IS_SET(MODE_ALTSCREEN); + if (alt) { + tclearregion(0, 0, term.col-1, + term.row-1); + } + if (set ^ alt) /* set is always 1 or 0 */ + tswapscreen(); + if (*args != 1049) + break; + /* FALLTHROUGH */ + case 1048: + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + break; + case 2004: /* 2004: bracketed paste mode */ + xsetmode(set, MODE_BRCKTPASTE); + break; + /* Not implemented mouse modes. See comments there. */ + case 1001: /* mouse highlight mode; can hang the + terminal by design when implemented. */ + case 1005: /* UTF-8 mouse mode; will confuse + applications not supporting UTF-8 + and luit. */ + case 1015: /* urxvt mangled mouse mode; incompatible + and can be mistaken for other control + codes. */ + break; + default: + fprintf(stderr, + "erresc: unknown private set/reset mode %d\n", + *args); + break; + } + } else { + switch (*args) { + case 0: /* Error (IGNORED) */ + break; + case 2: + xsetmode(set, MODE_KBDLOCK); + break; + case 4: /* IRM -- Insertion-replacement */ + MODBIT(term.mode, set, MODE_INSERT); + break; + case 12: /* SRM -- Send/Receive */ + MODBIT(term.mode, !set, MODE_ECHO); + break; + case 20: /* LNM -- Linefeed/new line */ + MODBIT(term.mode, set, MODE_CRLF); + break; + default: + fprintf(stderr, + "erresc: unknown set/reset mode %d\n", + *args); + break; + } + } + } +} + +void +csihandle(void) +{ + char buf[40]; + int len; + + switch (csiescseq.mode[0]) { + default: + unknown: + fprintf(stderr, "erresc: unknown csi "); + csidump(); + /* die(""); */ + break; + case '@': /* ICH -- Insert blank char */ + DEFAULT(csiescseq.arg[0], 1); + tinsertblank(csiescseq.arg[0]); + break; + case 'A': /* CUU -- Cursor Up */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); + break; + case 'B': /* CUD -- Cursor Down */ + case 'e': /* VPR --Cursor Down */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); + break; + case 'i': /* MC -- Media Copy */ + switch (csiescseq.arg[0]) { + case 0: + tdump(); + break; + case 1: + tdumpline(term.c.y); + break; + case 2: + tdumpsel(); + break; + case 4: + term.mode &= ~MODE_PRINT; + break; + case 5: + term.mode |= MODE_PRINT; + break; + } + break; + case 'c': /* DA -- Device Attributes */ + if (csiescseq.arg[0] == 0) + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 'b': /* REP -- if last char is printable print it more times */ + DEFAULT(csiescseq.arg[0], 1); + if (term.lastc) + while (csiescseq.arg[0]-- > 0) + tputc(term.lastc); + break; + case 'C': /* CUF -- Cursor Forward */ + case 'a': /* HPR -- Cursor Forward */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x+csiescseq.arg[0], term.c.y); + break; + case 'D': /* CUB -- Cursor Backward */ + 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(csiescseq.arg[0], 1); + tmoveto(0, term.c.y+csiescseq.arg[0]); + break; + case 'F': /* CPL -- Cursor Up and first col */ + 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 '`': /* HPA */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(csiescseq.arg[0]-1, term.c.y); + break; + case 'H': /* CUP -- Move to */ + case 'f': /* HVP */ + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], 1); + tmoveato(csiescseq.arg[1]-1, csiescseq.arg[0]-1); + break; + case 'I': /* CHT -- Cursor Forward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + tputtab(csiescseq.arg[0]); + break; + case 'J': /* ED -- Clear screen */ + 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) { + tclearregion(0, term.c.y+1, term.col-1, + term.row-1); + } + break; + case 1: /* above */ + if (term.c.y > 1) + tclearregion(0, 0, term.col-1, term.c.y-1); + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* all */ + tclearregion(0, 0, term.col-1, term.row-1); + break; + default: + goto unknown; + } + break; + case 'K': /* EL -- Clear line */ + switch (csiescseq.arg[0]) { + case 0: /* right */ + tclearregion(term.c.x, term.c.y, term.col-1, + term.c.y); + break; + case 1: /* left */ + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* all */ + tclearregion(0, term.c.y, term.col-1, term.c.y); + break; + } + break; + case 'S': /* SU -- Scroll line up */ + DEFAULT(csiescseq.arg[0], 1); + tscrollup(term.top, csiescseq.arg[0]); + break; + case 'T': /* SD -- Scroll line down */ + DEFAULT(csiescseq.arg[0], 1); + tscrolldown(term.top, csiescseq.arg[0]); + break; + case 'L': /* IL -- Insert blank lines */ + DEFAULT(csiescseq.arg[0], 1); + tinsertblankline(csiescseq.arg[0]); + break; + case 'l': /* RM -- Reset Mode */ + tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); + break; + case 'M': /* DL -- Delete lines */ + DEFAULT(csiescseq.arg[0], 1); + tdeleteline(csiescseq.arg[0]); + break; + case 'X': /* ECH -- Erase char */ + DEFAULT(csiescseq.arg[0], 1); + tclearregion(term.c.x, term.c.y, + term.c.x + csiescseq.arg[0] - 1, term.c.y); + break; + case 'P': /* DCH -- Delete char */ + DEFAULT(csiescseq.arg[0], 1); + tdeletechar(csiescseq.arg[0]); + break; + case 'Z': /* CBT -- Cursor Backward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + tputtab(-csiescseq.arg[0]); + break; + case 'd': /* VPA -- Move to */ + DEFAULT(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); + break; + case 'm': /* SGR -- Terminal attribute (color) */ + tsetattr(csiescseq.arg, csiescseq.narg); + break; + case 'n': /* DSR – Device Status Report (cursor position) */ + if (csiescseq.arg[0] == 6) { + len = snprintf(buf, sizeof(buf), "\033[%i;%iR", + term.c.y+1, term.c.x+1); + ttywrite(buf, len, 0); + } + break; + case 'r': /* DECSTBM -- Set Scrolling Region */ + if (csiescseq.priv) { + goto unknown; + } else { + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], term.row); + tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); + tmoveato(0, 0); + } + break; + case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ + tcursor(CURSOR_SAVE); + break; + case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ + tcursor(CURSOR_LOAD); + break; + case ' ': + switch (csiescseq.mode[1]) { + case 'q': /* DECSCUSR -- Set Cursor Style */ + if (xsetcursor(csiescseq.arg[0])) + goto unknown; + break; + default: + goto unknown; + } + break; + } +} + +void +csidump(void) +{ + size_t i; + uint c; + + fprintf(stderr, "ESC["); + for (i = 0; i < csiescseq.len; i++) { + c = csiescseq.buf[i] & 0xff; + if (isprint(c)) { + putc(c, stderr); + } else if (c == '\n') { + fprintf(stderr, "(\\n)"); + } else if (c == '\r') { + fprintf(stderr, "(\\r)"); + } else if (c == 0x1b) { + fprintf(stderr, "(\\e)"); + } else { + fprintf(stderr, "(%02x)", c); + } + } + putc('\n', stderr); +} + +void +csireset(void) +{ + memset(&csiescseq, 0, sizeof(csiescseq)); +} + +void +strhandle(void) +{ + char *p = NULL, *dec; + int j, narg, par; + + term.esc &= ~(ESC_STR_END|ESC_STR); + strparse(); + par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; + + switch (strescseq.type) { + case ']': /* OSC -- Operating System Command */ + switch (par) { + case 0: + case 1: + case 2: + if (narg > 1) + xsettitle(strescseq.args[1]); + return; + case 52: + if (narg > 2 && allowwindowops) { + dec = base64dec(strescseq.args[2]); + if (dec) { + xsetsel(dec); + xclipcopy(); + } else { + fprintf(stderr, "erresc: invalid base64\n"); + } + } + return; + case 4: /* color set */ + if (narg < 3) + break; + p = strescseq.args[2]; + /* FALLTHROUGH */ + case 104: /* color reset, here p = NULL */ + j = (narg > 1) ? atoi(strescseq.args[1]) : -1; + if (xsetcolorname(j, p)) { + if (par == 104 && narg <= 1) + return; /* color reset without parameter */ + fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", + j, p ? p : "(null)"); + } else { + /* + * TODO if defaultbg color is changed, borders + * are dirty + */ + redraw(); + } + return; + } + break; + case 'k': /* old title set compatibility */ + xsettitle(strescseq.args[0]); + return; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + return; + } + + fprintf(stderr, "erresc: unknown str "); + strdump(); +} + +void +strparse(void) +{ + int c; + char *p = strescseq.buf; + + strescseq.narg = 0; + strescseq.buf[strescseq.len] = '\0'; + + if (*p == '\0') + return; + + while (strescseq.narg < STR_ARG_SIZ) { + strescseq.args[strescseq.narg++] = p; + while ((c = *p) != ';' && c != '\0') + ++p; + if (c == '\0') + return; + *p++ = '\0'; + } +} + +void +strdump(void) +{ + size_t i; + uint c; + + fprintf(stderr, "ESC%c", strescseq.type); + for (i = 0; i < strescseq.len; i++) { + c = strescseq.buf[i] & 0xff; + if (c == '\0') { + putc('\n', stderr); + return; + } else if (isprint(c)) { + putc(c, stderr); + } else if (c == '\n') { + fprintf(stderr, "(\\n)"); + } else if (c == '\r') { + fprintf(stderr, "(\\r)"); + } else if (c == 0x1b) { + fprintf(stderr, "(\\e)"); + } else { + fprintf(stderr, "(%02x)", c); + } + } + fprintf(stderr, "ESC\\\n"); +} + +void +strreset(void) +{ + strescseq = (STREscape){ + .buf = xrealloc(strescseq.buf, STR_BUF_SIZ), + .siz = STR_BUF_SIZ, + }; +} + +void +sendbreak(const Arg *arg) +{ + if (tcsendbreak(cmdfd, 0)) + perror("Error sending break"); +} + +void +tprinter(char *s, size_t len) +{ + if (iofd != -1 && xwrite(iofd, s, len) < 0) { + perror("Error writing to output file"); + close(iofd); + iofd = -1; + } +} + +void +toggleprinter(const Arg *arg) +{ + term.mode ^= MODE_PRINT; +} + +void +printscreen(const Arg *arg) +{ + tdump(); +} + +void +printsel(const Arg *arg) +{ + tdumpsel(); +} + +void +tdumpsel(void) +{ + char *ptr; + + if ((ptr = getsel())) { + tprinter(ptr, strlen(ptr)); + free(ptr); + } +} + +void +tdumpline(int n) +{ + char buf[UTF_SIZ]; + Glyph *bp, *end; + + bp = &term.line[n][0]; + end = &bp[MIN(tlinelen(n), term.col) - 1]; + if (bp != end || bp->u != ' ') { + for ( ; bp <= end; ++bp) + tprinter(buf, utf8encode(bp->u, buf)); + } + tprinter("\n", 1); +} + +void +tdump(void) +{ + int i; + + for (i = 0; i < term.row; ++i) + tdumpline(i); +} + +void +tputtab(int n) +{ + uint x = term.c.x; + + if (n > 0) { + while (x < term.col && n--) + for (++x; x < term.col && !term.tabs[x]; ++x) + /* nothing */ ; + } else if (n < 0) { + while (x > 0 && n++) + for (--x; x > 0 && !term.tabs[x]; --x) + /* nothing */ ; + } + term.c.x = LIMIT(x, 0, term.col-1); +} + +void +tdefutf8(char ascii) +{ + if (ascii == 'G') + term.mode |= MODE_UTF8; + else if (ascii == '@') + term.mode &= ~MODE_UTF8; +} + +void +tdeftran(char ascii) +{ + static char cs[] = "0B"; + static int vcs[] = {CS_GRAPHIC0, CS_USA}; + char *p; + + if ((p = strchr(cs, ascii)) == NULL) { + fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); + } else { + term.trantbl[term.icharset] = vcs[p - cs]; + } +} + +void +tdectest(char c) +{ + int x, y; + + if (c == '8') { /* DEC screen alignment test. */ + for (x = 0; x < term.col; ++x) { + for (y = 0; y < term.row; ++y) + tsetchar('E', &term.c.attr, x, y); + } + } +} + +void +tstrsequence(uchar c) +{ + switch (c) { + case 0x90: /* DCS -- Device Control String */ + c = 'P'; + break; + case 0x9f: /* APC -- Application Program Command */ + c = '_'; + break; + case 0x9e: /* PM -- Privacy Message */ + c = '^'; + break; + case 0x9d: /* OSC -- Operating System Command */ + c = ']'; + break; + } + strreset(); + strescseq.type = c; + term.esc |= ESC_STR; +} + +void +tcontrolcode(uchar ascii) +{ + switch (ascii) { + case '\t': /* HT */ + tputtab(1); + return; + case '\b': /* BS */ + tmoveto(term.c.x-1, term.c.y); + return; + case '\r': /* CR */ + tmoveto(0, term.c.y); + return; + case '\f': /* LF */ + case '\v': /* VT */ + case '\n': /* LF */ + /* go to first col if the mode is set */ + tnewline(IS_SET(MODE_CRLF)); + return; + case '\a': /* BEL */ + if (term.esc & ESC_STR_END) { + /* backwards compatibility to xterm */ + strhandle(); + } else { + xbell(); + } + break; + case '\033': /* ESC */ + csireset(); + term.esc &= ~(ESC_CSI|ESC_ALTCHARSET|ESC_TEST); + term.esc |= ESC_START; + return; + case '\016': /* SO (LS1 -- Locking shift 1) */ + case '\017': /* SI (LS0 -- Locking shift 0) */ + term.charset = 1 - (ascii - '\016'); + return; + case '\032': /* SUB */ + tsetchar('?', &term.c.attr, term.c.x, term.c.y); + /* FALLTHROUGH */ + case '\030': /* CAN */ + csireset(); + break; + case '\005': /* ENQ (IGNORED) */ + case '\000': /* NUL (IGNORED) */ + case '\021': /* XON (IGNORED) */ + case '\023': /* XOFF (IGNORED) */ + case 0177: /* DEL (IGNORED) */ + return; + case 0x80: /* TODO: PAD */ + case 0x81: /* TODO: HOP */ + case 0x82: /* TODO: BPH */ + case 0x83: /* TODO: NBH */ + case 0x84: /* TODO: IND */ + break; + case 0x85: /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 0x86: /* TODO: SSA */ + case 0x87: /* TODO: ESA */ + break; + case 0x88: /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; + case 0x89: /* TODO: HTJ */ + case 0x8a: /* TODO: VTS */ + case 0x8b: /* TODO: PLD */ + case 0x8c: /* TODO: PLU */ + case 0x8d: /* TODO: RI */ + case 0x8e: /* TODO: SS2 */ + case 0x8f: /* TODO: SS3 */ + case 0x91: /* TODO: PU1 */ + case 0x92: /* TODO: PU2 */ + case 0x93: /* TODO: STS */ + case 0x94: /* TODO: CCH */ + case 0x95: /* TODO: MW */ + case 0x96: /* TODO: SPA */ + case 0x97: /* TODO: EPA */ + case 0x98: /* TODO: SOS */ + case 0x99: /* TODO: SGCI */ + break; + case 0x9a: /* DECID -- Identify Terminal */ + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 0x9b: /* TODO: CSI */ + case 0x9c: /* TODO: ST */ + break; + case 0x90: /* DCS -- Device Control String */ + case 0x9d: /* OSC -- Operating System Command */ + case 0x9e: /* PM -- Privacy Message */ + case 0x9f: /* APC -- Application Program Command */ + tstrsequence(ascii); + return; + } + /* only CAN, SUB, \a and C1 chars interrupt a sequence */ + term.esc &= ~(ESC_STR_END|ESC_STR); +} + +/* + * returns 1 when the sequence is finished and it hasn't to read + * more characters for this sequence, otherwise 0 + */ +int +eschandle(uchar ascii) +{ + switch (ascii) { + case '[': + term.esc |= ESC_CSI; + return 0; + case '#': + term.esc |= ESC_TEST; + return 0; + case '%': + term.esc |= ESC_UTF8; + return 0; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + case ']': /* OSC -- Operating System Command */ + case 'k': /* old title set compatibility */ + tstrsequence(ascii); + return 0; + case 'n': /* LS2 -- Locking shift 2 */ + case 'o': /* LS3 -- Locking shift 3 */ + term.charset = 2 + (ascii - 'n'); + break; + case '(': /* GZD4 -- set primary charset G0 */ + case ')': /* G1D4 -- set secondary charset G1 */ + case '*': /* G2D4 -- set tertiary charset G2 */ + case '+': /* G3D4 -- set quaternary charset G3 */ + term.icharset = ascii - '('; + term.esc |= ESC_ALTCHARSET; + return 0; + case 'D': /* IND -- Linefeed */ + if (term.c.y == term.bot) { + tscrollup(term.top, 1); + } else { + tmoveto(term.c.x, term.c.y+1); + } + break; + case 'E': /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 'H': /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; + case 'M': /* RI -- Reverse index */ + if (term.c.y == term.top) { + tscrolldown(term.top, 1); + } else { + tmoveto(term.c.x, term.c.y-1); + } + break; + case 'Z': /* DECID -- Identify Terminal */ + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 'c': /* RIS -- Reset to initial state */ + treset(); + resettitle(); + xloadcols(); + break; + case '=': /* DECPAM -- Application keypad */ + xsetmode(1, MODE_APPKEYPAD); + break; + case '>': /* DECPNM -- Normal keypad */ + xsetmode(0, MODE_APPKEYPAD); + break; + case '7': /* DECSC -- Save Cursor */ + tcursor(CURSOR_SAVE); + break; + case '8': /* DECRC -- Restore Cursor */ + tcursor(CURSOR_LOAD); + break; + case '\\': /* ST -- String Terminator */ + if (term.esc & ESC_STR_END) + strhandle(); + break; + default: + fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", + (uchar) ascii, isprint(ascii)? ascii:'.'); + break; + } + return 1; +} + +void +tputc(Rune u) +{ + char c[UTF_SIZ]; + int control; + int width, len; + Glyph *gp; + + control = ISCONTROL(u); + if (u < 127 || !IS_SET(MODE_UTF8)) { + c[0] = u; + width = len = 1; + } else { + len = utf8encode(u, c); + if (!control && (width = wcwidth(u)) == -1) + width = 1; + } + + if (IS_SET(MODE_PRINT)) + tprinter(c, len); + + /* + * STR sequence must be checked before anything else + * because it uses all following characters until it + * receives a ESC, a SUB, a ST or any other C1 control + * character. + */ + if (term.esc & ESC_STR) { + if (u == '\a' || u == 030 || u == 032 || u == 033 || + ISCONTROLC1(u)) { + term.esc &= ~(ESC_START|ESC_STR); + term.esc |= ESC_STR_END; + goto check_control_code; + } + + if (strescseq.len+len >= strescseq.siz) { + /* + * 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(); + */ + if (strescseq.siz > (SIZE_MAX - UTF_SIZ) / 2) + return; + strescseq.siz *= 2; + strescseq.buf = xrealloc(strescseq.buf, strescseq.siz); + } + + memmove(&strescseq.buf[strescseq.len], c, len); + strescseq.len += len; + return; + } + +check_control_code: + /* + * Actions of control codes must be performed as soon they arrive + * because they can be embedded inside a control sequence, and + * they must not cause conflicts with sequences. + */ + if (control) { + tcontrolcode(u); + /* + * control codes are not shown ever + */ + if (!term.esc) + term.lastc = 0; + return; + } else if (term.esc & ESC_START) { + if (term.esc & ESC_CSI) { + csiescseq.buf[csiescseq.len++] = u; + if (BETWEEN(u, 0x40, 0x7E) + || csiescseq.len >= \ + sizeof(csiescseq.buf)-1) { + term.esc = 0; + csiparse(); + csihandle(); + } + return; + } else if (term.esc & ESC_UTF8) { + tdefutf8(u); + } else if (term.esc & ESC_ALTCHARSET) { + tdeftran(u); + } else if (term.esc & ESC_TEST) { + tdectest(u); + } else { + if (!eschandle(u)) + return; + /* sequence already finished */ + } + term.esc = 0; + /* + * All characters which form part of a sequence are not + * printed + */ + return; + } + if (selected(term.c.x, term.c.y)) + selclear(); + + gp = &term.line[term.c.y][term.c.x]; + if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { + gp->mode |= ATTR_WRAP; + tnewline(1); + gp = &term.line[term.c.y][term.c.x]; + } + + if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) + memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); + + if (term.c.x+width > term.col) { + tnewline(1); + gp = &term.line[term.c.y][term.c.x]; + } + + tsetchar(u, &term.c.attr, term.c.x, term.c.y); + term.lastc = u; + + if (width == 2) { + gp->mode |= ATTR_WIDE; + if (term.c.x+1 < term.col) { + gp[1].u = '\0'; + gp[1].mode = ATTR_WDUMMY; + } + } + if (term.c.x+width < term.col) { + tmoveto(term.c.x+width, term.c.y); + } else { + term.c.state |= CURSOR_WRAPNEXT; + } +} + +int +twrite(const char *buf, int buflen, int show_ctrl) +{ + int charsize; + Rune u; + int n; + + for (n = 0; n < buflen; n += charsize) { + if (IS_SET(MODE_UTF8)) { + /* process a complete utf8 char */ + charsize = utf8decode(buf + n, &u, buflen - n); + if (charsize == 0) + break; + } else { + u = buf[n] & 0xFF; + charsize = 1; + } + if (show_ctrl && ISCONTROL(u)) { + if (u & 0x80) { + u &= 0x7f; + tputc('^'); + tputc('['); + } else if (u != '\n' && u != '\r' && u != '\t') { + u ^= 0x40; + tputc('^'); + } + } + tputc(u); + } + return n; +} + +void +tresize(int col, int row) +{ + int i; + int minrow = MIN(row, term.row); + int mincol = MIN(col, term.col); + int *bp; + TCursor c; + + if (col < 1 || row < 1) { + fprintf(stderr, + "tresize: error resizing to %dx%d\n", col, row); + return; + } + + /* + * slide screen to keep cursor where we expect it - + * tscrollup would work here, but we can optimize to + * memmove because we're freeing the earlier lines + */ + for (i = 0; i <= term.c.y - row; i++) { + free(term.line[i]); + free(term.alt[i]); + } + /* ensure that both src and dst are not NULL */ + if (i > 0) { + memmove(term.line, term.line + i, row * sizeof(Line)); + memmove(term.alt, term.alt + i, row * sizeof(Line)); + } + for (i += row; i < term.row; i++) { + free(term.line[i]); + free(term.alt[i]); + } + + /* resize to new height */ + term.line = xrealloc(term.line, row * sizeof(Line)); + term.alt = xrealloc(term.alt, row * sizeof(Line)); + term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); + term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); + + /* resize each row to new width, zero-pad if needed */ + for (i = 0; i < minrow; i++) { + term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); + term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph)); + } + + /* allocate any new rows */ + for (/* i = minrow */; i < row; i++) { + term.line[i] = xmalloc(col * sizeof(Glyph)); + term.alt[i] = xmalloc(col * sizeof(Glyph)); + } + if (col > term.col) { + bp = term.tabs + term.col; + + memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); + while (--bp > term.tabs && !*bp) + /* nothing */ ; + for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) + *bp = 1; + } + /* update terminal size */ + term.col = col; + term.row = row; + /* reset scrolling region */ + tsetscroll(0, row-1); + /* make use of the LIMIT in tmoveto */ + tmoveto(term.c.x, term.c.y); + /* Clearing both screens (it makes dirty all lines) */ + c = term.c; + for (i = 0; i < 2; i++) { + if (mincol < col && 0 < minrow) { + tclearregion(mincol, 0, col - 1, minrow - 1); + } + if (0 < col && minrow < row) { + tclearregion(0, minrow, col - 1, row - 1); + } + tswapscreen(); + tcursor(CURSOR_LOAD); + } + term.c = c; +} + +void +resettitle(void) +{ + xsettitle(NULL); +} + +void +drawregion(int x1, int y1, int x2, int y2) +{ + int y; + + for (y = y1; y < y2; y++) { + if (!term.dirty[y]) + continue; + + term.dirty[y] = 0; + xdrawline(term.line[y], x1, y, x2); + } +} + +void +draw(void) +{ + int cx = term.c.x, ocx = term.ocx, ocy = term.ocy; + + if (!xstartdraw()) + return; + + /* adjust cursor position */ + LIMIT(term.ocx, 0, term.col-1); + LIMIT(term.ocy, 0, term.row-1); + if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY) + term.ocx--; + if (term.line[term.c.y][cx].mode & ATTR_WDUMMY) + cx--; + + drawregion(0, 0, term.col, term.row); + xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], + term.ocx, term.ocy, term.line[term.ocy][term.ocx]); + term.ocx = cx; + term.ocy = term.c.y; + xfinishdraw(); + if (ocx != term.ocx || ocy != term.ocy) + xximspot(term.ocx, term.ocy); +} + +void +redraw(void) +{ + tfulldirt(); + draw(); +} diff --git a/st.h b/st.h index 9f11a6a..5df7063 100644 --- a/st.h +++ b/st.h @@ -79,6 +79,7 @@ typedef union { void die(const char *, ...); void redraw(void); +void tfulldirt(void); void draw(void); void printscreen(const Arg *); @@ -123,4 +124,4 @@ extern char *termname; extern unsigned int tabspaces; extern unsigned int defaultfg; extern unsigned int defaultbg; -extern float alpha; +extern float alpha, alphaUnfocused; diff --git a/st.h.orig b/st.h.orig index 3d351b6..9f11a6a 100644 --- a/st.h.orig +++ b/st.h.orig @@ -123,3 +123,4 @@ extern char *termname; extern unsigned int tabspaces; extern unsigned int defaultfg; extern unsigned int defaultbg; +extern float alpha; diff --git a/st.o b/st.o new file mode 100644 index 0000000000000000000000000000000000000000..7af1142742a4bfc1e4026a8006ab0dbd8ddf1889 GIT binary patch literal 72936 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 BQ3?P6 literal 0 HcmV?d00001