commit 9b891278cf715cee229a00068fd8d5c29ef9d79d (HEAD, refs/remotes/origin/master) Author: Paul Eggert Date: Tue Jun 23 18:07:46 2015 -0700 * src/keyboard.h (kbd_buffer_store_event_hold): Remove unused local. diff --git a/src/keyboard.h b/src/keyboard.h index 1b489f3..eaf8194 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -457,7 +457,6 @@ 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 (alignof (struct input_event) == alignof (union buffered_input_event) && sizeof (struct input_event) == sizeof (union buffered_input_event)); return kbd_buffer_store_buffered_event ((union buffered_input_event *) event, commit 4fe5cb43d9c27da933b6e6a1beedb14eba4db4e9 Author: Paul Eggert Date: Tue Jun 23 18:01:55 2015 -0700 Port selection info fix to clang * src/keyboard.h (kbd_buffer_store_event_hold): Don't assume C11 semantics for alignof (Bug#20756). diff --git a/src/keyboard.h b/src/keyboard.h index 5278051..1b489f3 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -458,7 +458,8 @@ 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)); + verify (alignof (struct input_event) == alignof (union buffered_input_event) + && sizeof (struct input_event) == sizeof (union buffered_input_event)); return kbd_buffer_store_buffered_event ((union buffered_input_event *) event, hold_quit); } commit 1552e6737317ea2c85e06600e178114c6b0f9fb2 Author: Paul Eggert Date: Tue Jun 23 16:29:27 2015 -0700 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. diff --git a/src/keyboard.c b/src/keyboard.c index 7bfc3f3..8ea7b53 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -288,18 +288,18 @@ static bool input_was_pending; /* Circular buffer for pre-read keyboard input. */ -static struct input_event kbd_buffer[KBD_BUFFER_SIZE]; +static union buffered_input_event kbd_buffer[KBD_BUFFER_SIZE]; /* Pointer to next available character in kbd_buffer. If kbd_fetch_ptr == kbd_store_ptr, the buffer is empty. This may be kbd_buffer + KBD_BUFFER_SIZE, meaning that the next available char is in kbd_buffer[0]. */ -static struct input_event *kbd_fetch_ptr; +static union buffered_input_event *kbd_fetch_ptr; /* Pointer to next place to store character in kbd_buffer. This may be kbd_buffer + KBD_BUFFER_SIZE, meaning that the next character should go in kbd_buffer[0]. */ -static struct input_event * volatile kbd_store_ptr; +static union buffered_input_event *volatile kbd_store_ptr; /* The above pair of variables forms a "queue empty" flag. When we enqueue a non-hook event, we increment kbd_store_ptr. When we @@ -372,14 +372,9 @@ static bool help_char_p (Lisp_Object); static void save_getcjmp (sys_jmp_buf); static void restore_getcjmp (sys_jmp_buf); static Lisp_Object apply_modifiers (int, Lisp_Object); -static void clear_event (struct input_event *); static void restore_kboard_configuration (int); -#ifdef USABLE_SIGIO -static void deliver_input_available_signal (int signo); -#endif static void handle_interrupt (bool); static _Noreturn void quit_throw_to_read_char (bool); -static void process_special_events (void); static void timer_start_idle (void); static void timer_stop_idle (void); static void timer_resume_idle (void); @@ -3446,7 +3441,7 @@ readable_events (int flags) #endif )) { - struct input_event *event; + union buffered_input_event *event; event = ((kbd_fetch_ptr < kbd_buffer + KBD_BUFFER_SIZE) ? kbd_fetch_ptr @@ -3463,8 +3458,8 @@ readable_events (int flags) && !((flags & READABLE_EVENTS_IGNORE_SQUEEZABLES) && (event->kind == SCROLL_BAR_CLICK_EVENT || event->kind == HORIZONTAL_SCROLL_BAR_CLICK_EVENT) - && event->part == scroll_bar_handle - && event->modifiers == 0) + && event->ie.part == scroll_bar_handle + && event->ie.modifiers == 0) #endif && !((flags & READABLE_EVENTS_FILTER_EVENTS) && event->kind == BUFFER_SWITCH_EVENT)) @@ -3551,8 +3546,8 @@ kbd_buffer_store_event (register struct input_event *event) subsequent input events have been parsed (and discarded). */ void -kbd_buffer_store_event_hold (register struct input_event *event, - struct input_event *hold_quit) +kbd_buffer_store_buffered_event (union buffered_input_event *event, + struct input_event *hold_quit) { if (event->kind == NO_EVENT) emacs_abort (); @@ -3562,36 +3557,36 @@ kbd_buffer_store_event_hold (register struct input_event *event, if (event->kind == ASCII_KEYSTROKE_EVENT) { - register int c = event->code & 0377; + int c = event->ie.code & 0377; - if (event->modifiers & ctrl_modifier) + if (event->ie.modifiers & ctrl_modifier) c = make_ctrl_char (c); - c |= (event->modifiers + c |= (event->ie.modifiers & (meta_modifier | alt_modifier | hyper_modifier | super_modifier)); if (c == quit_char) { - KBOARD *kb = FRAME_KBOARD (XFRAME (event->frame_or_window)); - struct input_event *sp; + KBOARD *kb = FRAME_KBOARD (XFRAME (event->ie.frame_or_window)); if (single_kboard && kb != current_kboard) { kset_kbd_queue - (kb, list2 (make_lispy_switch_frame (event->frame_or_window), + (kb, list2 (make_lispy_switch_frame (event->ie.frame_or_window), make_number (c))); kb->kbd_queue_has_data = 1; + union buffered_input_event *sp; for (sp = kbd_fetch_ptr; sp != kbd_store_ptr; sp++) { if (sp == kbd_buffer + KBD_BUFFER_SIZE) sp = kbd_buffer; - if (event_to_kboard (sp) == kb) + if (event_to_kboard (&sp->ie) == kb) { - sp->kind = NO_EVENT; - sp->frame_or_window = Qnil; - sp->arg = Qnil; + sp->ie.kind = NO_EVENT; + sp->ie.frame_or_window = Qnil; + sp->ie.arg = Qnil; } } return; @@ -3599,7 +3594,7 @@ kbd_buffer_store_event_hold (register struct input_event *event, if (hold_quit) { - *hold_quit = *event; + *hold_quit = event->ie; return; } @@ -3610,9 +3605,9 @@ kbd_buffer_store_event_hold (register struct input_event *event, { Lisp_Object focus; - focus = FRAME_FOCUS_FRAME (XFRAME (event->frame_or_window)); + focus = FRAME_FOCUS_FRAME (XFRAME (event->ie.frame_or_window)); if (NILP (focus)) - focus = event->frame_or_window; + focus = event->ie.frame_or_window; internal_last_event_frame = focus; Vlast_event_frame = focus; } @@ -3682,22 +3677,27 @@ kbd_buffer_store_event_hold (register struct input_event *event, } -/* Put an input event back in the head of the event queue. */ +#ifdef HAVE_X11 + +/* Put a selection input event back in the head of the event queue. */ void -kbd_buffer_unget_event (register struct input_event *event) +kbd_buffer_unget_event (struct selection_input_event *event) { if (kbd_fetch_ptr == kbd_buffer) kbd_fetch_ptr = kbd_buffer + KBD_BUFFER_SIZE; /* Don't let the very last slot in the buffer become full, */ - if (kbd_fetch_ptr - 1 != kbd_store_ptr) + union buffered_input_event *kp = kbd_fetch_ptr - 1; + if (kp != kbd_store_ptr) { - --kbd_fetch_ptr; - *kbd_fetch_ptr = *event; + kp->sie = *event; + kbd_fetch_ptr = kp; } } +#endif + /* Limit help event positions to this range, to avoid overflow problems. */ #define INPUT_EVENT_POS_MAX \ ((ptrdiff_t) min (PTRDIFF_MAX, min (TYPE_MAXIMUM (Time) / 2, \ @@ -3776,7 +3776,7 @@ kbd_buffer_store_help_event (Lisp_Object frame, Lisp_Object help) void discard_mouse_events (void) { - struct input_event *sp; + union buffered_input_event *sp; for (sp = kbd_fetch_ptr; sp != kbd_store_ptr; sp++) { if (sp == kbd_buffer + KBD_BUFFER_SIZE) @@ -3806,7 +3806,7 @@ discard_mouse_events (void) bool kbd_buffer_events_waiting (void) { - struct input_event *sp; + union buffered_input_event *sp; for (sp = kbd_fetch_ptr; sp != kbd_store_ptr && sp->kind == NO_EVENT; @@ -3824,7 +3824,7 @@ kbd_buffer_events_waiting (void) /* Clear input event EVENT. */ static void -clear_event (struct input_event *event) +clear_event (union buffered_input_event *event) { event->kind = NO_EVENT; } @@ -3945,13 +3945,13 @@ kbd_buffer_get_event (KBOARD **kbp, mouse movement enabled and available. */ if (kbd_fetch_ptr != kbd_store_ptr) { - struct input_event *event; + union buffered_input_event *event; event = ((kbd_fetch_ptr < kbd_buffer + KBD_BUFFER_SIZE) ? kbd_fetch_ptr : kbd_buffer); - *kbp = event_to_kboard (event); + *kbp = event_to_kboard (&event->ie); if (*kbp == 0) *kbp = current_kboard; /* Better than returning null ptr? */ @@ -3964,12 +3964,10 @@ kbd_buffer_get_event (KBOARD **kbp, || event->kind == SELECTION_CLEAR_EVENT) { #ifdef HAVE_X11 - struct input_event copy; - /* Remove it from the buffer before processing it, since otherwise swallow_events will see it and process it again. */ - copy = *event; + struct selection_input_event copy = event->sie; kbd_fetch_ptr = event + 1; input_pending = readable_events (0); x_handle_selection_event (©); @@ -3983,7 +3981,7 @@ kbd_buffer_get_event (KBOARD **kbp, #if defined (HAVE_NS) else if (event->kind == NS_TEXT_EVENT) { - if (event->code == KEY_NS_PUT_WORKING_TEXT) + if (event->ie.code == KEY_NS_PUT_WORKING_TEXT) obj = list1 (intern ("ns-put-working-text")); else obj = list1 (intern ("ns-unput-working-text")); @@ -3998,7 +3996,7 @@ kbd_buffer_get_event (KBOARD **kbp, else if (event->kind == DELETE_WINDOW_EVENT) { /* Make an event (delete-frame (FRAME)). */ - obj = list2 (Qdelete_frame, list1 (event->frame_or_window)); + obj = list2 (Qdelete_frame, list1 (event->ie.frame_or_window)); kbd_fetch_ptr = event + 1; } #endif @@ -4007,13 +4005,13 @@ kbd_buffer_get_event (KBOARD **kbp, else if (event->kind == ICONIFY_EVENT) { /* Make an event (iconify-frame (FRAME)). */ - obj = list2 (Qiconify_frame, list1 (event->frame_or_window)); + obj = list2 (Qiconify_frame, list1 (event->ie.frame_or_window)); kbd_fetch_ptr = event + 1; } else if (event->kind == DEICONIFY_EVENT) { /* Make an event (make-frame-visible (FRAME)). */ - obj = list2 (Qmake_frame_visible, list1 (event->frame_or_window)); + obj = list2 (Qmake_frame_visible, list1 (event->ie.frame_or_window)); kbd_fetch_ptr = event + 1; } #endif @@ -4029,8 +4027,8 @@ kbd_buffer_get_event (KBOARD **kbp, { kbd_fetch_ptr = event + 1; input_pending = readable_events (0); - if (FRAME_LIVE_P (XFRAME (event->frame_or_window))) - x_activate_menubar (XFRAME (event->frame_or_window)); + if (FRAME_LIVE_P (XFRAME (event->ie.frame_or_window))) + x_activate_menubar (XFRAME (event->ie.frame_or_window)); } #endif #ifdef HAVE_NTGUI @@ -4038,9 +4036,9 @@ kbd_buffer_get_event (KBOARD **kbp, { /* Make an event (language-change FRAME CODEPAGE LANGUAGE-ID). */ obj = list4 (Qlanguage_change, - event->frame_or_window, - make_number (event->code), - make_number (event->modifiers)); + event->ie.frame_or_window, + make_number (event->ie.code), + make_number (event->ie.modifiers)); kbd_fetch_ptr = event + 1; } #endif @@ -4049,16 +4047,16 @@ kbd_buffer_get_event (KBOARD **kbp, { #ifdef HAVE_W32NOTIFY /* Make an event (file-notify (DESCRIPTOR ACTION FILE) CALLBACK). */ - obj = list3 (Qfile_notify, event->arg, event->frame_or_window); + obj = list3 (Qfile_notify, event->ie.arg, event->ie.frame_or_window); #else - obj = make_lispy_event (event); + obj = make_lispy_event (&event->ie); #endif kbd_fetch_ptr = event + 1; } #endif /* USE_FILE_NOTIFY */ else if (event->kind == SAVE_SESSION_EVENT) { - obj = list2 (Qsave_session, event->arg); + obj = list2 (Qsave_session, event->ie.arg); kbd_fetch_ptr = event + 1; } /* Just discard these, by returning nil. @@ -4075,11 +4073,11 @@ kbd_buffer_get_event (KBOARD **kbp, { Lisp_Object object, position, help, frame, window; - frame = event->frame_or_window; - object = event->arg; - position = make_number (Time_to_position (event->timestamp)); - window = event->x; - help = event->y; + frame = event->ie.frame_or_window; + object = event->ie.arg; + position = make_number (Time_to_position (event->ie.timestamp)); + window = event->ie.x; + help = event->ie.y; clear_event (event); kbd_fetch_ptr = event + 1; @@ -4095,14 +4093,14 @@ kbd_buffer_get_event (KBOARD **kbp, switch-frame event if necessary. */ Lisp_Object frame, focus; - frame = event->frame_or_window; + frame = event->ie.frame_or_window; focus = FRAME_FOCUS_FRAME (XFRAME (frame)); if (FRAMEP (focus)) frame = focus; if ( #ifdef HAVE_X11 - ! NILP (event->arg) + ! NILP (event->ie.arg) && #endif !EQ (frame, internal_last_event_frame) @@ -4119,7 +4117,7 @@ kbd_buffer_get_event (KBOARD **kbp, #ifdef HAVE_WINDOW_SYSTEM Display_Info *di; - Lisp_Object frame = event->frame_or_window; + Lisp_Object frame = event->ie.frame_or_window; bool focused = false; for (di = x_display_list; di && ! focused; di = di->next) @@ -4135,13 +4133,13 @@ kbd_buffer_get_event (KBOARD **kbp, #ifdef HAVE_DBUS else if (event->kind == DBUS_EVENT) { - obj = make_lispy_event (event); + obj = make_lispy_event (&event->ie); kbd_fetch_ptr = event + 1; } #endif else if (event->kind == CONFIG_CHANGED_EVENT) { - obj = make_lispy_event (event); + obj = make_lispy_event (&event->ie); kbd_fetch_ptr = event + 1; } else @@ -4151,7 +4149,7 @@ kbd_buffer_get_event (KBOARD **kbp, Lisp_Object frame; Lisp_Object focus; - frame = event->frame_or_window; + frame = event->ie.frame_or_window; if (CONSP (frame)) frame = XCAR (frame); else if (WINDOWP (frame)) @@ -4171,7 +4169,7 @@ kbd_buffer_get_event (KBOARD **kbp, if (NILP (obj)) { - obj = make_lispy_event (event); + obj = make_lispy_event (&event->ie); #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \ || defined (HAVE_NS) || defined (USE_GTK) @@ -4181,7 +4179,7 @@ kbd_buffer_get_event (KBOARD **kbp, beginning of the menu sequence, and we might as well leave that as the `event with parameters' for this selection. */ if (used_mouse_menu - && !EQ (event->frame_or_window, event->arg) + && !EQ (event->ie.frame_or_window, event->ie.arg) && (event->kind == MENU_BAR_EVENT || event->kind == TOOL_BAR_EVENT)) *used_mouse_menu = 1; @@ -4261,7 +4259,7 @@ kbd_buffer_get_event (KBOARD **kbp, static void process_special_events (void) { - struct input_event *event; + union buffered_input_event *event; for (event = kbd_fetch_ptr; event != kbd_store_ptr; ++event) { @@ -4284,23 +4282,22 @@ process_special_events (void) between kbd_fetch_ptr and EVENT one slot to the right, cyclically. */ - struct input_event copy = *event; - struct input_event *beg + struct selection_input_event copy = event->sie; + union buffered_input_event *beg = (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE) ? kbd_buffer : kbd_fetch_ptr; if (event > beg) - memmove (beg + 1, beg, (event - beg) * sizeof (struct input_event)); + memmove (beg + 1, beg, (event - beg) * sizeof *beg); else if (event < beg) { if (event > kbd_buffer) memmove (kbd_buffer + 1, kbd_buffer, - (event - kbd_buffer) * sizeof (struct input_event)); + (event - kbd_buffer) * sizeof *kbd_buffer); *kbd_buffer = *(kbd_buffer + KBD_BUFFER_SIZE - 1); if (beg < kbd_buffer + KBD_BUFFER_SIZE - 1) memmove (beg + 1, beg, - (kbd_buffer + KBD_BUFFER_SIZE - 1 - beg) - * sizeof (struct input_event)); + (kbd_buffer + KBD_BUFFER_SIZE - 1 - beg) * sizeof *beg); } if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE) @@ -10311,7 +10308,7 @@ stuff_buffered_input (Lisp_Object stuffstring) if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE) kbd_fetch_ptr = kbd_buffer; if (kbd_fetch_ptr->kind == ASCII_KEYSTROKE_EVENT) - stuff_char (kbd_fetch_ptr->code); + stuff_char (kbd_fetch_ptr->ie.code); clear_event (kbd_fetch_ptr); } @@ -11937,7 +11934,7 @@ mark_kboards (void) mark_object (KVAR (kb, echo_string)); } { - struct input_event *event; + union buffered_input_event *event; for (event = kbd_fetch_ptr; event != kbd_store_ptr; event++) { if (event == kbd_buffer + KBD_BUFFER_SIZE) @@ -11946,10 +11943,10 @@ mark_kboards (void) if (event->kind != SELECTION_REQUEST_EVENT && event->kind != SELECTION_CLEAR_EVENT) { - mark_object (event->x); - mark_object (event->y); - mark_object (event->frame_or_window); - mark_object (event->arg); + mark_object (event->ie.x); + mark_object (event->ie.y); + mark_object (event->ie.frame_or_window); + mark_object (event->ie.arg); } } } diff --git a/src/keyboard.h b/src/keyboard.h index bcdeaf6..5278051 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -21,6 +21,10 @@ along with GNU Emacs. If not, see . */ #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); diff --git a/src/termhooks.h b/src/termhooks.h index 3cafc43..168bc35 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -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; diff --git a/src/xselect.c b/src/xselect.c index 19ace06..bd2d65e 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -45,9 +45,8 @@ along with GNU Emacs. If not, see . */ 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; } diff --git a/src/xterm.c b/src/xterm.c index 4d79450..d573738 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -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++; } diff --git a/src/xterm.h b/src/xterm.h index 3081c16..5622344 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -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, commit 8769d0fe79dda776652c3bf342263568bbd7623b Author: Glenn Morris Date: Tue Jun 23 16:44:07 2015 -0400 * Makefile.in (install-arch-dep): Simplify with Make conditionals. diff --git a/Makefile.in b/Makefile.in index 63e17c3..c998d8d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -492,18 +492,17 @@ write_subdir=if [ -f "$${subdir}/subdirs.el" ]; \ install-arch-dep: src install-arch-indep install-etcdoc install-$(NTDIR) umask 022; ${MKDIR_P} "$(DESTDIR)${bindir}" $(MAKE) -C lib-src install - if test "${ns_self_contained}" = "no"; then \ - ${INSTALL_PROGRAM} $(INSTALL_STRIP) src/emacs${EXEEXT} "$(DESTDIR)${bindir}/$(EMACSFULL)" || exit 1 ; \ - chmod 1755 "$(DESTDIR)${bindir}/$(EMACSFULL)" || true; \ - if test "x${NO_BIN_LINK}" = x; then \ - rm -f "$(DESTDIR)${bindir}/$(EMACS)" ; \ - cd "$(DESTDIR)${bindir}" && $(LN_S_FILEONLY) $(EMACSFULL) $(EMACS); \ - fi; \ - else \ - subdir=${ns_appresdir}/site-lisp; \ - ${write_subdir} || exit 1; \ - rm -rf ${ns_appresdir}/share; \ - fi +ifeq (${ns_self_contained},no) + ${INSTALL_PROGRAM} $(INSTALL_STRIP) src/emacs${EXEEXT} "$(DESTDIR)${bindir}/$(EMACSFULL)" + -chmod 1755 "$(DESTDIR)${bindir}/$(EMACSFULL)" +ifndef NO_BIN_LINK + rm -f "$(DESTDIR)${bindir}/$(EMACS)" + cd "$(DESTDIR)${bindir}" && $(LN_S_FILEONLY) $(EMACSFULL) $(EMACS) +endif +else + subdir=${ns_appresdir}/site-lisp && ${write_subdir} + rm -rf ${ns_appresdir}/share +endif ### Windows-specific install target for installing programs produced ### in nt/, and its Posix do-nothing shadow. commit c7a19e0c80ec6134ab6fb1950d3e1ac59a7b986f Author: Artur Malabarba Date: Tue Jan 27 14:08:01 2015 -0200 * lisp/isearch.el: Fold many unicode characters to ASCII (isearch-character-fold-search, isearch--character-fold-extras) (isearch--character-fold-table): New variable. (isearch--character-folded-regexp): New function. (isearch-search-fun-default): Use them. * lisp/replace.el (replace-character-fold): New variable. (replace-search): Use it. * etc/NEWS: Document it. diff --git a/etc/NEWS b/etc/NEWS index 31055ac..e4cf2d6 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -84,6 +84,20 @@ command line when `initial-buffer-choice' is non-nil. * Changes in Emacs 25.1 +** `isearch' and `query-replace' now perform character folding in matches. +This is analogous to case-folding, but applies between Unicode +characters and their ASCII counterparts. This means many characters +will match entire groups of charactes. + +For instance, the " will match all variants of unicode double quotes +(like “ and ”), and the letter a will match all of its accented +cousins, even those composed of multiple characters, as well as many +other symbols like ℀, ℁, ⒜, and ⓐ. + +** New function `isearch--character-folded-regexp' can be used +by searching commands to produce a a regexp matching anything that +character-folds into STRING. + ** New command `checkdoc-package-keywords' checks if the current package keywords are recognized. Set the new option `checkdoc-package-keywords-flag' to non-nil to make diff --git a/lisp/isearch.el b/lisp/isearch.el index d1b92bd..44ce902 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -272,6 +272,79 @@ Default value, nil, means edit the string instead." :version "23.1" :group 'isearch) +(defvar isearch-character-fold-search t + "Non-nil if isearch should fold similar characters. +This means some characters will match entire groups of charactes. +For instance, \" will match all variants of double quotes, and +the letter a will match all of its accented versions (and then +some).") + +(defconst isearch--character-fold-extras + '((?\" """ "“" "”" "”" "„" "⹂" "〞" "‟" "‟" "❞" "❝" "❠" "“" "„" "〝" "〟" "🙷" "🙶" "🙸" "«" "»") + (?' "❟" "❛" "❜" "‘" "’" "‚" "‛" "‚" "󠀢" "❮" "❯" "‹" "›") + (?` "❛" "‘" "‛" "󠀢" "❮" "‹") + ;; `isearch-character-fold-search' doesn't interact with + ;; `isearch-lax-whitespace' yet. So we need to add this here. + (?\s " " "\r" "\n")) + "Extra entries to add to `isearch--character-fold-table'. +Used to specify character folding not covered by unicode +decomposition. Each car is a character and each cdr is a list of +strings that it should match (itself excluded).") + +(defvar isearch--character-fold-table + (eval-when-compile + (require 'subr-x) + (let ((equiv (make-char-table 'character-fold-table))) + ;; Compile a list of all complex characters that each simple + ;; character should match. + (dotimes (i (length equiv)) + (let ((dd (get-char-code-property i 'decomposition)) + d k found) + ;; Skip trivial cases (?a decomposes to (?a)). + (unless (and (eq i (car dd))) + ;; Discard a possible formatting tag. + (when (symbolp (car-safe dd)) + (setq dd (cdr dd))) + ;; Is k a number or letter, per unicode standard? + (setq d dd) + (while (and d (not found)) + (setq k (pop d)) + (setq found (and (characterp k) + (memq (get-char-code-property k 'general-category) + '(Lu Ll Lt Lm Lo Nd Nl No))))) + ;; If there's no number or letter on the + ;; decomposition, find the first character in it. + (setq d dd) + (while (and d (not found)) + (setq k (pop d)) + (setq found (characterp k))) + ;; Add i to the list of characters that k can + ;; represent. Also add its decomposition, so we can + ;; match multi-char representations like (format "a%c" 769) + (when (and found (not (eq i k))) + (aset equiv k (cons (apply #'string dd) + (cons (char-to-string i) + (aref equiv k)))))))) + (dotimes (i (length equiv)) + (when-let ((chars (append (cdr (assq i isearch--character-fold-extras)) + (aref equiv i)))) + (aset equiv i (regexp-opt (cons (char-to-string i) chars))))) + equiv)) + "Used for folding characters of the same group during search.") + +(defun isearch--character-folded-regexp (string) + "Return a regexp matching anything that character-folds into STRING. +If `isearch-character-fold-search' is nil, `regexp-quote' string. +Otherwise, any character in STRING that has an entry in +`isearch--character-fold-table' is replaced with that entry +\(which is a regexp) and other characters are `regexp-quote'd." + (if isearch-character-fold-search + (apply #'concat + (mapcar (lambda (c) (or (aref isearch--character-fold-table c) + (regexp-quote (string c)))) + string)) + (regexp-quote string))) + (defcustom isearch-lazy-highlight t "Controls the lazy-highlighting during incremental search. When non-nil, all text in the buffer matching the current search @@ -2607,6 +2680,11 @@ Can be changed via `isearch-search-fun-function' for special needs." 're-search-backward-lax-whitespace)) (isearch-regexp (if isearch-forward 're-search-forward 're-search-backward)) + (isearch-character-fold-search + (lambda (string &optional bound noerror count) + (funcall (if isearch-forward #'re-search-forward #'re-search-backward) + (isearch--character-folded-regexp string) + bound noerror count))) ((and isearch-lax-whitespace search-whitespace-regexp) (if isearch-forward 'search-forward-lax-whitespace diff --git a/lisp/replace.el b/lisp/replace.el index 74909ef..5e3ddc5 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -33,6 +33,14 @@ :type 'boolean :group 'matching) +(defcustom replace-character-fold t + "Non-nil means `query-replace' should do character folding in matches. +This means, for instance, that ' will match a large variety of +unicode quotes." + :type 'boolean + :group 'matching + :version "25.1") + (defcustom replace-lax-whitespace nil "Non-nil means `query-replace' matches a sequence of whitespace chars. When you enter a space or spaces in the strings to be replaced, @@ -2005,6 +2013,7 @@ It is called with three arguments, as if it were ;; used after `recursive-edit' might override them. (let* ((isearch-regexp regexp-flag) (isearch-word delimited-flag) + (isearch-character-fold-search replace-character-fold) (isearch-lax-whitespace replace-lax-whitespace) (isearch-regexp-lax-whitespace commit 2ca5558395c92b25b58478627b426c66f8e4f170 Author: Glenn Morris Date: Tue Jun 23 14:02:24 2015 -0400 Check for an input event before showing a dialog box. (Bug#20813) * lisp/subr.el (y-or-n-p): * src/fns.c (Fyes_or_no_p): Check last-input-event as well as last-nonmenu-event. diff --git a/lisp/subr.el b/lisp/subr.el index df17310..5d40aaa 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -2348,6 +2348,7 @@ is nil and `use-dialog-box' is non-nil." (t (setq temp-prompt (concat "Please answer y or n. " prompt)))))))) ((and (display-popup-menus-p) + last-input-event ; not during startup (listp last-nonmenu-event) use-dialog-box) (setq prompt (funcall padded prompt t) diff --git a/src/fns.c b/src/fns.c index 6bbb57f..cef2823 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2686,7 +2686,7 @@ if `last-nonmenu-event' is nil, and `use-dialog-box' is non-nil. */) CHECK_STRING (prompt); if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event)) - && use_dialog_box) + && use_dialog_box && ! NILP (last_input_event)) { Lisp_Object pane, menu, obj; redisplay_preserve_echo_area (4); commit abe07ef01ccb61968e6aebc1178dbefb683a27ae Author: Jürgen Hartmann Date: Tue Jun 23 17:43:58 2015 +0200 Respect ‘switch-to-visible-buffer’ more rigidly. (Bug#20861) * lisp/window.el (switch-to-visible-buffer): Doc adjustment. (switch-to-prev-buffer, switch-to-next-buffer): Respect switch-to-visible-buffer independent of the windows history. Copyright-paperwork-exempt: yes diff --git a/lisp/window.el b/lisp/window.el index 6e45711..a4ed9ea 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -3874,12 +3874,10 @@ before was current this also makes BUFFER the current buffer." (defcustom switch-to-visible-buffer t "If non-nil, allow switching to an already visible buffer. If this variable is non-nil, `switch-to-prev-buffer' and -`switch-to-next-buffer' may switch to an already visible buffer -provided the buffer was shown before in the window specified as -argument to those functions. If this variable is nil, -`switch-to-prev-buffer' and `switch-to-next-buffer' always try to -avoid switching to a buffer that is already visible in another -window on the same frame." +`switch-to-next-buffer' may switch to an already visible buffer. +If this variable is nil, `switch-to-prev-buffer' and +`switch-to-next-buffer' always try to avoid switching to a buffer +that is already visible in another window on the same frame." :type 'boolean :version "24.1" :group 'windows) @@ -3950,7 +3948,8 @@ to it." (or (null pred) (funcall pred buffer)) (not (eq (aref (buffer-name buffer) 0) ?\s)) (or bury-or-kill (not (memq buffer next-buffers)))) - (if (get-buffer-window buffer frame) + (if (and (not switch-to-visible-buffer) + (get-buffer-window buffer frame)) ;; Try to avoid showing a buffer visible in some other window. (unless visible (setq visible buffer)) @@ -4052,7 +4051,8 @@ found." (or (null pred) (funcall pred buffer)) (not (eq (aref (buffer-name buffer) 0) ?\s)) (not (assq buffer (window-prev-buffers window)))) - (if (get-buffer-window buffer frame) + (if (and (not switch-to-visible-buffer) + (get-buffer-window buffer frame)) ;; Try to avoid showing a buffer visible in some other window. (setq visible buffer) (setq new-buffer buffer) commit 931f00677dee11d687b99140d25e5373448e329c Author: Paul Eggert Date: Tue Jun 23 07:49:44 2015 -0700 * src/keyboard.c (last_timer_event): Remove unused var. diff --git a/src/keyboard.c b/src/keyboard.c index 9f42ad1..7bfc3f3 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -4372,9 +4372,6 @@ timer_resume_idle (void) timer_idleness_start_time = timer_last_idleness_start_time; } -/* This is only for debugging. */ -struct input_event last_timer_event EXTERNALLY_VISIBLE; - /* List of elisp functions to call, delayed because they were generated in a context where Elisp could not be safely run (e.g. redisplay, signal, ...). Each element has the form (FUN . ARGS). */ commit 8b169764adfd47fea8dd696184e1ab61c63e5c82 Author: Artur Malabarba Date: Tue Jun 23 09:39:27 2015 +0100 * test/automated/package-test.el (package-test-update-listing): Fix test. diff --git a/test/automated/package-test.el b/test/automated/package-test.el index 0e2f2106..5ab2747 100644 --- a/test/automated/package-test.el +++ b/test/automated/package-test.el @@ -305,6 +305,7 @@ Must called from within a `tar-mode' buffer." (search-forward-regexp "^ +simple-single") (package-menu-mark-install) (package-menu-execute) + (run-hooks 'post-command-hook) (should (package-installed-p 'simple-single)) (switch-to-buffer "*Packages*") (goto-char (point-min))