X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/b3bf18b3b87ac8f00857b8bfc3f2c74cf0e2fb7d..7e09ef09a479731d01b1ca46e94ddadd73ac98e3:/src/keyboard.c diff --git a/src/keyboard.c b/src/keyboard.c index 9e14560404..43a0dc9740 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1,6 +1,7 @@ /* Keyboard and mouse input; editor command loop. -Copyright (C) 1985-1989, 1993-1997, 1999-2014 Free Software Foundation, Inc. +Copyright (C) 1985-1989, 1993-1997, 1999-2015 Free Software Foundation, +Inc. This file is part of GNU Emacs. @@ -231,7 +232,7 @@ static ptrdiff_t last_point_position; 'volatile' here. */ Lisp_Object internal_last_event_frame; -static Lisp_Object Qx_set_selection, Qhandle_switch_frame; +static Lisp_Object Qgui_set_selection, Qhandle_switch_frame; static Lisp_Object Qhandle_select_window; Lisp_Object QPRIMARY; @@ -270,9 +271,57 @@ static Lisp_Object Qhelp_form_show; /* File in which we write all commands we read. */ static FILE *dribble; -/* Nonzero if input is available. */ +/* True if input is available. */ bool input_pending; +/* True if more input was available last time we read an event. + + Since redisplay can take a significant amount of time and is not + indispensable to perform the user's commands, when input arrives + "too fast", Emacs skips redisplay. More specifically, if the next + command has already been input when we finish the previous command, + we skip the intermediate redisplay. + + This is useful to try and make sure Emacs keeps up with fast input + rates, such as auto-repeating keys. But in some cases, this proves + too conservative: we may end up disabling redisplay for the whole + duration of a key repetition, even though we could afford to + redisplay every once in a while. + + So we "sample" the input_pending flag before running a command and + use *that* value after running the command to decide whether to + skip redisplay or not. This way, we only skip redisplay if we + really can't keep up with the repeat rate. + + This only makes a difference if the next input arrives while running the + command, which is very unlikely if the command is executed quickly. + IOW this tends to avoid skipping redisplay after a long running command + (which is a case where skipping redisplay is not very useful since the + redisplay time is small compared to the time it took to run the command). + + A typical use case is when scrolling. Scrolling time can be split into: + - Time to do jit-lock on the newly displayed portion of buffer. + - Time to run the actual scroll command. + - Time to perform the redisplay. + Jit-lock can happen either during the command or during the redisplay. + In the most painful cases, the jit-lock time is the one that dominates. + Also jit-lock can be tweaked (via jit-lock-defer) to delay its job, at the + cost of temporary inaccuracy in display and scrolling. + So without input_was_pending, what typically happens is the following: + - when the command starts, there's no pending input (yet). + - the scroll command triggers jit-lock. + - during the long jit-lock time the next input arrives. + - at the end of the command, we check input_pending and hence decide to + skip redisplay. + - we read the next input and start over. + End result: all the hard work of jit-locking is "wasted" since redisplay + doesn't actually happens (at least not before the input rate slows down). + With input_was_pending redisplay is still skipped if Emacs can't keep up + with the input rate, but if it can keep up just enough that there's no + input_pending when we begin the command, then redisplay is not skipped + which results in better feedback to the user. */ +static bool input_was_pending; + /* Circular buffer for pre-read keyboard input. */ static struct input_event kbd_buffer[KBD_BUFFER_SIZE]; @@ -551,6 +600,7 @@ echo_add_key (Lisp_Object c) /* Replace a dash from echo_dash with a space, otherwise add a space at the end as a separator between keys. */ + AUTO_STRING (space, " "); if (STRINGP (echo_string) && SCHARS (echo_string) > 1) { Lisp_Object last_char, prev_char, idx; @@ -566,10 +616,10 @@ echo_add_key (Lisp_Object c) if (XINT (last_char) == '-' && XINT (prev_char) != ' ') Faset (echo_string, idx, make_number (' ')); else - echo_string = concat2 (echo_string, build_string (" ")); + echo_string = concat2 (echo_string, space); } else if (STRINGP (echo_string) && SCHARS (echo_string) > 0) - echo_string = concat2 (echo_string, build_string (" ")); + echo_string = concat2 (echo_string, space); kset_echo_string (current_kboard, @@ -630,9 +680,9 @@ echo_dash (void) /* Put a dash at the end of the buffer temporarily, but make it go away when the next character is added. */ - kset_echo_string - (current_kboard, - concat2 (KVAR (current_kboard, echo_string), build_string ("-"))); + AUTO_STRING (dash, "-"); + kset_echo_string (current_kboard, + concat2 (KVAR (current_kboard, echo_string), dash)); echo_now (); } @@ -1125,7 +1175,7 @@ Default value of `command-error-function'. */) { print_error_message (data, Qexternal_debugging_output, SSDATA (context), signal); - Fterpri (Qexternal_debugging_output); + Fterpri (Qexternal_debugging_output, Qnil); Fkill_emacs (make_number (-1)); } else @@ -1285,13 +1335,9 @@ tracking_off (Lisp_Object old_value) } } -DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0, - doc: /* Evaluate BODY with mouse movement events enabled. -Within a `track-mouse' form, mouse motion generates input events that -you can read with `read-event'. -Normally, mouse motion is ignored. -usage: (track-mouse BODY...) */) - (Lisp_Object args) +DEFUN ("internal--track-mouse", Ftrack_mouse, Strack_mouse, 1, 1, 0, + doc: /* Call BODYFUN with mouse movement events enabled. */) + (Lisp_Object bodyfun) { ptrdiff_t count = SPECPDL_INDEX (); Lisp_Object val; @@ -1300,7 +1346,7 @@ usage: (track-mouse BODY...) */) do_mouse_tracking = Qt; - val = Fprogn (args); + val = call0 (bodyfun); return unbind_to (count, val); } @@ -1537,6 +1583,13 @@ command_loop_1 (void) /* Execute the command. */ + { + total_keys += total_keys < NUM_RECENT_KEYS; + ASET (recent_keys, recent_keys_index, + Fcons (Qnil, cmd)); + if (++recent_keys_index >= NUM_RECENT_KEYS) + recent_keys_index = 0; + } Vthis_command = cmd; Vreal_this_command = cmd; safe_run_hooks (Qpre_command_hook); @@ -1656,7 +1709,7 @@ command_loop_1 (void) = call1 (Fsymbol_value (Qregion_extract_function), Qnil); if (XINT (Flength (txt)) > 0) /* Don't set empty selections. */ - call2 (Qx_set_selection, QPRIMARY, txt); + call2 (Qgui_set_selection, QPRIMARY, txt); } if (current_buffer != prev_buffer || MODIFF != prev_modiff) @@ -1894,16 +1947,11 @@ safe_run_hooks_1 (ptrdiff_t nargs, Lisp_Object *args) static Lisp_Object safe_run_hooks_error (Lisp_Object error, ptrdiff_t nargs, Lisp_Object *args) { - Lisp_Object hook, fun, msgargs[4]; - eassert (nargs == 2); - hook = args[0]; - fun = args[1]; - msgargs[0] = build_string ("Error in %s (%S): %S"); - msgargs[1] = hook; - msgargs[2] = fun; - msgargs[3] = error; - Fmessage (4, msgargs); + AUTO_STRING (format, "Error in %s (%S): %S"); + Lisp_Object hook = args[0]; + Lisp_Object fun = args[1]; + Fmessage (4, (Lisp_Object []) {format, hook, fun, error}); if (SYMBOLP (hook)) { @@ -2355,7 +2403,7 @@ read_decoded_event_from_main_queue (struct timespec *end_time, struct coding_system *coding = TERMINAL_KEYBOARD_CODING (terminal); unsigned char src[MAX_ENCODED_BYTES]; - unsigned char dest[4 * sizeof src]; + unsigned char dest[MAX_ENCODED_BYTES * MAX_MULTIBYTE_LENGTH]; int i; for (i = 0; i < n; i++) src[i] = XINT (events[i]); @@ -2363,7 +2411,7 @@ read_decoded_event_from_main_queue (struct timespec *end_time, for (i = 0; i < n; i++) src[i] &= ~0x80; coding->destination = dest; - coding->dst_bytes = n * 4; + coding->dst_bytes = sizeof dest; decode_coding_c_string (coding, src, n, Qnil); eassert (coding->produced_char <= n); if (coding->produced_char == 0) @@ -2404,9 +2452,9 @@ echo_keystrokes_p (void) /* commandflag 0 means do not autosave, but do redisplay. -1 means do not redisplay, but do autosave. -2 means do neither. - 1 means do both. */ + 1 means do both. -/* The argument MAP is a keymap for menu prompting. + The argument MAP is a keymap for menu prompting. PREV_EVENT is the previous input event, or nil if we are reading the first event of a key sequence (or not reading a key sequence). @@ -2583,11 +2631,13 @@ read_char (int commandflag, Lisp_Object map, user-visible, such as X selection_request events. */ if (input_pending || detect_input_pending_run_timers (0)) - swallow_events (0); /* May clear input_pending. */ + swallow_events (false); /* May clear input_pending. */ /* Redisplay if no pending input. */ - while (!input_pending) + while (!(input_pending + && (input_was_pending || !redisplay_dont_pause))) { + input_was_pending = input_pending; if (help_echo_showing_p && !EQ (selected_window, minibuf_window)) redisplay_preserve_echo_area (5); else @@ -2599,7 +2649,7 @@ read_char (int commandflag, Lisp_Object map, /* Input arrived and pre-empted redisplay. Process any events which are not user-visible. */ - swallow_events (0); + swallow_events (false); /* If that cleared input_pending, try again to redisplay. */ } @@ -3256,6 +3306,7 @@ read_char (int commandflag, Lisp_Object map, exit: RESUME_POLLING; + input_was_pending = input_pending; RETURN_UNGCPRO (c); } @@ -3503,7 +3554,8 @@ readable_events (int flags) && event->part == scroll_bar_handle && event->modifiers == 0) #endif - ) + && !((flags & READABLE_EVENTS_FILTER_EVENTS) + && event->kind == BUFFER_SWITCH_EVENT)) return 1; event++; if (event == kbd_buffer + KBD_BUFFER_SIZE) @@ -3732,6 +3784,34 @@ kbd_buffer_unget_event (register struct input_event *event) } } +/* 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, \ + MOST_POSITIVE_FIXNUM))) +#define INPUT_EVENT_POS_MIN (-1 - INPUT_EVENT_POS_MAX) + +/* Return a Time that encodes position POS. POS must be in range. */ + +static Time +position_to_Time (ptrdiff_t pos) +{ + eassert (INPUT_EVENT_POS_MIN <= pos && pos <= INPUT_EVENT_POS_MAX); + return pos; +} + +/* Return the position that ENCODED_POS encodes. + Avoid signed integer overflow. */ + +static ptrdiff_t +Time_to_position (Time encoded_pos) +{ + if (encoded_pos <= INPUT_EVENT_POS_MAX) + return encoded_pos; + Time encoded_pos_min = INPUT_EVENT_POS_MIN; + eassert (encoded_pos_min <= encoded_pos); + ptrdiff_t notpos = -1 - encoded_pos; + return -1 - notpos; +} /* Generate a HELP_EVENT input_event and store it in the keyboard buffer. @@ -3750,14 +3830,12 @@ gen_help_event (Lisp_Object help, Lisp_Object frame, Lisp_Object window, { struct input_event event; - EVENT_INIT (event); - event.kind = HELP_EVENT; event.frame_or_window = frame; event.arg = object; event.x = WINDOWP (window) ? window : frame; event.y = help; - event.code = pos; + event.timestamp = position_to_Time (pos); kbd_buffer_store_event (&event); } @@ -3774,7 +3852,7 @@ kbd_buffer_store_help_event (Lisp_Object frame, Lisp_Object help) event.arg = Qnil; event.x = Qnil; event.y = help; - event.code = 0; + event.timestamp = 0; kbd_buffer_store_event (&event); } @@ -3852,7 +3930,7 @@ kbd_buffer_get_event (KBOARD **kbp, Lisp_Object obj; #ifdef subprocesses - if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE/4) + if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE / 4) { /* Start reading input again because we have processed enough to be able to accept new events again. */ @@ -4089,7 +4167,7 @@ kbd_buffer_get_event (KBOARD **kbp, frame = event->frame_or_window; object = event->arg; - position = make_number (event->code); + position = make_number (Time_to_position (event->timestamp)); window = event->x; help = event->y; clear_event (event); @@ -4344,7 +4422,7 @@ swallow_events (bool do_display) old_timers_run = timers_run; get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW); - if (timers_run != old_timers_run && do_display) + if (!input_pending && timers_run != old_timers_run && do_display) redisplay_preserve_echo_area (7); } @@ -4403,10 +4481,15 @@ decode_timer (Lisp_Object timer, struct timespec *result) vector = XVECTOR (timer)->contents; if (! NILP (vector[0])) return 0; + if (! INTEGERP (vector[2])) + return false; - return (decode_time_components (vector[1], vector[2], vector[3], vector[8], - result, 0) - && timespec_valid_p (*result)); + struct lisp_time t; + if (! decode_time_components (vector[1], vector[2], vector[3], vector[8], + &t, 0)) + return false; + *result = lisp_to_timespec (t); + return timespec_valid_p (*result); } @@ -5199,14 +5282,15 @@ static const char *const lispy_drag_n_drop_names[] = static Lisp_Object Qabove_handle, Qhandle, Qbelow_handle; static Lisp_Object Qbefore_handle, Qhorizontal_handle, Qafter_handle; Lisp_Object Qup, Qdown, Qtop, Qbottom; -Lisp_Object Qleft, Qright; static Lisp_Object Qleftmost, Qrightmost; static Lisp_Object Qend_scroll; static Lisp_Object Qratio; -/* An array of scroll bar parts, indexed by an enum scroll_bar_part value. */ +/* An array of scroll bar parts, indexed by an enum scroll_bar_part value. + Note that Qnil corresponds to scroll_bar_nowhere and should not appear + in Lisp events. */ static Lisp_Object *const scroll_bar_parts[] = { - &Qabove_handle, &Qhandle, &Qbelow_handle, + &Qnil, &Qabove_handle, &Qhandle, &Qbelow_handle, &Qup, &Qdown, &Qtop, &Qbottom, &Qend_scroll, &Qratio, &Qbefore_handle, &Qhorizontal_handle, &Qafter_handle, &Qleft, &Qright, &Qleftmost, &Qrightmost, &Qend_scroll, &Qratio @@ -5313,12 +5397,14 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, &object, &dx, &dy, &width, &height); if (STRINGP (string)) string_info = Fcons (string, make_number (charpos)); + xret = wx; yret = wy - WINDOW_HEADER_LINE_HEIGHT (w); } else if (part == ON_LEFT_FRINGE) { posn = Qleft_fringe; col = 0; + xret = wx; dx = wx - (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? 0 : window_box_width (w, LEFT_MARGIN_AREA)); @@ -5328,6 +5414,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, { posn = Qright_fringe; col = 0; + xret = wx; dx = wx - window_box_width (w, LEFT_MARGIN_AREA) - window_box_width (w, TEXT_AREA) @@ -5341,9 +5428,23 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, posn = Qvertical_line; width = 1; dx = 0; + xret = wx; + dy = yret = wy; + } + else if (part == ON_VERTICAL_SCROLL_BAR) + { + posn = Qvertical_scroll_bar; + width = WINDOW_SCROLL_BAR_AREA_WIDTH (w); + dx = xret = wx; + dy = yret = wy; + } + else if (part == ON_HORIZONTAL_SCROLL_BAR) + { + posn = Qhorizontal_scroll_bar; + width = WINDOW_SCROLL_BAR_AREA_HEIGHT (w); + dx = xret = wx; dy = yret = wy; } - /* Nothing special for part == ON_SCROLL_BAR. */ else if (part == ON_RIGHT_DIVIDER) { posn = Qright_divider; @@ -5427,7 +5528,12 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, extra_info))); } else if (f != 0) - XSETFRAME (window, f); + { + /* Return mouse pixel coordinates here. */ + XSETFRAME (window, f); + xret = XINT (x); + yret = XINT (y); + } else window = Qnil; @@ -5453,6 +5559,16 @@ toolkit_menubar_in_use (struct frame *f) #endif } +/* Build the part of Lisp event which represents scroll bar state from + EV. TYPE is one of Qvertical_scroll_bar or Qhorizontal_scroll_bar. */ + +static Lisp_Object +make_scroll_bar_position (struct input_event *ev, Lisp_Object type) +{ + return list5 (ev->frame_or_window, type, Fcons (ev->x, ev->y), + make_number (ev->timestamp), *scroll_bar_parts[ev->part]); +} + /* Given a struct input_event, build the lisp event which represents it. If EVENT is 0, build a mouse movement event from the mouse movement buffer, which should have a movement event in it. @@ -5541,30 +5657,27 @@ make_lispy_event (struct input_event *event) ARRAYELTS (iso_lispy_function_keys)); #endif - /* Handle system-specific or unknown keysyms. */ - if (event->code & (1 << 28) - || event->code - FUNCTION_KEY_OFFSET < 0 - || (event->code - FUNCTION_KEY_OFFSET - >= ARRAYELTS (lispy_function_keys)) - || !lispy_function_keys[event->code - FUNCTION_KEY_OFFSET]) - { - /* We need to use an alist rather than a vector as the cache - since we can't make a vector long enough. */ - if (NILP (KVAR (current_kboard, system_key_syms))) - kset_system_key_syms (current_kboard, Fcons (Qnil, Qnil)); - return modify_event_symbol (event->code, - event->modifiers, - Qfunction_key, - KVAR (current_kboard, Vsystem_key_alist), - 0, &KVAR (current_kboard, system_key_syms), - PTRDIFF_MAX); - } - - return modify_event_symbol (event->code - FUNCTION_KEY_OFFSET, + if ((FUNCTION_KEY_OFFSET <= event->code + && (event->code + < FUNCTION_KEY_OFFSET + ARRAYELTS (lispy_function_keys))) + && lispy_function_keys[event->code - FUNCTION_KEY_OFFSET]) + return modify_event_symbol (event->code - FUNCTION_KEY_OFFSET, + event->modifiers, + Qfunction_key, Qnil, + lispy_function_keys, &func_key_syms, + ARRAYELTS (lispy_function_keys)); + + /* Handle system-specific or unknown keysyms. + We need to use an alist rather than a vector as the cache + since we can't make a vector long enough. */ + if (NILP (KVAR (current_kboard, system_key_syms))) + kset_system_key_syms (current_kboard, Fcons (Qnil, Qnil)); + return modify_event_symbol (event->code, event->modifiers, - Qfunction_key, Qnil, - lispy_function_keys, &func_key_syms, - ARRAYELTS (lispy_function_keys)); + Qfunction_key, + KVAR (current_kboard, Vsystem_key_alist), + 0, &KVAR (current_kboard, system_key_syms), + PTRDIFF_MAX); #ifdef HAVE_NTGUI case MULTIMEDIA_KEY_EVENT: @@ -5670,20 +5783,8 @@ make_lispy_event (struct input_event *event) } #ifndef USE_TOOLKIT_SCROLL_BARS else - { - /* It's a scrollbar click. */ - Lisp_Object window; - Lisp_Object portion_whole; - Lisp_Object part; - - window = event->frame_or_window; - portion_whole = Fcons (event->x, event->y); - part = *scroll_bar_parts[(int) event->part]; - - position = list5 (window, Qvertical_scroll_bar, - portion_whole, make_number (event->timestamp), - part); - } + /* It's a scrollbar click. */ + position = make_scroll_bar_position (event, Qvertical_scroll_bar); #endif /* not USE_TOOLKIT_SCROLL_BARS */ if (button >= ASIZE (button_down_location)) @@ -5960,14 +6061,9 @@ make_lispy_event (struct input_event *event) case SCROLL_BAR_CLICK_EVENT: { - Lisp_Object position, head, window, portion_whole, part; - - window = event->frame_or_window; - portion_whole = Fcons (event->x, event->y); - part = *scroll_bar_parts[(int) event->part]; + Lisp_Object position, head; - position = list5 (window, Qvertical_scroll_bar, portion_whole, - make_number (event->timestamp), part); + position = make_scroll_bar_position (event, Qvertical_scroll_bar); /* Always treat scroll bar events as clicks. */ event->modifiers |= click_modifier; @@ -5990,14 +6086,9 @@ make_lispy_event (struct input_event *event) case HORIZONTAL_SCROLL_BAR_CLICK_EVENT: { - Lisp_Object position, head, window, portion_whole, part; + Lisp_Object position, head; - window = event->frame_or_window; - portion_whole = Fcons (event->x, event->y); - part = *scroll_bar_parts[(int) event->part]; - - position = list5 (window, Qhorizontal_scroll_bar, portion_whole, - make_number (event->timestamp), part); + position = make_scroll_bar_position (event, Qhorizontal_scroll_bar); /* Always treat scroll bar events as clicks. */ event->modifiers |= click_modifier; @@ -7879,11 +7970,12 @@ parse_menu_item (Lisp_Object item, int inmenubar) { /* This is a command. See if there is an equivalent key binding. */ Lisp_Object keyeq = AREF (item_properties, ITEM_PROPERTY_KEYEQ); + AUTO_STRING (space_space, " "); /* The previous code preferred :key-sequence to :keys, so we preserve this behavior. */ if (STRINGP (keyeq) && !CONSP (keyhint)) - keyeq = concat2 (build_string (" "), Fsubstitute_command_keys (keyeq)); + keyeq = concat2 (space_space, Fsubstitute_command_keys (keyeq)); else { Lisp_Object prefix = keyeq; @@ -7926,8 +8018,7 @@ parse_menu_item (Lisp_Object item, int inmenubar) if (STRINGP (XCDR (prefix))) tem = concat2 (tem, XCDR (prefix)); } - keyeq = concat2 (build_string (" "), tem); - /* keyeq = concat3(build_string(" ("),tem,build_string(")")); */ + keyeq = concat2 (space_space, tem); } else keyeq = Qnil; @@ -8513,7 +8604,7 @@ static Lisp_Object read_char_minibuf_menu_prompt (int commandflag, Lisp_Object map) { - register Lisp_Object name; + Lisp_Object name; ptrdiff_t nlength; /* FIXME: Use the minibuffer's frame width. */ ptrdiff_t width = FRAME_COLS (SELECTED_FRAME ()) - 4; @@ -8631,10 +8722,14 @@ read_char_minibuf_menu_prompt (int commandflag, /* Insert button prefix. */ Lisp_Object selected = AREF (item_properties, ITEM_PROPERTY_SELECTED); + AUTO_STRING (radio_yes, "(*) "); + AUTO_STRING (radio_no , "( ) "); + AUTO_STRING (check_yes, "[X] "); + AUTO_STRING (check_no , "[ ] "); if (EQ (tem, QCradio)) - tem = build_string (NILP (selected) ? "(*) " : "( ) "); + tem = NILP (selected) ? radio_yes : radio_no; else - tem = build_string (NILP (selected) ? "[X] " : "[ ] "); + tem = NILP (selected) ? check_yes : check_no; s = concat2 (tem, s); } @@ -10017,23 +10112,34 @@ If CHECK-TIMERS is non-nil, timers that are ready to run will do so. */) ? Qt : Qnil); } -DEFUN ("recent-keys", Frecent_keys, Srecent_keys, 0, 0, 0, - doc: /* Return vector of last 300 events, not counting those from keyboard macros. */) - (void) +DEFUN ("recent-keys", Frecent_keys, Srecent_keys, 0, 1, 0, + doc: /* Return vector of last few events, not counting those from keyboard macros. +If INCLUDE-CMDS is non-nil, include the commands that were run, +represented as events of the form (nil . COMMAND). */) + (Lisp_Object include_cmds) { - Lisp_Object *keys = XVECTOR (recent_keys)->contents; - Lisp_Object val; + bool cmds = !NILP (include_cmds); - if (total_keys < NUM_RECENT_KEYS) - return Fvector (total_keys, keys); + if (!total_keys + || (cmds && total_keys < NUM_RECENT_KEYS)) + return Fvector (total_keys, + XVECTOR (recent_keys)->contents); else { - val = Fvector (NUM_RECENT_KEYS, keys); - vcopy (val, 0, keys + recent_keys_index, - NUM_RECENT_KEYS - recent_keys_index); - vcopy (val, NUM_RECENT_KEYS - recent_keys_index, - keys, recent_keys_index); - return val; + Lisp_Object es = Qnil; + int i = (total_keys < NUM_RECENT_KEYS + ? 0 : recent_keys_index); + eassert (recent_keys_index < NUM_RECENT_KEYS); + do + { + Lisp_Object e = AREF (recent_keys, i); + if (cmds || !CONSP (e) || !NILP (XCAR (e))) + es = Fcons (e, es); + if (++i >= NUM_RECENT_KEYS) + i = 0; + } while (i != recent_keys_index); + es = Fnreverse (es); + return Fvconcat (1, &es); } } @@ -10341,7 +10447,7 @@ static void handle_interrupt_signal (int sig) { /* See if we have an active terminal on our controlling tty. */ - struct terminal *terminal = get_named_tty ("/dev/tty"); + struct terminal *terminal = get_named_terminal ("/dev/tty"); if (!terminal) { /* If there are no frames there, let's pretend that we are a @@ -10395,7 +10501,7 @@ handle_interrupt (bool in_signal_handler) cancel_echoing (); /* XXX This code needs to be revised for multi-tty support. */ - if (!NILP (Vquit_flag) && get_named_tty ("/dev/tty")) + if (!NILP (Vquit_flag) && get_named_terminal ("/dev/tty")) { if (! in_signal_handler) { @@ -10607,9 +10713,10 @@ Emacs reads input in CBREAK mode; see `set-input-interrupt-mode'. See also `current-input-mode'. */) (Lisp_Object flow, Lisp_Object terminal) { - struct terminal *t = get_terminal (terminal, 1); + struct terminal *t = decode_tty_terminal (terminal); struct tty_display_info *tty; - if (t == NULL || (t->type != output_termcap && t->type != output_msdos_raw)) + + if (!t) return Qnil; tty = t->display_info.tty; @@ -10649,11 +10756,11 @@ the currently selected frame. See also `current-input-mode'. */) (Lisp_Object meta, Lisp_Object terminal) { - struct terminal *t = get_terminal (terminal, 1); + struct terminal *t = decode_tty_terminal (terminal); struct tty_display_info *tty; int new_meta; - if (t == NULL || (t->type != output_termcap && t->type != output_msdos_raw)) + if (!t) return Qnil; tty = t->display_info.tty; @@ -10690,9 +10797,10 @@ process. See also `current-input-mode'. */) (Lisp_Object quit) { - struct terminal *t = get_named_tty ("/dev/tty"); + struct terminal *t = get_named_terminal ("/dev/tty"); struct tty_display_info *tty; - if (t == NULL || (t->type != output_termcap && t->type != output_msdos_raw)) + + if (!t) return Qnil; tty = t->display_info.tty; @@ -11134,7 +11242,7 @@ syms_of_keyboard (void) DEFSYM (Qpolling_period, "polling-period"); - DEFSYM (Qx_set_selection, "x-set-selection"); + DEFSYM (Qgui_set_selection, "gui-set-selection"); DEFSYM (QPRIMARY, "PRIMARY"); DEFSYM (Qhandle_switch_frame, "handle-switch-frame"); DEFSYM (Qhandle_select_window, "handle-select-window"); @@ -11812,7 +11920,7 @@ keys_of_keyboard (void) - we enter the second prompt. current-prefix-arg is non-nil, prefix-arg is nil. - before running the first real event, we run the special iconify-frame - event, but we pass the `special' arg to execute-command so + event, but we pass the `special' arg to command-execute so current-prefix-arg and prefix-arg are left untouched. - here we foolishly copy the non-nil current-prefix-arg to prefix-arg. - the next key event will have a spuriously non-nil current-prefix-arg. */