]> code.delx.au - gnu-emacs/blobdiff - src/xselect.c
(lookup_rgb_color): Handle TrueColor visuals specially.
[gnu-emacs] / src / xselect.c
index 06c0ec6362cbc39e74bc1d31ad0ab2e738a134fd..21b7ecff8abf8a4373b8519cdc3ad640a90723e0 100644 (file)
@@ -1,5 +1,5 @@
 /* X Selection processing for Emacs.
-   Copyright (C) 1993, 1994, 1995, 1996, 1997, 2000, 2001
+   Copyright (C) 1993, 1994, 1995, 1996, 1997, 2000, 2001, 2003
    Free Software Foundation.
 
 This file is part of GNU Emacs.
@@ -29,10 +29,7 @@ Boston, MA 02111-1307, USA.  */
 #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 "process.h"
-#include "composite.h"
 
 struct prop_location;
 
@@ -40,7 +37,7 @@ static Lisp_Object x_atom_to_symbol P_ ((Display *dpy, Atom atom));
 static Atom symbol_to_x_atom P_ ((struct x_display_info *, Display *,
                                  Lisp_Object));
 static void x_own_selection P_ ((Lisp_Object, Lisp_Object));
-static Lisp_Object x_get_local_selection P_ ((Lisp_Object, Lisp_Object));
+static Lisp_Object x_get_local_selection P_ ((Lisp_Object, Lisp_Object, int));
 static void x_decline_selection_request P_ ((struct input_event *));
 static Lisp_Object x_selection_request_lisp_error P_ ((Lisp_Object));
 static Lisp_Object queue_selection_requests_unwind P_ ((Lisp_Object));
@@ -96,8 +93,9 @@ Lisp_Object QPRIMARY, QSECONDARY, QSTRING, QINTEGER, QCLIPBOARD, QTIMESTAMP,
   QATOM_PAIR;
 
 Lisp_Object QCOMPOUND_TEXT;    /* This is a type of selection.  */
+Lisp_Object QUTF8_STRING;      /* This is a type of selection.  */
 
-Lisp_Object Qcompound_text_no_extensions;
+Lisp_Object Qcompound_text_with_extensions;
 
 #ifdef CUT_BUFFER_SUPPORT
 Lisp_Object QCUT_BUFFER0, QCUT_BUFFER1, QCUT_BUFFER2, QCUT_BUFFER3,
@@ -113,10 +111,12 @@ static Lisp_Object Vselection_coding_system;
 /* Coding system for the next communicating with other X clients.  */
 static Lisp_Object Vnext_selection_coding_system;
 
+static Lisp_Object Qforeign_selection;
+
 /* If this is a smaller number than the max-request-size of the display,
    emacs will use INCR selection transfer when the selection is larger
    than this.  The max-request-size is usually around 64k, so if you want
-   emacs to use incremental selection transfers when the selection is 
+   emacs to use incremental selection transfers when the selection is
    smaller than that, set this.  I added this mostly for debugging the
    incremental transfer stuff, but it might improve server performance.  */
 #define MAX_SELECTION_QUANTUM 0xFFFFFF
@@ -147,14 +147,14 @@ static Lisp_Object Vselection_alist;
 
 /* This is an alist whose CARs are selection-types (whose names are the same
    as the names of X Atoms) and whose CDRs are the names of Lisp functions to
-   call to convert the given Emacs selection value to a string representing 
+   call to convert the given Emacs selection value to a string representing
    the given selection type.  This is for Lisp-level extension of the emacs
    selection handling.  */
 static Lisp_Object Vselection_converter_alist;
 
 /* If the selection owner takes too long to reply to a selection request,
    we give up on it.  This is in milliseconds (0 = no timeout.)  */
-static int x_selection_timeout;
+static EMACS_INT x_selection_timeout;
 \f
 /* Utility functions */
 
@@ -162,7 +162,7 @@ static void lisp_data_to_selection_data ();
 static Lisp_Object selection_data_to_lisp_data ();
 static Lisp_Object x_get_window_property_as_lisp_data ();
 
-/* This converts a Lisp symbol to a server Atom, avoiding a server 
+/* This converts a Lisp symbol to a server Atom, avoiding a server
    roundtrip whenever possible.  */
 
 static Atom
@@ -182,6 +182,7 @@ symbol_to_x_atom (dpyinfo, display, sym)
   if (EQ (sym, QTIMESTAMP)) return dpyinfo->Xatom_TIMESTAMP;
   if (EQ (sym, QTEXT))     return dpyinfo->Xatom_TEXT;
   if (EQ (sym, QCOMPOUND_TEXT)) return dpyinfo->Xatom_COMPOUND_TEXT;
+  if (EQ (sym, QUTF8_STRING)) return dpyinfo->Xatom_UTF8_STRING;
   if (EQ (sym, QDELETE))    return dpyinfo->Xatom_DELETE;
   if (EQ (sym, QMULTIPLE))  return dpyinfo->Xatom_MULTIPLE;
   if (EQ (sym, QINCR))     return dpyinfo->Xatom_INCR;
@@ -200,9 +201,9 @@ symbol_to_x_atom (dpyinfo, display, sym)
 #endif
   if (!SYMBOLP (sym)) abort ();
 
-  TRACE1 (" XInternAtom %s", (char *) XSYMBOL (sym)->name->data);
+  TRACE1 (" XInternAtom %s", (char *) SDATA (SYMBOL_NAME (sym)));
   BLOCK_INPUT;
-  val = XInternAtom (display, (char *) XSYMBOL (sym)->name->data, False);
+  val = XInternAtom (display, (char *) SDATA (SYMBOL_NAME (sym)), False);
   UNBLOCK_INPUT;
   return val;
 }
@@ -219,10 +220,10 @@ x_atom_to_symbol (dpy, atom)
   struct x_display_info *dpyinfo;
   char *str;
   Lisp_Object val;
-  
+
   if (! atom)
     return Qnil;
-  
+
   switch (atom)
     {
     case XA_PRIMARY:
@@ -264,6 +265,8 @@ x_atom_to_symbol (dpy, atom)
     return QTEXT;
   if (atom == dpyinfo->Xatom_COMPOUND_TEXT)
     return QCOMPOUND_TEXT;
+  if (atom == dpyinfo->Xatom_UTF8_STRING)
+    return QUTF8_STRING;
   if (atom == dpyinfo->Xatom_DELETE)
     return QDELETE;
   if (atom == dpyinfo->Xatom_MULTIPLE)
@@ -291,7 +294,7 @@ x_atom_to_symbol (dpy, atom)
 }
 \f
 /* Do protocol to assert ourself as a selection owner.
-   Update the Vselection_alist so that we can reply to later requests for 
+   Update the Vselection_alist so that we can reply to later requests for
    our selection.  */
 
 static void
@@ -350,14 +353,15 @@ x_own_selection (selection_name, selection_value)
 /* Given a selection-name and desired type, look up our local copy of
    the selection value and convert it to the type.
    The value is nil or a string.
-   This function is used both for remote requests
-   and for local x-get-selection-internal.
+   This function is used both for remote requests (LOCAL_REQUEST is zero)
+   and for local x-get-selection-internal (LOCAL_REQUEST is nonzero).
 
    This calls random Lisp code, and may signal or gc.  */
 
 static Lisp_Object
-x_get_local_selection (selection_symbol, target_type)
+x_get_local_selection (selection_symbol, target_type, local_request)
      Lisp_Object selection_symbol, target_type;
+     int local_request;
 {
   Lisp_Object local_value;
   Lisp_Object handler_fn, value, type, check;
@@ -404,7 +408,8 @@ x_get_local_selection (selection_symbol, target_type)
          pair = XVECTOR (pairs)->contents [i];
          XVECTOR (pair)->contents [1]
            = x_get_local_selection (XVECTOR (pair)->contents [0],
-                                    XVECTOR (pair)->contents [1]);
+                                    XVECTOR (pair)->contents [1],
+                                    local_request);
        }
       return pairs;
     }
@@ -414,14 +419,17 @@ x_get_local_selection (selection_symbol, target_type)
       /* Don't allow a quit within the converter.
         When the user types C-g, he would be surprised
         if by luck it came during a converter.  */
