/* Selection processing for Emacs on the Microsoft W32 API.
- Copyright (C) 1993, 1994, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+Copyright (C) 1993-1994, 2001-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 3, 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
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 <http://www.gnu.org/licenses/>. */
/* Written by Kevin Gallo, Benjamin Riefenstahl */
* (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
*
* 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.
* types should be supported is also moved to Lisp, functionality
* could be expanded to CF_HTML, CF_RTF and maybe other types.
*/
-
+
#include <config.h>
+#include <setjmp.h>
#include "lisp.h"
#include "w32term.h" /* for all of the w32 includes */
#include "w32heap.h" /* os_subtype */
#include "keyboard.h" /* cmd_error_internal() */
#include "charset.h"
#include "coding.h"
+#include "character.h"
#include "composite.h"
static HGLOBAL convert_to_handle_as_coded (Lisp_Object coding_system);
static Lisp_Object render (Lisp_Object oformat);
static Lisp_Object render_locale (void);
-static Lisp_Object render_all (void);
-static void run_protected (Lisp_Object (*code) (), Lisp_Object arg);
+static Lisp_Object render_all (Lisp_Object ignore);
+static void run_protected (Lisp_Object (*code) (Lisp_Object), Lisp_Object arg);
static Lisp_Object lisp_error_handler (Lisp_Object error);
static LRESULT CALLBACK owner_callback (HWND win, UINT msg,
WPARAM wp, LPARAM lp);
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
PRIMARY and SECONDARY. */
Lisp_Object QCLIPBOARD;
-/* Coding system for communicating with other programs via the
- clipboard. */
-static Lisp_Object Vselection_coding_system;
-
-/* Coding system for the next communication with other programs. */
-static Lisp_Object Vnext_selection_coding_system;
-
/* Internal pseudo-constants, initialized in globals_of_w32select()
based on current system parameters. */
static LCID DEFAULT_LCID;
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;
+ 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);
- nbytes = SBYTES (string);
- src = SDATA (string);
-
- 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;
}
if (SetClipboardData (format, htext) == NULL)
{
- GlobalFree(htext);
+ GlobalFree (htext);
return Qnil;
}
if ((lcid_ptr = (LCID *) GlobalLock (hlocale)) == NULL)
{
- GlobalFree(hlocale);
+ GlobalFree (hlocale);
return Qnil;
}
if (SetClipboardData (CF_LOCALE, hlocale) == NULL)
{
- GlobalFree(hlocale);
+ GlobalFree (hlocale);
return Qnil;
}
data survives us. This code will do that. */
static Lisp_Object
-render_all (void)
+render_all (Lisp_Object ignore)
{
ONTRACE (fprintf (stderr, "render_all\n"));
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));
}
static void
-run_protected (Lisp_Object (*code) (), Lisp_Object arg)
+run_protected (Lisp_Object (*code) (Lisp_Object), Lisp_Object arg)
{
/* FIXME: This works but it doesn't feel right. Too much fiddling
with global variables and calling strange looking functions. Is
this really the right way to run Lisp callbacks? */
- extern int waiting_for_input;
int owfi;
BLOCK_INPUT;
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;
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)
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. */)
- (string, ignored)
- Lisp_Object string, ignored;
+ (Lisp_Object string, Lisp_Object ignored)
{
BOOL ok = TRUE;
int nbytes;
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
/* 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)
{
/* 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;
}
DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data,
Sw32_get_clipboard_data, 0, 1, 0,
doc: /* This gets the clipboard data in text format. */)
- (ignored)
- Lisp_Object ignored;
+ (Lisp_Object ignored)
{
HGLOBAL htext;
Lisp_Object ret = Qnil;
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'
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
{
\(Those are literal upper-case symbol names, since that's what X expects.)
For convenience, the symbol nil is the same as `PRIMARY',
and t is the same as `SECONDARY'. */)
- (selection)
- Lisp_Object selection;
+ (Lisp_Object selection)
{
CHECK_SYMBOL (selection);
{
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
dumped version. */
void
-syms_of_w32select ()
+syms_of_w32select (void)
{
defsubr (&Sw32_set_clipboard_data);
defsubr (&Sw32_get_clipboard_data);
defsubr (&Sx_selection_exists_p);
- DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system,
+ DEFVAR_LISP ("selection-coding-system", Vselection_coding_system,
doc: /* Coding system for communicating with other programs.
-When sending or receiving text via cut_buffer, selection, and
-clipboard, the text is encoded or decoded by this coding system.
-The default value is the current system default encoding on 9x/Me and
-`utf-16le-dos' (Unicode) on NT/W2K/XP. */);
+
+For MS-Windows and MS-DOS:
+When sending or receiving text via 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, `utf-16le-dos'
+\(Unicode) on NT/W2K/XP, and `iso-latin-1-dos' on MS-DOS.
+
+For X Windows:
+When sending text via selection and clipboard, if the target
+data-type matches with the type of this coding system, it is used
+for encoding the text. Otherwise (including the case that this
+variable is nil), a proper coding system is used as below:
+
+data-type coding system
+--------- -------------
+UTF8_STRING utf-8
+COMPOUND_TEXT compound-text-with-extensions
+STRING iso-latin-1
+C_STRING no-conversion
+
+When receiving text, if this coding system is non-nil, it is used
+for decoding regardless of the data-type. If this is nil, a
+proper coding system is used according to the data-type as above.
+
+See also the documentation of the variable `x-select-request-type' how
+to control which data-type to request for receiving text.
+
+The default value is nil. */);
/* The actual value is set dynamically in the dumped Emacs, see
below. */
Vselection_coding_system = Qnil;
- DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system,
+ DEFVAR_LISP ("next-selection-coding-system", Vnext_selection_coding_system,
doc: /* Coding system for the next communication with other programs.
Usually, `selection-coding-system' is used for communicating with
-other programs. But, if this variable is set, it is used for the
-next communication only. After the communication, this variable is
-set to nil. */);
+other programs (X Windows clients or MS Windows programs). But, if this
+variable is set, it is used for the next communication only.
+After the communication, this variable is set to nil. */);
Vnext_selection_coding_system = Qnil;
- QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD);
+ 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);
}
un-dumped version. */
void
-globals_of_w32select ()
+globals_of_w32select (void)
{
DEFAULT_LCID = GetUserDefaultLCID ();
/* Drop the sort order from the LCID, so we can compare this with
clipboard_owner = create_owner ();
}
-/* arch-tag: c96e9724-5eb1-4dad-be07-289f092fd2af
- (do not change this comment) */