terminal: add term_osc8_{open,close} functions

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).
This commit is contained in:
Daniel Eklöf 2021-02-13 12:34:48 +01:00
parent 841e5f0e50
commit 682494d45a
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 57 additions and 0 deletions

View file

@ -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)) {
/* Its 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};
}

View file

@ -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);