From c9a65a95d8493871bf6d1265592908e7b3ef68ad Mon Sep 17 00:00:00 2001 From: Jocelyn Falempe Date: Wed, 14 Jan 2026 16:47:47 +0100 Subject: [PATCH] vte: Add bracketed paste support (DEC 2004) When set, enclose the pasted data with escape character. Signed-off-by: Jocelyn Falempe --- src/tsm/libtsm.h | 2 ++ src/tsm/libtsm.sym | 5 +++++ src/tsm/tsm-vte.c | 23 +++++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/src/tsm/libtsm.h b/src/tsm/libtsm.h index 661ff64..2a07899 100644 --- a/src/tsm/libtsm.h +++ b/src/tsm/libtsm.h @@ -377,6 +377,7 @@ enum tsm_vte_color { #define TSM_VTE_MOUSE_EVENT_ANY 1003 /* sends position on mouse click and mouse move */ #define TSM_VTE_MOUSE_MODE_SGR 1006 /* modern mode that allows unlimited x and y coordinates */ #define TSM_VTE_MOUSE_MODE_PIXEL 1016 /* sends pixel coordinates instead of cell coordinates */ +#define TSM_VTE_BRACKETED_PASTE 2004 /* enclose paste data with escape characters */ enum tsm_mouse_track_mode { TSM_MOUSE_TRACK_DISABLE = 0, /* don't track mouse events */ @@ -520,6 +521,7 @@ bool tsm_vte_handle_mouse(struct tsm_vte *vte, unsigned int cell_x, unsigned int cell_y, unsigned int pixel_x, unsigned int pixel_y, unsigned int button, unsigned int event, unsigned char flags); +void tsm_vte_paste(struct tsm_vte *vte, const char *data); /** @} */ #ifdef __cplusplus diff --git a/src/tsm/libtsm.sym b/src/tsm/libtsm.sym index be7f246..5f2852f 100644 --- a/src/tsm/libtsm.sym +++ b/src/tsm/libtsm.sym @@ -137,3 +137,8 @@ LIBTSM_4_3 { global: tsm_screen_selection_word; } LIBTSM_4_1; + +LIBTSM_4_4 { +global: + tsm_vte_paste; +} LIBTSM_4_3; diff --git a/src/tsm/tsm-vte.c b/src/tsm/tsm-vte.c index ab62993..7827880 100644 --- a/src/tsm/tsm-vte.c +++ b/src/tsm/tsm-vte.c @@ -176,6 +176,7 @@ struct tsm_vte { unsigned int mouse_event; unsigned int mouse_last_col; unsigned int mouse_last_row; + bool bracketed_paste; uint8_t (*custom_palette_storage)[3]; uint8_t (*palette)[3]; @@ -1756,6 +1757,9 @@ static void csi_mode(struct tsm_vte *vte, bool set) continue; } continue; + case TSM_VTE_BRACKETED_PASTE: + vte->bracketed_paste = set; + continue; default: llog_debug(vte, "unknown DEC %set-Mode %d", set?"S":"Res", vte->csi_argv[i]); @@ -3358,3 +3362,22 @@ bool tsm_vte_handle_mouse(struct tsm_vte *vte, unsigned int cell_x, return false; } + +void tsm_vte_paste(struct tsm_vte *vte, const char *data) +{ + if (vte->bracketed_paste) { + const char start[] = "\e[200~"; + const char end[] = "\e[201~"; + char *buf; + int len; + + len = strlen(data) + sizeof(start) + sizeof(end) + 1; + buf = malloc(len); + if (!buf) + return; + snprintf(buf, len, "%s%s%s", start, data, end); + vte_write(vte, buf, strlen(buf)); + free(buf); + } else + vte_write(vte, data, strlen(data)); +} \ No newline at end of file