patch 9.1.1634: Clipboard code can be improved

Problem:  Clipboard code can be improved
Solution: Slightly refactor code (Foxe Chen).

This commit does the following:
-  Use garray_T when receiving data instead of manually reallocing
-  formatting fixes
-  skip Wayland test that requires clientserver if x11 not compiled
-  Make some functions static

closes: #17999

Signed-off-by: Foxe Chen <chen.foxe@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Foxe Chen
2025-08-14 22:08:17 +02:00
committed by Christian Brabandt
parent ade0815856
commit 126bc4690f
4 changed files with 51 additions and 51 deletions

View File

@ -47,8 +47,12 @@ static const char *supported_mimes[] = {
static void clip_wl_receive_data(Clipboard_T *cbd, static void clip_wl_receive_data(Clipboard_T *cbd,
const char *mime_type, int fd); const char *mime_type, int fd);
static void clip_wl_request_selection(Clipboard_T *cbd);
static void clip_wl_send_data(const char *mime_type, int fd, static void clip_wl_send_data(const char *mime_type, int fd,
wayland_selection_T); wayland_selection_T);
static int clip_wl_own_selection(Clipboard_T *cbd);
static void clip_wl_lose_selection(Clipboard_T *cbd);
static void clip_wl_set_selection(Clipboard_T *cbd);
static void clip_wl_selection_cancelled(wayland_selection_T selection); static void clip_wl_selection_cancelled(wayland_selection_T selection);
#if defined(USE_SYSTEM) && defined(PROTO) #if defined(USE_SYSTEM) && defined(PROTO)
@ -2336,11 +2340,10 @@ adjust_clip_reg(int *rp)
static void static void
clip_wl_receive_data(Clipboard_T *cbd, const char *mime_type, int fd) clip_wl_receive_data(Clipboard_T *cbd, const char *mime_type, int fd)
{ {
char_u *start, *buf, *tmp, *final, *enc; char_u *start, *final, *enc;
int motion_type = MAUTO; garray_T buf;
ssize_t r = 0; int motion_type = MAUTO;
size_t total = 0, max_total = 4096; // Initial buffer size, 4096 ssize_t r = 0;
// bytes seems reasonable.
#ifndef HAVE_SELECT #ifndef HAVE_SELECT
struct pollfd pfd struct pollfd pfd
@ -2358,9 +2361,13 @@ clip_wl_receive_data(Clipboard_T *cbd, const char *mime_type, int fd)
if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) == -1) if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) == -1)
return; return;
if ((buf = alloc_clear(max_total)) == NULL) ga_init2(&buf, 1, 4096);
// 4096 bytes seems reasonable for initial buffer size
if (ga_grow(&buf, 4096) == FAIL)
return; return;
start = buf;
start = buf.ga_data;
// Only poll before reading when we first start, then we do non-blocking // Only poll before reading when we first start, then we do non-blocking
// reads and check for EAGAIN or EINTR to signal to poll again. // reads and check for EAGAIN or EINTR to signal to poll again.
@ -2368,7 +2375,7 @@ clip_wl_receive_data(Clipboard_T *cbd, const char *mime_type, int fd)
while (errno = 0, TRUE) while (errno = 0, TRUE)
{ {
r = read(fd, start, max_total - 1 - total); r = read(fd, start, buf.ga_maxlen - 1 - buf.ga_len);
if (r == 0) if (r == 0)
break; break;
@ -2391,44 +2398,39 @@ poll_data:
} }
start += r; start += r;
total += (size_t)r; buf.ga_len += r;
// Realloc if we are at the end of the buffer // Realloc if we are at the end of the buffer
if (total >= max_total - 1) if (buf.ga_len >= buf.ga_maxlen - 1)
{ {
tmp = vim_realloc(buf, max_total * 2); if (ga_grow(&buf, 8192) == FAIL)
if (tmp == NULL)
break; break;
max_total *= 2; // Double buffer size each time start = buf.ga_data + buf.ga_len;
buf = tmp;
start = buf + total;
// Zero out the newly allocated memory part
vim_memset(buf + total, 0, max_total - total);
} }
} }
if (total == 0) if (buf.ga_len == 0)
{ {
clip_free_selection(cbd); // Nothing received, clear register clip_free_selection(cbd); // Nothing received, clear register
vim_free(buf); ga_clear(&buf);
return; return;
} }
final = buf; final = buf.ga_data;
if (STRCMP(mime_type, VIM_ATOM_NAME) == 0 && total >= 2) if (STRCMP(mime_type, VIM_ATOM_NAME) == 0 && buf.ga_len >= 2)
{ {
motion_type = *final++;; motion_type = *final++;;
total--; buf.ga_len--;
} }
else if (STRCMP(mime_type, VIMENC_ATOM_NAME) == 0 && total >= 3) else if (STRCMP(mime_type, VIMENC_ATOM_NAME) == 0 && buf.ga_len >= 3)
{ {
vimconv_T conv; vimconv_T conv;
int convlen; int convlen;
// first byte is motion type // first byte is motion type
motion_type = *final++; motion_type = *final++;
total--; buf.ga_len--;
// Get encoding of selection // Get encoding of selection
enc = final; enc = final;
@ -2437,30 +2439,32 @@ poll_data:
final += STRLEN(final) + 1; final += STRLEN(final) + 1;
// Subtract pointers to get length of encoding; // Subtract pointers to get length of encoding;
total -= final - enc; buf.ga_len -= final - enc;
conv.vc_type = CONV_NONE; conv.vc_type = CONV_NONE;
convert_setup(&conv, enc, p_enc); convert_setup(&conv, enc, p_enc);
if (conv.vc_type != CONV_NONE) if (conv.vc_type != CONV_NONE)
{ {
convlen = total; char_u *tmp;
convlen = buf.ga_len;
tmp = string_convert(&conv, final, &convlen); tmp = string_convert(&conv, final, &convlen);
total = convlen; buf.ga_len = convlen;
if (tmp != NULL) if (tmp != NULL)
final = tmp; final = tmp;
convert_setup(&conv, NULL, NULL); convert_setup(&conv, NULL, NULL);
} }
} }
clip_yank_selection(motion_type, final, (long)total, cbd); clip_yank_selection(motion_type, final, (long)buf.ga_len, cbd);
vim_free(buf); ga_clear(&buf);
} }
/* /*
* Get the current selection and fill the respective register for cbd with the * Get the current selection and fill the respective register for cbd with the
* data. * data.
*/ */
void static void
clip_wl_request_selection(Clipboard_T *cbd) clip_wl_request_selection(Clipboard_T *cbd)
{ {
wayland_selection_T selection; wayland_selection_T selection;
@ -2646,7 +2650,7 @@ clip_wl_selection_cancelled(wayland_selection_T selection)
* other Wayland clients so they can receive data from us. Returns OK on success * other Wayland clients so they can receive data from us. Returns OK on success
* and FAIL on failure. * and FAIL on failure.
*/ */
int static int
clip_wl_own_selection(Clipboard_T *cbd) clip_wl_own_selection(Clipboard_T *cbd)
{ {
wayland_selection_T selection; wayland_selection_T selection;
@ -2670,7 +2674,7 @@ clip_wl_own_selection(Clipboard_T *cbd)
* Disown the selection that cbd corresponds to. Note that the the cancelled * Disown the selection that cbd corresponds to. Note that the the cancelled
* event is not sent when the data source is destroyed. * event is not sent when the data source is destroyed.
*/ */
void static void
clip_wl_lose_selection(Clipboard_T *cbd) clip_wl_lose_selection(Clipboard_T *cbd)
{ {
if (cbd == &clip_plus) if (cbd == &clip_plus)
@ -2685,7 +2689,7 @@ clip_wl_lose_selection(Clipboard_T *cbd)
* Send the current selection to the clipboard. Do nothing for Wayland because * Send the current selection to the clipboard. Do nothing for Wayland because
* we will fill in the selection only when requested by another client. * we will fill in the selection only when requested by another client.
*/ */
void static void
clip_wl_set_selection(Clipboard_T *cbd UNUSED) clip_wl_set_selection(Clipboard_T *cbd UNUSED)
{ {
} }

View File

@ -35,10 +35,6 @@ int clip_convert_selection(char_u **str, long_u *len, Clipboard_T *cbd);
int may_get_selection(int regname); int may_get_selection(int regname);
void may_set_selection(void); void may_set_selection(void);
void adjust_clip_reg(int *rp); void adjust_clip_reg(int *rp);
void clip_wl_request_selection(Clipboard_T *cbd);
int clip_wl_own_selection(Clipboard_T *cbd);
void clip_wl_lose_selection(Clipboard_T *cbd);
void clip_wl_set_selection(Clipboard_T *cbd);
char *choose_clipmethod(void); char *choose_clipmethod(void);
void ex_clipreset(exarg_T *eap); void ex_clipreset(exarg_T *eap);
/* vim: set ft=c : */ /* vim: set ft=c : */

View File

@ -52,16 +52,15 @@ endfunc
" Need X connection for tests that use client server communication " Need X connection for tests that use client server communication
func s:CheckXConnection() func s:CheckXConnection()
if has('x11') CheckFeature x11
try try
call remote_send('xxx', '') call remote_send('xxx', '')
catch catch
if v:exception =~ 'E240:' if v:exception =~ 'E240:'
throw 'Skipped: no connection to the X server' thrclientserverow 'Skipped: no connection to the X server'
endif endif
" ignore other errors " ignore other errors
endtry endtry
endif
endfunc endfunc
func s:EndRemoteVim(name, job) func s:EndRemoteVim(name, job)
@ -379,7 +378,7 @@ func Test_wayland_autoselect_works()
call WaitForAssert({-> assert_equal("run", job_status(l:job))}) call WaitForAssert({-> assert_equal("run", job_status(l:job))})
call WaitForAssert({-> assert_match(name, serverlist())}) call WaitForAssert({-> assert_match(name, serverlist())})
1
call remote_send(l:name, "ve") call remote_send(l:name, "ve")
call WaitForAssert({-> assert_equal('LINE', system('wl-paste -p -n'))}) call WaitForAssert({-> assert_equal('LINE', system('wl-paste -p -n'))})
@ -648,7 +647,6 @@ func Test_wayland_handle_large_data()
call system('cmp --silent data_file data_file_cmp') call system('cmp --silent data_file data_file_cmp')
call assert_equal(0, v:shell_error) call assert_equal(0, v:shell_error)
" copy the text
call feedkeys('gg0v$G"+yy', 'x') call feedkeys('gg0v$G"+yy', 'x')
call system('wl-paste -n -t TEXT > data_file') call system('wl-paste -n -t TEXT > data_file')

View File

@ -719,6 +719,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1634,
/**/ /**/
1633, 1633,
/**/ /**/