X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/169f857ada132cc7caa98eecb9c266d55090c5ba..3c9dc1cf0d6be64608cd309ad042d74e4fc02049:/src/keyboard.c diff --git a/src/keyboard.c b/src/keyboard.c index 5a1fc4fa42..9260a17574 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1,5 +1,5 @@ /* Keyboard and mouse input; editor command loop. - Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99, 2000, 01, 02 + Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99,2000,01,02,03 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -785,14 +785,19 @@ echo_char (c) /* Replace a dash from echo_dash with a space, otherwise add a space at the end as a separator between keys. */ if (STRINGP (echo_string) - && SCHARS (echo_string) > 0) + && SCHARS (echo_string) > 1) { - Lisp_Object last_char, idx; + Lisp_Object last_char, prev_char, idx; + + idx = make_number (SCHARS (echo_string) - 2); + prev_char = Faref (echo_string, idx); idx = make_number (SCHARS (echo_string) - 1); last_char = Faref (echo_string, idx); - if (XINT (last_char) == '-') + /* We test PREV_CHAR to make sure this isn't the echoing + of a minus-sign. */ + if (XINT (last_char) == '-' && XINT (prev_char) != ' ') Faset (echo_string, idx, make_number (' ')); else echo_string = concat2 (echo_string, build_string (" ")); @@ -1869,7 +1874,10 @@ adjust_point_for_property (last_pt, modified) int beg, end; Lisp_Object val, overlay, tmp; int check_composition = 1, check_display = 1, check_invisible = 1; + int orig_pt = PT; + /* FIXME: cycling is probably not necessary because these properties + can't be usefully combined anyway. */ while (check_composition || check_display || check_invisible) { if (check_composition @@ -1936,7 +1944,19 @@ adjust_point_for_property (last_pt, modified) /* Move away from the inside area. */ if (beg < PT && end > PT) { - SET_PT (PT < last_pt ? beg : end); + SET_PT ((orig_pt == PT && (last_pt < beg || last_pt > end)) + /* We haven't moved yet (so we don't need to fear + infinite-looping) and we were outside the range + before (so either end of the range still corresponds + to a move in the right direction): pretend we moved + less than we actually did, so that we still have + more freedom below in choosing which end of the range + to go to. */ + ? (orig_pt = -1, PT < last_pt ? end : beg) + /* We either have moved already or the last point + was already in the range: we don't get to choose + which end of the range we have to go to. */ + : (PT < last_pt ? beg : end)); check_composition = check_display = 1; } xassert (PT == beg || PT == end); @@ -1983,6 +2003,11 @@ static Lisp_Object safe_run_hooks_error (data) Lisp_Object data; { + Lisp_Object args[3]; + args[0] = build_string ("Error in %s: %s"); + args[1] = Vinhibit_quit; + args[2] = data; + Fmessage (3, args); return Fset (Vinhibit_quit, Qnil); } @@ -4000,14 +4025,6 @@ kbd_buffer_get_event (kbp, used_mouse_menu) && !EQ (frame, selected_frame)) obj = make_lispy_switch_frame (frame); internal_last_event_frame = frame; - kbd_fetch_ptr = event + 1; - } - else if (event->kind == SELECT_WINDOW_EVENT) - { - /* Make an event (select-window (WINDOW)). */ - obj = Fcons (event->frame_or_window, Qnil); - obj = Fcons (Qselect_window, Fcons (obj, Qnil)); - kbd_fetch_ptr = event + 1; } else @@ -4996,8 +5013,17 @@ make_lispy_event (event) case MULTIBYTE_CHAR_KEYSTROKE_EVENT: { Lisp_Object lispy_c; + int c = event->code; - XSETFASTINT (lispy_c, event->code); + /* Add in the other modifier bits. We took care of ctrl_modifier + just above, and the shift key was taken care of by the X code, + and applied to control characters by make_ctrl_char. */ + c |= (event->modifiers + & (meta_modifier | alt_modifier + | hyper_modifier | super_modifier | ctrl_modifier)); + /* What about the `shift' modifier ? */ + button_down_time = 0; + XSETFASTINT (lispy_c, c); return lispy_c; } @@ -5089,6 +5115,7 @@ make_lispy_event (event) Lisp_Object posn; Lisp_Object string_info = Qnil; int row, column; + int wx, wy; /* Ignore mouse events that were made on frame that have been deleted. */ @@ -5160,7 +5187,8 @@ make_lispy_event (event) /* Set `window' to the window under frame pixel coordinates event->x/event->y. */ window = window_from_coordinates (f, XINT (event->x), - XINT (event->y), &part, 0); + XINT (event->y), + &part, &wx, &wy, 0); if (!WINDOWP (window)) { @@ -5173,11 +5201,6 @@ make_lispy_event (event) event->x/ event->y. */ struct window *w = XWINDOW (window); - /* Get window relative coordinates. Original code - `rounded' this to glyph boundaries. */ - int wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (event->x)); - int wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (event->y)); - /* Set event coordinates to window-relative coordinates for constructing the Lisp event below. */ XSETINT (event->x, wx); @@ -5491,7 +5514,7 @@ make_lispy_event (event) } } #endif /* WINDOWSNT */ -#if defined(WINDOWSNT) || defined(MAC_OSX) +#if defined(MAC_OSX) case MOUSE_WHEEL_EVENT: { enum window_part part; @@ -5508,7 +5531,8 @@ make_lispy_event (event) pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y), &column, &row, NULL, 1); window = window_from_coordinates (f, XINT (event->x), - XINT (event->y), &part, 0); + XINT (event->y), + &part, 0, 0, 0); if (!WINDOWP (window)) { @@ -5518,8 +5542,8 @@ make_lispy_event (event) else { int pixcolumn, pixrow; - column -= XINT (XWINDOW (window)->left); - row -= XINT (XWINDOW (window)->top); + column -= WINDOW_LEFT_EDGE_COL (XWINDOW (window)); + row -= WINDOW_TOP_EDGE_LINE (XWINDOW (window)); glyph_to_pixel_coords (XWINDOW(window), column, row, &pixcolumn, &pixrow); XSETINT (event->x, pixcolumn); @@ -5563,7 +5587,7 @@ make_lispy_event (event) Qnil)))); } } -#endif /* WINDOWSNT || MAC_OSX */ +#endif /* MAC_OSX */ case DRAG_N_DROP_EVENT: { @@ -5572,6 +5596,7 @@ make_lispy_event (event) Lisp_Object window; Lisp_Object posn; Lisp_Object files; + int wx, wy; /* The frame_or_window field should be a cons of the frame in which the event occurred and a list of the filenames @@ -5588,7 +5613,8 @@ make_lispy_event (event) return Qnil; window = window_from_coordinates (f, XINT (event->x), - XINT (event->y), &part, 0); + XINT (event->y), + &part, &wx, &wy, 0); if (!WINDOWP (window)) { @@ -5601,10 +5627,6 @@ make_lispy_event (event) event->x/ event->y. */ struct window *w = XWINDOW (window); - /* Get window relative coordinates. */ - int wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (event->x)); - int wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (event->y)); - /* Set event coordinates to window-relative coordinates for constructing the Lisp event below. */ XSETINT (event->x, wx); @@ -5658,6 +5680,12 @@ make_lispy_event (event) return event->arg; #endif + case SELECT_WINDOW_EVENT: + /* Make an event (select-window (WINDOW)). */ + return Fcons (Qselect_window, + Fcons (Fcons (event->frame_or_window, Qnil), + Qnil)); + case TOOL_BAR_EVENT: if (EQ (event->arg, event->frame_or_window)) /* This is the prefix key. We translate this to @@ -5713,21 +5741,20 @@ make_lispy_movement (frame, bar_window, part, x, y, time) enum window_part area; Lisp_Object window; Lisp_Object posn; + int wx, wy; if (frame) /* It's in a frame; which window on that frame? */ - window = window_from_coordinates (frame, XINT (x), XINT (y), &area, 0); + window = window_from_coordinates (frame, XINT (x), XINT (y), + &area, &wx, &wy, 0); else window = Qnil; if (WINDOWP (window)) { struct window *w = XWINDOW (window); - int wx, wy; - /* Get window relative coordinates. */ - wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (x)); - wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (y)); + /* Set window relative coordinates. */ XSETINT (x, wx); XSETINT (y, wy); @@ -5841,6 +5868,26 @@ parse_modifiers_uncached (symbol, modifier_end) break; #undef SINGLE_LETTER_MOD + +#define MULTI_LETTER_MOD(BIT, NAME, LEN) \ + if (i + LEN + 1 <= SBYTES (name) \ + && ! strncmp (SDATA (name) + i, NAME, LEN)) \ + { \ + this_mod_end = i + LEN; \ + this_mod = BIT; \ + } + + case 'd': + MULTI_LETTER_MOD (drag_modifier, "drag", 4); + MULTI_LETTER_MOD (down_modifier, "down", 4); + MULTI_LETTER_MOD (double_modifier, "double", 6); + break; + + case 't': + MULTI_LETTER_MOD (triple_modifier, "triple", 6); + break; +#undef MULTI_LETTER_MOD + } /* If we found no modifier, stop looking for them. */ @@ -6039,12 +6086,15 @@ apply_modifiers (modifiers, base) entry = Fcons (index, new_symbol); Fput (base, Qmodifier_cache, Fcons (entry, cache)); - /* We have the parsing info now for free, so add it to the caches. */ - XSETFASTINT (index, modifiers); - Fput (new_symbol, Qevent_symbol_element_mask, - Fcons (base, Fcons (index, Qnil))); - Fput (new_symbol, Qevent_symbol_elements, - Fcons (base, lispy_modifier_list (modifiers))); + /* We have the parsing info now for free, so we could add it to + the caches: + XSETFASTINT (index, modifiers); + Fput (new_symbol, Qevent_symbol_element_mask, + Fcons (base, Fcons (index, Qnil))); + Fput (new_symbol, Qevent_symbol_elements, + Fcons (base, lispy_modifier_list (modifiers))); + Sadly, this is only correct if `base' is indeed a base event, + which is not necessarily the case. -stef */ } /* Make sure this symbol is of the same kind as BASE. @@ -6666,7 +6716,7 @@ read_avail_input (expected) #ifdef SIGIO /* for entire page */ /* Note SIGIO has been undef'd if FIONREAD is missing. */ -SIGTYPE +static SIGTYPE input_available_signal (signo) int signo; { @@ -6727,8 +6777,8 @@ reinvoke_input_signal () -static void menu_bar_item P_ ((Lisp_Object, Lisp_Object)); -static void menu_bar_one_keymap P_ ((Lisp_Object)); +static void menu_bar_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object, void*)); +static Lisp_Object menu_bar_one_keymap_changed_items; /* These variables hold the vector under construction within menu_bar_items and its subroutines, and the current index @@ -6832,7 +6882,10 @@ menu_bar_items (old) def = get_keymap (access_keymap (maps[mapno], Qmenu_bar, 1, 0, 1), 0, 1); if (CONSP (def)) - menu_bar_one_keymap (def); + { + menu_bar_one_keymap_changed_items = Qnil; + map_keymap (def, menu_bar_item, Qnil, NULL, 1); + } } /* Move to the end those items that should be at the end. */ @@ -6886,48 +6939,15 @@ menu_bar_items (old) return menu_bar_items_vector; } -/* Scan one map KEYMAP, accumulating any menu items it defines - in menu_bar_items_vector. */ - -static Lisp_Object menu_bar_one_keymap_changed_items; - -static void -menu_bar_one_keymap (keymap) - Lisp_Object keymap; -{ - Lisp_Object tail, item; - - menu_bar_one_keymap_changed_items = Qnil; - - /* Loop over all keymap entries that have menu strings. */ - for (tail = keymap; CONSP (tail); tail = XCDR (tail)) - { - item = XCAR (tail); - if (CONSP (item)) - menu_bar_item (XCAR (item), XCDR (item)); - else if (VECTORP (item)) - { - /* Loop over the char values represented in the vector. */ - int len = XVECTOR (item)->size; - int c; - for (c = 0; c < len; c++) - { - Lisp_Object character; - XSETFASTINT (character, c); - menu_bar_item (character, XVECTOR (item)->contents[c]); - } - } - } -} - /* Add one item to menu_bar_items_vector, for KEY, ITEM_STRING and DEF. If there's already an item for KEY, add this DEF to it. */ Lisp_Object item_properties; static void -menu_bar_item (key, item) - Lisp_Object key, item; +menu_bar_item (key, item, dummy1, dummy2) + Lisp_Object key, item, dummy1; + void *dummy2; { struct gcpro gcpro1; int i; @@ -7000,7 +7020,10 @@ menu_bar_item (key, item) { Lisp_Object old; old = XVECTOR (menu_bar_items_vector)->contents[i + 2]; - XVECTOR (menu_bar_items_vector)->contents[i + 2] = Fcons (item, old); + /* If the new and the old items are not both keymaps, + the lookup will only find `item'. */ + item = Fcons (item, KEYMAPP (item) && KEYMAPP (XCAR (old)) ? old : Qnil); + XVECTOR (menu_bar_items_vector)->contents[i + 2] = item; } } @@ -7901,7 +7924,7 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps) register Lisp_Object name; int nlength; /* FIXME: Use the minibuffer's frame width. */ - int width = FRAME_WIDTH (SELECTED_FRAME ()) - 4; + int width = FRAME_COLS (SELECTED_FRAME ()) - 4; int idx = -1; int nobindings = 1; Lisp_Object rest, vector; @@ -8163,20 +8186,13 @@ follow_key (key, nmaps, current, defs, next) int nmaps; { int i, first_binding; - int did_meta = 0; first_binding = nmaps; for (i = nmaps - 1; i >= 0; i--) { if (! NILP (current[i])) { - Lisp_Object map; - if (did_meta) - map = defs[i]; - else - map = current[i]; - - defs[i] = access_keymap (map, key, 1, 0, 1); + defs[i] = access_keymap (current[i], key, 1, 0, 1); if (! NILP (defs[i])) first_binding = i; } @@ -8196,10 +8212,123 @@ follow_key (key, nmaps, current, defs, next) such as Vfunction_key_map and Vkey_translation_map. */ typedef struct keyremap { - Lisp_Object map; + Lisp_Object map, parent; int start, end; } keyremap; +/* Lookup KEY in MAP. + MAP is a keymap mapping keys to key vectors or functions. + If the mapping is a function and DO_FUNCTION is non-zero, then + the function is called with PROMPT as parameter and its return + value is used as the return value of this function (after checking + that it is indeed a vector). */ + +static Lisp_Object +access_keymap_keyremap (map, key, prompt, do_funcall) + Lisp_Object map, key, prompt; + int do_funcall; +{ + Lisp_Object next; + + next = access_keymap (map, key, 1, 0, 1); + + /* Handle symbol with autoload definition. */ + if (SYMBOLP (next) && !NILP (Ffboundp (next)) + && CONSP (XSYMBOL (next)->function) + && EQ (XCAR (XSYMBOL (next)->function), Qautoload)) + do_autoload (XSYMBOL (next)->function, next); + + /* Handle a symbol whose function definition is a keymap + or an array. */ + if (SYMBOLP (next) && !NILP (Ffboundp (next)) + && (!NILP (Farrayp (XSYMBOL (next)->function)) + || KEYMAPP (XSYMBOL (next)->function))) + next = XSYMBOL (next)->function; + + /* If the keymap gives a function, not an + array, then call the function with one arg and use + its value instead. */ + if (SYMBOLP (next) && !NILP (Ffboundp (next)) && do_funcall) + { + Lisp_Object tem; + tem = next; + + next = call1 (next, prompt); + /* If the function returned something invalid, + barf--don't ignore it. + (To ignore it safely, we would need to gcpro a bunch of + other variables.) */ + if (! (VECTORP (next) || STRINGP (next))) + error ("Function %s returns invalid key sequence", tem); + } + return next; +} + +/* Do one step of the key remapping used for function-key-map and + key-translation-map: + KEYBUF is the buffer holding the input events. + BUFSIZE is its maximum size. + FKEY is a pointer to the keyremap structure to use. + INPUT is the index of the last element in KEYBUF. + DOIT if non-zero says that the remapping can actually take place. + DIFF is used to return the number of keys added/removed by the remapping. + PARENT is the root of the keymap. + PROMPT is the prompt to use if the remapping happens through a function. + The return value is non-zero if the remapping actually took place. */ + +static int +keyremap_step (keybuf, bufsize, fkey, input, doit, diff, prompt) + Lisp_Object *keybuf, prompt; + keyremap *fkey; + int input, doit, *diff, bufsize; +{ + Lisp_Object next, key; + + key = keybuf[fkey->end++]; + next = access_keymap_keyremap (fkey->map, key, prompt, doit); + + /* If keybuf[fkey->start..fkey->end] is bound in the + map and we're in a position to do the key remapping, replace it with + the binding and restart with fkey->start at the end. */ + if ((VECTORP (next) || STRINGP (next)) && doit) + { + int len = XFASTINT (Flength (next)); + int i; + + *diff = len - (fkey->end - fkey->start); + + if (input + *diff >= bufsize) + error ("Key sequence too long"); + + /* Shift the keys that follow fkey->end. */ + if (*diff < 0) + for (i = fkey->end; i < input; i++) + keybuf[i + *diff] = keybuf[i]; + else if (*diff > 0) + for (i = input - 1; i >= fkey->end; i--) + keybuf[i + *diff] = keybuf[i]; + /* Overwrite the old keys with the new ones. */ + for (i = 0; i < len; i++) + keybuf[fkey->start + i] + = Faref (next, make_number (i)); + + fkey->start = fkey->end += *diff; + fkey->map = fkey->parent; + + return 1; + } + + fkey->map = get_keymap (next, 0, 1); + + /* If we no longer have a bound suffix, try a new position for + fkey->start. */ + if (!CONSP (fkey->map)) + { + fkey->end = ++fkey->start; + fkey->map = fkey->parent; + } + return 0; +} /* Read a sequence of keys that ends with a non prefix character, storing it in KEYBUF, a buffer of size BUFSIZE. @@ -8319,8 +8448,9 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, /* Likewise, for key_translation_map. */ volatile keyremap keytran; - /* If we receive a ``switch-frame'' event in the middle of a key sequence, - we put it off for later. While we're reading, we keep the event here. */ + /* If we receive a `switch-frame' or `select-window' event in the middle of + a key sequence, we put it off for later. + While we're reading, we keep the event here. */ volatile Lisp_Object delayed_switch_frame; /* See the comment below... */ @@ -8351,8 +8481,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, last_nonmenu_event = Qnil; delayed_switch_frame = Qnil; - fkey.map = Vfunction_key_map; - keytran.map = Vkey_translation_map; + fkey.map = fkey.parent = Vfunction_key_map; + keytran.map = keytran.parent = Vkey_translation_map; /* If there is no translation-map, turn off scanning. */ fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1; keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1; @@ -8491,6 +8621,9 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, just one key. */ volatile int echo_local_start, keys_local_start, local_first_binding; + eassert (fkey.end == t || (fkey.end > t && fkey.end <= mock_input)); + eassert (fkey.start <= fkey.end); + eassert (keytran.start <= keytran.end); /* key-translation-map is applied *after* function-key-map. */ eassert (keytran.end <= fkey.start); @@ -8505,9 +8638,9 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, keybuf[i - first_unbound - 1] = keybuf[i]; mock_input = t - first_unbound - 1; fkey.end = fkey.start -= first_unbound + 1; - fkey.map = Vfunction_key_map; + fkey.map = fkey.parent; keytran.end = keytran.start -= first_unbound + 1; - keytran.map = Vkey_translation_map; + keytran.map = keytran.parent; goto replay_sequence; } @@ -8659,6 +8792,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, Vquit_flag = Qnil; if (EVENT_HAS_PARAMETERS (key) + /* Either a `switch-frame' or a `select-window' event. */ && EQ (EVENT_HEAD_KIND (EVENT_HEAD (key)), Qswitch_frame)) { /* If we're at the beginning of a key sequence, and the caller @@ -8999,6 +9133,27 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, xterm-mouse-mode. -stef Isn't this just the most wonderful code ever? */ + + /* If mock_input > t + 1, the above simplification + will actually end up dropping keys on the floor. + This is probably OK for now, but even + if mock_input <= t + 1, we need to adjust fkey + and keytran. + Typical case [header-line down-mouse-N]: + mock_input = 2, t = 1, fkey.end = 1, + last_real_key_start = 0. */ + if (fkey.end > last_real_key_start) + { + fkey.end = fkey.start + = min (last_real_key_start, fkey.start); + fkey.map = fkey.parent; + if (keytran.end > last_real_key_start) + { + keytran.end = keytran.start + = min (last_real_key_start, keytran.start); + keytran.map = keytran.parent; + } + } if (t == last_real_key_start) { mock_input = 0; @@ -9058,212 +9213,54 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, invariant that keytran.end <= fkey.start). */ { if (fkey.start < t) - (fkey.start = fkey.end = t, fkey.map = Vfunction_key_map); + (fkey.start = fkey.end = t, fkey.map = fkey.parent); } else /* If the sequence is unbound, see if we can hang a function key off the end of it. */ - { - Lisp_Object next; - - /* Continue scan from fkey.end until we find a bound suffix. - If we fail, increment fkey.start and start over from there. */ - while (fkey.end < t) - { - Lisp_Object key; - - key = keybuf[fkey.end++]; - next = access_keymap (fkey.map, key, 1, 0, 1); - - /* Handle symbol with autoload definition. */ - if (SYMBOLP (next) && ! NILP (Ffboundp (next)) - && CONSP (XSYMBOL (next)->function) - && EQ (XCAR (XSYMBOL (next)->function), Qautoload)) - do_autoload (XSYMBOL (next)->function, next); - - /* Handle a symbol whose function definition is a keymap - or an array. */ - if (SYMBOLP (next) && ! NILP (Ffboundp (next)) - && (!NILP (Farrayp (XSYMBOL (next)->function)) - || KEYMAPP (XSYMBOL (next)->function))) - next = XSYMBOL (next)->function; - -#if 0 /* I didn't turn this on, because it might cause trouble - for the mapping of return into C-m and tab into C-i. */ - /* Optionally don't map function keys into other things. - This enables the user to redefine kp- keys easily. */ - if (SYMBOLP (key) && !NILP (Vinhibit_function_key_mapping)) - next = Qnil; -#endif - - /* If the function key map gives a function, not an - array, then call the function with no args and use - its value instead. */ - if (SYMBOLP (next) && ! NILP (Ffboundp (next)) - /* If there's a binding (i.e. first_binding >= nmaps) - we don't want to apply this function-key-mapping. */ - && fkey.end == t && first_binding >= nmaps) - { - struct gcpro gcpro1, gcpro2, gcpro3; - Lisp_Object tem; - tem = next; - - GCPRO3 (fkey.map, keytran.map, delayed_switch_frame); - next = call1 (next, prompt); - UNGCPRO; - /* If the function returned something invalid, - barf--don't ignore it. - (To ignore it safely, we would need to gcpro a bunch of - other variables.) */ - if (! (VECTORP (next) || STRINGP (next))) - error ("Function in key-translation-map returns invalid key sequence"); - } - - /* If keybuf[fkey.start..fkey.end] is bound in the - function key map and it's a suffix of the current - sequence (i.e. fkey.end == t), replace it with - the binding and restart with fkey.start at the end. */ - if ((VECTORP (next) || STRINGP (next)) - /* If there's a binding (i.e. first_binding >= nmaps) - we don't want to apply this function-key-mapping. */ - && fkey.end == t && first_binding >= nmaps) - { - int len = XFASTINT (Flength (next)); - - t = fkey.start + len; - if (t >= bufsize) - error ("Key sequence too long"); - - if (VECTORP (next)) - bcopy (XVECTOR (next)->contents, - keybuf + fkey.start, - (t - fkey.start) * sizeof (keybuf[0])); - else if (STRINGP (next)) - { - int i; - - for (i = 0; i < len; i++) - XSETFASTINT (keybuf[fkey.start + i], SREF (next, i)); - } - - mock_input = t; - fkey.start = fkey.end = t; - fkey.map = Vfunction_key_map; - - /* Do pass the results through key-translation-map. - But don't retranslate what key-translation-map - has already translated. */ - keytran.end = keytran.start; - keytran.map = Vkey_translation_map; - - goto replay_sequence; - } - - fkey.map = get_keymap (next, 0, 1); - - /* If we no longer have a bound suffix, try a new positions for - fkey.start. */ - if (!CONSP (fkey.map)) - { - fkey.end = ++fkey.start; - fkey.map = Vfunction_key_map; - } - } - } - - /* Look for this sequence in key-translation-map. */ - { - Lisp_Object next; - - /* Scan from keytran.end until we find a bound suffix. */ - while (keytran.end < fkey.start) + /* Continue scan from fkey.end until we find a bound suffix. */ + while (fkey.end < t) { - Lisp_Object key; - - key = keybuf[keytran.end++]; - next = access_keymap (keytran.map, key, 1, 0, 1); - - /* Handle symbol with autoload definition. */ - if (SYMBOLP (next) && ! NILP (Ffboundp (next)) - && CONSP (XSYMBOL (next)->function) - && EQ (XCAR (XSYMBOL (next)->function), Qautoload)) - do_autoload (XSYMBOL (next)->function, next); - - /* Handle a symbol whose function definition is a keymap - or an array. */ - if (SYMBOLP (next) && ! NILP (Ffboundp (next)) - && (!NILP (Farrayp (XSYMBOL (next)->function)) - || KEYMAPP (XSYMBOL (next)->function))) - next = XSYMBOL (next)->function; - - /* If the key translation map gives a function, not an - array, then call the function with one arg and use - its value instead. */ - if (SYMBOLP (next) && ! NILP (Ffboundp (next))) - { - struct gcpro gcpro1, gcpro2, gcpro3; - Lisp_Object tem; - tem = next; - - GCPRO3 (fkey.map, keytran.map, delayed_switch_frame); - next = call1 (next, prompt); - UNGCPRO; - /* If the function returned something invalid, - barf--don't ignore it. - (To ignore it safely, we would need to gcpro a bunch of - other variables.) */ - if (! (VECTORP (next) || STRINGP (next))) - error ("Function in key-translation-map returns invalid key sequence"); - } - - /* If keybuf[keytran.start..keytran.end] is bound in the - key translation map and it's a suffix of the current - sequence (i.e. keytran.end == t), replace it with - the binding and restart with keytran.start at the end. */ - if ((VECTORP (next) || STRINGP (next))) + struct gcpro gcpro1, gcpro2, gcpro3; + int done, diff; + + GCPRO3 (fkey.map, keytran.map, delayed_switch_frame); + done = keyremap_step (keybuf, bufsize, &fkey, + max (t, mock_input), + /* If there's a binding (i.e. + first_binding >= nmaps) we don't want + to apply this function-key-mapping. */ + fkey.end + 1 == t && first_binding >= nmaps, + &diff, prompt); + UNGCPRO; + if (done) { - int len = XFASTINT (Flength (next)); - int i, diff = len - (keytran.end - keytran.start); - - mock_input = max (t, mock_input); - if (mock_input + diff >= bufsize) - error ("Key sequence too long"); - - /* Shift the keys that are after keytran.end. */ - if (diff < 0) - for (i = keytran.end; i < mock_input; i++) - keybuf[i + diff] = keybuf[i]; - else if (diff > 0) - for (i = mock_input - 1; i >= keytran.end; i--) - keybuf[i + diff] = keybuf[i]; - /* Replace the keys between keytran.start and keytran.end - with those from next. */ - for (i = 0; i < len; i++) - keybuf[keytran.start + i] - = Faref (next, make_number (i)); - - mock_input += diff; - keytran.start = keytran.end += diff; - keytran.map = Vkey_translation_map; - - /* Adjust the function-key-map counters. */ - fkey.start += diff; - fkey.end += diff; - + mock_input = diff + max (t, mock_input); goto replay_sequence; } + } - keytran.map = get_keymap (next, 0, 1); + /* Look for this sequence in key-translation-map. + Scan from keytran.end until we find a bound suffix. */ + while (keytran.end < fkey.start) + { + struct gcpro gcpro1, gcpro2, gcpro3; + int done, diff; - /* If we no longer have a bound suffix, try a new positions for - keytran.start. */ - if (!CONSP (keytran.map)) - { - keytran.end = ++keytran.start; - keytran.map = Vkey_translation_map; - } - } - } + GCPRO3 (fkey.map, keytran.map, delayed_switch_frame); + done = keyremap_step (keybuf, bufsize, &keytran, max (t, mock_input), + 1, &diff, prompt); + UNGCPRO; + if (done) + { + mock_input = diff + max (t, mock_input); + /* Adjust the function-key-map counters. */ + fkey.end += diff; + fkey.start += diff; + + goto replay_sequence; + } + } /* If KEY is not defined in any of the keymaps, and cannot be part of a function key or translation, @@ -10584,6 +10581,11 @@ init_keyboard () poll_suppress_count = 1; start_polling (); #endif + +#ifdef MAC_OSX + /* At least provide an escape route since C-g doesn't work. */ + signal (SIGINT, interrupt_signal); +#endif } /* This type's only use is in syms_of_keyboard, to initialize the @@ -10601,7 +10603,9 @@ struct event_head head_table[] = { {&Qdelete_frame, "delete-frame", &Qdelete_frame}, {&Qiconify_frame, "iconify-frame", &Qiconify_frame}, {&Qmake_frame_visible, "make-frame-visible", &Qmake_frame_visible}, - {&Qselect_window, "select-window", &Qselect_window} + /* `select-window' should be handled just like `switch-frame' + in read_key_sequence. */ + {&Qselect_window, "select-window", &Qswitch_frame} }; void @@ -11271,8 +11275,12 @@ keys_of_keyboard () "ignore-event"); initial_define_lispy_key (Vspecial_event_map, "make-frame-visible", "ignore-event"); - initial_define_lispy_key (Vspecial_event_map, "select-window", - "handle-select-window"); + /* Handling it at such a low-level causes read_key_sequence to get + * confused because it doesn't realize that the current_buffer was + * changed by read_char. + * + * initial_define_lispy_key (Vspecial_event_map, "select-window", + * "handle-select-window"); */ initial_define_lispy_key (Vspecial_event_map, "save-session", "handle-save-session"); }