diff options
| author | Jason Rumney | 2005-02-15 23:19:26 +0000 |
|---|---|---|
| committer | Jason Rumney | 2005-02-15 23:19:26 +0000 |
| commit | 52c7f9eea2faf4094df00bf30d2d7cd2210c8cb5 (patch) | |
| tree | 75db6243e27131ee03d6c73d2323841e627b19e7 /src/w32select.c | |
| parent | d02d0705b396b0deed399af01a370e8c9de6f7e6 (diff) | |
| download | emacs-52c7f9eea2faf4094df00bf30d2d7cd2210c8cb5.tar.gz emacs-52c7f9eea2faf4094df00bf30d2d7cd2210c8cb5.zip | |
2004-11-08 Benjamin Riefenstahl <Benjamin.Riefenstahl@epost.de>
* w32select.c: Summary: Thorough rework to implement Unicode
clipboard operations and delayed rendering.
Drop last_clipboard_text and related code, keep track of
ownership via clipboard_owner instead. Drop old #if0
sections.
(DEFAULT_LCID, ANSICP, OEMCP, QUNICODE, QANSICP, QOEMCP)
(clipboard_owner, modifying_clipboard, cfg_coding_system)
(cfg_codepage, cfg_lcid, cfg_clipboard_type, current_text)
(current_coding_system, current_requires_encoding)
(current_num_nls, current_clipboard_type, current_lcid): New
static variables.
(convert_to_handle_as_ascii, convert_to_handle_as_coded)
(render, render_all, run_protected, lisp_error_handler)
(owner_callback, create_owner, setup_config)
(enum_locale_callback, cp_from_locale, coding_from_cp): New
local functions.
(term_w32select, globals_of_w32select): New global functions.
(Fw32_set_clipboard_data): Ignore parameter FRAME, use
clipboard_owner instead. Use delayed rendering and provide
all text formats. Provide CF_LOCALE if necessary.
(Fw32_get_clipboard_data): Handle CF_UNICODETEXT and
CF_LOCALE. Fall back to CF_TEXT, if CF_UNICODETEXT is not
available. Force DOS line-ends for decoding.
(Fx_selection_exists_p): Handle CF_UNICODETEXT.
(syms_of_w32select): Init and register new variables.
* w32.h: Add prototypes for globals_of_w32select and
term_w32select. Make the neighboring K&R declarations into
prototypes, too.
* emacs.c: Include w32.h to get function prototypes.
(main): Call globals_of_w32select.
* w32.c (term_ntproc): Call term_w32select.
* mule-cmds.el (set-locale-environment): Remove call to
set-selection-coding-system on Windows.
* s/ms-w32.h: Guard MSC-specific #pragmas with an #ifdef.
Diffstat (limited to 'src/w32select.c')
| -rw-r--r-- | src/w32select.c | 1095 |
1 files changed, 846 insertions, 249 deletions
diff --git a/src/w32select.c b/src/w32select.c index 20f7cfc457f..e562dc7efbb 100644 --- a/src/w32select.c +++ b/src/w32select.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* Selection processing for Emacs on the Microsoft W32 API. | 1 | /* Selection processing for Emacs on the Microsoft W32 API. |
| 2 | Copyright (C) 1993, 1994 Free Software Foundation. | 2 | Copyright (C) 1993, 1994, 2004 Free Software Foundation. |
| 3 | 3 | ||
| 4 | This file is part of GNU Emacs. | 4 | This file is part of GNU Emacs. |
| 5 | 5 | ||
| @@ -18,273 +18,744 @@ along with GNU Emacs; see the file COPYING. If not, write to | |||
| 18 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| 19 | Boston, MA 02111-1307, USA. */ | 19 | Boston, MA 02111-1307, USA. */ |
| 20 | 20 | ||
| 21 | /* Written by Kevin Gallo */ | 21 | /* Written by Kevin Gallo, Benjamin Riefenstahl */ |
| 22 | 22 | ||
| 23 | |||
| 24 | /* | ||
| 25 | * Notes on usage of selection-coding-system and | ||
| 26 | * next-selection-coding-system on MS Windows: | ||
| 27 | * | ||
| 28 | * The selection coding system variables apply only to the version of | ||
| 29 | * the clipboard data that is closest in type, i.e. when a 16-bit | ||
| 30 | * Unicode coding system is given, they apply to he Unicode clipboard | ||
| 31 | * (CF_UNICODETEXT), when a well-known console codepage is given, they | ||
| 32 | * apply to the console version of the clipboard data (CF_OEMTEXT), | ||
| 33 | * else they apply to the normal 8-bit text clipboard (CF_TEXT). | ||
| 34 | * | ||
| 35 | * When pasting (getting data from the OS), the clipboard format that | ||
| 36 | * matches the {next-}selection-coding-system is retrieved. If | ||
| 37 | * Unicode is requested, but not available, 8-bit text (CF_TEXT) is | ||
| 38 | * used. In all other cases the OS will transparently convert | ||
| 39 | * formats, so no other fallback is needed. | ||
| 40 | * | ||
| 41 | * When copying or cutting (sending data to the OS), the data is | ||
| 42 | * announced and stored internally, but only actually rendered on | ||
| 43 | * request. The requester determines the format provided. The | ||
| 44 | * {next-}selection-coding-system is only used, when its corresponding | ||
| 45 | * clipboard type matches the type requested. | ||
| 46 | * | ||
| 47 | * Scenarios to use the facilities for customizing the selection | ||
| 48 | * coding system are: | ||
| 49 | * | ||
| 50 | * ;; Generally use KOI8-R instead of the russian MS codepage for | ||
| 51 | * ;; the 8-bit clipboard. | ||
| 52 | * (set-selection-coding-system 'koi8-r-dos) | ||
| 53 | * | ||
| 54 | * Or | ||
| 55 | * | ||
| 56 | * ;; Create a special clipboard copy function that uses codepage | ||
| 57 | * ;; 1253 (Greek) to copy Greek text to a specific non-Unicode | ||
| 58 | * ;; application. | ||
| 59 | * (defun greek-copy (beg end) | ||
| 60 | * (interactive "r") | ||
| 61 | * (set-next-selection-coding-system 'cp1253-dos) | ||
| 62 | * (copy-region-as-kill beg end)) | ||
| 63 | * (global-set-key "\C-c\C-c" 'greek-copy) | ||
| 64 | */ | ||
| 65 | |||
| 66 | /* | ||
| 67 | * Ideas for further directions: | ||
| 68 | * | ||
| 69 | * The encoding and decoding routines could be moved to Lisp code | ||
| 70 | * similar to how xselect.c does it (using well-known routine names | ||
| 71 | * for the delayed rendering). If the definition of which clipboard | ||
| 72 | * types should be supported is also moved to Lisp, functionality | ||
| 73 | * could be expanded to CF_HTML, CF_RTF and maybe other types. | ||
| 74 | */ | ||
| 75 | |||
| 23 | #include <config.h> | 76 | #include <config.h> |
| 24 | #include "lisp.h" | 77 | #include "lisp.h" |
| 25 | #include "w32term.h" /* for all of the w32 includes */ | 78 | #include "w32term.h" /* for all of the w32 includes */ |
| 26 | #include "dispextern.h" /* frame.h seems to want this */ | 79 | #include "w32heap.h" /* os_subtype */ |
| 27 | #include "keyboard.h" | ||
| 28 | #include "frame.h" /* Need this to get the X window of selected_frame */ | ||
| 29 | #include "blockinput.h" | 80 | #include "blockinput.h" |
| 30 | #include "buffer.h" | 81 | #include "keyboard.h" /* cmd_error_internal() */ |
| 31 | #include "charset.h" | 82 | #include "charset.h" |
| 32 | #include "coding.h" | 83 | #include "coding.h" |
| 33 | #include "composite.h" | 84 | #include "composite.h" |
| 34 | 85 | ||
| 86 | |||
| 87 | static HGLOBAL convert_to_handle_as_ascii (void); | ||
| 88 | static HGLOBAL convert_to_handle_as_coded (Lisp_Object coding_system); | ||
| 89 | static Lisp_Object render (Lisp_Object oformat); | ||
| 90 | static Lisp_Object render_locale (void); | ||
| 91 | static Lisp_Object render_all (void); | ||
| 92 | static void run_protected (Lisp_Object (*code) (), Lisp_Object arg); | ||
| 93 | static Lisp_Object lisp_error_handler (Lisp_Object error); | ||
| 94 | static LRESULT CALLBACK owner_callback (HWND win, UINT msg, | ||
| 95 | WPARAM wp, LPARAM lp); | ||
| 96 | static HWND create_owner (void); | ||
| 97 | |||
| 98 | static void setup_config (void); | ||
| 99 | static BOOL WINAPI enum_locale_callback (/*const*/ char* loc_string); | ||
| 100 | static UINT cp_from_locale (LCID lcid, UINT format); | ||
| 101 | static Lisp_Object coding_from_cp (UINT codepage); | ||
| 102 | |||
| 103 | |||
| 104 | /* A remnant from X11: Symbol for the CLIPBORD selection type. Other | ||
| 105 | selections are not used on Windows, so we don't need symbols for | ||
| 106 | PRIMARY and SECONDARY. */ | ||
| 35 | Lisp_Object QCLIPBOARD; | 107 | Lisp_Object QCLIPBOARD; |
| 36 | 108 | ||
| 37 | /* Coding system for communicating with other Windows programs via the | 109 | /* Coding system for communicating with other programs via the |
| 38 | clipboard. */ | 110 | clipboard. */ |
| 39 | static Lisp_Object Vselection_coding_system; | 111 | static Lisp_Object Vselection_coding_system; |
| 40 | 112 | ||
| 41 | /* Coding system for the next communicating with other Windows programs. */ | 113 | /* Coding system for the next communication with other programs. */ |
| 42 | static Lisp_Object Vnext_selection_coding_system; | 114 | static Lisp_Object Vnext_selection_coding_system; |
| 43 | 115 | ||
| 44 | /* Sequence number, used where possible to detect when we are pasting | 116 | /* Internal pseudo-constants, initialized in globals_of_w32select() |
| 45 | our own text. */ | 117 | based on current system parameters. */ |
| 46 | static DWORD last_clipboard_sequence_number; | 118 | static LCID DEFAULT_LCID; |
| 47 | extern ClipboardSequence_Proc clipboard_sequence_fn; | 119 | static UINT ANSICP, OEMCP; |
| 48 | 120 | static Lisp_Object QUNICODE, QANSICP, QOEMCP; | |
| 49 | /* The last text we put into the clipboard. This is used when the OS | 121 | |
| 50 | does not support sequence numbers (NT4, 95). It is undesirable to | 122 | /* A hidden window just for the clipboard management. */ |
| 51 | use data put on the clipboard by Emacs because the clipboard data | 123 | static HWND clipboard_owner; |
| 52 | could be MULEtilated by inappropriately chosen | 124 | /* A flag to tell WM_DESTROYCLIPBOARD who is to blame this time (just |
| 53 | (next-)selection-coding-system. For this reason, we must store the | 125 | checking GetClipboardOwner() doesn't work, sadly). */ |
| 54 | text *after* it was encoded/Unix-to-DOS-converted. */ | 126 | static int modifying_clipboard = 0; |
| 55 | static unsigned char *last_clipboard_text = NULL; | 127 | |
| 56 | static size_t clipboard_storage_size = 0; | 128 | /* Configured transfer parameters, based on the last inspection of |
| 57 | 129 | selection-coding-system. */ | |
| 58 | #if 0 | 130 | static Lisp_Object cfg_coding_system; |
| 59 | DEFUN ("w32-open-clipboard", Fw32_open_clipboard, Sw32_open_clipboard, 0, 1, 0, | 131 | static UINT cfg_codepage; |
| 60 | doc: /* This opens the clipboard with the given frame pointer. */) | 132 | static LCID cfg_lcid; |
| 61 | (frame) | 133 | static UINT cfg_clipboard_type; |
| 62 | Lisp_Object frame; | 134 | |
| 135 | /* The current state for delayed rendering. */ | ||
| 136 | static Lisp_Object current_text; | ||
| 137 | static Lisp_Object current_coding_system; | ||
| 138 | static int current_requires_encoding, current_num_nls; | ||
| 139 | static UINT current_clipboard_type; | ||
| 140 | static LCID current_lcid; | ||
| 141 | |||
| 142 | #if TRACE | ||
| 143 | #define ONTRACE(stmt) stmt | ||
| 144 | #else | ||
| 145 | #define ONTRACE(stmt) /*stmt*/ | ||
| 146 | #endif | ||
| 147 | |||
| 148 | |||
| 149 | /* This function assumes that there is no multibyte character in | ||
| 150 | current_text, so we can short-cut encoding. */ | ||
| 151 | |||
| 152 | static HGLOBAL | ||
| 153 | convert_to_handle_as_ascii (void) | ||
| 63 | { | 154 | { |
| 64 | BOOL ok = FALSE; | 155 | HGLOBAL htext = NULL; |
| 156 | int nbytes; | ||
| 157 | int truelen; | ||
| 158 | unsigned char *src; | ||
| 159 | unsigned char *dst; | ||
| 65 | 160 | ||
| 66 | if (!NILP (frame)) | 161 | ONTRACE (fprintf (stderr, "convert_to_handle_as_ascii\n")); |
| 67 | CHECK_LIVE_FRAME (frame); | ||
| 68 | 162 | ||
| 69 | BLOCK_INPUT; | 163 | nbytes = SBYTES (current_text) + 1; |
| 164 | src = SDATA (current_text); | ||
| 70 | 165 | ||
| 71 | ok = OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL); | 166 | /* We need to add to the size the number of LF chars where we have |
| 167 | to insert CR chars (the standard CF_TEXT clipboard format uses | ||
| 168 | CRLF line endings, while Emacs uses just LF internally). */ | ||
| 72 | 169 | ||
| 73 | UNBLOCK_INPUT; | 170 | truelen = nbytes + current_num_nls; |
| 171 | |||
| 172 | if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, truelen)) == NULL) | ||
| 173 | return NULL; | ||
| 74 | 174 | ||
| 75 | return (ok ? frame : Qnil); | 175 | if ((dst = (unsigned char *) GlobalLock (htext)) == NULL) |
| 176 | { | ||
| 177 | GlobalFree (htext); | ||
| 178 | return NULL; | ||
| 179 | } | ||
| 180 | |||
| 181 | /* convert to CRLF line endings expected by clipboard */ | ||
| 182 | while (1) | ||
| 183 | { | ||
| 184 | unsigned char *next; | ||
| 185 | /* copy next line or remaining bytes including '\0' */ | ||
| 186 | next = _memccpy (dst, src, '\n', nbytes); | ||
| 187 | if (next) | ||
| 188 | { | ||
| 189 | /* copied one line ending with '\n' */ | ||
| 190 | int copied = next - dst; | ||
| 191 | nbytes -= copied; | ||
| 192 | src += copied; | ||
| 193 | /* insert '\r' before '\n' */ | ||
| 194 | next[-1] = '\r'; | ||
| 195 | next[0] = '\n'; | ||
| 196 | dst = next + 1; | ||
| 197 | } | ||
| 198 | else | ||
| 199 | /* copied remaining partial line -> now finished */ | ||
| 200 | break; | ||
| 201 | } | ||
| 202 | |||
| 203 | GlobalUnlock (htext); | ||
| 204 | |||
| 205 | return htext; | ||
| 76 | } | 206 | } |
| 77 | 207 | ||
| 78 | DEFUN ("w32-empty-clipboard", Fw32_empty_clipboard, | 208 | /* This function assumes that there are multibyte or NUL characters in |
| 79 | Sw32_empty_clipboard, 0, 0, 0, | 209 | current_text, or that we need to construct Unicode. It runs the |
| 80 | doc: /* Empty the clipboard. | 210 | text through the encoding machinery. */ |
| 81 | Assigns ownership of the clipboard to the window which opened it. */) | 211 | |
| 82 | () | 212 | static HGLOBAL |
| 213 | convert_to_handle_as_coded (Lisp_Object coding_system) | ||
| 83 | { | 214 | { |
| 84 | BOOL ok = FALSE; | 215 | HGLOBAL htext = NULL, htext2; |
| 216 | int nbytes; | ||
| 217 | unsigned char *src; | ||
| 218 | unsigned char *dst = NULL; | ||
| 219 | int bufsize; | ||
| 220 | struct coding_system coding; | ||
| 221 | Lisp_Object string = Qnil; | ||
| 222 | |||
| 223 | ONTRACE (fprintf (stderr, "convert_to_handle_as_coded: %s\n", | ||
| 224 | SDATA (SYMBOL_NAME (coding_system)))); | ||
| 225 | |||
| 226 | setup_coding_system (Fcheck_coding_system (coding_system), &coding); | ||
| 227 | coding.src_multibyte = 1; | ||
| 228 | coding.dst_multibyte = 0; | ||
| 229 | /* Need to set COMPOSITION_DISABLED, otherwise Emacs crashes in | ||
| 230 | encode_coding_iso2022 trying to dereference a null pointer. */ | ||
| 231 | coding.composing = COMPOSITION_DISABLED; | ||
| 232 | if (coding.type == coding_type_iso2022) | ||
| 233 | coding.flags |= CODING_FLAG_ISO_SAFE; | ||
| 234 | coding.mode |= CODING_MODE_LAST_BLOCK; | ||
| 235 | /* Force DOS line-ends. */ | ||
| 236 | coding.eol_type = CODING_EOL_CRLF; | ||
| 237 | |||
| 238 | if (SYMBOLP (coding.pre_write_conversion) | ||
| 239 | && !NILP (Ffboundp (coding.pre_write_conversion))) | ||
| 240 | string = run_pre_post_conversion_on_str (current_text, &coding, 1); | ||
| 241 | else | ||
| 242 | string = current_text; | ||
| 243 | |||
| 244 | nbytes = SBYTES (string); | ||
| 245 | src = SDATA (string); | ||
| 85 | 246 | ||
| 86 | BLOCK_INPUT; | 247 | bufsize = encoding_buffer_size (&coding, nbytes) +2; |
| 248 | htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, bufsize); | ||
| 87 | 249 | ||
| 88 | ok = EmptyClipboard (); | 250 | if (htext != NULL) |
| 251 | dst = (unsigned char *) GlobalLock (htext); | ||
| 89 | 252 | ||
| 90 | UNBLOCK_INPUT; | 253 | if (dst != NULL) |
| 254 | { | ||
| 255 | encode_coding (&coding, src, dst, nbytes, bufsize-2); | ||
| 256 | /* Add the string terminator. Add two NULs in case we are | ||
| 257 | producing Unicode here. */ | ||
| 258 | dst[coding.produced] = dst[coding.produced+1] = '\0'; | ||
| 259 | } | ||
| 91 | 260 | ||
| 92 | return (ok ? Qt : Qnil); | 261 | if (dst != NULL) |
| 262 | GlobalUnlock (htext); | ||
| 263 | |||
| 264 | if (htext != NULL) | ||
| 265 | { | ||
| 266 | /* Shrink data block to actual size. */ | ||
| 267 | htext2 = GlobalReAlloc (htext, coding.produced+2, | ||
| 268 | GMEM_MOVEABLE | GMEM_DDESHARE); | ||
| 269 | if (htext2 != NULL) htext = htext2; | ||
| 270 | } | ||
| 271 | |||
| 272 | return htext; | ||
| 93 | } | 273 | } |
| 94 | 274 | ||
| 95 | DEFUN ("w32-close-clipboard", Fw32_close_clipboard, | 275 | static Lisp_Object |
| 96 | Sw32_close_clipboard, 0, 0, 0, | 276 | render (Lisp_Object oformat) |
| 97 | doc: /* Close the clipboard. */) | ||
| 98 | () | ||
| 99 | { | 277 | { |
| 100 | BOOL ok = FALSE; | 278 | HGLOBAL htext = NULL; |
| 279 | UINT format = XFASTINT (oformat); | ||
| 280 | |||
| 281 | ONTRACE (fprintf (stderr, "render\n")); | ||
| 282 | |||
| 283 | if (NILP (current_text)) | ||
| 284 | return Qnil; | ||
| 285 | |||
| 286 | if (current_requires_encoding || format == CF_UNICODETEXT) | ||
| 287 | { | ||
| 288 | if (format == current_clipboard_type) | ||
| 289 | htext = convert_to_handle_as_coded (current_coding_system); | ||
| 290 | else | ||
| 291 | switch (format) | ||
| 292 | { | ||
| 293 | case CF_UNICODETEXT: | ||
| 294 | htext = convert_to_handle_as_coded (QUNICODE); | ||
| 295 | break; | ||
| 296 | case CF_TEXT: | ||
| 297 | case CF_OEMTEXT: | ||
| 298 | { | ||
| 299 | Lisp_Object cs; | ||
| 300 | cs = coding_from_cp (cp_from_locale (current_lcid, format)); | ||
| 301 | htext = convert_to_handle_as_coded (cs); | ||
| 302 | break; | ||
| 303 | } | ||
| 304 | } | ||
| 305 | } | ||
| 306 | else | ||
| 307 | htext = convert_to_handle_as_ascii (); | ||
| 308 | |||
| 309 | ONTRACE (fprintf (stderr, "render: htext = 0x%08X\n", (unsigned) htext)); | ||
| 310 | |||
| 311 | if (htext == NULL) | ||
| 312 | return Qnil; | ||
| 313 | |||
| 314 | if (SetClipboardData (format, htext) == NULL) | ||
| 315 | { | ||
| 316 | GlobalFree(htext); | ||
| 317 | return Qnil; | ||
| 318 | } | ||
| 319 | |||
| 320 | return Qt; | ||
| 321 | } | ||
| 322 | |||
| 323 | static Lisp_Object | ||
| 324 | render_locale (void) | ||
| 325 | { | ||
| 326 | HANDLE hlocale = NULL; | ||
| 327 | LCID * lcid_ptr; | ||
| 328 | |||
| 329 | ONTRACE (fprintf (stderr, "render_locale\n")); | ||
| 330 | |||
| 331 | if (current_lcid == LOCALE_NEUTRAL || current_lcid == DEFAULT_LCID) | ||
| 332 | return Qt; | ||
| 333 | |||
| 334 | hlocale = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, sizeof (current_lcid)); | ||
| 335 | if (hlocale == NULL) | ||
| 336 | return Qnil; | ||
| 337 | |||
| 338 | if ((lcid_ptr = (LCID *) GlobalLock (hlocale)) == NULL) | ||
| 339 | { | ||
| 340 | GlobalFree(hlocale); | ||
| 341 | return Qnil; | ||
| 342 | } | ||
| 343 | |||
| 344 | *lcid_ptr = current_lcid; | ||
| 345 | GlobalUnlock (hlocale); | ||
| 346 | |||
| 347 | if (SetClipboardData (CF_LOCALE, hlocale) == NULL) | ||
| 348 | { | ||
| 349 | GlobalFree(hlocale); | ||
| 350 | return Qnil; | ||
| 351 | } | ||
| 352 | |||
| 353 | return Qt; | ||
| 354 | } | ||
| 355 | |||
| 356 | /* At the end of the program, we want to ensure that our clipboard | ||
| 357 | data survives us. This code will do that. */ | ||
| 358 | |||
| 359 | static Lisp_Object | ||
| 360 | render_all (void) | ||
| 361 | { | ||
| 362 | ONTRACE (fprintf (stderr, "render_all\n")); | ||
| 363 | |||
| 364 | /* According to the docs we should not call OpenClipboard() here, | ||
| 365 | but testing on W2K and working code in other projects shows that | ||
| 366 | it is actually necessary. */ | ||
| 367 | |||
| 368 | OpenClipboard (NULL); | ||
| 369 | |||
| 370 | /* There is no usefull means to report errors here, there are none | ||
| 371 | expected anyway, and even if there were errors, they wouldn't do | ||
| 372 | any harm. So we just go ahead and do what has to be done without | ||
| 373 | bothering with error handling. */ | ||
| 374 | |||
| 375 | ++modifying_clipboard; | ||
| 376 | EmptyClipboard (); | ||
| 377 | --modifying_clipboard; | ||
| 378 | |||
| 379 | /* For text formats that we don't render here, the OS can use its | ||
| 380 | own translation rules instead, so we don't really need to offer | ||
| 381 | everything. To minimize memory consumption we cover three | ||
| 382 | possible situations based on our primary format as detected from | ||
| 383 | selection-coding-system (see setup_config()): | ||
| 384 | |||
| 385 | - Post CF_TEXT only. Let the OS convert to CF_OEMTEXT and the OS | ||
| 386 | (on NT) or the application (on 9x/Me) convert to | ||
| 387 | CF_UNICODETEXT. | ||
| 388 | |||
| 389 | - Post CF_OEMTEXT only. Similar automatic conversions happen as | ||
| 390 | for CF_TEXT. | ||
| 391 | |||
| 392 | - Post CF_UNICODETEXT + CF_TEXT. 9x itself ignores | ||
| 393 | CF_UNICODETEXT, even though some applications can still handle | ||
| 394 | it. | ||
| 395 | |||
| 396 | Note 1: We render the less capable CF_TEXT *before* the more | ||
| 397 | capable CF_UNICODETEXT, to prevent clobbering through automatic | ||
| 398 | conversions, just in case. | ||
| 399 | |||
| 400 | Note 2: We could check os_subtype here and only render the | ||
| 401 | additional CF_TEXT on 9x/Me. But OTOH with | ||
| 402 | current_clipboard_type == CF_UNICODETEXT we don't involve the | ||
| 403 | automatic conversions anywhere else, so to get consistent | ||
| 404 | results, we probably don't want to rely on it here either. */ | ||
| 405 | |||
| 406 | render_locale(); | ||
| 407 | |||
| 408 | if (current_clipboard_type == CF_UNICODETEXT) | ||
| 409 | render (make_number (CF_TEXT)); | ||
| 410 | render (make_number (current_clipboard_type)); | ||
| 411 | |||
| 412 | CloseClipboard (); | ||
| 413 | |||
| 414 | return Qnil; | ||
| 415 | } | ||
| 416 | |||
| 417 | static void | ||
| 418 | run_protected (Lisp_Object (*code) (), Lisp_Object arg) | ||
| 419 | { | ||
| 420 | /* FIXME: This works but it doesn't feel right. Too much fiddling | ||
| 421 | with global variables and calling strange looking functions. Is | ||
| 422 | this really the right way to run Lisp callbacks? */ | ||
| 423 | |||
| 424 | extern int waiting_for_input; | ||
| 425 | int owfi; | ||
| 101 | 426 | ||
| 102 | BLOCK_INPUT; | 427 | BLOCK_INPUT; |
| 103 | 428 | ||
| 104 | ok = CloseClipboard (); | 429 | /* Fsignal calls abort() if it sees that waiting_for_input is |
| 430 | set. */ | ||
| 431 | owfi = waiting_for_input; | ||
| 432 | waiting_for_input = 0; | ||
| 433 | |||
| 434 | internal_condition_case_1 (code, arg, Qt, lisp_error_handler); | ||
| 435 | |||
| 436 | waiting_for_input = owfi; | ||
| 105 | 437 | ||
| 106 | UNBLOCK_INPUT; | 438 | UNBLOCK_INPUT; |
| 439 | } | ||
| 107 | 440 | ||
| 108 | return (ok ? Qt : Qnil); | 441 | static Lisp_Object |
| 442 | lisp_error_handler (Lisp_Object error) | ||
| 443 | { | ||
| 444 | Vsignaling_function = Qnil; | ||
| 445 | cmd_error_internal (error, "Error in delayed clipboard rendering: "); | ||
| 446 | Vinhibit_quit = Qt; | ||
| 447 | return Qt; | ||
| 448 | } | ||
| 449 | |||
| 450 | |||
| 451 | static LRESULT CALLBACK | ||
| 452 | owner_callback (HWND win, UINT msg, WPARAM wp, LPARAM lp) | ||
| 453 | { | ||
| 454 | switch (msg) | ||
| 455 | { | ||
| 456 | case WM_RENDERFORMAT: | ||
| 457 | ONTRACE (fprintf (stderr, "WM_RENDERFORMAT\n")); | ||
| 458 | run_protected (render, make_number (wp)); | ||
| 459 | return 0; | ||
| 460 | |||
| 461 | case WM_RENDERALLFORMATS: | ||
| 462 | ONTRACE (fprintf (stderr, "WM_RENDERALLFORMATS\n")); | ||
| 463 | run_protected (render_all, Qnil); | ||
| 464 | return 0; | ||
| 465 | |||
| 466 | case WM_DESTROYCLIPBOARD: | ||
| 467 | if (!modifying_clipboard) | ||
| 468 | { | ||
| 469 | ONTRACE (fprintf (stderr, "WM_DESTROYCLIPBOARD (other)\n")); | ||
| 470 | current_text = Qnil; | ||
| 471 | current_coding_system = Qnil; | ||
| 472 | } | ||
| 473 | else | ||
| 474 | { | ||
| 475 | ONTRACE (fprintf (stderr, "WM_DESTROYCLIPBOARD (self)\n")); | ||
| 476 | } | ||
| 477 | return 0; | ||
| 478 | |||
| 479 | case WM_DESTROY: | ||
| 480 | if (win == clipboard_owner) | ||
| 481 | clipboard_owner = NULL; | ||
| 482 | break; | ||
| 483 | } | ||
| 484 | |||
| 485 | return DefWindowProc (win, msg, wp, lp); | ||
| 486 | } | ||
| 487 | |||
| 488 | static HWND | ||
| 489 | create_owner (void) | ||
| 490 | { | ||
| 491 | static const char CLASSNAME[] = "Emacs Clipboard"; | ||
| 492 | WNDCLASS wc; | ||
| 493 | |||
| 494 | memset (&wc, 0, sizeof (wc)); | ||
| 495 | wc.lpszClassName = CLASSNAME; | ||
| 496 | wc.lpfnWndProc = owner_callback; | ||
| 497 | RegisterClass (&wc); | ||
| 498 | |||
| 499 | return CreateWindow (CLASSNAME, CLASSNAME, 0, 0, 0, 0, 0, NULL, NULL, | ||
| 500 | NULL, NULL); | ||
| 501 | } | ||
| 502 | |||
| 503 | /* Called on exit by term_ntproc() in w32.c */ | ||
| 504 | |||
| 505 | void | ||
| 506 | term_w32select (void) | ||
| 507 | { | ||
| 508 | /* This is needed to trigger WM_RENDERALLFORMATS. */ | ||
| 509 | if (clipboard_owner != NULL) | ||
| 510 | DestroyWindow (clipboard_owner); | ||
| 511 | } | ||
| 512 | |||
| 513 | static void | ||
| 514 | setup_config (void) | ||
| 515 | { | ||
| 516 | const char *coding_name; | ||
| 517 | const char *cp; | ||
| 518 | char *end; | ||
| 519 | int slen; | ||
| 520 | Lisp_Object new_coding_system; | ||
| 521 | |||
| 522 | CHECK_SYMBOL (Vselection_coding_system); | ||
| 523 | |||
| 524 | /* Check if we have it cached */ | ||
| 525 | new_coding_system = NILP (Vnext_selection_coding_system) ? | ||
| 526 | Vselection_coding_system : Vnext_selection_coding_system; | ||
| 527 | if (!NILP (cfg_coding_system) | ||
| 528 | && EQ (cfg_coding_system, new_coding_system)) | ||
| 529 | return; | ||
| 530 | cfg_coding_system = new_coding_system; | ||
| 531 | |||
| 532 | /* Set some sensible fallbacks */ | ||
| 533 | cfg_codepage = ANSICP; | ||
| 534 | cfg_lcid = LOCALE_NEUTRAL; | ||
| 535 | cfg_clipboard_type = CF_TEXT; | ||
| 536 | |||
| 537 | /* Interpret the coding system symbol name */ | ||
| 538 | coding_name = SDATA (SYMBOL_NAME (cfg_coding_system)); | ||
| 539 | |||
| 540 | /* "(.*-)?utf-16.*" -> CF_UNICODETEXT */ | ||
| 541 | cp = strstr (coding_name, "utf-16"); | ||
| 542 | if (cp != NULL && (cp == coding_name || cp[-1] == '-')) | ||
| 543 | { | ||
| 544 | cfg_clipboard_type = CF_UNICODETEXT; | ||
| 545 | return; | ||
| 546 | } | ||
| 547 | |||
| 548 | /* "cp[0-9]+.*" or "windows-[0-9]+.*" -> CF_TEXT or CF_OEMTEXT */ | ||
| 549 | slen = strlen (coding_name); | ||
| 550 | if (slen >= 4 && coding_name[0] == 'c' && coding_name[1] == 'p') | ||
| 551 | cp = coding_name + 2; | ||
| 552 | else if (slen >= 10 && memcmp (coding_name, "windows-", 8) == 0) | ||
| 553 | cp = coding_name + 8; | ||
| 554 | else | ||
| 555 | return; | ||
| 556 | |||
| 557 | end = (char*)cp; | ||
| 558 | cfg_codepage = strtol (cp, &end, 10); | ||
| 559 | |||
| 560 | /* Error return from strtol() or number of digits < 2 -> Restore the | ||
| 561 | default and drop it. */ | ||
| 562 | if (cfg_codepage == 0 || (end-cp) < 2 ) | ||
| 563 | { | ||
| 564 | cfg_codepage = ANSICP; | ||
| 565 | return; | ||
| 566 | } | ||
| 567 | |||
| 568 | /* Is it the currently active system default? */ | ||
| 569 | if (cfg_codepage == ANSICP) | ||
| 570 | { | ||
| 571 | /* cfg_clipboard_type = CF_TEXT; */ | ||
| 572 | return; | ||
| 573 | } | ||
| 574 | if (cfg_codepage == OEMCP) | ||
| 575 | { | ||
| 576 | cfg_clipboard_type = CF_OEMTEXT; | ||
| 577 | return; | ||
| 578 | } | ||
| 579 | |||
| 580 | /* Else determine a suitable locale the hard way. */ | ||
| 581 | EnumSystemLocales (enum_locale_callback, LCID_INSTALLED); | ||
| 582 | } | ||
| 583 | |||
| 584 | static BOOL WINAPI | ||
| 585 | enum_locale_callback (/*const*/ char* loc_string) | ||
| 586 | { | ||
| 587 | LCID lcid; | ||
| 588 | UINT codepage; | ||
| 589 | |||
| 590 | lcid = strtoul (loc_string, NULL, 16); | ||
| 591 | |||
| 592 | /* Is the wanted codepage the "ANSI" codepage for this locale? */ | ||
| 593 | codepage = cp_from_locale (lcid, CF_TEXT); | ||
| 594 | if (codepage == cfg_codepage) | ||
| 595 | { | ||
| 596 | cfg_lcid = lcid; | ||
| 597 | cfg_clipboard_type = CF_TEXT; | ||
| 598 | return FALSE; /* Stop enumeration */ | ||
| 599 | } | ||
| 600 | |||
| 601 | /* Is the wanted codepage the OEM codepage for this locale? */ | ||
| 602 | codepage = cp_from_locale (lcid, CF_OEMTEXT); | ||
| 603 | if (codepage == cfg_codepage) | ||
| 604 | { | ||
| 605 | cfg_lcid = lcid; | ||
| 606 | cfg_clipboard_type = CF_OEMTEXT; | ||
| 607 | return FALSE; /* Stop enumeration */ | ||
| 608 | } | ||
| 609 | |||
| 610 | return TRUE; /* Continue enumeration */ | ||
| 611 | } | ||
| 612 | |||
| 613 | static UINT | ||
| 614 | cp_from_locale (LCID lcid, UINT format) | ||
| 615 | { | ||
| 616 | char buffer[20] = ""; | ||
| 617 | UINT variant, cp; | ||
| 618 | |||
| 619 | variant = | ||
| 620 | format == CF_TEXT ? LOCALE_IDEFAULTANSICODEPAGE : LOCALE_IDEFAULTCODEPAGE; | ||
| 621 | |||
| 622 | GetLocaleInfo (lcid, variant, buffer, sizeof (buffer)); | ||
| 623 | cp = strtoul (buffer, NULL, 10); | ||
| 624 | |||
| 625 | if (cp == CP_ACP) | ||
| 626 | return ANSICP; | ||
| 627 | else if (cp == CP_OEMCP) | ||
| 628 | return OEMCP; | ||
| 629 | else | ||
| 630 | return cp; | ||
| 631 | } | ||
| 632 | |||
| 633 | static Lisp_Object | ||
| 634 | coding_from_cp (UINT codepage) | ||
| 635 | { | ||
| 636 | char buffer[30]; | ||
| 637 | sprintf (buffer, "cp%d-dos", (int) codepage); | ||
| 638 | return intern (buffer); | ||
| 639 | /* We don't need to check that this coding system exists right here, | ||
| 640 | because that is done when the coding system is actually | ||
| 641 | instantiated, i.e. it is passed through Fcheck_coding_system() | ||
| 642 | there. */ | ||
| 109 | } | 643 | } |
| 110 | 644 | ||
| 111 | #endif | ||
| 112 | 645 | ||
| 113 | DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, | 646 | DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, |
| 114 | Sw32_set_clipboard_data, 1, 2, 0, | 647 | Sw32_set_clipboard_data, 1, 2, 0, |
| 115 | doc: /* This sets the clipboard data to the given text. */) | 648 | doc: /* This sets the clipboard data to the given text. */) |
| 116 | (string, frame) | 649 | (string, ignored) |
| 117 | Lisp_Object string, frame; | 650 | Lisp_Object string, ignored; |
| 118 | { | 651 | { |
| 119 | BOOL ok = TRUE; | 652 | BOOL ok = TRUE; |
| 120 | HANDLE htext; | ||
| 121 | int nbytes; | 653 | int nbytes; |
| 122 | int truelen, nlines = 0; | ||
| 123 | unsigned char *src; | 654 | unsigned char *src; |
| 124 | unsigned char *dst; | 655 | unsigned char *dst; |
| 656 | unsigned char *end; | ||
| 657 | |||
| 658 | /* This parameter used to be the current frame, but we don't use | ||
| 659 | that any more. */ | ||
| 660 | (void) ignored; | ||
| 125 | 661 | ||
| 126 | CHECK_STRING (string); | 662 | CHECK_STRING (string); |
| 127 | 663 | ||
| 128 | if (!NILP (frame)) | 664 | setup_config (); |
| 129 | CHECK_LIVE_FRAME (frame); | ||
| 130 | 665 | ||
| 666 | current_text = string; | ||
| 667 | current_coding_system = cfg_coding_system; | ||
| 668 | current_clipboard_type = cfg_clipboard_type; | ||
| 669 | current_lcid = cfg_lcid; | ||
| 670 | current_num_nls = 0; | ||
| 671 | current_requires_encoding = 0; | ||
| 672 | |||
| 131 | BLOCK_INPUT; | 673 | BLOCK_INPUT; |
| 132 | 674 | ||
| 133 | /* Include the terminating NULL character in the source of | 675 | /* Check for non-ASCII characters. While we are at it, count the |
| 134 | conversion. */ | 676 | number of LFs, so we know how many CRs we will have to add later |
| 135 | nbytes = SBYTES (string) + 1; | 677 | (just in the case where we can use our internal ASCII rendering, |
| 678 | see code and comment in convert_to_handle_as_ascii() above). */ | ||
| 679 | nbytes = SBYTES (string); | ||
| 136 | src = SDATA (string); | 680 | src = SDATA (string); |
| 137 | dst = src; | ||
| 138 | 681 | ||
| 139 | /* We need to know how many lines there are, since we need CRLF line | 682 | for (dst = src, end = src+nbytes; dst < end; dst++) |
| 140 | termination for compatibility with other Windows Programs. | ||
| 141 | avoid using strchr because it recomputes the length every time */ | ||
| 142 | while ((dst = memchr (dst, '\n', nbytes - (dst - src))) != NULL) | ||
| 143 | { | 683 | { |
| 144 | nlines++; | 684 | if (*dst == '\n') |
| 145 | dst++; | 685 | current_num_nls++; |
| 686 | else if (*dst >= 0x80 || *dst == 0) | ||
| 687 | { | ||
| 688 | current_requires_encoding = 1; | ||
| 689 | break; | ||
| 690 | } | ||
| 146 | } | 691 | } |
| 147 | 692 | ||
| 148 | { | 693 | if (!current_requires_encoding) |
| 149 | /* Since we are now handling multilingual text, we must consider | 694 | { |
| 150 | encoding text for the clipboard. */ | 695 | /* If all we have is ASCII we don't need to pretend we offer |
| 151 | int charset_info = find_charset_in_text (src, SCHARS (string), | 696 | anything fancy. */ |
| 152 | nbytes, NULL, Qnil); | 697 | current_coding_system = Qraw_text; |
| 153 | 698 | current_clipboard_type = CF_TEXT; | |
| 154 | if (charset_info == 0) | 699 | current_lcid = LOCALE_NEUTRAL; |
| 155 | { | 700 | } |
| 156 | /* No multibyte character in OBJ. We need not encode it. */ | ||
| 157 | |||
| 158 | /* Need to know final size after CR chars are inserted (the | ||
| 159 | standard CF_TEXT clipboard format uses CRLF line endings, | ||
| 160 | while Emacs uses just LF internally). */ | ||
| 161 | |||
| 162 | truelen = nbytes + nlines; | ||
| 163 | |||
| 164 | if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, truelen)) == NULL) | ||
| 165 | goto error; | ||
| 166 | |||
| 167 | if ((dst = (unsigned char *) GlobalLock (htext)) == NULL) | ||
| 168 | goto error; | ||
| 169 | |||
| 170 | /* convert to CRLF line endings expected by clipboard */ | ||
| 171 | while (1) | ||
| 172 | { | ||
| 173 | unsigned char *next; | ||
| 174 | /* copy next line or remaining bytes including '\0' */ | ||
| 175 | next = _memccpy (dst, src, '\n', nbytes); | ||
| 176 | if (next) | ||
| 177 | { | ||
| 178 | /* copied one line ending with '\n' */ | ||
| 179 | int copied = next - dst; | ||
| 180 | nbytes -= copied; | ||
| 181 | src += copied; | ||
| 182 | /* insert '\r' before '\n' */ | ||
| 183 | next[-1] = '\r'; | ||
| 184 | next[0] = '\n'; | ||
| 185 | dst = next + 1; | ||
| 186 | } | ||
| 187 | else | ||
| 188 | /* copied remaining partial line -> now finished */ | ||
| 189 | break; | ||
| 190 | } | ||
| 191 | |||
| 192 | GlobalUnlock (htext); | ||
| 193 | 701 | ||
| 194 | Vlast_coding_system_used = Qraw_text; | 702 | if (!OpenClipboard (clipboard_owner)) |
| 195 | } | 703 | goto error; |
| 196 | else | ||
| 197 | { | ||
| 198 | /* We must encode contents of OBJ to the selection coding | ||
| 199 | system. */ | ||
| 200 | int bufsize; | ||
| 201 | struct coding_system coding; | ||
| 202 | HANDLE htext2; | ||
| 203 | |||
| 204 | if (NILP (Vnext_selection_coding_system)) | ||
| 205 | Vnext_selection_coding_system = Vselection_coding_system; | ||
| 206 | setup_coding_system | ||
| 207 | (Fcheck_coding_system (Vnext_selection_coding_system), &coding); | ||
| 208 | if (SYMBOLP (coding.pre_write_conversion) | ||
| 209 | && !NILP (Ffboundp (coding.pre_write_conversion))) | ||
| 210 | { | ||
| 211 | string = run_pre_post_conversion_on_str (string, &coding, 1); | ||
| 212 | src = SDATA (string); | ||
| 213 | /* Include the terminating NULL character in the source of | ||
| 214 | conversion. */ | ||
| 215 | nbytes = SBYTES (string) + 1; | ||
| 216 | } | ||
| 217 | coding.src_multibyte = 1; | ||
| 218 | coding.dst_multibyte = 0; | ||
| 219 | /* Need to set COMPOSITION_DISABLED, otherwise Emacs crashes in | ||
| 220 | encode_coding_iso2022 trying to dereference a null pointer. */ | ||
| 221 | coding.composing = COMPOSITION_DISABLED; | ||
| 222 | if (coding.type == coding_type_iso2022) | ||
| 223 | coding.flags |= CODING_FLAG_ISO_SAFE; | ||
| 224 | Vnext_selection_coding_system = Qnil; | ||
| 225 | coding.mode |= CODING_MODE_LAST_BLOCK; | ||
| 226 | bufsize = encoding_buffer_size (&coding, nbytes); | ||
| 227 | if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, bufsize)) == NULL) | ||
| 228 | goto error; | ||
| 229 | if ((dst = (unsigned char *) GlobalLock (htext)) == NULL) | ||
| 230 | goto error; | ||
| 231 | encode_coding (&coding, src, dst, nbytes, bufsize); | ||
| 232 | Vlast_coding_system_used = coding.symbol; | ||
| 233 | 704 | ||
| 234 | /* If clipboard sequence numbers are not supported, keep a copy for | 705 | ++modifying_clipboard; |
| 235 | later comparison. */ | 706 | ok = EmptyClipboard (); |
| 236 | if (!clipboard_sequence_fn) | 707 | --modifying_clipboard; |
| 237 | { | ||
| 238 | /* Stash away the data we are about to put into the | ||
| 239 | clipboard, so we could later check inside | ||
| 240 | Fw32_get_clipboard_data whether the clipboard still | ||
| 241 | holds our data. */ | ||
| 242 | if (clipboard_storage_size < coding.produced) | ||
| 243 | { | ||
| 244 | clipboard_storage_size = coding.produced + 100; | ||
| 245 | last_clipboard_text = (char *) xrealloc (last_clipboard_text, | ||
| 246 | clipboard_storage_size); | ||
| 247 | } | ||
| 248 | if (last_clipboard_text) | ||
| 249 | memcpy (last_clipboard_text, dst, coding.produced); | ||
| 250 | } | ||
| 251 | 708 | ||
| 252 | GlobalUnlock (htext); | 709 | /* If we have something non-ASCII we may want to set a locale. We |
| 710 | do that directly (non-delayed), as it's just a small bit. */ | ||
| 711 | if (ok) | ||
| 712 | ok = !NILP(render_locale()); | ||
| 253 | 713 | ||
| 254 | /* Shrink data block to actual size. */ | 714 | if (ok) |
| 255 | htext2 = GlobalReAlloc (htext, coding.produced, | 715 | { |
| 256 | GMEM_MOVEABLE | GMEM_DDESHARE); | 716 | if (clipboard_owner == NULL) |
| 257 | if (htext2 != NULL) htext = htext2; | 717 | { |
| 258 | } | 718 | /* If for some reason we don't have a clipboard_owner, we |
| 259 | } | 719 | just set the text format as chosen by the configuration |
| 720 | and than forget about the whole thing. */ | ||
| 721 | ok = !NILP(render (make_number (current_clipboard_type))); | ||
| 722 | current_text = Qnil; | ||
| 723 | current_coding_system = Qnil; | ||
| 724 | } | ||
| 725 | else | ||
| 726 | { | ||
| 727 | /* Advertise all supported formats so that whatever the | ||
| 728 | requester chooses, only one encoding step needs to be | ||
| 729 | made. This is intentionally different from what we do in | ||
| 730 | the handler for WM_RENDERALLFORMATS. */ | ||
| 731 | SetClipboardData (CF_UNICODETEXT, NULL); | ||
| 732 | SetClipboardData (CF_TEXT, NULL); | ||
| 733 | SetClipboardData (CF_OEMTEXT, NULL); | ||
| 734 | } | ||
| 735 | } | ||
| 260 | 736 | ||
| 261 | if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL)) | 737 | CloseClipboard (); |
| 262 | goto error; | ||
| 263 | 738 | ||
| 264 | ok = EmptyClipboard () && SetClipboardData (CF_TEXT, htext); | 739 | /* With delayed rendering we haven't really "used" this coding |
| 740 | system yet, and it's even unclear if we ever will. But this is a | ||
| 741 | way to tell the upper level what we *would* use under ideal | ||
| 742 | circumstances. | ||
| 265 | 743 | ||
| 266 | CloseClipboard (); | 744 | We don't signal the actually used coding-system later when we |
| 745 | finally render, because that can happen at any time and we don't | ||
| 746 | want to disturb the "foreground" action. */ | ||
| 747 | if (ok) | ||
| 748 | Vlast_coding_system_used = current_coding_system; | ||
| 267 | 749 | ||
| 268 | /* Common sense says to read the sequence number inside the | 750 | Vnext_selection_coding_system = Qnil; |
| 269 | OpenClipboard/ CloseClipboard block to avoid race conditions | ||
| 270 | where another app puts something on the clipboard straight after | ||
| 271 | us. But experience suggests that the sequence number from the | ||
| 272 | SetClipboardData is not allocated until we close the clipboard! | ||
| 273 | Since clipboard operations are normally user-driven, the race | ||
| 274 | condition is probably not going to really happen. */ | ||
| 275 | if (clipboard_sequence_fn) | ||
| 276 | last_clipboard_sequence_number = clipboard_sequence_fn (); | ||
| 277 | 751 | ||
| 278 | if (ok) goto done; | 752 | if (ok) goto done; |
| 279 | 753 | ||
| 280 | error: | 754 | error: |
| 281 | 755 | ||
| 282 | ok = FALSE; | 756 | ok = FALSE; |
| 283 | if (htext) GlobalFree (htext); | 757 | current_text = Qnil; |
| 284 | if (last_clipboard_text) | 758 | current_coding_system = Qnil; |
| 285 | *last_clipboard_text = '\0'; | ||
| 286 | |||
| 287 | last_clipboard_sequence_number = 0; | ||
| 288 | 759 | ||
| 289 | done: | 760 | done: |
| 290 | UNBLOCK_INPUT; | 761 | UNBLOCK_INPUT; |
| @@ -292,24 +763,52 @@ DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, | |||
| 292 | return (ok ? string : Qnil); | 763 | return (ok ? string : Qnil); |
| 293 | } | 764 | } |
| 294 | 765 | ||
| 766 | |||
| 295 | DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, | 767 | DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, |
| 296 | Sw32_get_clipboard_data, 0, 1, 0, | 768 | Sw32_get_clipboard_data, 0, 1, 0, |
| 297 | doc: /* This gets the clipboard data in text format. */) | 769 | doc: /* This gets the clipboard data in text format. */) |
| 298 | (frame) | 770 | (ignored) |
| 299 | Lisp_Object frame; | 771 | Lisp_Object ignored; |
| 300 | { | 772 | { |
| 301 | HANDLE htext; | 773 | HGLOBAL htext; |
| 302 | Lisp_Object ret = Qnil; | 774 | Lisp_Object ret = Qnil; |
| 775 | UINT actual_clipboard_type; | ||
| 776 | int use_configured_coding_system = 1; | ||
| 777 | |||
| 778 | /* This parameter used to be the current frame, but we don't use | ||
| 779 | that any more. */ | ||
| 780 | (void) ignored; | ||
| 303 | 781 | ||
| 304 | if (!NILP (frame)) | 782 | /* Don't pass our own text from the clipboard (which might be |
| 305 | CHECK_LIVE_FRAME (frame); | 783 | troublesome if the killed text includes null characters). */ |
| 784 | if (!NILP (current_text)) | ||
| 785 | return ret; | ||
| 786 | |||
| 787 | setup_config (); | ||
| 788 | actual_clipboard_type = cfg_clipboard_type; | ||
| 306 | 789 | ||
| 307 | BLOCK_INPUT; | 790 | BLOCK_INPUT; |
| 308 | 791 | ||
| 309 | if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL)) | 792 | if (!OpenClipboard (clipboard_owner)) |
| 310 | goto done; | 793 | goto done; |
| 311 | 794 | ||
| 312 | if ((htext = GetClipboardData (CF_TEXT)) == NULL) | 795 | if ((htext = GetClipboardData (actual_clipboard_type)) == NULL) |
| 796 | { | ||
| 797 | /* If we want CF_UNICODETEXT but can't get it, the current | ||
| 798 | coding system is useless. OTOH we can still try and decode | ||
| 799 | CF_TEXT based on the locale that the system gives us and that | ||
| 800 | we get down below. */ | ||
| 801 | if (actual_clipboard_type == CF_UNICODETEXT) | ||
| 802 | { | ||
| 803 | htext = GetClipboardData (CF_TEXT); | ||
| 804 | if (htext != NULL) | ||
| 805 | { | ||
| 806 | actual_clipboard_type = CF_TEXT; | ||
| 807 | use_configured_coding_system = 0; | ||
| 808 | } | ||
| 809 | } | ||
| 810 | } | ||
| 811 | if (htext == NULL) | ||
| 313 | goto closeclip; | 812 | goto closeclip; |
| 314 | 813 | ||
| 315 | { | 814 | { |
| @@ -322,53 +821,107 @@ DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, | |||
| 322 | if ((src = (unsigned char *) GlobalLock (htext)) == NULL) | 821 | if ((src = (unsigned char *) GlobalLock (htext)) == NULL) |
| 323 | goto closeclip; | 822 | goto closeclip; |
| 324 | 823 | ||
| 325 | nbytes = strlen (src); | 824 | /* If the clipboard data contains any non-ascii code, we need to |
| 326 | 825 | decode it with a coding system. */ | |
| 327 | /* If the text in clipboard is identical to what we put there | 826 | if (actual_clipboard_type == CF_UNICODETEXT) |
| 328 | last time w32_set_clipboard_data was called, pretend there's no | 827 | { |
| 329 | data in the clipboard. This is so we don't pass our own text | 828 | nbytes = lstrlenW ((WCHAR *)src) * 2; |
| 330 | from the clipboard (which might be troublesome if the killed | 829 | require_decoding = 1; |
| 331 | text includes null characters). */ | 830 | } |
| 332 | if ((clipboard_sequence_fn | 831 | else |
| 333 | && clipboard_sequence_fn () == last_clipboard_sequence_number) | 832 | { |
| 334 | || (last_clipboard_text | 833 | int i; |
| 335 | && clipboard_storage_size >= nbytes | ||
| 336 | && memcmp(last_clipboard_text, src, nbytes) == 0)) | ||
| 337 | goto closeclip; | ||
| 338 | 834 | ||
| 339 | { | 835 | nbytes = strlen (src); |
| 340 | /* If the clipboard data contains any non-ascii code, we | ||
| 341 | need to decode it. */ | ||
| 342 | int i; | ||
| 343 | 836 | ||
| 344 | for (i = 0; i < nbytes; i++) | 837 | for (i = 0; i < nbytes; i++) |
| 345 | { | 838 | { |
| 346 | if (src[i] >= 0x80) | 839 | if (src[i] >= 0x80) |
| 347 | { | 840 | { |
| 348 | require_decoding = 1; | 841 | require_decoding = 1; |
| 349 | break; | 842 | break; |
| 350 | } | 843 | } |
| 351 | } | 844 | } |
| 352 | } | 845 | } |
| 353 | 846 | ||
| 354 | if (require_decoding) | 847 | if (require_decoding) |
| 355 | { | 848 | { |
| 356 | int bufsize; | 849 | int bufsize; |
| 357 | unsigned char *buf; | 850 | unsigned char *buf; |
| 358 | struct coding_system coding; | 851 | struct coding_system coding; |
| 852 | Lisp_Object coding_system = Qnil; | ||
| 853 | |||
| 854 | /* `next-selection-coding-system' should override everything, | ||
| 855 | even when the locale passed by the system disagrees. The | ||
| 856 | only exception is when `next-selection-coding-system' | ||
| 857 | requested CF_UNICODETEXT and we couldn't get that. */ | ||
| 858 | if (use_configured_coding_system | ||
| 859 | && !NILP (Vnext_selection_coding_system)) | ||
| 860 | coding_system = Vnext_selection_coding_system; | ||
| 861 | |||
| 862 | /* If we have CF_TEXT or CF_OEMTEXT, we want to check out | ||
| 863 | CF_LOCALE, too. */ | ||
| 864 | else if (actual_clipboard_type != CF_UNICODETEXT) | ||
| 865 | { | ||
| 866 | HGLOBAL hlocale; | ||
| 867 | LCID lcid = DEFAULT_LCID; | ||
| 868 | UINT cp; | ||
| 869 | |||
| 870 | /* Documentation says that the OS always generates | ||
| 871 | CF_LOCALE info automatically, so the locale handle | ||
| 872 | should always be present. Fact is that this is not | ||
| 873 | always true on 9x ;-(. */ | ||
| 874 | hlocale = GetClipboardData (CF_LOCALE); | ||
| 875 | if (hlocale != NULL) | ||
| 876 | { | ||
| 877 | const LCID * lcid_ptr; | ||
| 878 | lcid_ptr = (const LCID *) GlobalLock (hlocale); | ||
| 879 | if (lcid_ptr != NULL) | ||
| 880 | { | ||
| 881 | lcid = *lcid_ptr; | ||
| 882 | GlobalUnlock (hlocale); | ||
| 883 | } | ||
| 884 | |||
| 885 | /* 9x has garbage as the sort order (to be exact there | ||
| 886 | is another instance of the language id in the upper | ||
| 887 | word). We don't care about sort order anyway, so | ||
| 888 | we just filter out the unneeded mis-information to | ||
| 889 | avoid irritations. */ | ||
| 890 | lcid = MAKELCID (LANGIDFROMLCID (lcid), SORT_DEFAULT); | ||
| 891 | } | ||
| 892 | |||
| 893 | /* If we are using fallback from CF_UNICODETEXT, we can't | ||
| 894 | use the configured coding system. Also we don't want | ||
| 895 | to use it, if the system has supplied us with a locale | ||
| 896 | and it is not just the system default. */ | ||
| 897 | if (!use_configured_coding_system || lcid != DEFAULT_LCID) | ||
| 898 | { | ||
| 899 | cp = cp_from_locale (lcid, actual_clipboard_type); | ||
| 900 | /* If it's just our current standard setting anyway, | ||
| 901 | use the coding system that the user has selected. | ||
| 902 | Otherwise create a new spec to match the locale | ||
| 903 | that was specified by the other side or the | ||
| 904 | system. */ | ||
| 905 | if (!use_configured_coding_system || cp != cfg_codepage) | ||
| 906 | coding_system = coding_from_cp (cp); | ||
| 907 | } | ||
| 908 | } | ||
| 909 | |||
| 910 | if (NILP (coding_system)) | ||
| 911 | coding_system = Vselection_coding_system; | ||
| 912 | Vnext_selection_coding_system = Qnil; | ||
| 359 | 913 | ||
| 360 | if (NILP (Vnext_selection_coding_system)) | 914 | setup_coding_system (Fcheck_coding_system (coding_system), &coding); |
| 361 | Vnext_selection_coding_system = Vselection_coding_system; | ||
| 362 | setup_coding_system | ||
| 363 | (Fcheck_coding_system (Vnext_selection_coding_system), &coding); | ||
| 364 | coding.src_multibyte = 0; | 915 | coding.src_multibyte = 0; |
| 365 | coding.dst_multibyte = 1; | 916 | coding.dst_multibyte = 1; |
| 366 | Vnext_selection_coding_system = Qnil; | ||
| 367 | coding.mode |= CODING_MODE_LAST_BLOCK; | 917 | coding.mode |= CODING_MODE_LAST_BLOCK; |
| 368 | /* We explicitely disable composition handling because | 918 | /* We explicitely disable composition handling because |
| 369 | selection data should not contain any composition | 919 | selection data should not contain any composition |
| 370 | sequence. */ | 920 | sequence. */ |
| 371 | coding.composing = COMPOSITION_DISABLED; | 921 | coding.composing = COMPOSITION_DISABLED; |
| 922 | /* Force DOS line-ends. */ | ||
| 923 | coding.eol_type = CODING_EOL_CRLF; | ||
| 924 | |||
| 372 | bufsize = decoding_buffer_size (&coding, nbytes); | 925 | bufsize = decoding_buffer_size (&coding, nbytes); |
| 373 | buf = (unsigned char *) xmalloc (bufsize); | 926 | buf = (unsigned char *) xmalloc (bufsize); |
| 374 | decode_coding (&coding, src, buf, nbytes, bufsize); | 927 | decode_coding (&coding, src, buf, nbytes, bufsize); |
| @@ -382,10 +935,13 @@ DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, | |||
| 382 | } | 935 | } |
| 383 | else | 936 | else |
| 384 | { | 937 | { |
| 385 | /* Need to know final size after CR chars are removed because we | 938 | /* FIXME: We may want to repeat the code in this branch for |
| 386 | can't change the string size manually, and doing an extra | 939 | the Unicode case. */ |
| 387 | copy is silly. Note that we only remove CR when it appears | 940 | |
| 388 | as part of CRLF. */ | 941 | /* Need to know final size after CR chars are removed because |
| 942 | we can't change the string size manually, and doing an | ||
| 943 | extra copy is silly. We only remove CR when it appears as | ||
| 944 | part of CRLF. */ | ||
| 389 | 945 | ||
| 390 | truelen = nbytes; | 946 | truelen = nbytes; |
| 391 | dst = src; | 947 | dst = src; |
| @@ -462,9 +1018,14 @@ and t is the same as `SECONDARY'. */) | |||
| 462 | 1018 | ||
| 463 | if (OpenClipboard (NULL)) | 1019 | if (OpenClipboard (NULL)) |
| 464 | { | 1020 | { |
| 465 | int format = 0; | 1021 | UINT format = 0; |
| 466 | while (format = EnumClipboardFormats (format)) | 1022 | setup_config (); |
| 467 | if (format == CF_TEXT) | 1023 | while ((format = EnumClipboardFormats (format))) |
| 1024 | /* Check CF_TEXT in addition to cfg_clipboard_type, | ||
| 1025 | because we can fall back on that if CF_UNICODETEXT is | ||
| 1026 | not available. Actually a check for CF_TEXT only | ||
| 1027 | should be enough. */ | ||
| 1028 | if (format == cfg_clipboard_type || format == CF_TEXT) | ||
| 468 | { | 1029 | { |
| 469 | val = Qt; | 1030 | val = Qt; |
| 470 | break; | 1031 | break; |
| @@ -476,24 +1037,25 @@ and t is the same as `SECONDARY'. */) | |||
| 476 | return Qnil; | 1037 | return Qnil; |
| 477 | } | 1038 | } |
| 478 | 1039 | ||
| 1040 | /* One-time init. Called in the un-dumped Emacs, but not in the | ||
| 1041 | dumped version. */ | ||
| 1042 | |||
| 479 | void | 1043 | void |
| 480 | syms_of_w32select () | 1044 | syms_of_w32select () |
| 481 | { | 1045 | { |
| 482 | #if 0 | ||
| 483 | defsubr (&Sw32_open_clipboard); | ||
| 484 | defsubr (&Sw32_empty_clipboard); | ||
| 485 | defsubr (&Sw32_close_clipboard); | ||
| 486 | #endif | ||
| 487 | defsubr (&Sw32_set_clipboard_data); | 1046 | defsubr (&Sw32_set_clipboard_data); |
| 488 | defsubr (&Sw32_get_clipboard_data); | 1047 | defsubr (&Sw32_get_clipboard_data); |
| 489 | defsubr (&Sx_selection_exists_p); | 1048 | defsubr (&Sx_selection_exists_p); |
| 490 | 1049 | ||
| 491 | DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system, | 1050 | DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system, |
| 492 | doc: /* Coding system for communicating with other programs. | 1051 | doc: /* Coding system for communicating with other programs. |
| 493 | When sending or receiving text via cut_buffer, selection, and clipboard, | 1052 | When sending or receiving text via cut_buffer, selection, and |
| 494 | the text is encoded or decoded by this coding system. | 1053 | clipboard, the text is encoded or decoded by this coding system. |
| 495 | The default value is `iso-latin-1-dos'. */); | 1054 | The default value is the current system default encoding on 9x/Me and |
| 496 | Vselection_coding_system = intern ("iso-latin-1-dos"); | 1055 | `utf-16le-dos' (Unicode) on NT/W2K/XP. */); |
| 1056 | /* The actual value is set dynamically in the dumped Emacs, see | ||
| 1057 | below. */ | ||
| 1058 | Vselection_coding_system = Qnil; | ||
| 497 | 1059 | ||
| 498 | DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system, | 1060 | DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system, |
| 499 | doc: /* Coding system for the next communication with other programs. | 1061 | doc: /* Coding system for the next communication with other programs. |
| @@ -504,6 +1066,41 @@ set to nil. */); | |||
| 504 | Vnext_selection_coding_system = Qnil; | 1066 | Vnext_selection_coding_system = Qnil; |
| 505 | 1067 | ||
| 506 | QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD); | 1068 | QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD); |
| 1069 | |||
| 1070 | cfg_coding_system = Qnil; staticpro (&cfg_coding_system); | ||
| 1071 | current_text = Qnil; staticpro (¤t_text); | ||
| 1072 | current_coding_system = Qnil; staticpro (¤t_coding_system); | ||
| 1073 | |||
| 1074 | QUNICODE = intern ("utf-16le-dos"); staticpro (&QUNICODE); | ||
| 1075 | QANSICP = Qnil; staticpro (&QANSICP); | ||
| 1076 | QOEMCP = Qnil; staticpro (&QOEMCP); | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | /* One-time init. Called in the dumped Emacs, but not in the | ||
| 1080 | un-dumped version. */ | ||
| 1081 | |||
| 1082 | void | ||
| 1083 | globals_of_w32select () | ||
| 1084 | { | ||
| 1085 | DEFAULT_LCID = GetUserDefaultLCID (); | ||
| 1086 | /* Drop the sort order from the LCID, so we can compare this with | ||
| 1087 | CF_LOCALE objects that have the same fix on 9x. */ | ||
| 1088 | DEFAULT_LCID = MAKELCID (LANGIDFROMLCID (DEFAULT_LCID), SORT_DEFAULT); | ||
| 1089 | |||
| 1090 | ANSICP = GetACP (); | ||
| 1091 | OEMCP = GetOEMCP (); | ||
| 1092 | |||
| 1093 | QANSICP = coding_from_cp (ANSICP); | ||
| 1094 | QOEMCP = coding_from_cp (OEMCP); | ||
| 1095 | |||
| 1096 | if (os_subtype == OS_NT) | ||
| 1097 | Vselection_coding_system = QUNICODE; | ||
| 1098 | else if (inhibit_window_system) | ||
| 1099 | Vselection_coding_system = QOEMCP; | ||
| 1100 | else | ||
| 1101 | Vselection_coding_system = QANSICP; | ||
| 1102 | |||
| 1103 | clipboard_owner = create_owner (); | ||
| 507 | } | 1104 | } |
| 508 | 1105 | ||
| 509 | /* arch-tag: c96e9724-5eb1-4dad-be07-289f092fd2af | 1106 | /* arch-tag: c96e9724-5eb1-4dad-be07-289f092fd2af |