-      count = specpdl_ptr - specpdl;
+      count = SPECPDL_INDEX ();
       specbind (Qinhibit_quit, Qt);
 
       CHECK_SYMBOL (target_type);
       handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist));
+      /* gcpro is not needed here since nothing but HANDLER_FN
+        is live, and that ought to be a symbol.  */
+
       if (!NILP (handler_fn))
        value = call3 (handler_fn,
-                      selection_symbol, target_type,
+                      selection_symbol, (local_request ? Qnil : target_type),
                       XCAR (XCDR (local_value)));
       else
        value = Qnil;
@@ -436,7 +444,7 @@ x_get_local_selection (selection_symbol, target_type)
       && SYMBOLP (XCAR (value)))
     type = XCAR (value),
     check = XCDR (value);
-  
+
   if (STRINGP (check)
       || VECTORP (check)
       || SYMBOLP (check)
@@ -470,7 +478,7 @@ x_decline_selection_request (event)
 {
   XSelectionEvent reply;
   int count;
-  
+
   reply.type = SelectionNotify;
   reply.display = SELECTION_EVENT_DISPLAY (event);
   reply.requestor = SELECTION_EVENT_REQUESTOR (event);
@@ -644,7 +652,7 @@ x_reply_selection_request (event, format, data, size, type)
 
       if (x_window_to_frame (dpyinfo, window)) /* #### debug */
        error ("Attempt to transfer an INCR to ourself!");
-      
+
       TRACE2 ("Start sending %d bytes incrementally (%s)",
              bytes_remaining,  XGetAtomName (display, reply.property));
       wait_object = expect_property_change (display, window, reply.property,
@@ -656,7 +664,7 @@ x_reply_selection_request (event, format, data, size, type)
                       32, PropModeReplace,
                       (unsigned char *) &bytes_remaining, 1);
       XSelectInput (display, window, PropertyChangeMask);
-      
+
       /* Tell 'em the INCR data is there...  */
       TRACE0 ("Send SelectionNotify event");
       XSendEvent (display, window, False, 0L, (XEvent *) &reply);
@@ -690,7 +698,7 @@ x_reply_selection_request (event, format, data, size, type)
          TRACE1 ("Sending increment of %d bytes", i);
          TRACE1 ("Set %s to increment data",
                  XGetAtomName (display, reply.property));
-         
+
          /* Append the next chunk of data to the property.  */
          XChangeProperty (display, window, reply.property, type, format,
                           PropModeAppend, data, i / format_bytes);
@@ -709,7 +717,7 @@ x_reply_selection_request (event, format, data, size, type)
                  XGetAtomName (display, reply.property));
          wait_for_property_change (wait_object);
        }
-      
+
       /* Now write a zero-length chunk to the property to tell the
         requester that we're done.  */
       BLOCK_INPUT;
@@ -723,6 +731,7 @@ x_reply_selection_request (event, format, data, size, type)
       TRACE0 ("Done sending incrementally");
     }
 
+  /* rms, 2003-01-03: I think I have fixed this bug.  */
   /* The window we're communicating with may have been deleted
      in the meantime (that's a real situation from a bug report).
      In this case, there may be events in the event queue still
@@ -786,7 +795,7 @@ x_handle_selection_request (event)
     }
 
   x_selection_current_request = event;
-  count = BINDING_STACK_SIZE ();
+  count = SPECPDL_INDEX ();
   selection_request_dpyinfo = dpyinfo;
   record_unwind_protect (x_selection_request_lisp_error, Qnil);
 
@@ -797,12 +806,12 @@ x_handle_selection_request (event)
   if (EQ (target_symbol, QMULTIPLE))
     target_symbol = fetch_multiple_target (event);
 #endif
-  
+
   /* Convert lisp objects back into binary data */
-  
+
   converted_selection
