X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=st.c;h=3ebf8c6947e69086dfb51541600d5320f8ce7466;hb=33201ac65f74e45b4fa60822ba9a538c3cfa9b25;hp=9cfa5470925cd360469c7ae1d3471a336c366e56;hpb=8b564c1a3f51c08e64c2f589852a02b8595d44ca;p=st.git diff --git a/st.c b/st.c index 9cfa547..3ebf8c6 100644 --- a/st.c +++ b/st.c @@ -108,6 +108,7 @@ typedef struct { static void execsh(char **); static void stty(char **); static void sigchld(int); +static void ttywriteraw(const char *, size_t); static void csidump(void); static void csihandle(void); @@ -140,6 +141,7 @@ 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); @@ -166,11 +168,11 @@ static ssize_t xwrite(int, const char *, size_t); /* Globals */ Term term; -Selection sel; int cmdfd; pid_t pid; int oldbutton = 3; /* button event on startup: 3 = release */ +static Selection sel; static CSIEscape csiescseq; static STREscape strescseq; static int iofd = 1; @@ -365,13 +367,9 @@ base64dec(const char *src) void selinit(void) { - clock_gettime(CLOCK_MONOTONIC, &sel.tclick1); - clock_gettime(CLOCK_MONOTONIC, &sel.tclick2); sel.mode = SEL_IDLE; sel.snap = 0; sel.ob.x = -1; - sel.primary = NULL; - sel.clipboard = NULL; } int @@ -388,6 +386,52 @@ tlinelen(int y) return i; } +void +selstart(int col, int row, int snap) +{ + selclear(); + sel.mode = SEL_EMPTY; + sel.type = SEL_REGULAR; + 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) + 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.alt = IS_SET(MODE_ALTSCREEN); + sel.oe.x = col; + sel.oe.y = row; + selnormalize(); + sel.type = type; + + if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type) + tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); + + sel.mode = done ? SEL_IDLE : SEL_READY; +} + void selnormalize(void) { @@ -419,7 +463,8 @@ selnormalize(void) int selected(int x, int y) { - if (sel.mode == SEL_EMPTY) + if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || + sel.alt != IS_SET(MODE_ALTSCREEN)) return 0; if (sel.type == SEL_RECTANGULAR) @@ -670,7 +715,6 @@ void ttynew(char *line, char *out, char **args) { int m, s; - struct winsize w = {term.row, term.col, 0, 0}; if (out) { term.mode |= MODE_PRINT; @@ -691,7 +735,7 @@ ttynew(char *line, char *out, char **args) } /* seems to work fine on linux, openbsd and freebsd */ - if (openpty(&m, &s, NULL, NULL, &w) < 0) + if (openpty(&m, &s, NULL, NULL, NULL) < 0) die("openpty failed: %s\n", strerror(errno)); switch (pid = fork()) { @@ -741,7 +785,35 @@ ttyread(void) } void -ttywrite(const char *s, size_t n) +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; @@ -797,14 +869,6 @@ write_error: die("write error on tty: %s\n", strerror(errno)); } -void -ttysend(char *s, size_t n) -{ - ttywrite(s, n); - if (IS_SET(MODE_ECHO)) - twrite(s, n, 1); -} - void ttyresize(int tw, int th) { @@ -1527,7 +1591,7 @@ csihandle(void) break; case 'c': /* DA -- Device Attributes */ if (csiescseq.arg[0] == 0) - ttywrite(vtiden, strlen(vtiden)); + ttywrite(vtiden, strlen(vtiden), 0); break; case 'C': /* CUF -- Cursor Forward */ case 'a': /* HPR -- Cursor Forward */ @@ -1655,7 +1719,7 @@ csihandle(void) if (csiescseq.arg[0] == 6) { len = snprintf(buf, sizeof(buf),"\033[%i;%iR", term.c.y+1, term.c.x+1); - ttywrite(buf, len); + ttywrite(buf, len, 0); } break; case 'r': /* DECSTBM -- Set Scrolling Region */ @@ -1873,7 +1937,7 @@ iso14755(const Arg *arg) (*e != '\n' && *e != '\0')) return; - ttysend(uc, utf8encode(utf32, uc)); + ttywrite(uc, utf8encode(utf32, uc), 1); } void @@ -2086,7 +2150,7 @@ tcontrolcode(uchar ascii) case 0x99: /* TODO: SGCI */ break; case 0x9a: /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden)); + ttywrite(vtiden, strlen(vtiden), 0); break; case 0x9b: /* TODO: CSI */ case 0x9c: /* TODO: ST */ @@ -2158,7 +2222,7 @@ eschandle(uchar ascii) } break; case 'Z': /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden)); + ttywrite(vtiden, strlen(vtiden), 0); break; case 'c': /* RIS -- Reset to inital state */ treset();