/* X Selection processing for Emacs.
- Copyright (C) 1993-1997, 2000-2012 Free Software Foundation, Inc.
+ Copyright (C) 1993-1997, 2000-2013 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <config.h>
#include <limits.h>
#include <stdio.h> /* termhooks.h needs this */
-#include <setjmp.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
struct prop_location;
struct selection_data;
-static Lisp_Object x_atom_to_symbol (Display *dpy, Atom atom);
-static Atom symbol_to_x_atom (struct x_display_info *, Lisp_Object);
-static void x_own_selection (Lisp_Object, Lisp_Object, Lisp_Object);
-static Lisp_Object x_get_local_selection (Lisp_Object, Lisp_Object, int,
- struct x_display_info *);
static void x_decline_selection_request (struct input_event *);
-static Lisp_Object x_selection_request_lisp_error (Lisp_Object);
-static Lisp_Object queue_selection_requests_unwind (Lisp_Object);
-static Lisp_Object x_catch_errors_unwind (Lisp_Object);
-static void x_reply_selection_request (struct input_event *, struct x_display_info *);
static int x_convert_selection (struct input_event *, Lisp_Object, Lisp_Object,
Atom, int, struct x_display_info *);
static int waiting_for_other_props_on_window (Display *, Window);
static struct prop_location *expect_property_change (Display *, Window,
Atom, int);
static void unexpect_property_change (struct prop_location *);
-static Lisp_Object wait_for_property_change_unwind (Lisp_Object);
static void wait_for_property_change (struct prop_location *);
-static Lisp_Object x_get_foreign_selection (Lisp_Object, Lisp_Object,
- Lisp_Object, Lisp_Object);
static Lisp_Object x_get_window_property_as_lisp_data (Display *,
Window, Atom,
Lisp_Object, Atom);
static void lisp_data_to_selection_data (Display *, Lisp_Object,
unsigned char **, Atom *,
ptrdiff_t *, int *, int *);
-static Lisp_Object clean_local_selection_data (Lisp_Object);
/* Printing traces to stderr. */
if (!SYMBOLP (sym)) emacs_abort ();
TRACE1 (" XInternAtom %s", SSDATA (SYMBOL_NAME (sym)));
- BLOCK_INPUT;
+ block_input ();
val = XInternAtom (dpyinfo->display, SSDATA (SYMBOL_NAME (sym)), False);
- UNBLOCK_INPUT;
+ unblock_input ();
return val;
}
if (atom == dpyinfo->Xatom_NULL)
return QNULL;
- BLOCK_INPUT;
+ block_input ();
str = XGetAtomName (dpy, atom);
- UNBLOCK_INPUT;
+ unblock_input ();
TRACE1 ("XGetAtomName --> %s", str);
if (! str) return Qnil;
val = intern (str);
- BLOCK_INPUT;
+ block_input ();
/* This was allocated by Xlib, so use XFree. */
XFree (str);
- UNBLOCK_INPUT;
+ unblock_input ();
return val;
}
\f
Time timestamp = last_event_timestamp;
Atom selection_atom = symbol_to_x_atom (dpyinfo, selection_name);
- BLOCK_INPUT;
+ block_input ();
x_catch_errors (display);
XSetSelectionOwner (display, selection_atom, selecting_window, timestamp);
x_check_errors (display, "Can't set selection: %s");
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
/* Now update the local cache */
{
/* The reason for the error may be that the receiver has
died in the meantime. Handle that case. */
- BLOCK_INPUT;
+ block_input ();
x_catch_errors (reply->display);
XSendEvent (reply->display, reply->requestor, False, 0L, &reply_base);
XFlush (reply->display);
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* This is the selection request currently being processed.
an error, we tell the requestor that we were unable to do what they wanted
before we throw to top-level or go into the debugger or whatever. */
-static Lisp_Object
-x_selection_request_lisp_error (Lisp_Object ignore)
+static void
+x_selection_request_lisp_error (void)
{
struct selection_data *cs, *next;
if (x_selection_current_request != 0
&& selection_request_dpyinfo->display)
x_decline_selection_request (x_selection_current_request);
- return Qnil;
}
-static Lisp_Object
-x_catch_errors_unwind (Lisp_Object dummy)
+static void
+x_catch_errors_unwind (void)
{
- BLOCK_INPUT;
+ block_input ();
x_uncatch_errors ();
- UNBLOCK_INPUT;
- return Qnil;
+ unblock_input ();
}
\f
struct prop_location *next;
};
-static struct prop_location *expect_property_change (Display *display, Window window, Atom property, int state);
-static void wait_for_property_change (struct prop_location *location);
-static void unexpect_property_change (struct prop_location *location);
-static int waiting_for_other_props_on_window (Display *display, Window window);
-
static int prop_location_identifier;
static Lisp_Object property_change_reply;
static struct prop_location *property_change_wait_list;
-static Lisp_Object
-queue_selection_requests_unwind (Lisp_Object tem)
-{
- x_stop_queuing_selection_requests ();
- return Qnil;
-}
-
\f
/* Send the reply to a selection request event EVENT. */
if (reply->property == None)
reply->property = reply->target;
- BLOCK_INPUT;
+ block_input ();
/* The protected block contains wait_for_property_change, which can
run random lisp code (process handlers) or signal. Therefore, we
put the x_uncatch_errors call in an unwind. */
- record_unwind_protect (x_catch_errors_unwind, Qnil);
+ record_unwind_protect_void (x_catch_errors_unwind);
x_catch_errors (display);
/* Loop over converted selections, storing them in the requested
if (cs->wait_object)
{
int format_bytes = cs->format / 8;
- int had_errors = x_had_errors_p (display);
- UNBLOCK_INPUT;
+ bool had_errors_p = x_had_errors_p (display);
+ unblock_input ();
bytes_remaining = cs->size;
bytes_remaining *= format_bytes;
/* Wait for the requestor to ack by deleting the property.
This can run Lisp code (process handlers) or signal. */
- if (! had_errors)
+ if (! had_errors_p)
{
TRACE1 ("Waiting for ACK (deletion of %s)",
XGetAtomName (display, cs->property));
int i = ((bytes_remaining < max_bytes)
? bytes_remaining
: max_bytes) / format_bytes;
- BLOCK_INPUT;
+ block_input ();
cs->wait_object
= expect_property_change (display, window, cs->property,
cs->data += i * ((cs->format == 32) ? sizeof (long)
: format_bytes);
XFlush (display);
- had_errors = x_had_errors_p (display);
- UNBLOCK_INPUT;
+ had_errors_p = x_had_errors_p (display);
+ unblock_input ();
- if (had_errors) break;
+ if (had_errors_p) break;
/* Wait for the requestor to ack this chunk by deleting
the property. This can run Lisp code or signal. */
/* Now write a zero-length chunk to the property to tell the
requestor that we're done. */
- BLOCK_INPUT;
+ block_input ();
if (! waiting_for_other_props_on_window (display, window))
XSelectInput (display, window, 0L);
/* 2004-09-10: XSync and UNBLOCK so that possible protocol errors are
delivered before uncatch errors. */
XSync (display, False);
- UNBLOCK_INPUT;
+ unblock_input ();
/* GTK queues events in addition to the queue in Xlib. So we
UNBLOCK to enter the event loop and get possible errors delivered,
and then BLOCK again because x_uncatch_errors requires it. */
- BLOCK_INPUT;
+ block_input ();
/* This calls x_uncatch_errors. */
unbind_to (count, Qnil);
- UNBLOCK_INPUT;
+ unblock_input ();
}
\f
/* Handle a SelectionRequest event EVENT.
x_selection_current_request = event;
selection_request_dpyinfo = dpyinfo;
- record_unwind_protect (x_selection_request_lisp_error, Qnil);
+ record_unwind_protect_void (x_selection_request_lisp_error);
/* We might be able to handle nested x_handle_selection_requests,
but this is difficult to test, and seems unimportant. */
x_start_queuing_selection_requests ();
- record_unwind_protect (queue_selection_requests_unwind, Qnil);
+ record_unwind_protect_void (x_stop_queuing_selection_requests);
TRACE2 ("x_handle_selection_request: selection=%s, target=%s",
SDATA (SYMBOL_NAME (selection_symbol)),
We do this when about to delete a frame. */
void
-x_clear_frame_selections (FRAME_PTR f)
+x_clear_frame_selections (struct frame *f)
{
Lisp_Object frame;
Lisp_Object rest;
/* Remove the property change expectation element for IDENTIFIER. */
-static Lisp_Object
-wait_for_property_change_unwind (Lisp_Object loc)
+static void
+wait_for_property_change_unwind (void *loc)
{
- struct prop_location *location = XSAVE_VALUE (loc)->pointer;
+ struct prop_location *location = loc;
unexpect_property_change (location);
if (location == property_change_reply_object)
property_change_reply_object = 0;
- return Qnil;
}
/* Actually wait for a property change.
emacs_abort ();
/* Make sure to do unexpect_property_change if we quit or err. */
- record_unwind_protect (wait_for_property_change_unwind,
- make_save_value (location, 0));
+ record_unwind_protect_ptr (wait_for_property_change_unwind, location);
XSETCAR (property_change_reply, Qnil);
property_change_reply_object = location;
if (! NILP (time_stamp))
CONS_TO_INTEGER (time_stamp, Time, requestor_time);
- BLOCK_INPUT;
+ block_input ();
TRACE2 ("Get selection %s, type %s",
XGetAtomName (display, type_atom),
XGetAtomName (display, target_property));
SelectionNotify. */
#if 0
x_start_queuing_selection_requests ();
- record_unwind_protect (queue_selection_requests_unwind, Qnil);
+ record_unwind_protect_void (x_stop_queuing_selection_requests);
#endif
- UNBLOCK_INPUT;
+ unblock_input ();
/* This allows quits. Also, don't wait forever. */
timeout = max (0, x_selection_timeout);
? min (PTRDIFF_MAX, SIZE_MAX) - 1
: LONG_MAX * x_long_size);
- BLOCK_INPUT;
+ block_input ();
/* First probe the thing to find out how big it is. */
result = XGetWindowProperty (display, window, property,
data = data1;
}
- if (32 < BITS_PER_LONG && *actual_format_ret == 32)
+ if (BITS_PER_LONG > 32 && *actual_format_ret == 32)
{
unsigned long i;
int *idata = (int *) (data + offset);
data[offset] = '\0';
done:
- UNBLOCK_INPUT;
+ unblock_input ();
*data_ret = data;
*bytes_ret = offset;
return;
size_overflow:
free (data);
- UNBLOCK_INPUT;
+ unblock_input ();
memory_full (SIZE_MAX);
memory_exhausted:
free (data);
- UNBLOCK_INPUT;
+ unblock_input ();
memory_full (total_size + 1);
}
\f
that property, then reading the property, then deleting it to ack.
We are done when the sender places a property of length 0.
*/
- BLOCK_INPUT;
+ block_input ();
XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask);
TRACE1 (" Delete property %s",
SDATA (SYMBOL_NAME (x_atom_to_symbol (display, property))));
wait_object = expect_property_change (display, window, property,
PropertyNewValue);
XFlush (display);
- UNBLOCK_INPUT;
+ unblock_input ();
while (1)
{
break;
}
- BLOCK_INPUT;
+ block_input ();
TRACE1 (" ACK by deleting property %s",
XGetAtomName (display, property));
XDeleteProperty (display, window, property);
wait_object = expect_property_change (display, window, property,
PropertyNewValue);
XFlush (display);
- UNBLOCK_INPUT;
+ unblock_input ();
if (*size_bytes_ret - offset < tmp_size_bytes)
*data_ret = xpalloc (*data_ret, size_bytes_ret,
if (! data)
{
int there_is_a_selection_owner;
- BLOCK_INPUT;
+ block_input ();
there_is_a_selection_owner
= XGetSelectionOwner (display, selection_atom);
- UNBLOCK_INPUT;
+ unblock_input ();
if (there_is_a_selection_owner)
signal_error ("Selection owner couldn't convert",
actual_type
/* That wasn't really the data, just the beginning. */
unsigned int min_size_bytes = * ((unsigned int *) data);
- BLOCK_INPUT;
+ block_input ();
/* Use xfree, not XFree, because x_get_window_property
calls xmalloc itself. */
xfree (data);
- UNBLOCK_INPUT;
+ unblock_input ();
receive_incremental_selection (display, window, property, target_type,
min_size_bytes, &data, &bytes,
&actual_type, &actual_format,
&actual_size);
}
- BLOCK_INPUT;
+ block_input ();
TRACE1 (" Delete property %s", XGetAtomName (display, property));
XDeleteProperty (display, window, property);
XFlush (display);
- UNBLOCK_INPUT;
+ unblock_input ();
/* It's been read. Now convert it to a lisp object in some semi-rational
manner. */
return x_atom_to_symbol (display, (Atom) idata[0]);
else
{
- Lisp_Object v = Fmake_vector (make_number (size / sizeof (int)),
- make_number (0));
+ Lisp_Object v = make_uninit_vector (size / sizeof (int));
+
for (i = 0; i < size / sizeof (int); i++)
- Faset (v, make_number (i),
- x_atom_to_symbol (display, (Atom) idata[i]));
+ ASET (v, i, x_atom_to_symbol (display, (Atom) idata[i]));
return v;
}
}
else if (format == 16)
{
ptrdiff_t i;
- Lisp_Object v;
- v = Fmake_vector (make_number (size / 2), make_number (0));
+ Lisp_Object v = make_uninit_vector (size / 2);
+
for (i = 0; i < size / 2; i++)
{
short j = ((short *) data) [i];
- Faset (v, make_number (i), make_number (j));
+ ASET (v, i, make_number (j));
}
return v;
}
else
{
ptrdiff_t i;
- Lisp_Object v = Fmake_vector (make_number (size / X_LONG_SIZE),
- make_number (0));
+ Lisp_Object v = make_uninit_vector (size / X_LONG_SIZE);
+
for (i = 0; i < size / X_LONG_SIZE; i++)
{
int j = ((int *) data) [i];
- Faset (v, make_number (i), INTEGER_TO_CONS (j));
+ ASET (v, i, INTEGER_TO_CONS (j));
}
return v;
}
Lisp_Object copy;
if (size == 1)
return clean_local_selection_data (AREF (obj, 0));
- copy = Fmake_vector (make_number (size), Qnil);
+ copy = make_uninit_vector (size);
for (i = 0; i < size; i++)
ASET (copy, i, clean_local_selection_data (AREF (obj, i)));
return copy;
static struct frame *
frame_for_x_selection (Lisp_Object object)
{
- Lisp_Object tail;
+ Lisp_Object tail, frame;
struct frame *f;
if (NILP (object))
if (FRAME_X_P (f) && FRAME_LIVE_P (f))
return f;
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, frame)
{
- f = XFRAME (XCAR (tail));
+ f = XFRAME (frame);
if (FRAME_X_P (f) && FRAME_LIVE_P (f))
return f;
}
else if (TERMINALP (object))
{
struct terminal *t = get_terminal (object, 1);
+
if (t->type == output_x_window)
- {
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
- {
- f = XFRAME (XCAR (tail));
- if (FRAME_LIVE_P (f) && f->terminal == t)
- return f;
- }
- }
+ FOR_EACH_FRAME (tail, frame)
+ {
+ f = XFRAME (frame);
+ if (FRAME_LIVE_P (f) && f->terminal == t)
+ return f;
+ }
}
else if (FRAMEP (object))
{
selection_atom = symbol_to_x_atom (dpyinfo, selection);
- BLOCK_INPUT;
+ block_input ();
if (NILP (time_object))
timestamp = last_event_timestamp;
else
CONS_TO_INTEGER (time_object, Time, timestamp);
XSetSelectionOwner (dpyinfo->display, selection_atom, None, timestamp);
- UNBLOCK_INPUT;
+ unblock_input ();
/* It doesn't seem to be guaranteed that a SelectionClear event will be
generated for a window which owns the selection when that window sets
atom = symbol_to_x_atom (dpyinfo, selection);
if (atom == 0) return Qnil;
- BLOCK_INPUT;
+ block_input ();
owner = XGetSelectionOwner (dpyinfo->display, atom);
- UNBLOCK_INPUT;
+ unblock_input ();
return (owner ? Qt : Qnil);
}
val = cons_to_signed (o, LONG_MIN, LONG_MAX);
else if (STRINGP (o))
{
- BLOCK_INPUT;
+ block_input ();
val = (long) XInternAtom (dpy, SSDATA (o), False);
- UNBLOCK_INPUT;
+ unblock_input ();
}
else
error ("Wrong type, must be string, number or cons");
/* Get the mouse position in frame relative coordinates. */
static void
-mouse_position_for_drop (FRAME_PTR f, int *x, int *y)
+mouse_position_for_drop (struct frame *f, int *x, int *y)
{
Window root, dummy_window;
int dummy;
- BLOCK_INPUT;
+ block_input ();
XQueryPointer (FRAME_X_DISPLAY (f),
DefaultRootWindow (FRAME_X_DISPLAY (f)),
*x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
*y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
- UNBLOCK_INPUT;
+ unblock_input ();
}
DEFUN ("x-get-atom-name", Fx_get_atom_name,
If the value is 0 or the atom is not known, return the empty string. */)
(Lisp_Object value, Lisp_Object frame)
{
- struct frame *f = check_x_frame (frame);
+ struct frame *f = decode_window_system_frame (frame);
char *name = 0;
char empty[] = "";
Lisp_Object ret = Qnil;
Display *dpy = FRAME_X_DISPLAY (f);
Atom atom;
- int had_errors;
+ bool had_errors_p;
CONS_TO_INTEGER (value, Atom, atom);
- BLOCK_INPUT;
+ block_input ();
x_catch_errors (dpy);
name = atom ? XGetAtomName (dpy, atom) : empty;
- had_errors = x_had_errors_p (dpy);
+ had_errors_p = x_had_errors_p (dpy);
x_uncatch_errors ();
- if (!had_errors)
+ if (!had_errors_p)
ret = build_string (name);
if (atom && name) XFree (name);
if (NILP (ret)) ret = empty_unibyte_string;
- UNBLOCK_INPUT;
+ unblock_input ();
return ret;
}
(Lisp_Object atom, Lisp_Object frame)
{
Atom x_atom;
- struct frame *f = check_x_frame (frame);
+ struct frame *f = decode_window_system_frame (frame);
ptrdiff_t i;
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
x_atom = symbol_to_x_atom (dpyinfo, atom);
else if (STRINGP (atom))
{
- BLOCK_INPUT;
+ block_input ();
x_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (atom), False);
- UNBLOCK_INPUT;
+ unblock_input ();
}
else
error ("ATOM must be a symbol or a string");
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 (32 < BITS_PER_LONG && event->format == 32)
+ if (BITS_PER_LONG > 32 && event->format == 32)
{
for (i = 0; i < 5; ++i) /* There are only 5 longs in a ClientMessage. */
idata[i] = event->data.l[i];
return 1;
}
-DEFUN ("x-send-client-message", Fx_send_client_event,
+DEFUN ("x-send-client-message", Fx_send_client_message,
Sx_send_client_message, 6, 6, 0,
doc: /* Send a client message of MESSAGE-TYPE to window DEST on DISPLAY.
struct x_display_info *dpyinfo = check_x_display_info (display);
Window wdest;
XEvent event;
- struct frame *f = check_x_frame (from);
+ struct frame *f = decode_window_system_frame (from);
int to_root;
CHECK_NUMBER (format);
if (FRAMEP (dest) || NILP (dest))
{
- struct frame *fdest = check_x_frame (dest);
+ struct frame *fdest = decode_window_system_frame (dest);
wdest = FRAME_OUTER_WINDOW (fdest);
}
else if (STRINGP (dest))
if (wdest == 0) wdest = dpyinfo->root_window;
to_root = wdest == dpyinfo->root_window;
- BLOCK_INPUT;
+ block_input ();
event.xclient.message_type = message_type;
event.xclient.display = dpyinfo->display;
XFlush (dpyinfo->display);
}
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
}
\f