changeset 60092:04686828d0da

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.
author Jason Rumney <jasonr@gnu.org>
date Tue, 15 Feb 2005 23:19:26 +0000
parents 8decd369825f
children 8a7df836bf64
files lisp/ChangeLog lisp/international/mule-cmds.el src/ChangeLog src/emacs.c src/s/ms-w32.h src/w32.c src/w32.h src/w32select.c
diffstat 8 files changed, 924 insertions(+), 266 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Tue Feb 15 23:04:45 2005 +0000
+++ b/lisp/ChangeLog	Tue Feb 15 23:19:26 2005 +0000
@@ -1,3 +1,8 @@
+2005-02-15  Benjamin Riefenstahl  <Benjamin.Riefenstahl@epost.de>
+
+	* international/mule-cmds.el (set-locale-environment): Remove call
+	to set-selection-coding-system on Windows.
+
 2005-02-15  Jay Belanger  <belanger@truman.edu>
 
 	* calc/calc-alg.el: Add simplification rules for calcFunc-sec,
--- a/lisp/international/mule-cmds.el	Tue Feb 15 23:04:45 2005 +0000
+++ b/lisp/international/mule-cmds.el	Tue Feb 15 23:19:26 2005 +0000
@@ -2421,13 +2421,13 @@
 	  (prefer-coding-system coding-system)
 	  (setq locale-coding-system coding-system))))
 
-    ;; On Windows, override locale-coding-system, keyboard-coding-system,
-    ;; selection-coding-system with system codepage.
+    ;; On Windows, override locale-coding-system,
+    ;; keyboard-coding-system with system codepage.  Note:
+    ;; selection-coding-system is already set in w32select.c.
     (when (boundp 'w32-ansi-code-page)
       (let ((code-page-coding (intern (format "cp%d" w32-ansi-code-page))))
 	(when (coding-system-p code-page-coding)
 	  (setq locale-coding-system code-page-coding)
-	  (set-selection-coding-system code-page-coding)
 	  (set-keyboard-coding-system code-page-coding)
 	  (set-terminal-coding-system code-page-coding))))
 
--- a/src/ChangeLog	Tue Feb 15 23:04:45 2005 +0000
+++ b/src/ChangeLog	Tue Feb 15 23:19:26 2005 +0000
@@ -1,3 +1,50 @@
+2004-02-15  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. 
+
+	* s/ms-w32.h: Guard MSC-specific #pragmas with an #ifdef.
+
 2005-02-16  Kim F. Storm  <storm@cua.dk>
 
 	* xdisp.c (BUFFER_POS_REACHED_P): Return true if pos reached and
--- a/src/emacs.c	Tue Feb 15 23:04:45 2005 +0000
+++ b/src/emacs.c	Tue Feb 15 23:19:26 2005 +0000
@@ -42,6 +42,8 @@
 
 #ifdef WINDOWSNT
 #include <fcntl.h>
+#include <windows.h> /* just for w32.h */
+#include "w32.h"
 #endif
 
 #include "lisp.h"
@@ -1654,6 +1656,7 @@
 #ifdef HAVE_NTGUI
       globals_of_w32fns ();
       globals_of_w32menu ();
+      globals_of_w32select ();
 #endif  /* HAVE_NTGUI */
     }
 
--- a/src/s/ms-w32.h	Tue Feb 15 23:04:45 2005 +0000
+++ b/src/s/ms-w32.h	Tue Feb 15 23:19:26 2005 +0000
@@ -477,8 +477,10 @@
    must include config.h to pick up this pragma.  */
 
 /* Names must be < 8 bytes */
+#ifdef _MSC_VER
 #pragma data_seg("EMDATA")
 #pragma bss_seg("EMBSS")
+#endif
 
 /* #define FULL_DEBUG */
 /* #define EMACSDEBUG */
--- a/src/w32.c	Tue Feb 15 23:04:45 2005 +0000
+++ b/src/w32.c	Tue Feb 15 23:19:26 2005 +0000
@@ -3884,6 +3884,8 @@
   /* shutdown the socket interface if necessary */
   term_winsock ();
 #endif
+
+  term_w32select ();
 }
 
 void
--- a/src/w32.h	Tue Feb 15 23:04:45 2005 +0000
+++ b/src/w32.h	Tue Feb 15 23:19:26 2005 +0000
@@ -122,16 +122,18 @@
 /* Return the string resource associated with KEY of type TYPE.  */
 extern LPBYTE w32_get_resource (char * key, LPDWORD type);
 
-extern void init_ntproc ();
-extern void term_ntproc ();
-extern void globals_of_w32 ();
-extern void syms_of_w32term ();
-extern void syms_of_w32fns ();
-extern void globals_of_w32fns ();
-extern void syms_of_w32select ();
-extern void syms_of_w32menu ();
-extern void globals_of_w32menu ();
-extern void syms_of_fontset ();
+extern void init_ntproc (void);
+extern void term_ntproc (void);
+extern void globals_of_w32 (void);
+extern void syms_of_w32term (void);
+extern void syms_of_w32fns (void);
+extern void globals_of_w32fns (void);
+extern void syms_of_w32select (void);
+extern void globals_of_w32select (void);
+extern void term_w32select (void);
+extern void syms_of_w32menu (void);
+extern void globals_of_w32menu (void);
+extern void syms_of_fontset (void);
 
 #endif /* EMACS_W32_H */
 
--- a/src/w32select.c	Tue Feb 15 23:04:45 2005 +0000
+++ b/src/w32select.c	Tue Feb 15 23:19:26 2005 +0000
@@ -1,5 +1,5 @@
 /* Selection processing for Emacs on the Microsoft W32 API.
-   Copyright (C) 1993, 1994 Free Software Foundation.
+   Copyright (C) 1993, 1994, 2004 Free Software Foundation.
 
 This file is part of GNU Emacs.
 
@@ -18,273 +18,744 @@
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-/* Written by Kevin Gallo */
+/* Written by Kevin Gallo, Benjamin Riefenstahl */
+
 
+/*
+ * Notes on usage of selection-coding-system and
+ * next-selection-coding-system on MS Windows:
+ *
+ * The selection coding system variables apply only to the version of
+ * the clipboard data that is closest in type, i.e. when a 16-bit
+ * Unicode coding system is given, they apply to he Unicode clipboard
+ * (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
+ * used.  In all other cases the OS will transparently convert
+ * formats, so no other fallback is needed.
+ *
+ * When copying or cutting (sending data to the OS), the data is
+ * announced and stored internally, but only actually rendered on
+ * request.  The requester determines the format provided.  The
+ * {next-}selection-coding-system is only used, when its corresponding
+ * clipboard type matches the type requested.
+ *
+ * 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.
+ *   (defun greek-copy (beg end)
+ *     (interactive "r")
+ *     (set-next-selection-coding-system 'cp1253-dos)
+ *     (copy-region-as-kill beg end))
+ *   (global-set-key "\C-c\C-c" 'greek-copy)
+ */
+
+/*
+ * Ideas for further directions:
+ *
+ * The encoding and decoding routines could be moved to Lisp code
+ * similar to how xselect.c does it (using well-known routine names
+ * for the delayed rendering).  If the definition of which clipboard
+ * 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 "lisp.h"
 #include "w32term.h"	/* for all of the w32 includes */
-#include "dispextern.h"	/* frame.h seems to want this */
-#include "keyboard.h"
-#include "frame.h"	/* Need this to get the X window of selected_frame */
+#include "w32heap.h"	/* os_subtype */
 #include "blockinput.h"
-#include "buffer.h"
+#include "keyboard.h"	/* cmd_error_internal() */
 #include "charset.h"
 #include "coding.h"
 #include "composite.h"
 
+
+static HGLOBAL convert_to_handle_as_ascii (void);
+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 lisp_error_handler (Lisp_Object error);
+static LRESULT CALLBACK owner_callback (HWND win, UINT msg,
+					WPARAM wp, LPARAM lp);
+static HWND create_owner (void);
+
+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);
+
+
+/* A remnant from X11: Symbol for the CLIPBORD selection type.  Other
+   selections are not used on Windows, so we don't need symbols for
+   PRIMARY and SECONDARY.  */
 Lisp_Object QCLIPBOARD;
 
-/* Coding system for communicating with other Windows programs via the
+/* Coding system for communicating with other programs via the
    clipboard.  */
 static Lisp_Object Vselection_coding_system;
 
-/* Coding system for the next communicating with other Windows programs.  */
+/* Coding system for the next communication with other programs.  */
 static Lisp_Object Vnext_selection_coding_system;
 
-/* Sequence number, used where possible to detect when we are pasting
-   our own text.  */
-static DWORD last_clipboard_sequence_number;
-extern ClipboardSequence_Proc clipboard_sequence_fn;
+/* Internal pseudo-constants, initialized in globals_of_w32select()
+   based on current system parameters. */
+static LCID DEFAULT_LCID;
+static UINT ANSICP, OEMCP;
+static Lisp_Object QUNICODE, QANSICP, QOEMCP;
+
+/* A hidden window just for the clipboard management. */
+static HWND clipboard_owner;
+/* A flag to tell WM_DESTROYCLIPBOARD who is to blame this time (just
+   checking GetClipboardOwner() doesn't work, sadly). */
+static int modifying_clipboard = 0;
+
+/* Configured transfer parameters, based on the last inspection of
+   selection-coding-system.  */
+static Lisp_Object cfg_coding_system;
+static UINT cfg_codepage;
+static LCID cfg_lcid;
+static UINT cfg_clipboard_type;
+
+/* The current state for delayed rendering. */
+static Lisp_Object current_text;
+static Lisp_Object current_coding_system;
+static int current_requires_encoding, current_num_nls;
+static UINT current_clipboard_type;
+static LCID current_lcid;
+
+#if TRACE
+#define ONTRACE(stmt) stmt
+#else
+#define ONTRACE(stmt) /*stmt*/
+#endif
+
+
+/* This function assumes that there is no multibyte character in
+   current_text, so we can short-cut encoding.  */
+
+static HGLOBAL
+convert_to_handle_as_ascii (void)
+{
+  HGLOBAL htext = NULL;
+  int nbytes;
+  int truelen;
+  unsigned char *src;
+  unsigned char *dst;
+
+  ONTRACE (fprintf (stderr, "convert_to_handle_as_ascii\n"));
+
+  nbytes = SBYTES (current_text) + 1;
+  src = SDATA (current_text);
+
+  /* We need to add to the size the number of LF chars where we have
+     to insert CR chars (the standard CF_TEXT clipboard format uses
+     CRLF line endings, while Emacs uses just LF internally).  */
+
+  truelen = nbytes + current_num_nls;
+
+  if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, truelen)) == NULL)
+    return NULL;
+
+  if ((dst = (unsigned char *) GlobalLock (htext)) == NULL)
+    {
+      GlobalFree (htext);
+      return NULL;
+    }
+
+  /* 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);
+
+  return htext;
+}
+
+/* This function assumes that there are multibyte or NUL characters in
+   current_text, or that we need to construct Unicode.  It runs the
+   text through the encoding machinery.  */
+
+static HGLOBAL
+convert_to_handle_as_coded (Lisp_Object coding_system)
+{
+  HGLOBAL htext = NULL, htext2;
+  int nbytes;
+  unsigned char *src;
+  unsigned char *dst = NULL;
+  int bufsize;
+  struct coding_system coding;
+  Lisp_Object string = Qnil;
+
+  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);
+
+  bufsize = encoding_buffer_size (&coding, nbytes) +2;
+  htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, bufsize);
+
+  if (htext != NULL)
+    dst = (unsigned char *) GlobalLock (htext);
+
+  if (dst != NULL)
+    {
+      encode_coding (&coding, src, dst, nbytes, bufsize-2);
+      /* 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);
 
-/* The last text we put into the clipboard.  This is used when the OS
-   does not support sequence numbers (NT4, 95). It is undesirable to
-   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.  */
-static unsigned char *last_clipboard_text = NULL;
-static size_t clipboard_storage_size = 0;
+  if (htext != NULL)
+    {
+      /* Shrink data block to actual size.  */
+      htext2 = GlobalReAlloc (htext, coding.produced+2,
+			      GMEM_MOVEABLE | GMEM_DDESHARE);
+      if (htext2 != NULL) htext = htext2;
+    }
+
+  return htext;
+}
+
+static Lisp_Object
+render (Lisp_Object oformat)
+{
+  HGLOBAL htext = NULL;
+  UINT format = XFASTINT (oformat);
+
+  ONTRACE (fprintf (stderr, "render\n"));
+
+  if (NILP (current_text))
+    return Qnil;
+
+  if (current_requires_encoding || format == CF_UNICODETEXT)
+    {
+      if (format == current_clipboard_type)
+	htext = convert_to_handle_as_coded (current_coding_system);
+      else
+	switch (format)
+	  {
+	  case CF_UNICODETEXT:
+	    htext = convert_to_handle_as_coded (QUNICODE);
+	    break;
+	  case CF_TEXT:
+	  case CF_OEMTEXT:
+	    {
+	      Lisp_Object cs;
+	      cs = coding_from_cp (cp_from_locale (current_lcid, format));
+	      htext = convert_to_handle_as_coded (cs);
+	      break;
+	    }
+	  }
+    }
+  else
+    htext = convert_to_handle_as_ascii ();
+
+  ONTRACE (fprintf (stderr, "render: htext = 0x%08X\n", (unsigned) htext));
+
+  if (htext == NULL)
+    return Qnil;
+
+  if (SetClipboardData (format, htext) == NULL)
+    {
+      GlobalFree(htext);
+      return Qnil;
+    }
+
+  return Qt;
+}
+
+static Lisp_Object
+render_locale (void)
+{
+  HANDLE hlocale = NULL;
+  LCID * lcid_ptr;
+
+  ONTRACE (fprintf (stderr, "render_locale\n"));
+
+  if (current_lcid == LOCALE_NEUTRAL || current_lcid == DEFAULT_LCID)
+    return Qt;
+
+  hlocale = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, sizeof (current_lcid));
+  if (hlocale == NULL)
+    return Qnil;
+
+  if ((lcid_ptr = (LCID *) GlobalLock (hlocale)) == NULL)
+    {
+      GlobalFree(hlocale);
+      return Qnil;
+    }
 
-#if 0
-DEFUN ("w32-open-clipboard", Fw32_open_clipboard, Sw32_open_clipboard, 0, 1, 0,
-       doc: /* This opens the clipboard with the given frame pointer.  */)
-     (frame)
-     Lisp_Object frame;
+  *lcid_ptr = current_lcid;
+  GlobalUnlock (hlocale);
+
+  if (SetClipboardData (CF_LOCALE, hlocale) == NULL)
+    {
+      GlobalFree(hlocale);
+      return Qnil;
+    }
+
+  return Qt;
+}
+
+/* At the end of the program, we want to ensure that our clipboard
+   data survives us.  This code will do that.  */
+
+static Lisp_Object
+render_all (void)
 {
-  BOOL ok = FALSE;
+  ONTRACE (fprintf (stderr, "render_all\n"));
+
+  /* According to the docs we should not call OpenClipboard() here,
+     but testing on W2K and working code in other projects shows that
+     it is actually necessary.  */
+
+  OpenClipboard (NULL);
+
+  /* There is no usefull means to report errors here, there are none
+     expected anyway, and even if there were errors, they wouldn't do
+     any harm.  So we just go ahead and do what has to be done without
+     bothering with error handling.  */
+
+  ++modifying_clipboard;
+  EmptyClipboard ();
+  --modifying_clipboard;
+
+  /* For text formats that we don't render here, the OS can use its
+     own translation rules instead, so we don't really need to offer
+     everything.  To minimize memory consumption we cover three
+     possible situations based on our primary format as detected from
+     selection-coding-system (see setup_config()):
+
+     - Post CF_TEXT only.  Let the OS convert to CF_OEMTEXT and the OS
+       (on NT) or the application (on 9x/Me) convert to
+       CF_UNICODETEXT.
+
+     - Post CF_OEMTEXT only.  Similar automatic conversions happen as
+       for CF_TEXT.
 
-  if (!NILP (frame))
-    CHECK_LIVE_FRAME (frame);
+     - Post CF_UNICODETEXT + CF_TEXT.  9x itself ignores
+       CF_UNICODETEXT, even though some applications can still handle
+       it.
+
+       Note 1: We render the less capable CF_TEXT *before* the more
+       capable CF_UNICODETEXT, to prevent clobbering through automatic
+       conversions, just in case.
+
+       Note 2: We could check os_subtype here and only render the
+       additional CF_TEXT on 9x/Me.  But OTOH with
+       current_clipboard_type == CF_UNICODETEXT we don't involve the
+       automatic conversions anywhere else, so to get consistent
+       results, we probably don't want to rely on it here either.  */
+
+  render_locale();
+
+  if (current_clipboard_type == CF_UNICODETEXT)
+    render (make_number (CF_TEXT));
+  render (make_number (current_clipboard_type));
+
+  CloseClipboard ();
+
+  return Qnil;
+}
+
+static void
+run_protected (Lisp_Object (*code) (), 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;
 
-  ok = OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL);
-
-  UNBLOCK_INPUT;
-
-  return (ok ? frame : Qnil);
-}
+  /* Fsignal calls abort() if it sees that waiting_for_input is
+     set.  */
+  owfi = waiting_for_input;
+  waiting_for_input = 0;
 
-DEFUN ("w32-empty-clipboard", Fw32_empty_clipboard,
-       Sw32_empty_clipboard, 0, 0, 0,
-       doc: /* Empty the clipboard.
-Assigns ownership of the clipboard to the window which opened it.  */)
-     ()
-{
-  BOOL ok = FALSE;
+  internal_condition_case_1 (code, arg, Qt, lisp_error_handler);
 
-  BLOCK_INPUT;
-
-  ok = EmptyClipboard ();
+  waiting_for_input = owfi;
 
   UNBLOCK_INPUT;
+}
 
-  return (ok ? Qt : Qnil);
+static Lisp_Object
+lisp_error_handler (Lisp_Object error)
+{
+  Vsignaling_function = Qnil;
+  cmd_error_internal (error, "Error in delayed clipboard rendering: ");
+  Vinhibit_quit = Qt;
+  return Qt;
+}
+
+
+static LRESULT CALLBACK
+owner_callback (HWND win, UINT msg, WPARAM wp, LPARAM lp)
+{
+  switch (msg)
+    {
+    case WM_RENDERFORMAT:
+      ONTRACE (fprintf (stderr, "WM_RENDERFORMAT\n"));
+      run_protected (render, make_number (wp));
+      return 0;
+
+    case WM_RENDERALLFORMATS:
+      ONTRACE (fprintf (stderr, "WM_RENDERALLFORMATS\n"));
+      run_protected (render_all, Qnil);
+      return 0;
+
+    case WM_DESTROYCLIPBOARD:
+      if (!modifying_clipboard)
+	{
+	  ONTRACE (fprintf (stderr, "WM_DESTROYCLIPBOARD (other)\n"));
+	  current_text = Qnil;
+	  current_coding_system = Qnil;
+	}
+      else
+	{
+	  ONTRACE (fprintf (stderr, "WM_DESTROYCLIPBOARD (self)\n"));
+	}
+      return 0;
+
+    case WM_DESTROY:
+      if (win == clipboard_owner)
+	clipboard_owner = NULL;
+      break;
+    }
+
+  return DefWindowProc (win, msg, wp, lp);
+}
+
+static HWND
+create_owner (void)
+{
+  static const char CLASSNAME[] = "Emacs Clipboard";
+  WNDCLASS wc;
+
+  memset (&wc, 0, sizeof (wc));
+  wc.lpszClassName = CLASSNAME;
+  wc.lpfnWndProc = owner_callback;
+  RegisterClass (&wc);
+
+  return CreateWindow (CLASSNAME, CLASSNAME, 0, 0, 0, 0, 0, NULL, NULL,
+		       NULL, NULL);
+}
+
+/* Called on exit by term_ntproc() in w32.c */
+
+void
+term_w32select (void)
+{
+  /* This is needed to trigger WM_RENDERALLFORMATS. */
+  if (clipboard_owner != NULL)
+    DestroyWindow (clipboard_owner);
 }
 
-DEFUN ("w32-close-clipboard", Fw32_close_clipboard,
-       Sw32_close_clipboard, 0, 0, 0,
-       doc: /* Close the clipboard.  */)
-     ()
+static void
+setup_config (void)
 {
-  BOOL ok = FALSE;
+  const char *coding_name;
+  const char *cp;
+  char *end;
+  int slen;
+  Lisp_Object new_coding_system;
+
+  CHECK_SYMBOL (Vselection_coding_system);
+
+  /* Check if we have it cached */
+  new_coding_system = NILP (Vnext_selection_coding_system) ?
+    Vselection_coding_system : Vnext_selection_coding_system;
+  if (!NILP (cfg_coding_system)
+      && EQ (cfg_coding_system, new_coding_system))
+    return;
+  cfg_coding_system = new_coding_system;
+  
+  /* Set some sensible fallbacks */
+  cfg_codepage = ANSICP;
+  cfg_lcid = LOCALE_NEUTRAL;
+  cfg_clipboard_type = CF_TEXT;
+
+  /* Interpret the coding system symbol name */
+  coding_name = SDATA (SYMBOL_NAME (cfg_coding_system));
+
+  /* "(.*-)?utf-16.*" -> CF_UNICODETEXT */
+  cp = strstr (coding_name, "utf-16");
+  if (cp != NULL && (cp == coding_name || cp[-1] == '-'))
+    {
+      cfg_clipboard_type = CF_UNICODETEXT;
+      return;
+    }
 
-  BLOCK_INPUT;
+  /* "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;
 
-  ok = CloseClipboard ();
+  end = (char*)cp;
+  cfg_codepage = strtol (cp, &end, 10);
 
-  UNBLOCK_INPUT;
+  /* Error return from strtol() or number of digits < 2 -> Restore the
+     default and drop it. */
+  if (cfg_codepage == 0 || (end-cp) < 2 )
+    {
+      cfg_codepage = ANSICP;
+      return;
+    }
 
-  return (ok ? Qt : Qnil);
+  /* Is it the currently active system default? */
+  if (cfg_codepage == ANSICP)
+    {
+      /* cfg_clipboard_type = CF_TEXT; */
+      return;
+    }
+  if (cfg_codepage == OEMCP)
+    {
+      cfg_clipboard_type = CF_OEMTEXT;
+      return;
+    }
+
+  /* Else determine a suitable locale the hard way. */
+  EnumSystemLocales (enum_locale_callback, LCID_INSTALLED);
 }
 
-#endif
+static BOOL WINAPI
+enum_locale_callback (/*const*/ char* loc_string)
+{
+  LCID lcid;
+  UINT codepage;
+
+  lcid = strtoul (loc_string, NULL, 16);
+
+  /* Is the wanted codepage the "ANSI" codepage for this locale? */
+  codepage = cp_from_locale (lcid, CF_TEXT);
+  if (codepage == cfg_codepage)
+    {
+      cfg_lcid = lcid;
+      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)
+    {
+      cfg_lcid = lcid;
+      cfg_clipboard_type = CF_OEMTEXT;
+      return FALSE; /* Stop enumeration */
+    }
+
+  return TRUE; /* Continue enumeration */
+}
+
+static UINT
+cp_from_locale (LCID lcid, UINT format)
+{
+  char buffer[20] = "";
+  UINT variant, cp;
+
+  variant =
+    format == CF_TEXT ? LOCALE_IDEFAULTANSICODEPAGE : LOCALE_IDEFAULTCODEPAGE;
+
+  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 Lisp_Object
+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.  */
+}
+
 
 DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data,
        Sw32_set_clipboard_data, 1, 2, 0,
        doc: /* This sets the clipboard data to the given text.  */)
-    (string, frame)
-    Lisp_Object string, frame;
+    (string, ignored)
+    Lisp_Object string, ignored;
 {
   BOOL ok = TRUE;
-  HANDLE htext;
   int nbytes;
-  int truelen, nlines = 0;
   unsigned char *src;
   unsigned char *dst;
+  unsigned char *end;
+
+  /* This parameter used to be the current frame, but we don't use
+     that any more. */
+  (void) ignored;
 
   CHECK_STRING (string);
 
-  if (!NILP (frame))
-    CHECK_LIVE_FRAME (frame);
+  setup_config ();
 
+  current_text = string;
+  current_coding_system = cfg_coding_system;
+  current_clipboard_type = cfg_clipboard_type;
+  current_lcid = cfg_lcid;
+  current_num_nls = 0;
+  current_requires_encoding = 0;
+  
   BLOCK_INPUT;
 
-  /* Include the terminating NULL character in the source of
-     conversion.  */
-  nbytes = SBYTES (string) + 1;
+  /* Check for non-ASCII characters.  While we are at it, count the
+     number of LFs, so we know how many CRs we will have to add later
+     (just in the case where we can use our internal ASCII rendering,
+     see code and comment in convert_to_handle_as_ascii() above).  */
+  nbytes = SBYTES (string);
   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)
+  for (dst = src, end = src+nbytes; dst < end; dst++)
     {
-      nlines++;
-      dst++;
+      if (*dst == '\n')
+	current_num_nls++;
+      else if (*dst >= 0x80 || *dst == 0)
+	{
+	  current_requires_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.  */
-
-	/* 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;
-
-	if ((htext = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, truelen)) == 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;
-	  }
-
-	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;
+  if (!current_requires_encoding)
+    {
+      /* If all we have is ASCII we don't need to pretend we offer
+	 anything fancy. */
+      current_coding_system = Qraw_text;
+      current_clipboard_type = CF_TEXT;
+      current_lcid = LOCALE_NEUTRAL;
+    }
 
-	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);
-	    /* Include the terminating NULL character in the source of
-	       conversion.  */
-	    nbytes = SBYTES (string) + 1;
-	  }
-	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;
-
-	/* 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);
-
-	/* Shrink data block to actual size.  */
-	htext2 = GlobalReAlloc (htext, coding.produced,
-                                GMEM_MOVEABLE | GMEM_DDESHARE);
-	if (htext2 != NULL) htext = htext2;
-      }
-  }
-
-  if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL))
+  if (!OpenClipboard (clipboard_owner))
     goto error;
 
-  ok = EmptyClipboard () && SetClipboardData (CF_TEXT, htext);
+  ++modifying_clipboard;
+  ok = EmptyClipboard ();
+  --modifying_clipboard;
+
+  /* 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());
+
+  if (ok)
+    {
+      if (clipboard_owner == NULL)
+	{
+	  /* 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)));
+	  current_text = Qnil;
+	  current_coding_system = Qnil;
+	}
+      else
+	{
+	  /* Advertise all supported formats so that whatever the
+	     requester chooses, only one encoding step needs to be
+	     made.  This is intentionally different from what we do in
+	     the handler for WM_RENDERALLFORMATS.  */
+	  SetClipboardData (CF_UNICODETEXT, NULL);
+	  SetClipboardData (CF_TEXT, NULL);
+	  SetClipboardData (CF_OEMTEXT, NULL);
+	}
+    }
 
   CloseClipboard ();
 
-  /* Common sense says to read the sequence number inside the
-     OpenClipboard/ CloseClipboard block to avoid race conditions
-     where another app puts something on the clipboard straight after
-     us. But experience suggests that the sequence number from the
-     SetClipboardData is not allocated until we close the clipboard!
-     Since clipboard operations are normally user-driven, the race
-     condition is probably not going to really happen.  */
-  if (clipboard_sequence_fn)
-    last_clipboard_sequence_number = clipboard_sequence_fn ();
+  /* With delayed rendering we haven't really "used" this coding
+     system yet, and it's even unclear if we ever will.  But this is a
+     way to tell the upper level what we *would* use under ideal
+     circumstances.
+
+     We don't signal the actually used coding-system later when we
+     finally render, because that can happen at any time and we don't
+     want to disturb the "foreground" action. */
+  if (ok)
+    Vlast_coding_system_used = current_coding_system;
+
+  Vnext_selection_coding_system = Qnil;
 
   if (ok) goto done;
 
  error:
 
   ok = FALSE;
-  if (htext) GlobalFree (htext);
-  if (last_clipboard_text)
-    *last_clipboard_text = '\0';
-
-  last_clipboard_sequence_number = 0;
+  current_text = Qnil;
+  current_coding_system = Qnil;
 
  done:
   UNBLOCK_INPUT;
@@ -292,24 +763,52 @@
   return (ok ? string : 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.  */)
-     (frame)
-     Lisp_Object frame;
+     (ignored)
+     Lisp_Object ignored;
 {
-  HANDLE htext;
+  HGLOBAL htext;
   Lisp_Object ret = Qnil;
+  UINT actual_clipboard_type;
+  int use_configured_coding_system = 1;
 
-  if (!NILP (frame))
-    CHECK_LIVE_FRAME (frame);
+  /* This parameter used to be the current frame, but we don't use
+     that any more. */
+  (void) ignored;
+
+  /* Don't pass our own text from the clipboard (which might be
+     troublesome if the killed text includes null characters).  */
+  if (!NILP (current_text))
+    return ret;
+
+  setup_config ();
+  actual_clipboard_type = cfg_clipboard_type;
 
   BLOCK_INPUT;
 
-  if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? FRAME_W32_WINDOW (XFRAME (frame)) : NULL))
+  if (!OpenClipboard (clipboard_owner))
     goto done;
 
-  if ((htext = GetClipboardData (CF_TEXT)) == NULL)
+  if ((htext = GetClipboardData (actual_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.  */
+      if (actual_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;
 
   {
@@ -322,53 +821,107 @@
     if ((src = (unsigned char *) GlobalLock (htext)) == NULL)
       goto closeclip;
 
-    nbytes = strlen (src);
-
-    /* If the text in clipboard is identical to what we put there
-       last time w32_set_clipboard_data was called, pretend there's no
-       data in the clipboard.  This is so we don't pass our own text
-       from the clipboard (which might be troublesome if the killed
-       text includes null characters).  */
-    if ((clipboard_sequence_fn
-	 && clipboard_sequence_fn () == last_clipboard_sequence_number)
-	|| (last_clipboard_text
-	    && clipboard_storage_size >= nbytes
-	    && memcmp(last_clipboard_text, src, nbytes) == 0))
-      goto closeclip;
+    /* If the clipboard data contains any non-ascii code, we need to
+       decode it with a coding system.  */
+    if (actual_clipboard_type == CF_UNICODETEXT)
+      {
+	nbytes = lstrlenW ((WCHAR *)src) * 2;
+	require_decoding = 1;
+      }
+    else
+      {
+	int i;
 
-    {
-      /* If the clipboard data contains any non-ascii code, we
-	 need to decode it.  */
-      int i;
+	nbytes = strlen (src);
 
-      for (i = 0; i < nbytes; i++)
-	{
-	  if (src[i] >= 0x80)
-	    {
-	      require_decoding = 1;
-	      break;
-	    }
-	}
-    }
+	for (i = 0; i < nbytes; i++)
+	  {
+	    if (src[i] >= 0x80)
+	      {
+		require_decoding = 1;
+		break;
+	      }
+	  }
+      }
 
     if (require_decoding)
       {
 	int bufsize;
 	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 (NILP (Vnext_selection_coding_system))
-	  Vnext_selection_coding_system = Vselection_coding_system;
-	setup_coding_system
-	  (Fcheck_coding_system (Vnext_selection_coding_system), &coding);
+	/* If we have CF_TEXT or CF_OEMTEXT, we want to check out
+	   CF_LOCALE, too. */
+	else if (actual_clipboard_type != CF_UNICODETEXT)
+	  {
+	    HGLOBAL hlocale;
+	    LCID lcid = DEFAULT_LCID;
+	    UINT cp;
+
+	    /* Documentation says that the OS always generates
+	       CF_LOCALE info automatically, so the locale handle
+	       should always be present.  Fact is that this is not
+	       always true on 9x ;-(.  */
+	    hlocale = GetClipboardData (CF_LOCALE);
+	    if (hlocale != NULL)
+	      {
+		const LCID * lcid_ptr;
+		lcid_ptr = (const LCID *) GlobalLock (hlocale);
+		if (lcid_ptr != NULL)
+		  {
+		    lcid = *lcid_ptr;
+		    GlobalUnlock (hlocale);
+		  }
+
+		/* 9x has garbage as the sort order (to be exact there
+		   is another instance of the language id in the upper
+		   word).  We don't care about sort order anyway, so
+		   we just filter out the unneeded mis-information to
+		   avoid irritations. */
+		lcid = MAKELCID (LANGIDFROMLCID (lcid), SORT_DEFAULT);
+	      }
+
+	    /* 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 || lcid != DEFAULT_LCID)
+	      {
+		cp = cp_from_locale (lcid, actual_clipboard_type);
+		/* If it's just our current standard 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 != cfg_codepage)
+		  coding_system = coding_from_cp (cp);
+	      }
+	  }
+
+	if (NILP (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;
-	Vnext_selection_coding_system = Qnil;
 	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);
@@ -382,10 +935,13 @@
       }
     else
       {
-	/* Need to know final size after CR chars are removed because we
-	   can't change the string size manually, and doing an extra
-	   copy is silly.  Note that we only remove CR when it appears
-	   as part of CRLF.  */
+	/* FIXME: We may want to repeat the code in this branch for
+	   the Unicode case. */
+
+	/* Need to know final size after CR chars are removed because
+	   we can't change the string size manually, and doing an
+	   extra copy is silly.  We only remove CR when it appears as
+	   part of CRLF.  */
 
 	truelen = nbytes;
 	dst = src;
@@ -462,9 +1018,14 @@
 
       if (OpenClipboard (NULL))
 	{
-	  int format = 0;
-	  while (format = EnumClipboardFormats (format))
-	    if (format == CF_TEXT)
+	  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
+	       not available.  Actually a check for CF_TEXT only
+	       should be enough.  */
+	    if (format == cfg_clipboard_type || format == CF_TEXT)
 	      {
 		val = Qt;
 		break;
@@ -476,24 +1037,25 @@
   return Qnil;
 }
 
+/* One-time init.  Called in the un-dumped Emacs, but not in the
+   dumped version. */
+
 void
 syms_of_w32select ()
 {
-#if 0
-  defsubr (&Sw32_open_clipboard);
-  defsubr (&Sw32_empty_clipboard);
-  defsubr (&Sw32_close_clipboard);
-#endif
   defsubr (&Sw32_set_clipboard_data);
   defsubr (&Sw32_get_clipboard_data);
   defsubr (&Sx_selection_exists_p);
 
   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 `iso-latin-1-dos'.  */);
-  Vselection_coding_system = intern ("iso-latin-1-dos");
+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. */);  
+  /* 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,
 	       doc: /* Coding system for the next communication with other programs.
@@ -504,6 +1066,41 @@
   Vnext_selection_coding_system = Qnil;
 
   QCLIPBOARD = intern ("CLIPBOARD");	staticpro (&QCLIPBOARD);
+
+  cfg_coding_system = Qnil;     staticpro (&cfg_coding_system);
+  current_text = Qnil;		staticpro (&current_text);
+  current_coding_system = Qnil; staticpro (&current_coding_system);
+
+  QUNICODE = intern ("utf-16le-dos"); staticpro (&QUNICODE);
+  QANSICP = Qnil; staticpro (&QANSICP);
+  QOEMCP = Qnil;  staticpro (&QOEMCP);
+}
+
+/* One-time init.  Called in the dumped Emacs, but not in the
+   un-dumped version. */
+
+void
+globals_of_w32select ()
+{
+  DEFAULT_LCID = GetUserDefaultLCID ();
+  /* Drop the sort order from the LCID, so we can compare this with
+     CF_LOCALE objects that have the same fix on 9x.  */
+  DEFAULT_LCID = MAKELCID (LANGIDFROMLCID (DEFAULT_LCID), SORT_DEFAULT);
+
+  ANSICP = GetACP ();
+  OEMCP = GetOEMCP ();
+
+  QANSICP = coding_from_cp (ANSICP);
+  QOEMCP = coding_from_cp (OEMCP);
+
+  if (os_subtype == OS_NT)
+    Vselection_coding_system = QUNICODE;
+  else if (inhibit_window_system)
+    Vselection_coding_system = QOEMCP;
+  else
+    Vselection_coding_system = QANSICP;
+
+  clipboard_owner = create_owner ();
 }
 
 /* arch-tag: c96e9724-5eb1-4dad-be07-289f092fd2af