Patch to detect linewise selections from X clipboard

259 views
Skip to first unread message

Sung Pae

unread,
Apr 29, 2011, 7:11:16 PM4/29/11
to vim...@vim.org
Hello,

Currently, when `putting' from the "* and "+ registers, the register is
always pasted as MCHAR if it has been returned from the X clipboard.

However, vim convention implies that any string that ends in a \n or \r
should be expected to be behave like a linewise yank (see MAUTO).

Since it is easy in most GUI programs to explicitly make linewise
selections (typically via triple-click), this small patch marks strings
requested from the X clipboard as MLINE if they end in a NL or CR
character.

This is a very cheap operation.

Cheers,
Sung Pae
---
src/ui.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/src/ui.c b/src/ui.c
index 9d940b1..26688c8 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -2084,6 +2084,7 @@ clip_x11_request_selection_cb(w, success,
sel_atom, type, value, length,
XTextProperty text_prop;
int n_text = 0;
int status;
+ char_u z;

text_prop.value = (unsigned char *)value;
text_prop.encoding = *type;
@@ -2098,6 +2099,11 @@ clip_x11_request_selection_cb(w, success,
sel_atom, type, value, length,
}
p = (char_u *)text_list[0];
len = STRLEN(p);
+
+ /* This may be a linewise selection */
+ z = p[len - 1];
+ if (z == '\n' || z == '\r')
+ motion_type = MLINE;
}
clip_yank_selection(motion_type, p, (long)len, cbd);

--
1.7.5-rc0

0001-External-linewise-selections-from-X-clipboard.patch

Bram Moolenaar

unread,
Apr 30, 2011, 6:35:11 AM4/30/11
to Sung Pae, vim...@vim.org

Sung Pae wrote:

> Currently, when `putting' from the "* and "+ registers, the register is
> always pasted as MCHAR if it has been returned from the X clipboard.
>
> However, vim convention implies that any string that ends in a \n or \r
> should be expected to be behave like a linewise yank (see MAUTO).
>
> Since it is easy in most GUI programs to explicitly make linewise
> selections (typically via triple-click), this small patch marks strings
> requested from the X clipboard as MLINE if they end in a NL or CR
> character.
>
> This is a very cheap operation.

Thanks for the patch.

If I understand it correctly, this is only for when pasting text from
other applications, not from another Vim.

I would appreciate feedback from others, does this work as you would
expect?

--
I wonder how much deeper the ocean would be without sponges.

/// Bram Moolenaar -- Br...@Moolenaar.net -- 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 ///

Gary Johnson

unread,
Apr 30, 2011, 1:37:49 PM4/30/11
to vim...@googlegroups.com
On 2011-04-30, Bram Moolenaar wrote:
> Sung Pae wrote:
>
> > Currently, when `putting' from the "* and "+ registers, the register is
> > always pasted as MCHAR if it has been returned from the X clipboard.
> >
> > However, vim convention implies that any string that ends in a \n or \r
> > should be expected to be behave like a linewise yank (see MAUTO).
> >
> > Since it is easy in most GUI programs to explicitly make linewise
> > selections (typically via triple-click), this small patch marks strings
> > requested from the X clipboard as MLINE if they end in a NL or CR
> > character.
> >
> > This is a very cheap operation.
>
> Thanks for the patch.
>
> If I understand it correctly, this is only for when pasting text from
> other applications, not from another Vim.
>
> I would appreciate feedback from others, does this work as you would
> expect?

Copying and pasting seems to be working fine now. I don't
understand what problem this patch is supposed to fix. If I knew
what to look for, I would apply and test it.

Regards,
Gary

Dominique Pellé

unread,
Apr 30, 2011, 1:51:52 PM4/30/11
to vim...@googlegroups.com
Gary Johnson wrote:


Same for me, I don't fully understand how to reproduce
the problem. I suggest that the bug submitter adds the
steps to reproduce the bug.

-- Dominique

Sung Pae

unread,
Apr 30, 2011, 2:14:12 PM4/30/11
to vim...@googlegroups.com
On Sat, Apr 30, 2011 at 12:37 PM, Gary Johnson <gary...@spocom.com>
wrote:
>
> Copying and pasting seems to be working fine now.  I don't
> understand what problem this patch is supposed to fix.  If I knew

> what to look for, I would apply and test it.

Some clarification then:

On a vim compiled with X and xterm_clipboard, either

* Copy an explicit linewise selection (via triple-click in your browser
let's say) into the X PRIMARY or CLIPBOARD, then paste it into a vim
buffer using "*p or "+p, while in the middle of an existing line.

* Do a linewise yank with "+y. Then either quit vim, or duplicate the
selection with a clipboard manager (e.g. with parcellite, simply
click on the string you just yanked in the pull down menu). Try
pasting the line again with "+p

You should notice that when pasting a linewise selection that has not
originated from vim, or that has been duplicated by another program, it
will be pasted in MCHAR mode (pasted inline) as opposed to MLINE mode
(pasted on next/prev line).

This came to my attention while working on a Mac in my X terminal with
the new `unnamedplus' feature enabled. The Mac X11.app has a feature
that will sync the native clipboard with the X Clipboard, but in the
process, vim's native vimenc_atom format is replaced with the standard
X compound_text format.

