]> code.delx.au - gnu-emacs/blobdiff - src/xselect.c
Merge from emacs-24; up to 2014-07-21T01:34:03Z!monnier@iro.umontreal.ca
[gnu-emacs] / src / xselect.c
index 5b90d7def2216c38f7d5ea2393877bca589f6359..9b57a95b26b1908021a7c90e6696b3a9532a4b48 100644 (file)
@@ -1,5 +1,5 @@
 /* X Selection processing for Emacs.
-   Copyright (C) 1993-1997, 2000-2013 Free Software Foundation, Inc.
+   Copyright (C) 1993-1997, 2000-2014 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -45,36 +45,22 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 struct prop_location;
 struct selection_data;
 
-static Lisp_Object x_atom_to_symbol (Display *dpy, Atom atom);
-static Atom symbol_to_x_atom (struct x_display_info *, Lisp_Object);
-static void x_own_selection (Lisp_Object, Lisp_Object, Lisp_Object);
-static Lisp_Object x_get_local_selection (Lisp_Object, Lisp_Object, int,
-                                         struct x_display_info *);
 static void x_decline_selection_request (struct input_event *);
-static Lisp_Object x_selection_request_lisp_error (Lisp_Object);
-static Lisp_Object queue_selection_requests_unwind (Lisp_Object);
-static Lisp_Object x_catch_errors_unwind (Lisp_Object);
-static void x_reply_selection_request (struct input_event *, struct x_display_info *);
 static int x_convert_selection (struct input_event *, Lisp_Object, Lisp_Object,
                                Atom, int, struct x_display_info *);
 static int waiting_for_other_props_on_window (Display *, Window);
 static struct prop_location *expect_property_change (Display *, Window,
                                                      Atom, int);
 static void unexpect_property_change (struct prop_location *);
-static Lisp_Object wait_for_property_change_unwind (Lisp_Object);
 static void wait_for_property_change (struct prop_location *);
-static Lisp_Object x_get_foreign_selection (Lisp_Object, Lisp_Object,
-                                           Lisp_Object, Lisp_Object);
-static Lisp_Object x_get_window_property_as_lisp_data (Display *,
+static Lisp_Object x_get_window_property_as_lisp_data (struct x_display_info *,
                                                        Window, Atom,
                                                        Lisp_Object, Atom);
-static Lisp_Object selection_data_to_lisp_data (Display *,
+static Lisp_Object selection_data_to_lisp_data (struct x_display_info *,
                                                const unsigned char *,
                                                ptrdiff_t, Atom, int);
-static void lisp_data_to_selection_data (Display *, Lisp_Object,
-                                         unsigned char **, Atom *,
-                                        ptrdiff_t *, int *, int *);
-static Lisp_Object clean_local_selection_data (Lisp_Object);
+static void lisp_data_to_selection_data (struct x_display_info *, Lisp_Object,
+                                        struct selection_data *);
 
 /* Printing traces to stderr.  */
 
@@ -110,13 +96,6 @@ static Lisp_Object Qx_lost_selection_functions, Qx_sent_selection_functions;
    is not necessarily sizeof (long).  */
 #define X_LONG_SIZE 4
 
-/* Extreme 'short' and 'long' values suitable for libX11.  */
-#define X_SHRT_MAX 0x7fff
-#define X_SHRT_MIN (-1 - X_SHRT_MAX)
-#define X_LONG_MAX 0x7fffffff
-#define X_LONG_MIN (-1 - X_LONG_MAX)
-#define X_ULONG_MAX 0xffffffffUL
-
 /* 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
@@ -258,9 +237,8 @@ symbol_to_x_atom (struct x_display_info *dpyinfo, Lisp_Object sym)
    and calls to intern whenever possible.  */
 
 static Lisp_Object
-x_atom_to_symbol (Display *dpy, Atom atom)
+x_atom_to_symbol (struct x_display_info *dpyinfo, Atom atom)
 {
-  struct x_display_info *dpyinfo;
   char *str;
   Lisp_Object val;
 
@@ -281,7 +259,6 @@ x_atom_to_symbol (Display *dpy, Atom atom)
       return QATOM;
     }
 
-  dpyinfo = x_display_info_for_display (dpy);
   if (dpyinfo == NULL)
     return Qnil;
   if (atom == dpyinfo->Xatom_CLIPBOARD)
@@ -308,7 +285,7 @@ x_atom_to_symbol (Display *dpy, Atom atom)
     return QNULL;
 
   block_input ();
-  str = XGetAtomName (dpy, atom);
+  str = XGetAtomName (dpyinfo->display, atom);
   unblock_input ();
   TRACE1 ("XGetAtomName --> %s", str);
   if (! str) return Qnil;
@@ -331,9 +308,9 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
 {
   struct frame *f = XFRAME (frame);
   Window selecting_window = FRAME_X_WINDOW (f);
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   Display *display = dpyinfo->display;
-  Time timestamp = last_event_timestamp;
+  Time timestamp = dpyinfo->last_user_time;
   Atom selection_atom = symbol_to_x_atom (dpyinfo, selection_name);
 
   block_input ();
@@ -471,7 +448,7 @@ x_decline_selection_request (struct input_event *event)
      died in the meantime.  Handle that case.  */
   block_input ();
   x_catch_errors (reply->display);
-  XSendEvent (reply->display, reply->requestor, False, 0L, &reply_base);
+  XSendEvent (reply->display, reply->requestor, False, 0, &reply_base);
   XFlush (reply->display);
   x_uncatch_errors ();
   unblock_input ();
@@ -513,8 +490,8 @@ static Atom conversion_fail_tag;
    an error, we tell the requestor that we were unable to do what they wanted
    before we throw to top-level or go into the debugger or whatever.  */
 
-static Lisp_Object
-x_selection_request_lisp_error (Lisp_Object ignore)
+static void
+x_selection_request_lisp_error (void)
 {
   struct selection_data *cs, *next;
 
@@ -530,16 +507,14 @@ x_selection_request_lisp_error (Lisp_Object ignore)
   if (x_selection_current_request != 0
       && selection_request_dpyinfo->display)
     x_decline_selection_request (x_selection_current_request);
-  return Qnil;
 }
 
-static Lisp_Object
-x_catch_errors_unwind (Lisp_Object dummy)
+static void
+x_catch_errors_unwind (void)
 {
   block_input ();
   x_uncatch_errors ();
   unblock_input ();
-  return Qnil;
 }
 \f
 
@@ -560,11 +535,6 @@ struct prop_location
   struct prop_location *next;
 };
 
-static struct prop_location *expect_property_change (Display *display, Window window, Atom property, int state);
-static void wait_for_property_change (struct prop_location *location);
-static void unexpect_property_change (struct prop_location *location);
-static int waiting_for_other_props_on_window (Display *display, Window window);
-
 static int prop_location_identifier;
 
 static Lisp_Object property_change_reply;
@@ -573,13 +543,6 @@ static struct prop_location *property_change_reply_object;
 
 static struct prop_location *property_change_wait_list;
 
-static Lisp_Object
-queue_selection_requests_unwind (Lisp_Object tem)
-{
-  x_stop_queuing_selection_requests ();
-  return Qnil;
-}
-
 \f
 /* Send the reply to a selection request event EVENT.  */
 
@@ -614,7 +577,7 @@ x_reply_selection_request (struct input_event *event,
   /* The protected block contains wait_for_property_change, which can
      run random lisp code (process handlers) or signal.  Therefore, we
      put the x_uncatch_errors call in an unwind.  */
-  record_unwind_protect (x_catch_errors_unwind, Qnil);
+  record_unwind_protect_void (x_catch_errors_unwind);
   x_catch_errors (display);
 
   /* Loop over converted selections, storing them in the requested
@@ -659,7 +622,7 @@ x_reply_selection_request (struct input_event *event,
     }
 
   /* Now issue the SelectionNotify event.  */
-  XSendEvent (display, window, False, 0L, &reply_base);
+  XSendEvent (display, window, False, 0, &reply_base);
   XFlush (display);
 
 #ifdef TRACE_SELECTION
@@ -681,7 +644,7 @@ x_reply_selection_request (struct input_event *event,
     if (cs->wait_object)
       {
        int format_bytes = cs->format / 8;
-       int had_errors = x_had_errors_p (display);
+       bool had_errors_p = x_had_errors_p (display);
        unblock_input ();
 
        bytes_remaining = cs->size;
@@ -689,7 +652,7 @@ x_reply_selection_request (struct input_event *event,
 
        /* Wait for the requestor to ack by deleting the property.
           This can run Lisp code (process handlers) or signal.  */
-       if (! had_errors)
+       if (! had_errors_p)
          {
            TRACE1 ("Waiting for ACK (deletion of %s)",
                    XGetAtomName (display, cs->property));
@@ -721,10 +684,10 @@ x_reply_selection_request (struct input_event *event,
            cs->data += i * ((cs->format == 32) ? sizeof (long)
                             : format_bytes);
            XFlush (display);
-           had_errors = x_had_errors_p (display);
+           had_errors_p = x_had_errors_p (display);
            unblock_input ();
 
-           if (had_errors) break;
+           if (had_errors_p) break;
 
            /* Wait for the requestor to ack this chunk by deleting
               the property.  This can run Lisp code or signal.  */
@@ -737,7 +700,7 @@ x_reply_selection_request (struct input_event *event,
           requestor that we're done.  */
        block_input ();
        if (! waiting_for_other_props_on_window (display, window))
-         XSelectInput (display, window, 0L);
+         XSelectInput (display, window, 0);
 
        TRACE1 ("Set %s to a 0-length chunk to indicate EOF",
                XGetAtomName (display, cs->property));
@@ -777,12 +740,11 @@ x_handle_selection_request (struct input_event *event)
   struct gcpro gcpro1, gcpro2;
   Time local_selection_time;
 
-  Display *display = SELECTION_EVENT_DISPLAY (event);
-  struct x_display_info *dpyinfo = x_display_info_for_display (display);
+  struct x_display_info *dpyinfo = SELECTION_EVENT_DPYINFO (event);
   Atom selection = SELECTION_EVENT_SELECTION (event);
-  Lisp_Object selection_symbol = x_atom_to_symbol (display, selection);
+  Lisp_Object selection_symbol = x_atom_to_symbol (dpyinfo, selection);
   Atom target = SELECTION_EVENT_TARGET (event);
-  Lisp_Object target_symbol = x_atom_to_symbol (display, target);
+  Lisp_Object target_symbol = x_atom_to_symbol (dpyinfo, target);
   Atom property = SELECTION_EVENT_PROPERTY (event);
   Lisp_Object local_selection_data;
   int success = 0;
@@ -805,12 +767,12 @@ x_handle_selection_request (struct input_event *event)
 
   x_selection_current_request = event;
   selection_request_dpyinfo = dpyinfo;
-  record_unwind_protect (x_selection_request_lisp_error, Qnil);
+  record_unwind_protect_void (x_selection_request_lisp_error);
 
   /* We might be able to handle nested x_handle_selection_requests,
      but this is difficult to test, and seems unimportant.  */
   x_start_queuing_selection_requests ();
-  record_unwind_protect (queue_selection_requests_unwind, Qnil);
+  record_unwind_protect_void (x_stop_queuing_selection_requests);
 
   TRACE2 ("x_handle_selection_request: selection=%s, target=%s",
          SDATA (SYMBOL_NAME (selection_symbol)),
@@ -827,7 +789,7 @@ x_handle_selection_request (struct input_event *event)
 
       if (property == None) goto DONE;
       multprop
-       = x_get_window_property_as_lisp_data (display, requestor, property,
+       = x_get_window_property_as_lisp_data (dpyinfo, requestor, property,
                                              QMULTIPLE, selection);
 
       if (!VECTORP (multprop) || ASIZE (multprop) % 2)
@@ -931,11 +893,7 @@ x_convert_selection (struct input_event *event, Lisp_Object selection_symbol,
   cs->wait_object = NULL;
   cs->next = converted_selections;
   converted_selections = cs;
-  lisp_data_to_selection_data (SELECTION_EVENT_DISPLAY (event),
-                              lisp_selection,
-                              &(cs->data), &(cs->type),
-                              &(cs->size), &(cs->format),
-                              &(cs->nofree));
+  lisp_data_to_selection_data (dpyinfo, lisp_selection, cs);
   UNGCPRO;
   return 1;
 }
@@ -947,20 +905,19 @@ x_convert_selection (struct input_event *event, Lisp_Object selection_symbol,
 static void
 x_handle_selection_clear (struct input_event *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);
+  struct x_display_info *dpyinfo = SELECTION_EVENT_DPYINFO (event);
   Lisp_Object Vselection_alist;
 
   TRACE0 ("x_handle_selection_clear");
 
   if (!dpyinfo) return;
 
-  selection_symbol = x_atom_to_symbol (display, selection);
+  selection_symbol = x_atom_to_symbol (dpyinfo, selection);
   local_selection_data = LOCAL_SELECTION (selection_symbol, dpyinfo);
 
   /* Well, we already believe that we don't own it, so that's just fine.  */
@@ -999,7 +956,6 @@ x_handle_selection_clear (struct input_event *event)
     Frun_hook_with_args (2, args);
   }
 
-  prepare_menu_bars ();
   redisplay_preserve_echo_area (20);
 }
 
@@ -1020,11 +976,11 @@ x_handle_selection_event (struct input_event *event)
    We do this when about to delete a frame.  */
 
 void
-x_clear_frame_selections (FRAME_PTR f)
+x_clear_frame_selections (struct frame *f)
 {
   Lisp_Object frame;
   Lisp_Object rest;
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   struct terminal *t = dpyinfo->terminal;
 
   XSETFRAME (frame, f);
@@ -1098,34 +1054,31 @@ expect_property_change (Display *display, Window window,
 static void
 unexpect_property_change (struct prop_location *location)
 {
-  struct prop_location *prev = 0, *rest = property_change_wait_list;
-  while (rest)
+  struct prop_location *prop, **pprev = &property_change_wait_list;
+
+  for (prop = property_change_wait_list; prop; prop = *pprev)
     {
-      if (rest == location)
+      if (prop == location)
        {
-         if (prev)
-           prev->next = rest->next;
-         else
-           property_change_wait_list = rest->next;
-         xfree (rest);
-         return;
+         *pprev = prop->next;
+         xfree (prop);
+         break;
        }
-      prev = rest;
-      rest = rest->next;
+      else
+       pprev = &prop->next;
     }
 }
 
 /* Remove the property change expectation element for IDENTIFIER.  */
 
-static Lisp_Object
-wait_for_property_change_unwind (Lisp_Object loc)
+static void
+wait_for_property_change_unwind (void *loc)
 {
-  struct prop_location *location = XSAVE_POINTER (loc, 0);
+  struct prop_location *location = loc;
 
   unexpect_property_change (location);
   if (location == property_change_reply_object)
     property_change_reply_object = 0;
-  return Qnil;
 }
 
 /* Actually wait for a property change.
@@ -1140,8 +1093,7 @@ wait_for_property_change (struct prop_location *location)
     emacs_abort ();
 
   /* Make sure to do unexpect_property_change if we quit or err.  */
-  record_unwind_protect (wait_for_property_change_unwind,
-                        make_save_pointer (location));
+  record_unwind_protect_ptr (wait_for_property_change_unwind, location);
 
   XSETCAR (property_change_reply, Qnil);
   property_change_reply_object = location;
@@ -1170,7 +1122,7 @@ wait_for_property_change (struct prop_location *location)
 /* Called from XTread_socket in response to a PropertyNotify event.  */
 
 void
-x_handle_property_notify (XPropertyEvent *event)
+x_handle_property_notify (const XPropertyEvent *event)
 {
   struct prop_location *rest;
 
@@ -1214,10 +1166,10 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
                         Lisp_Object time_stamp, Lisp_Object frame)
 {
   struct frame *f = XFRAME (frame);
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   Display *display = dpyinfo->display;
   Window requestor_window = FRAME_X_WINDOW (f);
-  Time requestor_time = last_event_timestamp;
+  Time requestor_time = dpyinfo->last_user_time;
   Atom target_property = dpyinfo->Xatom_EMACS_TMP;
   Atom selection_atom = symbol_to_x_atom (dpyinfo, selection_symbol);
   Atom type_atom = (CONSP (target_type)
@@ -1254,7 +1206,7 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
      SelectionNotify. */
 #if 0
   x_start_queuing_selection_requests ();
-  record_unwind_protect (queue_selection_requests_unwind, Qnil);
+  record_unwind_protect_void (x_stop_queuing_selection_requests);
 #endif
 
   unblock_input ();
@@ -1275,7 +1227,7 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
 
   /* Otherwise, the selection is waiting for us on the requested property.  */
   return
-    x_get_window_property_as_lisp_data (display, requestor_window,
+    x_get_window_property_as_lisp_data (dpyinfo, requestor_window,
                                        target_property, target_type,
                                        selection_atom);
 }
@@ -1313,7 +1265,7 @@ x_get_window_property (Display *display, Window window, Atom property,
 
   /* First probe the thing to find out how big it is.  */
   result = XGetWindowProperty (display, window, property,
-                              0L, 0L, False, AnyPropertyType,
+                              0, 0, False, AnyPropertyType,
                               actual_type_ret, actual_format_ret,
                               actual_size_ret,
                               &bytes_remaining, &tmp_data);
@@ -1329,9 +1281,7 @@ x_get_window_property (Display *display, Window window, Atom property,
   if (total_size_max < bytes_remaining)
     goto size_overflow;
   total_size = bytes_remaining;
-  data = malloc (total_size + 1);
-  if (! data)
-    goto memory_exhausted;
+  data = xmalloc (total_size + 1);
 
   /* Now read, until we've gotten it all.  */
   while (bytes_remaining)
@@ -1382,13 +1332,11 @@ x_get_window_property (Display *display, Window window, Atom property,
          if (remaining_lim < 0 || remaining_lim < bytes_remaining)
            goto size_overflow;
          total_size = offset + bytes_gotten + bytes_remaining;
-         data1 = realloc (data, total_size + 1);
-         if (! data1)
-           goto memory_exhausted;
+         data1 = xrealloc (data, total_size + 1);
          data = data1;
        }
 
-      if (32 < BITS_PER_LONG && *actual_format_ret == 32)
+      if (BITS_PER_LONG > 32 && *actual_format_ret == 32)
         {
           unsigned long i;
          int  *idata = (int *) (data + offset);
@@ -1416,20 +1364,17 @@ x_get_window_property (Display *display, Window window, Atom property,
   return;
 
  size_overflow:
-  free (data);
+  if (data)
+    xfree (data);
   unblock_input ();
   memory_full (SIZE_MAX);
-
- memory_exhausted:
-  free (data);
-  unblock_input ();
-  memory_full (total_size + 1);
 }
 \f
 /* Use xfree, not XFree, to free the data obtained with this function.  */
 
 static void
-receive_incremental_selection (Display *display, Window window, Atom property,
+receive_incremental_selection (struct x_display_info *dpyinfo,
+                              Window window, Atom property,
                               Lisp_Object target_type,
                               unsigned int min_size_bytes,
                               unsigned char **data_ret,
@@ -1439,6 +1384,8 @@ receive_incremental_selection (Display *display, Window window, Atom property,
 {
   ptrdiff_t offset = 0;
   struct prop_location *wait_object;
+  Display *display = dpyinfo->display;
+
   if (min (PTRDIFF_MAX, SIZE_MAX) < min_size_bytes)
     memory_full (SIZE_MAX);
   *data_ret = xmalloc (min_size_bytes);
@@ -1457,10 +1404,10 @@ receive_incremental_selection (Display *display, Window window, Atom property,
   block_input ();
   XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask);
   TRACE1 ("  Delete property %s",
-         SDATA (SYMBOL_NAME (x_atom_to_symbol (display, property))));
+         SDATA (SYMBOL_NAME (x_atom_to_symbol (dpyinfo, property))));
   XDeleteProperty (display, window, property);
   TRACE1 ("  Expect new value of property %s",
-         SDATA (SYMBOL_NAME (x_atom_to_symbol (display, property))));
+         SDATA (SYMBOL_NAME (x_atom_to_symbol (dpyinfo, property))));
   wait_object = expect_property_change (display, window, property,
                                        PropertyNewValue);
   XFlush (display);
@@ -1525,8 +1472,8 @@ receive_incremental_selection (Display *display, Window window, Atom property,
    if this fails.  */
 
 static Lisp_Object
-x_get_window_property_as_lisp_data (Display *display, Window window,
-                                   Atom property,
+x_get_window_property_as_lisp_data (struct x_display_info *dpyinfo,
+                                   Window window, Atom property,
                                    Lisp_Object target_type,
                                    Atom selection_atom)
 {
@@ -1536,7 +1483,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window,
   unsigned char *data = 0;
   ptrdiff_t bytes = 0;
   Lisp_Object val;
-  struct x_display_info *dpyinfo = x_display_info_for_display (display);
+  Display *display = dpyinfo->display;
 
   TRACE0 ("Reading selection data");
 
@@ -1553,11 +1500,11 @@ x_get_window_property_as_lisp_data (Display *display, Window window,
        signal_error ("Selection owner couldn't convert",
                      actual_type
                      ? list2 (target_type,
-                              x_atom_to_symbol (display, actual_type))
+                              x_atom_to_symbol (dpyinfo, actual_type))
                      : target_type);
       else
        signal_error ("No selection",
-                     x_atom_to_symbol (display, selection_atom));
+                     x_atom_to_symbol (dpyinfo, selection_atom));
     }
 
   if (actual_type == dpyinfo->Xatom_INCR)
@@ -1570,7 +1517,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window,
         calls xmalloc itself.  */
       xfree (data);
       unblock_input ();
-      receive_incremental_selection (display, window, property, target_type,
+      receive_incremental_selection (dpyinfo, window, property, target_type,
                                     min_size_bytes, &data, &bytes,
                                     &actual_type, &actual_format,
                                     &actual_size);
@@ -1584,7 +1531,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window,
 
   /* It's been read.  Now convert it to a lisp object in some semi-rational
      manner.  */
-  val = selection_data_to_lisp_data (display, data, bytes,
+  val = selection_data_to_lisp_data (dpyinfo, data, bytes,
                                     actual_type, actual_format);
 
   /* Use xfree, not XFree, because x_get_window_property
@@ -1625,11 +1572,10 @@ x_get_window_property_as_lisp_data (Display *display, Window window,
 
 
 static Lisp_Object
-selection_data_to_lisp_data (Display *display, const unsigned char *data,
+selection_data_to_lisp_data (struct x_display_info *dpyinfo,
+                            const unsigned char *data,
                             ptrdiff_t size, Atom type, int format)
 {
-  struct x_display_info *dpyinfo = x_display_info_for_display (display);
-
   if (type == dpyinfo->Xatom_NULL)
     return QNULL;
 
@@ -1667,13 +1613,13 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
       int *idata = (int *) data;
 
       if (size == sizeof (int))
-       return x_atom_to_symbol (display, (Atom) idata[0]);
+       return x_atom_to_symbol (dpyinfo, (Atom) idata[0]);
       else
        {
          Lisp_Object v = make_uninit_vector (size / sizeof (int));
 
          for (i = 0; i < size / sizeof (int); i++)
-           ASET (v, i, x_atom_to_symbol (display, (Atom) idata[i]));
+           ASET (v, i, x_atom_to_symbol (dpyinfo, (Atom) idata[i]));
          return v;
        }
     }
@@ -1735,15 +1681,13 @@ cons_to_x_long (Lisp_Object obj)
 /* Use xfree, not XFree, to free the data obtained with this function.  */
 
 static void
-lisp_data_to_selection_data (Display *display, Lisp_Object obj,
-                            unsigned char **data_ret, Atom *type_ret,
-                            ptrdiff_t *size_ret,
-                            int *format_ret, int *nofree_ret)
+lisp_data_to_selection_data (struct x_display_info *dpyinfo,
+                            Lisp_Object obj, struct selection_data *cs)
 {
   Lisp_Object type = Qnil;
-  struct x_display_info *dpyinfo = x_display_info_for_display (display);
 
-  *nofree_ret = 0;
+  eassert (cs != NULL);
+  cs->nofree = 0;
 
   if (CONSP (obj) && SYMBOLP (XCAR (obj)))
     {
@@ -1755,9 +1699,9 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
 
   if (EQ (obj, QNULL) || (EQ (type, QNULL)))
     {                          /* This is not the same as declining */
-      *format_ret = 32;
-      *size_ret = 0;
-      *data_ret = 0;
+      cs->format = 32;
+      cs->size = 0;
+      cs->data = NULL;
       type = QNULL;
     }
   else if (STRINGP (obj))
@@ -1767,19 +1711,19 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
        signal_error ("Non-ASCII string must be encoded in advance", obj);
       if (NILP (type))
        type = QSTRING;
-      *format_ret = 8;
-      *size_ret = SBYTES (obj);
-      *data_ret = SDATA (obj);
-      *nofree_ret = 1;
+      cs->format = 8;
+      cs->size = SBYTES (obj);
+      cs->data = SDATA (obj);
+      cs->nofree = 1;
     }
   else if (SYMBOLP (obj))
     {
       void *data = xmalloc (sizeof (Atom) + 1);
       Atom *x_atom_ptr = data;
-      *data_ret = data;
-      *format_ret = 32;
-      *size_ret = 1;
-      (*data_ret) [sizeof (Atom)] = 0;
+      cs->data = data;
+      cs->format = 32;
+      cs->size = 1;
+      cs->data[sizeof (Atom)] = 0;
       *x_atom_ptr = symbol_to_x_atom (dpyinfo, obj);
       if (NILP (type)) type = QATOM;
     }
@@ -1787,10 +1731,10 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
     {
       void *data = xmalloc (sizeof (short) + 1);
       short *short_ptr = data;
-      *data_ret = data;
-      *format_ret = 16;
-      *size_ret = 1;
-      (*data_ret) [sizeof (short)] = 0;
+      cs->data = data;
+      cs->format = 16;
+      cs->size = 1;
+      cs->data[sizeof (short)] = 0;
       *short_ptr = XINT (obj);
       if (NILP (type)) type = QINTEGER;
     }
@@ -1802,10 +1746,10 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
     {
       void *data = xmalloc (sizeof (unsigned long) + 1);
       unsigned long *x_long_ptr = data;
-      *data_ret = data;
-      *format_ret = 32;
-      *size_ret = 1;
-      (*data_ret) [sizeof (unsigned long)] = 0;
+      cs->data = data;
+      cs->format = 32;
+      cs->size = 1;
+      cs->data[sizeof (unsigned long)] = 0;
       *x_long_ptr = cons_to_x_long (obj);
       if (NILP (type)) type = QINTEGER;
     }
@@ -1828,10 +1772,10 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
            if (!SYMBOLP (AREF (obj, i)))
              signal_error ("All elements of selection vector must have same type", obj);
 
-         *data_ret = data = xnmalloc (size, sizeof *x_atoms);
+         cs->data = data = xnmalloc (size, sizeof *x_atoms);
          x_atoms = data;
-         *format_ret = 32;
-         *size_ret = size;
+         cs->format = 32;
+         cs->size = size;
          for (i = 0; i < size; i++)
            x_atoms[i] = symbol_to_x_atom (dpyinfo, AREF (obj, i));
        }
@@ -1857,11 +1801,11 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
                  break;
                }
            }
-         *data_ret = data = xnmalloc (size, data_size);
+         cs->data = data = xnmalloc (size, data_size);
          x_atoms = data;
          shorts = data;
-         *format_ret = format;
-         *size_ret = size;
+         cs->format = format;
+         cs->size = size;
          for (i = 0; i < size; i++)
            {
              if (format == 32)
@@ -1874,7 +1818,7 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
   else
     signal_error (/* Qselection_error */ "Unrecognized selection data", obj);
 
-  *type_ret = symbol_to_x_atom (dpyinfo, type);
+  cs->type = symbol_to_x_atom (dpyinfo, type);
 }
 
 static Lisp_Object
@@ -1917,7 +1861,7 @@ clean_local_selection_data (Lisp_Object obj)
    We store t there if the reply is successful, lambda if not.  */
 
 void
-x_handle_selection_notify (XSelectionEvent *event)
+x_handle_selection_notify (const XSelectionEvent *event)
 {
   if (event->requestor != reading_selection_window)
     return;
@@ -2038,7 +1982,7 @@ On Nextstep, TIME-STAMP and TERMINAL are unused.  */)
     error ("X selection unavailable for this frame");
 
   val = x_get_local_selection (selection_symbol, target_type, 1,
-                              FRAME_X_DISPLAY_INFO (f));
+                              FRAME_DISPLAY_INFO (f));
 
   if (NILP (val) && FRAME_LIVE_P (f))
     {
@@ -2085,7 +2029,7 @@ On MS-DOS, all this does is return non-nil if we own the selection.  */)
   if (!f)
     return Qnil;
 
-  dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  dpyinfo = FRAME_DISPLAY_INFO (f);
   CHECK_SYMBOL (selection);
 
   /* Don't disown the selection when we're not the owner.  */
@@ -2096,7 +2040,7 @@ On MS-DOS, all this does is return non-nil if we own the selection.  */)
 
   block_input ();
   if (NILP (time_object))
-    timestamp = last_event_timestamp;
+    timestamp = dpyinfo->last_user_time;
   else
     CONS_TO_INTEGER (time_object, Time, timestamp);
   XSetSelectionOwner (dpyinfo->display, selection_atom, None, timestamp);
@@ -2107,7 +2051,7 @@ On MS-DOS, all this does is return non-nil if we own the selection.  */)
      the selection owner to None.  The NCD server does, the MIT Sun4 server
      doesn't.  So we synthesize one; this means we might get two, but
      that's ok, because the second one won't have any effect.  */
-  SELECTION_EVENT_DISPLAY (&event.sie) = dpyinfo->display;
+  SELECTION_EVENT_DPYINFO (&event.sie) = dpyinfo;
   SELECTION_EVENT_SELECTION (&event.sie) = selection_atom;
   SELECTION_EVENT_TIME (&event.sie) = timestamp;
   x_handle_selection_clear (&event.ie);
@@ -2137,7 +2081,7 @@ On Nextstep, TERMINAL is unused.  */)
   if (EQ (selection, Qnil)) selection = QPRIMARY;
   if (EQ (selection, Qt)) selection = QSECONDARY;
 
-  if (f && !NILP (LOCAL_SELECTION (selection, FRAME_X_DISPLAY_INFO (f))))
+  if (f && !NILP (LOCAL_SELECTION (selection, FRAME_DISPLAY_INFO (f))))
     return Qt;
   else
     return Qnil;
@@ -2170,7 +2114,7 @@ On Nextstep, TERMINAL is unused.  */)
   if (!f)
     return Qnil;
 
-  dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  dpyinfo = FRAME_DISPLAY_INFO (f);
 
   if (!NILP (LOCAL_SELECTION (selection, dpyinfo)))
     return Qt;
@@ -2191,7 +2135,7 @@ static Lisp_Object
 x_clipboard_manager_save (Lisp_Object frame)
 {
   struct frame *f = XFRAME (frame);
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   Atom data = dpyinfo->Xatom_UTF8_STRING;
 
   XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
@@ -2208,11 +2152,9 @@ x_clipboard_manager_save (Lisp_Object frame)
 static Lisp_Object
 x_clipboard_manager_error_1 (Lisp_Object err)
 {
-  Lisp_Object args[2];
-  args[0] = build_string ("X clipboard manager error: %s\n\
+  AUTO_STRING (format, "X clipboard manager error: %s\n\
 If the problem persists, set `x-select-enable-clipboard-manager' to nil.");
-  args[1] = CAR (CDR (err));
-  Fmessage (2, args);
+  Fmessage (2, (Lisp_Object []) {format, CAR (CDR (err))});
   return Qnil;
 }
 
@@ -2241,7 +2183,7 @@ x_clipboard_manager_save_frame (Lisp_Object frame)
       && (f = XFRAME (frame), FRAME_X_P (f))
       && FRAME_LIVE_P (f))
     {
-      struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+      struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
       Lisp_Object local_selection
        = LOCAL_SELECTION (QCLIPBOARD, dpyinfo);
 
@@ -2279,10 +2221,8 @@ x_clipboard_manager_save_all (void)
       local_frame = XCAR (XCDR (XCDR (XCDR (local_selection))));
       if (FRAME_LIVE_P (XFRAME (local_frame)))
        {
-         Lisp_Object args[1];
-         args[0] = build_string ("Saving clipboard to X clipboard manager...");
-         Fmessage (1, args);
-
+         AUTO_STRING (saving, "Saving clipboard to X clipboard manager...");
+         Fmessage (1, &saving);
          internal_condition_case_1 (x_clipboard_manager_save, local_frame,
                                     Qt, x_clipboard_manager_error_2);
        }
@@ -2337,10 +2277,10 @@ x_check_property_data (Lisp_Object data)
 void
 x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format)
 {
-  long val;
-  long  *d32 = (long  *) ret;
-  short *d16 = (short *) ret;
-  char  *d08 = (char  *) ret;
+  unsigned long val;
+  unsigned long  *d32 = (unsigned long  *) ret;
+  unsigned short *d16 = (unsigned short *) ret;
+  unsigned char  *d08 = (unsigned char  *) ret;
   Lisp_Object iter;
 
   for (iter = data; CONSP (iter); iter = XCDR (iter))
@@ -2348,11 +2288,26 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format)
       Lisp_Object o = XCAR (iter);
 
       if (INTEGERP (o) || FLOATP (o) || CONSP (o))
-       val = cons_to_signed (o, LONG_MIN, LONG_MAX);
+        {
+          if (CONSP (o)
+             && RANGED_INTEGERP (X_LONG_MIN >> 16, XCAR (o), X_LONG_MAX >> 16)
+             && RANGED_INTEGERP (- (1 << 15), XCDR (o), -1))
+            {
+             /* cons_to_x_long does not handle negative values for v2.
+                 For XDnd, v2 might be y of a window, and can be negative.
+                 The XDnd spec. is not explicit about negative values,
+                 but let's assume negative v2 is sent modulo 2**16.  */
+             unsigned long v1 = XINT (XCAR (o)) & 0xffff;
+             unsigned long v2 = XINT (XCDR (o)) & 0xffff;
+             val = (v1 << 16) | v2;
+            }
+          else
+            val = cons_to_x_long (o);
+        }
       else if (STRINGP (o))
         {
           block_input ();
-          val = (long) XInternAtom (dpy, SSDATA (o), False);
+          val = XInternAtom (dpy, SSDATA (o), False);
           unblock_input ();
         }
       else
@@ -2360,17 +2315,15 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format)
 
       if (format == 8)
        {
-         if (CHAR_MIN <= val && val <= CHAR_MAX)
-           *d08++ = val;
-         else
+         if ((1 << 8) < val && val <= X_ULONG_MAX - (1 << 7))
            error ("Out of 'char' range");
+         *d08++ = val;
        }
       else if (format == 16)
        {
-         if (SHRT_MIN <= val && val <= SHRT_MAX)
-           *d16++ = val;
-         else
+         if ((1 << 16) < val && val <= X_ULONG_MAX - (1 << 15))
            error ("Out of 'short' range");
+         *d16++ = val;
        }
       else
         *d32++ = val;
@@ -2394,50 +2347,13 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format)
 
 Lisp_Object
 x_property_data_to_lisp (struct frame *f, const unsigned char *data,
-                        Atom type, int format, long unsigned int size)
+                        Atom type, int format, unsigned long size)
 {
   ptrdiff_t format_bytes = format >> 3;
   if (PTRDIFF_MAX / format_bytes < size)
     memory_full (SIZE_MAX);
-  return selection_data_to_lisp_data (FRAME_X_DISPLAY (f),
-                                     data, size * format_bytes, type, format);
-}
-
-/* Get the mouse position in frame relative coordinates.  */
-
-static void
-mouse_position_for_drop (FRAME_PTR f, int *x, int *y)
-{
-  Window root, dummy_window;
-  int dummy;
-
-  block_input ();
-
-  XQueryPointer (FRAME_X_DISPLAY (f),
-                 DefaultRootWindow (FRAME_X_DISPLAY (f)),
-
-                 /* The root window which contains the pointer.  */
-                 &root,
-
-                 /* Window pointer is on, not used  */
-                 &dummy_window,
-
-                 /* The position on that root window.  */
-                 x, y,
-
-                 /* x/y in dummy_window coordinates, not used.  */
-                 &dummy, &dummy,
-
-                 /* Modifier keys and pointer buttons, about which
-                    we don't care.  */
-                 (unsigned int *) &dummy);
-
-
-  /* Absolute to relative.  */
-  *x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
-  *y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
-
-  unblock_input ();
+  return selection_data_to_lisp_data (FRAME_DISPLAY_INFO (f), data,
+                                     size * format_bytes, type, format);
 }
 
 DEFUN ("x-get-atom-name", Fx_get_atom_name,
@@ -2450,23 +2366,23 @@ Use the display for FRAME or the current frame if FRAME is not given or nil.
 If the value is 0 or the atom is not known, return the empty string.  */)
   (Lisp_Object value, Lisp_Object frame)
 {
-  struct frame *f = check_x_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
   char *name = 0;
   char empty[] = "";
   Lisp_Object ret = Qnil;
   Display *dpy = FRAME_X_DISPLAY (f);
   Atom atom;
-  int had_errors;
+  bool had_errors_p;
 
   CONS_TO_INTEGER (value, Atom, atom);
 
   block_input ();
   x_catch_errors (dpy);
   name = atom ? XGetAtomName (dpy, atom) : empty;
-  had_errors = x_had_errors_p (dpy);
+  had_errors_p = x_had_errors_p (dpy);
   x_uncatch_errors ();
 
-  if (!had_errors)
+  if (!had_errors_p)
     ret = build_string (name);
 
   if (atom && name) XFree (name);
@@ -2485,9 +2401,9 @@ FRAME is on.  If FRAME is nil, the selected frame is used.  */)
   (Lisp_Object atom, Lisp_Object frame)
 {
   Atom x_atom;
-  struct frame *f = check_x_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
   ptrdiff_t i;
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
 
 
   if (SYMBOLP (atom))
@@ -2517,7 +2433,7 @@ FRAME is on.  If FRAME is nil, the selected frame is used.  */)
 /* Convert an XClientMessageEvent to a Lisp event of type DRAG_N_DROP_EVENT.  */
 
 int
-x_handle_dnd_message (struct frame *f, XClientMessageEvent *event,
+x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event,
                       struct x_display_info *dpyinfo, struct input_event *bufp)
 {
   Lisp_Object vec;
@@ -2541,7 +2457,7 @@ x_handle_dnd_message (struct frame *f, XClientMessageEvent *event,
      function expects them to be of size int (i.e. 32).  So to be able to
      use that function, put the data in the form it expects if format is 32. */
 
-  if (32 < BITS_PER_LONG && event->format == 32)
+  if (BITS_PER_LONG > 32 && event->format == 32)
     {
       for (i = 0; i < 5; ++i) /* There are only 5 longs in a ClientMessage. */
        idata[i] = event->data.l[i];
@@ -2549,7 +2465,7 @@ x_handle_dnd_message (struct frame *f, XClientMessageEvent *event,
     }
 
   vec = Fmake_vector (make_number (4), Qnil);
-  ASET (vec, 0, SYMBOL_NAME (x_atom_to_symbol (FRAME_X_DISPLAY (f),
+  ASET (vec, 0, SYMBOL_NAME (x_atom_to_symbol (FRAME_DISPLAY_INFO (f),
                                               event->message_type)));
   ASET (vec, 1, frame);
   ASET (vec, 2, make_number (event->format));
@@ -2559,7 +2475,7 @@ x_handle_dnd_message (struct frame *f, XClientMessageEvent *event,
                                         event->format,
                                         size));
 
-  mouse_position_for_drop (f, &x, &y);
+  x_relative_mouse_position (f, &x, &y);
   bufp->kind = DRAG_N_DROP_EVENT;
   bufp->frame_or_window = frame;
   bufp->timestamp = CurrentTime;
@@ -2571,7 +2487,7 @@ x_handle_dnd_message (struct frame *f, XClientMessageEvent *event,
   return 1;
 }
 
-DEFUN ("x-send-client-message", Fx_send_client_event,
+DEFUN ("x-send-client-message", Fx_send_client_message,
        Sx_send_client_message, 6, 6, 0,
        doc: /* Send a client message of MESSAGE-TYPE to window DEST on DISPLAY.
 
@@ -2618,7 +2534,7 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
   struct x_display_info *dpyinfo = check_x_display_info (display);
   Window wdest;
   XEvent event;
-  struct frame *f = check_x_frame (from);
+  struct frame *f = decode_window_system_frame (from);
   int to_root;
 
   CHECK_NUMBER (format);
@@ -2635,7 +2551,7 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
 
   if (FRAMEP (dest) || NILP (dest))
     {
-      struct frame *fdest = check_x_frame (dest);
+      struct frame *fdest = decode_window_system_frame (dest);
       wdest = FRAME_OUTER_WINDOW (fdest);
     }
   else if (STRINGP (dest))
@@ -2657,6 +2573,8 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
 
   block_input ();
 
+  event.xclient.send_event = True;
+  event.xclient.serial = 0;
   event.xclient.message_type = message_type;
   event.xclient.display = dpyinfo->display;
 
@@ -2664,19 +2582,19 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
      when sending to the root window.  */
   event.xclient.window = to_root ? FRAME_OUTER_WINDOW (f) : wdest;
 
-
-  memset (event.xclient.data.b, 0, sizeof (event.xclient.data.b));
+  memset (event.xclient.data.l, 0, sizeof (event.xclient.data.l));
   x_fill_property_data (dpyinfo->display, values, event.xclient.data.b,
                         event.xclient.format);
 
   /* If event mask is 0 the event is sent to the client that created
      the destination window.  But if we are sending to the root window,
-     there is no such client.  Then we set the event mask to 0xffff.  The
+     there is no such client.  Then we set the event mask to 0xffffff.  The
      event then goes to clients selecting for events on the root window.  */
   x_catch_errors (dpyinfo->display);
   {
     int propagate = to_root ? False : True;
-    unsigned mask = to_root ? 0xffff : 0;
+    long mask = to_root ? 0xffffff : 0;
+
     XSendEvent (dpyinfo->display, wdest, propagate, mask, &event);
     XFlush (dpyinfo->display);
   }
@@ -2711,12 +2629,14 @@ syms_of_xselect (void)
   converted_selections = NULL;
   conversion_fail_tag = None;
 
+  /* FIXME: Duplicate definition in nsselect.c.  */
   DEFVAR_LISP ("selection-converter-alist", Vselection_converter_alist,
               doc: /* An alist associating X Windows selection-types with functions.
 These functions are called to convert the selection, with three args:
 the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');
 a desired type to which the selection should be converted;
-and the local selection value (whatever was given to `x-own-selection').
+and the local selection value (whatever was given to
+`x-own-selection-internal').
 
 The function should return the value to send to the X server
 \(typically a string).  A return value of nil