* coding.c, sysdep.c: Convert some more functions to standard C.
[bpt/emacs.git] / src / w32select.c
index ad5d0e6..4ecd926 100644 (file)
@@ -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  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 <http://www.gnu.org/licenses/>.  */
 
 /* 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 <config.h>
+#include <setjmp.h>
 #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"
 
 
@@ -89,8 +89,8 @@ 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 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);
@@ -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;
 }
 
@@ -358,7 +334,7 @@ render_locale (void)
    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"));
 
@@ -416,7 +392,7 @@ render_all (void)
 }
 
 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
@@ -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
@@ -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
       {
@@ -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
@@ -1042,7 +1065,7 @@ and t is the same as `SECONDARY'.  */)
    dumped version. */
 
 void
-syms_of_w32select ()
+syms_of_w32select (void)
 {
   defsubr (&Sw32_set_clipboard_data);
   defsubr (&Sw32_get_clipboard_data);
@@ -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 (&current_text);
   current_coding_system = Qnil; staticpro (&current_coding_system);
 
-  QUNICODE = intern ("utf-16le-dos"); staticpro (&QUNICODE);
+  DEFSYM (QUNICODE, "utf-16le-dos");
   QANSICP = Qnil; staticpro (&QANSICP);
   QOEMCP = Qnil;  staticpro (&QOEMCP);
 }
@@ -1081,7 +1104,7 @@ set to nil.  */);
    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