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,