Skip to content

Commit 80fa7a0

Browse files
Nicolas Pitregregkh
authored andcommitted
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 <[email protected]> Reviewed-by: Jiri Slaby <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent c4c7ead commit 80fa7a0

File tree

4 files changed

+44
-4
lines changed

4 files changed

+44
-4
lines changed

drivers/tty/vt/selection.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,12 @@ int paste_selection(struct tty_struct *tty)
403403
DECLARE_WAITQUEUE(wait, current);
404404
int ret = 0;
405405

406+
bool bp = vc->vc_bracketed_paste;
407+
static const char bracketed_paste_start[] = "\033[200~";
408+
static const char bracketed_paste_end[] = "\033[201~";
409+
const char *bps = bp ? bracketed_paste_start : NULL;
410+
const char *bpe = bp ? bracketed_paste_end : NULL;
411+
406412
console_lock();
407413
poke_blanked_console();
408414
console_unlock();
@@ -414,7 +420,7 @@ int paste_selection(struct tty_struct *tty)
414420

415421
add_wait_queue(&vc->paste_wait, &wait);
416422
mutex_lock(&vc_sel.lock);
417-
while (vc_sel.buffer && vc_sel.buf_len > pasted) {
423+
while (vc_sel.buffer && (vc_sel.buf_len > pasted || bpe)) {
418424
set_current_state(TASK_INTERRUPTIBLE);
419425
if (signal_pending(current)) {
420426
ret = -EINTR;
@@ -427,10 +433,27 @@ int paste_selection(struct tty_struct *tty)
427433
continue;
428434
}
429435
__set_current_state(TASK_RUNNING);
436+
437+
if (bps) {
438+
bps += tty_ldisc_receive_buf(ld, bps, NULL, strlen(bps));
439+
if (*bps != '\0')
440+
continue;
441+
bps = NULL;
442+
}
443+
430444
count = vc_sel.buf_len - pasted;
431-
count = tty_ldisc_receive_buf(ld, vc_sel.buffer + pasted, NULL,
432-
count);
433-
pasted += count;
445+
if (count) {
446+
pasted += tty_ldisc_receive_buf(ld, vc_sel.buffer + pasted,
447+
NULL, count);
448+
if (vc_sel.buf_len > pasted)
449+
continue;
450+
}
451+
452+
if (bpe) {
453+
bpe += tty_ldisc_receive_buf(ld, bpe, NULL, strlen(bpe));
454+
if (*bpe == '\0')
455+
bpe = NULL;
456+
}
434457
}
435458
mutex_unlock(&vc_sel.lock);
436459
remove_wait_queue(&vc->paste_wait, &wait);

drivers/tty/vt/vt.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,6 +1870,14 @@ int mouse_reporting(void)
18701870
return vc_cons[fg_console].d->vc_report_mouse;
18711871
}
18721872

1873+
/* invoked via ioctl(TIOCLINUX) */
1874+
static int get_bracketed_paste(struct tty_struct *tty)
1875+
{
1876+
struct vc_data *vc = tty->driver_data;
1877+
1878+
return vc->vc_bracketed_paste;
1879+
}
1880+
18731881
enum {
18741882
CSI_DEC_hl_CURSOR_KEYS = 1, /* CKM: cursor keys send ^[Ox/^[[x */
18751883
CSI_DEC_hl_132_COLUMNS = 3, /* COLM: 80/132 mode switch */
@@ -1880,6 +1888,7 @@ enum {
18801888
CSI_DEC_hl_MOUSE_X10 = 9,
18811889
CSI_DEC_hl_SHOW_CURSOR = 25, /* TCEM */
18821890
CSI_DEC_hl_MOUSE_VT200 = 1000,
1891+
CSI_DEC_hl_BRACKETED_PASTE = 2004,
18831892
};
18841893

18851894
/* console_lock is held */
@@ -1932,6 +1941,9 @@ static void csi_DEC_hl(struct vc_data *vc, bool on_off)
19321941
case CSI_DEC_hl_MOUSE_VT200:
19331942
vc->vc_report_mouse = on_off ? 2 : 0;
19341943
break;
1944+
case CSI_DEC_hl_BRACKETED_PASTE:
1945+
vc->vc_bracketed_paste = on_off;
1946+
break;
19351947
}
19361948
}
19371949

@@ -2157,6 +2169,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
21572169
vc->state.charset = 0;
21582170
vc->vc_need_wrap = 0;
21592171
vc->vc_report_mouse = 0;
2172+
vc->vc_bracketed_paste = 0;
21602173
vc->vc_utf = default_utf8;
21612174
vc->vc_utf_count = 0;
21622175

@@ -3483,6 +3496,8 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
34833496
break;
34843497
case TIOCL_BLANKEDSCREEN:
34853498
return console_blanked;
3499+
case TIOCL_GETBRACKETEDPASTE:
3500+
return get_bracketed_paste(tty);
34863501
default:
34873502
return -EINVAL;
34883503
}

include/linux/console_struct.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ struct vc_data {
145145
unsigned int vc_need_wrap : 1;
146146
unsigned int vc_can_do_color : 1;
147147
unsigned int vc_report_mouse : 2;
148+
unsigned int vc_bracketed_paste : 1;
148149
unsigned char vc_utf : 1; /* Unicode UTF-8 encoding */
149150
unsigned char vc_utf_count;
150151
int vc_utf_char;

include/uapi/linux/tiocl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,6 @@ struct tiocl_selection {
3636
#define TIOCL_BLANKSCREEN 14 /* keep screen blank even if a key is pressed */
3737
#define TIOCL_BLANKEDSCREEN 15 /* return which vt was blanked */
3838
#define TIOCL_GETKMSGREDIRECT 17 /* get the vt the kernel messages are restricted to */
39+
#define TIOCL_GETBRACKETEDPASTE 18 /* get whether paste may be bracketed */
3940

4041
#endif /* _LINUX_TIOCL_H */

0 commit comments

Comments
 (0)