-    = x_get_local_selection (selection_symbol, target_symbol);
-  
+    = x_get_local_selection (selection_symbol, target_symbol, 0);
+
   if (! NILP (converted_selection))
     {
       unsigned char *data;
@@ -814,7 +823,7 @@ x_handle_selection_request (event)
       lisp_data_to_selection_data (SELECTION_EVENT_DISPLAY (event),
                                   converted_selection,
                                   &data, &type, &size, &format, &nofree);
-      
+
       x_reply_selection_request (event, format, data, size, type);
       successful_p = Qt;
 
@@ -830,8 +839,6 @@ x_handle_selection_request (event)
 
  DONE:
 
-  UNGCPRO;
-
   /* Let random lisp code notice that the selection has been asked for.  */
   {
     Lisp_Object rest;
@@ -840,6 +847,8 @@ x_handle_selection_request (event)
       for (; CONSP (rest); rest = Fcdr (rest))
        call3 (Fcar (rest), selection_symbol, target_symbol, successful_p);
   }
+
+  UNGCPRO;
 }
 \f
 /* Handle a SelectionClear event EVENT, which indicates that some
@@ -853,7 +862,7 @@ x_handle_selection_clear (event)
   Display *display = SELECTION_EVENT_DISPLAY (event);
   Atom selection = SELECTION_EVENT_SELECTION (event);
   Time changed_owner_time = SELECTION_EVENT_TIME (event);
-  
+
   Lisp_Object selection_symbol, local_selection_data;
   Time local_selection_time;
   struct x_display_info *dpyinfo = x_display_info_for_display (display);
@@ -1074,7 +1083,7 @@ wait_for_property_change (location)
      struct prop_location *location;
 {
   int secs, usecs;
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
   Lisp_Object tem;
 
   tem = Fcons (Qnil, Qnil);
@@ -1139,7 +1148,7 @@ x_handle_property_notify (event)
          xfree (rest);
          return;
        }
-      
+
       prev = rest;
       rest = rest->next;
     }
@@ -1174,7 +1183,7 @@ copy_multiple_data (obj)
   int size;
   if (CONSP (obj))
     return Fcons (XCAR (obj), copy_multiple_data (XCDR (obj)));
-    
+
   CHECK_VECTOR (obj);
   vec = Fmake_vector (size = XVECTOR (obj)->size, Qnil);
   for (i = 0; i < size; i++)
@@ -1227,9 +1236,9 @@ x_get_foreign_selection (selection_symbol, target_type)
     type_atom = symbol_to_x_atom (dpyinfo, display, target_type);
 
   BLOCK_INPUT;
-  
+
   count = x_catch_errors (display);
-  
+
   TRACE2 ("Get selection %s, type %s",
          XGetAtomName (display, type_atom),
          XGetAtomName (display, target_property));
@@ -1272,7 +1281,7 @@ x_get_foreign_selection (selection_symbol, target_type)
   if (NILP (XCAR (reading_selection_reply)))
     error ("Timed out waiting for reply from selection owner");
   if (EQ (XCAR (reading_selection_reply), Qlambda))
-    error ("No `%s' selection", XSYMBOL (selection_symbol)->name->data);
+    error ("No `%s' selection", SDATA (SYMBOL_NAME (selection_symbol)));
 
   /* Otherwise, the selection is waiting for us on the requested property.  */
   return
