Patch 8.0.0210
Problem: Vim does not support bracketed paste, as implemented by xterm and
other terminals.
Solution: Add t_BE, t_BD, t_PS and t_PE.
Files: src/term.c, src/term.h, src/option.c, src/misc2.c, src/keymap.h,
src/edit.c, src/normal.c, src/evalfunc.c, src/getchar.c,
src/vim.h, src/proto/edit.pro, runtime/doc/term.txt
*** ../vim-8.0.0209/src/term.c 2017-01-06 18:16:15.632490849 +0100
--- src/term.c 2017-01-21 20:00:45.628203646 +0100
***************
*** 857,862 ****
--- 857,864 ----
{(int)KS_8F, IF_EB("\033[38;2;%lu;%lu;%lum", ESC_STR
"[38;2;%lu;%lu;%lum")},
{(int)KS_8B, IF_EB("\033[48;2;%lu;%lu;%lum", ESC_STR
"[48;2;%lu;%lu;%lum")},
# endif
+ {(int)KS_CBE, IF_EB("\033[?2004h", ESC_STR "[?2004h")},
+ {(int)KS_CBD, IF_EB("\033[?2004l", ESC_STR "[?2004l")},
{K_UP, IF_EB("\033O*A", ESC_STR "O*A")},
{K_DOWN, IF_EB("\033O*B", ESC_STR "O*B")},
***************
*** 902,914 ****
{K_ZEND, IF_EB("\033[8;*~", ESC_STR "[8;*~")},
{K_PAGEUP, IF_EB("\033[5;*~", ESC_STR "[5;*~")},
{K_PAGEDOWN, IF_EB("\033[6;*~", ESC_STR "[6;*~")},
! {K_KPLUS, IF_EB("\033O*k", ESC_STR "O*k")}, /* keypad plus
*/
! {K_KMINUS, IF_EB("\033O*m", ESC_STR "O*m")}, /*
keypad minus */
! {K_KDIVIDE, IF_EB("\033O*o", ESC_STR "O*o")}, /*
keypad / */
! {K_KMULTIPLY, IF_EB("\033O*j", ESC_STR "O*j")}, /* keypad * */
! {K_KENTER, IF_EB("\033O*M", ESC_STR "O*M")}, /*
keypad Enter */
! {K_KPOINT, IF_EB("\033O*n", ESC_STR "O*n")}, /*
keypad . */
! {K_KDEL, IF_EB("\033[3;*~", ESC_STR "[3;*~")}, /* keypad Del */
{BT_EXTRA_KEYS, ""},
{TERMCAP2KEY('k', '0'), IF_EB("\033[10;*~", ESC_STR "[10;*~")}, /* F0 */
--- 904,918 ----
{K_ZEND, IF_EB("\033[8;*~", ESC_STR "[8;*~")},
{K_PAGEUP, IF_EB("\033[5;*~", ESC_STR "[5;*~")},
{K_PAGEDOWN, IF_EB("\033[6;*~", ESC_STR "[6;*~")},
! {K_KPLUS, IF_EB("\033O*k", ESC_STR "O*k")}, /* keypad plus */
! {K_KMINUS, IF_EB("\033O*m", ESC_STR "O*m")}, /* keypad
minus */
! {K_KDIVIDE, IF_EB("\033O*o", ESC_STR "O*o")}, /* keypad
/ */
! {K_KMULTIPLY, IF_EB("\033O*j", ESC_STR "O*j")}, /* keypad * */
! {K_KENTER, IF_EB("\033O*M", ESC_STR "O*M")}, /* keypad
Enter */
! {K_KPOINT, IF_EB("\033O*n", ESC_STR "O*n")}, /* keypad
. */
! {K_KDEL, IF_EB("\033[3;*~", ESC_STR "[3;*~")}, /* keypad Del */
! {K_PS, IF_EB("\033[200~", ESC_STR "[200~")}, /* paste start */
! {K_PE, IF_EB("\033[201~", ESC_STR "[201~")}, /* paste end */
{BT_EXTRA_KEYS, ""},
{TERMCAP2KEY('k', '0'), IF_EB("\033[10;*~", ESC_STR "[10;*~")}, /* F0 */
***************
*** 1224,1229 ****
--- 1228,1235 ----
{K_KMULTIPLY, "[KMULTIPLY]"},
{K_KENTER, "[KENTER]"},
{K_KPOINT, "[KPOINT]"},
+ {K_PS, "[PASTE-START]"},
+ {K_PE, "[PASTE-END]"},
{K_K0, "[K0]"},
{K_K1, "[K1]"},
{K_K2, "[K2]"},
***************
*** 1538,1543 ****
--- 1544,1551 ----
{KS_CSI, "SI"}, {KS_CEI, "EI"},
{KS_U7, "u7"}, {KS_RBG, "RB"},
{KS_8F, "8f"}, {KS_8B, "8b"},
+ {KS_CBE, "BE"}, {KS_CBD, "BD"},
+ {KS_CPS, "PS"}, {KS_CPE, "PE"},
{(enum SpecialKey)0, NULL}
};
***************
*** 3140,3145 ****
--- 3148,3154 ----
{
out_str(T_TI); /* start termcap mode */
out_str(T_KS); /* start "keypad transmit" mode */
+ out_str(T_BE); /* enable bracketed paste moe */
out_flush();
termcap_active = TRUE;
screen_start(); /* don't know where cursor is now */
***************
*** 3189,3194 ****
--- 3198,3204 ----
check_for_codes_from_term();
}
#endif
+ out_str(T_BD); /* disable bracketed paste moe */
out_str(T_KE); /* stop "keypad transmit" mode */
out_flush();
termcap_active = FALSE;
*** ../vim-8.0.0209/src/term.h 2016-08-29 22:42:20.000000000 +0200
--- src/term.h 2017-01-21 16:34:00.936095982 +0100
***************
*** 89,98 ****
KS_OP, /* original color pair */
KS_U7, /* request cursor position */
KS_8F, /* set foreground color (RGB) */
! KS_8B /* set background color (RGB) */
};
! #define KS_LAST KS_8B
/*
* the terminal capabilities are stored in this array
--- 89,102 ----
KS_OP, /* original color pair */
KS_U7, /* request cursor position */
KS_8F, /* set foreground color (RGB) */
! KS_8B, /* set background color (RGB) */
! KS_CBE, /* enable bracketed paste mode */
! KS_CBD, /* disable bracketed paste mode */
! KS_CPS, /* start of brackted paste */
! KS_CPE /* end of brackted paste */
};
! #define KS_LAST KS_CPE
/*
* the terminal capabilities are stored in this array
***************
*** 170,175 ****
--- 174,183 ----
#define T_U7 (term_str(KS_U7)) /* request cursor position */
#define T_8F (term_str(KS_8F)) /* set foreground color (RGB) */
#define T_8B (term_str(KS_8B)) /* set background color (RGB) */
+ #define T_BE (term_str(KS_CBE)) /* enable bracketed paste mode */
+ #define T_BD (term_str(KS_CBD)) /* disable bracketed paste mode */
+ #define T_PS (term_str(KS_CPS)) /* start of bracketed paste */
+ #define T_PE (term_str(KS_CPE)) /* end of bracketed paste */
#define TMODE_COOK 0 /* terminal mode for external cmds and Ex mode */
#define TMODE_SLEEP 1 /* terminal mode for sleeping (cooked but no echo) */
*** ../vim-8.0.0209/src/option.c 2017-01-14 14:28:26.956592328 +0100
--- src/option.c 2017-01-21 15:34:59.567463663 +0100
***************
*** 3040,3045 ****
--- 3040,3047 ----
p_term("t_ZR", T_CZR)
p_term("t_8f", T_8F)
p_term("t_8b", T_8B)
+ p_term("t_BE", T_BE)
+ p_term("t_BD", T_BD)
/* terminal key codes are not in here */
*** ../vim-8.0.0209/src/misc2.c 2017-01-10 13:51:05.587236267 +0100
--- src/misc2.c 2017-01-21 15:43:20.460160465 +0100
***************
*** 2294,2299 ****
--- 2294,2301 ----
{K_XDOWN, (char_u *)"xDown"},
{K_XLEFT, (char_u *)"xLeft"},
{K_XRIGHT, (char_u *)"xRight"},
+ {K_PS, (char_u *)"PasteStart"},
+ {K_PE, (char_u *)"PasteEnd"},
{K_F1, (char_u *)"F1"},
{K_F2, (char_u *)"F2"},
*** ../vim-8.0.0209/src/keymap.h 2016-08-29 22:42:20.000000000 +0200
--- src/keymap.h 2017-01-21 15:45:55.467135851 +0100
***************
*** 391,396 ****
--- 391,398 ----
#define K_KMULTIPLY TERMCAP2KEY('K', '9') /* keypad * */
#define K_KENTER TERMCAP2KEY('K', 'A') /* keypad Enter */
#define K_KPOINT TERMCAP2KEY('K', 'B') /* keypad . or ,*/
+ #define K_PS TERMCAP2KEY('P', 'S') /* paste start */
+ #define K_PE TERMCAP2KEY('P', 'E') /* paste end */
#define K_K0 TERMCAP2KEY('K', 'C') /* keypad 0 */
#define K_K1 TERMCAP2KEY('K', 'D') /* keypad 1 */
*** ../vim-8.0.0209/src/edit.c 2017-01-20 21:51:46.130731009 +0100
--- src/edit.c 2017-01-21 19:22:18.064013812 +0100
***************
*** 309,314 ****
--- 309,315 ----
* "cmdchar" can be:
* 'i' normal insert command
* 'a' normal append command
+ * K_PS bracketed paste
* 'R' replace command
* 'r' "r<CR>" command: insert one <CR>. Note: count can be > 1, for
redo,
* but still only one <CR> is inserted. The <Esc> is not used for redo.
***************
*** 782,791 ****
dont_sync_undo = TRUE;
else
dont_sync_undo = FALSE;
! do
! {
! c = safe_vgetc();
! } while (c == K_IGNORE);
#ifdef FEAT_AUTOCMD
/* Don't want K_CURSORHOLD for the second key, e.g., after CTRL-V. */
--- 783,796 ----
dont_sync_undo = TRUE;
else
dont_sync_undo = FALSE;
! if (cmdchar == K_PS)
! /* Got here from normal mode when bracketed paste started. */
! c = K_PS;
! else
! do
! {
! c = safe_vgetc();
! } while (c == K_IGNORE);
#ifdef FEAT_AUTOCMD
/* Don't want K_CURSORHOLD for the second key, e.g., after CTRL-V. */
***************
*** 1193,1198 ****
--- 1198,1213 ----
ins_mousescroll(MSCR_RIGHT);
break;
#endif
+ case K_PS:
+ bracketed_paste(PASTE_INSERT, FALSE, NULL);
+ if (cmdchar == K_PS)
+ /* invoked from normal mode, bail out */
+ goto doESCkey;
+ break;
+ case K_PE:
+ /* Got K_PE without K_PS, ignore. */
+ break;
+
#ifdef FEAT_GUI_TABLINE
case K_TABLINE:
case K_TABMENU:
***************
*** 9424,9429 ****
--- 9439,9529 ----
}
#endif
+ /*
+ * Handle receiving P_PS: start paste mode. Inserts the following text up to
+ * P_PE literally.
+ * When "drop" is TRUE then consume the text and drop it.
+ */
+ int
+ bracketed_paste(paste_mode_T mode, int drop, garray_T *gap)
+ {
+ int c;
+ char_u buf[NUMBUFLEN + MB_MAXBYTES];
+ int idx = 0;
+ char_u *end = find_termcode((char_u *)"PE");
+ int ret_char = -1;
+ int save_allow_keys = allow_keys;
+
+ /* If the end code is too long we can't detect it, read everything. */
+ if (STRLEN(end) >= NUMBUFLEN)
+ end = NULL;
+ ++no_mapping;
+ allow_keys = 0;
+ for (;;)
+ {
+ /* When the end is not defined read everything. */
+ if (end == NULL && vpeekc() == NUL)
+ break;
+ c = plain_vgetc();
+ #ifdef FEAT_MBYTE
+ if (has_mbyte)
+ idx += (*mb_char2bytes)(c, buf + idx);
+ else
+ #endif
+ buf[idx++] = c;
+ buf[idx] = NUL;
+ if (end != NUL && STRNCMP(buf, end, idx) == 0)
+ {
+ if (end[idx] == NUL)
+ break; /* Found the end of paste code. */
+ continue;
+ }
+ if (!drop)
+ {
+ switch (mode)
+ {
+ case PASTE_CMDLINE:
+ put_on_cmdline(buf, idx, TRUE);
+ break;
+
+ case PASTE_EX:
+ if (gap != NULL && ga_grow(gap, idx) == OK)
+ {
+ mch_memmove((char *)gap->ga_data + gap->ga_len,
+ buf, (size_t)idx);
+ gap->ga_len += idx;
+ }
+ break;
+
+ case PASTE_INSERT:
+ if (stop_arrow() == OK)
+ {
+ ins_char_bytes(buf, idx);
+ AppendToRedobuffLit(buf, idx);
+ }
+ break;
+
+ case PASTE_ONE_CHAR:
+ if (ret_char == -1)
+ {
+ #ifdef FEAT_MBYTE
+ if (has_mbyte)
+ ret_char = (*mb_ptr2char)(buf);
+ else
+ #endif
+ ret_char = buf[0];
+ }
+ break;
+ }
+ }
+ idx = 0;
+ }
+ --no_mapping;
+ allow_keys = save_allow_keys;
+
+ return ret_char;
+ }
+
#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
static void
ins_tabline(int c)
*** ../vim-8.0.0209/src/normal.c 2017-01-20 21:51:46.130731009 +0100
--- src/normal.c 2017-01-21 19:29:47.988909502 +0100
***************
*** 426,431 ****
--- 426,432 ----
#ifdef FEAT_AUTOCMD
{K_CURSORHOLD, nv_cursorhold, NV_KEEPREG, 0},
#endif
+ {K_PS, nv_edit, 0, 0},
};
/* Number of commands in nv_cmds[]. */
***************
*** 3858,3864 ****
K_VER_SCROLLBAR, K_HOR_SCROLLBAR,
K_LEFTMOUSE_NM, K_LEFTRELEASE_NM,
# endif
! K_IGNORE,
K_LEFTMOUSE, K_LEFTDRAG, K_LEFTRELEASE,
K_MIDDLEMOUSE, K_MIDDLEDRAG, K_MIDDLERELEASE,
K_RIGHTMOUSE, K_RIGHTDRAG, K_RIGHTRELEASE,
--- 3859,3865 ----
K_VER_SCROLLBAR, K_HOR_SCROLLBAR,
K_LEFTMOUSE_NM, K_LEFTRELEASE_NM,
# endif
! K_IGNORE, K_PS,
K_LEFTMOUSE, K_LEFTDRAG, K_LEFTRELEASE,
K_MIDDLEMOUSE, K_MIDDLEDRAG, K_MIDDLERELEASE,
K_RIGHTMOUSE, K_RIGHTDRAG, K_RIGHTRELEASE,
***************
*** 9015,9020 ****
--- 9016,9022 ----
/*
* Handle "A", "a", "I", "i" and <Insert> commands.
+ * Also handle K_PS, start bracketed paste.
*/
static void
nv_edit(cmdarg_T *cap)
***************
*** 9042,9047 ****
--- 9044,9052 ----
/* Only give this error when 'insertmode' is off. */
EMSG(_(e_modifiable));
clearop(cap->oap);
+ if (cap->cmdchar == K_PS)
+ /* drop the pasted text */
+ bracketed_paste(PASTE_INSERT, TRUE, NULL);
}
else if (!checkclearopq(cap->oap))
{
***************
*** 9073,9078 ****
--- 9078,9084 ----
break;
case 'a': /* "a"ppend is like "i"nsert on the next character. */
+ case K_PS: /* bracketed paste works like "a"ppend */
#ifdef FEAT_VIRTUALEDIT
/* increment coladd when in virtual space, increment the
* column otherwise, also to append after an unprintable char */
***************
*** 9103,9108 ****
--- 9109,9117 ----
invoke_edit(cap, FALSE, cap->cmdchar, FALSE);
}
+ else if (cap->cmdchar == K_PS)
+ /* drop the pasted text */
+ bracketed_paste(PASTE_INSERT, TRUE, NULL);
}
/*
*** ../vim-8.0.0209/src/evalfunc.c 2017-01-20 19:59:47.983380544 +0100
--- src/evalfunc.c 2017-01-21 19:37:45.749632870 +0100
***************
*** 4231,4237 ****
{
if (argvars[0].v_type == VAR_UNKNOWN)
/* getchar(): blocking wait. */
! n = safe_vgetc();
else if (get_tv_number_chk(&argvars[0], &error) == 1)
/* getchar(1): only check if char avail */
n = vpeekc_any();
--- 4231,4237 ----
{
if (argvars[0].v_type == VAR_UNKNOWN)
/* getchar(): blocking wait. */
! n = plain_vgetc();
else if (get_tv_number_chk(&argvars[0], &error) == 1)
/* getchar(1): only check if char avail */
n = vpeekc_any();
***************
*** 4240,4246 ****
n = 0;
else
/* getchar(0) and char avail: return char */
! n = safe_vgetc();
if (n == K_IGNORE)
continue;
--- 4240,4246 ----
n = 0;
else
/* getchar(0) and char avail: return char */
! n = plain_vgetc();
if (n == K_IGNORE)
continue;
*** ../vim-8.0.0209/src/getchar.c 2017-01-10 13:51:05.583236296 +0100
--- src/getchar.c 2017-01-21 19:36:53.673989329 +0100
***************
*** 1817,1822 ****
--- 1817,1828 ----
{
c = safe_vgetc();
} while (c == K_IGNORE || c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR);
+
+ if (c == K_PS)
+ /* Only handle the first pasted character. Drop the rest, since we
+ * don't know what to do with it. */
+ c = bracketed_paste(PASTE_ONE_CHAR, FALSE, NULL);
+
return c;
}
***************
*** 1906,1912 ****
}
/*
! * get a character:
* 1. from the stuffbuffer
* This is used for abbreviated commands like "D" -> "d$".
* Also used to redo a command for ".".
--- 1912,1918 ----
}
/*
! * Get a character:
* 1. from the stuffbuffer
* This is used for abbreviated commands like "D" -> "d$".
* Also used to redo a command for ".".
*** ../vim-8.0.0209/src/vim.h 2017-01-12 21:44:45.146171805 +0100
--- src/vim.h 2017-01-21 19:05:15.035107243 +0100
***************
*** 2108,2113 ****
--- 2108,2121 ----
ASSERT_OTHER
} assert_type_T;
+ /* Mode for bracketed_paste(). */
+ typedef enum {
+ PASTE_INSERT, /* insert mode */
+ PASTE_CMDLINE, /* command line */
+ PASTE_EX, /* ex mode line */
+ PASTE_ONE_CHAR /* return first character */
+ } paste_mode_T;
+
#include "ex_cmds.h" /* Ex command defines */
#include "spell.h" /* spell checking stuff */
*** ../vim-8.0.0209/src/proto/edit.pro 2016-10-15 17:06:42.090912729 +0200
--- src/proto/edit.pro 2017-01-21 19:03:58.359641105 +0100
***************
*** 38,43 ****
--- 38,44 ----
void fix_indent(void);
int in_cinkeys(int keytyped, int when, int line_is_empty);
int hkmap(int c);
+ int bracketed_paste(paste_mode_T mode, int drop, garray_T *gap);
void ins_scroll(void);
void ins_horscroll(void);
int ins_copychar(linenr_T lnum);
*** ../vim-8.0.0209/runtime/doc/term.txt 2016-09-12 12:45:48.000000000
+0200
--- runtime/doc/term.txt 2017-01-21 19:58:23.397174277 +0100
***************
*** 89,94 ****
--- 89,106 ----
for a moment. This means that you can stop the output to the screen by
hitting a printing key. Output resumes when you hit <BS>.
+ *xterm-bracketed-paste*
+ When the 't_BE' option is set then 't_BE' will be sent to the
+ terminal when entering "raw" mode and 't_BD' when leaving "raw" mode. The
+ terminal is then expected to put 't_PS' before pasted text and 't_PE' after
+ pasted text. This way Vim can separate text that is pasted from characters
+ that are typed. The pasted text is handled like when the middle mouse button
+ is used.
+
+ Note that in some situations Vim will not recognize the bracketed paste and
+ you will get the raw text. In other situations Vim will only get the first
+ pasted character and drop the rest, e.g. when using the "r" command.
+
*cs7-problem*
Note: If the terminal settings are changed after running Vim, you might have
an illegal combination of settings. This has been reported on Solaris 2.5
***************
*** 306,311 ****
--- 318,327 ----
|xterm-true-color|
t_8b set background color (R, G, B) *t_8b* *'t_8b'*
|xterm-true-color|
+ t_BE enable bracketed paste mode *t_BE* *'t_BE'*
+ |xterm-bracketed-paste|
+ t_BD disable bracketed paste mode *t_BD* *'t_BD'*
+ |xterm-bracketed-paste|
KEY CODES
Note: Use the <> form if possible
***************
*** 398,403 ****
--- 414,421 ----
t_KK <k8> keypad 8 *<k8>* *t_KK* *'t_KK'*
t_KL <k9> keypad 9 *<k9>* *t_KL* *'t_KL'*
<Mouse> leader of mouse code *<Mouse>*
+ t_PS start of brackted paste |xterm-bracketed-paste| *t_PS* 't_PS'
+ t_PE end of bracketed paste |xterm-bracketed-paste| *t_PE* 't_PE'
Note about t_so and t_mr: When the termcap entry "so" is not present the
entry for "mr" is used. And vice versa. The same is done for "se" and "me".
*** ../vim-8.0.0209/src/version.c 2017-01-21 14:44:32.531503504 +0100
--- src/version.c 2017-01-21 17:22:39.156736230 +0100
***************
*** 766,767 ****
--- 766,769 ----
{ /* Add new patch number below this line */
+ /**/
+ 210,
/**/
--
FATHER: Make sure the Prince doesn't leave this room until I come and
get him.
FIRST GUARD: Not ... to leave the room ... even if you come and get him.
FATHER: No. Until I come and get him.
SECOND GUARD: Hic.
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.