Move CRLF input processing into ttywrite
[st.git] / st.c
diff --git a/st.c b/st.c
index 641f896..3ebf8c6 100644 (file)
--- a/st.c
+++ b/st.c
 #include <time.h>
 #include <unistd.h>
 #include <libgen.h>
-#include <fontconfig/fontconfig.h>
 #include <wchar.h>
 
-/* X11 */
-#include <X11/cursorfont.h>
-#include <X11/Xft/Xft.h>
-
 #include "st.h"
 #include "win.h"
 
@@ -109,23 +104,11 @@ typedef struct {
        int narg;              /* nb of args */
 } STREscape;
 
-/* function definitions used in config.h */
-static void clipcopy(const Arg *);
-static void clippaste(const Arg *);
-static void numlock(const Arg *);
-static void selpaste(const Arg *);
-static void printsel(const Arg *);
-static void printscreen(const Arg *) ;
-static void iso14755(const Arg *);
-static void toggleprinter(const Arg *);
-static void sendbreak(const Arg *);
-
-/* config.h for applying patches and the configuration. */
-#include "config.h"
 
 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);
@@ -158,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);
@@ -183,13 +167,12 @@ static char *base64dec(const char *);
 static ssize_t xwrite(int, const char *, size_t);
 
 /* Globals */
-TermWindow win;
 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;
@@ -199,14 +182,6 @@ 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};
 
-/* config.h array lengths */
-size_t colornamelen = LEN(colorname);
-size_t mshortcutslen = LEN(mshortcuts);
-size_t shortcutslen = LEN(shortcuts);
-size_t selmaskslen = LEN(selmasks);
-size_t keyslen = LEN(key);
-size_t mappedkeyslen = LEN(mappedkeys);
-
 ssize_t
 xwrite(int fd, const char *s, size_t len)
 {
@@ -392,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
@@ -415,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)
 {
@@ -446,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)
@@ -585,24 +603,6 @@ getsel(void)
        return str;
 }
 
-void
-selpaste(const Arg *dummy)
-{
-       xselpaste();
-}
-
-void
-clipcopy(const Arg *dummy)
-{
-       xclipcopy();
-}
-
-void
-clippaste(const Arg *dummy)
-{
-       xclippaste();
-}
-
 void
 selclear(void)
 {
@@ -715,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;
@@ -736,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()) {
@@ -786,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;
@@ -842,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)
 {
@@ -1572,7 +1591,7 @@ csihandle(void)
                break;
        case 'c': /* DA -- Device Attributes */
                if (csiescseq.arg[0] == 0)
-                       ttywrite(vtiden, sizeof(vtiden) - 1);
+                       ttywrite(vtiden, strlen(vtiden), 0);
                break;
        case 'C': /* CUF -- Cursor <n> Forward */
        case 'a': /* HPR -- Cursor <n> Forward */
@@ -1700,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 */
@@ -1722,11 +1741,8 @@ csihandle(void)
        case ' ':
                switch (csiescseq.mode[1]) {
                case 'q': /* DECSCUSR -- Set Cursor Style */
-                       DEFAULT(csiescseq.arg[0], 1);
-                       if (!BETWEEN(csiescseq.arg[0], 0, 6)) {
+                       if (xsetcursor(csiescseq.arg[0]))
                                goto unknown;
-                       }
-                       win.cursor = csiescseq.arg[0];
                        break;
                default:
                        goto unknown;
@@ -1790,8 +1806,8 @@ strhandle(void)
 
                                dec = base64dec(strescseq.args[2]);
                                if (dec) {
-                                       xsetsel(dec, CurrentTime);
-                                       clipcopy(NULL);
+                                       xsetsel(dec);
+                                       xclipcopy();
                                } else {
                                        fprintf(stderr, "erresc: invalid base64\n");
                                }
@@ -1921,7 +1937,7 @@ iso14755(const Arg *arg)
            (*e != '\n' && *e != '\0'))
                return;
 
-       ttysend(uc, utf8encode(utf32, uc));
+       ttywrite(uc, utf8encode(utf32, uc), 1);
 }
 
 void
@@ -2134,7 +2150,7 @@ tcontrolcode(uchar ascii)
        case 0x99:   /* TODO: SGCI */
                break;
        case 0x9a:   /* DECID -- Identify Terminal */
-               ttywrite(vtiden, sizeof(vtiden) - 1);
+               ttywrite(vtiden, strlen(vtiden), 0);
                break;
        case 0x9b:   /* TODO: CSI */
        case 0x9c:   /* TODO: ST */
@@ -2206,7 +2222,7 @@ eschandle(uchar ascii)
                }
                break;
        case 'Z': /* DECID -- Identify Terminal */
-               ttywrite(vtiden, sizeof(vtiden) - 1);
+               ttywrite(vtiden, strlen(vtiden), 0);
                break;
        case 'c': /* RIS -- Reset to inital state */
                treset();