X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/c07bb40b73856e3c40daf1dc6007ea13e3870912..de92a50b9e157cac071355b9836717e62b9edff1:/src/w32select.c diff --git a/src/w32select.c b/src/w32select.c index ad5d0e67f8..592ed1d05d 100644 --- a/src/w32select.c +++ b/src/w32select.c @@ -1,13 +1,13 @@ /* Selection processing for Emacs on the Microsoft W32 API. Copyright (C) 1993, 1994, 2001, 2002, 2003, 2004, - 2005, 2006, 2007 Free Software Foundation, Inc. + 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GNU Emacs. -GNU Emacs is free software; you can redistribute it and/or modify +GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,9 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ +along with GNU Emacs. If not, see . */ /* Written by Kevin Gallo, Benjamin Riefenstahl */ @@ -32,7 +30,7 @@ Boston, MA 02110-1301, USA. */ * (CF_UNICODETEXT), when a well-known console codepage is given, they * apply to the console version of the clipboard data (CF_OEMTEXT), * else they apply to the normal 8-bit text clipboard (CF_TEXT). - * + * * When pasting (getting data from the OS), the clipboard format that * matches the {next-}selection-coding-system is retrieved. If * Unicode is requested, but not available, 8-bit text (CF_TEXT) is @@ -47,13 +45,13 @@ Boston, MA 02110-1301, USA. */ * * Scenarios to use the facilities for customizing the selection * coding system are: - * + * * ;; Generally use KOI8-R instead of the russian MS codepage for * ;; the 8-bit clipboard. * (set-selection-coding-system 'koi8-r-dos) - * + * * Or - * + * * ;; Create a special clipboard copy function that uses codepage * ;; 1253 (Greek) to copy Greek text to a specific non-Unicode * ;; application. @@ -73,8 +71,9 @@ Boston, MA 02110-1301, USA. */ * types should be supported is also moved to Lisp, functionality * could be expanded to CF_HTML, CF_RTF and maybe other types. */ - + #include +#include #include "lisp.h" #include "w32term.h" /* for all of the w32 includes */ #include "w32heap.h" /* os_subtype */ @@ -82,6 +81,7 @@ Boston, MA 02110-1301, USA. */ #include "keyboard.h" /* cmd_error_internal() */ #include "charset.h" #include "coding.h" +#include "character.h" #include "composite.h" @@ -100,6 +100,9 @@ static void setup_config (void); static BOOL WINAPI enum_locale_callback (/*const*/ char* loc_string); static UINT cp_from_locale (LCID lcid, UINT format); static Lisp_Object coding_from_cp (UINT codepage); +static Lisp_Object validate_coding_system (Lisp_Object coding_system); +static void setup_windows_coding_system (Lisp_Object coding_system, + struct coding_system * coding); /* A remnant from X11: Symbol for the CLIPBORD selection type. Other @@ -213,63 +216,36 @@ convert_to_handle_as_ascii (void) static HGLOBAL convert_to_handle_as_coded (Lisp_Object coding_system) { - HGLOBAL htext = NULL, htext2; - int nbytes; - unsigned char *src; + HGLOBAL htext; unsigned char *dst = NULL; - int bufsize; struct coding_system coding; - Lisp_Object string = Qnil; - ONTRACE (fprintf (stderr, "convert_to_handle_as_coded: %s\n", + ONTRACE (fprintf (stderr, "convert_to_handle_as_coded: %s\n", SDATA (SYMBOL_NAME (coding_system)))); - setup_coding_system (Fcheck_coding_system (coding_system), &coding); - 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; - coding.mode |= CODING_MODE_LAST_BLOCK; - /* Force DOS line-ends. */ - coding.eol_type = CODING_EOL_CRLF; - - if (SYMBOLP (coding.pre_write_conversion) - && !NILP (Ffboundp (coding.pre_write_conversion))) - string = run_pre_post_conversion_on_str (current_text, &coding, 1); - else - string = current_text; - - nbytes = SBYTES (string); - src = SDATA (string); + setup_windows_coding_system (coding_system, &coding); + coding.dst_bytes = SBYTES (current_text) * 2; + coding.destination = (unsigned char *) xmalloc (coding.dst_bytes); + encode_coding_object (&coding, current_text, 0, 0, + SCHARS (current_text), SBYTES (current_text), Qnil); - bufsize = encoding_buffer_size (&coding, nbytes) +2; - htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, bufsize); + htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, coding.produced +2); if (htext != NULL) dst = (unsigned char *) GlobalLock (htext); if (dst != NULL) { - encode_coding (&coding, src, dst, nbytes, bufsize-2); + memcpy (dst, coding.destination, coding.produced); /* Add the string terminator. Add two NULs in case we are producing Unicode here. */ dst[coding.produced] = dst[coding.produced+1] = '\0'; - } - if (dst != NULL) - GlobalUnlock (htext); - - if (htext != NULL) - { - /* Shrink data block to actual size. */ - htext2 = GlobalReAlloc (htext, coding.produced+2, - GMEM_MOVEABLE | GMEM_DDESHARE); - if (htext2 != NULL) htext = htext2; + GlobalUnlock (htext); } + xfree (coding.destination); + return htext; } @@ -314,7 +290,7 @@ render (Lisp_Object oformat) if (SetClipboardData (format, htext) == NULL) { - GlobalFree(htext); + GlobalFree (htext); return Qnil; } @@ -338,7 +314,7 @@ render_locale (void) if ((lcid_ptr = (LCID *) GlobalLock (hlocale)) == NULL) { - GlobalFree(hlocale); + GlobalFree (hlocale); return Qnil; } @@ -347,7 +323,7 @@ render_locale (void) if (SetClipboardData (CF_LOCALE, hlocale) == NULL) { - GlobalFree(hlocale); + GlobalFree (hlocale); return Qnil; } @@ -404,7 +380,7 @@ render_all (void) automatic conversions anywhere else, so to get consistent results, we probably don't want to rely on it here either. */ - render_locale(); + render_locale (); if (current_clipboard_type == CF_UNICODETEXT) render (make_number (CF_TEXT)); @@ -518,18 +494,27 @@ setup_config (void) const char *cp; char *end; int slen; - Lisp_Object new_coding_system; + Lisp_Object coding_system; + Lisp_Object dos_coding_system; CHECK_SYMBOL (Vselection_coding_system); - /* Check if we have it cached */ - new_coding_system = NILP (Vnext_selection_coding_system) ? + coding_system = NILP (Vnext_selection_coding_system) ? Vselection_coding_system : Vnext_selection_coding_system; + + dos_coding_system = validate_coding_system (coding_system); + if (NILP (dos_coding_system)) + Fsignal (Qerror, + list2 (build_string ("Coding system is invalid or doesn't have " + "an eol variant for dos line ends"), + coding_system)); + + /* Check if we have it cached */ if (!NILP (cfg_coding_system) - && EQ (cfg_coding_system, new_coding_system)) + && EQ (cfg_coding_system, dos_coding_system)) return; - cfg_coding_system = new_coding_system; - + cfg_coding_system = dos_coding_system; + /* Set some sensible fallbacks */ cfg_codepage = ANSICP; cfg_lcid = LOCALE_NEUTRAL; @@ -598,7 +583,7 @@ enum_locale_callback (/*const*/ char* loc_string) cfg_clipboard_type = CF_TEXT; return FALSE; /* Stop enumeration */ } - + /* Is the wanted codepage the OEM codepage for this locale? */ codepage = cp_from_locale (lcid, CF_OEMTEXT); if (codepage == cfg_codepage) @@ -637,13 +622,62 @@ coding_from_cp (UINT codepage) char buffer[30]; sprintf (buffer, "cp%d-dos", (int) codepage); return intern (buffer); - /* We don't need to check that this coding system exists right here, - because that is done when the coding system is actually - instantiated, i.e. it is passed through Fcheck_coding_system() - there. */ + /* We don't need to check that this coding system actually exists + right here, because that is done later for all coding systems + used, regardless of where they originate. */ +} + +static Lisp_Object +validate_coding_system (Lisp_Object coding_system) +{ + Lisp_Object eol_type; + + /* Make sure the input is valid. */ + if (NILP (Fcoding_system_p (coding_system))) + return Qnil; + + /* Make sure we use a DOS coding system as mandated by the system + specs. */ + eol_type = Fcoding_system_eol_type (coding_system); + + /* Already a DOS coding system? */ + if (EQ (eol_type, make_number (1))) + return coding_system; + + /* Get EOL_TYPE vector of the base of CODING_SYSTEM. */ + if (!VECTORP (eol_type)) + { + eol_type = Fcoding_system_eol_type (Fcoding_system_base (coding_system)); + if (!VECTORP (eol_type)) + return Qnil; + } + + return AREF (eol_type, 1); +} + +static void +setup_windows_coding_system (Lisp_Object coding_system, + struct coding_system * coding) +{ + memset (coding, 0, sizeof (*coding)); + setup_coding_system (coding_system, coding); + + /* Unset CODING_ANNOTATE_COMPOSITION_MASK. Previous code had + comments about crashes in encode_coding_iso2022 trying to + dereference a null pointer when composition was on. Selection + data should not contain any composition sequence on Windows. + + CODING_ANNOTATION_MASK also includes + CODING_ANNOTATE_DIRECTION_MASK and CODING_ANNOTATE_CHARSET_MASK, + which both apply to ISO6429 only. We don't know if these really + need to be unset on Windows, but it probably doesn't hurt + either. */ + coding->mode &= ~CODING_ANNOTATION_MASK; + coding->mode |= CODING_MODE_LAST_BLOCK | CODING_MODE_SAFE_ENCODING; } + 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. */) @@ -670,7 +704,7 @@ DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, current_lcid = cfg_lcid; current_num_nls = 0; current_requires_encoding = 0; - + BLOCK_INPUT; /* Check for non-ASCII characters. While we are at it, count the @@ -710,7 +744,7 @@ DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, /* If we have something non-ASCII we may want to set a locale. We do that directly (non-delayed), as it's just a small bit. */ if (ok) - ok = !NILP(render_locale()); + ok = !NILP (render_locale ()); if (ok) { @@ -719,7 +753,7 @@ DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data, /* If for some reason we don't have a clipboard_owner, we just set the text format as chosen by the configuration and than forget about the whole thing. */ - ok = !NILP(render (make_number (current_clipboard_type))); + ok = !NILP (render (make_number (current_clipboard_type))); current_text = Qnil; current_coding_system = Qnil; } @@ -847,11 +881,10 @@ DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, if (require_decoding) { - int bufsize; - unsigned char *buf; struct coding_system coding; Lisp_Object coding_system = Qnil; - + Lisp_Object dos_coding_system; + /* `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' @@ -912,27 +945,16 @@ DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, coding_system = Vselection_coding_system; Vnext_selection_coding_system = Qnil; - setup_coding_system (Fcheck_coding_system (coding_system), &coding); - coding.src_multibyte = 0; - coding.dst_multibyte = 1; - coding.mode |= CODING_MODE_LAST_BLOCK; - /* We explicitely disable composition handling because - selection data should not contain any composition - sequence. */ - coding.composing = COMPOSITION_DISABLED; - /* Force DOS line-ends. */ - coding.eol_type = CODING_EOL_CRLF; - - bufsize = decoding_buffer_size (&coding, nbytes); - 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); - xfree (buf); - if (SYMBOLP (coding.post_read_conversion) - && !NILP (Ffboundp (coding.post_read_conversion))) - ret = run_pre_post_conversion_on_str (ret, &coding, 0); + dos_coding_system = validate_coding_system (coding_system); + if (!NILP (dos_coding_system)) + { + setup_windows_coding_system (dos_coding_system, &coding); + coding.source = src; + decode_coding_object (&coding, Qnil, 0, 0, nbytes, nbytes, Qt); + ret = coding.dst_object; + + Vlast_coding_system_used = CODING_ID_NAME (coding.id); + } } else { @@ -1005,7 +1027,7 @@ 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) + (selection) Lisp_Object selection; { CHECK_SYMBOL (selection); @@ -1017,10 +1039,11 @@ and t is the same as `SECONDARY'. */) { Lisp_Object val = Qnil; + setup_config (); + if (OpenClipboard (NULL)) { UINT format = 0; - setup_config (); while ((format = EnumClipboardFormats (format))) /* Check CF_TEXT in addition to cfg_clipboard_type, because we can fall back on that if CF_UNICODETEXT is @@ -1053,7 +1076,7 @@ syms_of_w32select () When sending or receiving text via cut_buffer, selection, and clipboard, the text is encoded or decoded by this coding system. The default value is the current system default encoding on 9x/Me and -`utf-16le-dos' (Unicode) on NT/W2K/XP. */); +`utf-16le-dos' (Unicode) on NT/W2K/XP. */); /* The actual value is set dynamically in the dumped Emacs, see below. */ Vselection_coding_system = Qnil; @@ -1066,13 +1089,13 @@ next communication only. After the communication, this variable is set to nil. */); Vnext_selection_coding_system = Qnil; - QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD); + DEFSYM (QCLIPBOARD, "CLIPBOARD"); cfg_coding_system = Qnil; staticpro (&cfg_coding_system); current_text = Qnil; staticpro (¤t_text); current_coding_system = Qnil; staticpro (¤t_coding_system); - QUNICODE = intern ("utf-16le-dos"); staticpro (&QUNICODE); + DEFSYM (QUNICODE, "utf-16le-dos"); QANSICP = Qnil; staticpro (&QANSICP); QOEMCP = Qnil; staticpro (&QOEMCP); }