From 2c10a147ea0e471f12facfa11913272d42163f76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 6 Feb 2021 11:51:58 +0100 Subject: [PATCH] url-mode: underline URLs using the color from colors.urls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is implemented by allocating one of the (few!) remaining bits in the cells’ attribute struct to indicate the cell should be “URL highlighted”. render_cell() looks at this bit and draws an underline using the color from colors.urls (defaults to regular3 - i.e. yellow). A new function, url_tag_cells(), iterates the currently detected URLs and sets the new ‘url’ attribute flag on the affected cells. Note: this is done in a separate function to keep urls_collect() free from as many dependencies as possible. urls_reset() is updated to *clear* the ‘url’ flag (and thus implicitly also results in a grid refresh, _if_ there were any URLs). We now exit URL mode on *any* client application input. This needs to be so since we can’t know if the URLs we previously detected are still valid. --- input.c | 1 + render.c | 9 +++++++++ terminal.c | 2 ++ terminal.h | 3 ++- url-mode.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ url-mode.h | 1 + 6 files changed, 61 insertions(+), 1 deletion(-) diff --git a/input.c b/input.c index 10507aa8..7ba8e8e0 100644 --- a/input.c +++ b/input.c @@ -281,6 +281,7 @@ execute_binding(struct seat *seat, struct terminal *term, : URL_ACTION_LAUNCH; urls_collect(term, url_action); + urls_tag_cells(term); render_refresh_urls(term); return true; } diff --git a/render.c b/render.c index fff280fc..4e41f48a 100644 --- a/render.c +++ b/render.c @@ -616,6 +616,15 @@ render_cell(struct terminal *term, pixman_image_t *pix, if (cell->attrs.strikethrough) draw_strikeout(term, pix, font, &fg, x, y, cell_cols); + if (unlikely(cell->attrs.url)) { + pixman_color_t url_color = color_hex_to_pixman( + term->conf->colors.use_custom.url + ? term->conf->colors.url + : term->colors.table[3] + ); + draw_underline(term, pix, font, &url_color, x, y, cell_cols); + } + draw_cursor: if (has_cursor && (term->cursor_style != CURSOR_BLOCK || !term->kbd_focus)) draw_cursor(term, cell, font, pix, &fg, &bg, x, y, cell_cols); diff --git a/terminal.c b/terminal.c index c67dda58..91a442ec 100644 --- a/terminal.c +++ b/terminal.c @@ -228,6 +228,8 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data) cursor_blink_rearm_timer(term); } + urls_reset(term); + uint8_t buf[24 * 1024]; ssize_t count = sizeof(buf); diff --git a/terminal.h b/terminal.h index c6a618bf..bb98efc2 100644 --- a/terminal.h +++ b/terminal.h @@ -40,7 +40,8 @@ struct attributes { uint32_t have_fg:1; uint32_t have_bg:1; uint32_t selected:2; - uint32_t reserved:3; + uint32_t url:1; + uint32_t reserved:2; uint32_t bg:24; }; static_assert(sizeof(struct attributes) == 8, "bad size"); diff --git a/url-mode.c b/url-mode.c index 8f3b867e..e418eb7e 100644 --- a/url-mode.c +++ b/url-mode.c @@ -7,6 +7,7 @@ #define LOG_ENABLE_DBG 1 #include "log.h" #include "grid.h" +#include "render.h" #include "selection.h" #include "spawn.h" #include "terminal.h" @@ -399,6 +400,49 @@ urls_collect(struct terminal *term, enum url_action action) } } +static void +tag_cells_for_url(struct terminal *term, const struct url *url, bool value) +{ + const struct coord *start = &url->start; + const struct coord *end = &url->end; + + size_t end_r = end->row & (term->grid->num_rows - 1); + + size_t r = start->row & (term->grid->num_rows - 1); + size_t c = start->col; + + struct row *row = term->grid->rows[r]; + row->dirty = true; + + while (true) { + struct cell *cell = &row->cells[c]; + cell->attrs.url = value; + cell->attrs.clean = 0; + + if (r == end_r && c == end->col) + break; + + if (++c >= term->cols) { + r = (r + 1) & (term->grid->num_rows - 1); + c = 0; + + row = term->grid->rows[r]; + row->dirty = true; + } + } +} + +void +urls_tag_cells(struct terminal *term) +{ + if (unlikely(tll_length(term->urls)) == 0) + return; + + tll_foreach(term->urls, it) + tag_cells_for_url(term, &it->item, true); + render_refresh(term); +} + void urls_reset(struct terminal *term) { @@ -416,10 +460,12 @@ urls_reset(struct terminal *term) } tll_foreach(term->urls, it) { + tag_cells_for_url(term, &it->item, false); free(it->item.url); free(it->item.text); } tll_free(term->urls); memset(term->url_keys, 0, sizeof(term->url_keys)); + render_refresh(term); } diff --git a/url-mode.h b/url-mode.h index 94c1e675..6651e119 100644 --- a/url-mode.h +++ b/url-mode.h @@ -12,6 +12,7 @@ static inline bool urls_mode_is_active(const struct terminal *term) } void urls_collect(struct terminal *term, enum url_action action); +void urls_tag_cells(struct terminal *term); void urls_reset(struct terminal *term); void urls_input(struct seat *seat, struct terminal *term, uint32_t key,