@@ -1305,12 +1314,12 @@ x_get_window_property (display, window, property, data_ret, bytes_ret,
   unsigned char *tmp_data = 0;
   int result;
   int buffer_size = SELECTION_QUANTUM (display);
-  
+
   if (buffer_size > MAX_SELECTION_QUANTUM)
     buffer_size = MAX_SELECTION_QUANTUM;
-  
+
   BLOCK_INPUT;
-  
+
   /* First probe the thing to find out how big it is.  */
   result = XGetWindowProperty (display, window, property,
                               0L, 0L, False, AnyPropertyType,
@@ -1324,10 +1333,10 @@ x_get_window_property (display, window, property, data_ret, bytes_ret,
       *bytes_ret = 0;
       return;
     }
-  
+
   /* This was allocated by Xlib, so use XFree.  */
   XFree ((char *) tmp_data);
-  
+
   if (*actual_type_ret == None || *actual_format_ret == 0)
     {
       UNBLOCK_INPUT;
@@ -1336,7 +1345,7 @@ x_get_window_property (display, window, property, data_ret, bytes_ret,
 
   total_size = bytes_remaining + 1;
   *data_ret = (unsigned char *) xmalloc (total_size);
-  
+
   /* Now read, until we've gotten it all.  */
   while (bytes_remaining)
     {
@@ -1363,7 +1372,7 @@ x_get_window_property (display, window, property, data_ret, bytes_ret,
       *actual_size_ret *= *actual_format_ret / 8;
       bcopy (tmp_data, (*data_ret) + offset, *actual_size_ret);
       offset += *actual_size_ret;
-      
+
       /* This was allocated by Xlib, so use XFree.  */
       XFree ((char *) tmp_data);
     }
@@ -1424,7 +1433,7 @@ receive_incremental_selection (display, window, property, target_type,
 
       TRACE0 ("  Wait for property change");
       wait_for_property_change (wait_object);
-      
+
       /* expect it again immediately, because x_get_window_property may
         .. no it won't, I don't get it.
         .. Ok, I get it now, the Xt code that implements INCR is broken. */
@@ -1462,10 +1471,10 @@ receive_incremental_selection (display, window, property, target_type,
          *size_bytes_ret = offset + tmp_size_bytes;
          *data_ret = (unsigned char *) xrealloc (*data_ret, *size_bytes_ret);
        }
-      
+
       bcopy (tmp_data, (*data_ret) + offset, tmp_size_bytes);
       offset += tmp_size_bytes;
-      
+
       /* Use xfree, not XFree, because x_get_window_property
         calls xmalloc itself.  */
       xfree (tmp_data);
@@ -1519,7 +1528,7 @@ x_get_window_property_as_lisp_data (display, window, property, target_type,
                                                 selection_atom),
                               Qnil)));
     }
-  
+
   if (actual_type == dpyinfo->Xatom_INCR)
     {
       /* That wasn't really the data, just the beginning.  */
@@ -1546,7 +1555,7 @@ x_get_window_property_as_lisp_data (display, window, property, target_type,
      manner.  */
   val = selection_data_to_lisp_data (display, data, bytes,
                                     actual_type, actual_format);
-  
+
   /* Use xfree, not XFree, because x_get_window_property
      calls xmalloc itself.  */
   xfree ((char *) data);
@@ -1595,70 +1604,21 @@ selection_data_to_lisp_data (display, data, size, type, format)
   /* Convert any 8-bit data to a string, for compactness.  */
   else if (format == 8)
     {
-      Lisp_Object str;
-      int require_encoding = 0;
-
-      if (
-#if 1
-         1
-#else
-         ! NILP (buffer_defaults.enable_multibyte_characters)
-#endif
-         )
-       {
-         /* If TYPE is `TEXT' or `COMPOUND_TEXT', we should decode
-            DATA to Emacs internal format because DATA may be encoded
-            in compound text format.  In addtion, if TYPE is `STRING'
-            and DATA contains any 8-bit Latin-1 code, we should also
-            decode it.  */
-         if (type == dpyinfo->Xatom_TEXT
-             || type == dpyinfo->Xatom_COMPOUND_TEXT)
-           require_encoding = 1;
-         else if (type == XA_STRING)
-           {
-             int i;
-             for (i = 0; i < size; i++)
-               {
-                 if (data[i] >= 0x80)
-                   {
-                     require_encoding = 1;
-                     break;
-                   }
-               }
-           }
-       }
-      if (!require_encoding)
-       {
-         str = make_unibyte_string ((char *) data, size);
-         Vlast_coding_system_used = Qraw_text;
-       }
+      Lisp_Object str, lispy_type;
+
+      str = make_unibyte_string ((char *) data, size);
+      /* Indicate that this string is from foreign selection by a text
+        property `foreign-selection' so that the caller of
+        x-get-selection-internal (usually x-get-selection) can know
+        that the string must be decode.  */
+      if (type == dpyinfo->Xatom_COMPOUND_TEXT)
+       lispy_type = QCOMPOUND_TEXT;
+      else if (type == dpyinfo->Xatom_UTF8_STRING)
+       lispy_type = QUTF8_STRING;
       else
-       {
-         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;
-         bufsize = decoding_buffer_size (&coding, size);
-         buf = (unsigned char *) xmalloc (bufsize);
-         decode_coding (&coding, data, buf, size, bufsize);
-         str = 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)))
-           str = run_pre_post_conversion_on_str (str, &coding, 0);
-         Vlast_coding_system_used = coding.symbol;
-       }
-      compose_chars_in_text (0, XSTRING (str)->size, str);
+       lispy_type = QSTRING;
+      Fput_text_property (make_number (0), make_number (size),
+                         Qforeign_selection, lispy_type, str);
       return str;
     }
   /* Convert a single atom to a Lisp_Symbol.  Convert a set of atoms to
@@ -1684,8 +1644,8 @@ selection_data_to_lisp_data (display, data, size, type, format)
      If the number is > 16 bits, convert it to a cons of integers,
      16 bits in each half.
    */
-  else if (format == 32 && size == sizeof (long))
-    return long_to_cons (((unsigned long *) data) [0]);
+  else if (format == 32 && size == sizeof (int))
+    return long_to_cons (((unsigned int *) data) [0]);
   else if (format == 16 && size == sizeof (short))
     return make_number ((int) (((unsigned short *) data) [0]));
 
@@ -1710,7 +1670,7 @@ selection_data_to_lisp_data (display, data, size, type, format)
       Lisp_Object v = Fmake_vector (make_number (size / 4), make_number (0));
       for (i = 0; i < size / 4; i++)
        {
-         unsigned long j = ((unsigned long *) data) [i];
+         unsigned int j = ((unsigned int *) data) [i];
          Faset (v, make_number (i), long_to_cons (j));
        }
       return v;
@@ -1754,26 +1714,13 @@ lisp_data_to_selection_data (display, obj,
     }
   else if (STRINGP (obj))
     {
-      /* Since we are now handling multilingual text, we must consider
-        sending back compound text.  */
-      int stringp;
-
-      if (NILP (Vnext_selection_coding_system))
-       Vnext_selection_coding_system = Vselection_coding_system;
-
+      xassert (! STRING_MULTIBYTE (obj));
+      if (NILP (type))
+       type = QSTRING;
       *format_ret = 8;
-      *data_ret = x_encode_text (obj, Vnext_selection_coding_system, 1,
-                                (int *) size_ret, &stringp);
-      *nofree_ret = (*data_ret == XSTRING (obj)->data);
-      if (EQ (Vnext_selection_coding_system,
-             Qcompound_text_no_extensions))
-       type = QCOMPOUND_TEXT;
-      else if (NILP (type))
-       type = (stringp ? QSTRING : QCOMPOUND_TEXT);
-      Vlast_coding_system_used = (*nofree_ret
-                                 ? Qraw_text
-                                 : Vnext_selection_coding_system);
-      Vnext_selection_coding_system = Qnil;
+      *size_ret = SBYTES (obj);
+      *data_ret = SDATA (obj);
+      *nofree_ret = 1;
     }
   else if (SYMBOLP (obj))
     {
@@ -1848,10 +1795,10 @@ lisp_data_to_selection_data (display, obj,
                Lisp_Object pair = XVECTOR (obj)->contents [i];
                if (XVECTOR (pair)->size != 2)
                  Fsignal (Qerror,
-                          Fcons (build_string 
+                          Fcons (build_string
        ("elements of the vector must be vectors of exactly two elements"),
                                  Fcons (pair, Qnil)));
-               
+
                (*(Atom **) data_ret) [i * 2]
                  = symbol_to_x_atom (dpyinfo, display,
                                      XVECTOR (pair)->contents [0]);
@@ -1864,7 +1811,7 @@ lisp_data_to_selection_data (display, obj,
                       Fcons (build_string
                   ("all elements of the vector must be of the same type"),
                              Fcons (obj, Qnil)));
-         
+
        }
 #endif
       else
@@ -2005,7 +1952,7 @@ TYPE is the type of data desired, typically `STRING'.  */)
 #endif
     CHECK_SYMBOL (target_type);
 
-  val = x_get_local_selection (selection_symbol, target_type);
+  val = x_get_local_selection (selection_symbol, target_type, 1);
 
   if (NILP (val))
     {
@@ -2108,7 +2055,7 @@ and t is the same as `SECONDARY'.  */)
   CHECK_SYMBOL (selection);
   if (EQ (selection, Qnil)) selection = QPRIMARY;
   if (EQ (selection, Qt)) selection = QSECONDARY;
-  
+
   if (NILP (Fassq (selection, Vselection_alist)))
     return Qnil;
   return Qt;
@@ -2215,7 +2162,7 @@ DEFUN ("x-get-cut-buffer-internal", Fx_get_cut_buffer_internal,
                         &type, &format, &size, 0);
   if (!data || !format)
     return Qnil;
-  
+
   if (format != 8 || type != XA_STRING)
     Fsignal (Qerror,
             Fcons (build_string ("cut buffer doesn't contain 8-bit data"),
@@ -2257,8 +2204,8 @@ DEFUN ("x-store-cut-buffer-internal", Fx_store_cut_buffer_internal,
   CHECK_STRING (string);
   buffer_atom = symbol_to_x_atom (FRAME_X_DISPLAY_INFO (sf),
                                  display, buffer);
-  data = (unsigned char *) XSTRING (string)->data;
-  bytes = STRING_BYTES (XSTRING (string));
+  data = (unsigned char *) SDATA (string);
+  bytes = SBYTES (string);
   bytes_remaining = bytes;
 
   if (! FRAME_X_DISPLAY_INFO (sf)->cut_buffers_initialized)
@@ -2400,14 +2347,14 @@ it merely informs you that they have happened.  */);
               doc: /* Coding system for communicating with other X clients.
 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 `compound-text'.  */);
-  Vselection_coding_system = intern ("compound-text");
+The default value is `compound-text-with-extensions'.  */);
+  Vselection_coding_system = intern ("compound-text-with-extensions");
 
   DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system,
               doc: /* Coding system for the next communication with other X clients.
 Usually, `selection-coding-system' is used for communicating with
-other X clients.   But, if this variable is set, it is used for the
-next communication only.   After the communication, this variable is
+other X clients.  But, if this variable is set, it is used for the
+next communication only.  After the communication, this variable is
 set to nil.  */);
   Vnext_selection_coding_system = Qnil;
 
@@ -2426,6 +2373,7 @@ A value of 0 means wait as long as necessary.  This is initialized from the
   QTIMESTAMP = intern ("TIMESTAMP");   staticpro (&QTIMESTAMP);
   QTEXT      = intern ("TEXT");        staticpro (&QTEXT);
   QCOMPOUND_TEXT = intern ("COMPOUND_TEXT"); staticpro (&QCOMPOUND_TEXT);
+  QUTF8_STRING = intern ("UTF8_STRING"); staticpro (&QUTF8_STRING);
   QTIMESTAMP = intern ("TIMESTAMP");   staticpro (&QTIMESTAMP);
   QDELETE    = intern ("DELETE");      staticpro (&QDELETE);
   QMULTIPLE  = intern ("MULTIPLE");    staticpro (&QMULTIPLE);
@@ -2435,8 +2383,8 @@ A value of 0 means wait as long as necessary.  This is initialized from the
   QATOM             = intern ("ATOM");         staticpro (&QATOM);
   QATOM_PAIR = intern ("ATOM_PAIR");   staticpro (&QATOM_PAIR);
   QNULL             = intern ("NULL");         staticpro (&QNULL);
-  Qcompound_text_no_extensions = intern ("compound-text-no-extensions");
-  staticpro (&Qcompound_text_no_extensions);
+  Qcompound_text_with_extensions = intern ("compound-text-with-extensions");
+  staticpro (&Qcompound_text_with_extensions);
 
 #ifdef CUT_BUFFER_SUPPORT
   QCUT_BUFFER0 = intern ("CUT_BUFFER0"); staticpro (&QCUT_BUFFER0);
@@ -2449,4 +2397,6 @@ A value of 0 means wait as long as necessary.  This is initialized from the
   QCUT_BUFFER7 = intern ("CUT_BUFFER7"); staticpro (&QCUT_BUFFER7);
 #endif
 
+  Qforeign_selection = intern ("foreign-selection");
+  staticpro (&Qforeign_selection);
 }