X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/3c37094348fddcd44941e7c65acd0ab19a5e131d..28d3ed91adb431470f8ee9b84941779709df9b8b:/src/keyboard.c diff --git a/src/keyboard.c b/src/keyboard.c index 61c57fe4c7..733a944ff3 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1,5 +1,5 @@ /* Keyboard and mouse input; editor command loop. - Copyright (C) 1985, 1986, 1987, 1988, 1989, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -35,6 +35,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "disptab.h" #include "dispextern.h" #include "keyboard.h" +#include "intervals.h" +#include "blockinput.h" #include #include @@ -48,6 +50,16 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ extern int errno; +/* Variables for blockinput.h: */ + +/* Non-zero if interrupt input is blocked right now. */ +int interrupt_input_blocked; + +/* Nonzero means an input interrupt has arrived + during the current critical section. */ +int interrupt_input_pending; + + #ifdef HAVE_X_WINDOWS extern Lisp_Object Vmouse_grabbed; @@ -155,6 +167,9 @@ Lisp_Object last_input_char; /* If not Qnil, a list of objects to be read as subsequent command input. */ Lisp_Object unread_command_events; +/* If not -1, an event to be read as subsequent command input. */ +int unread_command_char; + /* If not Qnil, this is a switch-frame event which we decided to put off until the end of a key sequence. This should be read as the next command input, after any unread_command_events. @@ -238,13 +253,27 @@ Lisp_Object Vkeyboard_translate_table; /* Keymap mapping ASCII function key sequences onto their preferred forms. */ extern Lisp_Object Vfunction_key_map; +/* Non-nil means deactivate the mark at end of this command. */ +Lisp_Object Vdeactivate_mark; + +/* Menu bar specified in Lucid Emacs fashion. */ + +Lisp_Object Vlucid_menu_bar_dirty_flag; +Lisp_Object Qrecompute_lucid_menubar, Qactivate_menubar_hook; + +/* Hooks to run before and after each command. */ +Lisp_Object Qpre_command_hook, Qpost_command_hook; +Lisp_Object Vpre_command_hook, Vpost_command_hook; + /* File in which we write all commands we read. */ FILE *dribble; /* Nonzero if input is available. */ int input_pending; -/* Nonzero if should obey 0200 bit in input chars as "Meta". */ +/* 1 if should obey 0200 bit in input chars as "Meta", 2 if should + keep 0200 bit in input chars. 0 to ignore the 0200 bit. */ + int meta_key; extern char *pending_malloc_warning; @@ -303,10 +332,10 @@ static struct input_event *kbd_store_ptr; dequeuing functions? Such a flag could be screwed up by interrupts at inopportune times. */ -/* If this flag is non-zero, we will check mouse_moved to see when the +/* If this flag is non-zero, we check mouse_moved to see when the mouse moves, and motion events will appear in the input stream. If - it is zero, mouse motion will be ignored. */ -int do_mouse_tracking; + it is zero, mouse motion is ignored. */ +static int do_mouse_tracking; /* The window system handling code should set this if the mouse has moved since the last call to the mouse_position_hook. Calling that @@ -327,7 +356,6 @@ int mouse_moved; /* Symbols to head events. */ Lisp_Object Qmouse_movement; Lisp_Object Qscroll_bar_movement; - Lisp_Object Qswitch_frame; /* Symbols to denote kinds of events. */ @@ -339,6 +367,8 @@ Lisp_Object Qmouse_click; Lisp_Object Qevent_kind; Lisp_Object Qevent_symbol_elements; +Lisp_Object Qmenu_enable; + /* An event header symbol HEAD may have a property named Qevent_symbol_element_mask, which is of the form (BASE MODIFIERS); BASE is the base, unmodified version of HEAD, and MODIFIERS is the @@ -352,10 +382,13 @@ Lisp_Object Qevent_symbol_element_mask; apply_modifiers. */ Lisp_Object Qmodifier_cache; -/* Symbols to use for non-text mouse positions. */ +/* Symbols to use for parts of windows. */ Lisp_Object Qmode_line; Lisp_Object Qvertical_line; Lisp_Object Qvertical_scroll_bar; +Lisp_Object Qmenu_bar; + +extern Lisp_Object Qmenu_enable; Lisp_Object recursive_edit_unwind (), command_loop (); Lisp_Object Fthis_command_keys (); @@ -491,6 +524,9 @@ echo_dash () { if (!immediate_echo && echoptr == echobuf) return; + /* Do nothing if not echoing at all. */ + if (echoptr == 0) + return; /* Put a dash at the end of the buffer temporarily, but make it go away when the next character is added. */ @@ -821,15 +857,18 @@ static int read_key_sequence (); Lisp_Object command_loop_1 () { - Lisp_Object cmd; + Lisp_Object cmd, tem; int lose; int nonundocount; Lisp_Object keybuf[30]; int i; int no_redisplay; int no_direct; + int prev_modiff; + struct buffer *prev_buffer; Vprefix_arg = Qnil; + Vdeactivate_mark = Qnil; waiting_for_input = 0; cancel_echoing (); @@ -860,6 +899,8 @@ command_loop_1 () no_direct = 0; + Vdeactivate_mark = Qnil; + /* If minibuffer on and echo area in use, wait 2 sec and redraw minibufer. */ @@ -897,6 +938,39 @@ command_loop_1 () Fselect_frame (internal_last_event_frame, Qnil); #endif #endif + /* 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); + +#if 0 /* This is done in xdisp.c now. */ +#ifdef MULTI_FRAME + for (tem = Vframe_list; CONSP (tem); tem = XCONS (tem)->cdr) + { + struct frame *f = XFRAME (XCONS (tem)->car); + struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f)); + + /* If the user has switched buffers or windows, we need to + recompute to reflect the new bindings. But we'll + recompute when update_mode_lines is set too; that means + that people can use force-mode-line-update to request + that the menu bar be recomputed. The adverse effect on + the rest of the redisplay algorithm is about the same as + windows_or_buffers_changed anyway. */ + if (windows_or_buffers_changed + || update_mode_lines + || (XFASTINT (w->last_modified) < MODIFF + && (XFASTINT (w->last_modified) + <= XBUFFER (w->buffer)->save_modified))) + { + struct buffer *prev = current_buffer; + current_buffer = XBUFFER (w->buffer); + FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (); + current_buffer = prev; + } + } +#endif /* MULTI_FRAME */ +#endif /* 0 */ /* Read next key sequence; i gets its length. */ i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])), 0); @@ -911,6 +985,11 @@ command_loop_1 () last_command_char = keybuf[i - 1]; + /* If the previous command tried to force a specific window-start, + forget about that, in case this command moves point far away + from that position. */ + XWINDOW (selected_window)->force_start = Qnil; + cmd = read_key_sequence_cmd; if (!NILP (Vexecuting_macro)) { @@ -926,8 +1005,15 @@ command_loop_1 () cases identified below that set no_redisplay to 1. */ no_redisplay = 0; + prev_buffer = current_buffer; + prev_modiff = MODIFF; + /* Execute the command. */ + this_command = cmd; + if (!NILP (Vpre_command_hook)) + call1 (Vrun_hooks, Qpre_command_hook); + if (NILP (cmd)) { /* nil means key is undefined. */ @@ -935,10 +1021,10 @@ command_loop_1 () defining_kbd_macro = 0; update_mode_lines = 1; Vprefix_arg = Qnil; + } else { - this_command = cmd; if (NILP (Vprefix_arg) && ! no_direct) { /* Recognize some common commands in common situations and @@ -949,10 +1035,10 @@ command_loop_1 () = window_display_table (XWINDOW (selected_window)); lose = FETCH_CHAR (point); SET_PT (point + 1); - if (((dp == 0 && lose >= 040 && lose < 0177) - || - (dp && (XTYPE (dp->contents[lose]) != Lisp_String - || XSTRING (dp->contents[lose])->size == sizeof (GLYPH)))) + if ((dp + ? (XTYPE (DISP_CHAR_VECTOR (dp, lose)) != Lisp_Vector + && XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1) + : (lose >= 0x20 && lose < 0x7f)) && (XFASTINT (XWINDOW (selected_window)->last_modified) >= MODIFF) && (XFASTINT (XWINDOW (selected_window)->last_point) @@ -970,10 +1056,10 @@ command_loop_1 () = window_display_table (XWINDOW (selected_window)); SET_PT (point - 1); lose = FETCH_CHAR (point); - if (((dp == 0 && lose >= 040 && lose < 0177) - || - (dp && (XTYPE (dp->contents[lose]) != Lisp_String - || XSTRING (dp->contents[lose])->size == sizeof (GLYPH)))) + if ((dp + ? (XTYPE (DISP_CHAR_VECTOR (dp, lose)) != Lisp_Vector + && XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1) + : (lose >= 0x20 && lose < 0x7f)) && (XFASTINT (XWINDOW (selected_window)->last_modified) >= MODIFF) && (XFASTINT (XWINDOW (selected_window)->last_point) @@ -1020,13 +1106,24 @@ command_loop_1 () { struct Lisp_Vector *dp = window_display_table (XWINDOW (selected_window)); + int lose = XINT (c); - if (dp == 0 || XTYPE (dp->contents[c]) != Lisp_String) - no_redisplay = direct_output_for_insert (XINT (c)); - else if (XSTRING (dp->contents[c])->size - == sizeof (GLYPH)) - no_redisplay = - direct_output_for_insert (*(GLYPH *)XSTRING (dp->contents[c])->data); + if (dp) + { + Lisp_Object obj = DISP_CHAR_VECTOR (dp, lose); + + if (XTYPE (obj) == Lisp_Vector + && XVECTOR (obj)->size == 1 + && (XTYPE (obj = XVECTOR (obj)->contents[0]) + == Lisp_Int)) + no_redisplay = + direct_output_for_insert (XINT (obj)); + } + else + { + if (lose >= 0x20 && lose <= 0x7e) + no_redisplay = direct_output_for_insert (lose); + } } goto directly_done; } @@ -1042,6 +1139,9 @@ command_loop_1 () } directly_done: ; + if (!NILP (Vpost_command_hook)) + call1 (Vrun_hooks, Qpost_command_hook); + /* If there is a prefix argument, 1) We don't want last_command to be ``universal-argument'' (that would be dumb), so don't set last_command, @@ -1057,6 +1157,17 @@ command_loop_1 () cancel_echoing (); this_command_key_count = 0; } + + if (!NILP (current_buffer->mark_active)) + { + if (!NILP (Vdeactivate_mark) && !NILP (Vtransient_mark_mode)) + { + current_buffer->mark_active = Qnil; + call1 (Vrun_hooks, intern ("deactivate-mark-hook")); + } + else if (current_buffer != prev_buffer || MODIFF != prev_modiff) + call1 (Vrun_hooks, intern ("activate-mark-hook")); + } } } @@ -1075,12 +1186,9 @@ int polling_for_input; SIGTYPE input_poll_signal () { -#ifdef HAVE_X_WINDOWS - extern int x_input_blocked; - if (x_input_blocked == 0) -#endif - if (!waiting_for_input) - read_avail_input (0); + if (interrupt_input_blocked == 0 + && !waiting_for_input) + read_avail_input (0); signal (SIGALRM, input_poll_signal); alarm (polling_period); } @@ -1166,6 +1274,17 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) goto reread; } + if (unread_command_char != -1) + { + XSET (c, Lisp_Int, unread_command_char); + unread_command_char = -1; + + if (this_command_key_count == 0) + goto reread_first; + else + goto reread; + } + if (!NILP (Vexecuting_macro)) { #ifdef MULTI_FRAME @@ -1182,13 +1301,21 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) Vlast_event_frame = internal_last_event_frame = Qmacro; #endif - if (executing_macro_index >= XFASTINT (Flength (Vexecuting_macro))) + /* Exit the macro if we are at the end. + Also, some things replace the macro with t + to force an early exit. */ + if (EQ (Vexecuting_macro, Qt) + || executing_macro_index >= XFASTINT (Flength (Vexecuting_macro))) { XSET (c, Lisp_Int, -1); return c; } c = Faref (Vexecuting_macro, make_number (executing_macro_index)); + if (XTYPE (Vexecuting_macro) == Lisp_String + && (XINT (c) & 0x80)) + XFASTINT (c) = CHAR_META | (XINT (c) & ~0x80); + executing_macro_index++; goto from_macro; @@ -1219,6 +1346,10 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) XSET (internal_last_event_frame, Lisp_Frame, selected_frame); Vlast_event_frame = internal_last_event_frame; #endif + /* If we report the quit char as an event, + don't do so more than once. */ + if (!NILP (Vinhibit_quit)) + Vquit_flag = Qnil; goto non_reread; } @@ -1325,11 +1456,38 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) if (noninteractive && XTYPE (c) == Lisp_Int && XINT (c) < 0) Fkill_emacs (make_number (1)); - /* Test for ControlMask and Mod1Mask. */ - if (extra_keyboard_modifiers & 4) - c &= ~0140; - if (extra_keyboard_modifiers & 8) - c |= 0200; + if (XTYPE (c) == Lisp_Int) + { + /* Add in any extra modifiers, where appropriate. */ + if ((extra_keyboard_modifiers & CHAR_CTL) + || ((extra_keyboard_modifiers & 0177) < ' ' + && (extra_keyboard_modifiers & 0177) != 0)) + { + /* If it's already a control character, don't mess with it. */ + if ((c & 0177) == 0) + ; + + /* Making ? a control character should result in DEL. */ + else if ((c & 0177) == '?') + c |= 0177; + + /* ASCII control chars are made from letters (both cases), + as well as the non-letters within 0100...0137. */ + else if ((c & 0137) >= 0101 && (c & 0137) <= 0132) + c = (c & (037 | ~0177)); + else if ((c & 0177) >= 0100 && (c & 0177) <= 0137) + c = (c & (037 | ~0177)); + + /* Anything else must get its high control bit set. */ + else + c = c | ctrl_modifier; + } + + /* Transfer any other modifier bits directly from + extra_keyboard_modifiers to c. Ignore the actual character code + in the low 16 bits of extra_keyboard_modifiers. */ + c |= (extra_keyboard_modifiers & ~0xff7f & ~CHAR_CTL); + } non_reread: @@ -1343,12 +1501,9 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) if (XTYPE (c) == Lisp_Int) { /* If kbd_buffer_get_event gave us an EOF, return that. */ - if (XINT (c) < 0) + if (XINT (c) == -1) return c; - /* Strip the high bits, and maybe the meta bit too. */ - XSETINT (c, XINT (c) & (meta_key ? 0377 : 0177)); - if (XTYPE (Vkeyboard_translate_table) == Lisp_String && XSTRING (Vkeyboard_translate_table)->size > XFASTINT (c)) XSETINT (c, XSTRING (Vkeyboard_translate_table)->data[XFASTINT (c)]); @@ -1537,8 +1692,7 @@ kbd_buffer_store_event (event) { register int c = XFASTINT (event->code) & 0377; - if (c == quit_char - || ((c == (0200 | quit_char)) && !meta_key)) + if (c == quit_char) { extern SIGTYPE interrupt_signal (); @@ -1616,6 +1770,7 @@ kbd_buffer_get_event () return obj; } + retry: /* Wait until there is input available. */ for (;;) { @@ -1667,6 +1822,34 @@ kbd_buffer_get_event () obj = Qnil; + /* These two kinds of events get special handling + and don't actually appear to the command loop. */ + if (event->kind == selection_request_event) + { +#ifdef HAVE_X11 + x_handle_selection_request (event); + kbd_fetch_ptr = event + 1; + goto retry; +#else + /* We're getting selection request events, but we don't have + a window system. */ + abort (); +#endif + } + + if (event->kind == selection_clear_event) + { +#ifdef HAVE_X11 + x_handle_selection_clear (event); + kbd_fetch_ptr = event + 1; + goto retry; +#else + /* We're getting selection request events, but we don't have + a window system. */ + abort (); +#endif + } + #ifdef MULTI_FRAME /* If this event is on a different frame, return a switch-frame this time, and leave the event in the queue for next time. */ @@ -1681,11 +1864,10 @@ kbd_buffer_get_event () if (! NILP (focus)) frame = focus; - if (! EQ (frame, internal_last_event_frame)) - { - internal_last_event_frame = frame; - obj = make_lispy_switch_frame (frame); - } + if (! EQ (frame, internal_last_event_frame) + && XFRAME (frame) != selected_frame) + obj = make_lispy_switch_frame (frame); + internal_last_event_frame = frame; } #endif @@ -1694,8 +1876,6 @@ kbd_buffer_get_event () if (NILP (obj)) { obj = make_lispy_event (event); - if (XTYPE (obj) == Lisp_Int) - XSET (obj, Lisp_Int, XINT (obj) & (meta_key ? 0377 : 0177)); /* Wipe out this event, to catch bugs. */ event->kind = no_event; @@ -1728,11 +1908,10 @@ kbd_buffer_get_event () if (NILP (frame)) XSET (frame, Lisp_Frame, f); - if (! EQ (frame, internal_last_event_frame)) - { - XSET (internal_last_event_frame, Lisp_Frame, frame); - obj = make_lispy_switch_frame (internal_last_event_frame); - } + if (! EQ (frame, internal_last_event_frame) + && XFRAME (frame) != selected_frame) + obj = make_lispy_switch_frame (internal_last_event_frame); + internal_last_event_frame = frame; } #endif @@ -1746,6 +1925,11 @@ kbd_buffer_get_event () something for us to read! */ abort (); + /* If something gave back nil as the Lispy event, + it means the event was discarded, so try again. */ + if (NILP (obj)) + goto retry; + input_pending = readable_events (); #ifdef MULTI_FRAME @@ -1766,6 +1950,23 @@ static char *lispy_function_keys[] = { /* X Keysym value */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff00 */ + "backspace", + "tab", + "linefeed", + "clear", + 0, + "return", + 0, 0, + 0, 0, 0, /* 0xff10 */ + "pause", + 0, 0, 0, 0, 0, 0, 0, + "escape", + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff20...2f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff30...3f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff40...4f */ + "home", /* 0xff50 */ /* IsCursorKey */ "left", "up", @@ -1829,11 +2030,15 @@ static char *lispy_function_keys[] = 0, 0, "kp-equal", /* 0xffbd */ "f1", /* 0xffbe */ /* IsFunctionKey */ - "f2", "f3", "f4", - "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", - "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", - "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", - "f29", "f30", "f31", "f32", "f33", "f34", "f35" /* 0xffe0 */ + "f2", + "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", /* 0xffc0 */ + "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", + "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", /* 0xffd0 */ + "f27", "f28", "f29", "f30", "f31", "f32", "f33", "f34", + "f35", 0, 0, 0, 0, 0, 0, 0, /* 0xffe0 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xfff0 */ + 0, 0, 0, 0, 0, 0, 0, "delete" }; static char *lispy_mouse_names[] = @@ -1883,8 +2088,33 @@ make_lispy_event (event) { /* A simple keystroke. */ case ascii_keystroke: - return XFASTINT (event->code); - break; + { + int c = XFASTINT (event->code); + /* Turn ASCII characters into control characters + when proper. */ + if (event->modifiers & ctrl_modifier) + { + if (c >= 0100 && c < 0140) + { + int oc = c; + c &= ~0140; + /* Set the shift modifier for a control char + made from a shifted letter. But only for letters! */ + if (oc >= 'A' && oc <= 'Z') + c |= shift_modifier; + } + else if (c >= 'a' && c <= 'z') + c &= ~0140; + /* Include the bits for control and shift + only if the basic ASCII code can't indicate them. */ + else + c |= ctrl_modifier; + } + c |= (event->modifiers + & (meta_modifier | alt_modifier + | hyper_modifier | super_modifier)); + return c; + } /* A function key. The symbol may need to have modifier prefixes tacked onto it. */ @@ -1913,13 +2143,40 @@ make_lispy_event (event) if (event->kind == mouse_click) { int part; - Lisp_Object window = - window_from_coordinates (XFRAME (event->frame_or_window), - XINT (event->x), XINT (event->y), - &part); + FRAME_PTR f = XFRAME (event->frame_or_window); + Lisp_Object window + = window_from_coordinates (f, XINT (event->x), XINT (event->y), + &part); Lisp_Object posn; - if (XTYPE (window) != Lisp_Window) + if (XINT (event->y) < FRAME_MENU_BAR_LINES (f)) + { + int hpos; + Lisp_Object items; + items = FRAME_MENU_BAR_ITEMS (f); + for (; CONSP (items); items = XCONS (items)->cdr) + { + Lisp_Object pos, string; + pos = Fcdr (Fcdr (Fcar (items))); + string = Fcar (Fcdr (Fcar (items))); + if (XINT (event->x) > XINT (pos) + && XINT (event->x) <= XINT (pos) + XSTRING (string)->size) + break; + } + position + = Fcons (event->frame_or_window, + Fcons (Qmenu_bar, + Fcons (Fcons (event->x, event->y), + Fcons (make_number (event->timestamp), + Qnil)))); + + if (CONSP (items)) + return Fcons (Fcar (Fcar (items)), + Fcons (position, Qnil)); + else + return Fcons (Qnil, Fcons (position, Qnil)); + } + else if (XTYPE (window) != Lisp_Window) posn = Qnil; else { @@ -1939,12 +2196,12 @@ make_lispy_event (event) XINT (event->y))); } - position = - Fcons (window, - Fcons (posn, - Fcons (Fcons (event->x, event->y), - Fcons (make_number (event->timestamp), - Qnil)))); + position + = Fcons (window, + Fcons (posn, + Fcons (Fcons (event->x, event->y), + Fcons (make_number (event->timestamp), + Qnil)))); } else { @@ -1975,19 +2232,22 @@ make_lispy_event (event) see if this was a click or a drag. */ else if (event->modifiers & up_modifier) { - /* Is there a start position stored at all for this - button? - - It would be nice if we could assume that if we're - getting a button release, we must therefore have gotten - a button press. Unfortunately, the X menu code thwarts - this assumption, so we'll have to be more robust. We - treat a button release with no stored start position as - a click. */ + /* If we did not see a down before this up, + ignore the up. Probably this happened because + the down event chose a menu item. + It would be an annoyance to treat the release + of the button that chose the menu item + as a separate event. */ + + if (XTYPE (start_pos) != Lisp_Cons) + return Qnil; + event->modifiers &= ~up_modifier; +#if 0 /* Formerly we treated an up with no down as a click event. */ if (XTYPE (start_pos) != Lisp_Cons) event->modifiers |= click_modifier; else +#endif { /* The third element of every position should be the (x,y) pair. */ @@ -2006,13 +2266,13 @@ make_lispy_event (event) { /* Get the symbol we should use for the mouse click. */ - Lisp_Object head = - modify_event_symbol (button, - event->modifiers, - Qmouse_click, - lispy_mouse_names, &mouse_syms, - (sizeof (lispy_mouse_names) - / sizeof (lispy_mouse_names[0]))); + Lisp_Object head + = modify_event_symbol (button, + event->modifiers, + Qmouse_click, + lispy_mouse_names, &mouse_syms, + (sizeof (lispy_mouse_names) + / sizeof (lispy_mouse_names[0]))); if (event->modifiers & drag_modifier) return Fcons (head, @@ -2028,7 +2288,7 @@ make_lispy_event (event) /* The 'kind' field of the event is something we don't recognize. */ default: - abort(); + abort (); } } @@ -2095,7 +2355,6 @@ make_lispy_movement (frame, bar_window, part, x, y, time) } } - /* Construct a switch frame event. */ static Lisp_Object make_lispy_switch_frame (frame) @@ -2103,7 +2362,6 @@ make_lispy_switch_frame (frame) { return Fcons (Qswitch_frame, Fcons (frame, Qnil)); } - /* Manipulating modifiers. */ @@ -2159,11 +2417,7 @@ parse_modifiers_uncached (symbol, modifier_end) break; case 's': - if (i + 6 > name->size - || strncmp (name->data + i, "super-", 6)) - goto no_more_modifiers; - modifiers |= super_modifier; - i += 6; + SINGLE_LETTER_MOD (super_modifier); break; case 'd': @@ -2217,7 +2471,7 @@ apply_modifiers_uncached (modifiers, base, base_len) to use Fintern, which expects a genuine Lisp_String, and keeps a reference to it. */ char *new_mods = - (char *) alloca (sizeof ("A-C-H-M-S-super-down-drag-")); + (char *) alloca (sizeof ("A-C-H-M-S-s-down-drag-")); int mod_len; { @@ -2233,7 +2487,7 @@ apply_modifiers_uncached (modifiers, base, base_len) if (modifiers & hyper_modifier) { *p++ = 'H'; *p++ = '-'; } if (modifiers & meta_modifier) { *p++ = 'M'; *p++ = '-'; } if (modifiers & shift_modifier) { *p++ = 'S'; *p++ = '-'; } - if (modifiers & super_modifier) { strcpy (p, "super-"); p += 6; } + if (modifiers & super_modifier) { *p++ = 's'; *p++ = '-'; } if (modifiers & down_modifier) { strcpy (p, "down-"); p += 5; } if (modifiers & drag_modifier) { strcpy (p, "drag-"); p += 5; } /* The click modifier is denoted by the absence of other modifiers. */ @@ -2256,9 +2510,11 @@ apply_modifiers_uncached (modifiers, base, base_len) static char *modifier_names[] = { - "up", "alt", "control", "hyper", "meta", "shift", "super", "down", "drag", - "click" + "up", 0, 0, 0, 0, 0, 0, "down", + "drag", "click", 0, 0, 0, 0, 0, 0, + 0, 0, "alt", "super", "hyper", "shift", "control", "meta" }; +#define NUM_MOD_NAMES (sizeof (modifier_names) / sizeof (modifier_names[0])) static Lisp_Object modifier_symbols; @@ -2271,14 +2527,10 @@ lispy_modifier_list (modifiers) int i; modifier_list = Qnil; - for (i = 0; (1<= XVECTOR (modifier_symbols)->size) - abort (); - modifier_list = Fcons (XVECTOR (modifier_symbols)->contents[i], - modifier_list); - } + modifier_list = Fcons (XVECTOR (modifier_symbols)->contents[i], + modifier_list); return modifier_list; } @@ -2308,6 +2560,8 @@ parse_modifiers (symbol) Qnil); Lisp_Object mask; + if (modifiers & ~((1<local_map; +#endif + maps[nmaps-1] = global_map; + } + + /* Look up in each map the dummy prefix key `menu-bar'. */ + + result = Qnil; + + for (mapno = 0; mapno < nmaps; mapno++) + { + if (! NILP (maps[mapno])) + def = get_keyelt (access_keymap (maps[mapno], Qmenu_bar, 1)); + else + def = Qnil; + + tem = Fkeymapp (def); + if (!NILP (tem)) + result = menu_bar_one_keymap (def, result); + } + + return Fnreverse (result); +} + +/* Scan one map KEYMAP, accumulating any menu items it defines + that have not yet been seen in RESULT. Return the updated RESULT. */ + +static Lisp_Object +menu_bar_one_keymap (keymap, result) + Lisp_Object keymap, result; +{ + Lisp_Object tail, item, key, binding, item_string, table; + + /* Loop over all keymap entries that have menu strings. */ + for (tail = keymap; XTYPE (tail) == Lisp_Cons; tail = XCONS (tail)->cdr) + { + item = XCONS (tail)->car; + if (XTYPE (item) == Lisp_Cons) + { + key = XCONS (item)->car; + binding = XCONS (item)->cdr; + if (XTYPE (binding) == Lisp_Cons) + { + item_string = XCONS (binding)->car; + if (XTYPE (item_string) == Lisp_String) + result = menu_bar_item (key, item_string, + Fcdr (binding), result); + } + } + else if (XTYPE (item) == Lisp_Vector) + { + /* 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; + XFASTINT (character) = c; + binding = XVECTOR (item)->contents[c]; + if (XTYPE (binding) == Lisp_Cons) + { + item_string = XCONS (binding)->car; + if (XTYPE (item_string) == Lisp_String) + result = menu_bar_item (key, item_string, + Fcdr (binding), result); + } + } + } + } + + return result; +} + +static Lisp_Object +menu_bar_item (key, item_string, def, result) + Lisp_Object key, item_string, def, result; +{ + Lisp_Object tem, elt; + Lisp_Object enabled; + + /* See if this entry is enabled. */ + enabled = Qt; + + if (XTYPE (def) == Lisp_Symbol) + { + /* No property, or nil, means enable. + Otherwise, enable if value is not nil. */ + tem = Fget (def, Qmenu_enable); + if (!NILP (tem)) + enabled = Feval (tem); + } + + /* Add an entry for this key and string + if there is none yet. */ + elt = Fassq (key, result); + if (!NILP (enabled) && NILP (elt)) + result = Fcons (Fcons (key, Fcons (item_string, Qnil)), result); + + return result; +} + static int echo_flag; static int echo_now; @@ -2770,6 +3188,15 @@ read_char_menu_prompt (nmaps, maps, prev_event, used_mouse_menu) realmaps[nmaps1++] = maps[mapno]; value = Fx_popup_menu (prev_event, Flist (nmaps1, realmaps)); + if (CONSP (value)) + { + /* If we got more than one event, put all but the first + onto this list to be read later. + Return just the first event now. */ + unread_command_events + = nconc2 (XCONS (value)->cdr, unread_command_events); + value = XCONS (value)->car; + } if (NILP (value)) XSET (value, Lisp_Int, quit_char); if (used_mouse_menu) @@ -2928,8 +3355,7 @@ follow_key (key, nmaps, current, defs, next) /* If KEY is a meta ASCII character, treat it like meta-prefix-char followed by the corresponding non-meta character. */ - if (XTYPE (key) == Lisp_Int - && XINT (key) >= 0200) + if (XTYPE (key) == Lisp_Int && (XINT (key) & CHAR_META)) { for (i = 0; i < nmaps; i++) if (! NILP (current[i])) @@ -2946,7 +3372,7 @@ follow_key (key, nmaps, current, defs, next) next[i] = Qnil; current = next; - XSET (key, Lisp_Int, XFASTINT (key) & 0177); + XSET (key, Lisp_Int, XFASTINT (key) & ~CHAR_META); } first_binding = nmaps; @@ -2967,9 +3393,15 @@ follow_key (key, nmaps, current, defs, next) lower-case letter, return the bindings for the lower-case letter. */ if (first_binding == nmaps && XTYPE (key) == Lisp_Int - && UPPERCASEP (XINT (key))) + && ((((XINT (key) & 0x3ffff) + < XSTRING (current_buffer->downcase_table)->size) + && UPPERCASEP (XINT (key) & 0x3ffff)) + || (XINT (key) & shift_modifier))) { - XSETINT (key, DOWNCASE (XINT (key))); + if (XINT (key) & shift_modifier) + XSETINT (key, XINT (key) & ~shift_modifier); + else + XSETINT (key, DOWNCASE (XINT (key))); first_binding = nmaps; for (i = nmaps - 1; i >= 0; i--) @@ -2984,7 +3416,7 @@ follow_key (key, nmaps, current, defs, next) defs[i] = Qnil; } } - + /* Given the set of bindings we've found, produce the next set of maps. */ if (first_binding < nmaps) for (i = 0; i < nmaps; i++) @@ -3023,6 +3455,7 @@ follow_key (key, nmaps, current, defs, next) If the user switches frames in the midst of a key sequence, we put off the switch-frame event until later; the next call to read_char will return it. */ + static int read_key_sequence (keybuf, bufsize, prompt) Lisp_Object *keybuf; @@ -3092,14 +3525,6 @@ read_key_sequence (keybuf, bufsize, prompt) if (NILP (Fkeymapp (Vfunction_key_map))) fkey_start = fkey_end = bufsize + 1; - /* We need to save the current buffer in case we switch buffers to - find the right binding for a mouse click. 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 accomodate a Fset_window_start or - something. */ - record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); - last_nonmenu_event = Qnil; if (INTERACTIVE) @@ -3139,7 +3564,11 @@ read_key_sequence (keybuf, bufsize, prompt) nmaps_allocated = nmaps; } bcopy (maps, submaps, (nmaps - 2) * sizeof (submaps[0])); - submaps[nmaps-2] = current_buffer->keymap; +#ifdef USE_TEXT_PROPERTIES + submaps[nmaps-2] = get_local_map (PT, current_buffer); +#else + submaps[nmaps-2] = current_buffer->local_map; +#endif submaps[nmaps-1] = global_map; } @@ -3218,7 +3647,7 @@ read_key_sequence (keybuf, bufsize, prompt) /* read_char returns -1 at the end of a macro. Emacs 18 handles this by returning immediately with a zero, so that's what we'll do. */ - if (XTYPE (key) == Lisp_Int && XINT (key) < 0) + if (XTYPE (key) == Lisp_Int && XINT (key) == -1) { t = 0; goto done; @@ -3266,6 +3695,18 @@ read_key_sequence (keybuf, bufsize, prompt) 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 accomodate 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; } @@ -3291,6 +3732,28 @@ read_key_sequence (keybuf, bufsize, prompt) goto replay_key; } } + else + { + 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; + } + } } } @@ -3311,8 +3774,7 @@ read_key_sequence (keybuf, bufsize, prompt) if (XTYPE (head) == Lisp_Symbol) { Lisp_Object breakdown = parse_modifiers (head); - Lisp_Object modifiers = - XINT (XCONS (XCONS (breakdown)->cdr)->car); + int modifiers = XINT (XCONS (XCONS (breakdown)->cdr)->car); /* We drop unbound `down-' events altogether. */ if (modifiers & down_modifier) @@ -3414,7 +3876,7 @@ read_key_sequence (keybuf, bufsize, prompt) key = keybuf[fkey_end++]; /* Look up meta-characters by prefixing them with meta_prefix_char. I hate this. */ - if (XTYPE (key) == Lisp_Int && XINT (key) & 0x80) + if (XTYPE (key) == Lisp_Int && XINT (key) & meta_modifier) { fkey_next = get_keymap_1 @@ -3422,7 +3884,7 @@ read_key_sequence (keybuf, bufsize, prompt) (access_keymap (fkey_map, meta_prefix_char, 1)), 0, 1); - XFASTINT (key) = XFASTINT (key) & 0x7f; + XFASTINT (key) = XFASTINT (key) & ~meta_modifier; } else fkey_next = fkey_map; @@ -3529,7 +3991,7 @@ sequences, where they wouldn't conflict with ordinary bindings. See\n\ NILP (prompt) ? 0 : XSTRING (prompt)->data); UNGCPRO; - return make_array (i, keybuf); + return make_event_array (i, keybuf); } DEFUN ("command-execute", Fcommand_execute, Scommand_execute, 1, 2, 0, @@ -3695,7 +4157,7 @@ DEFUN ("input-pending-p", Finput_pending_p, Sinput_pending_p, 0, 0, 0, Actually, the value is nil only if we can be sure that no input is available.") () { - if (!NILP (unread_command_events)) + if (!NILP (unread_command_events) || unread_command_char != -1) return (Qt); return detect_input_pending () ? Qt : Qnil; @@ -3724,11 +4186,12 @@ DEFUN ("recent-keys", Frecent_keys, Srecent_keys, 0, 0, 0, } DEFUN ("this-command-keys", Fthis_command_keys, Sthis_command_keys, 0, 0, 0, - "Return string of the keystrokes that invoked this command.") + "Return the key sequence that invoked this command.\n\ +The value is a string or a vector.") () { - return make_array (this_command_key_count, - XVECTOR (this_command_keys)->contents); + return make_event_array (this_command_key_count, + XVECTOR (this_command_keys)->contents); } DEFUN ("recursion-depth", Frecursion_depth, Srecursion_depth, 0, 0, 0, @@ -3769,6 +4232,7 @@ Also cancel any kbd macro being defined.") update_mode_lines++; unread_command_events = Qnil; + unread_command_char = -1; discard_tty_input (); @@ -3788,7 +4252,7 @@ On systems that don't have job control, run a subshell instead.\n\n\ If optional arg STUFFSTRING is non-nil, its characters are stuffed\n\ to be read as terminal input by Emacs's parent, after suspension.\n\ \n\ -Before suspending, call the functions in `suspend-hooks' with no args.\n\ +Before suspending, call the functions in `suspend-hook' with no args.\n\ If any of them returns nil, don't call the rest and don't suspend.\n\ Otherwise, suspend normally and after resumption run the normal hook\n\ `suspend-resume-hook' if that is bound and non-nil.\n\ @@ -3808,17 +4272,9 @@ On such systems, Emacs starts a subshell instead of suspending.") if (!NILP (stuffstring)) CHECK_STRING (stuffstring, 0); - /* Run the functions in suspend-hooks. */ - tem = Fsymbol_value (intern ("suspend-hooks")); - while (CONSP (tem)) - { - Lisp_Object val; - GCPRO2 (stuffstring, tem); - val = call0 (Fcar (tem)); - UNGCPRO; - tem = Fcdr (tem); - if (!EQ (val, Qnil)) return Qnil; - } + /* Run the functions in suspend-hook. */ + if (!NILP (Vrun_hooks)) + call1 (Vrun_hooks, intern ("suspend-hook")); GCPRO1 (stuffstring); get_frame_size (&old_width, &old_height); @@ -3837,8 +4293,7 @@ On such systems, Emacs starts a subshell instead of suspending.") if (width != old_width || height != old_height) change_frame_size (0, height, width, 0, 0); - /* Call value of suspend-resume-hook - if it is bound and value is non-nil. */ + /* Run suspend-resume-hook. */ if (!NILP (Vrun_hooks)) call1 (Vrun_hooks, intern ("suspend-resume-hook")); @@ -3931,7 +4386,6 @@ interrupt_signal () char c; /* Must preserve main program's value of errno. */ int old_errno = errno; - extern Lisp_Object Vwindow_system; #ifdef USG /* USG systems forget handlers when they are used; @@ -4022,6 +4476,13 @@ quit_throw_to_read_char () input_pending = 0; unread_command_events = Qnil; + unread_command_char = -1; + +#ifdef POLL_FOR_INPUT + /* May be > 1 if in recursive minibuffer. */ + if (poll_suppress_count == 0) + abort (); +#endif _longjmp (getcjmp, 1); } @@ -4032,9 +4493,11 @@ First arg INTERRUPT non-nil means use input interrupts;\n\ nil means use CBREAK mode.\n\ Second arg FLOW non-nil means use ^S/^Q flow control for output to terminal\n\ (no effect except in CBREAK mode).\n\ -Third arg META non-nil means accept 8-bit input (for a Meta key).\n\ - Otherwise, the top bit is ignored, on the assumption it is parity.\n\ -Optional fourth arg QUIT if non-nil specifies character to use for quitting.") +Third arg META t means accept 8-bit input (for a Meta key).\n\ + META nil means ignore the top bit, on the assumption it is parity.\n\ + Otherwise, accept 8-bit input and don't use the top bit for Meta.\n\ +Optional fourth arg QUIT if non-nil specifies character to use for quitting.\n\ +See also `current-input-mode'.") (interrupt, flow, meta, quit) Lisp_Object interrupt, flow, meta, quit; { @@ -4060,7 +4523,12 @@ Optional fourth arg QUIT if non-nil specifies character to use for quitting.") interrupt_input = 1; #endif flow_control = !NILP (flow); - meta_key = !NILP (meta); + if (NILP (meta)) + meta_key = 0; + else if (EQ (meta, Qt)) + meta_key = 1; + else + meta_key = 2; if (!NILP (quit)) /* Don't let this value be out of range. */ quit_char = XINT (quit) & (meta_key ? 0377 : 0177); @@ -4068,6 +4536,33 @@ Optional fourth arg QUIT if non-nil specifies character to use for quitting.") init_sys_modes (); return Qnil; } + +DEFUN ("current-input-mode", Fcurrent_input_mode, Scurrent_input_mode, 0, 0, 0, + "Return information about the way Emacs currently reads keyboard input.\n\ +The value is a list of the form (INTERRUPT FLOW META QUIT), where\n\ + INTERRUPT is non-nil if Emacs is using interrupt-driven input; if\n\ + nil, Emacs is using CBREAK mode.\n\ + FLOW is non-nil if Emacs uses ^S/^Q flow control for output to the\n\ + terminal; this does not apply if Emacs uses interrupt-driven input.\n\ + META is t if accepting 8-bit input with 8th bit as Meta flag.\n\ + META nil means ignoring the top bit, on the assumption it is parity.\n\ + META is neither t nor nil if accepting 8-bit input and using\n\ + all 8 bits as the character code.\n\ + QUIT is the character Emacs currently uses to quit.\n\ +The elements of this list correspond to the arguments of\n\ +`set-input-mode'.") + () +{ + Lisp_Object val[4]; + + val[0] = interrupt_input ? Qt : Qnil; + val[1] = flow_control ? Qt : Qnil; + val[2] = meta_key == 2 ? make_number (0) : meta_key == 1 ? Qt : Qnil; + XSETINT (val[3], quit_char); + + return Flist (val, sizeof (val) / sizeof (val[0])); +} + init_keyboard () { @@ -4076,6 +4571,7 @@ init_keyboard () immediate_quit = 0; quit_char = Ctl ('g'); unread_command_events = Qnil; + unread_command_char = -1; total_keys = 0; recent_keys_index = 0; kbd_fetch_ptr = kbd_buffer; @@ -4167,17 +4663,28 @@ syms_of_keyboard () Qdisabled = intern ("disabled"); staticpro (&Qdisabled); + Qpre_command_hook = intern ("pre-command-hook"); + staticpro (&Qpre_command_hook); + + Qpost_command_hook = intern ("post-command-hook"); + staticpro (&Qpost_command_hook); + Qfunction_key = intern ("function-key"); staticpro (&Qfunction_key); Qmouse_click = intern ("mouse-click"); staticpro (&Qmouse_click); + Qmenu_enable = intern ("menu-enable"); + staticpro (&Qmenu_enable); + Qmode_line = intern ("mode-line"); staticpro (&Qmode_line); Qvertical_line = intern ("vertical-line"); staticpro (&Qvertical_line); Qvertical_scroll_bar = intern ("vertical-scroll-bar"); staticpro (&Qvertical_scroll_bar); + Qmenu_bar = intern ("menu-bar"); + staticpro (&Qmenu_bar); Qabove_handle = intern ("above-handle"); staticpro (&Qabove_handle); @@ -4195,6 +4702,11 @@ syms_of_keyboard () Qmodifier_cache = intern ("modifier-cache"); staticpro (&Qmodifier_cache); + Qrecompute_lucid_menubar = intern ("recompute-lucid-menubar"); + staticpro (&Qrecompute_lucid_menubar); + Qactivate_menubar_hook = intern ("activate-menubar-hook"); + staticpro (&Qactivate_menubar_hook); + { struct event_head *p; @@ -4218,7 +4730,8 @@ syms_of_keyboard () modifier_symbols = Fmake_vector (make_number (len), Qnil); for (i = 0; i < len; i++) - XVECTOR (modifier_symbols)->contents[i] = intern (modifier_names[i]); + if (modifier_names[i]) + XVECTOR (modifier_symbols)->contents[i] = intern (modifier_names[i]); staticpro (&modifier_symbols); } @@ -4256,6 +4769,7 @@ syms_of_keyboard () defsubr (&Sdiscard_input); defsubr (&Sopen_dribble_file); defsubr (&Sset_input_mode); + defsubr (&Scurrent_input_mode); defsubr (&Sexecute_extended_command); DEFVAR_LISP ("disabled-command-hook", &Vdisabled_command_hook, @@ -4263,20 +4777,29 @@ syms_of_keyboard () \(has a non-nil `disabled' property)."); DEFVAR_LISP ("last-command-char", &last_command_char, - "Last terminal input key that was part of a command."); + "Last input event that was part of a command."); + + DEFVAR_LISP ("last-command-event", &last_command_char, + "Last input event that was part of a command."); DEFVAR_LISP ("last-nonmenu-event", &last_nonmenu_event, - "Last terminal input key in a command, except for mouse menus.\n\ + "Last input event in a command, except for mouse menu events.\n\ Mouse menus give back keys that don't look like mouse events;\n\ this variable holds the actual mouse event that led to the menu,\n\ so that you can determine whether the command was run by mouse or not."); DEFVAR_LISP ("last-input-char", &last_input_char, - "Last terminal input key."); + "Last input event."); + + DEFVAR_LISP ("last-input-event", &last_input_char, + "Last input event."); DEFVAR_LISP ("unread-command-events", &unread_command_events, "List of objects to be read as next command input events."); + DEFVAR_INT ("unread-command-char", &unread_command_char, + "If not -1, an object to be read as next command input event."); + DEFVAR_LISP ("meta-prefix-char", &meta_prefix_char, "Meta-prefix character code. Meta-foo as command input\n\ turns into this character followed by foo."); @@ -4368,11 +4891,35 @@ Type this character while in a menu prompt to rotate around the lines of it."); DEFVAR_INT ("extra-keyboard-modifiers", &extra_keyboard_modifiers, "A mask of additional modifier keys to use with every keyboard character.\n\ -These bits follow the convention for X windows,\n\ -but the control and meta bits work even when you are not using X:\n\ - 1 -- shift bit 2 -- lock bit\n\ - 4 -- control bit 8 -- meta bit."); +Emacs applies the modifiers of the character stored here to each keyboard\n\ +character it reads. For example, after evaluating the expression\n\ + (setq extra-keyboard-modifiers ?\C-x)\n\ +all input characters will have the control modifier applied to them.\n\ +\n\ +Note that the character ?\C-@, equivalent to the integer zero, does\n\ +not count as a control character; rather, it counts as a character\n\ +with no modifiers; thus, setting extra_keyboard_modifiers to zero\n\ +cancels any modification."); extra_keyboard_modifiers = 0; + + DEFVAR_LISP ("deactivate-mark", &Vdeactivate_mark, + "If an editing command sets this to t, deactivate the mark afterward.\n\ +The command loop sets this to nil before each command,\n\ +and tests the value when the command returns.\n\ +Buffer modification stores t in this variable."); + Vdeactivate_mark = Qnil; + + DEFVAR_LISP ("pre-command-hook", &Vpre_command_hook, + "Normal hook run before each command is executed."); + Vpre_command_hook = Qnil; + + DEFVAR_LISP ("post-command-hook", &Vpost_command_hook, + "Normal hook run before each command is executed."); + Vpost_command_hook = Qnil; + + DEFVAR_LISP ("lucid-menu-bar-dirty-flag", &Vlucid_menu_bar_dirty_flag, + "t means menu bar, specified Lucid style, needs to be recomputed."); + Vlucid_menu_bar_dirty_flag = Qnil; } keys_of_keyboard ()