diff options
| author | Richard M. Stallman | 1993-07-04 02:21:02 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1993-07-04 02:21:02 +0000 |
| commit | 7e85b93579088b041c61443ae19bba83ecffeab5 (patch) | |
| tree | 34ed6f9cc87e85b8bc3d9b19203b7a53dc49cc55 /src | |
| parent | 58bf6042169d93d1fbe96cab97be5c2999b63063 (diff) | |
| download | emacs-7e85b93579088b041c61443ae19bba83ecffeab5.tar.gz emacs-7e85b93579088b041c61443ae19bba83ecffeab5.zip | |
(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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/keyboard.c | 261 |
1 files changed, 144 insertions, 117 deletions
diff --git a/src/keyboard.c b/src/keyboard.c index 278f0dbb342..e0d7276a286 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -122,11 +122,14 @@ static int echoing; | |||
| 122 | int immediate_quit; | 122 | int immediate_quit; |
| 123 | 123 | ||
| 124 | /* Character to recognize as the help char. */ | 124 | /* Character to recognize as the help char. */ |
| 125 | Lisp_Object help_char; | 125 | Lisp_Object Vhelp_char; |
| 126 | 126 | ||
| 127 | /* Form to execute when help char is typed. */ | 127 | /* Form to execute when help char is typed. */ |
| 128 | Lisp_Object Vhelp_form; | 128 | Lisp_Object Vhelp_form; |
| 129 | 129 | ||
| 130 | /* Command to run when the help character follows a prefix key. */ | ||
| 131 | Lisp_Object Vprefix_help_command; | ||
| 132 | |||
| 130 | /* Character that causes a quit. Normally C-g. | 133 | /* Character that causes a quit. Normally C-g. |
| 131 | 134 | ||
| 132 | If we are running on an ordinary terminal, this must be an ordinary | 135 | If we are running on an ordinary terminal, this must be an ordinary |
| @@ -505,7 +508,7 @@ echo_char (c) | |||
| 505 | ptr += name->size; | 508 | ptr += name->size; |
| 506 | } | 509 | } |
| 507 | 510 | ||
| 508 | if (echoptr == echobuf && EQ (c, help_char)) | 511 | if (echoptr == echobuf && EQ (c, Vhelp_char)) |
| 509 | { | 512 | { |
| 510 | strcpy (ptr, " (Type ? for further options)"); | 513 | strcpy (ptr, " (Type ? for further options)"); |
| 511 | ptr += strlen (ptr); | 514 | ptr += strlen (ptr); |
| @@ -1480,7 +1483,10 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) | |||
| 1480 | consing going on to make it worthwhile. */ | 1483 | consing going on to make it worthwhile. */ |
| 1481 | if (!detect_input_pending () | 1484 | if (!detect_input_pending () |
| 1482 | && consing_since_gc > gc_cons_threshold / 2) | 1485 | && consing_since_gc > gc_cons_threshold / 2) |
| 1483 | Fgarbage_collect (); | 1486 | { |
| 1487 | Fgarbage_collect (); | ||
| 1488 | redisplay (); | ||
| 1489 | } | ||
| 1484 | } | 1490 | } |
| 1485 | } | 1491 | } |
| 1486 | } | 1492 | } |
| @@ -1587,7 +1593,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) | |||
| 1587 | num_input_chars++; | 1593 | num_input_chars++; |
| 1588 | 1594 | ||
| 1589 | /* Process the help character specially if enabled */ | 1595 | /* Process the help character specially if enabled */ |
| 1590 | if (EQ (c, help_char) && !NILP (Vhelp_form)) | 1596 | if (EQ (c, Vhelp_char) && !NILP (Vhelp_form)) |
| 1591 | { | 1597 | { |
| 1592 | Lisp_Object tem0; | 1598 | Lisp_Object tem0; |
| 1593 | count = specpdl_ptr - specpdl; | 1599 | count = specpdl_ptr - specpdl; |
| @@ -1914,7 +1920,7 @@ kbd_buffer_get_event () | |||
| 1914 | } | 1920 | } |
| 1915 | else if (do_mouse_tracking && mouse_moved) | 1921 | else if (do_mouse_tracking && mouse_moved) |
| 1916 | { | 1922 | { |
| 1917 | FRAME_PTR f; | 1923 | FRAME_PTR f = 0; |
| 1918 | Lisp_Object bar_window; | 1924 | Lisp_Object bar_window; |
| 1919 | enum scroll_bar_part part; | 1925 | enum scroll_bar_part part; |
| 1920 | Lisp_Object x, y; | 1926 | Lisp_Object x, y; |
| @@ -3802,6 +3808,9 @@ read_key_sequence (keybuf, bufsize, prompt) | |||
| 3802 | this_command_key_count = keys_local_start; | 3808 | this_command_key_count = keys_local_start; |
| 3803 | first_binding = local_first_binding; | 3809 | first_binding = local_first_binding; |
| 3804 | 3810 | ||
| 3811 | /* By default, assume each event is "real". */ | ||
| 3812 | last_real_key_start = t; | ||
| 3813 | |||
| 3805 | /* Does mock_input indicate that we are re-reading a key sequence? */ | 3814 | /* Does mock_input indicate that we are re-reading a key sequence? */ |
| 3806 | if (t < mock_input) | 3815 | if (t < mock_input) |
| 3807 | { | 3816 | { |
| @@ -3815,8 +3824,6 @@ read_key_sequence (keybuf, bufsize, prompt) | |||
| 3815 | { | 3824 | { |
| 3816 | struct buffer *buf = current_buffer; | 3825 | struct buffer *buf = current_buffer; |
| 3817 | 3826 | ||
| 3818 | last_real_key_start = t; | ||
| 3819 | |||
| 3820 | key = read_char (!prompt, nmaps, submaps, last_nonmenu_event, | 3827 | key = read_char (!prompt, nmaps, submaps, last_nonmenu_event, |
| 3821 | &used_mouse_menu); | 3828 | &used_mouse_menu); |
| 3822 | 3829 | ||
| @@ -3830,125 +3837,131 @@ read_key_sequence (keybuf, bufsize, prompt) | |||
| 3830 | } | 3837 | } |
| 3831 | 3838 | ||
| 3832 | Vquit_flag = Qnil; | 3839 | Vquit_flag = Qnil; |
| 3840 | } | ||
| 3833 | 3841 | ||
| 3834 | /* Clicks in non-text areas get prefixed by the symbol | 3842 | /* Clicks in non-text areas get prefixed by the symbol |
| 3835 | in their CHAR-ADDRESS field. For example, a click on | 3843 | in their CHAR-ADDRESS field. For example, a click on |
| 3836 | the mode line is prefixed by the symbol `mode-line'. | 3844 | the mode line is prefixed by the symbol `mode-line'. |
| 3837 | 3845 | ||
| 3838 | Furthermore, key sequences beginning with mouse clicks | 3846 | Furthermore, key sequences beginning with mouse clicks |
| 3839 | are read using the keymaps of the buffer clicked on, not | 3847 | are read using the keymaps of the buffer clicked on, not |
| 3840 | the current buffer. So we may have to switch the buffer | 3848 | the current buffer. So we may have to switch the buffer |
| 3841 | here. | 3849 | here. |
| 3850 | |||
| 3851 | When we turn one event into two events, we must make sure | ||
| 3852 | that neither of the two looks like the original--so that, | ||
| 3853 | if we replay the events, they won't be expanded again. | ||
| 3854 | If not for this, such reexpansion could happen either here | ||
| 3855 | or when user programs play with this-command-keys. */ | ||
| 3856 | if (EVENT_HAS_PARAMETERS (key)) | ||
| 3857 | { | ||
| 3858 | Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (key)); | ||
| 3842 | 3859 | ||
| 3843 | If the event was obtained from the unread_command_events | 3860 | if (EQ (kind, Qmouse_click)) |
| 3844 | queue, then don't expand it; we did that the first time | ||
| 3845 | we read it. */ | ||
| 3846 | if (EVENT_HAS_PARAMETERS (key)) | ||
| 3847 | { | 3861 | { |
| 3848 | Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (key)); | 3862 | Lisp_Object window = POSN_WINDOW (EVENT_START (key)); |
| 3863 | Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key)); | ||
| 3849 | 3864 | ||
| 3850 | if (EQ (kind, Qmouse_click)) | 3865 | if (XTYPE (posn) == Lisp_Cons) |
| 3851 | { | 3866 | { |
| 3852 | Lisp_Object window = POSN_WINDOW (EVENT_START (key)); | 3867 | /* We're looking at the second event of a |
| 3853 | Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key)); | 3868 | sequence which we expanded before. Set |
| 3854 | 3869 | last_real_key_start appropriately. */ | |
| 3855 | /* Key sequences beginning with mouse clicks are | 3870 | if (t > 0) |
| 3856 | read using the keymaps in the buffer clicked on, | 3871 | last_real_key_start = t - 1; |
| 3857 | not the current buffer. If we're at the | ||
| 3858 | beginning of a key sequence, switch buffers. */ | ||
| 3859 | if (t == 0 | ||
| 3860 | && XTYPE (window) == Lisp_Window | ||
| 3861 | && XTYPE (XWINDOW (window)->buffer) == Lisp_Buffer | ||
| 3862 | && XBUFFER (XWINDOW (window)->buffer) != current_buffer) | ||
| 3863 | { | ||
| 3864 | keybuf[t] = key; | ||
| 3865 | mock_input = t + 1; | ||
| 3866 | |||
| 3867 | /* Arrange to go back to the original buffer once we're | ||
| 3868 | done reading the key sequence. Note that we can't | ||
| 3869 | use save_excursion_{save,restore} here, because they | ||
| 3870 | save point as well as the current buffer; we don't | ||
| 3871 | want to save point, because redisplay may change it, | ||
| 3872 | to accommodate a Fset_window_start or something. We | ||
| 3873 | don't want to do this at the top of the function, | ||
| 3874 | because we may get input from a subprocess which | ||
| 3875 | wants to change the selected window and stuff (say, | ||
| 3876 | emacsclient). */ | ||
| 3877 | record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); | ||
| 3878 | |||
| 3879 | set_buffer_internal (XBUFFER (XWINDOW (window)->buffer)); | ||
| 3880 | goto replay_sequence; | ||
| 3881 | } | ||
| 3882 | else if (XTYPE (posn) == Lisp_Symbol) | ||
| 3883 | { | ||
| 3884 | if (t + 1 >= bufsize) | ||
| 3885 | error ("key sequence too long"); | ||
| 3886 | keybuf[t] = posn; | ||
| 3887 | keybuf[t+1] = key; | ||
| 3888 | mock_input = t + 2; | ||
| 3889 | |||
| 3890 | /* Zap the position in key, so we know that we've | ||
| 3891 | expanded it, and don't try to do so again. */ | ||
| 3892 | POSN_BUFFER_POSN (EVENT_START (key)) | ||
| 3893 | = Fcons (posn, Qnil); | ||
| 3894 | |||
| 3895 | /* If we switched buffers while reading the first event, | ||
| 3896 | replay in case we switched keymaps too. */ | ||
| 3897 | if (buf != current_buffer && t == 0) | ||
| 3898 | goto replay_sequence; | ||
| 3899 | goto replay_key; | ||
| 3900 | } | ||
| 3901 | else if (XTYPE (posn) == Lisp_Cons) | ||
| 3902 | { | ||
| 3903 | /* We're looking at the second event of a | ||
| 3904 | sequence which we expanded before. Set | ||
| 3905 | last_real_key_start appropriately. */ | ||
| 3906 | if (last_real_key_start == t && t > 0) | ||
| 3907 | last_real_key_start = t - 1; | ||
| 3908 | } | ||
| 3909 | } | 3872 | } |
| 3910 | else if (EQ (kind, Qswitch_frame)) | 3873 | |
| 3874 | /* Key sequences beginning with mouse clicks are | ||
| 3875 | read using the keymaps in the buffer clicked on, | ||
| 3876 | not the current buffer. If we're at the | ||
| 3877 | beginning of a key sequence, switch buffers. */ | ||
| 3878 | if (last_real_key_start == 0 | ||
| 3879 | && XTYPE (window) == Lisp_Window | ||
| 3880 | && XTYPE (XWINDOW (window)->buffer) == Lisp_Buffer | ||
| 3881 | && XBUFFER (XWINDOW (window)->buffer) != current_buffer) | ||
| 3911 | { | 3882 | { |
| 3912 | /* If we're at the beginning of a key sequence, go | 3883 | keybuf[t] = key; |
| 3913 | ahead and return this event. If we're in the | 3884 | mock_input = t + 1; |
| 3914 | midst of a key sequence, delay it until the end. */ | 3885 | |
| 3915 | if (t > 0) | 3886 | /* Arrange to go back to the original buffer once we're |
| 3916 | { | 3887 | done reading the key sequence. Note that we can't |
| 3917 | delayed_switch_frame = key; | 3888 | use save_excursion_{save,restore} here, because they |
| 3918 | goto replay_key; | 3889 | save point as well as the current buffer; we don't |
| 3919 | } | 3890 | want to save point, because redisplay may change it, |
| 3891 | to accommodate a Fset_window_start or something. We | ||
| 3892 | don't want to do this at the top of the function, | ||
| 3893 | because we may get input from a subprocess which | ||
| 3894 | wants to change the selected window and stuff (say, | ||
| 3895 | emacsclient). */ | ||
| 3896 | record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); | ||
| 3897 | |||
| 3898 | set_buffer_internal (XBUFFER (XWINDOW (window)->buffer)); | ||
| 3899 | goto replay_sequence; | ||
| 3920 | } | 3900 | } |
| 3921 | else | 3901 | else if (XTYPE (posn) == Lisp_Symbol) |
| 3922 | { | 3902 | { |
| 3923 | Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key)); | 3903 | /* Expand mode-line and scroll-bar events into two events: |
| 3904 | use posn as a fake prefix key. */ | ||
| 3924 | 3905 | ||
| 3925 | /* Handle menu-bar events: | 3906 | if (t + 1 >= bufsize) |
| 3926 | insert the dummy prefix char `menu-bar'. */ | 3907 | error ("key sequence too long"); |
| 3927 | if (EQ (posn, Qmenu_bar)) | 3908 | keybuf[t] = posn; |
| 3928 | { | 3909 | keybuf[t+1] = key; |
| 3929 | if (t + 1 >= bufsize) | 3910 | mock_input = t + 2; |
| 3930 | error ("key sequence too long"); | 3911 | |
| 3931 | /* Run the Lucid hook. */ | 3912 | /* Zap the position in key, so we know that we've |
| 3932 | call1 (Vrun_hooks, Qactivate_menubar_hook); | 3913 | expanded it, and don't try to do so again. */ |
| 3933 | /* If it has changed current-menubar from previous value, | 3914 | POSN_BUFFER_POSN (EVENT_START (key)) |
| 3934 | really recompute the menubar from the value. */ | 3915 | = Fcons (posn, Qnil); |
| 3935 | if (! NILP (Vlucid_menu_bar_dirty_flag)) | 3916 | goto replay_key; |
| 3936 | call0 (Qrecompute_lucid_menubar); | ||
| 3937 | keybuf[t] = posn; | ||
| 3938 | keybuf[t+1] = key; | ||
| 3939 | mock_input = t + 2; | ||
| 3940 | goto replay_sequence; | ||
| 3941 | } | ||
| 3942 | } | 3917 | } |
| 3943 | } | 3918 | } |
| 3944 | 3919 | else if (EQ (kind, Qswitch_frame)) | |
| 3945 | /* If we switched buffers while reading the first event, | ||
| 3946 | replay in case we switched keymaps too. */ | ||
| 3947 | if (buf != current_buffer && t == 0) | ||
| 3948 | { | 3920 | { |
| 3949 | keybuf[t++] = key; | 3921 | /* If we're at the beginning of a key sequence, go |
| 3950 | mock_input = t; | 3922 | ahead and return this event. If we're in the |
| 3951 | goto replay_sequence; | 3923 | midst of a key sequence, delay it until the end. */ |
| 3924 | if (t > 0) | ||
| 3925 | { | ||
| 3926 | delayed_switch_frame = key; | ||
| 3927 | goto replay_key; | ||
| 3928 | } | ||
| 3929 | } | ||
| 3930 | else | ||
| 3931 | { | ||
| 3932 | Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key)); | ||
| 3933 | |||
| 3934 | /* Handle menu-bar events: | ||
| 3935 | insert the dummy prefix event `menu-bar'. */ | ||
| 3936 | if (EQ (posn, Qmenu_bar)) | ||
| 3937 | { | ||
| 3938 | if (t + 1 >= bufsize) | ||
| 3939 | error ("key sequence too long"); | ||
| 3940 | /* Run the Lucid hook. */ | ||
| 3941 | call1 (Vrun_hooks, Qactivate_menubar_hook); | ||
| 3942 | /* If it has changed current-menubar from previous value, | ||
| 3943 | really recompute the menubar from the value. */ | ||
| 3944 | if (! NILP (Vlucid_menu_bar_dirty_flag)) | ||
| 3945 | call0 (Qrecompute_lucid_menubar); | ||
| 3946 | keybuf[t] = posn; | ||
| 3947 | keybuf[t+1] = key; | ||
| 3948 | |||
| 3949 | /* Zap the position in key, so we know that we've | ||
| 3950 | expanded it, and don't try to do so again. */ | ||
| 3951 | POSN_BUFFER_POSN (EVENT_START (key)) | ||
| 3952 | = Fcons (posn, Qnil); | ||
| 3953 | |||
| 3954 | mock_input = t + 2; | ||
| 3955 | goto replay_sequence; | ||
| 3956 | } | ||
| 3957 | else if (XTYPE (posn) == Lisp_Cons) | ||
| 3958 | { | ||
| 3959 | /* We're looking at the second event of a | ||
| 3960 | sequence which we expanded before. Set | ||
| 3961 | last_real_key_start appropriately. */ | ||
| 3962 | if (last_real_key_start == t && t > 0) | ||
| 3963 | last_real_key_start = t - 1; | ||
| 3964 | } | ||
| 3952 | } | 3965 | } |
| 3953 | } | 3966 | } |
| 3954 | 3967 | ||
| @@ -3966,6 +3979,14 @@ read_key_sequence (keybuf, bufsize, prompt) | |||
| 3966 | { | 3979 | { |
| 3967 | Lisp_Object head = EVENT_HEAD (key); | 3980 | Lisp_Object head = EVENT_HEAD (key); |
| 3968 | 3981 | ||
| 3982 | if (EQ (head, Vhelp_char)) | ||
| 3983 | { | ||
| 3984 | read_key_sequence_cmd = Vprefix_help_command; | ||
| 3985 | keybuf[t++] = key; | ||
| 3986 | last_nonmenu_event = key; | ||
| 3987 | goto done; | ||
| 3988 | } | ||
| 3989 | |||
| 3969 | if (XTYPE (head) == Lisp_Symbol) | 3990 | if (XTYPE (head) == Lisp_Symbol) |
| 3970 | { | 3991 | { |
| 3971 | Lisp_Object breakdown = parse_modifiers (head); | 3992 | Lisp_Object breakdown = parse_modifiers (head); |
| @@ -5081,18 +5102,24 @@ If the last event came from a keyboard macro, this is set to `macro'."); | |||
| 5081 | Vlast_event_frame = Qnil; | 5102 | Vlast_event_frame = Qnil; |
| 5082 | #endif | 5103 | #endif |
| 5083 | 5104 | ||
| 5084 | DEFVAR_LISP ("help-char", &help_char, | 5105 | DEFVAR_LISP ("help-char", &Vhelp_char, |
| 5085 | "Character to recognize as meaning Help.\n\ | 5106 | "Character to recognize as meaning Help.\n\ |
| 5086 | When it is read, do `(eval help-form)', and display result if it's a string.\n\ | 5107 | When it is read, do `(eval help-form)', and display result if it's a string.\n\ |
| 5087 | If the value of `help-form' is nil, this char can be read normally."); | 5108 | If the value of `help-form' is nil, this char can be read normally."); |
| 5088 | XSET (help_char, Lisp_Int, Ctl ('H')); | 5109 | XSET (Vhelp_char, Lisp_Int, Ctl ('H')); |
| 5089 | 5110 | ||
| 5090 | DEFVAR_LISP ("help-form", &Vhelp_form, | 5111 | DEFVAR_LISP ("help-form", &Vhelp_form, |
| 5091 | "Form to execute when character help-char is read.\n\ | 5112 | "Form to execute when character `help-char' is read.\n\ |
| 5092 | If the form returns a string, that string is displayed.\n\ | 5113 | If the form returns a string, that string is displayed.\n\ |
| 5093 | If `help-form' is nil, the help char is not recognized."); | 5114 | If `help-form' is nil, the help char is not recognized."); |
| 5094 | Vhelp_form = Qnil; | 5115 | Vhelp_form = Qnil; |
| 5095 | 5116 | ||
| 5117 | DEFVAR_LISP ("prefix-help-command", &Vprefix_help_command, | ||
| 5118 | "Command to run when `help-char' character follows a prefix key.\n\ | ||
| 5119 | This command is used only when there is no actual binding\n\ | ||
| 5120 | for that character after that prefix key."); | ||
| 5121 | Vprefix_help_command = Qnil; | ||
| 5122 | |||
| 5096 | DEFVAR_LISP ("top-level", &Vtop_level, | 5123 | DEFVAR_LISP ("top-level", &Vtop_level, |
| 5097 | "Form to evaluate when Emacs starts up.\n\ | 5124 | "Form to evaluate when Emacs starts up.\n\ |
| 5098 | Useful to set before you dump a modified Emacs."); | 5125 | Useful to set before you dump a modified Emacs."); |
| @@ -5144,7 +5171,7 @@ Buffer modification stores t in this variable."); | |||
| 5144 | Vpre_command_hook = Qnil; | 5171 | Vpre_command_hook = Qnil; |
| 5145 | 5172 | ||
| 5146 | DEFVAR_LISP ("post-command-hook", &Vpost_command_hook, | 5173 | DEFVAR_LISP ("post-command-hook", &Vpost_command_hook, |
| 5147 | "Normal hook run before each command is executed."); | 5174 | "Normal hook run after each command is executed."); |
| 5148 | Vpost_command_hook = Qnil; | 5175 | Vpost_command_hook = Qnil; |
| 5149 | 5176 | ||
| 5150 | DEFVAR_LISP ("lucid-menu-bar-dirty-flag", &Vlucid_menu_bar_dirty_flag, | 5177 | DEFVAR_LISP ("lucid-menu-bar-dirty-flag", &Vlucid_menu_bar_dirty_flag, |