From f26654f618cbfd99ff4c72b843db2f5fda5daa51 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 9 Dec 2017 08:41:03 +0000 Subject: [PATCH] Stop front ends remembering the data of their last paste. Previously, both the Unix and Windows front ends would respond to a paste action by retrieving data from the system clipboard, converting it appropriately, _storing_ it in a persistent dynamic data block inside the front end, and then calling term_do_paste(term), which in turn would call back to the front end via get_clip() to retrieve the current contents of that stored data block. But, as far as I can tell, this was a completely pointless mechanism, because after a data block was written into this storage area, it would be immediately used for exactly one paste, and then never accessed again until the next paste action caused it to be freed and replaced with a new chunk of pasted data. So why on earth was it stored persistently at all, and why that callback mechanism from frontend to terminal back to frontend to retrieve it for the actual paste action? I have no idea. This change removes the entire system and replaces it with the completely obvious alternative: the character-set-converted version of paste data is allocated in a _local_ variable in the frontend paste functions, passed directly to term_do_paste which now takes (buffer,length) parameters, and freed immediately afterwards. get_clip() is gone. --- fuzzterm.c | 1 - putty.h | 3 +- terminal.c | 104 +++++++++++++++++++++++------------------------ unix/gtkwin.c | 38 ++++++----------- windows/window.c | 29 ++++--------- 5 files changed, 73 insertions(+), 102 deletions(-) diff --git a/fuzzterm.c b/fuzzterm.c index 707c4ae8..3ce8b584 100644 --- a/fuzzterm.c +++ b/fuzzterm.c @@ -83,7 +83,6 @@ void palette_set(void *frontend, int a, int b, int c, int d) { } void palette_reset(void *frontend) { } int palette_get(void *frontend, int n, int *r, int *g, int *b) {return FALSE;} void write_clip(void *frontend, wchar_t *a, int *b, truecolour *c, int d, int e) { } -void get_clip(void *frontend, wchar_t **w, int *i) { } void set_raw_mouse_mode(void *frontend, int m) { } void request_paste(void *frontend) { } void do_beep(void *frontend, int a) { } diff --git a/putty.h b/putty.h index 97ef7130..964b4b23 100644 --- a/putty.h +++ b/putty.h @@ -637,7 +637,6 @@ void palette_reset(void *frontend); int palette_get(void *frontend, int n, int *r, int *g, int *b); void write_aclip(void *frontend, char *, int, int); void write_clip(void *frontend, wchar_t *, int *, truecolour *, int, int); -void get_clip(void *frontend, wchar_t **, int *); void optimised_move(void *frontend, int, int, int); void set_raw_mouse_mode(void *frontend, int); void connection_fatal(void *frontend, const char *, ...); @@ -1057,7 +1056,7 @@ void term_deselect(Terminal *); void term_update(Terminal *); void term_invalidate(Terminal *); void term_blink(Terminal *, int set_cursor); -void term_do_paste(Terminal *); +void term_do_paste(Terminal *, const wchar_t *, int); void term_nopaste(Terminal *); int term_ldisc(Terminal *, int option); void term_copyall(Terminal *); diff --git a/terminal.c b/terminal.c index 96a00266..f416e109 100644 --- a/terminal.c +++ b/terminal.c @@ -6073,66 +6073,66 @@ static void term_paste_callback(void *vterm) term->paste_len = 0; } -void term_do_paste(Terminal *term) +void term_do_paste(Terminal *term, const wchar_t *data, int len) { - wchar_t *data; - int len; + const wchar_t *p, *q; - get_clip(term->frontend, &data, &len); - if (data && len > 0) { - wchar_t *p, *q; + /* + * Pasting data into the terminal counts as a keyboard event (for + * purposes of the 'Reset scrollback on keypress' config option), + * unless the paste is zero-length. + */ + if (len == 0) + return; + term_seen_key_event(term); - term_seen_key_event(term); /* pasted data counts */ + if (term->paste_buffer) + sfree(term->paste_buffer); + term->paste_pos = term->paste_len = 0; + term->paste_buffer = snewn(len + 12, wchar_t); + if (term->bracketed_paste) { + memcpy(term->paste_buffer, L"\033[200~", 6 * sizeof(wchar_t)); + term->paste_len += 6; + } + + p = q = data; + while (p < data + len) { + while (p < data + len && + !(p <= data + len - sel_nl_sz && + !memcmp(p, sel_nl, sizeof(sel_nl)))) + p++; + + { + int i; + for (i = 0; i < p - q; i++) { + term->paste_buffer[term->paste_len++] = q[i]; + } + } + + if (p <= data + len - sel_nl_sz && + !memcmp(p, sel_nl, sizeof(sel_nl))) { + term->paste_buffer[term->paste_len++] = '\015'; + p += sel_nl_sz; + } + q = p; + } + + if (term->bracketed_paste) { + memcpy(term->paste_buffer + term->paste_len, + L"\033[201~", 6 * sizeof(wchar_t)); + term->paste_len += 6; + } + + /* Assume a small paste will be OK in one go. */ + if (term->paste_len < 256) { + if (term->ldisc) + luni_send(term->ldisc, term->paste_buffer, term->paste_len, 0); if (term->paste_buffer) sfree(term->paste_buffer); + term->paste_buffer = 0; term->paste_pos = term->paste_len = 0; - term->paste_buffer = snewn(len + 12, wchar_t); - - if (term->bracketed_paste) { - memcpy(term->paste_buffer, L"\033[200~", 6 * sizeof(wchar_t)); - term->paste_len += 6; - } - - p = q = data; - while (p < data + len) { - while (p < data + len && - !(p <= data + len - sel_nl_sz && - !memcmp(p, sel_nl, sizeof(sel_nl)))) - p++; - - { - int i; - for (i = 0; i < p - q; i++) { - term->paste_buffer[term->paste_len++] = q[i]; - } - } - - if (p <= data + len - sel_nl_sz && - !memcmp(p, sel_nl, sizeof(sel_nl))) { - term->paste_buffer[term->paste_len++] = '\015'; - p += sel_nl_sz; - } - q = p; - } - - if (term->bracketed_paste) { - memcpy(term->paste_buffer + term->paste_len, - L"\033[201~", 6 * sizeof(wchar_t)); - term->paste_len += 6; - } - - /* Assume a small paste will be OK in one go. */ - if (term->paste_len < 256) { - if (term->ldisc) - luni_send(term->ldisc, term->paste_buffer, term->paste_len, 0); - if (term->paste_buffer) - sfree(term->paste_buffer); - term->paste_buffer = 0; - term->paste_pos = term->paste_len = 0; - } } - get_clip(term->frontend, NULL, NULL); queue_toplevel_callback(term_paste_callback, term); } diff --git a/unix/gtkwin.c b/unix/gtkwin.c index b8607665..96421ac5 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -101,8 +101,6 @@ struct gui_data { GdkColormap *colmap; #endif int direct_to_font; - wchar_t *pastein_data; - int pastein_data_len; #ifdef JUST_USE_GTK_CLIPBOARD_UTF8 GtkClipboard *clipboard; struct clipboard_data_instance *current_cdi; @@ -2594,6 +2592,8 @@ static void clipboard_text_received(GtkClipboard *clipboard, const gchar *text, gpointer data) { struct gui_data *inst = (struct gui_data *)data; + wchar_t *paste; + int paste_len; int length; if (!text) @@ -2601,14 +2601,12 @@ static void clipboard_text_received(GtkClipboard *clipboard, length = strlen(text); - if (inst->pastein_data) - sfree(inst->pastein_data); + paste = snewn(length, wchar_t); + paste_len = mb_to_wc(CS_UTF8, 0, text, length, paste, length); - inst->pastein_data = snewn(length, wchar_t); - inst->pastein_data_len = mb_to_wc(CS_UTF8, 0, text, length, - inst->pastein_data, length); + term_do_paste(inst->term, paste, paste_len); - term_do_paste(inst->term); + sfree(paste); } void request_paste(void *frontend) @@ -2855,6 +2853,8 @@ static void selection_received(GtkWidget *widget, GtkSelectionData *seldata, GdkAtom seldata_type = gtk_selection_data_get_data_type(seldata); const guchar *seldata_data = gtk_selection_data_get_data(seldata); gint seldata_length = gtk_selection_data_get_length(seldata); + wchar_t *paste; + int paste_len; if (seldata_target == utf8_string_atom && seldata_length <= 0) { /* @@ -2942,16 +2942,12 @@ static void selection_received(GtkWidget *widget, GtkSelectionData *seldata, } } - if (inst->pastein_data) - sfree(inst->pastein_data); + paste = snewn(length, wchar_t); + paste_len = mb_to_wc(charset, 0, text, length, paste, length); - inst->pastein_data = snewn(length, wchar_t); - inst->pastein_data_len = length; - inst->pastein_data_len = - mb_to_wc(charset, 0, text, length, - inst->pastein_data, inst->pastein_data_len); + term_do_paste(inst->term, paste, paste_len); - term_do_paste(inst->term); + sfree(paste); #ifndef NOT_X_WINDOWS if (free_list_required) @@ -3011,16 +3007,6 @@ void init_clipboard(struct gui_data *inst) #endif /* JUST_USE_GTK_CLIPBOARD_UTF8 */ -void get_clip(void *frontend, wchar_t ** p, int *len) -{ - struct gui_data *inst = (struct gui_data *)frontend; - - if (p) { - *p = inst->pastein_data; - *len = inst->pastein_data_len; - } -} - static void set_window_titles(struct gui_data *inst) { /* diff --git a/windows/window.c b/windows/window.c index e5bd5b7f..3a67fb87 100644 --- a/windows/window.c +++ b/windows/window.c @@ -105,7 +105,7 @@ static int is_full_screen(void); static void make_full_screen(void); static void clear_full_screen(void); static void flip_full_screen(void); -static int process_clipdata(HGLOBAL clipdata, int unicode); +static void process_clipdata(HGLOBAL clipdata, int unicode); /* Window layout information */ static void reset_window(int); @@ -135,9 +135,6 @@ static const struct telnet_special *specials = NULL; static HMENU specials_menu = NULL; static int n_specials = 0; -static wchar_t *clipboard_contents; -static size_t clipboard_length; - #define TIMING_TIMER_ID 1234 static long timing_next_time; @@ -3176,8 +3173,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } return 0; case WM_GOT_CLIPDATA: - if (process_clipdata((HGLOBAL)lParam, wParam)) - term_do_paste(term); + process_clipdata((HGLOBAL)lParam, wParam); return 0; default: if (message == wm_mousewheel || message == WM_MOUSEWHEEL) { @@ -5340,11 +5336,10 @@ static DWORD WINAPI clipboard_read_threadfunc(void *param) return 0; } -static int process_clipdata(HGLOBAL clipdata, int unicode) +static void process_clipdata(HGLOBAL clipdata, int unicode) { - sfree(clipboard_contents); - clipboard_contents = NULL; - clipboard_length = 0; + wchar_t *clipboard_contents = NULL; + size_t clipboard_length = 0; if (unicode) { wchar_t *p = GlobalLock(clipdata); @@ -5357,7 +5352,7 @@ static int process_clipdata(HGLOBAL clipdata, int unicode) clipboard_contents = snewn(clipboard_length + 1, wchar_t); memcpy(clipboard_contents, p, clipboard_length * sizeof(wchar_t)); clipboard_contents[clipboard_length] = L'\0'; - return TRUE; + term_do_paste(term, clipboard_contents, clipboard_length); } } else { char *s = GlobalLock(clipdata); @@ -5370,11 +5365,11 @@ static int process_clipdata(HGLOBAL clipdata, int unicode) clipboard_contents, i); clipboard_length = i - 1; clipboard_contents[clipboard_length] = L'\0'; - return TRUE; + term_do_paste(term, clipboard_contents, clipboard_length); } } - return FALSE; + sfree(clipboard_contents); } void request_paste(void *frontend) @@ -5400,14 +5395,6 @@ void request_paste(void *frontend) hwnd, 0, &in_threadid); } -void get_clip(void *frontend, wchar_t **p, int *len) -{ - if (p) { - *p = clipboard_contents; - *len = clipboard_length; - } -} - #if 0 /* * Move `lines' lines from position `from' to position `to' in the