From c3a23cf5b7a06ed5e218c6bf912aa666836857fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 21 Dec 2019 19:42:59 +0100 Subject: [PATCH] osc: implement OSC 7 - set PWD OSC 7 updates the terminal's view of the current working directory. The format is OSC 7;URI ST We decode the URI and updates the term structs 'cwd' member. This is then used when spawning a new terminal instance. --- osc.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/osc.c b/osc.c index d69c34b9..d327d376 100644 --- a/osc.c +++ b/osc.c @@ -298,6 +298,66 @@ parse_rgb(const char *string, uint32_t *color) return true; } +static uint8_t +nibble2hex(char c) +{ + switch (c) { + case '0' ... '9': return c - '0'; + case 'a' ... 'f': return c - 'a' + 10; + case 'A' ... 'F': return c - 'A' + 10; + } + + assert(false); + return 0; +} + +static void +osc_set_pwd(struct terminal *term, char *string) +{ + LOG_DBG("PWD: URI: %s", string); + + if (memcmp(string, "file://", 7) != 0) + return; + string += 7; + + /* Skip past hostname */ + if ((string = strchr(string, '/')) == NULL) + return; + + /* Decode %xx encoded characters */ + char *pwd = malloc(strlen(string) + 1); + char *p = pwd; + + while (true) { + /* Find next '%' */ + char *next = strchr(string, '%'); + + if (next == NULL) { + strcpy(p, string); + break; + } + + /* Copy everything leading up to the '%' */ + size_t prefix_len = next - string; + memcpy(p, string, prefix_len); + p += prefix_len; + + if (isxdigit(next[1]) && isxdigit(next[2])) { + *p++ = nibble2hex(next[1]) << 4 | nibble2hex(next[2]); + *p = '\0'; + string = next + 3; + } else { + *p++ = *next; + *p = '\0'; + string = next + 1; + } + } + + LOG_DBG("PWD: decoded: %s", pwd); + free(term->cwd); + term->cwd = pwd; +} + #if 0 static void osc_notify(struct terminal *term, char *string) @@ -396,6 +456,11 @@ osc_dispatch(struct terminal *term) break; } + case 7: + /* Update terminal's understanding of PWD */ + osc_set_pwd(term, string); + break; + case 10: case 11: { /* Set default foreground/background color */