Commit 1552e673 authored by Paul Eggert's avatar Paul Eggert

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.
parent 8769d0fe
This diff is collapsed.
......@@ -21,6 +21,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "coding.h" /* for ENCODE_UTF_8 and ENCODE_SYSTEM */
#include "termhooks.h"
#ifdef HAVE_X11
# include "xterm.h" /* for struct selection_input_event */
#endif
INLINE_HEADER_BEGIN
/* Most code should use this macro to access Lisp fields in struct kboard. */
......@@ -217,6 +221,15 @@ kset_window_system (struct kboard *kb, Lisp_Object val)
kb->Vwindow_system_ = val;
}
union buffered_input_event
{
ENUM_BF (event_kind) kind : EVENT_KIND_WIDTH;
struct input_event ie;
#ifdef HAVE_X11
struct selection_input_event sie;
#endif
};
/* Temporarily used before a frame has been opened. */
extern KBOARD *initial_kboard;
......@@ -438,9 +451,20 @@ extern void clear_waiting_for_input (void);
extern void swallow_events (bool);
extern bool lucid_event_type_list_p (Lisp_Object);
extern void kbd_buffer_store_event (struct input_event *);
extern void kbd_buffer_store_event_hold (struct input_event *,
struct input_event *);
extern void kbd_buffer_unget_event (struct input_event *);
extern void kbd_buffer_store_buffered_event (union buffered_input_event *,
struct input_event *);
INLINE void
kbd_buffer_store_event_hold (struct input_event *event,
struct input_event *hold_quit)
{
union buffered_input_event *ev = (union buffered_input_event *) event;
verify (sizeof *event == sizeof *ev && alignof (*event) == alignof (*ev));
return kbd_buffer_store_buffered_event ((union buffered_input_event *) event,
hold_quit);
}
#ifdef HAVE_X11
extern void kbd_buffer_unget_event (struct selection_input_event *);
#endif
extern void poll_for_input_1 (void);
extern void show_help_echo (Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object);
......
......@@ -243,6 +243,9 @@ enum event_kind
};
/* Bit width of an enum event_kind tag at the start of structs and unions. */
enum { EVENT_KIND_WIDTH = 16 };
/* If a struct input_event has a kind which is SELECTION_REQUEST_EVENT
or SELECTION_CLEAR_EVENT, then its contents are really described
by `struct selection_input_event'; see xterm.h. */
......@@ -255,7 +258,7 @@ enum event_kind
struct input_event
{
/* What kind of event was this? */
ENUM_BF (event_kind) kind : 16;
ENUM_BF (event_kind) kind : EVENT_KIND_WIDTH;
/* Used in scroll back click events. */
ENUM_BF (scroll_bar_part) part : 16;
......
......@@ -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;
}
......
......@@ -7358,10 +7358,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
const XEvent *event,
int *finish, struct input_event *hold_quit)
{
union {
struct input_event ie;
struct selection_input_event sie;
} inev;
union buffered_input_event inev;
int count = 0;
int do_help = 0;
ptrdiff_t nbytes = 0;
......@@ -7589,7 +7586,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
const XSelectionClearEvent *eventp = &event->xselectionclear;
inev.ie.kind = SELECTION_CLEAR_EVENT;
inev.sie.kind = SELECTION_CLEAR_EVENT;
SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
......@@ -7605,7 +7602,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
const XSelectionRequestEvent *eventp = &event->xselectionrequest;
inev.ie.kind = SELECTION_REQUEST_EVENT;
inev.sie.kind = SELECTION_REQUEST_EVENT;
SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
......@@ -8116,7 +8113,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
? ASCII_KEYSTROKE_EVENT
: MULTIBYTE_CHAR_KEYSTROKE_EVENT);
inev.ie.code = ch;
kbd_buffer_store_event_hold (&inev.ie, hold_quit);
kbd_buffer_store_buffered_event (&inev, hold_quit);
}
count += nchars;
......@@ -8533,7 +8530,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
done:
if (inev.ie.kind != NO_EVENT)
{
kbd_buffer_store_event_hold (&inev.ie, hold_quit);
kbd_buffer_store_buffered_event (&inev, hold_quit);
count++;
}
......
......@@ -960,7 +960,7 @@ struct scroll_bar
struct selection_input_event
{
int kind;
ENUM_BF (event_kind) kind : EVENT_KIND_WIDTH;
struct x_display_info *dpyinfo;
/* We spell it with an "o" here because X does. */
Window requestor;
......@@ -970,23 +970,23 @@ struct selection_input_event
/* Unlike macros below, this can't be used as an lvalue. */
INLINE Display *
SELECTION_EVENT_DISPLAY (struct input_event *ev)
SELECTION_EVENT_DISPLAY (struct selection_input_event *ev)
{
return ((struct selection_input_event *) ev)->dpyinfo->display;
return ev->dpyinfo->display;
}
#define SELECTION_EVENT_DPYINFO(eventp) \
(((struct selection_input_event *) (eventp))->dpyinfo)
((eventp)->dpyinfo)
/* We spell it with an "o" here because X does. */
#define SELECTION_EVENT_REQUESTOR(eventp) \
(((struct selection_input_event *) (eventp))->requestor)
((eventp)->requestor)
#define SELECTION_EVENT_SELECTION(eventp) \
(((struct selection_input_event *) (eventp))->selection)
((eventp)->selection)
#define SELECTION_EVENT_TARGET(eventp) \
(((struct selection_input_event *) (eventp))->target)
((eventp)->target)
#define SELECTION_EVENT_PROPERTY(eventp) \
(((struct selection_input_event *) (eventp))->property)
((eventp)->property)
#define SELECTION_EVENT_TIME(eventp) \
(((struct selection_input_event *) (eventp))->time)
((eventp)->time)
/* From xfns.c. */
......@@ -1079,7 +1079,7 @@ extern void x_clear_under_internal_border (struct frame *f);
extern void x_handle_property_notify (const XPropertyEvent *);
extern void x_handle_selection_notify (const XSelectionEvent *);
extern void x_handle_selection_event (struct input_event *);
extern void x_handle_selection_event (struct selection_input_event *);
extern void x_clear_frame_selections (struct frame *);
extern void x_send_client_event (Lisp_Object display,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment