X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/3e4731a35aecef3d0002b3bcc2d89c87d26646fa..59b7fa6569f8b865b6ef688a8531d745f1cc67d4:/src/w32select.c diff --git a/src/w32select.c b/src/w32select.c index 560fad01a2..fa37bd6592 100644 --- a/src/w32select.c +++ b/src/w32select.c @@ -37,19 +37,28 @@ Lisp_Object QCLIPBOARD; clipboard. */ static Lisp_Object Vselection_coding_system; -/* Coding system for the next communicating with other X clients. */ +/* Coding system for the next communicating with other Windows programs. */ static Lisp_Object Vnext_selection_coding_system; +/* The last text we put into the clipboard. This is used to prevent + passing back our own text from the clipboard, instead of using the + kill ring. The former is undesirable because the clipboard data + could be MULEtilated by inappropriately chosen + (next-)selection-coding-system. For this reason, we must store the + text *after* it was encoded/Unix-to-DOS-converted. */ +static unsigned char *last_clipboard_text = NULL; +static size_t clipboard_storage_size = 0; + #if 0 DEFUN ("w32-open-clipboard", Fw32_open_clipboard, Sw32_open_clipboard, 0, 1, 0, - "This opens the clipboard with the given frame pointer.") + doc: /* This opens the clipboard with the given frame pointer. */) (frame) Lisp_Object frame; { BOOL ok = FALSE; if (!NILP (frame)) - CHECK_LIVE_FRAME (frame, 0); + CHECK_LIVE_FRAME (frame); BLOCK_INPUT; @@ -60,8 +69,10 @@ DEFUN ("w32-open-clipboard", Fw32_open_clipboard, Sw32_open_clipboard, 0, 1, 0, return (ok ? frame : Qnil); } -DEFUN ("w32-empty-clipboard", Fw32_empty_clipboard, Sw32_empty_clipboard, 0, 0, 0, - "This empties the clipboard and assigns ownership to the window which opened the clipboard.") +DEFUN ("w32-empty-clipboard", Fw32_empty_clipboard, + Sw32_empty_clipboard, 0, 0, 0, + doc: /* Empty the clipboard. +Assigns ownership of the clipboard to the window which opened it. */) () { BOOL ok = FALSE; @@ -75,8 +86,9 @@ DEFUN ("w32-empty-clipboard", Fw32_empty_clipboard, Sw32_empty_clipboard, 0, 0, return (ok ? Qt : Qnil); } -DEFUN ("w32-close-clipboard", Fw32_close_clipboard, Sw32_close_clipboard, 0, 0, 0, - "This closes the clipboard.") +DEFUN ("w32-close-clipboard", Fw32_close_clipboard, + Sw32_close_clipboard, 0, 0, 0, + doc: /* Close the clipboard. */) () { BOOL ok = FALSE; @@ -92,8 +104,9 @@ DEFUN ("w32-close-clipboard", Fw32_close_clipboard, Sw32_close_clipboard, 0, 0, #endif -DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, Sw32_set_clipboard_data, 1, 2, 0, - "This sets the clipboard data to the given text.") +DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, + Sw32_set_clipboard_data, 1, 2, 0, + doc: /* This sets the clipboard data to the given text. */) (string, frame) Lisp_Object string, frame; { @@ -104,10 +117,10 @@ DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, Sw32_set_clipboard_dat unsigned char *src; unsigned char *dst; - CHECK_STRING (string, 0); + CHECK_STRING (string); if (!NILP (frame)) - CHECK_LIVE_FRAME (frame, 0); + CHECK_LIVE_FRAME (frame); BLOCK_INPUT; @@ -174,10 +187,8 @@ DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, Sw32_set_clipboard_dat } else { - /* We must encode contents of OBJ to compound text format. - The format is compatible with what the target `STRING' - expects if OBJ contains only ASCII and Latin-1 - characters. */ + /* We must encode contents of OBJ to the selection coding + system. */ int bufsize; struct coding_system coding; HANDLE htext2; @@ -186,6 +197,13 @@ DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, Sw32_set_clipboard_dat Vnext_selection_coding_system = Vselection_coding_system; setup_coding_system (Fcheck_coding_system (Vnext_selection_coding_system), &coding); + if (SYMBOLP (coding.pre_write_conversion) + && !NILP (Ffboundp (coding.pre_write_conversion))) + { + string = run_pre_post_conversion_on_str (string, &coding, 1); + src = XSTRING (string)->data; + nbytes = STRING_BYTES (XSTRING (string)); + } coding.src_multibyte = 1; coding.dst_multibyte = 0; Vnext_selection_coding_system = Qnil; @@ -197,16 +215,31 @@ DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, Sw32_set_clipboard_dat goto error; encode_coding (&coding, src, dst, nbytes, bufsize); Vlast_coding_system_used = coding.symbol; + + /* Stash away the data we are about to put into the clipboard, so we + could later check inside Fw32_get_clipboard_data whether + the clipboard still holds our data. */ + if (clipboard_storage_size < coding.produced) + { + clipboard_storage_size = coding.produced + 100; + last_clipboard_text = (char *) xrealloc (last_clipboard_text, + clipboard_storage_size); + } + if (last_clipboard_text) + memcpy (last_clipboard_text, dst, coding.produced); + GlobalUnlock (htext); + /* Shrink data block to actual size. */ - htext2 = GlobalReAlloc (htext, coding.produced, GMEM_MOVEABLE | GMEM_DDESHARE); + htext2 = GlobalReAlloc (htext, coding.produced, + GMEM_MOVEABLE | GMEM_DDESHARE); if (htext2 != NULL) htext = htext2; } } if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL)) goto error; - + ok = EmptyClipboard () && SetClipboardData (CF_TEXT, htext); CloseClipboard (); @@ -217,15 +250,18 @@ DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, Sw32_set_clipboard_dat ok = FALSE; if (htext) GlobalFree (htext); - + if (last_clipboard_text) + *last_clipboard_text = '\0'; + done: UNBLOCK_INPUT; return (ok ? string : Qnil); } -DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, Sw32_get_clipboard_data, 0, 1, 0, - "This gets the clipboard data in text format.") +DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, + Sw32_get_clipboard_data, 0, 1, 0, + doc: /* This gets the clipboard data in text format. */) (frame) Lisp_Object frame; { @@ -233,7 +269,7 @@ DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, Sw32_get_clipboard_dat Lisp_Object ret = Qnil; if (!NILP (frame)) - CHECK_LIVE_FRAME (frame, 0); + CHECK_LIVE_FRAME (frame); BLOCK_INPUT; @@ -255,28 +291,31 @@ DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, Sw32_get_clipboard_dat nbytes = strlen (src); - if ( -#if 1 - 1 -#else - ! NILP (buffer_defaults.enable_multibyte_characters) -#endif - ) - { - /* If the clipboard data contains any non-ascii code, we - need to decode it. */ - int i; + /* If the text in clipboard is identical to what we put there + last time w32_set_clipboard_data was called, pretend there's no + data in the clipboard. This is so we don't pass our own text + from the clipboard (which might be troublesome if the killed + text includes null characters). */ + if (last_clipboard_text + && clipboard_storage_size >= nbytes + && memcmp(last_clipboard_text, src, nbytes) == 0) + goto closeclip; + + { + /* If the clipboard data contains any non-ascii code, we + need to decode it. */ + int i; + + for (i = 0; i < nbytes; i++) + { + if (src[i] >= 0x80) + { + require_decoding = 1; + break; + } + } + } - for (i = 0; i < nbytes; i++) - { - if (src[i] >= 0x80) - { - require_decoding = 1; - break; - } - } - } - if (require_decoding) { int bufsize; @@ -295,9 +334,12 @@ DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, Sw32_get_clipboard_dat buf = (unsigned char *) xmalloc (bufsize); decode_coding (&coding, src, buf, nbytes, bufsize); Vlast_coding_system_used = coding.symbol; - ret = make_string_from_bytes ((char *) buf, - coding.produced_char, coding.produced); + ret = make_string_from_bytes ((char *) buf, + coding.produced_char, coding.produced); xfree (buf); + if (SYMBOLP (coding.post_read_conversion) + && !NILP (Ffboundp (coding.post_read_conversion))) + ret = run_pre_post_conversion_on_str (ret, &coding, 0); } else { @@ -360,17 +402,17 @@ DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, Sw32_get_clipboard_dat /* Support checking for a clipboard selection. */ DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p, - 0, 1, 0, - "Whether there is an owner for the given X Selection.\n\ -The arg should be the name of the selection in question, typically one of\n\ -the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\ -\(Those are literal upper-case symbol names, since that's what X expects.)\n\ -For convenience, the symbol nil is the same as `PRIMARY',\n\ -and t is the same as `SECONDARY'.") + 0, 1, 0, + doc: /* Whether there is an owner for the given X Selection. +The arg should be the name of the selection in question, typically one of +the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. +\(Those are literal upper-case symbol names, since that's what X expects.) +For convenience, the symbol nil is the same as `PRIMARY', +and t is the same as `SECONDARY'. */) (selection) Lisp_Object selection; { - CHECK_SYMBOL (selection, 0); + CHECK_SYMBOL (selection); /* Return nil for PRIMARY and SECONDARY selections; for CLIPBOARD, check if the clipboard currently has valid text format contents. */ @@ -408,18 +450,17 @@ syms_of_w32select () defsubr (&Sx_selection_exists_p); DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system, - "Coding system for communicating with other X clients.\n\ -When sending or receiving text via cut_buffer, selection, and clipboard,\n\ -the text is encoded or decoded by this coding system.\n\ -A default value is `compound-text'"); + doc: /* Coding system for communicating with other programs. +When sending or receiving text via cut_buffer, selection, and clipboard, +the text is encoded or decoded by this coding system. */); Vselection_coding_system=intern ("iso-latin-1-dos"); DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system, - "Coding system for the next communication with other X clients.\n\ -Usually, `selection-coding-system' is used for communicating with\n\ -other X clients. But, if this variable is set, it is used for the\n\ -next communication only. After the communication, this variable is\n\ -set to nil."); + doc: /* Coding system for the next communication with other programs. +Usually, `selection-coding-system' is used for communicating with +other programs. But, if this variable is set, it is used for the +next communication only. After the communication, this variable is +set to nil. */); Vnext_selection_coding_system = Qnil; QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD);