url-mode: underline URLs using the color from colors.urls

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.
This commit is contained in:
Daniel Eklöf 2021-02-06 11:51:58 +01:00
parent 6726494f4c
commit 2c10a147ea
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
6 changed files with 61 additions and 1 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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,