X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/2b17d5ed901666e8ceebcaddd448c490d48ae2b6..3c9dc1cf0d6be64608cd309ad042d74e4fc02049:/src/keyboard.c diff --git a/src/keyboard.c b/src/keyboard.c index 76101090d4..9260a17574 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1,5 +1,5 @@ /* Keyboard and mouse input; editor command loop. - Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99, 2000, 01, 02 + Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99,2000,01,02,03 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -145,6 +145,10 @@ Lisp_Object recent_keys; /* A vector, holding the last 100 keystrokes */ Lisp_Object this_command_keys; int this_command_key_count; +/* 1 after calling Freset_this_command_lengths. + Usually it is 0. */ +int this_command_key_count_reset; + /* This vector is used as a buffer to record the events that were actually read by read_key_sequence. */ Lisp_Object raw_keybuf; @@ -169,13 +173,6 @@ int this_single_command_key_start; before this command was read. */ static int before_command_key_count; static int before_command_echo_length; -/* Values of before_command_key_count and before_command_echo_length - saved by reset-this-command-lengths. */ -static int before_command_key_count_1; -static int before_command_echo_length_1; -/* Flag set by reset-this-command-lengths, - saying to reset the lengths when add_command_key is called. */ -static int before_command_restore_flag; extern int minbuf_level; @@ -412,7 +409,7 @@ Lisp_Object Vecho_keystrokes; /* Form to evaluate (if non-nil) when Emacs is started. */ Lisp_Object Vtop_level; -/* User-supplied string to translate input characters through. */ +/* User-supplied table to translate input characters. */ Lisp_Object Vkeyboard_translate_table; /* Keymap mapping ASCII function key sequences onto their preferred forms. */ @@ -598,11 +595,12 @@ Lisp_Object Fthis_command_keys (); Lisp_Object Qextended_command_history; EMACS_TIME timer_check (); -extern Lisp_Object Vhistory_length; +extern Lisp_Object Vhistory_length, Vtranslation_table_for_input; extern char *x_get_keysym_name (); static void record_menu_key (); +static int echo_length (); Lisp_Object Qpolling_period; @@ -706,6 +704,7 @@ static void restore_getcjmp P_ ((jmp_buf)); static Lisp_Object apply_modifiers P_ ((int, Lisp_Object)); static void clear_event P_ ((struct input_event *)); static void any_kboard_state P_ ((void)); +static SIGTYPE interrupt_signal P_ ((int signalnum)); /* Nonzero means don't try to suspend even if the operating system seems to support it. */ @@ -740,7 +739,7 @@ echo_char (c) Lisp_Object echo_string; echo_string = current_kboard->echo_string; - + /* If someone has passed us a composite event, use its head symbol. */ c = EVENT_HEAD (c); @@ -752,7 +751,7 @@ echo_char (c) { Lisp_Object name = SYMBOL_NAME (c); int nbytes = SBYTES (name); - + if (size - (ptr - buffer) < nbytes) { int offset = ptr - buffer; @@ -770,7 +769,7 @@ echo_char (c) { const char *text = " (Type ? for further options)"; int len = strlen (text); - + if (size - (ptr - buffer) < len) { int offset = ptr - buffer; @@ -786,14 +785,19 @@ echo_char (c) /* Replace a dash from echo_dash with a space, otherwise add a space at the end as a separator between keys. */ if (STRINGP (echo_string) - && SCHARS (echo_string) > 0) + && SCHARS (echo_string) > 1) { - Lisp_Object last_char, idx; + Lisp_Object last_char, prev_char, idx; + + idx = make_number (SCHARS (echo_string) - 2); + prev_char = Faref (echo_string, idx); idx = make_number (SCHARS (echo_string) - 1); last_char = Faref (echo_string, idx); - if (XINT (last_char) == '-') + /* We test PREV_CHAR to make sure this isn't the echoing + of a minus-sign. */ + if (XINT (last_char) == '-' && XINT (prev_char) != ' ') Faset (echo_string, idx, make_number (' ')); else echo_string = concat2 (echo_string, build_string (" ")); @@ -819,12 +823,12 @@ echo_dash () if (!current_kboard->immediate_echo && SCHARS (current_kboard->echo_string) == 0) return; - + /* Do nothing if we just printed a prompt. */ if (current_kboard->echo_after_prompt == SCHARS (current_kboard->echo_string)) return; - + /* Put a dash at the end of the buffer temporarily, but make it go away when the next character is added. */ current_kboard->echo_string = concat2 (current_kboard->echo_string, @@ -846,11 +850,26 @@ echo_now () for (i = 0; i < this_command_key_count; i++) { Lisp_Object c; + + /* Set before_command_echo_length to the value that would + have been saved before the start of this subcommand in + command_loop_1, if we had already been echoing then. */ + if (i == this_single_command_key_start) + before_command_echo_length = echo_length (); + c = XVECTOR (this_command_keys)->contents[i]; if (! (EVENT_HAS_PARAMETERS (c) && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement))) echo_char (c); } + + /* Set before_command_echo_length to the value that would + have been saved before the start of this subcommand in + command_loop_1, if we had already been echoing then. */ + if (this_command_key_count == this_single_command_key_start) + before_command_echo_length = echo_length (); + + /* Put a dash at the end to invite the user to type more. */ echo_dash (); } @@ -912,6 +931,8 @@ static void add_command_key (key) Lisp_Object key; { +#if 0 /* Not needed after we made Freset_this_command_lengths + do the job immediately. */ /* If reset-this-command-length was called recently, obey it now. See the doc string of that function for an explanation of why. */ if (before_command_restore_flag) @@ -922,6 +943,7 @@ add_command_key (key) echo_truncate (before_command_echo_length_1); before_command_restore_flag = 0; } +#endif if (this_command_key_count >= ASIZE (this_command_keys)) this_command_keys = larger_vector (this_command_keys, @@ -1031,12 +1053,12 @@ recursive_edit_unwind (info) { if (BUFFERP (XCAR (info))) Fset_buffer (XCAR (info)); - + if (NILP (XCDR (info))) any_kboard_state (); else single_kboard_state (); - + command_loop_level--; update_mode_lines = 1; return Qnil; @@ -1213,7 +1235,7 @@ cmd_error_internal (data, context) since they are asyncronous. */ if (EQ (XCAR (data), Qquit)) Vsignaling_function = Qnil; - + print_error_message (data, stream, context, Vsignaling_function); Vsignaling_function = Qnil; @@ -1334,7 +1356,18 @@ DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0, static int read_key_sequence P_ ((Lisp_Object *, int, Lisp_Object, int, int, int)); void safe_run_hooks P_ ((Lisp_Object)); -static void adjust_point_for_property P_ ((int)); +static void adjust_point_for_property P_ ((int, int)); + +/* Cancel hourglass from protect_unwind. + ARG is not used. */ +#ifdef HAVE_X_WINDOWS +static Lisp_Object +cancel_hourglass_unwind (arg) + Lisp_Object arg; +{ + cancel_hourglass (); +} +#endif Lisp_Object command_loop_1 () @@ -1350,6 +1383,7 @@ command_loop_1 () #ifdef MULTI_KBOARD int was_locked = single_kboard; #endif + int already_adjusted; current_kboard->Vprefix_arg = Qnil; current_kboard->Vlast_prefix_arg = Qnil; @@ -1359,6 +1393,7 @@ command_loop_1 () nonundocount = 0; this_command_key_count = 0; + this_command_key_count_reset = 0; this_single_command_key_start = 0; if (NILP (Vmemory_full)) @@ -1491,6 +1526,7 @@ command_loop_1 () { cancel_echoing (); this_command_key_count = 0; + this_command_key_count_reset = 0; this_single_command_key_start = 0; goto finalize; } @@ -1543,7 +1579,7 @@ command_loop_1 () if (SYMBOLP (cmd)) { Lisp_Object cmd1; - if (cmd1 = Fremap_command (cmd), !NILP (cmd1)) + if (cmd1 = Fcommand_remapping (cmd), !NILP (cmd1)) cmd = cmd1; } @@ -1555,7 +1591,9 @@ command_loop_1 () if the symbol is a local variable. */ if (!NILP (Vpre_command_hook) && !NILP (Vrun_hooks)) safe_run_hooks (Qpre_command_hook); - + + already_adjusted = 0; + if (NILP (Vthis_command)) { /* nil means key is undefined. */ @@ -1579,12 +1617,23 @@ command_loop_1 () = window_display_table (XWINDOW (selected_window)); lose = FETCH_CHAR (PT_BYTE); SET_PT (PT + 1); - if ((dp - ? (VECTORP (DISP_CHAR_VECTOR (dp, lose)) - ? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1 - : (NILP (DISP_CHAR_VECTOR (dp, lose)) - && (lose >= 0x20 && lose < 0x7f))) - : (lose >= 0x20 && lose < 0x7f)) + if (! NILP (Vpost_command_hook)) + /* Put this before calling adjust_point_for_property + so it will only get called once in any case. */ + goto directly_done; + if (current_buffer == prev_buffer + && last_point_position != PT + && NILP (Vdisable_point_adjustment) + && NILP (Vglobal_disable_point_adjustment)) + adjust_point_for_property (last_point_position, 0); + already_adjusted = 1; + if (PT == last_point_position + 1 + && (dp + ? (VECTORP (DISP_CHAR_VECTOR (dp, lose)) + ? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1 + : (NILP (DISP_CHAR_VECTOR (dp, lose)) + && (lose >= 0x20 && lose < 0x7f))) + : (lose >= 0x20 && lose < 0x7f)) /* To extract the case of continuation on wide-column characters. */ && (WIDTH_BY_CHAR_HEAD (FETCH_BYTE (PT_BYTE)) == 1) @@ -1608,12 +1657,21 @@ command_loop_1 () = window_display_table (XWINDOW (selected_window)); SET_PT (PT - 1); lose = FETCH_CHAR (PT_BYTE); - if ((dp - ? (VECTORP (DISP_CHAR_VECTOR (dp, lose)) - ? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1 - : (NILP (DISP_CHAR_VECTOR (dp, lose)) - && (lose >= 0x20 && lose < 0x7f))) - : (lose >= 0x20 && lose < 0x7f)) + if (! NILP (Vpost_command_hook)) + goto directly_done; + if (current_buffer == prev_buffer + && last_point_position != PT + && NILP (Vdisable_point_adjustment) + && NILP (Vglobal_disable_point_adjustment)) + adjust_point_for_property (last_point_position, 0); + already_adjusted = 1; + if (PT == last_point_position - 1 + && (dp + ? (VECTORP (DISP_CHAR_VECTOR (dp, lose)) + ? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1 + : (NILP (DISP_CHAR_VECTOR (dp, lose)) + && (lose >= 0x20 && lose < 0x7f))) + : (lose >= 0x20 && lose < 0x7f)) && (XFASTINT (XWINDOW (selected_window)->last_modified) >= MODIFF) && (XFASTINT (XWINDOW (selected_window)->last_overlay_modified) @@ -1629,10 +1687,13 @@ command_loop_1 () goto directly_done; } else if (EQ (Vthis_command, Qself_insert_command) - /* Try this optimization only on ascii keystrokes. */ - && INTEGERP (last_command_char)) + /* Try this optimization only on char keystrokes. */ + && NATNUMP (last_command_char) + && CHAR_VALID_P (XFASTINT (last_command_char), 0)) { - unsigned int c = XINT (last_command_char); + unsigned int c + = translate_char (Vtranslation_table_for_input, + XFASTINT (last_command_char), 0, 0, 0); int value; if (NILP (Vexecuting_macro) && !EQ (minibuf_window, selected_window)) @@ -1644,7 +1705,7 @@ command_loop_1 () } nonundocount++; } - + lose = ((XFASTINT (XWINDOW (selected_window)->last_modified) < MODIFF) || (XFASTINT (XWINDOW (selected_window)->last_overlay_modified) @@ -1657,12 +1718,17 @@ command_loop_1 () || detect_input_pending () || !NILP (XWINDOW (selected_window)->column_number_displayed) || !NILP (Vexecuting_macro)); - + value = internal_self_insert (c, 0); if (value == 2) nonundocount = 0; + if (! NILP (Vpost_command_hook)) + /* Put this before calling adjust_point_for_property + so it will only get called once in any case. */ + goto directly_done; + /* VALUE == 1 when AFTER-CHANGE functions are installed which is the case most of the time because FONT-LOCK installs one. */ @@ -1674,16 +1740,22 @@ command_loop_1 () /* Here for a command that isn't executed directly */ + { #ifdef HAVE_X_WINDOWS - if (display_hourglass_p - && NILP (Vexecuting_macro)) - start_hourglass (); + int scount = SPECPDL_INDEX (); + + if (display_hourglass_p + && NILP (Vexecuting_macro)) + { + record_unwind_protect (cancel_hourglass_unwind, Qnil); + start_hourglass (); + } #endif - nonundocount = 0; - if (NILP (current_kboard->Vprefix_arg)) - Fundo_boundary (); - Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil); + nonundocount = 0; + if (NILP (current_kboard->Vprefix_arg)) + Fundo_boundary (); + Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil); #ifdef HAVE_X_WINDOWS /* Do not check display_hourglass_p here, because @@ -1692,8 +1764,9 @@ command_loop_1 () But don't cancel the hourglass within a macro just because a command in the macro finishes. */ if (NILP (Vexecuting_macro)) - cancel_hourglass (); + unbind_to (scount, Qnil); #endif + } } directly_done: ; current_kboard->Vlast_prefix_arg = Vcurrent_prefix_arg; @@ -1740,6 +1813,7 @@ command_loop_1 () current_kboard->Vreal_last_command = real_this_command; cancel_echoing (); this_command_key_count = 0; + this_command_key_count_reset = 0; this_single_command_key_start = 0; } @@ -1765,8 +1839,9 @@ command_loop_1 () if (current_buffer == prev_buffer && last_point_position != PT && NILP (Vdisable_point_adjustment) - && NILP (Vglobal_disable_point_adjustment)) - adjust_point_for_property (last_point_position); + && NILP (Vglobal_disable_point_adjustment) + && !already_adjusted) + adjust_point_for_property (last_point_position, MODIFF != prev_modiff); /* Install chars successfully executed in kbd macro. */ @@ -1785,47 +1860,131 @@ extern Lisp_Object Qcomposition, Qdisplay; /* Adjust point to a boundary of a region that has such a property that should be treated intangible. For the moment, we check - `composition' and `display' property. LAST_PT is the last position - of point. */ + `composition', `display' and `invisible' properties. + LAST_PT is the last position of point. */ + +extern Lisp_Object Qafter_string, Qbefore_string; +extern Lisp_Object get_pos_property P_ ((Lisp_Object, Lisp_Object, Lisp_Object)); static void -adjust_point_for_property (last_pt) +adjust_point_for_property (last_pt, modified) int last_pt; + int modified; { - int start, end; - Lisp_Object val; - int check_composition = 1, check_display = 1; + int beg, end; + Lisp_Object val, overlay, tmp; + int check_composition = 1, check_display = 1, check_invisible = 1; + int orig_pt = PT; - while (check_composition || check_display) + /* FIXME: cycling is probably not necessary because these properties + can't be usefully combined anyway. */ + while (check_composition || check_display || check_invisible) { if (check_composition && PT > BEGV && PT < ZV - && get_property_and_range (PT, Qcomposition, &val, &start, &end, Qnil) - && COMPOSITION_VALID_P (start, end, val) - && start < PT && end > PT - && (last_pt <= start || last_pt >= end)) + && get_property_and_range (PT, Qcomposition, &val, &beg, &end, Qnil) + && COMPOSITION_VALID_P (beg, end, val) + && beg < PT /* && end > PT <- It's always the case. */ + && (last_pt <= beg || last_pt >= end)) { - if (PT < last_pt) - SET_PT (start); - else - SET_PT (end); - check_display = 1; + xassert (end > PT); + SET_PT (PT < last_pt ? beg : end); + check_display = check_invisible = 1; } check_composition = 0; if (check_display && PT > BEGV && PT < ZV - && get_property_and_range (PT, Qdisplay, &val, &start, &end, Qnil) + && !NILP (val = get_char_property_and_overlay + (make_number (PT), Qdisplay, Qnil, &overlay)) && display_prop_intangible_p (val) - && start < PT && end > PT - && (last_pt <= start || last_pt >= end)) + && (!OVERLAYP (overlay) + ? get_property_and_range (PT, Qdisplay, &val, &beg, &end, Qnil) + : (beg = OVERLAY_POSITION (OVERLAY_START (overlay)), + end = OVERLAY_POSITION (OVERLAY_END (overlay)))) + && beg < PT) /* && end > PT <- It's always the case. */ { - if (PT < last_pt) - SET_PT (start); - else - SET_PT (end); - check_composition = 1; + xassert (end > PT); + SET_PT (PT < last_pt ? beg : end); + check_composition = check_invisible = 1; } check_display = 0; + if (check_invisible && PT > BEGV && PT < ZV) + { + int inv, ellipsis = 0; + beg = end = PT; + + /* Find boundaries `beg' and `end' of the invisible area, if any. */ + while (end < ZV + && !NILP (val = get_char_property_and_overlay + (make_number (end), Qinvisible, Qnil, &overlay)) + && (inv = TEXT_PROP_MEANS_INVISIBLE (val))) + { + ellipsis = ellipsis || inv > 1 + || (OVERLAYP (overlay) + && (!NILP (Foverlay_get (overlay, Qafter_string)) + || !NILP (Foverlay_get (overlay, Qbefore_string)))); + tmp = Fnext_single_char_property_change + (make_number (end), Qinvisible, Qnil, Qnil); + end = NATNUMP (tmp) ? XFASTINT (tmp) : ZV; + } + while (beg > BEGV + && !NILP (val = get_char_property_and_overlay + (make_number (beg - 1), Qinvisible, Qnil, &overlay)) + && (inv = TEXT_PROP_MEANS_INVISIBLE (val))) + { + ellipsis = ellipsis || inv > 1 + || (OVERLAYP (overlay) + && (!NILP (Foverlay_get (overlay, Qafter_string)) + || !NILP (Foverlay_get (overlay, Qbefore_string)))); + tmp = Fprevious_single_char_property_change + (make_number (beg), Qinvisible, Qnil, Qnil); + beg = NATNUMP (tmp) ? XFASTINT (tmp) : BEGV; + } + + /* Move away from the inside area. */ + if (beg < PT && end > PT) + { + SET_PT ((orig_pt == PT && (last_pt < beg || last_pt > end)) + /* We haven't moved yet (so we don't need to fear + infinite-looping) and we were outside the range + before (so either end of the range still corresponds + to a move in the right direction): pretend we moved + less than we actually did, so that we still have + more freedom below in choosing which end of the range + to go to. */ + ? (orig_pt = -1, PT < last_pt ? end : beg) + /* We either have moved already or the last point + was already in the range: we don't get to choose + which end of the range we have to go to. */ + : (PT < last_pt ? beg : end)); + check_composition = check_display = 1; + } + xassert (PT == beg || PT == end); + /* Pretend the area doesn't exist if the buffer is not + modified. */ + if (!modified && !ellipsis && beg < end) + { + if (last_pt == beg && PT == end && end < ZV) + (check_composition = check_display = 1, SET_PT (end + 1)); + else if (last_pt == end && PT == beg && beg > BEGV) + (check_composition = check_display = 1, SET_PT (beg - 1)); + else if (PT == ((PT < last_pt) ? beg : end)) + /* We've already moved as far as we can. Trying to go + to the other end would mean moving backwards and thus + could lead to an infinite loop. */ + ; + else if (val = get_pos_property (make_number (PT), + Qinvisible, Qnil), + TEXT_PROP_MEANS_INVISIBLE (val) + && (val = get_pos_property + (make_number (PT == beg ? end : beg), + Qinvisible, Qnil), + !TEXT_PROP_MEANS_INVISIBLE (val))) + (check_composition = check_display = 1, + SET_PT (PT == beg ? end : beg)); + } + } + check_invisible = 0; } } @@ -1844,6 +2003,11 @@ static Lisp_Object safe_run_hooks_error (data) Lisp_Object data; { + Lisp_Object args[3]; + args[0] = build_string ("Error in %s: %s"); + args[1] = Vinhibit_quit; + args[2] = data; + Fmessage (3, args); return Fset (Vinhibit_quit, Qnil); } @@ -1917,7 +2081,7 @@ start_polling () /* Turn alarm handling on unconditionally. It might have been turned off in process.c. */ turn_on_atimers (1); - + /* If poll timer doesn't exist, are we need one with a different interval, start a new one. */ if (poll_timer == NULL @@ -1927,7 +2091,7 @@ start_polling () if (poll_timer) cancel_atimer (poll_timer); - + EMACS_SET_SECS_USECS (interval, polling_period, 0); poll_timer = start_atimer (ATIMER_CONTINUOUS, interval, poll_for_input, NULL); @@ -2088,7 +2252,7 @@ show_help_echo (help, window, object, pos, ok_to_overwrite_keystroke_echo) } else help = safe_eval (help); - + if (!STRINGP (help)) return; } @@ -2111,7 +2275,7 @@ show_help_echo (help, window, object, pos, ok_to_overwrite_keystroke_echo) if (!help_echo_showing_p) Vpre_help_message = current_message (); - + specbind (Qmessage_truncate_lines, Qt); message3_nolog (help, SBYTES (help), STRING_MULTIBYTE (help)); @@ -2127,7 +2291,7 @@ show_help_echo (help, window, object, pos, ok_to_overwrite_keystroke_echo) else message (0); } - + help_echo_showing_p = STRINGP (help); } } @@ -2144,6 +2308,14 @@ static void record_char (); static jmp_buf wrong_kboard_jmpbuf; #endif +#define STOP_POLLING \ +do { if (! polling_stopped_here) stop_polling (); \ + polling_stopped_here = 1; } while (0) + +#define RESUME_POLLING \ +do { if (polling_stopped_here) start_polling (); \ + polling_stopped_here = 0; } while (0) + /* read a character from the keyboard; call the redisplay if needed */ /* commandflag 0 means do not do auto-saving, but do do redisplay. -1 means do not do redisplay, but do do autosaving. @@ -2183,11 +2355,14 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) volatile int reread; struct gcpro gcpro1, gcpro2; EMACS_TIME last_idle_start; + int polling_stopped_here = 0; also_record = Qnil; +#if 0 /* This was commented out as part of fixing echo for C-u left. */ before_command_key_count = this_command_key_count; before_command_echo_length = echo_length (); +#endif c = Qnil; previous_echo_area_message = Qnil; @@ -2233,13 +2408,13 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) && EQ (XCDR (c), Qdisabled) && (SYMBOLP (XCAR (c)) || INTEGERP (XCAR (c)))) c = XCAR (c); - + /* If the queued event is something that used the mouse, set used_mouse_menu accordingly. */ if (used_mouse_menu && (EQ (c, Qtool_bar) || EQ (c, Qmenu_bar))) *used_mouse_menu = 1; - + reread = 1; goto reread_for_input_method; } @@ -2259,9 +2434,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) goto reread_for_input_method; } - /* If there is no function key translated before - reset-this-command-lengths takes effect, forget about it. */ - before_command_restore_flag = 0; + this_command_key_count_reset = 0; if (!NILP (Vexecuting_macro)) { @@ -2284,7 +2457,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) || executing_macro_index >= XFASTINT (Flength (Vexecuting_macro))) { XSETINT (c, -1); - RETURN_UNGCPRO (c); + goto exit; } c = Faref (Vexecuting_macro, make_number (executing_macro_index)); @@ -2336,7 +2509,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) } /* Message turns off echoing unless more keystrokes turn it on again. - + The code in 20.x for the condition was 1. echo_area_glyphs && *echo_area_glyphs @@ -2344,10 +2517,10 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) 3. && ok_to_echo_at_next_pause != echo_area_glyphs (1) means there's a current message displayed - + (2) means it's not the message from echoing from the current kboard. - + (3) There's only one place in 20.x where ok_to_echo_at_next_pause is set to a non-null value. This is done in read_char and it is set to echo_area_glyphs after a call to echo_char. That means @@ -2359,7 +2532,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) must be either null, or the current message isn't from echoing at all, or it's from echoing from a different kboard than the current one. */ - + if (/* There currently is something in the echo area. */ !NILP (echo_area_buffer[0]) && (/* And it's either not from echoing. */ @@ -2371,7 +2544,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) cancel_echoing (); else echo_dash (); - + /* Try reading a character via menu prompting in the minibuf. Try this before the sit-for, because the sit-for would do the wrong thing if we are supposed to do @@ -2446,7 +2619,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) /* If in middle of key sequence and minibuffer not active, start echoing if enough time elapses. */ - if (minibuf_level == 0 + if (minibuf_level == 0 && !current_kboard->immediate_echo && this_command_key_count > 0 && ! noninteractive @@ -2463,7 +2636,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) || (!echo_kboard && ok_to_echo_at_next_pause))) { Lisp_Object tem0; - + /* After a mouse event, start echoing right away. This is because we are probably about to display a menu, and we don't want to delay before doing so. */ @@ -2516,7 +2689,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) /* Now that we have read an event, Emacs is not idle. */ timer_stop_idle (); - RETURN_UNGCPRO (c); + goto exit; } /* Maybe autosave and/or garbage collect due to idleness. */ @@ -2623,7 +2796,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) wrong_kboard: - stop_polling (); + STOP_POLLING; /* Finally, we read from the main queue, and if that gives us something we can't use yet, we put it on the @@ -2692,7 +2865,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) should the next event read be a help-echo. */ last_idle_start = timer_idleness_start_time; timer_stop_idle (); - start_polling (); + RESUME_POLLING; if (NILP (c)) { @@ -2709,7 +2882,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) so don't show them to the user. Also, don't record a key if we already did. */ if (BUFFERP (c) || key_already_recorded) - RETURN_UNGCPRO (c); + goto exit; /* Process special events within read_char and loop around to read another event. */ @@ -2744,14 +2917,14 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) { /* If kbd_buffer_get_event gave us an EOF, return that. */ if (XINT (c) == -1) - RETURN_UNGCPRO (c); + goto exit; if ((STRINGP (Vkeyboard_translate_table) && SCHARS (Vkeyboard_translate_table) > (unsigned) XFASTINT (c)) || (VECTORP (Vkeyboard_translate_table) && XVECTOR (Vkeyboard_translate_table)->size > (unsigned) XFASTINT (c)) || (CHAR_TABLE_P (Vkeyboard_translate_table) - && CHAR_TABLE_ORDINARY_SLOTS > (unsigned) XFASTINT (c))) + && CHAR_VALID_P (XINT (c), 0))) { Lisp_Object d; d = Faref (Vkeyboard_translate_table, c); @@ -2827,8 +3000,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) && (unsigned) XINT (c) != 127 && (unsigned) XINT (c) < 256) { - Lisp_Object keys; - int key_count; + Lisp_Object keys; + int key_count, key_count_reset; struct gcpro gcpro1; int count = SPECPDL_INDEX (); @@ -2837,6 +3010,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) struct kboard *saved_ok_to_echo = ok_to_echo_at_next_pause; int saved_echo_after_prompt = current_kboard->echo_after_prompt; +#if 0 if (before_command_restore_flag) { this_command_key_count = before_command_key_count_1; @@ -2845,9 +3019,11 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) echo_truncate (before_command_echo_length_1); before_command_restore_flag = 0; } +#endif /* Save the this_command_keys status. */ key_count = this_command_key_count; + key_count_reset = this_command_key_count_reset; if (key_count > 0) keys = Fcopy_sequence (this_command_keys); @@ -2857,6 +3033,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) /* Clear out this_command_keys. */ this_command_key_count = 0; + this_command_key_count_reset = 0; /* Now wipe the echo area. */ if (!NILP (echo_area_buffer[0])) @@ -2879,6 +3056,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) /* Restore the saved echoing state and this_command_keys state. */ this_command_key_count = key_count; + this_command_key_count_reset = key_count_reset; if (key_count > 0) this_command_keys = keys; @@ -2927,11 +3105,10 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) timer_idleness_start_time = last_idle_start; goto retry; } - - if (this_command_key_count == 0 || ! reread) + + if (! reread || this_command_key_count == 0 + || this_command_key_count_reset) { - before_command_key_count = this_command_key_count; - before_command_echo_length = echo_length (); /* Don't echo mouse motion events. */ if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes)) @@ -2986,6 +3163,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) } } + exit: + RESUME_POLLING; RETURN_UNGCPRO (c); } @@ -3001,8 +3180,10 @@ record_menu_key (c) record_char (c); +#if 0 before_command_key_count = this_command_key_count; before_command_echo_length = echo_length (); +#endif /* Don't echo mouse motion events. */ if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes)) @@ -3057,19 +3238,19 @@ record_char (c) Lisp_Object ev1, ev2, ev3; int ix1, ix2, ix3; - + if ((ix1 = recent_keys_index - 1) < 0) ix1 = NUM_RECENT_KEYS - 1; ev1 = AREF (recent_keys, ix1); - + if ((ix2 = ix1 - 1) < 0) ix2 = NUM_RECENT_KEYS - 1; ev2 = AREF (recent_keys, ix2); - + if ((ix3 = ix2 - 1) < 0) ix3 = NUM_RECENT_KEYS - 1; ev3 = AREF (recent_keys, ix3); - + if (EQ (XCAR (c), Qhelp_echo)) { /* Don't record `help-echo' in recent_keys unless it shows some help @@ -3140,7 +3321,7 @@ record_char (c) } num_nonmacro_input_events++; - + /* Write c to the dribble file. If c is a lispy event, write the event's symbol to the dribble file, in . Bleaugh. If you, dear reader, have a better idea, you've got the source. :-) */ @@ -3385,7 +3566,6 @@ kbd_buffer_store_event (event) if (c == quit_char) { - static SIGTYPE interrupt_signal P_ ((int)); #ifdef MULTI_KBOARD KBOARD *kb; struct input_event *sp; @@ -3456,7 +3636,7 @@ kbd_buffer_store_event (event) if (kbd_fetch_ptr - 1 != kbd_store_ptr) { int idx; - + #if 0 /* The SELECTION_REQUEST_EVENT case looks bogus, and it's error prone to assign individual members for other events, in case the input_event structure is changed. --2000-07-13, gerd. */ @@ -3580,7 +3760,7 @@ kbd_buffer_events_waiting (discard) int discard; { struct input_event *sp; - + for (sp = kbd_fetch_ptr; sp != kbd_store_ptr && sp->kind == NO_EVENT; ++sp) @@ -3776,7 +3956,8 @@ kbd_buffer_get_event (kbp, used_mouse_menu) XSETBUFFER (obj, current_buffer); kbd_fetch_ptr = event + 1; } -#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ + || defined (USE_GTK) else if (event->kind == MENU_BAR_ACTIVATE_EVENT) { kbd_fetch_ptr = event + 1; @@ -3844,14 +4025,6 @@ kbd_buffer_get_event (kbp, used_mouse_menu) && !EQ (frame, selected_frame)) obj = make_lispy_switch_frame (frame); internal_last_event_frame = frame; - kbd_fetch_ptr = event + 1; - } - else if (event->kind == SELECT_WINDOW_EVENT) - { - /* Make an event (select-window (WINDOW)). */ - obj = Fcons (event->frame_or_window, Qnil); - obj = Fcons (Qselect_window, Fcons (obj, Qnil)); - kbd_fetch_ptr = event + 1; } else @@ -3882,8 +4055,9 @@ kbd_buffer_get_event (kbp, used_mouse_menu) if (NILP (obj)) { obj = make_lispy_event (event); - -#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined(MAC_OS) + +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined(MAC_OS) \ + || defined (USE_GTK) /* If this was a menu selection, then set the flag to inhibit writing to last_nonmenu_event. Don't do this if the event we're returning is (menu-bar), though; that indicates the @@ -4212,7 +4386,7 @@ timer_check (do_it_now) difference = idle_timer_difference; } vector = XVECTOR (chosen_timer)->contents; - + /* If timer is ripe, run it if it hasn't been run. */ if (EMACS_TIME_NEG_P (difference) || (EMACS_SECS (difference) == 0 @@ -4229,7 +4403,7 @@ timer_check (do_it_now) vector[0] = Qt; specbind (Qinhibit_quit, Qt); - + call1 (Qtimer_event_handler, chosen_timer); Vdeactivate_mark = old_deactivate_mark; timers_run++; @@ -4337,6 +4511,41 @@ static int lispy_accent_codes[] = #else 0, #endif +#ifdef XK_dead_abovering + XK_dead_abovering, +#else + 0, +#endif +#ifdef XK_dead_iota + XK_dead_iota, +#else + 0, +#endif +#ifdef XK_dead_belowdot + XK_dead_belowdot, +#else + 0, +#endif +#ifdef XK_dead_voiced_sound + XK_dead_voiced_sound, +#else + 0, +#endif +#ifdef XK_dead_semivoiced_sound + XK_dead_semivoiced_sound, +#else + 0, +#endif +#ifdef XK_dead_hook + XK_dead_hook, +#else + 0, +#endif +#ifdef XK_dead_horn + XK_dead_horn, +#else + 0, +#endif }; /* This is a list of Lisp names for special "accent" characters. @@ -4357,6 +4566,13 @@ static char *lispy_accent_keys[] = "dead-caron", "dead-doubleacute", "dead-abovedot", + "dead-abovering", + "dead-iota", + "dead-belowdot", + "dead-voiced-sound", + "dead-semivoiced-sound", + "dead-hook", + "dead-horn", }; #ifdef HAVE_NTGUI @@ -4365,36 +4581,36 @@ static char *lispy_accent_keys[] = char *lispy_function_keys[] = { 0, /* 0 */ - + 0, /* VK_LBUTTON 0x01 */ 0, /* VK_RBUTTON 0x02 */ "cancel", /* VK_CANCEL 0x03 */ 0, /* VK_MBUTTON 0x04 */ - + 0, 0, 0, /* 0x05 .. 0x07 */ - + "backspace", /* VK_BACK 0x08 */ "tab", /* VK_TAB 0x09 */ - + 0, 0, /* 0x0A .. 0x0B */ - + "clear", /* VK_CLEAR 0x0C */ "return", /* VK_RETURN 0x0D */ - + 0, 0, /* 0x0E .. 0x0F */ - + 0, /* VK_SHIFT 0x10 */ 0, /* VK_CONTROL 0x11 */ 0, /* VK_MENU 0x12 */ "pause", /* VK_PAUSE 0x13 */ "capslock", /* VK_CAPITAL 0x14 */ - + 0, 0, 0, 0, 0, 0, /* 0x15 .. 0x1A */ - + "escape", /* VK_ESCAPE 0x1B */ - + 0, 0, 0, 0, /* 0x1C .. 0x1F */ - + 0, /* VK_SPACE 0x20 */ "prior", /* VK_PRIOR 0x21 */ "next", /* VK_NEXT 0x22 */ @@ -4411,25 +4627,25 @@ char *lispy_function_keys[] = "insert", /* VK_INSERT 0x2D */ "delete", /* VK_DELETE 0x2E */ "help", /* VK_HELP 0x2F */ - + /* VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */ - + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + 0, 0, 0, 0, 0, 0, 0, /* 0x3A .. 0x40 */ - + /* VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */ - - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + "lwindow", /* VK_LWIN 0x5B */ "rwindow", /* VK_RWIN 0x5C */ "apps", /* VK_APPS 0x5D */ - + 0, 0, /* 0x5E .. 0x5F */ - + "kp-0", /* VK_NUMPAD0 0x60 */ "kp-1", /* VK_NUMPAD1 0x61 */ "kp-2", /* VK_NUMPAD2 0x62 */ @@ -4470,13 +4686,13 @@ char *lispy_function_keys[] = "f22", /* VK_F22 0x85 */ "f23", /* VK_F23 0x86 */ "f24", /* VK_F24 0x87 */ - + 0, 0, 0, 0, /* 0x88 .. 0x8B */ 0, 0, 0, 0, /* 0x8C .. 0x8F */ - + "kp-numlock", /* VK_NUMLOCK 0x90 */ "scroll", /* VK_SCROLL 0x91 */ - + "kp-space", /* VK_NUMPAD_CLEAR 0x92 */ "kp-enter", /* VK_NUMPAD_ENTER 0x93 */ "kp-prior", /* VK_NUMPAD_PRIOR 0x94 */ @@ -4498,17 +4714,17 @@ char *lispy_function_keys[] = * No other API or message will distinguish left and right keys this way. */ /* 0xA0 .. 0xEF */ - + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + /* 0xF0 .. 0xF5 */ - + 0, 0, 0, 0, 0, 0, - + "attn", /* VK_ATTN 0xF6 */ "crsel", /* VK_CRSEL 0xF7 */ "exsel", /* VK_EXSEL 0xF8 */ @@ -4523,6 +4739,10 @@ char *lispy_function_keys[] = #else /* not HAVE_NTGUI */ +/* This should be dealt with in XTread_socket now, and that doesn't + depend on the client system having the Kana syms defined. See also + the XK_kana_A case below. */ +#if 0 #ifdef XK_kana_A static char *lispy_kana_keys[] = { @@ -4537,7 +4757,7 @@ static char *lispy_kana_keys[] = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,"overline",0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x480 .. 0x48f */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x490 .. 0x49f */ - 0, "kana-fullstop", "kana-openingbracket", "kana-closingbracket", + 0, "kana-fullstop", "kana-openingbracket", "kana-closingbracket", "kana-comma", "kana-conjunctive", "kana-WO", "kana-a", "kana-i", "kana-u", "kana-e", "kana-o", "kana-ya", "kana-yu", "kana-yo", "kana-tsu", @@ -4557,6 +4777,7 @@ static char *lispy_kana_keys[] = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x4f0 .. 0x4ff */ }; #endif /* XK_kana_A */ +#endif /* 0 */ #define FUNCTION_KEY_OFFSET 0xff00 @@ -4655,9 +4876,9 @@ static char *iso_lispy_function_keys[] = 0, 0, 0, 0, 0, 0, 0, 0, /* 0xfe10 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xfe18 */ "iso-lefttab", /* 0xfe20 */ - "iso-move-line-up", "iso-move-line-down", - "iso-partial-line-up", "iso-partial-line-down", - "iso-partial-space-left", "iso-partial-space-right", + "iso-move-line-up", "iso-move-line-down", + "iso-partial-line-up", "iso-partial-line-down", + "iso-partial-space-left", "iso-partial-space-right", "iso-set-margin-left", "iso-set-margin-right", /* 0xffe27, 28 */ "iso-release-margin-left", "iso-release-margin-right", "iso-release-both-margins", @@ -4679,7 +4900,7 @@ Lisp_Object Vlispy_mouse_stem; which they operate, and a delta corresponding to the amount and direction that the wheel is rotated. Clicking the mouse-wheel generates a mouse-2 event. */ -static char *lispy_mouse_wheel_names[] = +static char *lispy_mouse_wheel_names[] = { "mouse-wheel" }; @@ -4792,8 +5013,17 @@ make_lispy_event (event) case MULTIBYTE_CHAR_KEYSTROKE_EVENT: { Lisp_Object lispy_c; + int c = event->code; - XSETFASTINT (lispy_c, event->code); + /* Add in the other modifier bits. We took care of ctrl_modifier + just above, and the shift key was taken care of by the X code, + and applied to control characters by make_ctrl_char. */ + c |= (event->modifiers + & (meta_modifier | alt_modifier + | hyper_modifier | super_modifier | ctrl_modifier)); + /* What about the `shift' modifier ? */ + button_down_time = 0; + XSETFASTINT (lispy_c, c); return lispy_c; } @@ -4811,6 +5041,7 @@ make_lispy_event (event) (sizeof (lispy_accent_keys) / sizeof (lispy_accent_keys[0]))); +#if 0 #ifdef XK_kana_A if (event->code >= 0x400 && event->code < 0x500) return modify_event_symbol (event->code - 0x400, @@ -4820,6 +5051,7 @@ make_lispy_event (event) (sizeof (lispy_kana_keys) / sizeof (lispy_kana_keys[0]))); #endif /* XK_kana_A */ +#endif /* 0 */ #ifdef ISO_FUNCTION_KEY_OFFSET if (event->code < FUNCTION_KEY_OFFSET @@ -4878,11 +5110,12 @@ make_lispy_event (event) /* Build the position as appropriate for this mouse click. */ if (event->kind == MOUSE_CLICK_EVENT) { - int part; + enum window_part part; struct frame *f = XFRAME (event->frame_or_window); Lisp_Object posn; Lisp_Object string_info = Qnil; int row, column; + int wx, wy; /* Ignore mouse events that were made on frame that have been deleted. */ @@ -4897,7 +5130,7 @@ make_lispy_event (event) pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y), &column, &row, NULL, 1); -#ifndef USE_X_TOOLKIT +#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) /* In the non-toolkit version, clicks on the menu bar are ordinary button events in the event buffer. Distinguish them, and invoke the menu. @@ -4949,12 +5182,13 @@ make_lispy_event (event) return Fcons (item, Fcons (position, Qnil)); } -#endif /* not USE_X_TOOLKIT */ +#endif /* not USE_X_TOOLKIT && not USE_GTK */ /* Set `window' to the window under frame pixel coordinates event->x/event->y. */ window = window_from_coordinates (f, XINT (event->x), - XINT (event->y), &part, 0); + XINT (event->y), + &part, &wx, &wy, 0); if (!WINDOWP (window)) { @@ -4967,36 +5201,31 @@ make_lispy_event (event) event->x/ event->y. */ struct window *w = XWINDOW (window); - /* Get window relative coordinates. Original code - `rounded' this to glyph boundaries. */ - int wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (event->x)); - int wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (event->y)); - /* Set event coordinates to window-relative coordinates for constructing the Lisp event below. */ XSETINT (event->x, wx); XSETINT (event->y, wy); - if (part == 1 || part == 3) + if (part == ON_MODE_LINE || part == ON_HEADER_LINE) { /* Mode line or header line. Look for a string under the mouse that may have a `local-map' property. */ Lisp_Object string; int charpos; - - posn = part == 1 ? Qmode_line : Qheader_line; - string = mode_line_string (w, wx, wy, part == 1, &charpos); + + posn = part == ON_MODE_LINE ? Qmode_line : Qheader_line; + string = mode_line_string (w, wx, wy, part, &charpos); if (STRINGP (string)) string_info = Fcons (string, make_number (charpos)); } - else if (part == 2) + else if (part == ON_VERTICAL_BORDER) posn = Qvertical_line; - else if (part == 6 || part == 7) + else if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN) { int charpos; Lisp_Object object = marginal_area_string (w, wx, wy, part, &charpos); - posn = (part == 6) ? Qleft_margin : Qright_margin; + posn = (part == ON_LEFT_MARGIN) ? Qleft_margin : Qright_margin; if (STRINGP (object)) string_info = Fcons (object, make_number (charpos)); } @@ -5048,7 +5277,7 @@ make_lispy_event (event) button + 1, Qnil); mouse_syms = larger_vector (mouse_syms, button + 1, Qnil); } - + start_pos_ptr = &AREF (button_down_location, button); start_pos = *start_pos_ptr; *start_pos_ptr = Qnil; @@ -5081,7 +5310,7 @@ make_lispy_event (event) && ((int)(event->timestamp - button_down_time) < XINT (Vdouble_click_time))))); } - + last_mouse_button = button; last_mouse_x = XINT (event->x); last_mouse_y = XINT (event->y); @@ -5146,7 +5375,7 @@ make_lispy_event (event) button_down_time = 0; event->modifiers |= drag_modifier; } - + /* Don't check is_double; treat this as multiple if the down-event was multiple. */ if (double_click_count > 1) @@ -5205,7 +5434,7 @@ make_lispy_event (event) The incoming input_event contains in its `part' member an index of type `enum scroll_bar_part' which we can use as an index in scroll_bar_parts to get the appropriate symbol. */ - + case SCROLL_BAR_CLICK_EVENT: { Lisp_Object position, head, window, portion_whole, part; @@ -5225,16 +5454,19 @@ make_lispy_event (event) event->modifiers |= click_modifier; event->modifiers &= ~up_modifier; + if (event->code >= ASIZE (mouse_syms)) + mouse_syms = larger_vector (mouse_syms, event->code + 1, Qnil); + /* Get the symbol we should use for the mouse click. */ head = modify_event_symbol (event->code, event->modifiers, - Qmouse_click, + Qmouse_click, Vlispy_mouse_stem, NULL, &mouse_syms, XVECTOR (mouse_syms)->size); return Fcons (head, Fcons (position, Qnil)); } - + #endif /* USE_TOOLKIT_SCROLL_BARS */ #ifdef WINDOWSNT @@ -5272,7 +5504,7 @@ make_lispy_event (event) head = modify_event_symbol (button, event->modifiers, - Qmouse_click, + Qmouse_click, Vlispy_mouse_stem, NULL, &mouse_syms, XVECTOR (mouse_syms)->size); @@ -5282,10 +5514,10 @@ make_lispy_event (event) } } #endif /* WINDOWSNT */ -#if defined(WINDOWSNT) || defined(MAC_OSX) +#if defined(MAC_OSX) case MOUSE_WHEEL_EVENT: { - int part; + enum window_part part; FRAME_PTR f = XFRAME (event->frame_or_window); Lisp_Object window; Lisp_Object posn; @@ -5299,7 +5531,8 @@ make_lispy_event (event) pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y), &column, &row, NULL, 1); window = window_from_coordinates (f, XINT (event->x), - XINT (event->y), &part, 0); + XINT (event->y), + &part, 0, 0, 0); if (!WINDOWP (window)) { @@ -5309,18 +5542,18 @@ make_lispy_event (event) else { int pixcolumn, pixrow; - column -= XINT (XWINDOW (window)->left); - row -= XINT (XWINDOW (window)->top); + column -= WINDOW_LEFT_EDGE_COL (XWINDOW (window)); + row -= WINDOW_TOP_EDGE_LINE (XWINDOW (window)); glyph_to_pixel_coords (XWINDOW(window), column, row, &pixcolumn, &pixrow); XSETINT (event->x, pixcolumn); XSETINT (event->y, pixrow); - if (part == 1) + if (part == ON_MODE_LINE) posn = Qmode_line; - else if (part == 2) + else if (part == ON_VERTICAL_BORDER) posn = Qvertical_line; - else if (part == 3) + else if (part == ON_HEADER_LINE) posn = Qheader_line; else { @@ -5354,15 +5587,16 @@ make_lispy_event (event) Qnil)))); } } -#endif /* WINDOWSNT || MAC_OSX */ +#endif /* MAC_OSX */ case DRAG_N_DROP_EVENT: { - int part; + enum window_part part; FRAME_PTR f; Lisp_Object window; Lisp_Object posn; Lisp_Object files; + int wx, wy; /* The frame_or_window field should be a cons of the frame in which the event occurred and a list of the filenames @@ -5379,7 +5613,8 @@ make_lispy_event (event) return Qnil; window = window_from_coordinates (f, XINT (event->x), - XINT (event->y), &part, 0); + XINT (event->y), + &part, &wx, &wy, 0); if (!WINDOWP (window)) { @@ -5392,20 +5627,16 @@ make_lispy_event (event) event->x/ event->y. */ struct window *w = XWINDOW (window); - /* Get window relative coordinates. */ - int wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (event->x)); - int wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (event->y)); - /* Set event coordinates to window-relative coordinates for constructing the Lisp event below. */ XSETINT (event->x, wx); XSETINT (event->y, wy); - if (part == 1) + if (part == ON_MODE_LINE) posn = Qmode_line; - else if (part == 2) + else if (part == ON_VERTICAL_BORDER) posn = Qvertical_line; - else if (part == 3) + else if (part == ON_HEADER_LINE) posn = Qheader_line; else { @@ -5438,7 +5669,8 @@ make_lispy_event (event) } #endif /* HAVE_MOUSE */ -#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ + || defined (USE_GTK) case MENU_BAR_EVENT: if (EQ (event->arg, event->frame_or_window)) /* This is the prefix key. We translate this to @@ -5448,6 +5680,12 @@ make_lispy_event (event) return event->arg; #endif + case SELECT_WINDOW_EVENT: + /* Make an event (select-window (WINDOW)). */ + return Fcons (Qselect_window, + Fcons (Fcons (event->frame_or_window, Qnil), + Qnil)); + case TOOL_BAR_EVENT: if (EQ (event->arg, event->frame_or_window)) /* This is the prefix key. We translate this to @@ -5461,10 +5699,10 @@ make_lispy_event (event) case USER_SIGNAL_EVENT: /* A user signal. */ return *lispy_user_signals[event->code]; - + case SAVE_SESSION_EVENT: return Qsave_session; - + /* The 'kind' field of the event is something we don't recognize. */ default: abort (); @@ -5500,32 +5738,31 @@ make_lispy_movement (frame, bar_window, part, x, y, time) /* Or is it an ordinary mouse movement? */ else { - int area; + enum window_part area; Lisp_Object window; Lisp_Object posn; + int wx, wy; if (frame) /* It's in a frame; which window on that frame? */ - window = window_from_coordinates (frame, XINT (x), XINT (y), &area, 0); + window = window_from_coordinates (frame, XINT (x), XINT (y), + &area, &wx, &wy, 0); else window = Qnil; if (WINDOWP (window)) { struct window *w = XWINDOW (window); - int wx, wy; - - /* Get window relative coordinates. */ - wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (x)); - wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (y)); + + /* Set window relative coordinates. */ XSETINT (x, wx); XSETINT (y, wy); - - if (area == 1) + + if (area == ON_MODE_LINE) posn = Qmode_line; - else if (area == 2) + else if (area == ON_VERTICAL_BORDER) posn = Qvertical_line; - else if (area == 3) + else if (area == ON_HEADER_LINE) posn = Qheader_line; else { @@ -5631,6 +5868,26 @@ parse_modifiers_uncached (symbol, modifier_end) break; #undef SINGLE_LETTER_MOD + +#define MULTI_LETTER_MOD(BIT, NAME, LEN) \ + if (i + LEN + 1 <= SBYTES (name) \ + && ! strncmp (SDATA (name) + i, NAME, LEN)) \ + { \ + this_mod_end = i + LEN; \ + this_mod = BIT; \ + } + + case 'd': + MULTI_LETTER_MOD (drag_modifier, "drag", 4); + MULTI_LETTER_MOD (down_modifier, "down", 4); + MULTI_LETTER_MOD (double_modifier, "double", 6); + break; + + case 't': + MULTI_LETTER_MOD (triple_modifier, "triple", 6); + break; +#undef MULTI_LETTER_MOD + } /* If we found no modifier, stop looking for them. */ @@ -5829,12 +6086,15 @@ apply_modifiers (modifiers, base) entry = Fcons (index, new_symbol); Fput (base, Qmodifier_cache, Fcons (entry, cache)); - /* We have the parsing info now for free, so add it to the caches. */ - XSETFASTINT (index, modifiers); - Fput (new_symbol, Qevent_symbol_element_mask, - Fcons (base, Fcons (index, Qnil))); - Fput (new_symbol, Qevent_symbol_elements, - Fcons (base, lispy_modifier_list (modifiers))); + /* We have the parsing info now for free, so we could add it to + the caches: + XSETFASTINT (index, modifiers); + Fput (new_symbol, Qevent_symbol_element_mask, + Fcons (base, Fcons (index, Qnil))); + Fput (new_symbol, Qevent_symbol_elements, + Fcons (base, lispy_modifier_list (modifiers))); + Sadly, this is only correct if `base' is indeed a base event, + which is not necessarily the case. -stef */ } /* Make sure this symbol is of the same kind as BASE. @@ -5963,8 +6223,12 @@ modify_event_symbol (symbol_num, modifiers, symbol_kind, name_alist_or_stem, { int len = SBYTES (name_alist_or_stem); char *buf = (char *) alloca (len + 50); - sprintf (buf, "%s-%d", SDATA (name_alist_or_stem), - XINT (symbol_int) + 1); + if (sizeof (int) == sizeof (EMACS_INT)) + sprintf (buf, "%s-%d", SDATA (name_alist_or_stem), + XINT (symbol_int) + 1); + else if (sizeof (long) == sizeof (EMACS_INT)) + sprintf (buf, "%s-%ld", SDATA (name_alist_or_stem), + XINT (symbol_int) + 1); value = intern (buf); } else if (name_table != 0 && name_table[symbol_num]) @@ -6358,7 +6622,7 @@ read_avail_input (expected) if (n_to_read > sizeof cbuf) n_to_read = sizeof cbuf; #else /* no FIONREAD */ -#if defined (USG) || defined (DGUX) +#if defined (USG) || defined (DGUX) || defined(CYGWIN) /* Read some input if available, but don't wait. */ n_to_read = sizeof cbuf; fcntl (input_fd, F_SETFL, O_NDELAY); @@ -6415,9 +6679,9 @@ read_avail_input (expected) ); #ifndef FIONREAD -#if defined (USG) || defined (DGUX) +#if defined (USG) || defined (DGUX) || defined (CYGWIN) fcntl (input_fd, F_SETFL, 0); -#endif /* USG or DGUX */ +#endif /* USG or DGUX or CYGWIN */ #endif /* no FIONREAD */ for (i = 0; i < nread; i++) { @@ -6452,7 +6716,7 @@ read_avail_input (expected) #ifdef SIGIO /* for entire page */ /* Note SIGIO has been undef'd if FIONREAD is missing. */ -SIGTYPE +static SIGTYPE input_available_signal (signo) int signo; { @@ -6513,8 +6777,8 @@ reinvoke_input_signal () -static void menu_bar_item P_ ((Lisp_Object, Lisp_Object)); -static void menu_bar_one_keymap P_ ((Lisp_Object)); +static void menu_bar_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object, void*)); +static Lisp_Object menu_bar_one_keymap_changed_items; /* These variables hold the vector under construction within menu_bar_items and its subroutines, and the current index @@ -6618,7 +6882,10 @@ menu_bar_items (old) def = get_keymap (access_keymap (maps[mapno], Qmenu_bar, 1, 0, 1), 0, 1); if (CONSP (def)) - menu_bar_one_keymap (def); + { + menu_bar_one_keymap_changed_items = Qnil; + map_keymap (def, menu_bar_item, Qnil, NULL, 1); + } } /* Move to the end those items that should be at the end. */ @@ -6672,48 +6939,15 @@ menu_bar_items (old) return menu_bar_items_vector; } -/* Scan one map KEYMAP, accumulating any menu items it defines - in menu_bar_items_vector. */ - -static Lisp_Object menu_bar_one_keymap_changed_items; - -static void -menu_bar_one_keymap (keymap) - Lisp_Object keymap; -{ - Lisp_Object tail, item; - - menu_bar_one_keymap_changed_items = Qnil; - - /* Loop over all keymap entries that have menu strings. */ - for (tail = keymap; CONSP (tail); tail = XCDR (tail)) - { - item = XCAR (tail); - if (CONSP (item)) - menu_bar_item (XCAR (item), XCDR (item)); - else if (VECTORP (item)) - { - /* Loop over the char values represented in the vector. */ - int len = XVECTOR (item)->size; - int c; - for (c = 0; c < len; c++) - { - Lisp_Object character; - XSETFASTINT (character, c); - menu_bar_item (character, XVECTOR (item)->contents[c]); - } - } - } -} - /* Add one item to menu_bar_items_vector, for KEY, ITEM_STRING and DEF. If there's already an item for KEY, add this DEF to it. */ Lisp_Object item_properties; static void -menu_bar_item (key, item) - Lisp_Object key, item; +menu_bar_item (key, item, dummy1, dummy2) + Lisp_Object key, item, dummy1; + void *dummy2; { struct gcpro gcpro1; int i; @@ -6786,7 +7020,10 @@ menu_bar_item (key, item) { Lisp_Object old; old = XVECTOR (menu_bar_items_vector)->contents[i + 2]; - XVECTOR (menu_bar_items_vector)->contents[i + 2] = Fcons (item, old); + /* If the new and the old items are not both keymaps, + the lookup will only find `item'. */ + item = Fcons (item, KEYMAPP (item) && KEYMAPP (XCAR (old)) ? old : Qnil); + XVECTOR (menu_bar_items_vector)->contents[i + 2] = item; } } @@ -6803,7 +7040,7 @@ menu_item_eval_property_1 (arg) return Qnil; } -/* Evaluate an expression and return the result (or nil if something +/* Evaluate an expression and return the result (or nil if something went wrong). Used to evaluate dynamic parts of menu items. */ Lisp_Object menu_item_eval_property (sexpr) @@ -6856,7 +7093,7 @@ parse_menu_item (item, notreal, inmenubar) for (i = ITEM_PROPERTY_DEF; i < ITEM_PROPERTY_ENABLE; i++) AREF (item_properties, i) = Qnil; AREF (item_properties, ITEM_PROPERTY_ENABLE) = Qt; - + /* Save the item here to protect it from GC. */ AREF (item_properties, ITEM_PROPERTY_ITEM) = item; @@ -6876,7 +7113,7 @@ parse_menu_item (item, notreal, inmenubar) start = item; item = XCDR (item); } - + /* Maybe key binding cache. */ if (CONSP (item) && CONSP (XCAR (item)) && (NILP (XCAR (XCAR (item))) @@ -6885,7 +7122,7 @@ parse_menu_item (item, notreal, inmenubar) cachelist = XCAR (item); item = XCDR (item); } - + /* This is the real definition--the function to run. */ AREF (item_properties, ITEM_PROPERTY_DEF) = item; @@ -6981,7 +7218,7 @@ parse_menu_item (item, notreal, inmenubar) return 0; AREF (item_properties, ITEM_PROPERTY_NAME) = item_string; } - + /* If got a filter apply it on definition. */ def = AREF (item_properties, ITEM_PROPERTY_DEF); if (!NILP (filter)) @@ -7009,7 +7246,7 @@ parse_menu_item (item, notreal, inmenubar) is OK in a submenu but not in the menubar. */ if (NILP (def)) return (inmenubar ? 0 : 1); - + /* See if this is a separate pane or a submenu. */ def = AREF (item_properties, ITEM_PROPERTY_DEF); tem = get_keymap (def, 0, 1); @@ -7020,7 +7257,7 @@ parse_menu_item (item, notreal, inmenubar) AREF (item_properties, ITEM_PROPERTY_DEF) = tem; return 1; } - + /* At the top level in the menu bar, do likewise for commands also. The menu bar does not display equivalent key bindings anyway. ITEM_PROPERTY_DEF is already set up properly. */ @@ -7047,7 +7284,7 @@ parse_menu_item (item, notreal, inmenubar) XSETCAR (cachelist, Qt); } } - + tem = XCAR (cachelist); if (!EQ (tem, Qt)) { @@ -7155,7 +7392,7 @@ parse_menu_item (item, notreal, inmenubar) } */ - /* Handle radio buttons or toggle boxes. */ + /* Handle radio buttons or toggle boxes. */ tem = AREF (item_properties, ITEM_PROPERTY_SELECTED); if (!NILP (tem)) AREF (item_properties, ITEM_PROPERTY_SELECTED) @@ -7222,13 +7459,13 @@ tool_bar_items (reuse, nitems) avoids risk of specpdl overflow. */ oquit = Vinhibit_quit; Vinhibit_quit = Qt; - + /* Initialize tool_bar_items_vector and protect it from GC. */ init_tool_bar_items (reuse); /* Build list of keymaps in maps. Set nmaps to the number of maps to process. */ - + /* Should overriding-terminal-local-map and overriding-local-map apply? */ if (!NILP (Voverriding_local_map_menu_flag)) { @@ -7273,7 +7510,7 @@ tool_bar_items (reuse, nitems) if (CONSP (keymap)) { Lisp_Object tail; - + /* KEYMAP is a list `(keymap (KEY . BINDING) ...)'. */ for (tail = keymap; CONSP (tail); tail = XCDR (tail)) { @@ -7311,7 +7548,7 @@ process_tool_bar_item (key, def) for (i = 0; i < ntool_bar_items; i += TOOL_BAR_ITEM_NSLOTS) { Lisp_Object *v = XVECTOR (tool_bar_items_vector)->contents + i; - + if (EQ (key, v[TOOL_BAR_ITEM_KEY])) { if (ntool_bar_items > i + TOOL_BAR_ITEM_NSLOTS) @@ -7337,41 +7574,41 @@ process_tool_bar_item (key, def) invalid. ITEM is a list `(menu-item CAPTION BINDING PROPS...)'. - + CAPTION is the caption of the item, If it's not a string, it is evaluated to get a string. - + BINDING is the tool bar item's binding. Tool-bar items with keymaps as binding are currently ignored. The following properties are recognized: - `:enable FORM'. - + FORM is evaluated and specifies whether the tool bar item is enabled or disabled. - + - `:visible FORM' - + FORM is evaluated and specifies whether the tool bar item is visible. - + - `:filter FUNCTION' FUNCTION is invoked with one parameter `(quote BINDING)'. Its result is stored as the new binding. - + - `:button (TYPE SELECTED)' TYPE must be one of `:radio' or `:toggle'. SELECTED is evaluated and specifies whether the button is selected (pressed) or not. - + - `:image IMAGES' IMAGES is either a single image specification or a vector of four image specifications. See enum tool_bar_item_images. - + - `:help HELP-STRING'. - + Gives a help string to display for the tool bar item. */ static int @@ -7405,11 +7642,11 @@ parse_tool_bar_item (key, item) else tool_bar_item_properties = Fmake_vector (make_number (TOOL_BAR_ITEM_NSLOTS), Qnil); - + /* Set defaults. */ PROP (TOOL_BAR_ITEM_KEY) = key; PROP (TOOL_BAR_ITEM_ENABLED_P) = Qt; - + /* Get the caption of the item. If the caption is not a string, evaluate it to get a string. If we don't get a string, skip this item. */ @@ -7496,13 +7733,13 @@ parse_tool_bar_item (key, item) PROP (TOOL_BAR_ITEM_ENABLED_P) = menu_item_eval_property (PROP (TOOL_BAR_ITEM_ENABLED_P)); - /* Handle radio buttons or toggle boxes. */ + /* Handle radio buttons or toggle boxes. */ if (!NILP (PROP (TOOL_BAR_ITEM_SELECTED_P))) PROP (TOOL_BAR_ITEM_SELECTED_P) = menu_item_eval_property (PROP (TOOL_BAR_ITEM_SELECTED_P)); return 1; - + #undef PROP } @@ -7529,7 +7766,7 @@ static void append_tool_bar_item () { Lisp_Object *to, *from; - + /* Enlarge tool_bar_items_vector if necessary. */ if (ntool_bar_items + TOOL_BAR_ITEM_NSLOTS >= XVECTOR (tool_bar_items_vector)->size) @@ -7584,7 +7821,7 @@ read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu) int *used_mouse_menu; { int mapno; - register Lisp_Object name; + register Lisp_Object name = Qnil; if (used_mouse_menu) *used_mouse_menu = 0; @@ -7686,7 +7923,8 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps) int mapno; register Lisp_Object name; int nlength; - int width = FRAME_WIDTH (SELECTED_FRAME ()) - 4; + /* FIXME: Use the minibuffer's frame width. */ + int width = FRAME_COLS (SELECTED_FRAME ()) - 4; int idx = -1; int nobindings = 1; Lisp_Object rest, vector; @@ -7830,7 +8068,7 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps) tem = build_string (NILP (selected) ? "[X] " : "[ ] "); s = concat2 (tem, s); } - + /* If we have room for the prompt string, add it to this line. If this is the first on the line, always add it. */ @@ -7893,7 +8131,7 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps) } /* Prompt with that and read response. */ - message2_nolog (menu, strlen (menu), + message2_nolog (menu, strlen (menu), ! NILP (current_buffer->enable_multibyte_characters)); /* Make believe its not a keyboard macro in case the help char @@ -7948,20 +8186,13 @@ follow_key (key, nmaps, current, defs, next) int nmaps; { int i, first_binding; - int did_meta = 0; first_binding = nmaps; for (i = nmaps - 1; i >= 0; i--) { if (! NILP (current[i])) { - Lisp_Object map; - if (did_meta) - map = defs[i]; - else - map = current[i]; - - defs[i] = access_keymap (map, key, 1, 0, 1); + defs[i] = access_keymap (current[i], key, 1, 0, 1); if (! NILP (defs[i])) first_binding = i; } @@ -7977,6 +8208,128 @@ follow_key (key, nmaps, current, defs, next) return first_binding; } +/* Structure used to keep track of partial application of key remapping + such as Vfunction_key_map and Vkey_translation_map. */ +typedef struct keyremap +{ + Lisp_Object map, parent; + int start, end; +} keyremap; + +/* Lookup KEY in MAP. + MAP is a keymap mapping keys to key vectors or functions. + If the mapping is a function and DO_FUNCTION is non-zero, then + the function is called with PROMPT as parameter and its return + value is used as the return value of this function (after checking + that it is indeed a vector). */ + +static Lisp_Object +access_keymap_keyremap (map, key, prompt, do_funcall) + Lisp_Object map, key, prompt; + int do_funcall; +{ + Lisp_Object next; + + next = access_keymap (map, key, 1, 0, 1); + + /* Handle symbol with autoload definition. */ + if (SYMBOLP (next) && !NILP (Ffboundp (next)) + && CONSP (XSYMBOL (next)->function) + && EQ (XCAR (XSYMBOL (next)->function), Qautoload)) + do_autoload (XSYMBOL (next)->function, next); + + /* Handle a symbol whose function definition is a keymap + or an array. */ + if (SYMBOLP (next) && !NILP (Ffboundp (next)) + && (!NILP (Farrayp (XSYMBOL (next)->function)) + || KEYMAPP (XSYMBOL (next)->function))) + next = XSYMBOL (next)->function; + + /* If the keymap gives a function, not an + array, then call the function with one arg and use + its value instead. */ + if (SYMBOLP (next) && !NILP (Ffboundp (next)) && do_funcall) + { + Lisp_Object tem; + tem = next; + + next = call1 (next, prompt); + /* If the function returned something invalid, + barf--don't ignore it. + (To ignore it safely, we would need to gcpro a bunch of + other variables.) */ + if (! (VECTORP (next) || STRINGP (next))) + error ("Function %s returns invalid key sequence", tem); + } + return next; +} + +/* Do one step of the key remapping used for function-key-map and + key-translation-map: + KEYBUF is the buffer holding the input events. + BUFSIZE is its maximum size. + FKEY is a pointer to the keyremap structure to use. + INPUT is the index of the last element in KEYBUF. + DOIT if non-zero says that the remapping can actually take place. + DIFF is used to return the number of keys added/removed by the remapping. + PARENT is the root of the keymap. + PROMPT is the prompt to use if the remapping happens through a function. + The return value is non-zero if the remapping actually took place. */ + +static int +keyremap_step (keybuf, bufsize, fkey, input, doit, diff, prompt) + Lisp_Object *keybuf, prompt; + keyremap *fkey; + int input, doit, *diff, bufsize; +{ + Lisp_Object next, key; + + key = keybuf[fkey->end++]; + next = access_keymap_keyremap (fkey->map, key, prompt, doit); + + /* If keybuf[fkey->start..fkey->end] is bound in the + map and we're in a position to do the key remapping, replace it with + the binding and restart with fkey->start at the end. */ + if ((VECTORP (next) || STRINGP (next)) && doit) + { + int len = XFASTINT (Flength (next)); + int i; + + *diff = len - (fkey->end - fkey->start); + + if (input + *diff >= bufsize) + error ("Key sequence too long"); + + /* Shift the keys that follow fkey->end. */ + if (*diff < 0) + for (i = fkey->end; i < input; i++) + keybuf[i + *diff] = keybuf[i]; + else if (*diff > 0) + for (i = input - 1; i >= fkey->end; i--) + keybuf[i + *diff] = keybuf[i]; + /* Overwrite the old keys with the new ones. */ + for (i = 0; i < len; i++) + keybuf[fkey->start + i] + = Faref (next, make_number (i)); + + fkey->start = fkey->end += *diff; + fkey->map = fkey->parent; + + return 1; + } + + fkey->map = get_keymap (next, 0, 1); + + /* If we no longer have a bound suffix, try a new position for + fkey->start. */ + if (!CONSP (fkey->map)) + { + fkey->end = ++fkey->start; + fkey->map = fkey->parent; + } + return 0; +} + /* Read a sequence of keys that ends with a non prefix character, storing it in KEYBUF, a buffer of size BUFSIZE. Prompt with PROMPT. @@ -8064,7 +8417,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, defs[i] is non-nil. */ volatile int first_binding; /* Index of the first key that has no binding. - It is useless to try fkey_start larger than that. */ + It is useless to try fkey.start larger than that. */ volatile int first_unbound; /* If t < mock_input, then KEYBUF[t] should be read as the next @@ -8083,22 +8436,21 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, volatile int mock_input = 0; /* If the sequence is unbound in submaps[], then - keybuf[fkey_start..fkey_end-1] is a prefix in Vfunction_key_map, - and fkey_map is its binding. + keybuf[fkey.start..fkey.end-1] is a prefix in Vfunction_key_map, + and fkey.map is its binding. These might be > t, indicating that all function key scanning should hold off until t reaches them. We do this when we've just recognized a function key, to avoid searching for the function key's again in Vfunction_key_map. */ - volatile int fkey_start = 0, fkey_end = 0; - volatile Lisp_Object fkey_map; + volatile keyremap fkey; /* Likewise, for key_translation_map. */ - volatile int keytran_start = 0, keytran_end = 0; - volatile Lisp_Object keytran_map; + volatile keyremap keytran; - /* If we receive a ``switch-frame'' event in the middle of a key sequence, - we put it off for later. While we're reading, we keep the event here. */ + /* If we receive a `switch-frame' or `select-window' event in the middle of + a key sequence, we put it off for later. + While we're reading, we keep the event here. */ volatile Lisp_Object delayed_switch_frame; /* See the comment below... */ @@ -8129,16 +8481,11 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, last_nonmenu_event = Qnil; delayed_switch_frame = Qnil; - fkey_map = Vfunction_key_map; - keytran_map = Vkey_translation_map; - - /* If there is no function-key-map, turn off function key scanning. */ - if (!KEYMAPP (Vfunction_key_map)) - fkey_start = fkey_end = bufsize + 1; - - /* If there is no key-translation-map, turn off scanning. */ - if (!KEYMAPP (Vkey_translation_map)) - keytran_start = keytran_end = bufsize + 1; + fkey.map = fkey.parent = Vfunction_key_map; + keytran.map = keytran.parent = Vkey_translation_map; + /* If there is no translation-map, turn off scanning. */ + fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1; + keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1; if (INTERACTIVE) { @@ -8248,15 +8595,15 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, /* If the best binding for the current key sequence is a keymap, or we may be looking at a function key's escape sequence, keep on reading. */ - while ((first_binding < nmaps && ! NILP (submaps[first_binding])) - || (first_binding >= nmaps && fkey_start < t) - || (first_binding >= nmaps && keytran_start < t) + while (first_binding < nmaps + /* Keep reading as long as there's a prefix binding. */ + ? !NILP (submaps[first_binding]) /* Don't return in the middle of a possible function key sequence, if the only bindings we found were via case conversion. Thus, if ESC O a has a function-key-map translation and ESC o has a binding, don't return after ESC O, so that we can translate ESC O plus the next character. */ - ) + : (fkey.start < t || keytran.start < t)) { Lisp_Object key; int used_mouse_menu = 0; @@ -8274,10 +8621,13 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, just one key. */ volatile int echo_local_start, keys_local_start, local_first_binding; + eassert (fkey.end == t || (fkey.end > t && fkey.end <= mock_input)); + eassert (fkey.start <= fkey.end); + eassert (keytran.start <= keytran.end); /* key-translation-map is applied *after* function-key-map. */ - eassert (keytran_end <= fkey_start); + eassert (keytran.end <= fkey.start); - if (first_unbound < fkey_start && first_unbound < keytran_start) + if (first_unbound < fkey.start && first_unbound < keytran.start) { /* The prefix upto first_unbound has no binding and has no translation left to do either, so we know it's unbound. If we don't stop now, we risk staying here indefinitely @@ -8287,10 +8637,10 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, for (i = first_unbound + 1; i < t; i++) keybuf[i - first_unbound - 1] = keybuf[i]; mock_input = t - first_unbound - 1; - fkey_end = fkey_start -= first_unbound + 1; - fkey_map = Vfunction_key_map; - keytran_end = keytran_start -= first_unbound + 1; - keytran_map = Vkey_translation_map; + fkey.end = fkey.start -= first_unbound + 1; + fkey.map = fkey.parent; + keytran.end = keytran.start -= first_unbound + 1; + keytran.map = keytran.parent; goto replay_sequence; } @@ -8442,6 +8792,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, Vquit_flag = Qnil; if (EVENT_HAS_PARAMETERS (key) + /* Either a `switch-frame' or a `select-window' event. */ && EQ (EVENT_HEAD_KIND (EVENT_HEAD (key)), Qswitch_frame)) { /* If we're at the beginning of a key sequence, and the caller @@ -8528,7 +8879,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, orig_keymap = get_local_map (PT, current_buffer, Qkeymap); goto replay_sequence; } - + /* For a mouse click, get the local text-property keymap of the place clicked on, rather than point. */ if (last_real_key_start == 0 @@ -8539,7 +8890,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, localized_local_map = 1; start = EVENT_START (key); - + if (CONSP (start) && CONSP (XCDR (start))) { pos = POSN_BUFFER_POSN (start); @@ -8578,7 +8929,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, { if (t + 1 >= bufsize) error ("Key sequence too long"); - + keybuf[t] = posn; keybuf[t + 1] = key; mock_input = t + 2; @@ -8693,15 +9044,15 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, /* This is needed for the following scenario: event 0: a down-event that gets dropped by calling replay_key. event 1: some normal prefix like C-h. - After event 0, first_unbound is 0, after event 1 fkey_start - and keytran_start are both 1, so when we see that C-h is bound, + After event 0, first_unbound is 0, after event 1 fkey.start + and keytran.start are both 1, so when we see that C-h is bound, we need to update first_unbound. */ first_unbound = max (t + 1, first_unbound); else { Lisp_Object head; - - /* Remember the position to put an upper bound on fkey_start. */ + + /* Remember the position to put an upper bound on fkey.start. */ first_unbound = min (t, first_unbound); head = EVENT_HEAD (key); @@ -8782,6 +9133,27 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, xterm-mouse-mode. -stef Isn't this just the most wonderful code ever? */ + + /* If mock_input > t + 1, the above simplification + will actually end up dropping keys on the floor. + This is probably OK for now, but even + if mock_input <= t + 1, we need to adjust fkey + and keytran. + Typical case [header-line down-mouse-N]: + mock_input = 2, t = 1, fkey.end = 1, + last_real_key_start = 0. */ + if (fkey.end > last_real_key_start) + { + fkey.end = fkey.start + = min (last_real_key_start, fkey.start); + fkey.map = fkey.parent; + if (keytran.end > last_real_key_start) + { + keytran.end = keytran.start + = min (last_real_key_start, keytran.start); + keytran.map = keytran.parent; + } + } if (t == last_real_key_start) { mock_input = 0; @@ -8840,224 +9212,62 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, to go over the sequence before we return (since we keep the invariant that keytran.end <= fkey.start). */ { - if (fkey_start < t) - (fkey_start = fkey_end = t, fkey_map = Vfunction_key_map); + if (fkey.start < t) + (fkey.start = fkey.end = t, fkey.map = fkey.parent); } else /* If the sequence is unbound, see if we can hang a function key off the end of it. */ - { - Lisp_Object fkey_next; - - /* Continue scan from fkey_end until we find a bound suffix. - If we fail, increment fkey_start and start over from there. */ - while (fkey_end < t) - { - Lisp_Object key; - - key = keybuf[fkey_end++]; - fkey_next = access_keymap (fkey_map, key, 1, 0, 1); - - /* Handle symbol with autoload definition. */ - if (SYMBOLP (fkey_next) && ! NILP (Ffboundp (fkey_next)) - && CONSP (XSYMBOL (fkey_next)->function) - && EQ (XCAR (XSYMBOL (fkey_next)->function), Qautoload)) - do_autoload (XSYMBOL (fkey_next)->function, - fkey_next); - - /* Handle a symbol whose function definition is a keymap - or an array. */ - if (SYMBOLP (fkey_next) && ! NILP (Ffboundp (fkey_next)) - && (!NILP (Farrayp (XSYMBOL (fkey_next)->function)) - || KEYMAPP (XSYMBOL (fkey_next)->function))) - fkey_next = XSYMBOL (fkey_next)->function; - -#if 0 /* I didn't turn this on, because it might cause trouble - for the mapping of return into C-m and tab into C-i. */ - /* Optionally don't map function keys into other things. - This enables the user to redefine kp- keys easily. */ - if (SYMBOLP (key) && !NILP (Vinhibit_function_key_mapping)) - fkey_next = Qnil; -#endif - - /* If the function key map gives a function, not an - array, then call the function with no args and use - its value instead. */ - if (SYMBOLP (fkey_next) && ! NILP (Ffboundp (fkey_next)) - /* If there's a binding (i.e. first_binding >= nmaps) - we don't want to apply this function-key-mapping. */ - && fkey_end == t && first_binding >= nmaps) - { - struct gcpro gcpro1, gcpro2, gcpro3; - Lisp_Object tem; - tem = fkey_next; - - GCPRO3 (fkey_map, keytran_map, delayed_switch_frame); - fkey_next = call1 (fkey_next, prompt); - UNGCPRO; - /* If the function returned something invalid, - barf--don't ignore it. - (To ignore it safely, we would need to gcpro a bunch of - other variables.) */ - if (! (VECTORP (fkey_next) || STRINGP (fkey_next))) - error ("Function in key-translation-map returns invalid key sequence"); - } - - /* If keybuf[fkey_start..fkey_end] is bound in the - function key map and it's a suffix of the current - sequence (i.e. fkey_end == t), replace it with - the binding and restart with fkey_start at the end. */ - if ((VECTORP (fkey_next) || STRINGP (fkey_next)) - /* If there's a binding (i.e. first_binding >= nmaps) - we don't want to apply this function-key-mapping. */ - && fkey_end == t && first_binding >= nmaps) - { - int len = XFASTINT (Flength (fkey_next)); - - t = fkey_start + len; - if (t >= bufsize) - error ("Key sequence too long"); - - if (VECTORP (fkey_next)) - bcopy (XVECTOR (fkey_next)->contents, - keybuf + fkey_start, - (t - fkey_start) * sizeof (keybuf[0])); - else if (STRINGP (fkey_next)) - { - int i; - - for (i = 0; i < len; i++) - XSETFASTINT (keybuf[fkey_start + i], - SREF (fkey_next, i)); - } - - mock_input = t; - fkey_start = fkey_end = t; - fkey_map = Vfunction_key_map; - - /* Do pass the results through key-translation-map. - But don't retranslate what key-translation-map - has already translated. */ - keytran_end = keytran_start; - keytran_map = Vkey_translation_map; - - goto replay_sequence; - } - - fkey_map = get_keymap (fkey_next, 0, 1); - - /* If we no longer have a bound suffix, try a new positions for - fkey_start. */ - if (!CONSP (fkey_map)) - { - fkey_end = ++fkey_start; - fkey_map = Vfunction_key_map; - } - } - } - - /* Look for this sequence in key-translation-map. */ - { - Lisp_Object keytran_next; - - /* Scan from keytran_end until we find a bound suffix. */ - while (keytran_end < fkey_start) + /* Continue scan from fkey.end until we find a bound suffix. */ + while (fkey.end < t) { - Lisp_Object key; - - key = keybuf[keytran_end++]; - keytran_next - = access_keymap (keytran_map, key, 1, 0, 1); - - /* Handle symbol with autoload definition. */ - if (SYMBOLP (keytran_next) && ! NILP (Ffboundp (keytran_next)) - && CONSP (XSYMBOL (keytran_next)->function) - && EQ (XCAR (XSYMBOL (keytran_next)->function), Qautoload)) - do_autoload (XSYMBOL (keytran_next)->function, - keytran_next); - - /* Handle a symbol whose function definition is a keymap - or an array. */ - if (SYMBOLP (keytran_next) && ! NILP (Ffboundp (keytran_next)) - && (!NILP (Farrayp (XSYMBOL (keytran_next)->function)) - || KEYMAPP (XSYMBOL (keytran_next)->function))) - keytran_next = XSYMBOL (keytran_next)->function; - - /* If the key translation map gives a function, not an - array, then call the function with one arg and use - its value instead. */ - if (SYMBOLP (keytran_next) && ! NILP (Ffboundp (keytran_next))) - { - struct gcpro gcpro1, gcpro2, gcpro3; - Lisp_Object tem; - tem = keytran_next; - - GCPRO3 (fkey_map, keytran_map, delayed_switch_frame); - keytran_next = call1 (keytran_next, prompt); - UNGCPRO; - /* If the function returned something invalid, - barf--don't ignore it. - (To ignore it safely, we would need to gcpro a bunch of - other variables.) */ - if (! (VECTORP (keytran_next) || STRINGP (keytran_next))) - error ("Function in key-translation-map returns invalid key sequence"); - } - - /* If keybuf[keytran_start..keytran_end] is bound in the - key translation map and it's a suffix of the current - sequence (i.e. keytran_end == t), replace it with - the binding and restart with keytran_start at the end. */ - if ((VECTORP (keytran_next) || STRINGP (keytran_next))) + struct gcpro gcpro1, gcpro2, gcpro3; + int done, diff; + + GCPRO3 (fkey.map, keytran.map, delayed_switch_frame); + done = keyremap_step (keybuf, bufsize, &fkey, + max (t, mock_input), + /* If there's a binding (i.e. + first_binding >= nmaps) we don't want + to apply this function-key-mapping. */ + fkey.end + 1 == t && first_binding >= nmaps, + &diff, prompt); + UNGCPRO; + if (done) { - int len = XFASTINT (Flength (keytran_next)); - int i, diff = len - (keytran_end - keytran_start); - - mock_input = max (t, mock_input); - if (mock_input + diff >= bufsize) - error ("Key sequence too long"); - - /* Shift the keys that are after keytran_end. */ - if (diff < 0) - for (i = keytran_end; i < mock_input; i++) - keybuf[i + diff] = keybuf[i]; - else if (diff > 0) - for (i = mock_input - 1; i >= keytran_end; i--) - keybuf[i + diff] = keybuf[i]; - /* Replace the keys between keytran_start and keytran_end - with those from keytran_next. */ - for (i = 0; i < len; i++) - keybuf[keytran_start + i] - = Faref (keytran_next, make_number (i)); - - mock_input += diff; - keytran_start = keytran_end += diff; - keytran_map = Vkey_translation_map; - - /* Adjust the function-key-map counters. */ - fkey_start += diff; - fkey_end += diff; - + mock_input = diff + max (t, mock_input); goto replay_sequence; } + } - keytran_map = get_keymap (keytran_next, 0, 1); + /* Look for this sequence in key-translation-map. + Scan from keytran.end until we find a bound suffix. */ + while (keytran.end < fkey.start) + { + struct gcpro gcpro1, gcpro2, gcpro3; + int done, diff; - /* If we no longer have a bound suffix, try a new positions for - keytran_start. */ - if (!CONSP (keytran_map)) - { - keytran_end = ++keytran_start; - keytran_map = Vkey_translation_map; - } - } - } + GCPRO3 (fkey.map, keytran.map, delayed_switch_frame); + done = keyremap_step (keybuf, bufsize, &keytran, max (t, mock_input), + 1, &diff, prompt); + UNGCPRO; + if (done) + { + mock_input = diff + max (t, mock_input); + /* Adjust the function-key-map counters. */ + fkey.end += diff; + fkey.start += diff; + + goto replay_sequence; + } + } /* If KEY is not defined in any of the keymaps, and cannot be part of a function key or translation, and is an upper case letter use the corresponding lower-case letter instead. */ if (first_binding >= nmaps - && fkey_start >= t && keytran_start >= t + && fkey.start >= t && keytran.start >= t && INTEGERP (key) && ((((XINT (key) & 0x3ffff) < XCHAR_TABLE (current_buffer->downcase_table)->size) @@ -9088,7 +9298,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, and is a shifted function key, use the corresponding unshifted function key instead. */ if (first_binding >= nmaps - && fkey_start >= t && keytran_start >= t + && fkey.start >= t && keytran.start >= t && SYMBOLP (key)) { Lisp_Object breakdown; @@ -9146,7 +9356,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, add_command_key (keybuf[t]); } - + UNGCPRO; return t; @@ -9225,6 +9435,7 @@ will read just one key sequence. */) if (NILP (continue_echo)) { this_command_key_count = 0; + this_command_key_count_reset = 0; this_single_command_key_start = 0; } @@ -9284,6 +9495,7 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector, if (NILP (continue_echo)) { this_command_key_count = 0; + this_command_key_count_reset = 0; this_single_command_key_start = 0; } @@ -9477,6 +9689,7 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_ int i; this_command_key_count = 0; + this_command_key_count_reset = 0; this_single_command_key_start = 0; keys = XVECTOR (saved_keys)->contents; @@ -9537,7 +9750,7 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_ int message_p = push_message (); int count = SPECPDL_INDEX (); - record_unwind_protect (push_message_unwind, Qnil); + record_unwind_protect (pop_message_unwind, Qnil); binding = Fkey_description (bindings); newmessage @@ -9712,22 +9925,28 @@ The value is always a vector. */) DEFUN ("reset-this-command-lengths", Freset_this_command_lengths, Sreset_this_command_lengths, 0, 0, 0, - doc: /* Used for complicated reasons in `universal-argument-other-key'. + doc: /* Make the unread events replace the last command and echo. +Used in `universal-argument-other-key'. `universal-argument-other-key' rereads the event just typed. It then gets translated through `function-key-map'. -The translated event gets included in the echo area and in -the value of `this-command-keys' in addition to the raw original event. -That is not right. - -Calling this function directs the translated event to replace -the original event, so that only one version of the event actually -appears in the echo area and in the value of `this-command-keys'. */) +The translated event has to replace the real events, +both in the value of (this-command-keys) and in echoing. +To achieve this, `universal-argument-other-key' calls +`reset-this-command-lengths', which discards the record of reading +these events the first time. */) () { - before_command_restore_flag = 1; - before_command_key_count_1 = before_command_key_count; - before_command_echo_length_1 = before_command_echo_length; + this_command_key_count = before_command_key_count; + if (this_command_key_count < this_single_command_key_start) + this_single_command_key_start = this_command_key_count; + + echo_truncate (before_command_echo_length); + + /* Cause whatever we put into unread-command-events + to echo as if it were being freshly read from the keyboard. */ + this_command_key_count_reset = 1; + return Qnil; } @@ -9740,8 +9959,9 @@ KEEP-RECORD is non-nil. */) Lisp_Object keep_record; { int i; - + this_command_key_count = 0; + this_command_key_count_reset = 0; if (NILP (keep_record)) { @@ -9889,25 +10109,25 @@ stuff_buffered_input (stuffstring) stuff_char (*p++); stuff_char ('\n'); } - + /* Anything we have read ahead, put back for the shell to read. */ /* ?? What should this do when we have multiple keyboards?? Should we ignore anything that was typed in at the "wrong" kboard? */ for (; kbd_fetch_ptr != kbd_store_ptr; kbd_fetch_ptr++) { int idx; - + 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); - + kbd_fetch_ptr->kind = NO_EVENT; idx = 2 * (kbd_fetch_ptr - kbd_buffer); ASET (kbd_buffer_gcpro, idx, Qnil); ASET (kbd_buffer_gcpro, idx + 1, Qnil); } - + input_pending = 0; #endif #endif /* BSD_SYSTEM and not BSD4_1 */ @@ -9937,7 +10157,7 @@ clear_waiting_for_input () } /* This routine is called at interrupt level in response to C-g. - + If interrupt_input, this is the handler for SIGINT. Otherwise, it is called from kbd_buffer_store_event, in handling SIGIO or SIGTINT. @@ -9949,7 +10169,7 @@ clear_waiting_for_input () eval to throw, when it gets a chance. If quit-flag is already non-nil, it stops the job right away. */ -SIGTYPE +static SIGTYPE interrupt_signal (signalnum) /* If we don't have an argument, */ int signalnum; /* some compilers complain in signal calls. */ { @@ -10027,7 +10247,7 @@ interrupt_signal (signalnum) /* If we don't have an argument, */ } while (c != '\n') c = getchar (); } - else + else { /* During GC, it must be safe to reenable quitting again. */ Vinhibit_quit = Qnil; @@ -10269,7 +10489,7 @@ delete_kboard (kb) KBOARD *kb; { KBOARD **kbp; - + for (kbp = &all_kboards; *kbp != kb; kbp = &(*kbp)->next_kboard) if (*kbp == NULL) abort (); @@ -10284,7 +10504,7 @@ delete_kboard (kb) if (current_kboard == kb) abort (); } - + wipe_kboard (kb); xfree (kb); } @@ -10361,6 +10581,11 @@ init_keyboard () poll_suppress_count = 1; start_polling (); #endif + +#ifdef MAC_OSX + /* At least provide an escape route since C-g doesn't work. */ + signal (SIGINT, interrupt_signal); +#endif } /* This type's only use is in syms_of_keyboard, to initialize the @@ -10378,7 +10603,9 @@ struct event_head head_table[] = { {&Qdelete_frame, "delete-frame", &Qdelete_frame}, {&Qiconify_frame, "iconify-frame", &Qiconify_frame}, {&Qmake_frame_visible, "make-frame-visible", &Qmake_frame_visible}, - {&Qselect_window, "select-window", &Qselect_window} + /* `select-window' should be handled just like `switch-frame' + in read_key_sequence. */ + {&Qselect_window, "select-window", &Qswitch_frame} }; void @@ -10386,7 +10613,7 @@ syms_of_keyboard () { Vpre_help_message = Qnil; staticpro (&Vpre_help_message); - + Vlispy_mouse_stem = build_string ("mouse"); staticpro (&Vlispy_mouse_stem); @@ -10461,7 +10688,7 @@ syms_of_keyboard () Qsave_session = intern ("save-session"); staticpro(&Qsave_session); - + Qusr1_signal = intern ("usr1-signal"); staticpro (&Qusr1_signal); Qusr2_signal = intern ("usr2-signal"); @@ -10713,9 +10940,10 @@ will be in `last-command' during the following command. */); Vthis_command = Qnil; DEFVAR_LISP ("this-original-command", &Vthis_original_command, - doc: /* If non-nil, the original command bound to the current key sequence. -The value of `this-command' is the result of looking up the original -command in the active keymaps. */); + doc: /* The command bound to the current key sequence before remapping. +It equals `this-command' if the original command was not remapped through +any of the active keymaps. Otherwise, the value of `this-command' is the +result of looking up the original command in the active keymaps. */); Vthis_original_command = Qnil; DEFVAR_INT ("auto-save-interval", &auto_save_interval, @@ -10759,7 +10987,7 @@ instead of pixels. This variable is also the threshold for motion of the mouse to count as a drag. */); double_click_fuzz = 3; - + DEFVAR_BOOL ("inhibit-local-menu-bar-menus", &inhibit_local_menu_bar_menus, doc: /* *Non-nil means inhibit local map menu bar menus. */); inhibit_local_menu_bar_menus = 0; @@ -10818,7 +11046,10 @@ Each character is looked up in this string and the contents used instead. The value may be a string, a vector, or a char-table. If it is a string or vector of length N, character codes N and up are untranslated. -In a vector or a char-table, an element which is nil means "no translation". */); +In a vector or a char-table, an element which is nil means "no translation". + +This is applied to the characters supplied to input methods, not their +output. See also `translation-table-for-input'. */); Vkeyboard_translate_table = Qnil; DEFVAR_BOOL ("cannot-suspend", &cannot_suspend, @@ -11044,8 +11275,12 @@ keys_of_keyboard () "ignore-event"); initial_define_lispy_key (Vspecial_event_map, "make-frame-visible", "ignore-event"); - initial_define_lispy_key (Vspecial_event_map, "select-window", - "handle-select-window"); + /* Handling it at such a low-level causes read_key_sequence to get + * confused because it doesn't realize that the current_buffer was + * changed by read_char. + * + * initial_define_lispy_key (Vspecial_event_map, "select-window", + * "handle-select-window"); */ initial_define_lispy_key (Vspecial_event_map, "save-session", "handle-save-session"); }