Among other things, vimenc_atom stores the motion_type in the first byte
of the "format" member the of Atom struct, so the motion_type of the
original selection was lost. Performing a yyp would annoyingly repaste
the line after the current character, instead of opening a new line.

The vim[enc]_atom format seems to have been explicitly created to handle
this motion_type issue, and it works quite well. Linewise and blockwise
selections from even different vim processes paste perfectly across the
X CLIPBOARD.

This patch would just like address the small issue of pasting linewise
selections that are not in the vim[enc]_atom format, whether they
ultimately originate from vim, or from another program.

Blockwise selections, of course, cannot be distinguished from linewise
selections after the selection is converted into compound_text, but that
seems like a small issue since most applications do not allow blockwise
selections.

Cheers,
Sung Pae

Gary Johnson

unread,
Apr 30, 2011, 4:44:50 PM4/30/11
to vim...@googlegroups.com
On 2011-04-30, Sung Pae wrote:
> On Sat, Apr 30, 2011 at 12:37 PM, Gary Johnson wrote:
> >
> > Copying and pasting seems to be working fine now. �` I don't
> > understand what problem this patch is supposed to fix. �` If I knew

> > what to look for, I would apply and test it.
>
> Some clarification then:

[...]

Thank you for the thorough explanation. I won't be able to apply or
test your patch until Monday or Tuesday, but I'll do so then and let
you know how it works out.

I have a Windows XP machine at my desk and use NoMachine to connect
to a machine in the back room running Fedora 11 and (currently) KDE.
I also have True X-Mouse running on the Windows machine to make the
mouse behavior on Windows more like it is on X. I have 'clipboard'
set to include 'unnamed'. Should I set it to 'unnamedplus' instead?

Regards,
Gary

Sung Pae

unread,
Apr 30, 2011, 5:58:48 PM4/30/11
to vim...@googlegroups.com
On Sat, Apr 30, 2011 at 3:44 PM, Gary Johnson <gary...@spocom.com> wrote:
>
> Thank you for the thorough explanation. I won't be able to apply or
> test your patch until Monday or Tuesday, but I'll do so then and let
> you know how it works out.
>
> I have a Windows XP machine at my desk and use NoMachine to connect
> to a machine in the back room running Fedora 11 and (currently) KDE.
> I also have True X-Mouse running on the Windows machine to make the
> mouse behavior on Windows more like it is on X. I have 'clipboard'
> set to include 'unnamed'. Should I set it to 'unnamedplus' instead?

Setting `clipboard=unnamedplus' doesn't affect the issue, fortunately.
Yanking and pasting in a single vim instance, and between vim processes
works perfectly. The issue only appears when trying to paste text from
the X clipboard that is not in a vim selection format.

If `clipboard=unnamedplus', pressing `p' defaults to pasting from the
"+ register, and `clipboard=unnamed' from the "* register. This allows
easier interaction with the X clipboard, and so one is more likely to
notice this in practice.

On the Mac, setting unnamedplus and enabling the native clipboard sync
is a disaster, because the sync annoyingly overwrites the contents of
the X CLIPBOARD with the same text but in the non-vim format. This is
a bug of the X11 server application on OS X, but it highlights this
particular incompatibility with the X clipboard system.

Cheers,
Sung Pae

Gary Johnson

unread,
May 2, 2011, 1:17:46 PM5/2/11
to vim...@googlegroups.com
On 2011-04-30, Sung Pae wrote:
> On Sat, Apr 30, 2011 at 12:37 PM, Gary Johnson wrote:
> >
> > Copying and pasting seems to be working fine now. �` I don't
> > understand what problem this patch is supposed to fix. �` If I knew

> > what to look for, I would apply and test it.
>
> Some clarification then:
>
> On a vim compiled with X and xterm_clipboard, either
>
> * Copy an explicit linewise selection (via triple-click in your browser
> let's say) into the X PRIMARY or CLIPBOARD, then paste it into a vim
> buffer using "*p or "+p, while in the middle of an existing line.
>
> * Do a linewise yank with "+y. Then either quit vim, or duplicate the
> selection with a clipboard manager (e.g. with parcellite, simply
> click on the string you just yanked in the pull down menu). Try
> pasting the line again with "+p
>
> You should notice that when pasting a linewise selection that has not
> originated from vim, or that has been duplicated by another program, it
> will be pasted in MCHAR mode (pasted inline) as opposed to MLINE mode
> (pasted on next/prev line).

It may well be that there is something I'm not understanding, but
this patch doesn't seem to have any effect. I thought the purpose
of the patch was to make certain line-wise copies paste line-wise.
For me, they still paste character-wise.

I applied the patch to Vim 7.3.154 and built Vim, then ran the
following tests. This was all done on a system running Fedora 11.

Test 1

* Start Firefox (3.5.3).
* Go to vim.sf.net.
* Triple-click the Vim 7.3 release announcement.
* Start vim in a GNOME Terminal:

$ ./vim -N -u NONE

* Put text in vim buffer:

:r !ls -l

* Move the cursor to the middle of a line in the middle of the
screen and type

"*p

* The result is the line copied from Firefox inserted
_in-line_ in that line of ls output.

* Executing "+p yields the same results.

Test 2

* Using that same Vim instance, select three lines of text by
typing

Vjj"+y

* Vim displays "3 lines yanked" in the status line.

* Exit Vim:

:q!

* Start vim as before and again read ls into the buffer.

* Move the cursor to the middle of a line in the middle of the
screen and type

"+p

* As before, the three lines are inserted _in-line_ at the
cursor position.

Here is the output of "./vim --version".

VIM - Vi IMproved 7.3 (2010 Aug 15, compiled May 2 2011 09:37:36)
Included patches: 1-154
Compiled by gary...@host.company.com
Normal version with GTK2 GUI. Features included (+) or not (-):
-arabic +autocmd +balloon_eval +browse +builtin_terms +byte_offset +cindent
+clientserver +clipboard +cmdline_compl +cmdline_hist +cmdline_info +comments
-conceal +cryptv +cscope +cursorbind +cursorshape +dialog_con_gui +diff
+digraphs +dnd -ebcdic -emacs_tags +eval +ex_extra +extra_search -farsi
+file_in_path +find_in_path +float +folding -footer +fork() +gettext
-hangul_input +iconv +insert_expand +jumplist -keymap -langmap +libcall
+linebreak +lispindent +listcmds +localmap -lua +menu +mksession +modify_fname
+mouse +mouseshape -mouse_dec +mouse_gpm -mouse_jsbterm -mouse_netterm
-mouse_sysmouse +mouse_xterm +multi_byte +multi_lang -mzscheme +netbeans_intg
-osfiletype +path_extra -perl +persistent_undo +postscript +printer -profile
-python -python3 +quickfix +reltime -rightleft -ruby +scrollbind +signs
+smartindent -sniff +startuptime +statusline -sun_workshop +syntax +tag_binary
+tag_old_static -tag_any_white -tcl +terminfo +termresponse +textobjects +title
+toolbar +user_commands +vertsplit +virtualedit +visual +visualextra +viminfo
+vreplace +wildignore +wildmenu +windows +writebackup +X11 -xfontset +xim
+xsmp_interact +xterm_clipboard -xterm_save
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
user exrc file: "$HOME/.exrc"
system gvimrc file: "$VIM/gvimrc"
user gvimrc file: "$HOME/.gvimrc"
system menu file: "$VIMRUNTIME/menu.vim"
fall-back for $VIM: "/home/garyjohn/src/vim-hg/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -DFEAT_GUI_GTK -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12 -g -O2 -D_FORTIFY_SOURCE=1
Linking: gcc -L/usr/local/lib -Wl,--as-needed -o vim -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lgdk_pixbuf-2.0 -lpangocairo-1.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lgmodule-2.0 -lglib-2.0 -lSM -lICE -lXpm -lXt -lX11 -lXdmcp -lSM -lICE -lm -ltinfo -lelf -lnsl -lselinux -lacl -lattr -lgpm

Regards,
Gary

Sung Pae

unread,
May 2, 2011, 4:16:00 PM5/2/11
to vim...@googlegroups.com
Hi Gary,

Thank you very much for testing the patch. Here is what I have found:

> Test 1
>
>    *   Start Firefox (3.5.3).
>    *   Go to vim.sf.net.
>    *   Triple-click the Vim 7.3 release announcement.

I can confirm that triple-clicking on a line in Firefox 4 on my Arch
Linux box does not actually make a linewise selection! Specifically, it
seems that you cannot make a selection that ends in \n.

That's kind of unlucky; I didn't notice because I use Chromium as my
main browser. You can tell in most programs when the newline has been
selected by noticing that the highlight extends to the end of the
bounding box, instead of to the edge of the text.

When I submit a modified patch, we could agree to test selections from
xterm, which does allow linewise selections.


> Test 2
>
>    *   Using that same Vim instance, select three lines of text by
>        typing
>
>            Vjj"+y

...

>    *   As before, the three lines are inserted _in-line_ at the
>        cursor position.
>
> Here is the output of "./vim --version".
>

>    VIM - Vi IMproved 7.3 (2010 Aug 15, compiled May  2 2011 09:37:36)
>    Normal version with GTK2 GUI.  Features included (+) or not (-):

At first, I could not reproduce this result, so I reconfigured my
installation to match your flags (I compile my vim with HUGE and
--disable-gui)

After a couple recompiles, I can reproduce your result by compiling with
the NORMAL feature set, so it seems that the section of code I targeted
is subject to some DEFINEs that are only triggered in the HUGE version.

Oddly, only pasting a previous vim selection from "+ after restarting
seems to be broken; pasting from "* correctly pastes linewise, and
otherwise pasting from "+ also seems to work for me. Neither paste
linewise without the patch.

I will delve into this more deeply and try compiling with different
feature levels before re-submitting; I have a good idea about what is
the matter. I hope you will be willing to repeat you tests then!

Cheers,
guns

Gary Johnson

unread,
May 2, 2011, 5:13:32 PM5/2/11
to vim...@googlegroups.com
On 2011-05-02, Sung Pae wrote:
> Hi Gary,
>
> Thank you very much for testing the patch. Here is what I have found:

[...]

> I will delve into this more deeply and try compiling with different
> feature levels before re-submitting; I have a good idea about what is
> the matter. I hope you will be willing to repeat you tests then!

Sung Pae,

You're very welcome. I'm glad I was able to help. Thank you for
the patch. I'm certainly willing to test it again.

I finally have an environment that allows me to reliably copy and
paste between applications without always having to use the stupid
mouse, and I've been using that capability a lot recently. Copying
and pasting is so much better than it used to be for me that I've
probably encountered the idiosyncrasies your patch fixes and just
shrugged them off.

Regards,
Gary

Sung Pae

unread,
May 3, 2011, 3:59:38 AM5/3/11
to vim...@googlegroups.com
Upon closer inspection, I have the following observations about vim's
handling of foreign selections.


When pasting from the "* or "+ register, vim requests a selection
from the system clipboard. If the selection is not in a vim
selection format:

- The mac, macosx, msdos, mswin, and qnx ports detect the presence
of a NL or CR (whatever is appropriate) _anywhere_ in the text and
switch the motion_type to MLINE

- The riscos, gtk-x11, and x11 ports always set motion_type to MCHAR

- In X, if the selection request fails, CUT_BUFFER0 is used, and is
also always set to MCHAR

As you can see, vim's behavior wrt pasting foreign text is inconsistent.
Most of the non-X ports linewise paste multi-line selections, while the
X-based vims do not.

While the X behavior is not a bug (it is actually explicitly
documented), I believe it is surprising in this instance.

When I copy a large multi-line selection in an application in order to
transfer it into a vim buffer, I don't usually intend on engaging in a
delicate mid-line paste operation. The major non-X GUI ports evidently
share this view.


There a couple of other instances to consider in which vim yanks from
foreign sources:

- When dragging text into gvim (gtk-x11), the selection is always
yanked as MCHAR

- Modeless selections are always yanked as MCHAR

With drag and drop, pasting character-wise is justifiable because there
is typically not much context switching involved: there are no separate
yank and paste operations, the two applications are likely to be side
by side, and flashy GUIs often show a live preview of the text as it is
dragged about. It would be more surprising to open a new line for the
paste than to paste it exactly at the cursor.

With modeless selections, it is logical to simply yank as MCHAR since
one of their primary purposes is to transfer text to the command line.


Summary of the following patch:

* Risc OS, Gtk-X11, and X11:

Call vim_strchr(buf, '\n') on the selection buffer to switch
multi-line strings to MLINE mode before yanking into "* or "+

* Documentation:

Update relevant sections regarding pasting multi-line strings from
foreign applications


Gary, would you mind running your tests again with this patch? Yanking
multi-line selections from Firefox should be just fine, since it no
longer just looks at the last character to determine the motion type.

Cheers,
Sung Pae

---
runtime/doc/gui.txt | 7 ++++---
runtime/doc/gui_x11.txt | 5 +++--
src/gui_gtk_x11.c | 4 ++++
src/gui_riscos.c | 6 +++++-
src/ui.c | 12 ++++++++++--
5 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt
index 213f455..74c3cfc 100644
--- a/runtime/doc/gui.txt
+++ b/runtime/doc/gui.txt
@@ -439,9 +439,10 @@ When using this register under X11, also see
|x11-selection|. This also
explains the related "+ register.

Note that when pasting text from one Vim into another separate Vim, the type
-of selection (character, line, or block) will also be copied. For other
-applications the type is always character. However, if the text gets
-transferred via the |x11-cut-buffer|, the selection type is ALWAYS lost.
+of selection (character, line, or block) will also be copied. When pasting
+from other applications the type is character, unless the the selection
+consists of multiple lines, in which case the type is line. This also applies
+to text transferred via the |x11-cut-buffer|.

When the "unnamed" string is included in the 'clipboard' option, the unnamed
register is the same as the "* register. Thus you can yank to and paste the
diff --git a/runtime/doc/gui_x11.txt b/runtime/doc/gui_x11.txt
index 6d16500..ad434b6 100644
--- a/runtime/doc/gui_x11.txt
+++ b/runtime/doc/gui_x11.txt
@@ -566,8 +566,9 @@ requested X selection is empty or unavailable, Vim
reverts to reading the
current value of the CUT_BUFFER0.

Note that when text is copied to CUT_BUFFER0 in this way, the type of
-selection (character, line or block) is always lost, even if it is a Vim which
-later pastes it.
+selection (character, line or block) is always lost. However, when pasting
+from CUT_BUFFER0, the selection will be pasted as line if the text consists
+of multiple lines, and as character otherwise.

Xterm, by default, always writes visible selections to both PRIMARY and
CUT_BUFFER0. When it pastes, it uses PRIMARY if this is available, or else
diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c
index 0454afb..a527945 100644
--- a/src/gui_gtk_x11.c
+++ b/src/gui_gtk_x11.c
@@ -1258,6 +1258,10 @@ selection_received_cb(GtkWidget *widget UNUSED,
if (tmpbuf != NULL)
text = tmpbuf;
}
+
+ /* Switch multiline strings to MLINE */
+ if (vim_strchr(text, '\n') != NULL)
+ motion_type = MLINE;
}

/* Chop off any traiing NUL bytes. OpenOffice sends these. */
diff --git a/src/gui_riscos.c b/src/gui_riscos.c
index 90634fa..cbce7da 100644
--- a/src/gui_riscos.c
+++ b/src/gui_riscos.c
@@ -2649,6 +2649,7 @@ clip_mch_request_selection(VimClipboard *cbd)
int reason;
char_u *buffer;
long_u length;
+ int motion_type;

block[0] = 48; /* Size of block. */
block[3] = 0; /* Orinial message. */
@@ -2715,7 +2716,10 @@ clip_mch_request_selection(VimClipboard *cbd)
if (xswi(OS_File, 16, "<Wimp$Scrap>", buffer, 0) & v_flag)
return;

- clip_yank_selection(MCHAR, buffer, length, cbd);
+ /* Determine appropriate motion type */
+ motion_type = (vim_strchr(buffer, '\n') == NULL) ? MCHAR : MLINE;
+
+ clip_yank_selection(motion_type, buffer, length, cbd);

vim_free(buffer);

diff --git a/src/ui.c b/src/ui.c
index 9d940b1..67b27ee 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -2098,6 +2098,10 @@ clip_x11_request_selection_cb(w, success,


sel_atom, type, value, length,
}
p = (char_u *)text_list[0];
len = STRLEN(p);
+

