mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-29 06:46:35 -04:00
term: use custom cursor movement functions when OSC-8 is active
Use runtime switchable function pointers for cursor movement functions. The “normal” once are not OSC-8 aware, while the *_osc8 are. OSC-8 aware means the cursor movement functions will “close” the currently open URL before moving the cursor, and then re-open the URL after having moved the cursor. This simulates SGR-like behavior for OSC-8 URLs; the URL “property” is only assigned to cells that are actually printed to. Closes #816
This commit is contained in:
parent
11e7539b84
commit
d19326c496
2 changed files with 169 additions and 43 deletions
183
terminal.c
183
terminal.c
|
|
@ -58,6 +58,9 @@ const char *const XCURSOR_RIGHT_SIDE = "right_side";
|
|||
const char *const XCURSOR_TOP_SIDE = "top_side";
|
||||
const char *const XCURSOR_BOTTOM_SIDE = "bottom_side";
|
||||
|
||||
static void term_set_cursor_move_normal(struct terminal *term);
|
||||
static void term_set_cursor_move_osc8(struct terminal *term);
|
||||
|
||||
static void
|
||||
enqueue_data_for_slave(const void *data, size_t len, size_t offset,
|
||||
ptmx_buffer_list_t *buffer_list)
|
||||
|
|
@ -1223,7 +1226,8 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
#endif
|
||||
};
|
||||
|
||||
term_update_ascii_printer(term);
|
||||
term_update_ascii_printer(term);
|
||||
term_set_cursor_move_normal(term);
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
const struct config_font_list *font_list = &conf->fonts[i];
|
||||
|
|
@ -1851,6 +1855,7 @@ term_reset(struct terminal *term, bool hard)
|
|||
#endif
|
||||
|
||||
term_update_ascii_printer(term);
|
||||
term_set_cursor_move_normal(term);
|
||||
|
||||
if (!hard)
|
||||
return;
|
||||
|
|
@ -2347,62 +2352,160 @@ term_row_rel_to_abs(const struct terminal *term, int row)
|
|||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
term_cursor_to(struct terminal *term, int row, int col)
|
||||
{
|
||||
xassert(row < term->rows);
|
||||
xassert(col < term->cols);
|
||||
|
||||
term->grid->cursor.lcf = false;
|
||||
|
||||
term->grid->cursor.point.col = col;
|
||||
term->grid->cursor.point.row = row;
|
||||
|
||||
term->grid->cur_row = grid_row(term->grid, row);
|
||||
}
|
||||
|
||||
void
|
||||
term_cursor_home(struct terminal *term)
|
||||
{
|
||||
term_cursor_to(term, term_row_rel_to_abs(term, 0), 0);
|
||||
}
|
||||
|
||||
void
|
||||
term_cursor_left(struct terminal *term, int count)
|
||||
static void
|
||||
cursor_to(struct terminal *term, int row, int col)
|
||||
{
|
||||
int move_amount = min(term->grid->cursor.point.col, count);
|
||||
term->grid->cursor.point.col -= move_amount;
|
||||
xassert(term->grid->cursor.point.col >= 0);
|
||||
term->grid->cursor.lcf = false;
|
||||
xassert(row < term->rows);
|
||||
xassert(col < term->cols);
|
||||
|
||||
struct grid *grid = term->grid;
|
||||
|
||||
grid->cursor.lcf = false;
|
||||
grid->cursor.point.col = col;
|
||||
grid->cursor.point.row = row;
|
||||
grid->cur_row = grid_row(grid, row);
|
||||
}
|
||||
|
||||
void
|
||||
term_cursor_right(struct terminal *term, int count)
|
||||
static void
|
||||
cursor_to_osc8(struct terminal *term, int row, int col)
|
||||
{
|
||||
int move_amount = min(term->cols - term->grid->cursor.point.col - 1, count);
|
||||
term->grid->cursor.point.col += move_amount;
|
||||
xassert(term->grid->cursor.point.col < term->cols);
|
||||
term->grid->cursor.lcf = false;
|
||||
xassert(row < term->rows);
|
||||
xassert(col < term->cols);
|
||||
xassert(term->vt.osc8.begin.row >= 0);
|
||||
|
||||
struct grid *grid = term->grid;
|
||||
|
||||
char *osc8_uri = xstrdup(term->vt.osc8.uri);
|
||||
uint64_t osc8_id = term->vt.osc8.id;
|
||||
|
||||
term_osc8_close(term);
|
||||
grid->cursor.lcf = false;
|
||||
grid->cursor.point.col = col;
|
||||
grid->cursor.point.row = row;
|
||||
grid->cur_row = grid_row(grid, row);
|
||||
term_osc8_open(term, osc8_id, osc8_uri);
|
||||
free(osc8_uri);
|
||||
}
|
||||
|
||||
void
|
||||
term_cursor_up(struct terminal *term, int count)
|
||||
static void
|
||||
cursor_left(struct terminal *term, int count)
|
||||
{
|
||||
struct grid *grid = term->grid;
|
||||
const int move_amount = min(grid->cursor.point.col, count);
|
||||
grid->cursor.point.col -= move_amount;
|
||||
xassert(grid->cursor.point.col >= 0);
|
||||
grid->cursor.lcf = false;
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_left_osc8(struct terminal *term, int count)
|
||||
{
|
||||
struct grid *grid = term->grid;
|
||||
const int move_amount = min(grid->cursor.point.col, count);
|
||||
cursor_to_osc8(
|
||||
term,
|
||||
grid->cursor.point.row,
|
||||
grid->cursor.point.col - move_amount);
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_right(struct terminal *term, int count)
|
||||
{
|
||||
struct grid *grid = term->grid;
|
||||
const int move_amount = min(term->cols - grid->cursor.point.col - 1, count);
|
||||
grid->cursor.point.col += move_amount;
|
||||
xassert(grid->cursor.point.col < term->cols);
|
||||
grid->cursor.lcf = false;
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_right_osc8(struct terminal *term, int count)
|
||||
{
|
||||
struct grid *grid = term->grid;
|
||||
int move_amount = min(term->cols - grid->cursor.point.col - 1, count);
|
||||
cursor_to_osc8(
|
||||
term,
|
||||
grid->cursor.point.row,
|
||||
grid->cursor.point.col + move_amount);
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_up(struct terminal *term, int count)
|
||||
{
|
||||
struct grid *grid = term->grid;
|
||||
|
||||
int top = term->origin == ORIGIN_ABSOLUTE ? 0 : term->scroll_region.start;
|
||||
xassert(term->grid->cursor.point.row >= top);
|
||||
xassert(grid->cursor.point.row >= top);
|
||||
|
||||
int move_amount = min(term->grid->cursor.point.row - top, count);
|
||||
term_cursor_to(term, term->grid->cursor.point.row - move_amount, term->grid->cursor.point.col);
|
||||
int move_amount = min(grid->cursor.point.row - top, count);
|
||||
term_cursor_to(
|
||||
term, grid->cursor.point.row - move_amount, grid->cursor.point.col);
|
||||
}
|
||||
|
||||
void
|
||||
term_cursor_down(struct terminal *term, int count)
|
||||
static void
|
||||
cursor_up_osc8(struct terminal *term, int count)
|
||||
{
|
||||
int bottom = term->origin == ORIGIN_ABSOLUTE ? term->rows : term->scroll_region.end;
|
||||
xassert(bottom >= term->grid->cursor.point.row);
|
||||
struct grid *grid = term->grid;
|
||||
|
||||
int move_amount = min(bottom - term->grid->cursor.point.row - 1, count);
|
||||
term_cursor_to(term, term->grid->cursor.point.row + move_amount, term->grid->cursor.point.col);
|
||||
int top = term->origin == ORIGIN_ABSOLUTE ? 0 : term->scroll_region.start;
|
||||
xassert(grid->cursor.point.row >= top);
|
||||
|
||||
int move_amount = min(grid->cursor.point.row - top, count);
|
||||
cursor_to_osc8(
|
||||
term, grid->cursor.point.row - move_amount, grid->cursor.point.col);
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_down(struct terminal *term, int count)
|
||||
{
|
||||
struct grid *grid = term->grid;
|
||||
|
||||
int bottom = term->origin == ORIGIN_ABSOLUTE ? term->rows : term->scroll_region.end;
|
||||
xassert(bottom >= grid->cursor.point.row);
|
||||
|
||||
int move_amount = min(bottom - grid->cursor.point.row - 1, count);
|
||||
cursor_to(term, grid->cursor.point.row + move_amount, grid->cursor.point.col);
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_down_osc8(struct terminal *term, int count)
|
||||
{
|
||||
struct grid *grid = term->grid;
|
||||
|
||||
int bottom = term->origin == ORIGIN_ABSOLUTE ? term->rows : term->scroll_region.end;
|
||||
xassert(bottom >= grid->cursor.point.row);
|
||||
|
||||
int move_amount = min(bottom - grid->cursor.point.row - 1, count);
|
||||
cursor_to_osc8(
|
||||
term, grid->cursor.point.row + move_amount, grid->cursor.point.col);
|
||||
}
|
||||
|
||||
static void
|
||||
term_set_cursor_move_normal(struct terminal *term)
|
||||
{
|
||||
LOG_DBG("disabling OSC-8 aware cursor movements");
|
||||
term->cursor_move.to = &cursor_to;
|
||||
term->cursor_move.left = &cursor_left;
|
||||
term->cursor_move.right = &cursor_right;
|
||||
term->cursor_move.up = &cursor_up;
|
||||
term->cursor_move.down = &cursor_down;
|
||||
}
|
||||
|
||||
static void
|
||||
term_set_cursor_move_osc8(struct terminal *term)
|
||||
{
|
||||
LOG_DBG("enabling OSC-8 aware cursor movements");
|
||||
term->cursor_move.to = &cursor_to_osc8;
|
||||
term->cursor_move.left = &cursor_left_osc8;
|
||||
term->cursor_move.right = &cursor_right_osc8;
|
||||
term->cursor_move.up = &cursor_up_osc8;
|
||||
term->cursor_move.down = &cursor_down_osc8;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -3505,11 +3608,15 @@ term_osc8_open(struct terminal *term, uint64_t id, const char *uri)
|
|||
};
|
||||
term->vt.osc8.id = id;
|
||||
term->vt.osc8.uri = xstrdup(uri);
|
||||
|
||||
term_set_cursor_move_osc8(term);
|
||||
}
|
||||
|
||||
void
|
||||
term_osc8_close(struct terminal *term)
|
||||
{
|
||||
term_set_cursor_move_normal(term);
|
||||
|
||||
if (term->vt.osc8.begin.row < 0)
|
||||
return;
|
||||
|
||||
|
|
|
|||
29
terminal.h
29
terminal.h
|
|
@ -289,6 +289,13 @@ struct terminal {
|
|||
const struct config *conf;
|
||||
|
||||
void (*ascii_printer)(struct terminal *term, wchar_t c);
|
||||
struct {
|
||||
void (*to)(struct terminal *term, int row, int col);
|
||||
void (*left)(struct terminal *term, int count);
|
||||
void (*right)(struct terminal *term, int count);
|
||||
void (*up)(struct terminal *term, int count);
|
||||
void (*down)(struct terminal *term, int count);
|
||||
} cursor_move;
|
||||
|
||||
pid_t slave;
|
||||
int ptmx;
|
||||
|
|
@ -696,11 +703,23 @@ void term_erase_scrollback(struct terminal *term);
|
|||
|
||||
int term_row_rel_to_abs(const struct terminal *term, int row);
|
||||
void term_cursor_home(struct terminal *term);
|
||||
void term_cursor_to(struct terminal *term, int row, int col);
|
||||
void term_cursor_left(struct terminal *term, int count);
|
||||
void term_cursor_right(struct terminal *term, int count);
|
||||
void term_cursor_up(struct terminal *term, int count);
|
||||
void term_cursor_down(struct terminal *term, int count);
|
||||
|
||||
static inline void term_cursor_to(struct terminal *term, int row, int col) {
|
||||
term->cursor_move.to(term, row, col);
|
||||
}
|
||||
static inline void term_cursor_left(struct terminal *term, int count) {
|
||||
term->cursor_move.left(term, count);
|
||||
}
|
||||
static inline void term_cursor_right(struct terminal *term, int count) {
|
||||
term->cursor_move.right(term, count);
|
||||
}
|
||||
static inline void term_cursor_up(struct terminal *term, int count) {
|
||||
term->cursor_move.up(term, count);
|
||||
}
|
||||
static inline void term_cursor_down(struct terminal *term, int count) {
|
||||
term->cursor_move.down(term, count);
|
||||
}
|
||||
|
||||
void term_cursor_blink_update(struct terminal *term);
|
||||
|
||||
void term_print(struct terminal *term, wchar_t wc, int width);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue