Merge from trunk.
[bpt/emacs.git] / src / xselect.c
index 5c2e12c..9eee4ee 100644 (file)
@@ -81,13 +81,13 @@ static Lisp_Object clean_local_selection_data (Lisp_Object);
 
 #ifdef TRACE_SELECTION
 #define TRACE0(fmt) \
-  fprintf (stderr, "%d: " fmt "\n", getpid ())
+  fprintf (stderr, "%"pMd": " fmt "\n", (printmax_t) getpid ())
 #define TRACE1(fmt, a0) \
-  fprintf (stderr, "%d: " fmt "\n", getpid (), a0)
+  fprintf (stderr, "%"pMd": " fmt "\n", (printmax_t) getpid (), a0)
 #define TRACE2(fmt, a0, a1) \
-  fprintf (stderr, "%d: " fmt "\n", getpid (), a0, a1)
+  fprintf (stderr, "%"pMd": " fmt "\n", (printmax_t) getpid (), a0, a1)
 #define TRACE3(fmt, a0, a1, a2) \
-  fprintf (stderr, "%d: " fmt "\n", getpid (), a0, a1, a2)
+  fprintf (stderr, "%"pMd": " fmt "\n", (printmax_t) getpid (), a0, a1, a2)
 #else
 #define TRACE0(fmt)            (void) 0
 #define TRACE1(fmt, a0)                (void) 0
@@ -111,9 +111,12 @@ static Lisp_Object Qx_lost_selection_functions, Qx_sent_selection_functions;
    is not necessarily sizeof (long).  */
 #define X_LONG_SIZE 4
 
-/* Maximum unsigned 'short' and 'long' values suitable for libX11.  */
-#define X_USHRT_MAX 0xffff
-#define X_ULONG_MAX 0xffffffff
+/* 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
@@ -376,7 +379,8 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
 \f
 /* 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.
+   Return nil, a string, a vector, a symbol, an integer, or a cons
+   that CONS_TO_INTEGER could plausibly handle.
    This function is used both for remote requests (LOCAL_REQUEST is zero)
    and for local x-get-selection-internal (LOCAL_REQUEST is nonzero).
 
@@ -388,7 +392,6 @@ x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
 {
   Lisp_Object local_value;
   Lisp_Object handler_fn, value, check;
-  int count;
 
   local_value = LOCAL_SELECTION (selection_symbol, dpyinfo);
 
@@ -405,7 +408,7 @@ x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object 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_INDEX ();
+      ptrdiff_t count = SPECPDL_INDEX ();
       specbind (Qinhibit_quit, Qt);
 
       CHECK_SYMBOL (target_type);
@@ -590,7 +593,8 @@ static int x_reply_selection_request_cnt;
 #endif  /* TRACE_SELECTION */
 
 static void
-x_reply_selection_request (struct input_event *event, struct x_display_info *dpyinfo)
+x_reply_selection_request (struct input_event *event,
+                           struct x_display_info *dpyinfo)
 {
   XEvent reply_base;
   XSelectionEvent *reply = &(reply_base.xselection);
@@ -598,7 +602,7 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy
   Window window = SELECTION_EVENT_REQUESTOR (event);
   ptrdiff_t bytes_remaining;
   int max_bytes = selection_quantum (display);
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   struct selection_data *cs;
 
   reply->type = SelectionNotify;
@@ -641,7 +645,7 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy
       else
        {
          /* Send an INCR tag to initiate incremental transfer.  */
-         unsigned long value[1];
+         long value[1];
 
          TRACE2 ("Start sending %"pD"d bytes incrementally (%s)",
                  bytes_remaining, XGetAtomName (display, cs->property));
@@ -651,7 +655,7 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy
 
          /* XChangeProperty expects an array of long even if long is
             more than 32 bits.  */
-         value[0] = min (bytes_remaining, X_ULONG_MAX);
+         value[0] = min (bytes_remaining, X_LONG_MAX);
          XChangeProperty (display, window, cs->property,
                           dpyinfo->Xatom_INCR, 32, PropModeReplace,
                           (unsigned char *) value, 1);
@@ -787,7 +791,7 @@ x_handle_selection_request (struct input_event *event)
   Atom property = SELECTION_EVENT_PROPERTY (event);
   Lisp_Object local_selection_data;
   int success = 0;
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   GCPRO2 (local_selection_data, target_symbol);
 
   if (!dpyinfo) goto DONE;
@@ -1077,7 +1081,8 @@ waiting_for_other_props_on_window (Display *display, Window window)
    this awaited property change.  */
 
 static struct prop_location *
-expect_property_change (Display *display, Window window, Atom property, int state)
+expect_property_change (Display *display, Window window,
+                        Atom property, int state)
 {
   struct prop_location *pl = (struct prop_location *) xmalloc (sizeof *pl);
   pl->identifier = ++prop_location_identifier;
@@ -1134,7 +1139,7 @@ static void
 wait_for_property_change (struct prop_location *location)
 {
   int secs, usecs;
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
 
   if (property_change_reply_object)
     abort ();
@@ -1681,9 +1686,9 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
      convert it to a cons of integers, 16 bits in each half.
    */
   else if (format == 32 && size == sizeof (int))
-    return INTEGER_TO_CONS (((unsigned int *) data) [0]);
+    return INTEGER_TO_CONS (((int *) data) [0]);
   else if (format == 16 && size == sizeof (short))
-    return make_number (((unsigned short *) data) [0]);
+    return make_number (((short *) data) [0]);
 
   /* Convert any other kind of data to a vector of numbers, represented
      as above (as an integer, or a cons of two 16 bit integers.)
@@ -1695,7 +1700,7 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
       v = Fmake_vector (make_number (size / 2), make_number (0));
       for (i = 0; i < size / 2; i++)
        {
-         EMACS_INT j = ((unsigned short *) data) [i];
+         short j = ((short *) data) [i];
          Faset (v, make_number (i), make_number (j));
        }
       return v;
@@ -1707,13 +1712,28 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
                                    make_number (0));
       for (i = 0; i < size / X_LONG_SIZE; i++)
        {
-         unsigned int j = ((unsigned int *) data) [i];
+         int j = ((int *) data) [i];
          Faset (v, make_number (i), INTEGER_TO_CONS (j));
        }
       return v;
     }
 }
 
+/* Convert OBJ to an X long value, and return it as unsigned long.
+   OBJ should be an integer or a cons representing an integer.
+   Treat values in the range X_LONG_MAX + 1 .. X_ULONG_MAX as X
+   unsigned long values: in theory these values are supposed to be
+   signed but in practice unsigned 32-bit data are communicated via X
+   selections and we need to support that.  */
+static unsigned long
+cons_to_x_long (Lisp_Object obj)
+{
+  if (X_ULONG_MAX <= INTMAX_MAX
+      || XINT (INTEGERP (obj) ? obj : XCAR (obj)) < 0)
+    return cons_to_signed (obj, X_LONG_MIN, min (X_ULONG_MAX, INTMAX_MAX));
+  else
+    return cons_to_unsigned (obj, X_ULONG_MAX);
+}
 
 /* Use xfree, not XFree, to free the data obtained with this function.  */
 
@@ -1764,13 +1784,13 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
       (*(Atom **) data_ret) [0] = symbol_to_x_atom (dpyinfo, obj);
       if (NILP (type)) type = QATOM;
     }
-  else if (RANGED_INTEGERP (0, obj, X_USHRT_MAX))
+  else if (RANGED_INTEGERP (X_SHRT_MIN, obj, X_SHRT_MAX))
     {
       *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1);
       *format_ret = 16;
       *size_ret = 1;
       (*data_ret) [sizeof (short)] = 0;
-      (*(unsigned short **) data_ret) [0] = XINT (obj);
+      (*(short **) data_ret) [0] = XINT (obj);
       if (NILP (type)) type = QINTEGER;
     }
   else if (INTEGERP (obj)
@@ -1779,11 +1799,11 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
                   || (CONSP (XCDR (obj))
                       && INTEGERP (XCAR (XCDR (obj)))))))
     {
-      *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1);
+      *data_ret = (unsigned char *) xmalloc (sizeof (unsigned long) + 1);
       *format_ret = 32;
       *size_ret = 1;
-      (*data_ret) [sizeof (long)] = 0;
-      (*(unsigned long **) data_ret) [0] = cons_to_unsigned (obj, X_ULONG_MAX);
+      (*data_ret) [sizeof (unsigned long)] = 0;
+      (*(unsigned long **) data_ret) [0] = cons_to_x_long (obj);
       if (NILP (type)) type = QINTEGER;
     }
   else if (VECTORP (obj))
@@ -1817,25 +1837,30 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
          int data_size = sizeof (short);
          if (NILP (type)) type = QINTEGER;
          for (i = 0; i < size; i++)
-           if (X_USHRT_MAX
-               < cons_to_unsigned (XVECTOR (obj)->contents[i], X_ULONG_MAX))
-             {
-               /* Use sizeof (long) even if it is more than 32 bits.
-                  See comment in x_get_window_property and
-                  x_fill_property_data.  */
-               data_size = sizeof (long);
-               format = 32;
-             }
+           {
+             if (! RANGED_INTEGERP (X_SHRT_MIN, XVECTOR (obj)->contents[i],
+                                    X_SHRT_MAX))
+               {
+                 /* Use sizeof (long) even if it is more than 32 bits.
+                    See comment in x_get_window_property and
+                    x_fill_property_data.  */
+                 data_size = sizeof (long);
+                 format = 32;
+                 break;
+               }
+           }
          *data_ret = xnmalloc (size, data_size);
          *format_ret = format;
          *size_ret = size;
          for (i = 0; i < size; i++)
-           if (format == 32)
-             (*((unsigned long **) data_ret)) [i] =
-               cons_to_unsigned (XVECTOR (obj)->contents[i], X_ULONG_MAX);
-           else
-             (*((unsigned short **) data_ret)) [i] =
-               cons_to_unsigned (XVECTOR (obj)->contents[i], X_USHRT_MAX);
+           {
+             if (format == 32)
+               (*((unsigned long **) data_ret)) [i] =
+                 cons_to_x_long (XVECTOR (obj)->contents[i]);
+             else
+               (*((short **) data_ret)) [i] =
+                 XINT (XVECTOR (obj)->contents[i]);
+           }
        }
     }
   else
@@ -2454,15 +2479,9 @@ FRAME is on.  If FRAME is nil, the selected frame is used.  */)
       return Qnil;
 
   if (dpyinfo->x_dnd_atoms_length == dpyinfo->x_dnd_atoms_size)
-    {
-      if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *dpyinfo->x_dnd_atoms / 2
-         < dpyinfo->x_dnd_atoms_size)
-       memory_full (SIZE_MAX);
-      dpyinfo->x_dnd_atoms = xrealloc (dpyinfo->x_dnd_atoms,
-                                      (2 * sizeof *dpyinfo->x_dnd_atoms
-                                       * dpyinfo->x_dnd_atoms_size));
-      dpyinfo->x_dnd_atoms_size *= 2;
-    }
+    dpyinfo->x_dnd_atoms =
+      xpalloc (dpyinfo->x_dnd_atoms, &dpyinfo->x_dnd_atoms_size,
+              1, -1, sizeof *dpyinfo->x_dnd_atoms);
 
   dpyinfo->x_dnd_atoms[dpyinfo->x_dnd_atoms_length++] = x_atom;
   return Qnil;
@@ -2471,7 +2490,8 @@ 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, struct x_display_info *dpyinfo, struct input_event *bufp)
+x_handle_dnd_message (struct frame *f, XClientMessageEvent *event,
+                      struct x_display_info *dpyinfo, struct input_event *bufp)
 {
   Lisp_Object vec;
   Lisp_Object frame;
@@ -2479,7 +2499,7 @@ x_handle_dnd_message (struct frame *f, XClientMessageEvent *event, struct x_disp
   unsigned long size = 160/event->format;
   int x, y;
   unsigned char *data = (unsigned char *) event->data.b;
-  unsigned int idata[5];
+  int idata[5];
   ptrdiff_t i;
 
   for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i)
@@ -2549,22 +2569,24 @@ the Atom is sent.  If a value is a cons, it is converted to a 32 bit number
 with the high 16 bits from the car and the lower 16 bit from the cdr.
 If more values than fits into the event is given, the excessive values
 are ignored.  */)
-  (Lisp_Object display, Lisp_Object dest, Lisp_Object from, Lisp_Object message_type, Lisp_Object format, Lisp_Object values)
+  (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
+   Lisp_Object message_type, Lisp_Object format, Lisp_Object values)
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
 
   CHECK_STRING (message_type);
-  x_send_client_event(display, dest, from,
-                      XInternAtom (dpyinfo->display,
-                                   SSDATA (message_type),
-                                   False),
-                      format, values);
+  x_send_client_event (display, dest, from,
+                       XInternAtom (dpyinfo->display,
+                                    SSDATA (message_type),
+                                    False),
+                       format, values);
 
   return Qnil;
 }
 
 void
-x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from, Atom message_type, Lisp_Object format, Lisp_Object values)
+x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
+                     Atom message_type, Lisp_Object format, Lisp_Object values)
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
   Window wdest;
@@ -2578,13 +2600,12 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from, At
   if (x_check_property_data (values) == -1)
     error ("Bad data in VALUES, must be number, cons or string");
 
-  event.xclient.type = ClientMessage;
-  event.xclient.format = XFASTINT (format);
-
-  if (event.xclient.format != 8 && event.xclient.format != 16
-      && event.xclient.format != 32)
+  if (XINT (format) != 8 && XINT (format) != 16 && XINT (format) != 32)
     error ("FORMAT must be one of 8, 16 or 32");
 
+  event.xclient.type = ClientMessage;
+  event.xclient.format = XINT (format);
+
   if (FRAMEP (dest) || NILP (dest))
     {
       struct frame *fdest = check_x_frame (dest);