/* X Selection processing for Emacs.
- Copyright (C) 1993, 1994, 1995, 1996, 1997, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 1993-1997, 2000-2011 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
-#ifdef HAVE_UNISTD_H
+
#include <unistd.h>
-#endif
#include "lisp.h"
#include "xterm.h" /* for all of the X includes */
#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 Vx_lost_selection_functions;
-static Lisp_Object Vx_sent_selection_functions;
static Lisp_Object Qforeign_selection;
/* If this is a smaller number than the max-request-size of the display,
#define SELECTION_QUANTUM(dpy) ((XMaxRequestSize(dpy) << 2) - 100)
-/* The timestamp of the last input event Emacs received from the X server. */
-/* 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-values. */
static Lisp_Object Vselection_alist;
-/* This is an alist whose CARs are selection-types (whose names are the same
- as the names of X Atoms) and whose CDRs are the names of Lisp functions to
- call to convert the given Emacs selection value to a string representing
- the given selection type. This is for Lisp-level extension of the emacs
- selection handling. */
-static Lisp_Object Vselection_converter_alist;
-
-/* If the selection owner takes too long to reply to a selection request,
- we give up on it. This is in milliseconds (0 = no timeout.) */
-static EMACS_INT x_selection_timeout;
-
\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);
int size;
int i;
pairs = XCDR (target_type);
- size = XVECTOR (pairs)->size;
+ size = ASIZE (pairs);
/* If the target is MULTIPLE, then target_type looks like
(MULTIPLE . [[SELECTION1 TARGET1] [SELECTION2 TARGET2] ... ])
We modify the second element of each pair in the vector and
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;
}
}
return Fcons (XCAR (obj), copy_multiple_data (XCDR (obj)));
CHECK_VECTOR (obj);
- vec = Fmake_vector (size = XVECTOR (obj)->size, Qnil);
+ vec = Fmake_vector (size = ASIZE (obj), Qnil);
for (i = 0; i < size; i++)
{
Lisp_Object vec2 = XVECTOR (obj)->contents [i];
CHECK_VECTOR (vec2);
- if (XVECTOR (vec2)->size != 2)
+ if (ASIZE (vec2) != 2)
/* ??? Confusing error message */
signal_error ("Vectors must be of length 2", vec2);
XVECTOR (vec)->contents [i] = Fmake_vector (2, Qnil);
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);
/* This vector is an ATOM set */
{
if (NILP (type)) type = QATOM;
- *size_ret = XVECTOR (obj)->size;
+ *size_ret = ASIZE (obj);
*format_ret = 32;
*data_ret = (unsigned char *) xmalloc ((*size_ret) * sizeof (Atom));
for (i = 0; i < *size_ret; i++)
/* This vector is an ATOM_PAIR set */
{
if (NILP (type)) type = QATOM_PAIR;
- *size_ret = XVECTOR (obj)->size;
+ *size_ret = ASIZE (obj);
*format_ret = 32;
*data_ret = (unsigned char *)
xmalloc ((*size_ret) * sizeof (Atom) * 2);
if (VECTORP (XVECTOR (obj)->contents [i]))
{
Lisp_Object pair = XVECTOR (obj)->contents [i];
- if (XVECTOR (pair)->size != 2)
+ if (ASIZE (pair) != 2)
signal_error (
"Elements of the vector must be vectors of exactly two elements",
pair);
/* This vector is an INTEGER set, or something like it */
{
int data_size = 2;
- *size_ret = XVECTOR (obj)->size;
+ *size_ret = ASIZE (obj);
if (NILP (type)) type = QINTEGER;
*format_ret = 16;
for (i = 0; i < *size_ret; i++)
if (VECTORP (obj))
{
int i;
- int size = XVECTOR (obj)->size;
+ int size = ASIZE (obj);
Lisp_Object copy;
if (size == 1)
return clean_local_selection_data (XVECTOR (obj)->contents [0]);
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");
Vselection_alist = Qnil;
staticpro (&Vselection_alist);
- DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_alist,
+ 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');
and there is no meaningful selection value. */);
Vselection_converter_alist = Qnil;
- DEFVAR_LISP ("x-lost-selection-functions", &Vx_lost_selection_functions,
+ DEFVAR_LISP ("x-lost-selection-functions", Vx_lost_selection_functions,
doc: /* A list of functions to be called when Emacs loses an X selection.
\(This happens when some other X client makes its own selection
or when a Lisp program explicitly clears the selection.)
\(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'). */);
Vx_lost_selection_functions = Qnil;
- DEFVAR_LISP ("x-sent-selection-functions", &Vx_sent_selection_functions,
+ DEFVAR_LISP ("x-sent-selection-functions", Vx_sent_selection_functions,
doc: /* A list of functions to be called when Emacs answers a selection request.
The functions are called with four arguments:
- the selection name (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');
it merely informs you that they have happened. */);
Vx_sent_selection_functions = Qnil;
- DEFVAR_INT ("x-selection-timeout", &x_selection_timeout,
+ DEFVAR_INT ("x-selection-timeout", x_selection_timeout,
doc: /* Number of milliseconds to wait for a selection reply.
If the selection owner doesn't reply in this time, we give up.
A value of 0 means wait as long as necessary. This is initialized from the
Qforeign_selection = intern_c_string ("foreign-selection");
staticpro (&Qforeign_selection);
}
-
-/* arch-tag: 7c293b0f-9918-4f69-8ac7-03e142307236
- (do not change this comment) */