/* 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.
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
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. */
Lisp_Object selection_name, selection_value;
{
struct frame *sf = SELECTED_FRAME ();
- Window selecting_window = FRAME_X_WINDOW (sf);
- Display *display = FRAME_X_DISPLAY (sf);
+ Window selecting_window;
+ Display *display;
Time time = last_event_timestamp;
Atom selection_atom;
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (sf);
+ struct x_display_info *dpyinfo;
+
+ if (! FRAME_X_P (sf))
+ return;
+ selecting_window = FRAME_X_WINDOW (sf);
+ display = FRAME_X_DISPLAY (sf);
+ dpyinfo = FRAME_X_DISPLAY_INFO (sf);
+
CHECK_SYMBOL (selection_name);
selection_atom = symbol_to_x_atom (dpyinfo, display, selection_name);
&& 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. */
BLOCK_INPUT;
x_uncatch_errors ();
UNBLOCK_INPUT;
+ return Qnil;
}
\f
FOR_EACH_FRAME (list, frame)
{
- if (FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
+ if (FRAME_X_P (XFRAME (frame))
+ && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
return frame;
}
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);
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);
if (!nofree)
xfree (data);
}
+
+ DONE2:
unbind_to (count, Qnil);
DONE:
TRACE0 ("x_handle_selection_clear");
+#ifdef MULTI_KBOARD
/* If the new selection owner is also Emacs,
don't clear the new selection. */
BLOCK_INPUT;
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)
+ if (t_dpyinfo->terminal->kboard == dpyinfo->terminal->kboard)
{
Window owner_window
= XGetSelectionOwner (t_dpyinfo->display, selection);
}
}
UNBLOCK_INPUT;
-
+#endif
+
selection_symbol = x_atom_to_symbol (display, selection);
local_selection_data = assq_no_quit (selection_symbol, Vselection_alist);
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];
Lisp_Object selection_symbol, target_type, time_stamp;
{
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);
+ Window requestor_window;
+ Display *display;
+ struct x_display_info *dpyinfo;
Time requestor_time = last_event_timestamp;
- Atom target_property = dpyinfo->Xatom_EMACS_TMP;
- Atom selection_atom = symbol_to_x_atom (dpyinfo, display, selection_symbol);
+ Atom target_property;
+ Atom selection_atom;
Atom type_atom;
int secs, usecs;
int count = SPECPDL_INDEX ();
Lisp_Object frame;
+ if (! FRAME_X_P (sf))
+ return Qnil;
+
+ requestor_window = FRAME_X_WINDOW (sf);
+ display = FRAME_X_DISPLAY (sf);
+ dpyinfo = FRAME_X_DISPLAY_INFO (sf);
+ target_property = dpyinfo->Xatom_EMACS_TMP;
+ selection_atom = symbol_to_x_atom (dpyinfo, display, selection_symbol);
+
if (CONSP (target_type))
type_atom = symbol_to_x_atom (dpyinfo, display, XCAR (target_type));
else
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)
{
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;
(*(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]))
{
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,
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
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. */
}
}
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);
}
struct frame *sf = SELECTED_FRAME ();
check_x ();
+ if (! FRAME_X_P (sf))
+ return Qnil;
+
display = FRAME_X_DISPLAY (sf);
dpyinfo = FRAME_X_DISPLAY_INFO (sf);
CHECK_SYMBOL (selection);
#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,
struct frame *sf = SELECTED_FRAME ();
check_x ();
+
+ if (! FRAME_X_P (sf))
+ return Qnil;
+
display = FRAME_X_DISPLAY (sf);
dpyinfo = FRAME_X_DISPLAY_INFO (sf);
window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
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
struct frame *sf = SELECTED_FRAME ();
check_x ();
+
+ if (! FRAME_X_P (sf))
+ return Qnil;
+
display = FRAME_X_DISPLAY (sf);
window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
Atom props[8];
Display *display;
struct frame *sf = SELECTED_FRAME ();
-
+
check_x ();
+
+ if (! FRAME_X_P (sf))
+ return Qnil;
+
display = FRAME_X_DISPLAY (sf);
window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
CHECK_NUMBER (n);
ret = make_string (name, strlen (name));
if (atom && name) XFree (name);
- if (NILP (ret)) ret = make_string ("", 0);
+ if (NILP (ret)) ret = empty_unibyte_string;
UNBLOCK_INPUT;
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)
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);
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);
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");