/* X Selection processing for Emacs.
- Copyright (C) 1993, 1994, 1995, 1996, 1997, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1993-1997, 2000-2011 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#define TRACE0(fmt) (void) 0
#define TRACE1(fmt, a0) (void) 0
#define TRACE2(fmt, a0, a1) (void) 0
-#define TRACE3(fmt, a0, a1) (void) 0
#endif
-Lisp_Object QSECONDARY, QSTRING, QINTEGER, QCLIPBOARD, QTIMESTAMP,
+static Lisp_Object QSECONDARY, QSTRING, QINTEGER, QCLIPBOARD, QTIMESTAMP,
QTEXT, QDELETE, QMULTIPLE, QINCR, QEMACS_TMP, QTARGETS, QATOM, QNULL,
QATOM_PAIR;
-Lisp_Object QCOMPOUND_TEXT; /* This is a type of selection. */
-Lisp_Object QUTF8_STRING; /* This is a type of selection. */
+static Lisp_Object QCOMPOUND_TEXT; /* This is a type of selection. */
+static Lisp_Object QUTF8_STRING; /* This is a type of selection. */
-Lisp_Object Qcompound_text_with_extensions;
+static Lisp_Object Qcompound_text_with_extensions;
static Lisp_Object Qforeign_selection;
/* Defined in keyboard.c. */
extern unsigned long last_event_timestamp;
+/* This is an association list whose elements are of the form
+ ( SELECTION-NAME SELECTION-VALUE SELECTION-TIMESTAMP FRAME)
+ SELECTION-NAME is a lisp symbol, whose name is the name of an X Atom.
+ SELECTION-VALUE is the value that emacs owns for that selection.
+ It may be any kind of Lisp object.
+ SELECTION-TIMESTAMP is the time at which emacs began owning this selection,
+ as a cons of two 16-bit numbers (making a 32 bit time.)
+ FRAME is the frame for which we made the selection.
+ If there is an entry in this alist, then it can be assumed that Emacs owns
+ that selection.
+ The only (eq) parts of this list that are visible from Lisp are the
+ selection-values. */
+static Lisp_Object Vselection_alist;
+
\f
/* Define a queue to save up SELECTION_REQUEST_EVENT events for later
{
if (!memcmp (&queue_tmp->event, event, sizeof (*event)))
{
- TRACE1 ("DECLINE DUP SELECTION EVENT %08lx", (unsigned long)queue_tmp);
+ TRACE1 ("DECLINE DUP SELECTION EVENT %p", queue_tmp);
x_decline_selection_request (event);
return;
}
if (queue_tmp != NULL)
{
- TRACE1 ("QUEUE SELECTION EVENT %08lx", (unsigned long)queue_tmp);
+ TRACE1 ("QUEUE SELECTION EVENT %p", queue_tmp);
queue_tmp->event = *event;
queue_tmp->next = selection_queue;
selection_queue = queue_tmp;
while (selection_queue != NULL)
{
struct selection_event_queue *queue_tmp = selection_queue;
- TRACE1 ("RESTORE SELECTION EVENT %08lx", (unsigned long)queue_tmp);
+ TRACE1 ("RESTORE SELECTION EVENT %p", queue_tmp);
kbd_buffer_unget_event (&queue_tmp->event);
selection_queue = queue_tmp->next;
xfree ((char *)queue_tmp);
if (EQ (sym, QNULL)) return dpyinfo->Xatom_NULL;
if (!SYMBOLP (sym)) abort ();
- TRACE1 (" XInternAtom %s", (char *) SDATA (SYMBOL_NAME (sym)));
+ TRACE1 (" XInternAtom %s", SSDATA (SYMBOL_NAME (sym)));
BLOCK_INPUT;
- val = XInternAtom (display, (char *) SDATA (SYMBOL_NAME (sym)), False);
+ val = XInternAtom (display, SSDATA (SYMBOL_NAME (sym)), False);
UNBLOCK_INPUT;
return val;
}
struct frame *sf = SELECTED_FRAME ();
Window selecting_window;
Display *display;
- Time time = last_event_timestamp;
+ Time timestamp = last_event_timestamp;
Atom selection_atom;
struct x_display_info *dpyinfo;
BLOCK_INPUT;
x_catch_errors (display);
- XSetSelectionOwner (display, selection_atom, selecting_window, time);
+ XSetSelectionOwner (display, selection_atom, selecting_window, timestamp);
x_check_errors (display, "Can't set selection: %s");
x_uncatch_errors ();
UNBLOCK_INPUT;
Lisp_Object selection_data;
Lisp_Object prev_value;
- selection_time = long_to_cons ((unsigned long) time);
+ selection_time = long_to_cons ((unsigned long) timestamp);
selection_data = list4 (selection_name, selection_value,
selection_time, selected_frame);
prev_value = assq_no_quit (selection_name, Vselection_alist);
x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type, int local_request)
{
Lisp_Object local_value;
- Lisp_Object handler_fn, value, type, check;
+ Lisp_Object handler_fn, value, check;
int count;
local_value = assq_no_quit (selection_symbol, Vselection_alist);
check = value;
if (CONSP (value)
&& SYMBOLP (XCAR (value)))
- type = XCAR (value),
check = XCDR (value);
if (STRINGP (check)
static void
x_decline_selection_request (struct input_event *event)
{
- XSelectionEvent reply;
+ XEvent reply_base;
+ XSelectionEvent *reply = &(reply_base.xselection);
- reply.type = SelectionNotify;
- reply.display = SELECTION_EVENT_DISPLAY (event);
- reply.requestor = SELECTION_EVENT_REQUESTOR (event);
- reply.selection = SELECTION_EVENT_SELECTION (event);
- reply.time = SELECTION_EVENT_TIME (event);
- reply.target = SELECTION_EVENT_TARGET (event);
- reply.property = None;
+ reply->type = SelectionNotify;
+ reply->display = SELECTION_EVENT_DISPLAY (event);
+ reply->requestor = SELECTION_EVENT_REQUESTOR (event);
+ reply->selection = SELECTION_EVENT_SELECTION (event);
+ reply->time = SELECTION_EVENT_TIME (event);
+ reply->target = SELECTION_EVENT_TARGET (event);
+ reply->property = None;
/* The reason for the error may be that the receiver has
died in the meantime. Handle that case. */
BLOCK_INPUT;
- x_catch_errors (reply.display);
- XSendEvent (reply.display, reply.requestor, False, 0L, (XEvent *) &reply);
- XFlush (reply.display);
+ x_catch_errors (reply->display);
+ XSendEvent (reply->display, reply->requestor, False, 0L, &reply_base);
+ XFlush (reply->display);
x_uncatch_errors ();
UNBLOCK_INPUT;
}
static void
x_reply_selection_request (struct input_event *event, int format, unsigned char *data, int size, Atom type)
{
- XSelectionEvent reply;
+ XEvent reply_base;
+ XSelectionEvent *reply = &(reply_base.xselection);
Display *display = SELECTION_EVENT_DISPLAY (event);
Window window = SELECTION_EVENT_REQUESTOR (event);
int bytes_remaining;
if (max_bytes > MAX_SELECTION_QUANTUM)
max_bytes = MAX_SELECTION_QUANTUM;
- reply.type = SelectionNotify;
- reply.display = display;
- reply.requestor = window;
- reply.selection = SELECTION_EVENT_SELECTION (event);
- reply.time = SELECTION_EVENT_TIME (event);
- reply.target = SELECTION_EVENT_TARGET (event);
- reply.property = SELECTION_EVENT_PROPERTY (event);
- if (reply.property == None)
- reply.property = reply.target;
+ reply->type = SelectionNotify;
+ reply->display = display;
+ reply->requestor = window;
+ reply->selection = SELECTION_EVENT_SELECTION (event);
+ reply->time = SELECTION_EVENT_TIME (event);
+ reply->target = SELECTION_EVENT_TARGET (event);
+ reply->property = SELECTION_EVENT_PROPERTY (event);
+ if (reply->property == None)
+ reply->property = reply->target;
BLOCK_INPUT;
/* The protected block contains wait_for_property_change, which can
#ifdef TRACE_SELECTION
{
- char *sel = XGetAtomName (display, reply.selection);
- char *tgt = XGetAtomName (display, reply.target);
+ char *sel = XGetAtomName (display, reply->selection);
+ char *tgt = XGetAtomName (display, reply->target);
TRACE3 ("%s, target %s (%d)", sel, tgt, ++x_reply_selection_request_cnt);
if (sel) XFree (sel);
if (tgt) XFree (tgt);
{
/* Send all the data at once, with minimal handshaking. */
TRACE1 ("Sending all %d bytes", bytes_remaining);
- XChangeProperty (display, window, reply.property, type, format,
+ XChangeProperty (display, window, reply->property, type, format,
PropModeReplace, data, size);
/* At this point, the selection was successfully stored; ack it. */
- XSendEvent (display, window, False, 0L, (XEvent *) &reply);
+ XSendEvent (display, window, False, 0L, &reply_base);
}
else
{
error ("Attempt to transfer an INCR to ourself!");
TRACE2 ("Start sending %d bytes incrementally (%s)",
- bytes_remaining, XGetAtomName (display, reply.property));
- wait_object = expect_property_change (display, window, reply.property,
+ bytes_remaining, XGetAtomName (display, reply->property));
+ wait_object = expect_property_change (display, window, reply->property,
PropertyDelete);
TRACE1 ("Set %s to number of bytes to send",
- XGetAtomName (display, reply.property));
+ XGetAtomName (display, reply->property));
{
/* XChangeProperty expects an array of long even if long is more than
32 bits. */
long value[1];
value[0] = bytes_remaining;
- XChangeProperty (display, window, reply.property, dpyinfo->Xatom_INCR,
+ XChangeProperty (display, window, reply->property, dpyinfo->Xatom_INCR,
32, PropModeReplace,
(unsigned char *) value, 1);
}
/* Tell 'em the INCR data is there... */
TRACE0 ("Send SelectionNotify event");
- XSendEvent (display, window, False, 0L, (XEvent *) &reply);
+ XSendEvent (display, window, False, 0L, &reply_base);
XFlush (display);
had_errors = x_had_errors_p (display);
if (! had_errors)
{
TRACE1 ("Waiting for ACK (deletion of %s)",
- XGetAtomName (display, reply.property));
+ XGetAtomName (display, reply->property));
wait_for_property_change (wait_object);
}
else
BLOCK_INPUT;
wait_object
- = expect_property_change (display, window, reply.property,
+ = expect_property_change (display, window, reply->property,
PropertyDelete);
TRACE1 ("Sending increment of %d elements", i);
TRACE1 ("Set %s to increment data",
- XGetAtomName (display, reply.property));
+ XGetAtomName (display, reply->property));
/* Append the next chunk of data to the property. */
- XChangeProperty (display, window, reply.property, type, format,
+ XChangeProperty (display, window, reply->property, type, format,
PropModeAppend, data, i);
bytes_remaining -= i * format_bytes;
if (format == 32)
/* Now wait for the requester to ack this chunk by deleting the
property. This can run random lisp code or signal. */
TRACE1 ("Waiting for increment ACK (deletion of %s)",
- XGetAtomName (display, reply.property));
+ XGetAtomName (display, reply->property));
wait_for_property_change (wait_object);
}
XSelectInput (display, window, 0L);
TRACE1 ("Set %s to a 0-length chunk to indicate EOF",
- XGetAtomName (display, reply.property));
- XChangeProperty (display, window, reply.property, type, format,
+ XGetAtomName (display, reply->property));
+ XChangeProperty (display, window, reply->property, type, format,
PropModeReplace, data, 0);
TRACE0 ("Done sending incrementally");
}
void
x_handle_property_notify (XPropertyEvent *event)
{
- struct prop_location *prev = 0, *rest = property_change_wait_list;
+ struct prop_location *rest;
- while (rest)
+ for (rest = property_change_wait_list; rest; rest = rest->next)
{
if (!rest->arrived
&& rest->property == event->atom
return;
}
-
- prev = rest;
- rest = rest->next;
}
}
while (bytes_remaining)
{
#ifdef TRACE_SELECTION
- int last = bytes_remaining;
+ unsigned long last = bytes_remaining;
#endif
result
= XGetWindowProperty (display, window, property,
actual_type_ret, actual_format_ret,
actual_size_ret, &bytes_remaining, &tmp_data);
- TRACE2 ("Read %ld bytes from property %s",
+ TRACE2 ("Read %lu bytes from property %s",
last - bytes_remaining,
XGetAtomName (display, property));
The bytes and offsets passed to XGetWindowProperty refers to the
property and those are indeed in 32 bit quantities if format is 32. */
- if (*actual_format_ret == 32 && *actual_format_ret < BITS_PER_LONG)
+ if (32 < BITS_PER_LONG && *actual_format_ret == 32)
{
unsigned long i;
int *idata = (int *) ((*data_ret) + offset);
Sx_disown_selection_internal, 1, 2, 0,
doc: /* If we own the selection SELECTION, disown it.
Disowning it means there is no such selection. */)
- (Lisp_Object selection, Lisp_Object time)
+ (Lisp_Object selection, Lisp_Object time_object)
{
Time timestamp;
Atom selection_atom;
display = FRAME_X_DISPLAY (sf);
dpyinfo = FRAME_X_DISPLAY_INFO (sf);
CHECK_SYMBOL (selection);
- if (NILP (time))
+ if (NILP (time_object))
timestamp = last_event_timestamp;
else
- timestamp = cons_to_long (time);
+ timestamp = cons_to_long (time_object);
if (NILP (assq_no_quit (selection, Vselection_alist)))
return Qnil; /* Don't disown the selection when we're not the owner. */
return Qt;
}
-/* Get rid of all the selections in buffer BUFFER.
- This is used when we kill a buffer. */
-
-void
-x_disown_buffer_selections (Lisp_Object buffer)
-{
- Lisp_Object tail;
- struct buffer *buf = XBUFFER (buffer);
-
- for (tail = Vselection_alist; CONSP (tail); tail = XCDR (tail))
- {
- Lisp_Object elt, value;
- elt = XCAR (tail);
- value = XCDR (elt);
- if (CONSP (value) && MARKERP (XCAR (value))
- && XMARKER (XCAR (value))->buffer == buf)
- Fx_disown_selection_internal (XCAR (elt), Qnil);
- }
-}
-
DEFUN ("x-selection-owner-p", Fx_selection_owner_p, Sx_selection_owner_p,
0, 1, 0,
doc: /* Whether the current Emacs process owns the given X Selection.
***********************************************************************/
/* Check that lisp values are of correct type for x_fill_property_data.
That is, number, string or a cons with two numbers (low and high 16
- bit parts of a 32 bit number). */
+ bit parts of a 32 bit number). Return the number of items in DATA,
+ or -1 if there is an error. */
int
x_check_property_data (Lisp_Object data)
Lisp_Object iter;
int size = 0;
- for (iter = data; CONSP (iter) && size != -1; iter = XCDR (iter), ++size)
+ for (iter = data; CONSP (iter); iter = XCDR (iter))
{
Lisp_Object o = XCAR (iter);
if (! NUMBERP (o) && ! STRINGP (o) && ! CONSP (o))
- size = -1;
+ return -1;
else if (CONSP (o) &&
(! NUMBERP (XCAR (o)) || ! NUMBERP (XCDR (o))))
- size = -1;
+ return -1;
+ size++;
}
return size;
else if (STRINGP (o))
{
BLOCK_INPUT;
- val = (long) XInternAtom (dpy, (char *) SDATA (o), False);
+ val = (long) XInternAtom (dpy, SSDATA (o), False);
UNBLOCK_INPUT;
}
else
else if (STRINGP (atom))
{
BLOCK_INPUT;
- x_atom = XInternAtom (FRAME_X_DISPLAY (f), (char *) SDATA (atom), False);
+ x_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (atom), False);
UNBLOCK_INPUT;
}
else
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 (event->format == 32 && event->format < BITS_PER_LONG)
+ if (32 < BITS_PER_LONG && event->format == 32)
{
- int i;
for (i = 0; i < 5; ++i) /* There are only 5 longs in a ClientMessage. */
idata[i] = (int) event->data.l[i];
data = (unsigned char *) idata;
CHECK_STRING (message_type);
x_send_client_event(display, dest, from,
XInternAtom (dpyinfo->display,
- SDATA (message_type),
+ SSDATA (message_type),
False),
format, values);
}
else if (STRINGP (dest))
{
- if (strcmp (SDATA (dest), "PointerWindow") == 0)
+ if (strcmp (SSDATA (dest), "PointerWindow") == 0)
wdest = PointerWindow;
- else if (strcmp (SDATA (dest), "InputFocus") == 0)
+ else if (strcmp (SSDATA (dest), "InputFocus") == 0)
wdest = InputFocus;
else
error ("DEST as a string must be one of PointerWindow or InputFocus");