From 682494d45a50e81aec0618bdd2d282ad17fe27d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 13 Feb 2021 12:34:48 +0100 Subject: [PATCH] terminal: add term_osc8_{open,close} functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These functions update the OSC-8 URI state in the terminal. term_osc8_open() tracks the beginning of an URL, by storing the start coordinate (i.e. the current cursor location), along with the URL itself. Note that term_osc8_open() may not be called with an empty URL. This is important to notice, since the way OSC-8 works, applications close an URL by “opening” a new, empty one: \E]8;;https://foo.bar\e\\this is an OSC-8 URL\E]8;;\e\\ It is up to the caller to check for this, and call term_osc8_close() instead of term_osc8_open() when the URL is empty. However, it is *also* valid to switch directly from one URL to another: \E]8;;http://123\e\\First URL\E]8;;http//456\e\\Second URL\E]8;;\e\\ This use-case *is* handled by term_osc8_open(). term_osc8_close() uses the information from term_osc8_open() to add per-row URL data (using the new ‘extra’ row data). --- terminal.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ terminal.h | 3 +++ 2 files changed, 57 insertions(+) diff --git a/terminal.c b/terminal.c index 28c061ca..c6afbef1 100644 --- a/terminal.c +++ b/terminal.c @@ -3015,3 +3015,57 @@ term_ime_set_cursor_rect(struct terminal *term, int x, int y, int width, #endif } +void +term_osc8_open(struct terminal *term, const char *uri) +{ + if (unlikely(term->vt.osc8.begin.row < 0)) { + /* It’s valid to switch from one URI to another without + * closing the first one */ + term_osc8_close(term); + } + + term->vt.osc8.begin = (struct coord){ + .col = term->grid->cursor.point.col, + .row = grid_row_absolute(term->grid, term->grid->cursor.point.row), + }; + term->vt.osc8.uri = xstrdup(uri); +} + +void +term_osc8_close(struct terminal *term) +{ + if (term->vt.osc8.begin.row < 0) + return; + + if (term->vt.osc8.uri[0] == '\0') + goto done; + + struct coord start = term->vt.osc8.begin; + struct coord end = (struct coord){ + .col = term->grid->cursor.point.col, + .row = grid_row_absolute(term->grid, term->grid->cursor.point.row), + }; + + int r = start.row; + int start_col = start.col; + do { + int end_col = r == end.row ? end.col : term->cols - 1; + + struct row *row = term->grid->rows[r]; + if (row->extra == NULL) + row->extra = xcalloc(1, sizeof(*row->extra)); + + struct row_uri_range range = { + .start = start_col, + .end = end_col, + .uri = xstrdup(term->vt.osc8.uri), + }; + tll_push_back(row->extra->uri_ranges, range); + start_col = 0; + } while (r++ != end.row); + +done: + free(term->vt.osc8.uri); + term->vt.osc8.uri = NULL; + term->vt.osc8.begin = (struct coord){-1, -1}; +} diff --git a/terminal.h b/terminal.h index 3f58180b..6dc211d9 100644 --- a/terminal.h +++ b/terminal.h @@ -689,3 +689,6 @@ void term_ime_set_cursor_rect( void term_urls_reset(struct terminal *term); void term_collect_urls(struct terminal *term); + +void term_osc8_open(struct terminal *term, const char *uri); +void term_osc8_close(struct terminal *term);