mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-15 22:31:47 -04:00
vt: bracketed paste support
This is comprised of 3 aspects:
- Take note of when applications advertise bracketed paste support via
"\e[?2004h" and "\e[?2004l".
- Insert bracketed paste markers ("\e[200~" and "\e[201~") around pasted
content in paste_selection() when bracketed paste is active.
- Add TIOCL_GETBRACKETEDPASTE to return bracketed paste status so user
space daemons implementing cut-and-paste functionality (e.g. gpm,
BRLTTY) may know when to insert bracketed paste markers.
Link: https://en.wikipedia.org/wiki/Bracketed-paste
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
Link: https://lore.kernel.org/r/20250520171851.1219676-2-nico@fluxnic.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
c4c7ead7b8
commit
80fa7a0337
@@ -403,6 +403,12 @@ int paste_selection(struct tty_struct *tty)
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
int ret = 0;
|
||||
|
||||
bool bp = vc->vc_bracketed_paste;
|
||||
static const char bracketed_paste_start[] = "\033[200~";
|
||||
static const char bracketed_paste_end[] = "\033[201~";
|
||||
const char *bps = bp ? bracketed_paste_start : NULL;
|
||||
const char *bpe = bp ? bracketed_paste_end : NULL;
|
||||
|
||||
console_lock();
|
||||
poke_blanked_console();
|
||||
console_unlock();
|
||||
@@ -414,7 +420,7 @@ int paste_selection(struct tty_struct *tty)
|
||||
|
||||
add_wait_queue(&vc->paste_wait, &wait);
|
||||
mutex_lock(&vc_sel.lock);
|
||||
while (vc_sel.buffer && vc_sel.buf_len > pasted) {
|
||||
while (vc_sel.buffer && (vc_sel.buf_len > pasted || bpe)) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (signal_pending(current)) {
|
||||
ret = -EINTR;
|
||||
@@ -427,10 +433,27 @@ int paste_selection(struct tty_struct *tty)
|
||||
continue;
|
||||
}
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
||||
if (bps) {
|
||||
bps += tty_ldisc_receive_buf(ld, bps, NULL, strlen(bps));
|
||||
if (*bps != '\0')
|
||||
continue;
|
||||
bps = NULL;
|
||||
}
|
||||
|
||||
count = vc_sel.buf_len - pasted;
|
||||
count = tty_ldisc_receive_buf(ld, vc_sel.buffer + pasted, NULL,
|
||||
count);
|
||||
pasted += count;
|
||||
if (count) {
|
||||
pasted += tty_ldisc_receive_buf(ld, vc_sel.buffer + pasted,
|
||||
NULL, count);
|
||||
if (vc_sel.buf_len > pasted)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bpe) {
|
||||
bpe += tty_ldisc_receive_buf(ld, bpe, NULL, strlen(bpe));
|
||||
if (*bpe == '\0')
|
||||
bpe = NULL;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&vc_sel.lock);
|
||||
remove_wait_queue(&vc->paste_wait, &wait);
|
||||
|
||||
@@ -1870,6 +1870,14 @@ int mouse_reporting(void)
|
||||
return vc_cons[fg_console].d->vc_report_mouse;
|
||||
}
|
||||
|
||||
/* invoked via ioctl(TIOCLINUX) */
|
||||
static int get_bracketed_paste(struct tty_struct *tty)
|
||||
{
|
||||
struct vc_data *vc = tty->driver_data;
|
||||
|
||||
return vc->vc_bracketed_paste;
|
||||
}
|
||||
|
||||
enum {
|
||||
CSI_DEC_hl_CURSOR_KEYS = 1, /* CKM: cursor keys send ^[Ox/^[[x */
|
||||
CSI_DEC_hl_132_COLUMNS = 3, /* COLM: 80/132 mode switch */
|
||||
@@ -1880,6 +1888,7 @@ enum {
|
||||
CSI_DEC_hl_MOUSE_X10 = 9,
|
||||
CSI_DEC_hl_SHOW_CURSOR = 25, /* TCEM */
|
||||
CSI_DEC_hl_MOUSE_VT200 = 1000,
|
||||
CSI_DEC_hl_BRACKETED_PASTE = 2004,
|
||||
};
|
||||
|
||||
/* console_lock is held */
|
||||
@@ -1932,6 +1941,9 @@ static void csi_DEC_hl(struct vc_data *vc, bool on_off)
|
||||
case CSI_DEC_hl_MOUSE_VT200:
|
||||
vc->vc_report_mouse = on_off ? 2 : 0;
|
||||
break;
|
||||
case CSI_DEC_hl_BRACKETED_PASTE:
|
||||
vc->vc_bracketed_paste = on_off;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2157,6 +2169,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
|
||||
vc->state.charset = 0;
|
||||
vc->vc_need_wrap = 0;
|
||||
vc->vc_report_mouse = 0;
|
||||
vc->vc_bracketed_paste = 0;
|
||||
vc->vc_utf = default_utf8;
|
||||
vc->vc_utf_count = 0;
|
||||
|
||||
@@ -3483,6 +3496,8 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
|
||||
break;
|
||||
case TIOCL_BLANKEDSCREEN:
|
||||
return console_blanked;
|
||||
case TIOCL_GETBRACKETEDPASTE:
|
||||
return get_bracketed_paste(tty);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -145,6 +145,7 @@ struct vc_data {
|
||||
unsigned int vc_need_wrap : 1;
|
||||
unsigned int vc_can_do_color : 1;
|
||||
unsigned int vc_report_mouse : 2;
|
||||
unsigned int vc_bracketed_paste : 1;
|
||||
unsigned char vc_utf : 1; /* Unicode UTF-8 encoding */
|
||||
unsigned char vc_utf_count;
|
||||
int vc_utf_char;
|
||||
|
||||
@@ -36,5 +36,6 @@ struct tiocl_selection {
|
||||
#define TIOCL_BLANKSCREEN 14 /* keep screen blank even if a key is pressed */
|
||||
#define TIOCL_BLANKEDSCREEN 15 /* return which vt was blanked */
|
||||
#define TIOCL_GETKMSGREDIRECT 17 /* get the vt the kernel messages are restricted to */
|
||||
#define TIOCL_GETBRACKETEDPASTE 18 /* get whether paste may be bracketed */
|
||||
|
||||
#endif /* _LINUX_TIOCL_H */
|
||||
|
||||
Reference in New Issue
Block a user