X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/bcc3646eaa7f8224fb4141730665f8e29ced0776..025ae9533de941cd045374c1639d20e9b830284a:/src/keyboard.c diff --git a/src/keyboard.c b/src/keyboard.c index 1a09436557..526586f17f 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1,7 +1,7 @@ /* Keyboard and mouse input; editor command loop. Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007 Free Software Foundation, Inc. + 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -33,7 +33,7 @@ Boston, MA 02110-1301, USA. */ #include "window.h" #include "commands.h" #include "buffer.h" -#include "charset.h" +#include "character.h" #include "disptab.h" #include "dispextern.h" #include "syntax.h" @@ -95,35 +95,7 @@ volatile int interrupt_input_blocked; during the current critical section. */ int interrupt_input_pending; - -#ifdef HAVE_WINDOW_SYSTEM -/* Make all keyboard buffers much bigger when using X windows. */ -#ifdef MAC_OS8 -/* But not too big (local data > 32K error) if on Mac OS Classic. */ -#define KBD_BUFFER_SIZE 512 -#else -#define KBD_BUFFER_SIZE 4096 -#endif -#else /* No X-windows, character input */ #define KBD_BUFFER_SIZE 4096 -#endif /* No X-windows */ - -#define abs(x) ((x) >= 0 ? (x) : -(x)) - -/* Following definition copied from eval.c */ - -struct backtrace - { - struct backtrace *next; - Lisp_Object *function; - Lisp_Object *args; /* Points to vector of args. */ - int nargs; /* length of vector. If nargs is UNEVALLED, - args points to slot holding list of - unevalled args */ - char evalargs; - /* Nonzero means call value of debugger when done with this operation. */ - char debug_on_exit; - }; #ifdef MULTI_KBOARD KBOARD *initial_kboard; @@ -160,16 +132,12 @@ int this_command_key_count_reset; Lisp_Object raw_keybuf; int raw_keybuf_count; +/* Non-nil if the present key sequence was obtained by shift translation. */ +Lisp_Object Vthis_command_keys_shift_translated; + #define GROW_RAW_KEYBUF \ if (raw_keybuf_count == XVECTOR (raw_keybuf)->size) \ - { \ - int newsize = 2 * XVECTOR (raw_keybuf)->size; \ - Lisp_Object new; \ - new = Fmake_vector (make_number (newsize), Qnil); \ - bcopy (XVECTOR (raw_keybuf)->contents, XVECTOR (new)->contents, \ - raw_keybuf_count * sizeof (Lisp_Object)); \ - raw_keybuf = new; \ - } + raw_keybuf = larger_vector (raw_keybuf, raw_keybuf_count * 2, Qnil) \ /* Number of elements of this_command_keys that precede this key sequence. */ @@ -184,8 +152,6 @@ extern int minbuf_level; extern int message_enable_multibyte; -extern struct backtrace *backtrace_list; - /* If non-nil, the function that implements the display of help. It's called with one argument, the help string to display. */ @@ -447,7 +413,7 @@ Lisp_Object Qcommand_hook_internal, Vcommand_hook_internal; /* Parent keymap of terminal-local function-key-map instances. */ Lisp_Object Vfunction_key_map; -/* Parent keymap of terminal-local key-translation-map instances. */ +/* Keymap of key translations that can override keymaps. */ Lisp_Object Vkey_translation_map; /* List of deferred actions to be performed at a later time. @@ -523,7 +489,9 @@ Lisp_Object Qsave_session; #ifdef MAC_OS Lisp_Object Qmac_apple_event; #endif - +#ifdef HAVE_DBUS +Lisp_Object Qdbus_event; +#endif /* Lisp_Object Qmouse_movement; - also an event header */ /* Properties of event headers. */ @@ -693,8 +661,6 @@ static int store_user_signal_events P_ ((void)); /* Nonzero means don't try to suspend even if the operating system seems to support it. */ static int cannot_suspend; - -extern Lisp_Object Qidentity, Qonly; /* Install the string STR as the beginning of the string of echoing, so that it serves as a prompt for the next character. @@ -953,7 +919,7 @@ add_command_key (key) 2 * ASIZE (this_command_keys), Qnil); - AREF (this_command_keys, this_command_key_count) = key; + ASET (this_command_keys, this_command_key_count, key); ++this_command_key_count; } @@ -970,7 +936,7 @@ recursive_edit_1 () specbind (Qstandard_input, Qt); } -#ifdef HAVE_X_WINDOWS +#ifdef HAVE_WINDOW_SYSTEM /* The command loop has started an hourglass timer, so we have to cancel it here, otherwise it will fire because the recursive edit can take some time. Do not check for display_hourglass_p here, @@ -1255,7 +1221,7 @@ cmd_error (data) Lisp_Object old_level, old_length; char macroerror[50]; -#ifdef HAVE_X_WINDOWS +#ifdef HAVE_WINDOW_SYSTEM if (display_hourglass_p) cancel_hourglass (); #endif @@ -1431,7 +1397,7 @@ DEFUN ("top-level", Ftop_level, Stop_level, 0, 0, "", doc: /* Exit all recursive editing levels. */) () { -#ifdef HAVE_X_WINDOWS +#ifdef HAVE_WINDOW_SYSTEM if (display_hourglass_p) cancel_hourglass (); #endif @@ -1554,7 +1520,7 @@ static void adjust_point_for_property P_ ((int, int)); /* Cancel hourglass from protect_unwind. ARG is not used. */ -#ifdef HAVE_X_WINDOWS +#ifdef HAVE_WINDOW_SYSTEM static Lisp_Object cancel_hourglass_unwind (arg) Lisp_Object arg; @@ -1572,14 +1538,13 @@ command_loop_1 () int nonundocount; Lisp_Object keybuf[30]; int i; - int no_direct; int prev_modiff = 0; struct buffer *prev_buffer = NULL; #if 0 /* This shouldn't be necessary anymore. --lorentey */ #ifdef MULTI_KBOARD int was_locked = single_kboard; #endif -#endif +#endif int already_adjusted = 0; current_kboard->Vprefix_arg = Qnil; @@ -1614,6 +1579,8 @@ command_loop_1 () /* Do this after running Vpost_command_hook, for consistency. */ current_kboard->Vlast_command = Vthis_command; current_kboard->Vreal_last_command = real_this_command; + if (!CONSP (last_command_char)) + current_kboard->Vlast_repeatable_command = real_this_command; while (1) { @@ -1630,8 +1597,6 @@ command_loop_1 () while (pending_malloc_warning) display_malloc_warning (); - no_direct = 0; - Vdeactivate_mark = Qnil; /* If minibuffer on and echo area in use, @@ -1639,17 +1604,15 @@ command_loop_1 () if (minibuf_level && !NILP (echo_area_buffer[0]) - && EQ (minibuf_window, echo_area_window)) + && EQ (minibuf_window, echo_area_window) + && NUMBERP (Vminibuffer_message_timeout)) { /* Bind inhibit-quit to t so that C-g gets read in rather than quitting back to the minibuffer. */ int count = SPECPDL_INDEX (); specbind (Qinhibit_quit, Qt); - if (NUMBERP (Vminibuffer_message_timeout)) - sit_for (Vminibuffer_message_timeout, 0, 2); - else - sit_for (Qt, 0, 2); + sit_for (Vminibuffer_message_timeout, 0, 2); /* Clear the echo area. */ message2 (0, 0, 0); @@ -1686,6 +1649,7 @@ command_loop_1 () Vthis_command = Qnil; real_this_command = Qnil; Vthis_original_command = Qnil; + Vthis_command_keys_shift_translated = Qnil; /* Read next key sequence; i gets its length. */ i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0], @@ -1792,14 +1756,16 @@ command_loop_1 () } else { - if (NILP (current_kboard->Vprefix_arg) && ! no_direct) + if (NILP (current_kboard->Vprefix_arg)) { /* In case we jump to directly_done. */ Vcurrent_prefix_arg = current_kboard->Vprefix_arg; /* Recognize some common commands in common situations and do them directly. */ - if (EQ (Vthis_command, Qforward_char) && PT < ZV) + if (EQ (Vthis_command, Qforward_char) && PT < ZV + && NILP (Vthis_command_keys_shift_translated) + && !CONSP (Vtransient_mark_mode)) { struct Lisp_Char_Table *dp = window_display_table (XWINDOW (selected_window)); @@ -1824,7 +1790,7 @@ command_loop_1 () : (lose >= 0x20 && lose < 0x7f)) /* To extract the case of continuation on wide-column characters. */ - && (WIDTH_BY_CHAR_HEAD (FETCH_BYTE (PT_BYTE)) == 1) + && ASCII_BYTE_P (lose) && (XFASTINT (XWINDOW (selected_window)->last_modified) >= MODIFF) && (XFASTINT (XWINDOW (selected_window)->last_overlay_modified) @@ -1839,7 +1805,9 @@ command_loop_1 () direct_output_forward_char (1); goto directly_done; } - else if (EQ (Vthis_command, Qbackward_char) && PT > BEGV) + else if (EQ (Vthis_command, Qbackward_char) && PT > BEGV + && NILP (Vthis_command_keys_shift_translated) + && !CONSP (Vtransient_mark_mode)) { struct Lisp_Char_Table *dp = window_display_table (XWINDOW (selected_window)); @@ -1881,7 +1849,7 @@ command_loop_1 () { unsigned int c = translate_char (Vtranslation_table_for_input, - XFASTINT (last_command_char), 0, 0, 0); + XFASTINT (last_command_char)); int value; if (NILP (Vexecuting_kbd_macro) && !EQ (minibuf_window, selected_window)) @@ -1929,7 +1897,7 @@ command_loop_1 () /* Here for a command that isn't executed directly */ { -#ifdef HAVE_X_WINDOWS +#ifdef HAVE_WINDOW_SYSTEM int scount = SPECPDL_INDEX (); if (display_hourglass_p @@ -1945,7 +1913,7 @@ command_loop_1 () Fundo_boundary (); Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil); -#ifdef HAVE_X_WINDOWS +#ifdef HAVE_WINDOW_SYSTEM /* Do not check display_hourglass_p here, because Fcommand_execute could change it, but we should cancel hourglass cursor anyway. @@ -1989,6 +1957,8 @@ command_loop_1 () { current_kboard->Vlast_command = Vthis_command; current_kboard->Vreal_last_command = real_this_command; + if (!CONSP (last_command_char)) + current_kboard->Vlast_repeatable_command = real_this_command; cancel_echoing (); this_command_key_count = 0; this_command_key_count_reset = 0; @@ -1997,14 +1967,6 @@ command_loop_1 () if (!NILP (current_buffer->mark_active) && !NILP (Vrun_hooks)) { - /* Setting transient-mark-mode to `only' is a way of - turning it on for just one command. */ - - if (EQ (Vtransient_mark_mode, Qidentity)) - Vtransient_mark_mode = Qnil; - if (EQ (Vtransient_mark_mode, Qonly)) - Vtransient_mark_mode = Qidentity; - if (!NILP (Vdeactivate_mark) && !NILP (Vtransient_mark_mode)) { /* We could also call `deactivate'mark'. */ @@ -2058,7 +2020,7 @@ adjust_point_for_property (last_pt, modified) int last_pt; int modified; { - int beg, end; + EMACS_INT beg, end; Lisp_Object val, overlay, tmp; int check_composition = 1, check_display = 1, check_invisible = 1; int orig_pt = PT; @@ -2388,6 +2350,9 @@ make_ctrl_char (c) /* Save the upper bits here. */ int upper = c & ~0177; + if (! ASCII_BYTE_P (c)) + return c |= ctrl_modifier; + c &= 0177; /* Everything in the columns containing the upper-case letters @@ -2571,7 +2536,7 @@ do { if (polling_stopped_here) start_polling (); \ USED_MOUSE_MENU is null, we don't dereference it. Value is -2 when we find input on another keyboard. A second call - to read_char will read it. + to read_char will read it. If END_TIME is non-null, it is a pointer to an EMACS_TIME specifying the maximum time to wait until. If no input arrives by @@ -2738,6 +2703,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time) /* if redisplay was requested */ if (commandflag >= 0) { + int echo_current = EQ (echo_message_buffer, echo_area_buffer[0]); + /* If there is pending input, process any events which are not user-visible, such as X selection_request events. */ if (input_pending @@ -2761,6 +2728,12 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time) swallow_events (0); /* If that cleared input_pending, try again to redisplay. */ } + + /* Prevent the redisplay we just did + from messing up echoing of the input after the prompt. */ + if (commandflag == 0 && echo_current) + echo_message_buffer = echo_area_buffer[0]; + } /* Message turns off echoing unless more keystrokes turn it on again. @@ -3186,7 +3159,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time) int count = SPECPDL_INDEX (); record_single_kboard_state (); #endif - + last_input_char = c; Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char), Qt); @@ -3219,7 +3192,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time) || (VECTORP (current_kboard->Vkeyboard_translate_table) && XVECTOR (current_kboard->Vkeyboard_translate_table)->size > (unsigned) XFASTINT (c)) || (CHAR_TABLE_P (current_kboard->Vkeyboard_translate_table) - && CHAR_VALID_P (XINT (c), 0))) + && CHARACTERP (c))) { Lisp_Object d; d = Faref (current_kboard->Vkeyboard_translate_table, c); @@ -4022,9 +3995,6 @@ discard_mouse_events () if (sp->kind == MOUSE_CLICK_EVENT || sp->kind == WHEEL_EVENT || sp->kind == HORIZ_WHEEL_EVENT -#ifdef WINDOWSNT - || sp->kind == W32_SCROLL_BAR_CLICK_EVENT -#endif #ifdef HAVE_GPM || sp->kind == GPM_CLICK_EVENT #endif @@ -4100,6 +4070,12 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time) /* Wait until there is input available. */ for (;;) { + /* Break loop if there's an unread command event. Needed in + moused window autoselection which uses a timer to insert such + events. */ + if (CONSP (Vunread_command_events)) + break; + if (kbd_fetch_ptr != kbd_store_ptr) break; #if defined (HAVE_MOUSE) || defined (HAVE_GPM) @@ -4311,6 +4287,13 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time) internal_last_event_frame = frame; kbd_fetch_ptr = event + 1; } +#ifdef HAVE_DBUS + else if (event->kind == DBUS_EVENT) + { + obj = make_lispy_event (event); + kbd_fetch_ptr = event + 1; + } +#endif else { /* If this event is on a different frame, return a switch-frame this @@ -4520,6 +4503,13 @@ timer_resume_idle () /* This is only for debugging. */ struct input_event last_timer_event; +/* List of elisp functions to call, delayed because they were generated in + a context where Elisp could not be safely run (e.g. redisplay, signal, + ...). Each lement has the form (FUN . ARGS). */ +Lisp_Object pending_funcalls; + +extern Lisp_Object Qapply; + /* Check whether a timer has fired. To prevent larger problems we simply disregard elements that are not proper timers. Do not make a circular timer list for the time being. @@ -4556,6 +4546,14 @@ timer_check (do_it_now) chosen_timer = Qnil; GCPRO3 (timers, idle_timers, chosen_timer); + /* First run the code that was delayed. */ + while (CONSP (pending_funcalls)) + { + Lisp_Object funcall = XCAR (pending_funcalls); + pending_funcalls = XCDR (pending_funcalls); + safe_call2 (Qapply, XCAR (funcall), XCDR (funcall)); + } + if (CONSP (timers) || CONSP (idle_timers)) { EMACS_GET_TIME (now); @@ -4715,12 +4713,14 @@ timer_check (do_it_now) } DEFUN ("current-idle-time", Fcurrent_idle_time, Scurrent_idle_time, 0, 0, 0, - doc: /* Return the current length of Emacs idleness. -The value is returned as a list of three integers. The first has the + doc: /* Return the current length of Emacs idleness, or nil. +The value when Emacs is idle is a list of three integers. The first has the most significant 16 bits of the seconds, while the second has the least significant 16 bits. The third integer gives the microsecond count. +The value when Emacs is not idle is nil. + The microsecond count is zero on systems that do not provide resolution finer than a second. */) () @@ -4910,13 +4910,17 @@ char *lispy_function_keys[] = 0, /* VK_MENU 0x12 */ "pause", /* VK_PAUSE 0x13 */ "capslock", /* VK_CAPITAL 0x14 */ - - 0, 0, 0, 0, 0, 0, /* 0x15 .. 0x1A */ - + "kana", /* VK_KANA/VK_HANGUL 0x15 */ + 0, /* 0x16 */ + "junja", /* VK_JUNJA 0x17 */ + "final", /* VK_FINAL 0x18 */ + "kanji", /* VK_KANJI/VK_HANJA 0x19 */ + 0, /* 0x1A */ "escape", /* VK_ESCAPE 0x1B */ - - 0, 0, 0, 0, /* 0x1C .. 0x1F */ - + "convert", /* VK_CONVERT 0x1C */ + "non-convert", /* VK_NONCONVERT 0x1D */ + "accept", /* VK_ACCEPT 0x1E */ + "mode-change", /* VK_MODECHANGE 0x1F */ 0, /* VK_SPACE 0x20 */ "prior", /* VK_PRIOR 0x21 */ "next", /* VK_NEXT 0x22 */ @@ -4949,9 +4953,8 @@ char *lispy_function_keys[] = "lwindow", /* VK_LWIN 0x5B */ "rwindow", /* VK_RWIN 0x5C */ "apps", /* VK_APPS 0x5D */ - - 0, 0, /* 0x5E .. 0x5F */ - + 0, /* 0x5E */ + "sleep", "kp-0", /* VK_NUMPAD0 0x60 */ "kp-1", /* VK_NUMPAD1 0x61 */ "kp-2", /* VK_NUMPAD2 0x62 */ @@ -4998,7 +5001,9 @@ char *lispy_function_keys[] = "kp-numlock", /* VK_NUMLOCK 0x90 */ "scroll", /* VK_SCROLL 0x91 */ - + /* Not sure where the following block comes from. + Windows headers have NEC and Fujitsu specific keys in + this block, but nothing generic. */ "kp-space", /* VK_NUMPAD_CLEAR 0x92 */ "kp-enter", /* VK_NUMPAD_ENTER 0x93 */ "kp-prior", /* VK_NUMPAD_PRIOR 0x94 */ @@ -5018,19 +5023,47 @@ char *lispy_function_keys[] = * VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys. * Used only as parameters to GetAsyncKeyState and GetKeyState. * No other API or message will distinguish left and right keys this way. + * 0xA0 .. 0xA5 */ - /* 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, 0, 0, 0, 0, 0, 0, + /* Multimedia keys. These are handled as WM_APPCOMMAND, which allows us + to enable them selectively, and gives access to a few more functions. + See lispy_multimedia_keys below. */ + 0, 0, 0, 0, 0, 0, 0, /* 0xA6 .. 0xAC Browser */ + 0, 0, 0, /* 0xAD .. 0xAF Volume */ + 0, 0, 0, 0, /* 0xB0 .. 0xB3 Media */ + 0, 0, 0, 0, /* 0xB4 .. 0xB7 Apps */ - /* 0xF0 .. 0xF5 */ + /* 0xB8 .. 0xC0 "OEM" keys - all seem to be punctuation. */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, + /* 0xC1 - 0xDA unallocated, 0xDB-0xDF more OEM keys */ + 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, /* 0xE0 */ + "ax", /* VK_OEM_AX 0xE1 */ + 0, /* VK_OEM_102 0xE2 */ + "ico-help", /* VK_ICO_HELP 0xE3 */ + "ico-00", /* VK_ICO_00 0xE4 */ + 0, /* VK_PROCESSKEY 0xE5 */ + "ico-clear", /* VK_ICO_CLEAR 0xE6 */ + "packet", /* VK_PACKET 0xE7 */ + 0, /* 0xE8 */ + "reset", /* VK_OEM_RESET 0xE9 */ + "jump", /* VK_OEM_JUMP 0xEA */ + "oem-pa1", /* VK_OEM_PA1 0xEB */ + "oem-pa2", /* VK_OEM_PA2 0xEC */ + "oem-pa3", /* VK_OEM_PA3 0xED */ + "wsctrl", /* VK_OEM_WSCTRL 0xEE */ + "cusel", /* VK_OEM_CUSEL 0xEF */ + "oem-attn", /* VK_OEM_ATTN 0xF0 */ + "finish", /* VK_OEM_FINISH 0xF1 */ + "copy", /* VK_OEM_COPY 0xF2 */ + "auto", /* VK_OEM_AUTO 0xF3 */ + "enlw", /* VK_OEM_ENLW 0xF4 */ + "backtab", /* VK_OEM_BACKTAB 0xF5 */ "attn", /* VK_ATTN 0xF6 */ "crsel", /* VK_CRSEL 0xF7 */ "exsel", /* VK_EXSEL 0xF8 */ @@ -5043,6 +5076,65 @@ char *lispy_function_keys[] = 0 /* 0xFF */ }; +/* Some of these duplicate the "Media keys" on newer keyboards, + but they are delivered to the application in a different way. */ +static char *lispy_multimedia_keys[] = + { + 0, + "browser-back", + "browser-forward", + "browser-refresh", + "browser-stop", + "browser-search", + "browser-favorites", + "browser-home", + "volume-mute", + "volume-down", + "volume-up", + "media-next", + "media-previous", + "media-stop", + "media-play-pause", + "mail", + "media-select", + "app-1", + "app-2", + "bass-down", + "bass-boost", + "bass-up", + "treble-down", + "treble-up", + "mic-volume-mute", + "mic-volume-down", + "mic-volume-up", + "help", + "find", + "new", + "open", + "close", + "save", + "print", + "undo", + "redo", + "copy", + "cut", + "paste", + "mail-reply", + "mail-forward", + "mail-send", + "spell-check", + "toggle-dictate-command", + "mic-toggle", + "correction-list", + "media-play", + "media-pause", + "media-record", + "media-fast-forward", + "media-rewind", + "media-channel-up", + "media-channel-down" + }; + #else /* not HAVE_NTGUI */ /* This should be dealt with in XTread_socket now, and that doesn't @@ -5457,41 +5549,32 @@ make_lispy_event (event) { /* A simple keystroke. */ case ASCII_KEYSTROKE_EVENT: - { - Lisp_Object lispy_c; - int c = event->code & 0377; - /* Turn ASCII characters into control characters - when proper. */ - if (event->modifiers & ctrl_modifier) - c = make_ctrl_char (c); - - /* 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)); - /* Distinguish Shift-SPC from SPC. */ - if ((event->code & 0377) == 040 - && event->modifiers & shift_modifier) - c |= shift_modifier; - button_down_time = 0; - XSETFASTINT (lispy_c, c); - return lispy_c; - } - case MULTIBYTE_CHAR_KEYSTROKE_EVENT: { Lisp_Object lispy_c; int c = event->code; + if (event->kind == ASCII_KEYSTROKE_EVENT) + { + c &= 0377; + eassert (c == event->code); + /* Turn ASCII characters into control characters + when proper. */ + if (event->modifiers & ctrl_modifier) + { + c = make_ctrl_char (c); + event->modifiers &= ~ctrl_modifier; + } + } - /* 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. */ + /* Add in the other modifier bits. The shift key was taken care + of by the X code. */ c |= (event->modifiers & (meta_modifier | alt_modifier | hyper_modifier | super_modifier | ctrl_modifier)); - /* What about the `shift' modifier ? */ + /* Distinguish Shift-SPC from SPC. */ + if ((event->code) == 040 + && event->modifiers & shift_modifier) + c |= shift_modifier; button_down_time = 0; XSETFASTINT (lispy_c, c); return lispy_c; @@ -5560,6 +5643,21 @@ make_lispy_event (event) (sizeof (lispy_function_keys) / sizeof (lispy_function_keys[0]))); +#ifdef WINDOWSNT + case MULTIMEDIA_KEY_EVENT: + if (event->code < (sizeof (lispy_multimedia_keys) + / sizeof (lispy_multimedia_keys[0])) + && event->code > 0 && lispy_multimedia_keys[event->code]) + { + return modify_event_symbol (event->code, event->modifiers, + Qfunction_key, Qnil, + lispy_multimedia_keys, &func_key_syms, + (sizeof (lispy_multimedia_keys) + / sizeof (lispy_multimedia_keys[0]))); + } + return Qnil; +#endif + #ifdef HAVE_MOUSE /* A mouse click. Figure out where it is, decide whether it's a press, click or drag, and build the appropriate structure. */ @@ -5706,8 +5804,8 @@ make_lispy_event (event) fuzz = double_click_fuzz / 8; is_double = (button == last_mouse_button - && (abs (XINT (event->x) - last_mouse_x) <= fuzz) - && (abs (XINT (event->y) - last_mouse_y) <= fuzz) + && (eabs (XINT (event->x) - last_mouse_x) <= fuzz) + && (eabs (XINT (event->y) - last_mouse_y) <= fuzz) && button_down_time != 0 && (EQ (Vdouble_click_time, Qt) || (INTEGERP (Vdouble_click_time) @@ -5875,8 +5973,8 @@ make_lispy_event (event) fuzz = double_click_fuzz / 8; is_double = (last_mouse_button < 0 - && (abs (XINT (event->x) - last_mouse_x) <= fuzz) - && (abs (XINT (event->y) - last_mouse_y) <= fuzz) + && (eabs (XINT (event->x) - last_mouse_x) <= fuzz) + && (eabs (XINT (event->y) - last_mouse_y) <= fuzz) && button_down_time != 0 && (EQ (Vdouble_click_time, Qt) || (INTEGERP (Vdouble_click_time) @@ -6000,52 +6098,6 @@ make_lispy_event (event) #endif /* USE_TOOLKIT_SCROLL_BARS */ -#ifdef WINDOWSNT - case W32_SCROLL_BAR_CLICK_EVENT: - { - int button = event->code; - int is_double; - Lisp_Object position; - Lisp_Object *start_pos_ptr; - Lisp_Object start_pos; - - { - Lisp_Object window; - Lisp_Object portion_whole; - Lisp_Object part; - - window = event->frame_or_window; - portion_whole = Fcons (event->x, event->y); - part = *scroll_bar_parts[(int) event->part]; - - position - = Fcons (window, - Fcons (Qvertical_scroll_bar, - Fcons (portion_whole, - Fcons (make_number (event->timestamp), - Fcons (part, Qnil))))); - } - - /* Always treat W32 scroll bar events as clicks. */ - event->modifiers |= click_modifier; - - { - /* Get the symbol we should use for the mouse click. */ - Lisp_Object head; - - head = modify_event_symbol (button, - event->modifiers, - Qmouse_click, - Vlispy_mouse_stem, - NULL, &mouse_syms, - XVECTOR (mouse_syms)->size); - return Fcons (head, - Fcons (position, - Qnil)); - } - } -#endif /* WINDOWSNT */ - case DRAG_N_DROP_EVENT: { FRAME_PTR f; @@ -6126,6 +6178,13 @@ make_lispy_event (event) } #endif +#ifdef HAVE_DBUS + case DBUS_EVENT: + { + return Fcons (Qdbus_event, event->arg); + } +#endif /* HAVE_DBUS */ + #ifdef HAVE_GPM case GPM_CLICK_EVENT: { @@ -6444,12 +6503,21 @@ lispy_modifier_list (modifiers) SYMBOL's Qevent_symbol_element_mask property, and maintains the Qevent_symbol_elements property. */ +#define KEY_TO_CHAR(k) (XINT (k) & ((1 << CHARACTERBITS) - 1)) + Lisp_Object parse_modifiers (symbol) Lisp_Object symbol; { Lisp_Object elements; + if (INTEGERP (symbol)) + return (Fcons (make_number (KEY_TO_CHAR (symbol)), + Fcons (make_number (XINT (symbol) & CHAR_MODIFIER_MASK), + Qnil))); + else if (!SYMBOLP (symbol)) + return Qnil; + elements = Fget (symbol, Qevent_symbol_element_mask); if (CONSP (elements)) return elements; @@ -6484,6 +6552,20 @@ parse_modifiers (symbol) } } +DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers, + Sevent_symbol_parse_modifiers, 1, 1, 0, + doc: /* Parse the event symbol. For internal use. */) + (symbol) + Lisp_Object symbol; +{ + /* Fill the cache if needed. */ + parse_modifiers (symbol); + /* Ignore the result (which is stored on Qevent_symbol_element_mask) + and use the Lispier representation stored on Qevent_symbol_elements + instead. */ + return Fget (symbol, Qevent_symbol_elements); +} + /* Apply the modifiers MODIFIERS to the symbol BASE. BASE must be unmodified. @@ -6503,6 +6585,9 @@ apply_modifiers (modifiers, base) /* Mask out upper bits. We don't know where this value's been. */ modifiers &= INTMASK; + if (INTEGERP (base)) + return make_number (XINT (base) | modifiers); + /* The click modifier never figures into cache indices. */ cache = Fget (base, Qmodifier_cache); XSETFASTINT (index, (modifiers & ~click_modifier)); @@ -6914,6 +6999,11 @@ void gobble_input (expected) int expected; { +#ifdef HAVE_DBUS + /* Check whether a D-Bus message has arrived. */ + xd_read_queued_messages (); +#endif /* HAVE_DBUS */ + #ifndef VMS #ifdef SIGIO if (interrupt_input) @@ -7033,7 +7123,7 @@ read_avail_input (expected) nread += nr; expected = 0; } - + if (nr == -1) /* Not OK to read input now. */ { err = 1; @@ -7041,7 +7131,7 @@ read_avail_input (expected) else if (nr == -2) /* Non-transient error. */ { /* The terminal device terminated; it should be closed. */ - + /* Kill Emacs if this was our last terminal. */ if (!terminal_list->next_terminal) /* Formerly simply reported no input, but that @@ -7053,12 +7143,13 @@ read_avail_input (expected) group? Perhaps on systems with FIONREAD Emacs is alone in its group. */ kill (getpid (), SIGHUP); - + /* XXX Is calling delete_terminal safe here? It calls Fdelete_frame. */ - if (t->delete_terminal_hook) - (*t->delete_terminal_hook) (t); - else - delete_terminal (t); + { + Lisp_Object tmp; + XSETTERMINAL (tmp, t); + Fdelete_terminal (tmp, Qnoelisp); + } } if (hold_quit.kind != NO_EVENT) @@ -7094,7 +7185,7 @@ tty_read_avail_input (struct terminal *terminal, int nread = 0; if (!terminal->name) /* Don't read from a dead terminal. */ - return; + return 0; if (terminal->type != output_termcap) abort (); @@ -7121,7 +7212,7 @@ tty_read_avail_input (struct terminal *terminal, return 0; /* The terminal is suspended. */ #ifdef HAVE_GPM - if (term_gpm && gpm_tty == tty->terminal->id) + if (gpm_tty == tty) { Gpm_Event event; struct input_event hold_quit; @@ -7155,7 +7246,7 @@ tty_read_avail_input (struct terminal *terminal, if (n_to_read > sizeof cbuf) n_to_read = sizeof cbuf; #else /* no FIONREAD */ -#if defined (USG) || defined (DGUX) || defined(CYGWIN) +#if defined (USG) || defined(CYGWIN) /* Read some input if available, but don't wait. */ n_to_read = sizeof cbuf; fcntl (fileno (tty->input), F_SETFL, O_NDELAY); @@ -7176,7 +7267,7 @@ tty_read_avail_input (struct terminal *terminal, Jeffrey Honig says this is generally safe. */ if (nread == -1 && errno == EIO) return -2; /* Close this terminal. */ -#if defined (AIX) && (! defined (aix386) && defined (_BSD)) +#if defined (AIX) && defined (_BSD) /* The kernel sometimes fails to deliver SIGHUP for ptys. This looks incorrect, but it isn't, because _BSD causes O_NDELAY to be defined in fcntl.h as O_NONBLOCK, @@ -7205,9 +7296,9 @@ tty_read_avail_input (struct terminal *terminal, ); #ifndef FIONREAD -#if defined (USG) || defined (DGUX) || defined (CYGWIN) +#if defined (USG) || defined (CYGWIN) fcntl (fileno (tty->input), F_SETFL, 0); -#endif /* USG or DGUX or CYGWIN */ +#endif /* USG or CYGWIN */ #endif /* no FIONREAD */ if (nread <= 0) @@ -7226,14 +7317,14 @@ tty_read_avail_input (struct terminal *terminal, buf.modifiers = meta_modifier; if (tty->meta_key != 2) cbuf[i] &= ~0x80; - + buf.code = cbuf[i]; /* Set the frame corresponding to the active tty. Note that the value of selected_frame is not reliable here, redisplay tends to temporarily change it. */ buf.frame_or_window = tty->top_frame; buf.arg = Qnil; - + kbd_buffer_store_event (&buf); /* Don't look at input that follows a C-g too closely. This reduces lossage due to autorepeat on C-g. */ @@ -7590,13 +7681,7 @@ menu_bar_items (old) /* Add nil, nil, nil, nil at the end. */ i = menu_bar_items_index; if (i + 4 > XVECTOR (menu_bar_items_vector)->size) - { - Lisp_Object tem; - tem = Fmake_vector (make_number (2 * i), Qnil); - bcopy (XVECTOR (menu_bar_items_vector)->contents, - XVECTOR (tem)->contents, i * sizeof (Lisp_Object)); - menu_bar_items_vector = tem; - } + menu_bar_items_vector = larger_vector (menu_bar_items_vector, 2 * i, Qnil); /* Add this item. */ XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil; XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil; @@ -7668,14 +7753,7 @@ menu_bar_item (key, item, dummy1, dummy2) { /* If vector is too small, get a bigger one. */ if (i + 4 > XVECTOR (menu_bar_items_vector)->size) - { - Lisp_Object tem; - tem = Fmake_vector (make_number (2 * i), Qnil); - bcopy (XVECTOR (menu_bar_items_vector)->contents, - XVECTOR (tem)->contents, i * sizeof (Lisp_Object)); - menu_bar_items_vector = tem; - } - + menu_bar_items_vector = larger_vector (menu_bar_items_vector, 2 * i, Qnil); /* Add this item. */ XVECTOR (menu_bar_items_vector)->contents[i++] = key; XVECTOR (menu_bar_items_vector)->contents[i++] @@ -7760,11 +7838,11 @@ parse_menu_item (item, notreal, inmenubar) /* Initialize optional entries. */ for (i = ITEM_PROPERTY_DEF; i < ITEM_PROPERTY_ENABLE; i++) - AREF (item_properties, i) = Qnil; - AREF (item_properties, ITEM_PROPERTY_ENABLE) = Qt; + ASET (item_properties, i, Qnil); + ASET (item_properties, ITEM_PROPERTY_ENABLE, Qt); /* Save the item here to protect it from GC. */ - AREF (item_properties, ITEM_PROPERTY_ITEM) = item; + ASET (item_properties, ITEM_PROPERTY_ITEM, item); item_string = XCAR (item); @@ -7773,12 +7851,12 @@ parse_menu_item (item, notreal, inmenubar) if (STRINGP (item_string)) { /* Old format menu item. */ - AREF (item_properties, ITEM_PROPERTY_NAME) = item_string; + ASET (item_properties, ITEM_PROPERTY_NAME, item_string); /* Maybe help string. */ if (CONSP (item) && STRINGP (XCAR (item))) { - AREF (item_properties, ITEM_PROPERTY_HELP) = XCAR (item); + ASET (item_properties, ITEM_PROPERTY_HELP, XCAR (item)); start = item; item = XCDR (item); } @@ -7793,27 +7871,27 @@ parse_menu_item (item, notreal, inmenubar) } /* This is the real definition--the function to run. */ - AREF (item_properties, ITEM_PROPERTY_DEF) = item; + ASET (item_properties, ITEM_PROPERTY_DEF, item); /* Get enable property, if any. */ if (SYMBOLP (item)) { tem = Fget (item, Qmenu_enable); if (!NILP (Venable_disabled_menus_and_buttons)) - AREF (item_properties, ITEM_PROPERTY_ENABLE) = Qt; + ASET (item_properties, ITEM_PROPERTY_ENABLE, Qt); else if (!NILP (tem)) - AREF (item_properties, ITEM_PROPERTY_ENABLE) = tem; + ASET (item_properties, ITEM_PROPERTY_ENABLE, tem); } } else if (EQ (item_string, Qmenu_item) && CONSP (item)) { /* New format menu item. */ - AREF (item_properties, ITEM_PROPERTY_NAME) = XCAR (item); + ASET (item_properties, ITEM_PROPERTY_NAME, XCAR (item)); start = XCDR (item); if (CONSP (start)) { /* We have a real binding. */ - AREF (item_properties, ITEM_PROPERTY_DEF) = XCAR (start); + ASET (item_properties, ITEM_PROPERTY_DEF, XCAR (start)); item = XCDR (start); /* Is there a cache list with key equivalences. */ @@ -7832,9 +7910,9 @@ parse_menu_item (item, notreal, inmenubar) if (EQ (tem, QCenable)) { if (!NILP (Venable_disabled_menus_and_buttons)) - AREF (item_properties, ITEM_PROPERTY_ENABLE) = Qt; + ASET (item_properties, ITEM_PROPERTY_ENABLE, Qt); else - AREF (item_properties, ITEM_PROPERTY_ENABLE) = XCAR (item); + ASET (item_properties, ITEM_PROPERTY_ENABLE, XCAR (item)); } else if (EQ (tem, QCvisible) && !notreal) { @@ -7845,7 +7923,7 @@ parse_menu_item (item, notreal, inmenubar) return 0; } else if (EQ (tem, QChelp)) - AREF (item_properties, ITEM_PROPERTY_HELP) = XCAR (item); + ASET (item_properties, ITEM_PROPERTY_HELP, XCAR (item)); else if (EQ (tem, QCfilter)) filter = item; else if (EQ (tem, QCkey_sequence)) @@ -7860,7 +7938,7 @@ parse_menu_item (item, notreal, inmenubar) { tem = XCAR (item); if (CONSP (tem) || (STRINGP (tem) && NILP (cachelist))) - AREF (item_properties, ITEM_PROPERTY_KEYEQ) = tem; + ASET (item_properties, ITEM_PROPERTY_KEYEQ, tem); } else if (EQ (tem, QCbutton) && CONSP (XCAR (item))) { @@ -7869,10 +7947,9 @@ parse_menu_item (item, notreal, inmenubar) type = XCAR (tem); if (EQ (type, QCtoggle) || EQ (type, QCradio)) { - AREF (item_properties, ITEM_PROPERTY_SELECTED) - = XCDR (tem); - AREF (item_properties, ITEM_PROPERTY_TYPE) - = type; + ASET (item_properties, ITEM_PROPERTY_SELECTED, + XCDR (tem)); + ASET (item_properties, ITEM_PROPERTY_TYPE, type); } } item = XCDR (item); @@ -7892,7 +7969,7 @@ parse_menu_item (item, notreal, inmenubar) item_string = menu_item_eval_property (item_string); if (!STRINGP (item_string)) return 0; - AREF (item_properties, ITEM_PROPERTY_NAME) = item_string; + ASET (item_properties, ITEM_PROPERTY_NAME, item_string); } /* If got a filter apply it on definition. */ @@ -7902,7 +7979,7 @@ parse_menu_item (item, notreal, inmenubar) def = menu_item_eval_property (list2 (XCAR (filter), list2 (Qquote, def))); - AREF (item_properties, ITEM_PROPERTY_DEF) = def; + ASET (item_properties, ITEM_PROPERTY_DEF, def); } /* Enable or disable selection of item. */ @@ -7915,7 +7992,7 @@ parse_menu_item (item, notreal, inmenubar) tem = menu_item_eval_property (tem); if (inmenubar && NILP (tem)) return 0; /* Ignore disabled items in menu bar. */ - AREF (item_properties, ITEM_PROPERTY_ENABLE) = tem; + ASET (item_properties, ITEM_PROPERTY_ENABLE, tem); } /* If we got no definition, this item is just unselectable text which @@ -7929,8 +8006,8 @@ parse_menu_item (item, notreal, inmenubar) /* For a subkeymap, just record its details and exit. */ if (CONSP (tem)) { - AREF (item_properties, ITEM_PROPERTY_MAP) = tem; - AREF (item_properties, ITEM_PROPERTY_DEF) = tem; + ASET (item_properties, ITEM_PROPERTY_MAP, tem); + ASET (item_properties, ITEM_PROPERTY_DEF, tem); return 1; } @@ -8044,7 +8121,8 @@ parse_menu_item (item, notreal, inmenubar) tem = XCDR (cachelist); if (newcache && !NILP (tem)) { - tem = concat3 (build_string (" ("), tem, build_string (")")); + tem = concat2 (build_string (" "), tem); + // tem = concat3 (build_string (" ("), tem, build_string (")")); XSETCDR (cachelist, tem); } @@ -8053,7 +8131,7 @@ parse_menu_item (item, notreal, inmenubar) return 1; /* If we have an equivalent key binding, use that. */ - AREF (item_properties, ITEM_PROPERTY_KEYEQ) = tem; + ASET (item_properties, ITEM_PROPERTY_KEYEQ, tem); /* Include this when menu help is implemented. tem = XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]; @@ -8069,8 +8147,8 @@ parse_menu_item (item, notreal, inmenubar) /* Handle radio buttons or toggle boxes. */ tem = AREF (item_properties, ITEM_PROPERTY_SELECTED); if (!NILP (tem)) - AREF (item_properties, ITEM_PROPERTY_SELECTED) - = menu_item_eval_property (tem); + ASET (item_properties, ITEM_PROPERTY_SELECTED, + menu_item_eval_property (tem)); return 1; } @@ -8444,16 +8522,9 @@ append_tool_bar_item () /* Enlarge tool_bar_items_vector if necessary. */ if (ntool_bar_items + TOOL_BAR_ITEM_NSLOTS >= XVECTOR (tool_bar_items_vector)->size) - { - Lisp_Object new_vector; - int old_size = XVECTOR (tool_bar_items_vector)->size; - - new_vector = Fmake_vector (make_number (2 * old_size), Qnil); - bcopy (XVECTOR (tool_bar_items_vector)->contents, - XVECTOR (new_vector)->contents, - old_size * sizeof (Lisp_Object)); - tool_bar_items_vector = new_vector; - } + tool_bar_items_vector + = larger_vector (tool_bar_items_vector, + 2 * XVECTOR (tool_bar_items_vector)->size, Qnil); /* Append entries from tool_bar_item_properties to the end of tool_bar_items_vector. */ @@ -8557,7 +8628,7 @@ read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu) to indicate that they came from a mouse menu, so that when present in last_nonmenu_event they won't confuse things. */ - for (tem = XCDR (value); !NILP (tem); tem = XCDR (tem)) + for (tem = XCDR (value); CONSP (tem); tem = XCDR (tem)) { record_menu_key (XCAR (tem)); if (SYMBOLP (XCAR (tem)) @@ -9133,8 +9204,13 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, key's again in Vfunction_key_map. */ volatile keyremap fkey; - /* Likewise, for key_translation_map. */ - volatile keyremap keytran; + /* Likewise, for key_translation_map and input-decode-map. */ + volatile keyremap keytran, indec; + + /* Non-zero if we are trying to map a key by changing an upper-case + letter to lower case, or a shifted function key to an unshifted + one. */ + volatile int shift_translated = 0; /* If we receive a `switch-frame' or `select-window' event in the middle of a key sequence, we put it off for later. @@ -9169,7 +9245,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, last_nonmenu_event = Qnil; delayed_switch_frame = Qnil; - + if (INTERACTIVE) { if (!NILP (prompt)) @@ -9204,18 +9280,28 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, orig_keymap = get_local_map (PT, current_buffer, Qkeymap); from_string = Qnil; + /* The multi-tty merge moved the code below to right after + `replay_sequence' which caused all these translation maps to be applied + repeatedly, even tho their doc says very clearly they are not applied to + their own output. + The reason for this move was: "We may switch keyboards between rescans, + so we need to reinitialize fkey and keytran before each replay". + This move was wrong (even if we switch keyboards, keybuf still holds the + keys we've read already from the original keyboard and some of those keys + may have already been translated). So there may still be a bug out there + lurking. */ + indec.map = indec.parent = current_kboard->Vinput_decode_map; + fkey.map = fkey.parent = current_kboard->Vlocal_function_key_map; + keytran.map = keytran.parent = Vkey_translation_map; + indec.start = indec.end = 0; + fkey.start = fkey.end = 0; + keytran.start = keytran.end = 0; + /* We jump here when the key sequence has been thoroughly changed, and we need to rescan it starting from the beginning. When we jump here, keybuf[0..mock_input] holds the sequence we should reread. */ replay_sequence: - /* We may switch keyboards between rescans, so we need to - reinitialize fkey and keytran before each replay. */ - fkey.map = fkey.parent = current_kboard->Vlocal_function_key_map; - keytran.map = keytran.parent = current_kboard->Vlocal_key_translation_map; - fkey.start = fkey.end = 0; - keytran.start = keytran.end = 0; - starting_buffer = current_buffer; first_unbound = bufsize + 1; @@ -9301,7 +9387,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, 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)) + : (/* indec.start < t || fkey.start < t || */ keytran.start < t)) { Lisp_Object key; int used_mouse_menu = 0; @@ -9319,13 +9405,17 @@ 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 (indec.end == t || (indec.end > t && indec.end <= mock_input)); + eassert (indec.start <= indec.end); eassert (fkey.start <= fkey.end); eassert (keytran.start <= keytran.end); - /* key-translation-map is applied *after* function-key-map. */ + /* key-translation-map is applied *after* function-key-map + which is itself applied *after* input-decode-map. */ + eassert (fkey.end <= indec.start); eassert (keytran.end <= fkey.start); - if (first_unbound < fkey.start && first_unbound < keytran.start) + if (/* first_unbound < indec.start && 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 @@ -9335,6 +9425,8 @@ 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; + indec.end = indec.start -= first_unbound + 1; + indec.map = indec.parent; fkey.end = fkey.start -= first_unbound + 1; fkey.map = fkey.parent; keytran.end = keytran.start -= first_unbound + 1; @@ -9515,7 +9607,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, } GROW_RAW_KEYBUF; - XVECTOR (raw_keybuf)->contents[raw_keybuf_count++] = key; + ASET (raw_keybuf, raw_keybuf_count, key); + raw_keybuf_count++; } /* Clicks in non-text areas get prefixed by the symbol @@ -9542,7 +9635,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, { Lisp_Object window, posn; - window = POSN_WINDOW (EVENT_START (key)); + window = POSN_WINDOW (EVENT_START (key)); posn = POSN_POSN (EVENT_START (key)); if (CONSP (posn) @@ -9760,15 +9853,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, - we need to update first_unbound. */ + After event 0, first_unbound is 0, after event 1 indec.start, + fkey.start, and keytran.start are all 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 indec.start. */ first_unbound = min (t, first_unbound); head = EVENT_HEAD (key); @@ -9853,21 +9946,27 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, /* 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. + if mock_input <= t + 1, we need to adjust indec, + 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) + if (indec.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) + indec.end = indec.start + = min (last_real_key_start, indec.start); + indec.map = indec.parent; + if (fkey.end > last_real_key_start) { - keytran.end = keytran.start - = min (last_real_key_start, keytran.start); - keytran.map = keytran.parent; + 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) @@ -9921,8 +10020,28 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, /* Record what part of this_command_keys is the current key sequence. */ this_single_command_key_start = this_command_key_count - t; - if (first_binding < nmaps && NILP (submaps[first_binding])) + /* Look for this sequence in input-decode-map. + Scan from indec.end until we find a bound suffix. */ + while (indec.end < t) + { + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; + int done, diff; + + GCPRO4 (indec.map, fkey.map, keytran.map, delayed_switch_frame); + done = keyremap_step (keybuf, bufsize, &indec, max (t, mock_input), + 1, &diff, prompt); + UNGCPRO; + if (done) + { + mock_input = diff + max (t, mock_input); + goto replay_sequence; + } + } + + if (first_binding < nmaps && NILP (submaps[first_binding]) + && indec.start >= t) /* There is a binding and it's not a prefix. + (and it doesn't have any input-decode-map translation pending). There is thus no function-key in this sequence. Moving fkey.start is important in this case to allow keytran.start to go over the sequence before we return (since we keep the @@ -9935,12 +10054,12 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, /* If the sequence is unbound, see if we can hang a function key off the end of it. */ /* Continue scan from fkey.end until we find a bound suffix. */ - while (fkey.end < t) + while (fkey.end < indec.start) { - struct gcpro gcpro1, gcpro2, gcpro3; + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; int done, diff; - GCPRO3 (fkey.map, keytran.map, delayed_switch_frame); + GCPRO4 (indec.map, fkey.map, keytran.map, delayed_switch_frame); done = keyremap_step (keybuf, bufsize, &fkey, max (t, mock_input), /* If there's a binding (i.e. @@ -9952,6 +10071,10 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, if (done) { mock_input = diff + max (t, mock_input); + /* Adjust the input-decode-map counters. */ + indec.end += diff; + indec.start += diff; + goto replay_sequence; } } @@ -9960,17 +10083,19 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, Scan from keytran.end until we find a bound suffix. */ while (keytran.end < fkey.start) { - struct gcpro gcpro1, gcpro2, gcpro3; + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; int done, diff; - GCPRO3 (fkey.map, keytran.map, delayed_switch_frame); + GCPRO4 (indec.map, 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. */ + /* Adjust the function-key-map and input-decode-map counters. */ + indec.end += diff; + indec.start += diff; fkey.end += diff; fkey.start += diff; @@ -9983,11 +10108,10 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, and is an upper case letter use the corresponding lower-case letter instead. */ if (first_binding >= nmaps - && fkey.start >= t && keytran.start >= t + && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t && INTEGERP (key) - && ((((XINT (key) & 0x3ffff) - < XCHAR_TABLE (current_buffer->downcase_table)->size) - && UPPERCASEP (XINT (key) & 0x3ffff)) + && ((CHARACTERP (make_number (XINT (key) & ~CHAR_MODIFIER_MASK)) + && UPPERCASEP (XINT (key) & ~CHAR_MODIFIER_MASK)) || (XINT (key) & shift_modifier))) { Lisp_Object new_key; @@ -9998,14 +10122,15 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, if (XINT (key) & shift_modifier) XSETINT (new_key, XINT (key) & ~shift_modifier); else - XSETINT (new_key, (DOWNCASE (XINT (key) & 0x3ffff) - | (XINT (key) & ~0x3ffff))); + XSETINT (new_key, (DOWNCASE (XINT (key) & ~CHAR_MODIFIER_MASK) + | (XINT (key) & CHAR_MODIFIER_MASK))); /* We have to do this unconditionally, regardless of whether the lower-case char is defined in the keymaps, because they might get translated through function-key-map. */ keybuf[t - 1] = new_key; mock_input = max (t, mock_input); + shift_translated = 1; goto replay_sequence; } @@ -10014,35 +10139,45 @@ 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 - && SYMBOLP (key)) - { - Lisp_Object breakdown; - int modifiers; - - breakdown = parse_modifiers (key); - modifiers = XINT (XCAR (XCDR (breakdown))); - if (modifiers & shift_modifier) + && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t) + { + Lisp_Object breakdown = parse_modifiers (key); + int modifiers + = CONSP (breakdown) ? (XINT (XCAR (XCDR (breakdown)))) : 0; + + if (modifiers & shift_modifier + /* Treat uppercase keys as shifted. */ + || (INTEGERP (key) + && (KEY_TO_CHAR (key) + < XCHAR_TABLE (current_buffer->downcase_table)->size) + && UPPERCASEP (KEY_TO_CHAR (key)))) { - Lisp_Object new_key; + Lisp_Object new_key + = (modifiers & shift_modifier + ? apply_modifiers (modifiers & ~shift_modifier, + XCAR (breakdown)) + : make_number (DOWNCASE (KEY_TO_CHAR (key)) | modifiers)); original_uppercase = key; original_uppercase_position = t - 1; - modifiers &= ~shift_modifier; - new_key = apply_modifiers (modifiers, - XCAR (breakdown)); - + /* We have to do this unconditionally, regardless of whether + the lower-case char is defined in the keymaps, because they + might get translated through function-key-map. */ keybuf[t - 1] = new_key; mock_input = max (t, mock_input); + /* Reset fkey (and consequently keytran) to apply + function-key-map on the result, so that S-backspace is + correctly mapped to DEL (via backspace). OTOH, + input-decode-map doesn't need to go through it again. */ fkey.start = fkey.end = 0; keytran.start = keytran.end = 0; + shift_translated = 1; goto replay_sequence; } } } - if (!dummyflag) read_key_sequence_cmd = (first_binding < nmaps ? defs[first_binding] @@ -10056,7 +10191,13 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, if ((dont_downcase_last || first_binding >= nmaps) && t > 0 && t - 1 == original_uppercase_position) - keybuf[t - 1] = original_uppercase; + { + keybuf[t - 1] = original_uppercase; + shift_translated = 0; + } + + if (shift_translated) + Vthis_command_keys_shift_translated = Qt; /* Occasionally we fabricate events, perhaps by expanding something according to function-key-map, or by adding a prefix symbol to a @@ -10075,8 +10216,6 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, add_command_key (keybuf[t]); } - - UNGCPRO; return t; } @@ -10158,7 +10297,7 @@ will read just one key sequence. */) this_single_command_key_start = 0; } -#ifdef HAVE_X_WINDOWS +#ifdef HAVE_WINDOW_SYSTEM if (display_hourglass_p) cancel_hourglass (); #endif @@ -10170,7 +10309,7 @@ will read just one key sequence. */) #if 0 /* The following is fine for code reading a key sequence and then proceeding with a lenghty computation, but it's not good for code reading keys in a loop, like an input method. */ -#ifdef HAVE_X_WINDOWS +#ifdef HAVE_WINDOW_SYSTEM if (display_hourglass_p) start_hourglass (); #endif @@ -10218,7 +10357,7 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector, this_single_command_key_start = 0; } -#ifdef HAVE_X_WINDOWS +#ifdef HAVE_WINDOW_SYSTEM if (display_hourglass_p) cancel_hourglass (); #endif @@ -10227,7 +10366,7 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector, prompt, ! NILP (dont_downcase_last), ! NILP (can_return_switch_frame), 0); -#ifdef HAVE_X_WINDOWS +#ifdef HAVE_WINDOW_SYSTEM if (display_hourglass_p) start_hourglass (); #endif @@ -10257,7 +10396,6 @@ a special event, so ignore the prefix argument and don't clear it. */) register Lisp_Object final; register Lisp_Object tem; Lisp_Object prefixarg; - struct backtrace backtrace; extern int debug_on_next_call; debug_on_next_call = 0; @@ -10323,20 +10461,11 @@ a special event, so ignore the prefix argument and don't clear it. */) } if (CONSP (final) || SUBRP (final) || COMPILEDP (final)) - { - backtrace.next = backtrace_list; - backtrace_list = &backtrace; - backtrace.function = &Qcall_interactively; - backtrace.args = &cmd; - backtrace.nargs = 1; - backtrace.evalargs = 0; - backtrace.debug_on_exit = 0; + /* Don't call Fcall_interactively directly because we want to make + sure the backtrace has an entry for `call-interactively'. + For the same reason, pass `cmd' rather than `final'. */ + return call3 (Qcall_interactively, cmd, record_flag, keys); - tem = Fcall_interactively (cmd, record_flag, keys); - - backtrace_list = backtrace.next; - return tem; - } return Qnil; } @@ -10360,7 +10489,7 @@ give to the command you invoke, if it asks for an argument. */) Lisp_Object saved_keys, saved_last_point_position_buffer; Lisp_Object bindings, value; struct gcpro gcpro1, gcpro2, gcpro3; -#ifdef HAVE_X_WINDOWS +#ifdef HAVE_WINDOW_SYSTEM /* The call to Fcompleting_read wil start and cancel the hourglass, but if the hourglass was already scheduled, this means that no hourglass will be shown for the actual M-x command itself. @@ -10400,7 +10529,7 @@ give to the command you invoke, if it asks for an argument. */) Qt, Qnil, Qextended_command_history, Qnil, Qnil); -#ifdef HAVE_X_WINDOWS +#ifdef HAVE_WINDOW_SYSTEM if (hstarted) start_hourglass (); #endif @@ -10447,7 +10576,7 @@ give to the command you invoke, if it asks for an argument. */) bindings = Qnil; value = Qnil; - GCPRO2 (bindings, value); + GCPRO3 (bindings, value, function); value = Fcommand_execute (function, Qt, Qnil, Qnil); /* If the command has a key binding, print it now. */ @@ -11159,7 +11288,7 @@ See also `current-input-mode'. */) new_interrupt_input = 1; #endif - if (new_interrupt_input != interrupt_input) + if (new_interrupt_input != interrupt_input) { #ifdef POLL_FOR_INPUT stop_polling (); @@ -11239,7 +11368,7 @@ See also `current-input-mode'. */) struct terminal *t = get_terminal (terminal, 1); struct tty_display_info *tty; int new_meta; - + if (t == NULL || t->type != output_termcap) return Qnil; tty = t->display_info.tty; @@ -11251,7 +11380,7 @@ See also `current-input-mode'. */) else new_meta = 2; - if (tty->meta_key != new_meta) + if (tty->meta_key != new_meta) { #ifndef DOS_NT /* this causes startup screen to be restored and messes with the mouse */ @@ -11259,7 +11388,7 @@ See also `current-input-mode'. */) #endif tty->meta_key = new_meta; - + #ifndef DOS_NT init_sys_modes (tty); #endif @@ -11291,7 +11420,7 @@ See also `current-input-mode'. */) /* this causes startup screen to be restored and messes with the mouse */ reset_sys_modes (tty); #endif - + /* Don't let this value be out of range. */ quit_char = XINT (quit) & (tty->meta_key == 0 ? 0177 : 0377); @@ -11301,7 +11430,7 @@ See also `current-input-mode'. */) return Qnil; } - + DEFUN ("set-input-mode", Fset_input_mode, Sset_input_mode, 3, 4, 0, doc: /* Set mode of reading keyboard input. First arg INTERRUPT non-nil means use input interrupts; @@ -11448,6 +11577,7 @@ init_kboard (kb) kb->Vlast_command = Qnil; kb->Vreal_last_command = Qnil; kb->Vkeyboard_translate_table = Qnil; + kb->Vlast_repeatable_command = Qnil; kb->Vprefix_arg = Qnil; kb->Vlast_prefix_arg = Qnil; kb->kbd_queue = Qnil; @@ -11462,10 +11592,10 @@ init_kboard (kb) kb->reference_count = 0; kb->Vsystem_key_alist = Qnil; kb->system_key_syms = Qnil; + kb->Vwindow_system = Qt; /* Unset. */ + kb->Vinput_decode_map = Fmake_sparse_keymap (Qnil); kb->Vlocal_function_key_map = Fmake_sparse_keymap (Qnil); Fset_keymap_parent (kb->Vlocal_function_key_map, Vfunction_key_map); - kb->Vlocal_key_translation_map = Fmake_sparse_keymap (Qnil); - Fset_keymap_parent (kb->Vlocal_key_translation_map, Vkey_translation_map); kb->Vdefault_minibuffer_frame = Qnil; } @@ -11543,8 +11673,12 @@ init_keyboard () #ifdef MULTI_KBOARD current_kboard = initial_kboard; #endif + /* Re-initialize the keyboard again. */ wipe_kboard (current_kboard); init_kboard (current_kboard); + /* A value of nil for Vwindow_system normally means a tty, but we also use + it for the initial terminal since there is no window system there. */ + current_kboard->Vwindow_system = Qnil; if (!noninteractive) { @@ -11616,6 +11750,8 @@ struct event_head head_table[] = { void syms_of_keyboard () { + pending_funcalls = Qnil; + Vpre_help_message = Qnil; staticpro (&Vpre_help_message); @@ -11695,6 +11831,11 @@ syms_of_keyboard () staticpro (&Qmac_apple_event); #endif +#ifdef HAVE_DBUS + Qdbus_event = intern ("dbus-event"); + staticpro (&Qdbus_event); +#endif + Qmenu_enable = intern ("menu-enable"); staticpro (&Qmenu_enable); Qmenu_alias = intern ("menu-alias"); @@ -11855,6 +11996,7 @@ syms_of_keyboard () staticpro (&help_form_saved_window_configs); defsubr (&Scurrent_idle_time); + defsubr (&Sevent_symbol_parse_modifiers); defsubr (&Sevent_convert_list); defsubr (&Sread_key_sequence); defsubr (&Sread_key_sequence_vector); @@ -11956,12 +12098,25 @@ See Info node `(elisp)Multiple displays'. */); DEFVAR_KBOARD ("real-last-command", Vreal_last_command, doc: /* Same as `last-command', but never altered by Lisp code. */); + DEFVAR_KBOARD ("last-repeatable-command", Vlast_repeatable_command, + doc: /* Last command that may be repeated. +The last command executed that was not bound to an input event. +This is the command `repeat' will try to repeat. */); + DEFVAR_LISP ("this-command", &Vthis_command, doc: /* The command now being executed. The command can set this variable; whatever is put here will be in `last-command' during the following command. */); Vthis_command = Qnil; + DEFVAR_LISP ("this-command-keys-shift-translated", + &Vthis_command_keys_shift_translated, + doc: /* Non-nil if the key sequence activating this command was shift-translated. +Shift-translation occurs when there is no binding for the key sequence +as entered, but a binding was found by changing an upper-case letter +to lower-case, or a shifted function key to an unshifted one. */); + Vthis_command_keys_shift_translated = Qnil; + DEFVAR_LISP ("this-original-command", &Vthis_original_command, doc: /* The command bound to the current key sequence before remapping. It equals `this-command' if the original command was not remapped through @@ -12198,8 +12353,8 @@ See Info node `(elisp)Multiple displays'. */); DEFVAR_KBOARD ("local-function-key-map", Vlocal_function_key_map, doc: /* Keymap that translates key sequences to key sequences during input. -This is used mainly for mapping ASCII function key sequences into -real Emacs function key events (symbols). +This is used mainly for mapping key sequences into some preferred +key events (symbols). The `read-key-sequence' function replaces any subsequence bound by `local-function-key-map' with its binding. More precisely, when the @@ -12225,6 +12380,25 @@ define a binding on all terminals, change `function-key-map' instead. Initially, `local-function-key-map' is an empty keymap that has `function-key-map' as its parent on all terminal devices. */); + DEFVAR_KBOARD ("input-decode-map", Vinput_decode_map, + doc: /* Keymap that decodes input escape sequences. +This is used mainly for mapping ASCII function key sequences into +real Emacs function key events (symbols). + +The `read-key-sequence' function replaces any subsequence bound by +`local-function-key-map' with its binding. Contrary to `function-key-map', +this map applies its rebinding regardless of the presence of an ordinary +binding. So it is more like `key-translation-map' except that it applies +before `function-key-map' rather than after. + +If the binding is a function, it is called with one argument (the prompt) +and its return value (a key sequence) is used. + +The events that come from bindings in `input-decode-map' are not +themselves looked up in `input-decode-map'. + +This variable is keyboard-local. */); + DEFVAR_LISP ("function-key-map", &Vfunction_key_map, doc: /* The parent keymap of all `local-function-key-map' instances. Function key definitions that apply to all terminal devices should go @@ -12232,19 +12406,12 @@ here. If a mapping is defined in both the current `local-function-key-map' binding and this variable, then the local definition will take precendence. */); Vfunction_key_map = Fmake_sparse_keymap (Qnil); - - DEFVAR_KBOARD ("local-key-translation-map", Vlocal_key_translation_map, - doc: /* Keymap of key translations that can override keymaps. -This keymap works like `function-key-map', but comes after that, -and its non-prefix bindings override ordinary bindings. - -`key-translation-map' has a separate binding for each terminal device. -(See Info node `(elisp)Multiple displays'.) If you need to set a key -translation on all terminals, change `global-key-translation-map' instead. */); DEFVAR_LISP ("key-translation-map", &Vkey_translation_map, - doc: /* The parent keymap of all `local-key-translation-map' instances. -Key translations that apply to all terminal devices should go here. */); + doc: /* Keymap of key translations that can override keymaps. +This keymap works like `function-key-map', but comes after that, +and its non-prefix bindings override ordinary bindings. +Another difference is that it is global rather than keyboard-local. */); Vkey_translation_map = Fmake_sparse_keymap (Qnil); DEFVAR_LISP ("deferred-action-list", &Vdeferred_action_list, @@ -12353,6 +12520,15 @@ and the Lisp function within which the error was signaled. */); Help functions bind this to allow help on disabled menu items and tool-bar buttons. */); Venable_disabled_menus_and_buttons = Qnil; + +#ifdef MULTI_KBOARD + /* Create the initial keyboard. */ + initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD)); + init_kboard (initial_kboard); + /* Vwindow_system is left at t for now. */ + initial_kboard->next_kboard = all_kboards; + all_kboards = initial_kboard; +#endif } void @@ -12397,6 +12573,13 @@ keys_of_keyboard () * "handle-select-window"); */ initial_define_lispy_key (Vspecial_event_map, "save-session", "handle-save-session"); + +#ifdef HAVE_DBUS + /* Define a special event which is raised for dbus callback + functions. */ + initial_define_lispy_key (Vspecial_event_map, "dbus-event", + "dbus-handle-event"); +#endif } /* Mark the pointers in the kboard objects. @@ -12415,6 +12598,7 @@ mark_kboards () mark_object (kb->Vlast_command); mark_object (kb->Vreal_last_command); mark_object (kb->Vkeyboard_translate_table); + mark_object (kb->Vlast_repeatable_command); mark_object (kb->Vprefix_arg); mark_object (kb->Vlast_prefix_arg); mark_object (kb->kbd_queue); @@ -12422,8 +12606,9 @@ mark_kboards () mark_object (kb->Vlast_kbd_macro); mark_object (kb->Vsystem_key_alist); mark_object (kb->system_key_syms); + mark_object (kb->Vwindow_system); + mark_object (kb->Vinput_decode_map); mark_object (kb->Vlocal_function_key_map); - mark_object (kb->Vlocal_key_translation_map); mark_object (kb->Vdefault_minibuffer_frame); mark_object (kb->echo_string); }