summaryrefslogtreecommitdiff
path: root/src/xselect.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2015-06-23 16:29:27 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2015-06-23 16:30:58 -0700
commit1552e6737317ea2c85e06600e178114c6b0f9fb2 (patch)
tree3b68536fbd72bcaa840cc99aff6ea427120fa4bd /src/xselect.c
parent8769d0fe79dda776652c3bf342263568bbd7623b (diff)
downloademacs-1552e6737317ea2c85e06600e178114c6b0f9fb2.tar.gz
Fix bug that munged selection info
On some optimizing C compilers, copying a structure did not copy the padding bytes between elements, and the type punning between struct input_data and struct selection_input_data did not work. Change the C code to use a proper union type instead. Problem reported by YAMAMOTO Mitsuharu (Bug#20756). * src/keyboard.c (kbd_buffer, kbd_fetch_ptr, kbd_store_ptr) (readable_events, discard_mouse_events, kbd_buffer_events_waiting) (kbd_buffer_get_event, process_special_events, stuff_buffered_input) (mark_kboards): Use union buffered_input_event, not struct input_event. (clear_event, deliver_input_available_signal, process_special_events): Remove unnecessary forward decls. (kbd_buffer_store_buffered_event): New function, mostly just the old kbd_buffer_store_event_hold, except its argument is of type union buffered_input_event, not struct input_event. (kbd_buffer_unget_event): Define only if HAVE_X11, since it's not needed otherwise. Argument is now of type struct selection_input_event *, not struct input_event *. All callers changed. (clear_event): Arg is now of type union buffered_input_event *, not struct input_event *. All callers changed. * src/keyboard.h [HAVE_X11]: Include "xterm.h". (union buffered_input_event): New type. (kbd_buffer_store_event_hold): Now an inline function, defined here. * src/termhooks.h (EVENT_KIND_WIDTH): New constant. (struct input_event): Use it. * src/xselect.c (struct selection_event_queue): Make elements be of type struct selection_input_event, not struct input_event. (selection_input_event_equal): New static function. (x_queue_event): Use it. (x_queue_event, x_decline_selection_request) (x_selection_current_request, x_reply_selection_request) (x_handle_selection_request, x_handle_selection_clear) (x_handle_selection_event): Use struct selection_input_event, not struct input_event. All callers changed. (x_convert_selection): Omit unused first arg. All callers changed. (Fx_disown_selection_internal): Omit unnecessary union. * src/xterm.c (handle_one_xevent): Use new union buffered_input_event rather than rolling our own equivalent. Prefer sie.kind when setting up that kind of structure. Call kbd_buffer_store_buffered_event, not kbd_buffer_store_event_hold. * src/xterm.h (struct selection_input_event: Use EVENT_KIND_WIDTH. (SELECTION_EVENT_DISPLAY, SELECTION_EVENT_DPYINFO) (SELECTION_EVENT_REQUESTOR, SELECTION_EVENT_SELECTION) (SELECTION_EVENT_TARGET, SELECTION_EVENT_PROPERTY) (SELECTION_EVENT_TIME, x_handle_selection_event): Arg is now of type struct selection_input_event *) not struct input_event *. All callers changed.
Diffstat (limited to 'src/xselect.c')
-rw-r--r--src/xselect.c54
1 files changed, 31 insertions, 23 deletions
diff --git a/src/xselect.c b/src/xselect.c
index 19ace065698..bd2d65e795f 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -45,9 +45,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
struct prop_location;
struct selection_data;
-static void x_decline_selection_request (struct input_event *);
-static bool x_convert_selection (struct input_event *, Lisp_Object,
- Lisp_Object, Atom, bool,
+static void x_decline_selection_request (struct selection_input_event *);
+static bool x_convert_selection (Lisp_Object, Lisp_Object, Atom, bool,
struct x_display_info *);
static bool waiting_for_other_props_on_window (Display *, Window);
static struct prop_location *expect_property_change (Display *, Window,
@@ -117,7 +116,7 @@ selection_quantum (Display *display)
struct selection_event_queue
{
- struct input_event event;
+ struct selection_input_event event;
struct selection_event_queue *next;
};
@@ -127,10 +126,22 @@ static struct selection_event_queue *selection_queue;
static int x_queue_selection_requests;
+/* True if the input events are duplicates. */
+
+static bool
+selection_input_event_equal (struct selection_input_event *a,
+ struct selection_input_event *b)
+{
+ return (a->kind == b->kind && a->dpyinfo == b->dpyinfo
+ && a->requestor == b->requestor && a->selection == b->selection
+ && a->target == b->target && a->property == b->property
+ && a->time == b->time);
+}
+
/* Queue up an SELECTION_REQUEST_EVENT *EVENT, to be processed later. */
static void
-x_queue_event (struct input_event *event)
+x_queue_event (struct selection_input_event *event)
{
struct selection_event_queue *queue_tmp;
@@ -138,7 +149,7 @@ x_queue_event (struct input_event *event)
This only happens for large requests which uses the incremental protocol. */
for (queue_tmp = selection_queue; queue_tmp; queue_tmp = queue_tmp->next)
{
- if (!memcmp (&queue_tmp->event, event, sizeof (*event)))
+ if (selection_input_event_equal (event, &queue_tmp->event))
{
TRACE1 ("DECLINE DUP SELECTION EVENT %p", queue_tmp);
x_decline_selection_request (event);
@@ -419,7 +430,7 @@ x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
meaning we were unable to do what they wanted. */
static void
-x_decline_selection_request (struct input_event *event)
+x_decline_selection_request (struct selection_input_event *event)
{
XEvent reply_base;
XSelectionEvent *reply = &(reply_base.xselection);
@@ -444,7 +455,7 @@ x_decline_selection_request (struct input_event *event)
/* This is the selection request currently being processed.
It is set to zero when the request is fully processed. */
-static struct input_event *x_selection_current_request;
+static struct selection_input_event *x_selection_current_request;
/* Display info in x_selection_request. */
@@ -549,7 +560,7 @@ static int x_reply_selection_request_cnt;
#endif /* TRACE_SELECTION */
static void
-x_reply_selection_request (struct input_event *event,
+x_reply_selection_request (struct selection_input_event *event,
struct x_display_info *dpyinfo)
{
XEvent reply_base;
@@ -740,7 +751,7 @@ x_reply_selection_request (struct input_event *event,
This is called from keyboard.c when such an event is found in the queue. */
static void
-x_handle_selection_request (struct input_event *event)
+x_handle_selection_request (struct selection_input_event *event)
{
struct gcpro gcpro1, gcpro2;
Time local_selection_time;
@@ -809,7 +820,7 @@ x_handle_selection_request (struct input_event *event)
AREF (multprop, 2*j+1));
if (subproperty != None)
- x_convert_selection (event, selection_symbol, subtarget,
+ x_convert_selection (selection_symbol, subtarget,
subproperty, true, dpyinfo);
}
success = true;
@@ -818,7 +829,7 @@ x_handle_selection_request (struct input_event *event)
{
if (property == None)
property = SELECTION_EVENT_TARGET (event);
- success = x_convert_selection (event, selection_symbol,
+ success = x_convert_selection (selection_symbol,
target_symbol, property,
false, dpyinfo);
}
@@ -849,7 +860,7 @@ x_handle_selection_request (struct input_event *event)
Return true iff successful. */
static bool
-x_convert_selection (struct input_event *event, Lisp_Object selection_symbol,
+x_convert_selection (Lisp_Object selection_symbol,
Lisp_Object target_symbol, Atom property,
bool for_multiple, struct x_display_info *dpyinfo)
{
@@ -902,7 +913,7 @@ x_convert_selection (struct input_event *event, Lisp_Object selection_symbol,
This is called from keyboard.c when such an event is found in the queue. */
static void
-x_handle_selection_clear (struct input_event *event)
+x_handle_selection_clear (struct selection_input_event *event)
{
Atom selection = SELECTION_EVENT_SELECTION (event);
Time changed_owner_time = SELECTION_EVENT_TIME (event);
@@ -954,7 +965,7 @@ x_handle_selection_clear (struct input_event *event)
}
void
-x_handle_selection_event (struct input_event *event)
+x_handle_selection_event (struct selection_input_event *event)
{
TRACE0 ("x_handle_selection_event");
if (event->kind != SELECTION_REQUEST_EVENT)
@@ -2006,10 +2017,7 @@ On MS-DOS, all this does is return non-nil if we own the selection. */)
{
Time timestamp;
Atom selection_atom;
- union {
- struct selection_input_event sie;
- struct input_event ie;
- } event;
+ struct selection_input_event event;
struct frame *f = frame_for_x_selection (terminal);
struct x_display_info *dpyinfo;
@@ -2038,10 +2046,10 @@ On MS-DOS, all this does is return non-nil if we own the selection. */)
the selection owner to None. The NCD server does, the MIT Sun4 server
doesn't. So we synthesize one; this means we might get two, but
that's ok, because the second one won't have any effect. */
- SELECTION_EVENT_DPYINFO (&event.sie) = dpyinfo;
- SELECTION_EVENT_SELECTION (&event.sie) = selection_atom;
- SELECTION_EVENT_TIME (&event.sie) = timestamp;
- x_handle_selection_clear (&event.ie);
+ SELECTION_EVENT_DPYINFO (&event) = dpyinfo;
+ SELECTION_EVENT_SELECTION (&event) = selection_atom;
+ SELECTION_EVENT_TIME (&event) = timestamp;
+ x_handle_selection_clear (&event);
return Qt;
}