# HG changeset patch # User Richard M. Stallman # Date 741752462 0 # Node ID e49ff3115e7d439e53ec59bd4f50cc1175463c4a # Parent 6e7afc0a7fbc461551563556da060488a8406752 (read_char): After Fgarbage_collect, call redisplay. (read_key_sequence): When inserting `menu-bar' prefix, modify the position field to prevent doing so twice. Do all these forms of event expansion after replayed events also. Set last_real_key_start before each key. Use last_real_key_start in criterion for being the first event. (syms_of_keyboard): Doc fix. (Vhelp_char): Renamed from help_char. (Vprefix_help_command): New Lisp variable. (read_key_sequence): Use that, for help char after prefix key. (kbd_buffer_get_event): Clear f before calling mouse_position_hook. diff -r 6e7afc0a7fbc -r e49ff3115e7d src/keyboard.c --- a/src/keyboard.c Sun Jul 04 02:20:59 1993 +0000 +++ b/src/keyboard.c Sun Jul 04 02:21:02 1993 +0000 @@ -122,11 +122,14 @@ int immediate_quit; /* Character to recognize as the help char. */ -Lisp_Object help_char; +Lisp_Object Vhelp_char; /* Form to execute when help char is typed. */ Lisp_Object Vhelp_form; +/* Command to run when the help character follows a prefix key. */ +Lisp_Object Vprefix_help_command; + /* Character that causes a quit. Normally C-g. If we are running on an ordinary terminal, this must be an ordinary @@ -505,7 +508,7 @@ ptr += name->size; } - if (echoptr == echobuf && EQ (c, help_char)) + if (echoptr == echobuf && EQ (c, Vhelp_char)) { strcpy (ptr, " (Type ? for further options)"); ptr += strlen (ptr); @@ -1480,7 +1483,10 @@ consing going on to make it worthwhile. */ if (!detect_input_pending () && consing_since_gc > gc_cons_threshold / 2) - Fgarbage_collect (); + { + Fgarbage_collect (); + redisplay (); + } } } } @@ -1587,7 +1593,7 @@ num_input_chars++; /* Process the help character specially if enabled */ - if (EQ (c, help_char) && !NILP (Vhelp_form)) + if (EQ (c, Vhelp_char) && !NILP (Vhelp_form)) { Lisp_Object tem0; count = specpdl_ptr - specpdl; @@ -1914,7 +1920,7 @@ } else if (do_mouse_tracking && mouse_moved) { - FRAME_PTR f; + FRAME_PTR f = 0; Lisp_Object bar_window; enum scroll_bar_part part; Lisp_Object x, y; @@ -3802,6 +3808,9 @@ this_command_key_count = keys_local_start; first_binding = local_first_binding; + /* By default, assume each event is "real". */ + last_real_key_start = t; + /* Does mock_input indicate that we are re-reading a key sequence? */ if (t < mock_input) { @@ -3815,8 +3824,6 @@ { struct buffer *buf = current_buffer; - last_real_key_start = t; - key = read_char (!prompt, nmaps, submaps, last_nonmenu_event, &used_mouse_menu); @@ -3830,125 +3837,131 @@ } Vquit_flag = Qnil; - - /* Clicks in non-text areas get prefixed by the symbol - in their CHAR-ADDRESS field. For example, a click on - the mode line is prefixed by the symbol `mode-line'. - - Furthermore, key sequences beginning with mouse clicks - are read using the keymaps of the buffer clicked on, not - the current buffer. So we may have to switch the buffer - here. - - If the event was obtained from the unread_command_events - queue, then don't expand it; we did that the first time - we read it. */ - if (EVENT_HAS_PARAMETERS (key)) + } + + /* Clicks in non-text areas get prefixed by the symbol + in their CHAR-ADDRESS field. For example, a click on + the mode line is prefixed by the symbol `mode-line'. + + Furthermore, key sequences beginning with mouse clicks + are read using the keymaps of the buffer clicked on, not + the current buffer. So we may have to switch the buffer + here. + + When we turn one event into two events, we must make sure + that neither of the two looks like the original--so that, + if we replay the events, they won't be expanded again. + If not for this, such reexpansion could happen either here + or when user programs play with this-command-keys. */ + if (EVENT_HAS_PARAMETERS (key)) + { + Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (key)); + + if (EQ (kind, Qmouse_click)) { - Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (key)); - - if (EQ (kind, Qmouse_click)) + Lisp_Object window = POSN_WINDOW (EVENT_START (key)); + Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key)); + + if (XTYPE (posn) == Lisp_Cons) { - Lisp_Object window = POSN_WINDOW (EVENT_START (key)); - Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key)); - - /* Key sequences beginning with mouse clicks are - read using the keymaps in the buffer clicked on, - not the current buffer. If we're at the - beginning of a key sequence, switch buffers. */ - if (t == 0 - && XTYPE (window) == Lisp_Window - && XTYPE (XWINDOW (window)->buffer) == Lisp_Buffer - && XBUFFER (XWINDOW (window)->buffer) != current_buffer) - { - keybuf[t] = key; - mock_input = t + 1; - - /* Arrange to go back to the original buffer once we're - done reading the key sequence. Note that we can't - use save_excursion_{save,restore} here, because they - save point as well as the current buffer; we don't - want to save point, because redisplay may change it, - to accommodate a Fset_window_start or something. We - don't want to do this at the top of the function, - because we may get input from a subprocess which - wants to change the selected window and stuff (say, - emacsclient). */ - record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); - - set_buffer_internal (XBUFFER (XWINDOW (window)->buffer)); - goto replay_sequence; - } - else if (XTYPE (posn) == Lisp_Symbol) - { - if (t + 1 >= bufsize) - error ("key sequence too long"); - keybuf[t] = posn; - keybuf[t+1] = key; - mock_input = t + 2; - - /* Zap the position in key, so we know that we've - expanded it, and don't try to do so again. */ - POSN_BUFFER_POSN (EVENT_START (key)) - = Fcons (posn, Qnil); - - /* If we switched buffers while reading the first event, - replay in case we switched keymaps too. */ - if (buf != current_buffer && t == 0) - goto replay_sequence; - goto replay_key; - } - else if (XTYPE (posn) == Lisp_Cons) - { - /* We're looking at the second event of a - sequence which we expanded before. Set - last_real_key_start appropriately. */ - if (last_real_key_start == t && t > 0) - last_real_key_start = t - 1; - } + /* We're looking at the second event of a + sequence which we expanded before. Set + last_real_key_start appropriately. */ + if (t > 0) + last_real_key_start = t - 1; } - else if (EQ (kind, Qswitch_frame)) - { - /* If we're at the beginning of a key sequence, go - ahead and return this event. If we're in the - midst of a key sequence, delay it until the end. */ - if (t > 0) - { - delayed_switch_frame = key; - goto replay_key; - } - } - else + + /* Key sequences beginning with mouse clicks are + read using the keymaps in the buffer clicked on, + not the current buffer. If we're at the + beginning of a key sequence, switch buffers. */ + if (last_real_key_start == 0 + && XTYPE (window) == Lisp_Window + && XTYPE (XWINDOW (window)->buffer) == Lisp_Buffer + && XBUFFER (XWINDOW (window)->buffer) != current_buffer) { - Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key)); - - /* Handle menu-bar events: - insert the dummy prefix char `menu-bar'. */ - if (EQ (posn, Qmenu_bar)) - { - if (t + 1 >= bufsize) - error ("key sequence too long"); - /* Run the Lucid hook. */ - call1 (Vrun_hooks, Qactivate_menubar_hook); - /* If it has changed current-menubar from previous value, - really recompute the menubar from the value. */ - if (! NILP (Vlucid_menu_bar_dirty_flag)) - call0 (Qrecompute_lucid_menubar); - keybuf[t] = posn; - keybuf[t+1] = key; - mock_input = t + 2; - goto replay_sequence; - } + keybuf[t] = key; + mock_input = t + 1; + + /* Arrange to go back to the original buffer once we're + done reading the key sequence. Note that we can't + use save_excursion_{save,restore} here, because they + save point as well as the current buffer; we don't + want to save point, because redisplay may change it, + to accommodate a Fset_window_start or something. We + don't want to do this at the top of the function, + because we may get input from a subprocess which + wants to change the selected window and stuff (say, + emacsclient). */ + record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); + + set_buffer_internal (XBUFFER (XWINDOW (window)->buffer)); + goto replay_sequence; + } + else if (XTYPE (posn) == Lisp_Symbol) + { + /* Expand mode-line and scroll-bar events into two events: + use posn as a fake prefix key. */ + + if (t + 1 >= bufsize) + error ("key sequence too long"); + keybuf[t] = posn; + keybuf[t+1] = key; + mock_input = t + 2; + + /* Zap the position in key, so we know that we've + expanded it, and don't try to do so again. */ + POSN_BUFFER_POSN (EVENT_START (key)) + = Fcons (posn, Qnil); + goto replay_key; } } - - /* If we switched buffers while reading the first event, - replay in case we switched keymaps too. */ - if (buf != current_buffer && t == 0) + else if (EQ (kind, Qswitch_frame)) + { + /* If we're at the beginning of a key sequence, go + ahead and return this event. If we're in the + midst of a key sequence, delay it until the end. */ + if (t > 0) + { + delayed_switch_frame = key; + goto replay_key; + } + } + else { - keybuf[t++] = key; - mock_input = t; - goto replay_sequence; + Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key)); + + /* Handle menu-bar events: + insert the dummy prefix event `menu-bar'. */ + if (EQ (posn, Qmenu_bar)) + { + if (t + 1 >= bufsize) + error ("key sequence too long"); + /* Run the Lucid hook. */ + call1 (Vrun_hooks, Qactivate_menubar_hook); + /* If it has changed current-menubar from previous value, + really recompute the menubar from the value. */ + if (! NILP (Vlucid_menu_bar_dirty_flag)) + call0 (Qrecompute_lucid_menubar); + keybuf[t] = posn; + keybuf[t+1] = key; + + /* Zap the position in key, so we know that we've + expanded it, and don't try to do so again. */ + POSN_BUFFER_POSN (EVENT_START (key)) + = Fcons (posn, Qnil); + + mock_input = t + 2; + goto replay_sequence; + } + else if (XTYPE (posn) == Lisp_Cons) + { + /* We're looking at the second event of a + sequence which we expanded before. Set + last_real_key_start appropriately. */ + if (last_real_key_start == t && t > 0) + last_real_key_start = t - 1; + } } } @@ -3966,6 +3979,14 @@ { Lisp_Object head = EVENT_HEAD (key); + if (EQ (head, Vhelp_char)) + { + read_key_sequence_cmd = Vprefix_help_command; + keybuf[t++] = key; + last_nonmenu_event = key; + goto done; + } + if (XTYPE (head) == Lisp_Symbol) { Lisp_Object breakdown = parse_modifiers (head); @@ -5081,18 +5102,24 @@ Vlast_event_frame = Qnil; #endif - DEFVAR_LISP ("help-char", &help_char, + DEFVAR_LISP ("help-char", &Vhelp_char, "Character to recognize as meaning Help.\n\ When it is read, do `(eval help-form)', and display result if it's a string.\n\ If the value of `help-form' is nil, this char can be read normally."); - XSET (help_char, Lisp_Int, Ctl ('H')); + XSET (Vhelp_char, Lisp_Int, Ctl ('H')); DEFVAR_LISP ("help-form", &Vhelp_form, - "Form to execute when character help-char is read.\n\ + "Form to execute when character `help-char' is read.\n\ If the form returns a string, that string is displayed.\n\ If `help-form' is nil, the help char is not recognized."); Vhelp_form = Qnil; + DEFVAR_LISP ("prefix-help-command", &Vprefix_help_command, + "Command to run when `help-char' character follows a prefix key.\n\ +This command is used only when there is no actual binding\n\ +for that character after that prefix key."); + Vprefix_help_command = Qnil; + DEFVAR_LISP ("top-level", &Vtop_level, "Form to evaluate when Emacs starts up.\n\ Useful to set before you dump a modified Emacs."); @@ -5144,7 +5171,7 @@ Vpre_command_hook = Qnil; DEFVAR_LISP ("post-command-hook", &Vpost_command_hook, - "Normal hook run before each command is executed."); + "Normal hook run after each command is executed."); Vpost_command_hook = Qnil; DEFVAR_LISP ("lucid-menu-bar-dirty-flag", &Vlucid_menu_bar_dirty_flag,