+ /* Switch multiline strings to MLINE */
+ if (vim_strchr(p, '\n') != NULL)


+ motion_type = MLINE;
}
clip_yank_selection(motion_type, p, (long)len, cbd);

@@ -2401,6 +2405,10 @@ yank_cut_buffer0(dpy, cbd)
{
int nbytes = 0;
char_u *buffer = (char_u *)XFetchBuffer(dpy, &nbytes, 0);
+ int motion_type;
+
+ /* Determine appropriate motion type */
+ motion_type = (vim_strchr(buffer, '\n') == NULL) ? MCHAR : MLINE;

if (nbytes > 0)
{
@@ -2422,7 +2430,7 @@ yank_cut_buffer0(dpy, cbd)
conv_buf = string_convert(&vc, buffer, &nbytes);
if (conv_buf != NULL)
{
- clip_yank_selection(MCHAR, conv_buf, (long)nbytes, cbd);
+ clip_yank_selection(motion_type, conv_buf, (long)nbytes, cbd);
vim_free(conv_buf);
done = TRUE;
}
@@ -2431,7 +2439,7 @@ yank_cut_buffer0(dpy, cbd)
}
if (!done) /* use the text without conversion */
#endif
- clip_yank_selection(MCHAR, buffer, (long)nbytes, cbd);
+ clip_yank_selection(motion_type, buffer, (long)nbytes, cbd);
XFree((void *)buffer);
if (p_verbose > 0)
{
--
1.7.5-rc0

0001-Linewise-pasting-of-multi-line-selections-in-X-and-R.patch

Tony Mechelynck

unread,
May 3, 2011, 4:42:45 AM5/3/11
to vim...@googlegroups.com, Sung Pae
> if (xswi(OS_File, 16, "<Wimp$Scrap>", buffer, 0)& v_flag)

> return;
>
> - clip_yank_selection(MCHAR, buffer, length, cbd);
> + /* Determine appropriate motion type */
> + motion_type = (vim_strchr(buffer, '\n') == NULL) ? MCHAR : MLINE;
> +
> + clip_yank_selection(motion_type, buffer, length, cbd);
>
> vim_free(buffer);
>
> diff --git a/src/ui.c b/src/ui.c
> index 9d940b1..67b27ee 100644
> --- a/src/ui.c
> +++ b/src/ui.c
> @@ -2098,6 +2098,10 @@ clip_x11_request_selection_cb(w, success,
> sel_atom, type, value, length,
> }
> p = (char_u *)text_list[0];
> len = STRLEN(p);
> +
> + /* Switch multiline strings to MLINE */
> + if (vim_strchr(p, '\n') != NULL)
> + motion_type = MLINE;
> }
> clip_yank_selection(motion_type, p, (long)len, cbd);
>
> @@ -2401,6 +2405,10 @@ yank_cut_buffer0(dpy, cbd)
> {
> int nbytes = 0;
> char_u *buffer = (char_u *)XFetchBuffer(dpy,&nbytes, 0);

> + int motion_type;
> +
> + /* Determine appropriate motion type */
> + motion_type = (vim_strchr(buffer, '\n') == NULL) ? MCHAR : MLINE;
>
> if (nbytes> 0)
> {
> @@ -2422,7 +2430,7 @@ yank_cut_buffer0(dpy, cbd)
> conv_buf = string_convert(&vc, buffer,&nbytes);
> if (conv_buf != NULL)
> {
> - clip_yank_selection(MCHAR, conv_buf, (long)nbytes, cbd);
> + clip_yank_selection(motion_type, conv_buf, (long)nbytes, cbd);
> vim_free(conv_buf);
> done = TRUE;
> }
> @@ -2431,7 +2439,7 @@ yank_cut_buffer0(dpy, cbd)
> }
> if (!done) /* use the text without conversion */
> #endif
> - clip_yank_selection(MCHAR, buffer, (long)nbytes, cbd);
> + clip_yank_selection(motion_type, buffer, (long)nbytes, cbd);
> XFree((void *)buffer);
> if (p_verbose> 0)
> {
>
>
> 0001-Linewise-pasting-of-multi-line-selections-in-X-and-R.patch
>
>
> From 76797820cfb212c3f185efcee2189eed4240ac5a Mon Sep 17 00:00:00 2001
> From: guns<se...@sungpae.com>
> Date: Tue, 3 May 2011 01:51:08 -0500
> Subject: [PATCH] Linewise pasting of multi-line selections in X and Risc OS

>
> Upon closer inspection, I have the following observations about vim's
> handling of foreign selections.
>
> When pasting from the "* or "+ register, vim requests a selection
> from the system clipboard. If the selection is not in a vim
> selection format:
>
> - The mac, macosx, msdos, mswin, and qnx ports detect the presence
> of a NL or CR (whatever is appropriate) _anywhere_ in the text and
> switch the motion_type to MLINE
>
> - The riscos, gtk-x11, and x11 ports always set motion_type to MCHAR
>
> - In X, if the selection request fails, CUT_BUFFER0 is used, and is
> also always set to MCHAR
>
> As you can see, vim's behavior wrt pasting foreign text is a little

> inconsistent. Most of the non-X ports linewise paste multi-line
> selections, while the X-based vims do not.
>
> While the X behavior is not a bug (it is actually explicitly
> documented), I believe it is surprising in this instance.
>
> When I copy a large multi-line selection in an application in order to
> transfer it into a vim buffer, I don't usually intend on engaging in a
> delicate mid-line paste operation. The major non-X GUI ports share this
> view, and scan the text for the presence of an EOL character.
>
> I should mention that scanning the selection buffer for an EOL could
> be costly if the user tries to paste a single, very long line from the
> X clipboard (minified javascript comes to mind). It would be nice in
> this instance to be able to use a reverse strchr (strrchr) on the likely
> chance that the line ends in a newline.

Well, what if I yank (in Firefox, say, or in Thunderbird) a multiline
sentence from the middle of a paragraph? As in the example below, I
mean? With this newfangled system, I won't be able to insert it in the
middle of a different paragraph in Vim, except by calling setreg('+',
'', 'ac') to force it to characterwise.

Example (using [ and ] to show the ends of the visual selection)

Nemo enim ipsam voluptatem, quia voluptas sit, aspernatur aut odit aut
fugit, sed quia consequuntur magni dolores eos, qui ratione voluptatem
sequi nesciunt, neque porro quisquam est, qui do[lorem ipsum, quia
dolor sit amet, consectetur, adipisci velit, sed quia non numquam ejus
modi tempora incidunt, ut labore et dolore magnam aliquam quaerat
voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem
ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi
consequa]tur? Quis autem vel eum jure reprehenderit, qui in ea voluptate
velit esse, quam nihil molestiae consequatur, vel illum, qui dolorem
eum fugiat, quo voluptas nulla pariatur?


Best regards,
Tony.
--
Deliberation, n.:
The act of examining one's bread to determine which side it is
buttered on.
-- Ambrose Bierce, "The Devil's Dictionary"

Ben Schmidt

unread,
May 3, 2011, 4:58:38 AM5/3/11
to vim...@googlegroups.com, Tony Mechelynck, Sung Pae
> Well, what if I yank (in Firefox, say, or in Thunderbird) a multiline sentence
> from the middle of a paragraph? As in the example below, I mean? With this
> newfangled system, I won't be able to insert it in the middle of a different
> paragraph in Vim, except by calling setreg('+', '', 'ac') to force it to
> characterwise.

That is the thing I find frustrating, too. I find it easier to whack my cursor at
the beginning of a line or open a new line than split a line, paste linewise, then
join lines again.

Someone did note a workaround for this, though: going into insert mode and using
Ctrl-R + to paste. This perhaps allows the best of both worlds (once the people
who, like me, prefer characterwise clipboard pasting, put together some mappings
to do it that way).

Cheers,

Ben.

P.S. Tony, I think you just won the award for the worst quote trimming ever. ;-)

guns

unread,
May 3, 2011, 5:35:01 AM5/3/11
to vim_dev
On May 3, 3:42 am, Tony Mechelynck <antoine.mechely...@gmail.com>
wrote:
>
> Well, what if I yank (in Firefox, say, or in Thunderbird) a multiline
> sentence from the middle of a paragraph? As in the example below, I
> mean? With this newfangled system, I won't be able to insert it in the
> middle of a different paragraph in Vim, except by calling setreg('+',
> '', 'ac') to force it to characterwise.


One consolation is that browsers typically display <p> sections as
a single unbroken line. If your example was from the Wikipedia page on
Lorem Ipsum, for example, your selection would paste characterwise as
before.

With regards to email in your mail client, I suspect that most people
receive email that is not politely hard-wrapped at 72 characters, and
possibly the response therein is even top-posted for convenience. If
this does not describe your mail, then I am quite jealous.

Also, the fact that i_Ctrl-r always pastes characterwise is a very
nice
workaround (thank you Ben Schmidt - I think I will set up those
mappings
right now); you would have to explicitly type "*p or "+p to paste from
the X clipboard anyhow (unless clipboard=unnamed or unnamedplus).

Cheers,
Sung Pae

Sung Pae

unread,
May 3, 2011, 6:18:49 AM5/3/11
to vim...@googlegroups.com
On Tue, May 3, 2011 at 3:58 AM, Ben Schmidt:

> This perhaps allows the best of both worlds (once the people who, like
> me, prefer characterwise clipboard pasting, put together some mappings
> to do it that way).

I'd like to mention that there is another way to resolve this issue:

Instead of scanning the whole selection buffer for an EOL character, you
could simply allow clip_yank_selection() to take MAUTO as a valid motion
type and then have it switch between MCHAR/MLINE depending on the value
of the LAST character only.

Currently this strategy is only being employed for setting registers
via `let @r = "foo\nbar\n"'. It would be simple to add the MAUTO
functionality to clip_yank_selection(), and then change all the
strchr(buf, '\n') calls in the OS ports to simply marking strings from
the clipboard as MAUTO.

I prefer this solution myself, since it allows very granular control of
the selection's motion type, but I surmised that it would be rejected
because it would change the behavior of all the OS versions, instead of
just one.

Also, this control is annoyingly incompatible with Firefox since it does
not seem to allow you to select a terminating newline.

Cheers,
Sung Pae

Gary Johnson

unread,
May 4, 2011, 1:11:42 PM5/4/11
to vim...@googlegroups.com
On 2011-05-03, Sung Pae wrote:

> Gary, would you mind running your tests again with this patch? Yanking
> multi-line selections from Firefox should be just fine, since it no
> longer just looks at the last character to determine the motion type.

Sung Pae,

Thanks for the new patch. I reverted your previous patch and
applied this one.

Test 1a

* Start vim as "vim -N -u NONE". (I replaced the previous
version of vim in my PATH with this patched version.)
* Read some text into vim with ":r !ls -l".
* Triple-click on the Vim 7.3 release notice from vim.sf.net
("[2010-08-15] Finally, ... Moolenaar)")
* Paste into the middle of a line in the middle of the vim
screen with

"*p

* The text is pasted character-wise, that is, is inserted in
the middle of the line with no newlines.

This is the same behavior as before, but may be because Firefox
may not put a newline in the copied text.

Test 1b

* Set up vim as before.
* On the vim.sf.net page, select the text from "Vim charity
update" through the end of the Vim 7.3 release notice by
left-clicking and dragging the mouse over it.
* Paste into the middle of a line in the middle of the vim
screen with

"*p

* This time the text is pasted line-wise below the cursor.

I didn't test this case with the previous patch. An unpatched
vim pastes this character-wise.

Test 2

* Set up vim as before.
* Move the cursor to the middle of some line below the top of
the screen and copy three lines with

Vjj"+y

* Exit vim, then restart and set up as before.


* Move the cursor to the middle of a line in the middle of the

screen and paste with

"+p

* The text is pasted line-wise below the cursor. (It was
pasted character-wise with the previous patch.)

This one is weird. From this experiment, the patch appears to
work correctly. The first time I tried it, though, it pasted
character-wise. I've been repeating this one a number of times
and sometimes it pastes line-wise and sometimes it pastes
character-wise. I've been copying lines randomly and pasting
them in random positions, but I _think_ I've done all the other
steps the same way. I haven't found a pattern yet.

I replied to your message of May 2, but I never received a copy from
the list. I haven't checked the web interface to see if it wasn't
received by the list or whether I just didn't receive my copy.

Regards,
Gary

Bram Moolenaar

unread,
May 5, 2011, 8:25:12 AM5/5/11
to Sung Pae, vim...@googlegroups.com

Sung Pae wrote:

> Upon closer inspection, I have the following observations about vim's
> handling of foreign selections.
>
>
> When pasting from the "* or "+ register, vim requests a selection
> from the system clipboard. If the selection is not in a vim
> selection format:
>
> - The mac, macosx, msdos, mswin, and qnx ports detect the presence
> of a NL or CR (whatever is appropriate) _anywhere_ in the text and
> switch the motion_type to MLINE
>
> - The riscos, gtk-x11, and x11 ports always set motion_type to MCHAR
>
> - In X, if the selection request fails, CUT_BUFFER0 is used, and is
> also always set to MCHAR
>
> As you can see, vim's behavior wrt pasting foreign text is inconsistent.
> Most of the non-X ports linewise paste multi-line selections, while the
> X-based vims do not.
>
> While the X behavior is not a bug (it is actually explicitly
> documented), I believe it is surprising in this instance.
>
> When I copy a large multi-line selection in an application in order to
> transfer it into a vim buffer, I don't usually intend on engaging in a
> delicate mid-line paste operation. The major non-X GUI ports evidently
> share this view.

We need to think of various things the user wants to do and how he can
make it work. I think it's not unusual to copy a few lines, starting
halfway a line and ending halfway a line. E.g., a sentence that is
split over multiple lines. And then the user would like to paste it
somewhere inside an existing line. If we would make the selection
linewise, the user would first have to break the line, paste the text
linewise, then join the lines back together. This is possible, but a
bit clumsy.

I would rather use the linewise selection only when the text ends in a
line break. I think in most situations the user can select the text
either with or without a terminating NL. At least in xterm you can.

If I understand the other remarks correctly, there are situations where
it's not possible to get a terminating NL. That means the selection
won't become linewise, thus we get the current behavior. That's not too
bad. Depending on where the text is pasted, the user would have to
insert a line break before and/or after the pasted text. The cursor
should be at the end, thus if the user pastes in front of a line it's a
matter of inserting a line break there.

To make it consistent, we would also have to change the operating
systems that currently find a NL or CR anywhere in the selection.
I wonder if anybody would have a problem with that.


--
Never go to the toilet in a paperless office.

Tony Mechelynck

unread,
May 5, 2011, 2:50:19 PM5/5/11
to Ben Schmidt, vim...@googlegroups.com
On 03/05/11 10:58, Ben Schmidt wrote:
[...]

> P.S. Tony, I think you just won the award for the worst quote trimming
> ever. ;-)

Maybe I did, at that. I try to trim unneeded quoted text, but when in
doubt, I prefer to trim too little than too much -- time and again I've
seen people quoting posts of mine (with trimming) and saying I didn't
make sense, while the critical sentence or URL needed to have it make
sense was in the part they had trimmed.

Best regards,
Tony.
--
This is an unauthorized cybernetic announcement.

Tony Mechelynck

unread,
May 5, 2011, 3:30:31 PM5/5/11
to vim...@googlegroups.com, guns
On 03/05/11 11:35, guns wrote:
[...]

> With regards to email in your mail client, I suspect that most people
> receive email that is not politely hard-wrapped at 72 characters, and
> possibly the response therein is even top-posted for convenience. If
> this does not describe your mail, then I am quite jealous.
[...]

How email messages look when I receive them depends in part on the
sender's email client's settings: for instance, I got your message
hard-wrapped as above, with a huge lot of empty space on the right. My
own messages appear wrapped at 72 columns or something when I send them,
but they are rewrapped to my mail client's message pane width when I get
them back; only the first time however, not when quoted, even when I do
the quoting. This may be due to "format=flowed" in my outgoing
Content-Type headers. I think there must be a preference about that
somewhere but I'm not sure where.

I've seen argued back and forth whether the use of format=flowed is "the
only polite thing to do" or "the worst impolite thing to do", usually
with partisans of either opinion heatedly defending their own standpoint
and never letting themselves be convinced, so let's not start one more
flame war.


About top-posting, my email client (Mozilla SeaMonkey) has settings for
that, and I even know where they are (what follows is best seen in a
fixed font):

Edit → Mail & Newsgroup Account Settings → <account name> → Composition
& Addressing

___Composition_____________________________________________________
[ ] Compose mail in HTML format
[x] Automatically quote the original message when replying
Then, [ start my reply below the quote |v]
| start my reply above the quote |
| select the quote |
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
but even when I use the Google Groups web interface (where replies are
top-posted by default), hitting Ctrl-End to move the cursor to the
bottom of the textbox is not a great hassle.


Best regards,
Tony.
--
"If God lived on Earth, people would knock out all His windows."
-- Yiddish saying

Sung Pae

unread,
May 5, 2011, 3:31:03 PM5/5/11
to Bram Moolenaar, vim...@googlegroups.com
On Thu, May 5, 2011 at 7:25 AM, Bram Moolenaar <Br...@moolenaar.net> wrote:
>
> I would rather use the linewise selection only when the text ends in a
> line break. I think in most situations the user can select the text
> either with or without a terminating NL. At least in xterm you can.

I'm happy to hear that! I have a branch containing just this patch;
it involves allowing str_to_reg() to accept MAUTO as a motion type,
where it switches on the value of the last character. Then, you can
replace all the duplicate strchr(buf, '\n') calls in the ports with
simply passing MAUTO to clip_yank_selection, which calls str_to_reg in
turn.

I've been trying to reproduce the previously posted test results before
replying back to the thread (thanks again for the testing Gary); I think
now I'll go back and clean up this other patch and submit that instead.

Cheers,
Sung Pae

Reply all
Reply to author
Forward
0 new messages