From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Benjamin Riefenstahl Newsgroups: gmane.emacs.devel Subject: Re: Unicode support for the MS Windows clipboard Date: Thu, 03 Jun 2004 11:17:29 +0200 Sender: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Message-ID: References: <9681-Thu27May2004100522+0300-eliz@gnu.org> NNTP-Posting-Host: deer.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: sea.gmane.org 1086254374 23918 80.91.224.253 (3 Jun 2004 09:19:34 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Thu, 3 Jun 2004 09:19:34 +0000 (UTC) Cc: Eli Zaretskii , Stefan Monnier , Jason Rumney Original-X-From: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Thu Jun 03 11:19:22 2004 Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by deer.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 1BVoNd-0007Yc-00 for ; Thu, 03 Jun 2004 11:19:21 +0200 Original-Received: from lists.gnu.org ([199.232.76.165]) by quimby.gnus.org with esmtp (Exim 3.35 #1 (Debian)) id 1BVoNZ-00028a-00 for ; Thu, 03 Jun 2004 11:19:17 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.33) id 1BVoNr-0008Fm-9A for emacs-devel@quimby.gnus.org; Thu, 03 Jun 2004 05:19:35 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.33) id 1BVoNS-000880-CD for emacs-devel@gnu.org; Thu, 03 Jun 2004 05:19:10 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.33) id 1BVoNO-00087L-En for emacs-devel@gnu.org; Thu, 03 Jun 2004 05:19:09 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.33) id 1BVoNO-000876-CC for emacs-devel@gnu.org; Thu, 03 Jun 2004 05:19:06 -0400 Original-Received: from [193.28.100.151] (helo=mail.epost.de) by monty-python.gnu.org with esmtp (Exim 4.34) id 1BVoMe-0001Kx-0N; Thu, 03 Jun 2004 05:18:22 -0400 Original-Received: from seneca.benny.turtle-trading.net.epost.de (193.99.153.30) by mail.epost.de (6.7.015) id 40BE5A1F00017866; Thu, 3 Jun 2004 11:18:16 +0200 Original-To: emacs-devel@gnu.org In-Reply-To: (Benjamin Riefenstahl's message of "Fri, 28 May 2004 15:26:10 +0200") User-Agent: Gnus/5.1001 (Gnus v5.10.1) Emacs/21.3.50 (gnu/linux) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.4 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Xref: main.gmane.org gmane.emacs.devel:24463 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:24463 --=-=-= Hi all, Benjamin Riefenstahl writes: > - If selection-coding-system has the form /(.*-)?utf-16.*/, I assume > CF_UNICODETEXT is wanted. > > - If selection-coding-system has the form /cp[0-9]+.*/ or > /windows-[0-9]+.*/, I derive the codepage from that. > > - Check if the codepage is identical to GetACP() or GetOEMCP(). > If it is, use CF_TEXT or CF_OEMTEXT accordingly. > > - Else get a corresponding LCID (reverse mapping via > EnumLocales()) which has the codepage as OEM or "ANSI". In this > case we also need to set LC_LOCALE accordingly. I implemented this in the attached patch. I have tested it on W2K, 95 and 98SE. Please tell of any problem the code has or of other improvements I can make. I have a couple of notes: The C code constructs it's own cpXXXX-dos coding system names in one place. I would like to check that the constructed coding system actually exists, but I don't know how yet. I didn't worry about the console encoding (CF_OEMTEXT) too much, but I added support for it, where it seemed straight-forward to me. I get the feeling that the C code does too much, and that it should delegate major parts of the processing to Lisp. I am not yet sure how to structure that, though. Somebody suggested to automatically map all Unicode coding-systems to the right one, utf-16le-dos. If we actually want that, I'd suggest doing it in the Lisp in (set-selection-coding-system) and not in C. I also wouldn't want to automatically map utf-8-dos, because it seems clear and well-known to me that an 8-bit Unicode variant is not what Windows thinks of as "Unicode", so when I say utf-8-dos, I expect that to be respected here. But that's just IMO. I didn't do anything about the defaults yet. That's because it's done in Lisp until now, and I haven't studied that code yet. To reiterate the last discussion, the idea would be to set selection-coding-system to utf-16le-dos on NT/W2K/XP and to cpXXXX on 9x/Me. About the ASCII-only optimizations in w32select.c, these are now enabled, except for the Unicode case in w32-get-clipboard-data, where I would have to duplicate some 8-bit code as 16-bit code. I didn't feel like doing that just now. Even with a small enhancement, the optimization still doesn't do very much for setting the clipboard. It *does* make a noticable difference with *getting* data from the clipboard. Ideally somebody could profile w32-set-clipboard-data to see if the time is spent in Emacs or in Windows' clipboard API. Unicode on 9x: The only applications that I have on 98 that have support for CF_UNICODETEXT are Wordpad and IE 6, they produce that format themself and they also use it if somebody has posted it. I assume Word and other Office apps would also have it. Both Wordpad and IE need CF_TEXT to be present (or promised via delayed rendering) to even enable pasting, so Unicode pasting has to wait until we implement delayed rendering in Emacs. We'll probably need documentation updates in some place. The patch also fixes two mostly benign bugs. I assume that for this to go in, I need to sign papers, and I understand that somebody needs to contact me about that from your side. While I am still familiar with the internal of this module, I'd like to tackle delayed rendering. I am thinking of constructing a hidden window for hanging the message handlers on (we have a regular message loop running even with "emacs -nw", right?). I know how to do that, so it should not be too much of an effort. benny 2004-06-02 Benjamin Riefenstahl * w32select.c (cached_coding_system, codepage, lcid) (clipboard_type, DEFAULT_LCID, ANSICP, OEMCP): New static variables. (cp_from_locale, enum_locale_callback, setup_parameters): New functions. (Fw32_set_clipboard_data): Handle CF_UNICODETEXT and CF_LOCALE. Correct end-of-string handling on clipboard. (Fw32_get_clipboard_data): Handle CF_UNICODETEXT and CF_LOCALE. Correct end-of-string for last_clipboard_text. (Fx_selection_exists_p): Handle CF_UNICODETEXT. (syms_of_w32select): Init and register cached_coding_system. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=w32select.c.patch Index: w32select.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32select.c,v retrieving revision 1.32 diff -u -p -r1.32 w32select.c --- w32select.c 18 Apr 2004 18:34:03 -0000 1.32 +++ w32select.c 2 Jun 2004 15:17:41 -0000 @@ -41,6 +41,16 @@ static Lisp_Object Vselection_coding_sys /* Coding system for the next communicating with other Windows programs. */ static Lisp_Object Vnext_selection_coding_system; +/* Cached transfer parameters. */ +static Lisp_Object cached_coding_system; +static UINT codepage; +static LCID lcid; +static UINT clipboard_type; + +/* Constants, initialized dynamically later. */ +static LCID DEFAULT_LCID = LOCALE_NEUTRAL; +static UINT ANSICP, OEMCP; + /* Sequence number, used where possible to detect when we are pasting our own text. */ static DWORD last_clipboard_sequence_number; @@ -51,7 +61,17 @@ extern ClipboardSequence_Proc clipboard_ use data put on the clipboard by Emacs 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. */ + text *after* it was encoded/Unix-to-DOS-converted. + + FIXME: This doesn't work quite right, in the situation when the + last stored text is in CF_TEXT format and the format that we want + according to `selection-coding-system' is CF_UNICODETEXT. We'd + have to retrieve the CF_TEXT just for the comparison, which is + wastefull with delayed rendering. A better method is to check the + clipboard owner, but that requires that we *always* pass a HWND to + OpenClipboard(), and than preferably always the same HWND. This + will probably be easier once we implement delayed rendering + (WM_RENDERFORMAT) ourself, where this is also a requirement. */ static unsigned char *last_clipboard_text = NULL; static size_t clipboard_storage_size = 0; @@ -110,6 +130,136 @@ DEFUN ("w32-close-clipboard", Fw32_close #endif +static UINT +cp_from_locale (LCID lcid, UINT variant) +{ + char buffer[20] = ""; + UINT cp; + + GetLocaleInfo (lcid, variant, buffer, sizeof (buffer)); + cp = strtoul (buffer, NULL, 10); + + if (cp == CP_ACP) + return ANSICP; + else if (cp == CP_OEMCP) + return OEMCP; + else + return cp; +} + +static BOOL WINAPI +enum_locale_callback (/*const*/ char* loc_string) +{ + LCID this_lcid; + UINT this_codepage; + + this_lcid = strtoul (loc_string, NULL, 16); + + /* Is the wanted codepage the "ANSI" codepage for this locale? */ + this_codepage = cp_from_locale (this_lcid, LOCALE_IDEFAULTANSICODEPAGE); + if (this_codepage == codepage) + { + lcid = this_lcid; + clipboard_type = CF_TEXT; + return FALSE; /* Stop enumeration */ + } + + /* Is the wanted codepage the OEM codepage for this locale? */ + this_codepage = cp_from_locale (this_lcid, LOCALE_IDEFAULTCODEPAGE); + if (this_codepage == codepage) + { + lcid = this_lcid; + clipboard_type = CF_OEMTEXT; + return FALSE; /* Stop enumeration */ + } + + return TRUE; /* Continue enumeration */ +} + +static void +setup_parameters (void) +{ + const char *coding_name; + const char *cp; + char *end; + int slen; + Lisp_Object current_coding_system; + + CHECK_SYMBOL (Vselection_coding_system); + + /* One-time init. */ + if (DEFAULT_LCID == LOCALE_NEUTRAL) + { + DEFAULT_LCID = GetUserDefaultLCID (); + + /* Drop the sort order, so we compare this to CF_LOCALE objects + with the same fix on W'9x. */ + DEFAULT_LCID = MAKELCID (LANGIDFROMLCID (DEFAULT_LCID), SORT_DEFAULT); + + ANSICP = GetACP (); + OEMCP = GetOEMCP (); + } + + /* Check if we have it cached */ + current_coding_system = NILP (Vnext_selection_coding_system) ? + Vselection_coding_system : Vnext_selection_coding_system; + if (!NILP (cached_coding_system) + && EQ (cached_coding_system, current_coding_system)) + return; + cached_coding_system = current_coding_system; + + /* Set some sensible fallbacks */ + codepage = ANSICP; + lcid = LOCALE_NEUTRAL; + clipboard_type = CF_TEXT; + + /* Interpret the coding system symbol name */ + coding_name = SDATA (SYMBOL_NAME (current_coding_system)); + + /* "(.*-)?utf-16.*" -> CF_UNICODETEXT */ + cp = strstr (coding_name, "utf-16"); + if (cp != NULL && (cp == coding_name || cp[-1] == '-')) + { + clipboard_type = CF_UNICODETEXT; + return; + } + + /* "cp[0-9]+.*" or "windows-[0-9]+.*" -> CF_TEXT or CF_OEMTEXT */ + slen = strlen (coding_name); + if (slen >= 4 && coding_name[0] == 'c' && coding_name[1] == 'p') + cp = coding_name + 2; + else if (slen >= 10 && memcmp (coding_name, "windows-", 8) == 0) + cp = coding_name + 8; + else + return; + + end = (char*)cp; + codepage = strtol (cp, &end, 10); + + /* Error return from strtol() or number of digits < 2 -> Restore the + default and drop it. */ + if (codepage == 0 || (end-cp) < 2 ) + { + codepage = ANSICP; + return; + } + + /* Is it the current system default? */ + if (codepage == ANSICP) + { + /* clipboard_type = CF_TEXT; */ + return; + } + if (codepage == OEMCP) + { + clipboard_type = CF_OEMTEXT; + return; + } + + /* Else determine a suitable locale the hard way. */ + EnumSystemLocales (enum_locale_callback, LCID_INSTALLED); +} + 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. */) @@ -117,147 +267,176 @@ DEFUN ("w32-set-clipboard-data", Fw32_se Lisp_Object string, frame; { BOOL ok = TRUE; - HANDLE htext; + HANDLE htext, hlocale = NULL; int nbytes; int truelen, nlines = 0; + int require_encoding = 0; unsigned char *src; unsigned char *dst; + unsigned char *end; + UINT actual_clipboard_type; CHECK_STRING (string); if (!NILP (frame)) CHECK_LIVE_FRAME (frame); + setup_parameters (); + actual_clipboard_type = clipboard_type; + BLOCK_INPUT; nbytes = SBYTES (string) + 1; src = SDATA (string); - dst = src; - /* We need to know how many lines there are, since we need CRLF line - termination for compatibility with other Windows Programs. - avoid using strchr because it recomputes the length every time */ - while ((dst = memchr (dst, '\n', nbytes - (dst - src))) != NULL) + /* Check for non-ASCII characters. While we are at it, count the + number of LFs, so we know how many CRs we have to add later + on. */ + for (dst = src, end = src+nbytes; dst < end; dst++) { - nlines++; - dst++; + if (*dst == '\n') + nlines++; + else if (*dst >= 0x80 || *dst == 0) + { + require_encoding = 1; + break; + } } - { - /* Since we are now handling multilingual text, we must consider - encoding text for the clipboard. */ - int charset_info = find_charset_in_text (src, SCHARS (string), - nbytes, NULL, Qnil); - - if (charset_info == 0) - { - /* No multibyte character in OBJ. We need not encode it. */ + if (!require_encoding) + { + /* No multibyte character in OBJ. We need not encode it. */ - /* Need to know final size after CR chars are inserted (the - standard CF_TEXT clipboard format uses CRLF line endings, - while Emacs uses just LF internally). */ + /* Need to know final size after CR chars are inserted (the + standard CF_TEXT clipboard format uses CRLF line endings, + while Emacs uses just LF internally). */ - truelen = nbytes + nlines; + truelen = nbytes + nlines; - if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, truelen)) == NULL) + if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, truelen)) == NULL) goto error; - if ((dst = (unsigned char *) GlobalLock (htext)) == NULL) - goto error; + if ((dst = (unsigned char *) GlobalLock (htext)) == NULL) + goto error; - /* convert to CRLF line endings expected by clipboard */ - while (1) - { - unsigned char *next; - /* copy next line or remaining bytes including '\0' */ - next = _memccpy (dst, src, '\n', nbytes); - if (next) - { - /* copied one line ending with '\n' */ - int copied = next - dst; - nbytes -= copied; - src += copied; - /* insert '\r' before '\n' */ - next[-1] = '\r'; - next[0] = '\n'; - dst = next + 1; - } - else - /* copied remaining partial line -> now finished */ - break; - } + /* convert to CRLF line endings expected by clipboard */ + while (1) + { + unsigned char *next; + /* copy next line or remaining bytes including '\0' */ + next = _memccpy (dst, src, '\n', nbytes); + if (next) + { + /* copied one line ending with '\n' */ + int copied = next - dst; + nbytes -= copied; + src += copied; + /* insert '\r' before '\n' */ + next[-1] = '\r'; + next[0] = '\n'; + dst = next + 1; + } + else + /* copied remaining partial line -> now finished */ + break; + } - GlobalUnlock (htext); + GlobalUnlock (htext); - Vlast_coding_system_used = Qraw_text; - } - else - { - /* We must encode contents of OBJ to the selection coding - system. */ - int bufsize; - struct coding_system coding; - HANDLE htext2; + /* Truncate last_clipboard_text by setting it to the string + terminator. */ + if (last_clipboard_text) + last_clipboard_text[0] = last_clipboard_text[1] = '\0'; - if (NILP (Vnext_selection_coding_system)) - 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 = SDATA (string); - nbytes = SBYTES (string); - } - coding.src_multibyte = 1; - coding.dst_multibyte = 0; - /* Need to set COMPOSITION_DISABLED, otherwise Emacs crashes in - encode_coding_iso2022 trying to dereference a null pointer. */ - coding.composing = COMPOSITION_DISABLED; - if (coding.type == coding_type_iso2022) - coding.flags |= CODING_FLAG_ISO_SAFE; - Vnext_selection_coding_system = Qnil; - coding.mode |= CODING_MODE_LAST_BLOCK; - bufsize = encoding_buffer_size (&coding, nbytes); - if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, bufsize)) == NULL) - goto error; - if ((dst = (unsigned char *) GlobalLock (htext)) == NULL) - goto error; - encode_coding (&coding, src, dst, nbytes, bufsize); - Vlast_coding_system_used = coding.symbol; + Vlast_coding_system_used = Qraw_text; + actual_clipboard_type = CF_TEXT; + } + else + { + /* We must encode contents of OBJ to the selection coding + system. */ + int bufsize; + struct coding_system coding; + HANDLE htext2; + + if (NILP (Vnext_selection_coding_system)) + 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 = SDATA (string); + nbytes = SBYTES (string); + } + coding.src_multibyte = 1; + coding.dst_multibyte = 0; + /* Need to set COMPOSITION_DISABLED, otherwise Emacs crashes in + encode_coding_iso2022 trying to dereference a null pointer. */ + coding.composing = COMPOSITION_DISABLED; + if (coding.type == coding_type_iso2022) + coding.flags |= CODING_FLAG_ISO_SAFE; + Vnext_selection_coding_system = Qnil; + coding.mode |= CODING_MODE_LAST_BLOCK; + bufsize = encoding_buffer_size (&coding, nbytes) +2; + if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, bufsize)) == NULL) + goto error; + if ((dst = (unsigned char *) GlobalLock (htext)) == NULL) + goto error; + + encode_coding (&coding, src, dst, nbytes, bufsize-2); + Vlast_coding_system_used = coding.symbol; + + /* Add the string terminator. */ + dst[coding.produced] = dst[coding.produced+1] = '\0'; + + /* If clipboard sequence numbers are not supported, keep a copy for + later comparison. */ + if (!clipboard_sequence_fn) + { + /* 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+2) + { + 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+2); + } - /* If clipboard sequence numbers are not supported, keep a copy for - later comparison. */ - if (!clipboard_sequence_fn) - { - /* 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); - GlobalUnlock (htext); + /* Shrink data block to actual size. */ + htext2 = GlobalReAlloc (htext, coding.produced+2, + GMEM_MOVEABLE | GMEM_DDESHARE); + if (htext2 != NULL) htext = htext2; - /* Shrink data block to actual size. */ - htext2 = GlobalReAlloc (htext, coding.produced, - GMEM_MOVEABLE | GMEM_DDESHARE); - if (htext2 != NULL) htext = htext2; - } - } + if (lcid != LOCALE_NEUTRAL && lcid != DEFAULT_LCID) + { + hlocale = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, sizeof (lcid)); + if (hlocale != NULL) + { + * (LCID*) GlobalLock (hlocale) = lcid; + GlobalUnlock (hlocale); + } + } + } if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL)) goto error; - ok = EmptyClipboard () && SetClipboardData (CF_TEXT, htext); + ok = EmptyClipboard () && SetClipboardData (actual_clipboard_type, htext); + + if (ok && hlocale != NULL) + { + ok = ok && SetClipboardData (CF_LOCALE, hlocale); + if (!ok) EmptyClipboard (); + } CloseClipboard (); @@ -277,8 +456,12 @@ DEFUN ("w32-set-clipboard-data", Fw32_se ok = FALSE; if (htext) GlobalFree (htext); + if (hlocale) GlobalFree (hlocale); + + /* Truncate last_clipboard_text by setting it to the string + terminator. */ if (last_clipboard_text) - *last_clipboard_text = '\0'; + last_clipboard_text[0] = last_clipboard_text[1] = '\0'; last_clipboard_sequence_number = 0; @@ -296,16 +479,40 @@ DEFUN ("w32-get-clipboard-data", Fw32_ge { HANDLE htext; Lisp_Object ret = Qnil; + UINT actual_clipboard_type; + int use_configured_coding_system = 1; if (!NILP (frame)) CHECK_LIVE_FRAME (frame); + setup_parameters (); + actual_clipboard_type = clipboard_type; + BLOCK_INPUT; if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL)) goto done; - if ((htext = GetClipboardData (CF_TEXT)) == NULL) + if ((htext = GetClipboardData (clipboard_type)) == NULL) + { + /* If we want CF_UNICODETEXT but can't get it, the current + coding system is useless. OTOH we can still try and decode + CF_TEXT based on the locale that the system gives us and that + we get down below. Note that Windows is documented to always + generate CF_LOCALE info automatically, so the locale handle + should be always present (actually this is not always true on + W'9x ;-(). */ + if (clipboard_type == CF_UNICODETEXT) + { + htext = GetClipboardData (CF_TEXT); + if (htext != NULL) + { + actual_clipboard_type = CF_TEXT; + use_configured_coding_system = 0; + } + } + } + if (htext == NULL) goto closeclip; { @@ -318,7 +525,10 @@ DEFUN ("w32-get-clipboard-data", Fw32_ge if ((src = (unsigned char *) GlobalLock (htext)) == NULL) goto closeclip; - nbytes = strlen (src); + if (actual_clipboard_type == CF_UNICODETEXT) + nbytes = (lstrlenW ((WCHAR *)src) + 1) * 2; + else + nbytes = strlen (src) + 1; /* If the text in clipboard is identical to what we put there last time w32_set_clipboard_data was called, pretend there's no @@ -329,34 +539,99 @@ DEFUN ("w32-get-clipboard-data", Fw32_ge && clipboard_sequence_fn () == last_clipboard_sequence_number) || (last_clipboard_text && clipboard_storage_size >= nbytes - && memcmp(last_clipboard_text, src, nbytes) == 0)) + && 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; + /* Drop the string terminator from here on. */ + nbytes -= actual_clipboard_type == CF_UNICODETEXT ? 2 : 1; - for (i = 0; i < nbytes; i++) - { - if (src[i] >= 0x80) - { - require_decoding = 1; - break; - } - } - } + /* If the clipboard data contains any non-ascii code, we need to + decode it with a coding system. + FIXME: Repeat the code for the Unicode case. */ + if (actual_clipboard_type == CF_UNICODETEXT) + require_decoding = 1; + else + { + int i; + + for (i = 0; i < nbytes; i++) + { + if (src[i] >= 0x80) + { + require_decoding = 1; + break; + } + } + } if (require_decoding) { int bufsize; unsigned char *buf; struct coding_system coding; + Lisp_Object coding_system = Qnil; + + /* `next-selection-coding-system' should override everything, + even when the locale passed by the system disagrees. The + only exception is when `next-selection-coding-system' + requested CF_UNICODETEXT and we couldn't get that. */ + if (use_configured_coding_system + && !NILP (Vnext_selection_coding_system)) + coding_system = Vnext_selection_coding_system; + + /* If we have CF_TEXT or CF_OEMTEXT, we want to check out + CF_LOCALE, too. */ + else if (actual_clipboard_type != CF_UNICODETEXT) + { + HANDLE hlocale; + LCID cb_lcid; + UINT cp; + + hlocale = GetClipboardData (CF_LOCALE); + if (hlocale != NULL) + { + cb_lcid = *(LCID*)GlobalLock (hlocale); + GlobalUnlock (hlocale); - if (NILP (Vnext_selection_coding_system)) - Vnext_selection_coding_system = Vselection_coding_system; - setup_coding_system - (Fcheck_coding_system (Vnext_selection_coding_system), &coding); + /* W'9x has garbage as the sort order (i.e. there is + another instance of the language id in the upper + word). We can just filter out the unneeded + mis-information to avoid irritations. */ + cb_lcid = MAKELCID (LANGIDFROMLCID (cb_lcid), SORT_DEFAULT); + } + else + cb_lcid = DEFAULT_LCID; + + /* If we are using fallback from CF_UNICODETEXT, we can't + use the configured coding system. Also we don't want + to use it, if the system has supplied us with a locale + and it is not just the system default. */ + if (!use_configured_coding_system || cb_lcid != DEFAULT_LCID) + { + cp = cp_from_locale (cb_lcid, + actual_clipboard_type == CF_TEXT + ? LOCALE_IDEFAULTANSICODEPAGE + : LOCALE_IDEFAULTCODEPAGE); + /* If it's just our current setting anyway, use the + coding system that the user has selected. + Otherwise create a new spec to match the locale + that was specified by the other side or the + system. */ + if (!use_configured_coding_system || cp != codepage) + { + char buffer[30]; + sprintf (buffer, "cp%d-dos", (int) cp); + coding_system = intern (buffer); + /* FIXME: We should verify that this coding system + actually exists. */ + } + } + } + + if (NILP (coding_system)) + coding_system = Vselection_coding_system; + + setup_coding_system (Fcheck_coding_system (coding_system), &coding); coding.src_multibyte = 0; coding.dst_multibyte = 1; Vnext_selection_coding_system = Qnil; @@ -459,8 +734,12 @@ and t is the same as `SECONDARY'. */) if (OpenClipboard (NULL)) { int format = 0; + setup_parameters (); while (format = EnumClipboardFormats (format)) - if (format == CF_TEXT) + /* Check CF_TEXT in addition to clipboard_type, because we + fall back on that if CF_UNICODETEXT is not + available. */ + if (format == clipboard_type || format == CF_TEXT) { val = Qt; break; @@ -500,6 +779,8 @@ set to nil. */); Vnext_selection_coding_system = Qnil; QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD); + + cached_coding_system = Qnil; staticpro (&cached_coding_system); } /* arch-tag: c96e9724-5eb1-4dad-be07-289f092fd2af --=-=-= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Emacs-devel mailing list Emacs-devel@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-devel --=-=-=--