# HG changeset patch # User Bram Moolenaar # Date 1363193425 -3600 # Node ID fb533fb6c015f40a3b1301c0c876c35665b0d6ef # Parent b92c36ba3b347c5d53884a562480ee5f3f96d017 updated for version 7.3.856 Problem: When calling system() multi-byte clipboard contents is garbled. Solution: Save and restore the clipboard contents. (Yukihiro Nakadaira) diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -5674,12 +5674,8 @@ clip_mch_request_selection(VimClipboard void clip_mch_lose_selection(VimClipboard *cbd UNUSED) { - /* WEIRD: when using NULL to actually disown the selection, we lose the - * selection the first time we own it. */ - /* - gtk_selection_owner_set(NULL, cbd->gtk_sel_atom, (guint32)GDK_CURRENT_TIME); + gtk_selection_owner_set(NULL, cbd->gtk_sel_atom, gui.event_time); gui_mch_update(); - */ } /* @@ -5705,6 +5701,12 @@ clip_mch_set_selection(VimClipboard *cbd { } + int +clip_gtk_owner_exists(VimClipboard *cbd) +{ + return gdk_selection_owner_get(cbd->gtk_sel_atom) != NULL; +} + #if defined(FEAT_MENU) || defined(PROTO) /* diff --git a/src/ops.c b/src/ops.c --- a/src/ops.c +++ b/src/ops.c @@ -1017,6 +1017,19 @@ put_register(name, reg) may_set_selection(); # endif } + + void +free_register(reg) + void *reg; +{ + struct yankreg tmp; + + tmp = *y_current; + *y_current = *(struct yankreg *)reg; + free_yank_all(); + vim_free(reg); + *y_current = tmp; +} #endif #if defined(FEAT_MOUSE) || defined(PROTO) diff --git a/src/os_unix.c b/src/os_unix.c --- a/src/os_unix.c +++ b/src/os_unix.c @@ -1138,6 +1138,11 @@ sigcont_handler SIGDEFARG(sigarg) # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) static void loose_clipboard __ARGS((void)); +static void save_clipboard __ARGS((void)); +static void restore_clipboard __ARGS((void)); + +static void *clip_star_save = NULL; +static void *clip_plus_save = NULL; /* * Called when Vim is going to sleep or execute a shell command. @@ -1158,6 +1163,42 @@ loose_clipboard() XFlush(x11_display); } } + +/* + * Save clipboard text to restore later. + */ + static void +save_clipboard() +{ + if (clip_star.owned) + clip_star_save = get_register('*', TRUE); + if (clip_plus.owned) + clip_plus_save = get_register('+', TRUE); +} + +/* + * Restore clipboard text if no one own the X selection. + */ + static void +restore_clipboard() +{ + if (clip_star_save != NULL) + { + if (!clip_gen_owner_exists(&clip_star)) + put_register('*', clip_star_save); + else + free_register(clip_star_save); + clip_star_save = NULL; + } + if (clip_plus_save != NULL) + { + if (!clip_gen_owner_exists(&clip_plus)) + put_register('+', clip_plus_save); + else + free_register(clip_plus_save); + clip_plus_save = NULL; + } +} #endif /* @@ -3844,6 +3885,7 @@ mch_call_shell(cmd, options) settmode(TMODE_COOK); /* set to normal mode */ # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) + save_clipboard(); loose_clipboard(); # endif @@ -3917,6 +3959,9 @@ mch_call_shell(cmd, options) # ifdef FEAT_TITLE resettitle(); # endif +# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) + restore_clipboard(); +# endif return x; #else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */ @@ -3965,6 +4010,9 @@ mch_call_shell(cmd, options) settmode(TMODE_COOK); /* set to normal mode */ # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) + /* Disown the clipboard, because is the executed command tries to obtain a + * selection and we own it we get a deadlock. */ + save_clipboard(); loose_clipboard(); # endif @@ -4836,6 +4884,9 @@ error: # ifdef FEAT_TITLE resettitle(); # endif +# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) + restore_clipboard(); +# endif vim_free(newcmd); return retval; diff --git a/src/proto/gui_gtk_x11.pro b/src/proto/gui_gtk_x11.pro --- a/src/proto/gui_gtk_x11.pro +++ b/src/proto/gui_gtk_x11.pro @@ -59,6 +59,7 @@ void clip_mch_request_selection __ARGS(( void clip_mch_lose_selection __ARGS((VimClipboard *cbd)); int clip_mch_own_selection __ARGS((VimClipboard *cbd)); void clip_mch_set_selection __ARGS((VimClipboard *cbd)); +int clip_gtk_owner_exists __ARGS((VimClipboard *cbd)); void gui_mch_menu_grey __ARGS((vimmenu_T *menu, int grey)); void gui_mch_menu_hidden __ARGS((vimmenu_T *menu, int hidden)); void gui_mch_draw_menubar __ARGS((void)); diff --git a/src/proto/ops.pro b/src/proto/ops.pro --- a/src/proto/ops.pro +++ b/src/proto/ops.pro @@ -15,6 +15,7 @@ void get_yank_register __ARGS((int regna int may_get_selection __ARGS((int regname)); void *get_register __ARGS((int name, int copy)); void put_register __ARGS((int name, void *reg)); +void free_register __ARGS((void *reg)); int yank_register_mline __ARGS((int regname)); int do_record __ARGS((int c)); int do_execreg __ARGS((int regname, int colon, int addcr, int silent)); diff --git a/src/proto/ui.pro b/src/proto/ui.pro --- a/src/proto/ui.pro +++ b/src/proto/ui.pro @@ -29,6 +29,7 @@ int clip_gen_own_selection __ARGS((VimCl void clip_gen_lose_selection __ARGS((VimClipboard *cbd)); void clip_gen_set_selection __ARGS((VimClipboard *cbd)); void clip_gen_request_selection __ARGS((VimClipboard *cbd)); +int clip_gen_owner_exists __ARGS((VimClipboard *cbd)); int vim_is_input_buf_full __ARGS((void)); int vim_is_input_buf_empty __ARGS((void)); int vim_free_in_input_buf __ARGS((void)); @@ -52,6 +53,7 @@ void clip_x11_request_selection __ARGS(( void clip_x11_lose_selection __ARGS((Widget myShell, VimClipboard *cbd)); int clip_x11_own_selection __ARGS((Widget myShell, VimClipboard *cbd)); void clip_x11_set_selection __ARGS((VimClipboard *cbd)); +int clip_x11_owner_exists __ARGS((VimClipboard *cbd)); void yank_cut_buffer0 __ARGS((Display *dpy, VimClipboard *cbd)); int jump_to_mouse __ARGS((int flags, int *inclusive, int which_button)); int mouse_comp_pos __ARGS((win_T *win, int *rowp, int *colp, linenr_T *lnump)); diff --git a/src/ui.c b/src/ui.c --- a/src/ui.c +++ b/src/ui.c @@ -1456,6 +1456,21 @@ clip_gen_request_selection(cbd) #endif } + int +clip_gen_owner_exists(cbd) + VimClipboard *cbd; +{ +#ifdef FEAT_XCLIPBOARD +# ifdef FEAT_GUI_GTK + if (gui.in_use) + return clip_gtk_owner_exists(cbd); + else +# endif + return clip_x11_owner_exists(cbd); +#endif + return TRUE; +} + #endif /* FEAT_CLIPBOARD */ /***************************************************************************** @@ -2398,7 +2413,8 @@ clip_x11_lose_selection(myShell, cbd) Widget myShell; VimClipboard *cbd; { - XtDisownSelection(myShell, cbd->sel_atom, CurrentTime); + XtDisownSelection(myShell, cbd->sel_atom, + XtLastTimestampProcessed(XtDisplay(myShell))); } int @@ -2440,6 +2456,13 @@ clip_x11_set_selection(cbd) VimClipboard *cbd UNUSED; { } + + int +clip_x11_owner_exists(cbd) + VimClipboard *cbd; +{ + return XGetSelectionOwner(X_DISPLAY, cbd->sel_atom) != None; +} #endif #if defined(FEAT_XCLIPBOARD) || defined(FEAT_GUI_X11) \ diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 856, +/**/ 855, /**/ 854,