Last active
July 12, 2017 08:30
-
-
Save ichizok/548dda4bd3839a517c5b0a66d4cbf3e5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/testdir/shared.vim b/src/testdir/shared.vim | |
index e28d162b8..790b07b56 100644 | |
--- a/src/testdir/shared.vim | |
+++ b/src/testdir/shared.vim | |
@@ -111,14 +111,15 @@ endfunc | |
" Wait for up to a second for "expr" to become true. | |
" Return time slept in milliseconds. With the +reltime feature this can be | |
" more than the actual waiting time. Without +reltime it can also be less. | |
-func WaitFor(expr) | |
+func WaitFor(expr, ...) | |
+ let timeout = get(a:000, 0, 1000) | |
" using reltime() is more accurate, but not always available | |
if has('reltime') | |
let start = reltime() | |
else | |
let slept = 0 | |
endif | |
- for i in range(100) | |
+ for i in range(timeout / 10) | |
try | |
if eval(a:expr) | |
if has('reltime') | |
@@ -133,7 +134,7 @@ func WaitFor(expr) | |
endif | |
sleep 10m | |
endfor | |
- return 1000 | |
+ return timeout | |
endfunc | |
" Wait for up to a given milliseconds. | |
diff --git a/src/testdir/test_quotestar.vim b/src/testdir/test_quotestar.vim | |
index b053260be..b7d31583d 100644 | |
--- a/src/testdir/test_quotestar.vim | |
+++ b/src/testdir/test_quotestar.vim | |
@@ -88,6 +88,18 @@ func Do_test_quotestar_for_x11() | |
call WaitFor('@* == "yes"') | |
call assert_equal('yes', @*) | |
+ " Handle the large selection over 262040 byte. | |
+ let length = 262044 | |
+ let sample = 'a' . repeat('b', length - 2) . 'c' | |
+ let @* = sample | |
+ call WaitFor('remote_expr("' . name . '", "len(@*) >= ' . length . '", "", 1)', 3000) | |
+ let res = remote_expr(name, "@*", "", 2) | |
+ call assert_equal(length, len(res)) | |
+ " Check length to prevent a large amount of output at assertion failure. | |
+ if length == len(res) | |
+ call assert_equal(sample, res) | |
+ endif | |
+ | |
if has('unix') && has('gui') && !has('gui_running') | |
let @* = '' | |
diff --git a/src/ui.c b/src/ui.c | |
index 8691ab741..19064b808 100644 | |
--- a/src/ui.c | |
+++ b/src/ui.c | |
@@ -2043,9 +2043,10 @@ x11_setup_atoms(Display *dpy) | |
*/ | |
static Boolean clip_x11_convert_selection_cb(Widget, Atom *, Atom *, Atom *, XtPointer *, long_u *, int *); | |
-static void clip_x11_lose_ownership_cb(Widget, Atom *); | |
+static void clip_x11_lose_ownership_cb(Widget, Atom *); | |
+static void clip_x11_notify_cb(Widget, Atom *, Atom *); | |
static void clip_x11_timestamp_cb(Widget w, XtPointer n, XEvent *event, Boolean *cont); | |
-static void clip_x11_request_selection_cb(Widget, XtPointer, Atom *, Atom *, XtPointer, long_u *, int *); | |
+static void clip_x11_request_selection_cb(Widget, XtPointer, Atom *, Atom *, XtPointer, long_u *, int *); | |
/* | |
* Property callback to get a timestamp for XtOwnSelection. | |
@@ -2085,7 +2086,7 @@ clip_x11_timestamp_cb( | |
/* Get the selection, using the event timestamp. */ | |
if (XtOwnSelection(w, xproperty->atom, xproperty->time, | |
clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb, | |
- NULL) == OK) | |
+ clip_x11_notify_cb) == OK) | |
{ | |
/* Set the "owned" flag now, there may have been a call to | |
* lose_ownership_cb in between. */ | |
@@ -2276,9 +2277,9 @@ clip_x11_request_selection( | |
start_time = time(NULL); | |
while (success == MAYBE) | |
{ | |
- if (XCheckTypedEvent(dpy, SelectionNotify, &event) | |
- || XCheckTypedEvent(dpy, SelectionRequest, &event) | |
- || XCheckTypedEvent(dpy, PropertyNotify, &event)) | |
+ if (XCheckTypedEvent(dpy, PropertyNotify, &event) | |
+ || XCheckTypedEvent(dpy, SelectionNotify, &event) | |
+ || XCheckTypedEvent(dpy, SelectionRequest, &event)) | |
{ | |
/* This is where clip_x11_request_selection_cb() should be | |
* called. It may actually happen a bit later, so we loop | |
@@ -2331,8 +2332,9 @@ clip_x11_convert_selection_cb( | |
long_u *length, | |
int *format) | |
{ | |
+ static char_u *save_result; | |
+ static long_u save_length; | |
char_u *string; | |
- char_u *result; | |
int motion_type; | |
VimClipboard *cbd; | |
int i; | |
@@ -2348,10 +2350,8 @@ clip_x11_convert_selection_cb( | |
/* requestor wants to know what target types we support */ | |
if (*target == targets_atom) | |
{ | |
- Atom *array; | |
+ static Atom array[7]; | |
- if ((array = (Atom *)XtMalloc((unsigned)(sizeof(Atom) * 7))) == NULL) | |
- return False; | |
*value = (XtPointer)array; | |
i = 0; | |
array[i++] = targets_atom; | |
@@ -2400,13 +2400,17 @@ clip_x11_convert_selection_cb( | |
*length += STRLEN(p_enc) + 2; | |
#endif | |
- *value = XtMalloc((Cardinal)*length); | |
- result = (char_u *)*value; | |
- if (result == NULL) | |
+ if (save_length < *length || save_length / 2 >= *length) | |
+ *value = XtRealloc((char *)save_result, (Cardinal)*length + 1); | |
+ else | |
+ *value = save_result; | |
+ if (*value == NULL) | |
{ | |
vim_free(string); | |
return False; | |
} | |
+ save_result = (char_u *)*value; | |
+ save_length = *length; | |
if (*target == XA_STRING | |
#ifdef FEAT_MBYTE | |
@@ -2414,13 +2418,13 @@ clip_x11_convert_selection_cb( | |
#endif | |
) | |
{ | |
- mch_memmove(result, string, (size_t)(*length)); | |
+ mch_memmove(save_result, string, (size_t)(*length)); | |
*type = *target; | |
} | |
else if (*target == compound_text_atom || *target == text_atom) | |
{ | |
XTextProperty text_prop; | |
- char *string_nt = (char *)alloc((unsigned)*length + 1); | |
+ char *string_nt = (char *)save_result; | |
int conv_result; | |
/* create NUL terminated string which XmbTextListToTextProperty wants */ | |
@@ -2428,8 +2432,6 @@ clip_x11_convert_selection_cb( | |
string_nt[*length] = NUL; | |
conv_result = XmbTextListToTextProperty(X_DISPLAY, (char **)&string_nt, | |
1, XCompoundTextStyle, &text_prop); | |
- vim_free(string_nt); | |
- XtFree(*value); /* replace with COMPOUND text */ | |
if (conv_result != Success) | |
{ | |
vim_free(string); | |
@@ -2438,24 +2440,25 @@ clip_x11_convert_selection_cb( | |
*value = (XtPointer)(text_prop.value); /* from plain text */ | |
*length = text_prop.nitems; | |
*type = compound_text_atom; | |
+ XtFree((char *)save_result); | |
+ save_result = (char_u *)*value; | |
+ save_length = *length; | |
} | |
- | |
#ifdef FEAT_MBYTE | |
else if (*target == vimenc_atom) | |
{ | |
int l = STRLEN(p_enc); | |
- result[0] = motion_type; | |
- STRCPY(result + 1, p_enc); | |
- mch_memmove(result + l + 2, string, (size_t)(*length - l - 2)); | |
+ save_result[0] = motion_type; | |
+ STRCPY(save_result + 1, p_enc); | |
+ mch_memmove(save_result + l + 2, string, (size_t)(*length - l - 2)); | |
*type = vimenc_atom; | |
} | |
#endif | |
- | |
else | |
{ | |
- result[0] = motion_type; | |
- mch_memmove(result + 1, string, (size_t)(*length - 1)); | |
+ save_result[0] = motion_type; | |
+ mch_memmove(save_result + 1, string, (size_t)(*length - 1)); | |
*type = vim_atom; | |
} | |
*format = 8; /* 8 bits per char */ | |
@@ -2479,6 +2482,12 @@ clip_x11_lose_selection(Widget myShell, VimClipboard *cbd) | |
XtLastTimestampProcessed(XtDisplay(myShell))); | |
} | |
+ static void | |
+clip_x11_notify_cb(Widget w UNUSED, Atom *sel_atom UNUSED, Atom *target UNUSED) | |
+{ | |
+ /* To prevent automatically freeing the selection value. */ | |
+} | |
+ | |
int | |
clip_x11_own_selection(Widget myShell, VimClipboard *cbd) | |
{ | |
@@ -2492,7 +2501,7 @@ clip_x11_own_selection(Widget myShell, VimClipboard *cbd) | |
if (XtOwnSelection(myShell, cbd->sel_atom, | |
XtLastTimestampProcessed(XtDisplay(myShell)), | |
clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb, | |
- NULL) == False) | |
+ clip_x11_notify_cb) == False) | |
return FAIL; | |
} | |
else |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment