+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);
+}
+
+static void
+setup_config (void)
+{
+ 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;
+ }
+
+ /* "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;
+ cfg_codepage = strtol (cp, &end, 10);
+
+ /* 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;
+ }
+
+ /* 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);
+}
+
+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. */