Mercurial > emacs
changeset 45279:220c13a65624
(keymap_parent): New fun, extracted from Fkeymap_parent.
(Fkeymap_parent, keymap_memberp, fix_submap_inheritance): Use it.
(Fset_keymap_parent): Gcpro a bit more.
(access_keymap): Gcpro around meta_map call and around the main loop.
(get_keyelt): Gcpro when following indirect references.
(copy_keymap_item): New fun, extracted from Fcopy_keymap.
(copy_keymap_1, Fcopy_keymap): Use it. Don't copy the parent map.
(Fdefine_key, Flookup_key): Gcpro before calling get_keymap.
Remove useless ad-hoc remap code.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Tue, 14 May 2002 03:04:24 +0000 |
parents | 97b1e590eb61 |
children | 501be79c92f1 |
files | src/keymap.c |
diffstat | 1 files changed, 157 insertions(+), 174 deletions(-) [+] |
line wrap: on
line diff
--- a/src/keymap.c Mon May 13 20:35:30 2002 +0000 +++ b/src/keymap.c Tue May 14 03:04:24 2002 +0000 @@ -273,11 +273,11 @@ if (autoload) { struct gcpro gcpro1, gcpro2; - + GCPRO2 (tem, object); do_autoload (tem, object); UNGCPRO; - + goto autoload_retry; } else @@ -292,17 +292,17 @@ return Qnil; } -/* Return the parent map of the keymap MAP, or nil if it has none. - We assume that MAP is a valid keymap. */ - -DEFUN ("keymap-parent", Fkeymap_parent, Skeymap_parent, 1, 1, 0, - doc: /* Return the parent keymap of KEYMAP. */) - (keymap) +/* Return the parent map of KEYMAP, or nil if it has none. + We assume that KEYMAP is a valid keymap. */ + +Lisp_Object +keymap_parent (keymap, autoload) Lisp_Object keymap; + int autoload; { Lisp_Object list; - keymap = get_keymap (keymap, 1, 1); + keymap = get_keymap (keymap, 1, autoload); /* Skip past the initial element `keymap'. */ list = XCDR (keymap); @@ -313,9 +313,16 @@ return list; } - return get_keymap (list, 0, 1); + return get_keymap (list, 0, autoload); } +DEFUN ("keymap-parent", Fkeymap_parent, Skeymap_parent, 1, 1, 0, + doc: /* Return the parent keymap of KEYMAP. */) + (keymap) + Lisp_Object keymap; +{ + return keymap_parent (keymap, 1); +} /* Check whether MAP is one of MAPS parents. */ int @@ -324,7 +331,7 @@ { if (NILP (map)) return 0; while (KEYMAPP (maps) && !EQ (map, maps)) - maps = Fkeymap_parent (maps); + maps = keymap_parent (maps, 0); return (EQ (map, maps)); } @@ -337,7 +344,7 @@ Lisp_Object keymap, parent; { Lisp_Object list, prev; - struct gcpro gcpro1; + struct gcpro gcpro1, gcpro2; int i; /* Force a keymap flush for the next call to where-is. @@ -349,9 +356,9 @@ This is a very minor correctness (rather than safety) issue. */ where_is_cache_keymaps = Qt; + GCPRO2 (keymap, parent); keymap = get_keymap (keymap, 1, 1); - GCPRO1 (keymap); - + if (!NILP (parent)) { parent = get_keymap (parent, 1, 1); @@ -432,7 +439,7 @@ if (!CONSP (submap)) return; - map_parent = Fkeymap_parent (map); + map_parent = keymap_parent (map, 0); if (!NILP (map_parent)) parent_entry = get_keymap (access_keymap (map_parent, event, 0, 0, 0), 0, 0); @@ -452,7 +459,7 @@ { Lisp_Object tem; - tem = Fkeymap_parent (submap_parent); + tem = keymap_parent (submap_parent, 0); if (KEYMAPP (tem)) { @@ -512,10 +519,13 @@ { /* See if there is a meta-map. If there's none, there is no binding for IDX, unless a default binding exists in MAP. */ - Lisp_Object meta_map = - get_keymap (access_keymap (map, meta_prefix_char, - t_ok, noinherit, autoload), - 0, autoload); + struct gcpro gcpro1; + Lisp_Object meta_map; + GCPRO1 (map); + meta_map = get_keymap (access_keymap (map, meta_prefix_char, + t_ok, noinherit, autoload), + 0, autoload); + UNGCPRO; if (CONSP (meta_map)) { map = meta_map; @@ -529,15 +539,15 @@ return Qnil; } + /* t_binding is where we put a default binding that applies, + to use in case we do not find a binding specifically + for this key sequence. */ { Lisp_Object tail; - - /* t_binding is where we put a default binding that applies, - to use in case we do not find a binding specifically - for this key sequence. */ - - Lisp_Object t_binding; - t_binding = Qnil; + Lisp_Object t_binding = Qnil; + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; + + GCPRO4 (map, tail, idx, t_binding); /* If `t_ok' is 2, both `t' and generic-char bindings are accepted. If it is 1, only generic-char bindings are accepted. @@ -557,7 +567,7 @@ /* If NOINHERIT, stop finding prefix definitions after we pass a second occurrence of the `keymap' symbol. */ if (noinherit && EQ (binding, Qkeymap)) - return Qnil; + RETURN_UNGCPRO (Qnil); } else if (CONSP (binding)) { @@ -621,11 +631,11 @@ val = get_keyelt (val, autoload); if (KEYMAPP (val)) fix_submap_inheritance (map, idx, val); - return val; + RETURN_UNGCPRO (val); } QUIT; } - + UNGCPRO; return get_keyelt (t_binding, autoload); } } @@ -644,7 +654,7 @@ Lisp_Object get_keyelt (object, autoload) - register Lisp_Object object; + Lisp_Object object; int autoload; { while (1) @@ -686,7 +696,7 @@ } } else - /* Invalid keymap */ + /* Invalid keymap. */ return object; } @@ -713,8 +723,11 @@ /* If the contents are (KEYMAP . ELEMENT), go indirect. */ else { + struct gcpro gcpro1; Lisp_Object map; + GCPRO1 (object); map = get_keymap (Fcar_safe (object), 0, autoload); + UNGCPRO; return (!CONSP (map) ? object /* Invalid keymap */ : access_keymap (map, Fcdr (object), 0, 0, autoload)); } @@ -821,18 +834,91 @@ XSETCDR (insertion_point, Fcons (Fcons (idx, def), XCDR (insertion_point))); } - + return def; } EXFUN (Fcopy_keymap, 1); +Lisp_Object +copy_keymap_item (elt) + Lisp_Object elt; +{ + Lisp_Object res, tem; + + if (!CONSP (elt)) + return elt; + + res = tem = elt; + + /* Is this a new format menu item. */ + if (EQ (XCAR (tem), Qmenu_item)) + { + /* Copy cell with menu-item marker. */ + res = elt = Fcons (XCAR (tem), XCDR (tem)); + tem = XCDR (elt); + if (CONSP (tem)) + { + /* Copy cell with menu-item name. */ + XSETCDR (elt, Fcons (XCAR (tem), XCDR (tem))); + elt = XCDR (elt); + tem = XCDR (elt); + } + if (CONSP (tem)) + { + /* Copy cell with binding and if the binding is a keymap, + copy that. */ + XSETCDR (elt, Fcons (XCAR (tem), XCDR (tem))); + elt = XCDR (elt); + tem = XCAR (elt); + if (CONSP (tem) && EQ (XCAR (tem), Qkeymap)) + XSETCAR (elt, Fcopy_keymap (tem)); + tem = XCDR (elt); + if (CONSP (tem) && CONSP (XCAR (tem))) + /* Delete cache for key equivalences. */ + XSETCDR (elt, XCDR (tem)); + } + } + else + { + /* It may be an old fomat menu item. + Skip the optional menu string. */ + if (STRINGP (XCAR (tem))) + { + /* Copy the cell, since copy-alist didn't go this deep. */ + res = elt = Fcons (XCAR (tem), XCDR (tem)); + tem = XCDR (elt); + /* Also skip the optional menu help string. */ + if (CONSP (tem) && STRINGP (XCAR (tem))) + { + XSETCDR (elt, Fcons (XCAR (tem), XCDR (tem))); + elt = XCDR (elt); + tem = XCDR (elt); + } + /* There may also be a list that caches key equivalences. + Just delete it for the new keymap. */ + if (CONSP (tem) + && CONSP (XCAR (tem)) + && (NILP (XCAR (XCAR (tem))) + || VECTORP (XCAR (XCAR (tem))))) + { + XSETCDR (elt, XCDR (tem)); + tem = XCDR (tem); + } + if (CONSP (tem) && EQ (XCAR (tem), Qkeymap)) + XSETCDR (elt, Fcopy_keymap (tem)); + } + else if (EQ (XCAR (tem), Qkeymap)) + res = Fcopy_keymap (elt); + } + return res; +} + void copy_keymap_1 (chartable, idx, elt) Lisp_Object chartable, idx, elt; { - if (CONSP (elt) && EQ (XCAR (elt), Qkeymap)) - Faset (chartable, idx, Fcopy_keymap (elt)); + Faset (chartable, idx, copy_keymap_item (elt)); } DEFUN ("copy-keymap", Fcopy_keymap, Scopy_keymap, 1, 1, 0, @@ -845,112 +931,34 @@ (keymap) Lisp_Object keymap; { - /* FIXME: This doesn't properly copy menu-items in vectors. */ - /* FIXME: This also copies the parent keymap. */ - register Lisp_Object copy, tail; - - copy = Fcopy_alist (get_keymap (keymap, 1, 0)); - - for (tail = copy; CONSP (tail); tail = XCDR (tail)) + keymap = get_keymap (keymap, 1, 0); + copy = tail = Fcons (Qkeymap, Qnil); + keymap = XCDR (keymap); /* Skip the `keymap' symbol. */ + + while (CONSP (keymap) && !EQ (XCAR (keymap), Qkeymap)) { - Lisp_Object elt; - - elt = XCAR (tail); + Lisp_Object elt = XCAR (keymap); if (CHAR_TABLE_P (elt)) { Lisp_Object indices[3]; - elt = Fcopy_sequence (elt); - XSETCAR (tail, elt); - map_char_table (copy_keymap_1, Qnil, elt, elt, 0, indices); } else if (VECTORP (elt)) { int i; - elt = Fcopy_sequence (elt); - XSETCAR (tail, elt); - for (i = 0; i < ASIZE (elt); i++) - if (CONSP (AREF (elt, i)) && EQ (XCAR (AREF (elt, i)), Qkeymap)) - ASET (elt, i, Fcopy_keymap (AREF (elt, i))); + ASET (elt, i, copy_keymap_item (AREF (elt, i))); } - else if (CONSP (elt) && CONSP (XCDR (elt))) - { - Lisp_Object tem; - tem = XCDR (elt); - - /* Is this a new format menu item. */ - if (EQ (XCAR (tem),Qmenu_item)) - { - /* Copy cell with menu-item marker. */ - XSETCDR (elt, - Fcons (XCAR (tem), XCDR (tem))); - elt = XCDR (elt); - tem = XCDR (elt); - if (CONSP (tem)) - { - /* Copy cell with menu-item name. */ - XSETCDR (elt, - Fcons (XCAR (tem), XCDR (tem))); - elt = XCDR (elt); - tem = XCDR (elt); - }; - if (CONSP (tem)) - { - /* Copy cell with binding and if the binding is a keymap, - copy that. */ - XSETCDR (elt, - Fcons (XCAR (tem), XCDR (tem))); - elt = XCDR (elt); - tem = XCAR (elt); - if (CONSP (tem) && EQ (XCAR (tem), Qkeymap)) - XSETCAR (elt, Fcopy_keymap (tem)); - tem = XCDR (elt); - if (CONSP (tem) && CONSP (XCAR (tem))) - /* Delete cache for key equivalences. */ - XSETCDR (elt, XCDR (tem)); - } - } - else - { - /* It may be an old fomat menu item. - Skip the optional menu string. - */ - if (STRINGP (XCAR (tem))) - { - /* Copy the cell, since copy-alist didn't go this deep. */ - XSETCDR (elt, - Fcons (XCAR (tem), XCDR (tem))); - elt = XCDR (elt); - tem = XCDR (elt); - /* Also skip the optional menu help string. */ - if (CONSP (tem) && STRINGP (XCAR (tem))) - { - XSETCDR (elt, - Fcons (XCAR (tem), XCDR (tem))); - elt = XCDR (elt); - tem = XCDR (elt); - } - /* There may also be a list that caches key equivalences. - Just delete it for the new keymap. */ - if (CONSP (tem) - && CONSP (XCAR (tem)) - && (NILP (XCAR (XCAR (tem))) - || VECTORP (XCAR (XCAR (tem))))) - XSETCDR (elt, XCDR (tem)); - } - if (CONSP (elt) - && CONSP (XCDR (elt)) - && EQ (XCAR (XCDR (elt)), Qkeymap)) - XSETCDR (elt, Fcopy_keymap (XCDR (elt))); - } - - } + else if (CONSP (elt)) + elt = Fcons (XCAR (elt), copy_keymap_item (XCDR (elt))); + XSETCDR (tail, Fcons (elt, Qnil)); + tail = XCDR (tail); + keymap = XCDR (keymap); } - + XSETCDR (tail, keymap); return copy; } @@ -993,29 +1001,20 @@ int length; struct gcpro gcpro1, gcpro2, gcpro3; + GCPRO3 (keymap, key, def); keymap = get_keymap (keymap, 1, 1); if (!VECTORP (key) && !STRINGP (key)) - key = wrong_type_argument (Qarrayp, key); + key = wrong_type_argument (Qarrayp, key); length = XFASTINT (Flength (key)); if (length == 0) - return Qnil; - - /* Check for valid [remap COMMAND] bindings. */ - if (VECTORP (key) && EQ (AREF (key, 0), Qremap) - && (length != 2 || !SYMBOLP (AREF (key, 1)))) - wrong_type_argument (Qvectorp, key); + RETURN_UNGCPRO (Qnil); if (SYMBOLP (def) && !EQ (Vdefine_key_rebound_commands, Qt)) Vdefine_key_rebound_commands = Fcons (def, Vdefine_key_rebound_commands); - GCPRO3 (keymap, key, def); - - if (VECTORP (key)) - meta_bit = meta_modifier; - else - meta_bit = 0x80; + meta_bit = VECTORP (key) ? meta_modifier : 0x80; idx = 0; while (1) @@ -1073,7 +1072,6 @@ (command) Lisp_Object command; { - /* This will GCPRO the command argument. */ ASET (remap_command_vector, 1, command); return Fkey_binding (remap_command_vector, Qnil, Qt); } @@ -1097,7 +1095,7 @@ third optional argument ACCEPT-DEFAULT is non-nil, `lookup-key' will recognize the default bindings, just as `read-key-sequence' does. */) (keymap, key, accept_default) - register Lisp_Object keymap; + Lisp_Object keymap; Lisp_Object key; Lisp_Object accept_default; { @@ -1106,32 +1104,17 @@ register Lisp_Object c; int length; int t_ok = !NILP (accept_default); - struct gcpro gcpro1; - + struct gcpro gcpro1, gcpro2; + + GCPRO2 (keymap, key); keymap = get_keymap (keymap, 1, 1); - /* Perform command remapping initiated by Fremap_command directly. - This is strictly not necessary, but it is faster and it returns - nil instead of 1 if KEYMAP doesn't contain command remappings. */ - if (EQ (key, remap_command_vector)) - { - /* KEY has format [remap COMMAND]. - Lookup `remap' in KEYMAP; result is nil or a keymap containing - command remappings. Then lookup COMMAND in that keymap. */ - if ((keymap = access_keymap (keymap, Qremap, t_ok, 0, 1), !NILP (keymap)) - && (keymap = get_keymap (keymap, 0, 1), CONSP (keymap))) - return access_keymap (keymap, AREF (key, 1), t_ok, 0, 1); - return Qnil; - } - if (!VECTORP (key) && !STRINGP (key)) key = wrong_type_argument (Qarrayp, key); length = XFASTINT (Flength (key)); if (length == 0) - return keymap; - - GCPRO1 (key); + RETURN_UNGCPRO (keymap); idx = 0; while (1) @@ -1413,7 +1396,7 @@ if (!NILP (local)) keymaps = Fcons (local, keymaps); } - + return keymaps; } @@ -1692,9 +1675,9 @@ int meta_bit = meta_modifier; Lisp_Object last = make_number (XINT (Flength (thisseq)) - 1); tem = Fcopy_sequence (thisseq); - + Faset (tem, last, make_number (XINT (key) | meta_bit)); - + /* This new sequence is the same length as thisseq, so stick it in the list right after this one. */ @@ -1830,13 +1813,13 @@ for (i = 0; i < ASIZE (elt); i++) accessible_keymaps_1 (make_number (i), AREF (elt, i), maps, tail, thisseq, is_metized); - + } else if (CONSP (elt)) accessible_keymaps_1 (XCAR (elt), XCDR (elt), maps, tail, thisseq, is_metized && INTEGERP (XCAR (elt))); - + } } @@ -1954,7 +1937,7 @@ int force_multibyte; { unsigned c2; - + /* Clear all the meaningless bits above the meta bit. */ c &= meta_modifier | ~ - meta_modifier; c2 = c & ~(alt_modifier | ctrl_modifier | hyper_modifier @@ -2048,7 +2031,7 @@ else { int valid_p = SINGLE_BYTE_CHAR_P (c) || char_valid_p (c, 0); - + if (force_multibyte && valid_p) { if (SINGLE_BYTE_CHAR_P (c)) @@ -2281,7 +2264,7 @@ Faccessible_keymaps (get_keymap (XCAR (found), 1, 0), Qnil)); found = XCDR (found); } - + GCPRO5 (definition, keymaps, maps, found, sequences); found = Qnil; sequences = Qnil; @@ -2310,7 +2293,7 @@ keymaps bound to `menu-bar' and `tool-bar' and other non-ascii prefixes like `C-down-mouse-2'. */ continue; - + QUIT; while (CONSP (map)) @@ -2455,7 +2438,7 @@ return the best we could find. */ if (!NILP (firstonly)) return Fcar (found); - + return found; } @@ -2514,7 +2497,7 @@ Lisp_Object args[2]; where_is_cache = Fmake_hash_table (0, args); where_is_cache_keymaps = Qt; - + /* Fill in the cache. */ GCPRO5 (definition, keymaps, firstonly, noindirect, no_remap); where_is_internal (definition, keymaps, firstonly, noindirect, no_remap); @@ -2531,7 +2514,7 @@ defns = (Lisp_Object *) alloca (n * sizeof *defns); for (i = 0; CONSP (sequences); sequences = XCDR (sequences)) defns[i++] = XCAR (sequences); - + /* Verify that the key bindings are not shadowed. Note that the following can GC. */ GCPRO2 (definition, keymaps); @@ -3315,7 +3298,7 @@ if (!NILP (shadow) && complete_char) { Lisp_Object tem; - + ASET (kludge, 0, make_number (character)); tem = shadow_lookup (shadow, kludge, Qt); @@ -3425,7 +3408,7 @@ !NILP (tem2)) && !NILP (Fequal (tem2, definition))) i++; - + /* If we have a range of more than one character, print where the range reaches to. */