Merge from emacs--devo--0
[bpt/emacs.git] / src / xselect.c
index 9c2c221..3fe109a 100644 (file)
@@ -1,6 +1,6 @@
 /* X Selection processing for Emacs.
    Copyright (C) 1993, 1994, 1995, 1996, 1997, 2000, 2001, 2002, 2003,
-                 2004, 2005, 2006 Free Software Foundation, Inc.
+                 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -123,8 +123,8 @@ Lisp_Object QCUT_BUFFER0, QCUT_BUFFER1, QCUT_BUFFER2, QCUT_BUFFER3,
 
 static Lisp_Object Vx_lost_selection_functions;
 static Lisp_Object Vx_sent_selection_functions;
-/* Coding system for communicating with other X clients via cutbuffer,
-   selection, and clipboard.  */
+/* Coding system for communicating with other X clients via selection
+   and clipboard.  */
 static Lisp_Object Vselection_coding_system;
 
 /* Coding system for the next communicating with other X clients.  */
@@ -555,11 +555,9 @@ x_get_local_selection (selection_symbol, target_type, local_request)
                && INTEGERP (XCAR (XCDR (check)))
                && NILP (XCDR (XCDR (check))))))
     return value;
-  else
-    return
-      Fsignal (Qerror,
-              Fcons (build_string ("invalid data returned by selection-conversion function"),
-                     Fcons (handler_fn, Fcons (value, Qnil))));
+
+  signal_error ("Invalid data returned by selection-conversion function",
+               list2 (handler_fn, value));
 }
 \f
 /* Subroutines of x_reply_selection_request.  */
@@ -837,7 +835,7 @@ x_reply_selection_request (event, format, data, size, type)
            break;
 
          /* Now wait for the requester to ack this chunk by deleting the
-            property.   This can run random lisp code or signal.  */
+            property.  This can run random lisp code or signal.  */
          TRACE1 ("Waiting for increment ACK (deletion of %s)",
                  XGetAtomName (display, reply.property));
          wait_for_property_change (wait_object);
@@ -958,6 +956,12 @@ x_handle_selection_request (event)
       Atom type;
       int nofree;
 
+      if (CONSP (converted_selection) && NILP (XCDR (converted_selection)))
+        {
+          x_decline_selection_request (event);
+          goto DONE2;
+        }
+
       lisp_data_to_selection_data (SELECTION_EVENT_DISPLAY (event),
                                   converted_selection,
                                   &data, &type, &size, &format, &nofree);
@@ -973,6 +977,8 @@ x_handle_selection_request (event)
       if (!nofree)
        xfree (data);
     }
+
+ DONE2:
   unbind_to (count, Qnil);
 
  DONE:
@@ -1348,8 +1354,7 @@ copy_multiple_data (obj)
       CHECK_VECTOR (vec2);
       if (XVECTOR (vec2)->size != 2)
        /* ??? Confusing error message */
-       Fsignal (Qerror, Fcons (build_string ("vectors must be of length 2"),
-                               Fcons (vec2, Qnil)));
+       signal_error ("Vectors must be of length 2", vec2);
       XVECTOR (vec)->contents [i] = Fmake_vector (2, Qnil);
       XVECTOR (XVECTOR (vec)->contents [i])->contents [0]
        = XVECTOR (vec2)->contents [0];
@@ -1717,19 +1722,15 @@ x_get_window_property_as_lisp_data (display, window, property, target_type,
       there_is_a_selection_owner
        = XGetSelectionOwner (display, selection_atom);
       UNBLOCK_INPUT;
-      Fsignal (Qerror,
-              there_is_a_selection_owner
-              ? Fcons (build_string ("selection owner couldn't convert"),
-                       actual_type
-                       ? Fcons (target_type,
-                                Fcons (x_atom_to_symbol (display,
-                                                         actual_type),
-                                       Qnil))
-                       : Fcons (target_type, Qnil))
-              : Fcons (build_string ("no selection"),
-                       Fcons (x_atom_to_symbol (display,
-                                                selection_atom),
-                              Qnil)));
+      if (there_is_a_selection_owner)
+       signal_error ("Selection owner couldn't convert",
+                     actual_type
+                     ? list2 (target_type,
+                              x_atom_to_symbol (display, actual_type))
+                     : target_type);
+      else
+       signal_error ("No selection",
+                     x_atom_to_symbol (display, selection_atom));
     }
 
   if (actual_type == dpyinfo->Xatom_INCR)
@@ -1929,10 +1930,7 @@ lisp_data_to_selection_data (display, obj,
     {
       if (SCHARS (obj) < SBYTES (obj))
        /* OBJ is a multibyte string containing a non-ASCII char.  */
-       Fsignal (Qerror, /* Qselection_error */
-                Fcons (build_string
-                       ("Non-ASCII string must be encoded in advance"),
-                       Fcons (obj, Qnil)));
+       signal_error ("Non-ASCII string must be encoded in advance", obj);
       if (NILP (type))
        type = QSTRING;
       *format_ret = 8;
@@ -1993,10 +1991,7 @@ lisp_data_to_selection_data (display, obj,
              (*(Atom **) data_ret) [i]
                = symbol_to_x_atom (dpyinfo, display, XVECTOR (obj)->contents [i]);
            else
-             Fsignal (Qerror, /* Qselection_error */
-                      Fcons (build_string
-                  ("all elements of selection vector must have same type"),
-                             Fcons (obj, Qnil)));
+             signal_error ("All elements of selection vector must have same type", obj);
        }
 #if 0 /* #### MULTIPLE doesn't work yet */
       else if (VECTORP (XVECTOR (obj)->contents [0]))
@@ -2012,10 +2007,9 @@ lisp_data_to_selection_data (display, obj,
              {
                Lisp_Object pair = XVECTOR (obj)->contents [i];
                if (XVECTOR (pair)->size != 2)
-                 Fsignal (Qerror,
-                          Fcons (build_string
-       ("elements of the vector must be vectors of exactly two elements"),
-                                 Fcons (pair, Qnil)));
+                 signal_error (
+       "Elements of the vector must be vectors of exactly two elements",
+                               pair);
 
                (*(Atom **) data_ret) [i * 2]
                  = symbol_to_x_atom (dpyinfo, display,
@@ -2025,10 +2019,8 @@ lisp_data_to_selection_data (display, obj,
                                      XVECTOR (pair)->contents [1]);
              }
            else
-             Fsignal (Qerror,
-                      Fcons (build_string
-                  ("all elements of the vector must be of the same type"),
-                             Fcons (obj, Qnil)));
+             signal_error ("All elements of the vector must be of the same type",
+                           obj);
 
        }
 #endif
@@ -2043,10 +2035,9 @@ lisp_data_to_selection_data (display, obj,
            if (CONSP (XVECTOR (obj)->contents [i]))
              *format_ret = 32;
            else if (!INTEGERP (XVECTOR (obj)->contents [i]))
-             Fsignal (Qerror, /* Qselection_error */
-                      Fcons (build_string
-       ("elements of selection vector must be integers or conses of integers"),
-                             Fcons (obj, Qnil)));
+             signal_error (/* Qselection_error */
+    "Elements of selection vector must be integers or conses of integers",
+                           obj);
 
           /* Use sizeof(long) even if it is more than 32 bits.  See comment
              in x_get_window_property and x_fill_property_data.  */
@@ -2063,9 +2054,7 @@ lisp_data_to_selection_data (display, obj,
        }
     }
   else
-    Fsignal (Qerror, /* Qselection_error */
-            Fcons (build_string ("unrecognized selection data"),
-                   Fcons (obj, Qnil)));
+    signal_error (/* Qselection_error */ "Unrecognized selection data", obj);
 
   *type_ret = symbol_to_x_atom (dpyinfo, display, type);
 }
@@ -2351,15 +2340,13 @@ initialize_cut_buffers (display, window)
 
 
 #define CHECK_CUT_BUFFER(symbol)                                       \
-  { CHECK_SYMBOL ((symbol));                                   \
+  do { CHECK_SYMBOL ((symbol));                                        \
     if (!EQ((symbol), QCUT_BUFFER0) && !EQ((symbol), QCUT_BUFFER1)     \
        && !EQ((symbol), QCUT_BUFFER2) && !EQ((symbol), QCUT_BUFFER3)   \
        && !EQ((symbol), QCUT_BUFFER4) && !EQ((symbol), QCUT_BUFFER5)   \
        && !EQ((symbol), QCUT_BUFFER6) && !EQ((symbol), QCUT_BUFFER7))  \
-      Fsignal (Qerror,                                                 \
-              Fcons (build_string ("doesn't name a cut buffer"),       \
-                            Fcons ((symbol), Qnil)));                  \
-  }
+      signal_error ("Doesn't name a cut buffer", (symbol));            \
+  } while (0)
 
 DEFUN ("x-get-cut-buffer-internal", Fx_get_cut_buffer_internal,
        Sx_get_cut_buffer_internal, 1, 1, 0,
@@ -2392,10 +2379,9 @@ DEFUN ("x-get-cut-buffer-internal", Fx_get_cut_buffer_internal,
     return Qnil;
 
   if (format != 8 || type != XA_STRING)
-    Fsignal (Qerror,
-            Fcons (build_string ("cut buffer doesn't contain 8-bit data"),
-                   Fcons (x_atom_to_symbol (display, type),
-                          Fcons (make_number (format), Qnil))));
+    signal_error ("Cut buffer doesn't contain 8-bit data",
+                 list2 (x_atom_to_symbol (display, type),
+                        make_number (format)));
 
   ret = (bytes ? make_unibyte_string ((char *) data, bytes) : Qnil);
   /* Use xfree, not XFree, because x_get_window_property
@@ -2699,8 +2685,48 @@ If the value is 0 or the atom is not known, return the empty string.  */)
   return ret;
 }
 
-/* Convert an XClientMessageEvent to a Lisp event of type DRAG_N_DROP_EVENT.
-   TODO: Check if this client event really is a DND event?  */
+DEFUN ("x-register-dnd-atom", Fx_register_dnd_atom,
+       Sx_register_dnd_atom, 1, 2, 0,
+       doc: /* Request that dnd events are made for ClientMessages with ATOM.
+ATOM can be a symbol or a string.  The ATOM is interned on the display that
+FRAME is on.  If FRAME is nil, the selected frame is used.  */)
+    (atom, frame)
+    Lisp_Object atom, frame;
+{
+  Atom x_atom;
+  struct frame *f = check_x_frame (frame);
+  size_t i;
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+
+  if (SYMBOLP (atom))
+    x_atom = symbol_to_x_atom (dpyinfo, FRAME_X_DISPLAY (f), atom);
+  else if (STRINGP (atom))
+    {
+      BLOCK_INPUT;
+      x_atom = XInternAtom (FRAME_X_DISPLAY (f), (char *) SDATA (atom), False);
+      UNBLOCK_INPUT;
+    }
+  else
+    error ("ATOM must be a symbol or a string");
+
+  for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i)
+    if (dpyinfo->x_dnd_atoms[i] == x_atom)
+      return Qnil;
+
+  if (dpyinfo->x_dnd_atoms_length == dpyinfo->x_dnd_atoms_size)
+    {
+      dpyinfo->x_dnd_atoms_size *= 2;
+      dpyinfo->x_dnd_atoms = xrealloc (dpyinfo->x_dnd_atoms,
+                                       sizeof (*dpyinfo->x_dnd_atoms)
+                                       * dpyinfo->x_dnd_atoms_size);
+    }
+
+  dpyinfo->x_dnd_atoms[dpyinfo->x_dnd_atoms_length++] = x_atom;
+  return Qnil;
+}
+
+/* Convert an XClientMessageEvent to a Lisp event of type DRAG_N_DROP_EVENT.  */
 
 int
 x_handle_dnd_message (f, event, dpyinfo, bufp)
@@ -2716,6 +2742,12 @@ x_handle_dnd_message (f, event, dpyinfo, bufp)
   int x, y;
   unsigned char *data = (unsigned char *) event->data.b;
   int idata[5];
+  size_t i;
+
+  for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i)
+    if (dpyinfo->x_dnd_atoms[i] == event->message_type) break;
+
+  if (i == dpyinfo->x_dnd_atoms_length) return 0;
 
   XSETFRAME (frame, f);
 
@@ -2889,6 +2921,7 @@ syms_of_xselect ()
 
   defsubr (&Sx_get_atom_name);
   defsubr (&Sx_send_client_message);
+  defsubr (&Sx_register_dnd_atom);
 
   reading_selection_reply = Fcons (Qnil, Qnil);
   staticpro (&reading_selection_reply);
@@ -2942,8 +2975,17 @@ it merely informs you that they have happened.  */);
 
   DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system,
               doc: /* Coding system for communicating with other X clients.
-When sending or receiving text via cut_buffer, selection, and clipboard,
-the text is encoded or decoded by this coding system.
+
+When sending text via selection and clipboard, if the requested
+data-type is not "UTF8_STRING", the text is encoded by this coding
+system.
+
+When receiving text, if the data-type of the received text is not
+"UTF8_STRING", it is decoded by this coding system.
+
+See also the documentation of the variable `x-select-request-type' how
+to control which data-type to request for receiving text.
+
 The default value is `compound-text-with-extensions'.  */);
   Vselection_coding_system = intern ("compound-text-with-extensions");