]> code.delx.au - gnu-emacs/blobdiff - src/xselect.c
(gnus-start-news-server): Use expand-file-name, not
[gnu-emacs] / src / xselect.c
index 2a94e2a7cde3df4959b709fc1524fc51d08c0c0b..289d01e03b93e039139773aa3c7e39e71fdf572d 100644 (file)
@@ -1,5 +1,5 @@
 /* X Selection processing for Emacs.
-   Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation.
+   Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation.
 
 This file is part of GNU Emacs.
 
@@ -27,8 +27,11 @@ Boston, MA 02111-1307, USA.  */
 #include "dispextern.h"        /* frame.h seems to want this */
 #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"
 
 #define CUT_BUFFER_SUPPORT
 
@@ -45,6 +48,12 @@ Lisp_Object QCUT_BUFFER0, QCUT_BUFFER1, QCUT_BUFFER2, QCUT_BUFFER3,
 
 static Lisp_Object Vx_lost_selection_hooks;
 static Lisp_Object Vx_sent_selection_hooks;
+/* Coding system for communicating with other X clients via cutbuffer,
+   selection, and clipboard.  */
+static Lisp_Object Vselection_coding_system;
+
+/* Coding system for the next communicating with other X clients.  */
+static Lisp_Object Vnext_selection_coding_system;
 
 /* 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
@@ -231,11 +240,12 @@ static void
 x_own_selection (selection_name, selection_value)
      Lisp_Object selection_name, selection_value;
 {
-  Window selecting_window = FRAME_X_WINDOW (selected_frame);
-  Display *display = FRAME_X_DISPLAY (selected_frame);
+  struct frame *sf = SELECTED_FRAME ();
+  Window selecting_window = FRAME_X_WINDOW (sf);
+  Display *display = FRAME_X_DISPLAY (sf);
   Time time = last_event_timestamp;
   Atom selection_atom;
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (selected_frame);
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (sf);
   int count;
 
   CHECK_SYMBOL (selection_name, 0);
@@ -258,7 +268,7 @@ x_own_selection (selection_name, selection_value)
     selection_data = Fcons (selection_name,
                            Fcons (selection_value,
                                   Fcons (selection_time,
-                                         Fcons (Fselected_frame (), Qnil))));
+                                         Fcons (selected_frame, Qnil))));
     prev_value = assq_no_quit (selection_name, Vselection_alist);
 
     Vselection_alist = Fcons (selection_data, Vselection_alist);
@@ -270,9 +280,9 @@ x_own_selection (selection_name, selection_value)
       {
        Lisp_Object rest;       /* we know it's not the CAR, so it's easy.  */
        for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest))
-         if (EQ (prev_value, Fcar (XCONS (rest)->cdr)))
+         if (EQ (prev_value, Fcar (XCDR (rest))))
            {
-             XCONS (rest)->cdr = Fcdr (XCONS (rest)->cdr);
+             XCDR (rest) = Fcdr (XCDR (rest));
              break;
            }
       }
@@ -303,7 +313,7 @@ x_get_local_selection (selection_symbol, target_type)
   if (EQ (target_type, QTIMESTAMP))
     {
       handler_fn = Qnil;
-      value = XCONS (XCONS (XCONS (local_value)->cdr)->cdr)->car;
+      value = XCAR (XCDR (XCDR (local_value)));
     }
 #if 0
   else if (EQ (target_type, QDELETE))
@@ -311,19 +321,19 @@ x_get_local_selection (selection_symbol, target_type)
       handler_fn = Qnil;
       Fx_disown_selection_internal
        (selection_symbol,
-        XCONS (XCONS (XCONS (local_value)->cdr)->cdr)->car);
+        XCAR (XCDR (XCDR (local_value))));
       value = QNULL;
     }
 #endif
 
 #if 0 /* #### MULTIPLE doesn't work yet */
   else if (CONSP (target_type)
-          && XCONS (target_type)->car == QMULTIPLE)
+          && XCAR (target_type) == QMULTIPLE)
     {
       Lisp_Object pairs;
       int size;
       int i;
-      pairs = XCONS (target_type)->cdr;
+      pairs = XCDR (target_type);
       size = XVECTOR (pairs)->size;
       /* If the target is MULTIPLE, then target_type looks like
          (MULTIPLE . [[SELECTION1 TARGET1] [SELECTION2 TARGET2] ... ])
@@ -354,7 +364,7 @@ x_get_local_selection (selection_symbol, target_type)
       if (!NILP (handler_fn))
        value = call3 (handler_fn,
                       selection_symbol, target_type,
-                      XCONS (XCONS (local_value)->cdr)->car);
+                      XCAR (XCDR (local_value)));
       else
        value = Qnil;
       unbind_to (count, Qnil);
@@ -365,9 +375,9 @@ x_get_local_selection (selection_symbol, target_type)
 
   check = value;
   if (CONSP (value)
-      && SYMBOLP (XCONS (value)->car))
-    type = XCONS (value)->car,
-    check = XCONS (value)->cdr;
+      && SYMBOLP (XCAR (value)))
+    type = XCAR (value),
+    check = XCDR (value);
   
   if (STRINGP (check)
       || VECTORP (check)
@@ -377,12 +387,12 @@ x_get_local_selection (selection_symbol, target_type)
     return value;
   /* Check for a value that cons_to_long could handle.  */
   else if (CONSP (check)
-          && INTEGERP (XCONS (check)->car)
-          && (INTEGERP (XCONS (check)->cdr)
+          && INTEGERP (XCAR (check))
+          && (INTEGERP (XCDR (check))
               ||
-              (CONSP (XCONS (check)->cdr)
-               && INTEGERP (XCONS (XCONS (check)->cdr)->car)
-               && NILP (XCONS (XCONS (check)->cdr)->cdr))))
+              (CONSP (XCDR (check))
+               && INTEGERP (XCAR (XCDR (check)))
+               && NILP (XCDR (XCDR (check))))))
     return value;
   else
     return
@@ -529,7 +539,7 @@ x_reply_selection_request (event, format, data, size, type)
 
   /* #### XChangeProperty can generate BadAlloc, and we must handle it! */
   BLOCK_INPUT;
-  x_catch_errors (display, count);
+  count = x_catch_errors (display);
 
   /* Store the data on the requested property.
      If the selection is large, only store the first N bytes of it.
@@ -551,7 +561,6 @@ x_reply_selection_request (event, format, data, size, type)
       /* Send an INCR selection.  */
       struct prop_location *wait_object;
       int had_errors;
-      int count = specpdl_ptr - specpdl;
       Lisp_Object frame;
 
       frame = some_frame_on_display (dpyinfo);
@@ -633,8 +642,6 @@ x_reply_selection_request (event, format, data, size, type)
 
       XChangeProperty (display, window, reply.property, type, format,
                       PropModeReplace, data, 0);
-
-      unbind_to (count, Qnil);
     }
 
   XFlush (display);
@@ -682,7 +689,7 @@ x_handle_selection_request (event)
     }
 
   local_selection_time = (Time)
-    cons_to_long (XCONS (XCONS (XCONS (local_selection_data)->cdr)->cdr)->car);
+    cons_to_long (XCAR (XCDR (XCDR (local_selection_data))));
 
   if (SELECTION_EVENT_TIME (event) != CurrentTime
       && local_selection_time > SELECTION_EVENT_TIME (event))
@@ -729,10 +736,10 @@ x_handle_selection_request (event)
       /* Indicate we have successfully processed this event.  */
       x_selection_current_request = 0;
 
-      /* Use free, not XFree, because lisp_data_to_selection_data
+      /* Use xfree, not XFree, because lisp_data_to_selection_data
         calls xmalloc itself.  */
       if (!nofree)
-       free (data);
+       xfree (data);
     }
   unbind_to (count, Qnil);
 
@@ -750,7 +757,7 @@ x_handle_selection_request (event)
   }
 }
 \f
-/* Handle a SelectionClear event EVENT, which indicates that some other
+/* Handle a SelectionClear event EVENT, which indicates that some
    client cleared out our previously asserted selection.
    This is called from keyboard.c when such an event is found in the queue.  */
 
@@ -765,6 +772,26 @@ x_handle_selection_clear (event)
   Lisp_Object selection_symbol, local_selection_data;
   Time local_selection_time;
   struct x_display_info *dpyinfo = x_display_info_for_display (display);
+  struct x_display_info *t_dpyinfo;
+
+  /* If the new selection owner is also Emacs,
+     don't clear the new selection.  */
+  BLOCK_INPUT;
+  /* Check each display on the same terminal,
+     to see if this Emacs job now owns the selection
+     through that display.  */
+  for (t_dpyinfo = x_display_list; t_dpyinfo; t_dpyinfo = t_dpyinfo->next)
+    if (t_dpyinfo->kboard == dpyinfo->kboard)
+      {
+       Window owner_window
+         = XGetSelectionOwner (t_dpyinfo->display, selection);
+       if (x_window_to_frame (t_dpyinfo, owner_window) != 0)
+         {
+           UNBLOCK_INPUT;
+           return;
+         }
+      }
+  UNBLOCK_INPUT;
 
   selection_symbol = x_atom_to_symbol (dpyinfo, display, selection);
 
@@ -774,7 +801,7 @@ x_handle_selection_clear (event)
   if (NILP (local_selection_data)) return;
 
   local_selection_time = (Time)
-    cons_to_long (XCONS (XCONS (XCONS (local_selection_data)->cdr)->cdr)->car);
+    cons_to_long (XCAR (XCDR (XCDR (local_selection_data))));
 
   /* This SelectionClear is for a selection that we no longer own, so we can
      disregard it.  (That is, we have reasserted the selection since this
@@ -793,9 +820,9 @@ x_handle_selection_clear (event)
     {
       Lisp_Object rest;
       for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest))
-       if (EQ (local_selection_data, Fcar (XCONS (rest)->cdr)))
+       if (EQ (local_selection_data, Fcar (XCDR (rest))))
          {
-           XCONS (rest)->cdr = Fcdr (XCONS (rest)->cdr);
+           XCDR (rest) = Fcdr (XCDR (rest));
            break;
          }
     }
@@ -856,13 +883,13 @@ x_clear_frame_selections (f)
 
   /* Delete elements after the beginning of Vselection_alist.  */
   for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest))
-    if (EQ (frame, Fcar (Fcdr (Fcdr (Fcdr (Fcar (XCONS (rest)->cdr)))))))
+    if (EQ (frame, Fcar (Fcdr (Fcdr (Fcdr (Fcar (XCDR (rest))))))))
       {
        /* Let random Lisp code notice that the selection has been stolen.  */
        Lisp_Object hooks, selection_symbol;
 
        hooks = Vx_lost_selection_hooks;
-       selection_symbol = Fcar (Fcar (XCONS (rest)->cdr));
+       selection_symbol = Fcar (Fcar (XCDR (rest)));
 
        if (!EQ (hooks, Qunbound))
          {
@@ -872,7 +899,7 @@ x_clear_frame_selections (f)
            redisplay_preserve_echo_area ();
 #endif
          }
-       XCONS (rest)->cdr = Fcdr (XCONS (rest)->cdr);
+       XCDR (rest) = Fcdr (XCDR (rest));
        break;
       }
 }
@@ -935,7 +962,7 @@ unexpect_property_change (location)
            prev->next = rest->next;
          else
            property_change_wait_list = rest->next;
-         free (rest);
+         xfree (rest);
          return;
        }
       prev = rest;
@@ -950,8 +977,8 @@ wait_for_property_change_unwind (identifierval)
      Lisp_Object identifierval;
 {
   unexpect_property_change ((struct prop_location *)
-                           (XFASTINT (XCONS (identifierval)->car) << 16
-                            | XFASTINT (XCONS (identifierval)->cdr)));
+                           (XFASTINT (XCAR (identifierval)) << 16
+                            | XFASTINT (XCDR (identifierval))));
   return Qnil;
 }
 
@@ -967,13 +994,13 @@ wait_for_property_change (location)
   Lisp_Object tem;
 
   tem = Fcons (Qnil, Qnil);
-  XSETFASTINT (XCONS (tem)->car, (EMACS_UINT)location >> 16);
-  XSETFASTINT (XCONS (tem)->cdr, (EMACS_UINT)location & 0xffff);
+  XSETFASTINT (XCAR (tem), (EMACS_UINT)location >> 16);
+  XSETFASTINT (XCDR (tem), (EMACS_UINT)location & 0xffff);
 
   /* Make sure to do unexpect_property_change if we quit or err.  */
   record_unwind_protect (wait_for_property_change_unwind, tem);
 
-  XCONS (property_change_reply)->car = Qnil;
+  XCAR (property_change_reply) = Qnil;
 
   property_change_reply_object = location;
   /* If the event we are waiting for arrives beyond here, it will set
@@ -984,7 +1011,7 @@ wait_for_property_change (location)
       usecs = (x_selection_timeout % 1000) * 1000;
       wait_reading_process_input (secs, usecs, property_change_reply, 0);
 
-      if (NILP (XCONS (property_change_reply)->car))
+      if (NILP (XCAR (property_change_reply)))
        error ("Timed out waiting for property-notify event");
     }
 
@@ -1018,13 +1045,13 @@ x_handle_property_notify (event)
          /* If this is the one wait_for_property_change is waiting for,
             tell it to wake up.  */
          if (rest == property_change_reply_object)
-           XCONS (property_change_reply)->car = Qt;
+           XCAR (property_change_reply) = Qt;
 
          if (prev)
            prev->next = rest->next;
          else
            property_change_wait_list = rest->next;
-         free (rest);
+         xfree (rest);
          return;
        }
       prev = rest;
@@ -1067,7 +1094,7 @@ copy_multiple_data (obj)
   int i;
   int size;
   if (CONSP (obj))
-    return Fcons (XCONS (obj)->car, copy_multiple_data (XCONS (obj)->cdr));
+    return Fcons (XCAR (obj), copy_multiple_data (XCDR (obj)));
     
   CHECK_VECTOR (obj, 0);
   vec = Fmake_vector (size = XVECTOR (obj)->size, Qnil);
@@ -1103,9 +1130,10 @@ static Lisp_Object
 x_get_foreign_selection (selection_symbol, target_type)
      Lisp_Object selection_symbol, target_type;
 {
-  Window requestor_window = FRAME_X_WINDOW (selected_frame);
-  Display *display = FRAME_X_DISPLAY (selected_frame);
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (selected_frame);
+  struct frame *sf = SELECTED_FRAME ();
+  Window requestor_window = FRAME_X_WINDOW (sf);
+  Display *display = FRAME_X_DISPLAY (sf);
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (sf);
   Time requestor_time = last_event_timestamp;
   Atom target_property = dpyinfo->Xatom_EMACS_TMP;
   Atom selection_atom = symbol_to_x_atom (dpyinfo, display, selection_symbol);
@@ -1115,7 +1143,7 @@ x_get_foreign_selection (selection_symbol, target_type)
   Lisp_Object frame;
 
   if (CONSP (target_type))
-    type_atom = symbol_to_x_atom (dpyinfo, display, XCONS (target_type)->car);
+    type_atom = symbol_to_x_atom (dpyinfo, display, XCAR (target_type));
   else
     type_atom = symbol_to_x_atom (dpyinfo, display, target_type);
 
@@ -1128,7 +1156,7 @@ x_get_foreign_selection (selection_symbol, target_type)
   /* Prepare to block until the reply has been read.  */
   reading_selection_window = requestor_window;
   reading_which_selection = selection_atom;
-  XCONS (reading_selection_reply)->car = Qnil;
+  XCAR (reading_selection_reply) = Qnil;
 
   frame = some_frame_on_display (dpyinfo);
 
@@ -1154,9 +1182,9 @@ x_get_foreign_selection (selection_symbol, target_type)
   x_uncatch_errors (display, count);
   UNBLOCK_INPUT;
 
-  if (NILP (XCONS (reading_selection_reply)->car))
+  if (NILP (XCAR (reading_selection_reply)))
     error ("Timed out waiting for reply from selection owner");
-  if (EQ (XCONS (reading_selection_reply)->car, Qlambda))
+  if (EQ (XCAR (reading_selection_reply), Qlambda))
     error ("No `%s' selection", XSYMBOL (selection_symbol)->name->data);
 
   /* Otherwise, the selection is waiting for us on the requested property.  */
@@ -1168,7 +1196,7 @@ x_get_foreign_selection (selection_symbol, target_type)
 \f
 /* Subroutines of x_get_window_property_as_lisp_data */
 
-/* Use free, not XFree, to free the data obtained with this function.  */
+/* Use xfree, not XFree, to free the data obtained with this function.  */
 
 static void
 x_get_window_property (display, window, property, data_ret, bytes_ret,
@@ -1251,7 +1279,7 @@ x_get_window_property (display, window, property, data_ret, bytes_ret,
   *bytes_ret = offset;
 }
 \f
-/* Use free, not XFree, to free the data obtained with this function.  */
+/* Use xfree, not XFree, to free the data obtained with this function.  */
 
 static void
 receive_incremental_selection (display, window, property, target_type,
@@ -1313,9 +1341,9 @@ receive_incremental_selection (display, window, property, target_type,
          if (! waiting_for_other_props_on_window (display, window))
            XSelectInput (display, window, STANDARD_EVENT_SET);
          unexpect_property_change (wait_object);
-         /* Use free, not XFree, because x_get_window_property
+         /* Use xfree, not XFree, because x_get_window_property
             calls xmalloc itself.  */
-         if (tmp_data) free (tmp_data);
+         if (tmp_data) xfree (tmp_data);
          break;
        }
 
@@ -1340,9 +1368,9 @@ receive_incremental_selection (display, window, property, target_type,
        }
       bcopy (tmp_data, (*data_ret) + offset, tmp_size_bytes);
       offset += tmp_size_bytes;
-      /* Use free, not XFree, because x_get_window_property
+      /* Use xfree, not XFree, because x_get_window_property
         calls xmalloc itself.  */
-      free (tmp_data);
+      xfree (tmp_data);
     }
 }
 \f
@@ -1397,9 +1425,9 @@ x_get_window_property_as_lisp_data (display, window, property, target_type,
 
       unsigned int min_size_bytes = * ((unsigned int *) data);
       BLOCK_INPUT;
-      /* Use free, not XFree, because x_get_window_property
+      /* Use xfree, not XFree, because x_get_window_property
         calls xmalloc itself.  */
-      free ((char *) data);
+      xfree ((char *) data);
       UNBLOCK_INPUT;
       receive_incremental_selection (display, window, property, target_type,
                                     min_size_bytes, &data, &bytes,
@@ -1417,9 +1445,9 @@ x_get_window_property_as_lisp_data (display, window, property, target_type,
   val = selection_data_to_lisp_data (display, data, bytes,
                                     actual_type, actual_format);
   
-  /* Use free, not XFree, because x_get_window_property
+  /* Use xfree, not XFree, because x_get_window_property
      calls xmalloc itself.  */
-  free ((char *) data);
+  xfree ((char *) data);
   return val;
 }
 \f
@@ -1466,27 +1494,65 @@ selection_data_to_lisp_data (display, data, size, type, format)
   else if (format == 8)
     {
       Lisp_Object str;
+      int require_encoding = 0;
 
-      if (type != dpyinfo->Xatom_TEXT && type != dpyinfo->Xatom_COMPOUND_TEXT)
-       str = make_string ((char *) data, size);
-      else
+      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.  */
-         int bufsize, dummy;
+            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;
+       }
+      else
+       {
+         int bufsize;
          unsigned char *buf;
          struct coding_system coding;
-         Lisp_Object sym = intern ("iso-8859-1");
 
-         setup_coding_system (Fcheck_coding_system (sym), &coding);
-         coding.last_block = 1;
+         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);
-         size = decode_coding (&coding, data, buf, size, bufsize, &dummy);
-         str = make_string ((char *) buf, size);
+         decode_coding (&coding, data, buf, size, bufsize);
+         str = make_string_from_bytes ((char *) buf,
+                                       coding.produced_char, coding.produced);
          xfree (buf);
+         Vlast_coding_system_used = coding.symbol;
        }
+      compose_chars_in_text (0, XSTRING (str)->size, str);
       return str;
     }
   /* Convert a single atom to a Lisp_Symbol.  Convert a set of atoms to
@@ -1499,10 +1565,11 @@ selection_data_to_lisp_data (display, data, size, type, format)
        return x_atom_to_symbol (dpyinfo, display, *((Atom *) data));
       else
        {
-         Lisp_Object v = Fmake_vector (size / sizeof (Atom), 0);
+         Lisp_Object v = Fmake_vector (make_number (size / sizeof (Atom)),
+                                       make_number (0));
          for (i = 0; i < size / sizeof (Atom); i++)
-           Faset (v, i, x_atom_to_symbol (dpyinfo, display,
-                                          ((Atom *) data) [i]));
+           Faset (v, make_number (i),
+                  x_atom_to_symbol (dpyinfo, display, ((Atom *) data) [i]));
          return v;
        }
     }
@@ -1522,29 +1589,30 @@ selection_data_to_lisp_data (display, data, size, type, format)
   else if (format == 16)
     {
       int i;
-      Lisp_Object v = Fmake_vector (size / 4, 0);
-      for (i = 0; i < size / 4; i++)
+      Lisp_Object v;
+      v = Fmake_vector (make_number (size / 2), make_number (0));
+      for (i = 0; i < size / 2; i++)
        {
          int j = (int) ((unsigned short *) data) [i];
-         Faset (v, i, make_number (j));
+         Faset (v, make_number (i), make_number (j));
        }
       return v;
     }
   else
     {
       int i;
-      Lisp_Object v = Fmake_vector (size / 4, 0);
+      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];
-         Faset (v, i, long_to_cons (j));
+         Faset (v, make_number (i), long_to_cons (j));
        }
       return v;
     }
 }
 
 
-/* Use free, not XFree, to free the data obtained with this function.  */
+/* Use xfree, not XFree, to free the data obtained with this function.  */
 
 static void
 lisp_data_to_selection_data (display, obj,
@@ -1563,12 +1631,12 @@ lisp_data_to_selection_data (display, obj,
 
   *nofree_ret = 0;
 
-  if (CONSP (obj) && SYMBOLP (XCONS (obj)->car))
+  if (CONSP (obj) && SYMBOLP (XCAR (obj)))
     {
-      type = XCONS (obj)->car;
-      obj = XCONS (obj)->cdr;
-      if (CONSP (obj) && NILP (XCONS (obj)->cdr))
-       obj = XCONS (obj)->car;
+      type = XCAR (obj);
+      obj = XCDR (obj);
+      if (CONSP (obj) && NILP (XCDR (obj)))
+       obj = XCAR (obj);
     }
 
   if (EQ (obj, QNULL) || (EQ (type, QNULL)))
@@ -1582,53 +1650,21 @@ lisp_data_to_selection_data (display, obj,
     {
       /* Since we are now handling multilingual text, we must consider
         sending back compound text.  */
-      char charsets[MAX_CHARSET + 1];
-      int num;
+      int stringp;
 
-      *format_ret = 8;
-      *size_ret = XSTRING (obj)->size;
-      *data_ret = XSTRING (obj)->data;
-      bzero (charsets, MAX_CHARSET + 1);
-      num = ((*size_ret <= 1)  /* Check the possibility of short cut.  */
-            ? 0
-            : find_charset_in_str (*data_ret, *size_ret, charsets));
-
-      if (!num || (num == 1 && charsets[CHARSET_ASCII]))
-       {
-         /* No multibyte character in OBJ.  We need not encode it.  */
-         *nofree_ret = 1;
-         if (NILP (type)) type = QSTRING;
-       }
-      else
-       {
-         /* We must encode contents of OBJ to compound text format.
-             The format is compatible with what the target `STRING'
-             expects if OBJ contains only ASCII and Latin-1
-             characters.  */
-         int bufsize, dummy;
-         unsigned char *buf;
-         struct coding_system coding;
-         Lisp_Object sym = intern ("iso-8859-1");
+      if (NILP (Vnext_selection_coding_system))
+       Vnext_selection_coding_system = Vselection_coding_system;
 
-         setup_coding_system (Fcheck_coding_system (sym), &coding);
-         coding.last_block = 1;
-         bufsize = encoding_buffer_size (&coding, *size_ret);
-         buf = (unsigned char *) xmalloc (bufsize);
-         *size_ret = encode_coding (&coding, *data_ret, buf,
-                                    *size_ret, bufsize, &dummy);
-         *data_ret = buf;
-         if (charsets[charset_latin_iso8859_1]
-             && (num == 1 || (num == 2 && charsets[CHARSET_ASCII])))
-           {
-             /* Ok, we can return it as `STRING'.  */
-             if (NILP (type)) type = QSTRING;
-           }
-         else
-           {
-             /* We must return it as `COMPOUND_TEXT'.  */
-             if (NILP (type)) type = QCOMPOUND_TEXT;
-           }
-       }
+      *format_ret = 8;
+      *data_ret = x_encode_text (obj, Vnext_selection_coding_system,
+                                (int *) size_ret, &stringp);
+      *nofree_ret = (*data_ret == XSTRING (obj)->data);
+      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;
     }
   else if (SYMBOLP (obj))
     {
@@ -1651,10 +1687,10 @@ lisp_data_to_selection_data (display, obj,
       if (NILP (type)) type = QINTEGER;
     }
   else if (INTEGERP (obj)
-          || (CONSP (obj) && INTEGERP (XCONS (obj)->car)
-              && (INTEGERP (XCONS (obj)->cdr)
-                  || (CONSP (XCONS (obj)->cdr)
-                      && INTEGERP (XCONS (XCONS (obj)->cdr)->car)))))
+          || (CONSP (obj) && INTEGERP (XCAR (obj))
+              && (INTEGERP (XCDR (obj))
+                  || (CONSP (XCDR (obj))
+                      && INTEGERP (XCAR (XCDR (obj)))))))
     {
       *format_ret = 32;
       *size_ret = 1;
@@ -1760,20 +1796,20 @@ clean_local_selection_data (obj)
      Lisp_Object obj;
 {
   if (CONSP (obj)
-      && INTEGERP (XCONS (obj)->car)
-      && CONSP (XCONS (obj)->cdr)
-      && INTEGERP (XCONS (XCONS (obj)->cdr)->car)
-      && NILP (XCONS (XCONS (obj)->cdr)->cdr))
-    obj = Fcons (XCONS (obj)->car, XCONS (obj)->cdr);
+      && INTEGERP (XCAR (obj))
+      && CONSP (XCDR (obj))
+      && INTEGERP (XCAR (XCDR (obj)))
+      && NILP (XCDR (XCDR (obj))))
+    obj = Fcons (XCAR (obj), XCDR (obj));
 
   if (CONSP (obj)
-      && INTEGERP (XCONS (obj)->car)
-      && INTEGERP (XCONS (obj)->cdr))
+      && INTEGERP (XCAR (obj))
+      && INTEGERP (XCDR (obj)))
     {
-      if (XINT (XCONS (obj)->car) == 0)
-       return XCONS (obj)->cdr;
-      if (XINT (XCONS (obj)->car) == -1)
-       return make_number (- XINT (XCONS (obj)->cdr));
+      if (XINT (XCAR (obj)) == 0)
+       return XCDR (obj);
+      if (XINT (XCAR (obj)) == -1)
+       return make_number (- XINT (XCDR (obj)));
     }
   if (VECTORP (obj))
     {
@@ -1782,7 +1818,7 @@ clean_local_selection_data (obj)
       Lisp_Object copy;
       if (size == 1)
        return clean_local_selection_data (XVECTOR (obj)->contents [0]);
-      copy = Fmake_vector (size, Qnil);
+      copy = Fmake_vector (make_number (size), Qnil);
       for (i = 0; i < size; i++)
        XVECTOR (copy)->contents [i]
          = clean_local_selection_data (XVECTOR (obj)->contents [i]);
@@ -1805,7 +1841,7 @@ x_handle_selection_notify (event)
   if (event->selection != reading_which_selection)
     return;
 
-  XCONS (reading_selection_reply)->car
+  XCAR (reading_selection_reply)
     = (event->property != 0 ? Qt : Qlambda);
 }
 
@@ -1849,9 +1885,9 @@ TYPE is the type of data desired, typically `STRING'.")
 
 #if 0 /* #### MULTIPLE doesn't work yet */
   if (CONSP (target_type)
-      && XCONS (target_type)->car == QMULTIPLE)
+      && XCAR (target_type) == QMULTIPLE)
     {
-      CHECK_VECTOR (XCONS (target_type)->cdr, 0);
+      CHECK_VECTOR (XCDR (target_type), 0);
       /* So we don't destructively modify this...  */
       target_type = copy_multiple_data (target_type);
     }
@@ -1868,11 +1904,11 @@ TYPE is the type of data desired, typically `STRING'.")
     }
 
   if (CONSP (val)
-      && SYMBOLP (XCONS (val)->car))
+      && SYMBOLP (XCAR (val)))
     {
-      val = XCONS (val)->cdr;
-      if (CONSP (val) && NILP (XCONS (val)->cdr))
-       val = XCONS (val)->car;
+      val = XCDR (val);
+      if (CONSP (val) && NILP (XCDR (val)))
+       val = XCAR (val);
     }
   val = clean_local_selection_data (val);
  DONE:
@@ -1890,13 +1926,14 @@ Disowning it means there is no such selection.")
 {
   Time timestamp;
   Atom selection_atom;
-  XSelectionClearEvent event;
+  struct selection_input_event event;
   Display *display;
   struct x_display_info *dpyinfo;
+  struct frame *sf = SELECTED_FRAME ();
 
   check_x ();
-  display = FRAME_X_DISPLAY (selected_frame);
-  dpyinfo = FRAME_X_DISPLAY_INFO (selected_frame);
+  display = FRAME_X_DISPLAY (sf);
+  dpyinfo = FRAME_X_DISPLAY_INFO (sf);
   CHECK_SYMBOL (selection, 0);
   if (NILP (time))
     timestamp = last_event_timestamp;
@@ -1920,7 +1957,7 @@ Disowning it means there is no such selection.")
   SELECTION_EVENT_DISPLAY (&event) = display;
   SELECTION_EVENT_SELECTION (&event) = selection_atom;
   SELECTION_EVENT_TIME (&event) = timestamp;
-  x_handle_selection_clear (&event);
+  x_handle_selection_clear ((struct input_event *) &event);
 
   return Qt;
 }
@@ -1935,14 +1972,14 @@ x_disown_buffer_selections (buffer)
   Lisp_Object tail;
   struct buffer *buf = XBUFFER (buffer);
 
-  for (tail = Vselection_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vselection_alist; CONSP (tail); tail = XCDR (tail))
     {
       Lisp_Object elt, value;
-      elt = XCONS (tail)->car;
-      value = XCONS (elt)->cdr;
-      if (CONSP (value) && MARKERP (XCONS (value)->car)
-         && XMARKER (XCONS (value)->car)->buffer == buf)
-       Fx_disown_selection_internal (XCONS (elt)->car, Qnil);
+      elt = XCAR (tail);
+      value = XCDR (elt);
+      if (CONSP (value) && MARKERP (XCAR (value))
+         && XMARKER (XCAR (value))->buffer == buf)
+       Fx_disown_selection_internal (XCAR (elt), Qnil);
     }
 }
 
@@ -1981,19 +2018,19 @@ and t is the same as `SECONDARY'.)")
   Window owner;
   Atom atom;
   Display *dpy;
+  struct frame *sf = SELECTED_FRAME ();
 
   /* It should be safe to call this before we have an X frame.  */
-  if (! FRAME_X_P (selected_frame))
+  if (! FRAME_X_P (sf))
     return Qnil;
 
-  dpy = FRAME_X_DISPLAY (selected_frame);
+  dpy = FRAME_X_DISPLAY (sf);
   CHECK_SYMBOL (selection, 0);
   if (!NILP (Fx_selection_owner_p (selection)))
     return Qt;
   if (EQ (selection, Qnil)) selection = QPRIMARY;
   if (EQ (selection, Qt)) selection = QSECONDARY;
-  atom = symbol_to_x_atom (FRAME_X_DISPLAY_INFO (selected_frame),
-                          dpy, selection);
+  atom = symbol_to_x_atom (FRAME_X_DISPLAY_INFO (sf), dpy, selection);
   if (atom == 0)
     return Qnil;
   BLOCK_INPUT;
@@ -2055,17 +2092,19 @@ DEFUN ("x-get-cut-buffer-internal", Fx_get_cut_buffer_internal,
   Lisp_Object ret;
   Display *display;
   struct x_display_info *dpyinfo;
+  struct frame *sf = SELECTED_FRAME ();
 
   check_x ();
-  display = FRAME_X_DISPLAY (selected_frame);
-  dpyinfo = FRAME_X_DISPLAY_INFO (selected_frame);
+  display = FRAME_X_DISPLAY (sf);
+  dpyinfo = FRAME_X_DISPLAY_INFO (sf);
   window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
   CHECK_CUT_BUFFER (buffer, 0);
   buffer_atom = symbol_to_x_atom (dpyinfo, display, buffer);
 
   x_get_window_property (display, window, buffer_atom, &data, &bytes,
                         &type, &format, &size, 0);
-  if (!data) return Qnil;
+  if (!data || !format)
+    return Qnil;
   
   if (format != 8 || type != XA_STRING)
     Fsignal (Qerror,
@@ -2074,9 +2113,9 @@ DEFUN ("x-get-cut-buffer-internal", Fx_get_cut_buffer_internal,
                           Fcons (make_number (format), Qnil))));
 
   ret = (bytes ? make_string ((char *) data, bytes) : Qnil);
-  /* Use free, not XFree, because x_get_window_property
+  /* Use xfree, not XFree, because x_get_window_property
      calls xmalloc itself.  */
-  free (data);
+  xfree (data);
   return ret;
 }
 
@@ -2094,9 +2133,10 @@ DEFUN ("x-store-cut-buffer-internal", Fx_store_cut_buffer_internal,
   int bytes_remaining;
   int max_bytes;
   Display *display;
+  struct frame *sf = SELECTED_FRAME ();
 
   check_x ();
-  display = FRAME_X_DISPLAY (selected_frame);
+  display = FRAME_X_DISPLAY (sf);
   window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
 
   max_bytes = SELECTION_QUANTUM (display);
@@ -2105,16 +2145,16 @@ DEFUN ("x-store-cut-buffer-internal", Fx_store_cut_buffer_internal,
 
   CHECK_CUT_BUFFER (buffer, 0);
   CHECK_STRING (string, 0);
-  buffer_atom = symbol_to_x_atom (FRAME_X_DISPLAY_INFO (selected_frame),
+  buffer_atom = symbol_to_x_atom (FRAME_X_DISPLAY_INFO (sf),
                                  display, buffer);
   data = (unsigned char *) XSTRING (string)->data;
-  bytes = XSTRING (string)->size;
+  bytes = STRING_BYTES (XSTRING (string));
   bytes_remaining = bytes;
 
-  if (! FRAME_X_DISPLAY_INFO (selected_frame)->cut_buffers_initialized)
+  if (! FRAME_X_DISPLAY_INFO (sf)->cut_buffers_initialized)
     {
       initialize_cut_buffers (display, window);
-      FRAME_X_DISPLAY_INFO (selected_frame)->cut_buffers_initialized = 1;
+      FRAME_X_DISPLAY_INFO (sf)->cut_buffers_initialized = 1;
     }
 
   BLOCK_INPUT;
@@ -2143,25 +2183,26 @@ DEFUN ("x-store-cut-buffer-internal", Fx_store_cut_buffer_internal,
 
 DEFUN ("x-rotate-cut-buffers-internal", Fx_rotate_cut_buffers_internal,
   Sx_rotate_cut_buffers_internal, 1, 1, 0,
-  "Rotate the values of the cut buffers by the given number of steps;\n\
-positive means move values forward, negative means backward.")
+  "Rotate the values of the cut buffers by the given number of step.\n\
+Positive means shift the values forward, negative means backward.")
   (n)
      Lisp_Object n;
 {
   Window window;
   Atom props[8];
   Display *display;
+  struct frame *sf = SELECTED_FRAME ();
 
   check_x ();
-  display = FRAME_X_DISPLAY (selected_frame);
+  display = FRAME_X_DISPLAY (sf);
   window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
   CHECK_NUMBER (n, 0);
   if (XINT (n) == 0)
     return n;
-  if (! FRAME_X_DISPLAY_INFO (selected_frame)->cut_buffers_initialized)
+  if (! FRAME_X_DISPLAY_INFO (sf)->cut_buffers_initialized)
     {
       initialize_cut_buffers (display, window);
-      FRAME_X_DISPLAY_INFO (selected_frame)->cut_buffers_initialized = 1;
+      FRAME_X_DISPLAY_INFO (sf)->cut_buffers_initialized = 1;
     }
 
   props[0] = XA_CUT_BUFFER0;
@@ -2209,7 +2250,7 @@ syms_of_xselect ()
   staticpro (&Vselection_alist);
 
   DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_alist,
-  "An alist associating X Windows selection-types with functions.\n\
+    "An alist associating X Windows selection-types with functions.\n\
 These functions are called to convert the selection, with three args:\n\
 the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\
 a desired type to which the selection should be converted;\n\
@@ -2224,7 +2265,7 @@ and there is no meaningful selection value.");
   Vselection_converter_alist = Qnil;
 
   DEFVAR_LISP ("x-lost-selection-hooks", &Vx_lost_selection_hooks,
-  "A list of functions to be called when Emacs loses an X selection.\n\
+    "A list of functions to be called when Emacs loses an X selection.\n\
 \(This happens when some other X client makes its own selection\n\
 or when a Lisp program explicitly clears the selection.)\n\
 The functions are called with one argument, the selection type\n\
@@ -2232,7 +2273,7 @@ The functions are called with one argument, the selection type\n\
   Vx_lost_selection_hooks = Qnil;
 
   DEFVAR_LISP ("x-sent-selection-hooks", &Vx_sent_selection_hooks,
-  "A list of functions to be called when Emacs answers a selection request.\n\
+    "A list of functions to be called when Emacs answers a selection request.\n\
 The functions are called with four arguments:\n\
   - the selection name (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\
   - the selection-type which Emacs was asked to convert the\n\
@@ -2245,8 +2286,23 @@ This hook doesn't let you change the behavior of Emacs's selection replies,\n\
 it merely informs you that they have happened.");
   Vx_sent_selection_hooks = Qnil;
 
+  DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system,
+    "Coding system for communicating with other X clients.\n\
+When sending or receiving text via cut_buffer, selection, and clipboard,\n\
+the text is encoded or decoded by this coding system.\n\
+The default value is `compound-text'.");
+  Vselection_coding_system = intern ("compound-text");
+
+  DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system,
+    "Coding system for the next communication with other X clients.\n\
+Usually, `selection-coding-system' is used for communicating with\n\
+other X clients.   But, if this variable is set, it is used for the\n\
+next communication only.   After the communication, this variable is\n\
+set to nil.");
+  Vnext_selection_coding_system = Qnil;
+
   DEFVAR_INT ("x-selection-timeout", &x_selection_timeout,
-   "Number of milliseconds to wait for a selection reply.\n\
+    "Number of milliseconds to wait for a selection reply.\n\
 If the selection owner doesn't reply in this time, we give up.\n\
 A value of 0 means wait as long as necessary.  This is initialized from the\n\
 \"*selectionTimeout\" resource.");