emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to emacs/src/w32select.c


From: Jason Rumney
Subject: [Emacs-diffs] Changes to emacs/src/w32select.c
Date: Tue, 15 Feb 2005 18:19:27 -0500

Index: emacs/src/w32select.c
diff -c emacs/src/w32select.c:1.33 emacs/src/w32select.c:1.34
*** emacs/src/w32select.c:1.33  Wed Jun 30 23:30:39 2004
--- emacs/src/w32select.c       Tue Feb 15 23:19:26 2005
***************
*** 1,5 ****
  /* Selection processing for Emacs on the Microsoft W32 API.
!    Copyright (C) 1993, 1994 Free Software Foundation.
  
  This file is part of GNU Emacs.
  
--- 1,5 ----
  /* Selection processing for Emacs on the Microsoft W32 API.
!    Copyright (C) 1993, 1994, 2004 Free Software Foundation.
  
  This file is part of GNU Emacs.
  
***************
*** 18,290 ****
  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  Boston, MA 02111-1307, USA.  */
  
! /* Written by Kevin Gallo */
  
  #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 "blockinput.h"
! #include "buffer.h"
  #include "charset.h"
  #include "coding.h"
  #include "composite.h"
  
  Lisp_Object QCLIPBOARD;
  
! /* Coding system for communicating with other Windows programs via the
     clipboard.  */
  static Lisp_Object Vselection_coding_system;
  
! /* Coding system for the next communicating with other Windows 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;
! 
! /* 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 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;
  {
!   BOOL ok = FALSE;
  
!   if (!NILP (frame))
!     CHECK_LIVE_FRAME (frame);
  
!   BLOCK_INPUT;
  
!   ok = OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? 
FRAME_W32_WINDOW (XFRAME (frame)) : NULL);
  
!   UNBLOCK_INPUT;
  
!   return (ok ? frame : Qnil);
  }
  
! 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;
  
!   BLOCK_INPUT;
  
!   ok = EmptyClipboard ();
  
!   UNBLOCK_INPUT;
  
!   return (ok ? Qt : Qnil);
  }
  
! DEFUN ("w32-close-clipboard", Fw32_close_clipboard,
!        Sw32_close_clipboard, 0, 0, 0,
!        doc: /* Close the clipboard.  */)
!      ()
  {
!   BOOL ok = FALSE;
  
    BLOCK_INPUT;
  
!   ok = CloseClipboard ();
  
    UNBLOCK_INPUT;
  
!   return (ok ? Qt : Qnil);
  }
  
- #endif
  
! 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;
  {
!   BOOL ok = TRUE;
!   HANDLE htext;
!   int nbytes;
!   int truelen, nlines = 0;
!   unsigned char *src;
!   unsigned char *dst;
  
!   CHECK_STRING (string);
  
!   if (!NILP (frame))
!     CHECK_LIVE_FRAME (frame);
  
!   BLOCK_INPUT;
  
!   /* Include the terminating NULL character in the source of
!      conversion.  */
!   nbytes = SBYTES (string) + 1;
!   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)
      {
!       nlines++;
!       dst++;
      }
  
!   {
!     /* 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 (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))
      goto error;
  
!   ok = EmptyClipboard () && SetClipboardData (CF_TEXT, htext);
  
    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 ();
  
    if (ok) goto done;
  
   error:
  
    ok = FALSE;
!   if (htext) GlobalFree (htext);
!   if (last_clipboard_text)
!     *last_clipboard_text = '\0';
! 
!   last_clipboard_sequence_number = 0;
  
   done:
    UNBLOCK_INPUT;
--- 18,761 ----
  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  Boston, MA 02111-1307, USA.  */
  
! /* 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 "w32heap.h"  /* os_subtype */
  #include "blockinput.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 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 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);
! 
!   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;
!     }
! 
!   *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)
! {
!   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.
! 
!      - 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;
  
!   /* Fsignal calls abort() if it sees that waiting_for_input is
!      set.  */
!   owfi = waiting_for_input;
!   waiting_for_input = 0;
! 
!   internal_condition_case_1 (code, arg, Qt, lisp_error_handler);
! 
!   waiting_for_input = owfi;
  
    UNBLOCK_INPUT;
+ }
  
! 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.  */
! }
  
  
! 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;
! {
!   BOOL ok = TRUE;
!   int nbytes;
!   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);
! 
!   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;
! 
!   /* 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);
  
!   for (dst = src, end = src+nbytes; dst < end; dst++)
!     {
!       if (*dst == '\n')
!       current_num_nls++;
!       else if (*dst >= 0x80 || *dst == 0)
!       {
!         current_requires_encoding = 1;
!         break;
!       }
!     }
! 
!   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 (!OpenClipboard (clipboard_owner))
      goto error;
  
!   ++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 ();
  
!   /* 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;
!   current_text = Qnil;
!   current_coding_system = Qnil;
  
   done:
    UNBLOCK_INPUT;
***************
*** 292,315 ****
    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;
  {
!   HANDLE htext;
    Lisp_Object ret = Qnil;
  
!   if (!NILP (frame))
!     CHECK_LIVE_FRAME (frame);
  
    BLOCK_INPUT;
  
!   if (!OpenClipboard ((!NILP (frame) && FRAME_W32_P (XFRAME (frame))) ? 
FRAME_W32_WINDOW (XFRAME (frame)) : NULL))
      goto done;
  
!   if ((htext = GetClipboardData (CF_TEXT)) == NULL)
      goto closeclip;
  
    {
--- 763,814 ----
    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.  */)
!      (ignored)
!      Lisp_Object ignored;
  {
!   HGLOBAL htext;
    Lisp_Object ret = Qnil;
+   UINT actual_clipboard_type;
+   int use_configured_coding_system = 1;
  
!   /* 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 (clipboard_owner))
      goto done;
  
!   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,374 ****
      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.  */
!       int i;
  
!       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;
  
!       if (NILP (Vnext_selection_coding_system))
!         Vnext_selection_coding_system = Vselection_coding_system;
!       setup_coding_system
!         (Fcheck_coding_system (Vnext_selection_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;
        bufsize = decoding_buffer_size (&coding, nbytes);
        buf = (unsigned char *) xmalloc (bufsize);
        decode_coding (&coding, src, buf, nbytes, bufsize);
--- 821,927 ----
      if ((src = (unsigned char *) GlobalLock (htext)) == NULL)
        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;
  
!       nbytes = strlen (src);
  
!       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 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;
        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,391 ****
        }
      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.  */
  
        truelen = nbytes;
        dst = src;
--- 935,947 ----
        }
      else
        {
!       /* 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,470 ****
  
        if (OpenClipboard (NULL))
        {
!         int format = 0;
!         while (format = EnumClipboardFormats (format))
!           if (format == CF_TEXT)
              {
                val = Qt;
                break;
--- 1018,1031 ----
  
        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
!              not available.  Actually a check for CF_TEXT only
!              should be enough.  */
!           if (format == cfg_clipboard_type || format == CF_TEXT)
              {
                val = Qt;
                break;
***************
*** 476,499 ****
    return Qnil;
  }
  
  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");
  
    DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system,
               doc: /* Coding system for the next communication with other 
programs.
--- 1037,1061 ----
    return Qnil;
  }
  
+ /* One-time init.  Called in the un-dumped Emacs, but not in the
+    dumped version. */
+ 
  void
  syms_of_w32select ()
  {
    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 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,509 ****
--- 1066,1106 ----
    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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]