diff options
| author | Jim Blandy | 1992-09-23 12:46:52 +0000 |
|---|---|---|
| committer | Jim Blandy | 1992-09-23 12:46:52 +0000 |
| commit | f5b79c1c36da2b7d5b61920a074798a6a542b613 (patch) | |
| tree | c2eb2608fecc96bcfe2afda579a814f204dff5f1 /src | |
| parent | 230a4cbd80a0423b12177a568f523da4acb70ada (diff) | |
| download | emacs-f5b79c1c36da2b7d5b61920a074798a6a542b613.tar.gz emacs-f5b79c1c36da2b7d5b61920a074798a6a542b613.zip | |
* keymap.c (DENSE_TABLE_SIZE): Doc fix.
(keymap_table): Function removed; this function exists only to
support an incorrect understanding of the format of keymaps.
(access_keymap, store_in_keymap, Fcopy_keymap,
Faccessible_keymaps): Correctly handle vectors at any point in the
keymap; don't assume it must be at the front.
(describe_map): Instead of calling describe_vector on the vector
in the cadr of the keymap (if present) and then calling
describe_alist to do the rest, just call describe_map_2.
(describe_alist): Renamed to describe_map_2; call describe_vector
when we encounter a vector in the list.
* keymap.c (access_keymap, store_in_keymap): Clarify error message
for non-ASCII characters.
* keymap.c (access_keymap): Return the binding of Qt as the
binding for all unbound characters.
Diffstat (limited to 'src')
| -rw-r--r-- | src/keymap.c | 418 |
1 files changed, 204 insertions, 214 deletions
diff --git a/src/keymap.c b/src/keymap.c index 21176546bec..373528655ba 100644 --- a/src/keymap.c +++ b/src/keymap.c | |||
| @@ -28,9 +28,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 28 | 28 | ||
| 29 | #define min(a, b) ((a) < (b) ? (a) : (b)) | 29 | #define min(a, b) ((a) < (b) ? (a) : (b)) |
| 30 | 30 | ||
| 31 | /* Dense keymaps look like (keymap VECTOR . ALIST), where VECTOR is a | 31 | /* The number of elements in keymap vectors. */ |
| 32 | 128-element vector used to look up bindings for ASCII characters, | ||
| 33 | and ALIST is an assoc list for looking up symbols. */ | ||
| 34 | #define DENSE_TABLE_SIZE (0200) | 32 | #define DENSE_TABLE_SIZE (0200) |
| 35 | 33 | ||
| 36 | /* Actually allocate storage for these variables */ | 34 | /* Actually allocate storage for these variables */ |
| @@ -84,7 +82,7 @@ void describe_map_tree (); | |||
| 84 | static Lisp_Object describe_buffer_bindings (); | 82 | static Lisp_Object describe_buffer_bindings (); |
| 85 | static void describe_command (); | 83 | static void describe_command (); |
| 86 | static void describe_map (); | 84 | static void describe_map (); |
| 87 | static void describe_alist (); | 85 | static void describe_map_2 (); |
| 88 | 86 | ||
| 89 | /* Keymap object support - constructors and predicates. */ | 87 | /* Keymap object support - constructors and predicates. */ |
| 90 | 88 | ||
| @@ -190,6 +188,7 @@ get_keymap_1 (object, error) | |||
| 190 | tem = indirect_function (object); | 188 | tem = indirect_function (object); |
| 191 | if (CONSP (tem) && EQ (XCONS (tem)->car, Qkeymap)) | 189 | if (CONSP (tem) && EQ (XCONS (tem)->car, Qkeymap)) |
| 192 | return tem; | 190 | return tem; |
| 191 | |||
| 193 | if (error) | 192 | if (error) |
| 194 | wrong_type_argument (Qkeymapp, object); | 193 | wrong_type_argument (Qkeymapp, object); |
| 195 | else | 194 | else |
| @@ -204,27 +203,12 @@ get_keymap (object) | |||
| 204 | } | 203 | } |
| 205 | 204 | ||
| 206 | 205 | ||
| 207 | /* If KEYMAP is a dense keymap, return the vector from its cadr. | ||
| 208 | Otherwise, return nil. */ | ||
| 209 | |||
| 210 | Lisp_Object | ||
| 211 | keymap_table (keymap) | ||
| 212 | Lisp_Object keymap; | ||
| 213 | { | ||
| 214 | Lisp_Object cadr; | ||
| 215 | |||
| 216 | if (CONSP (XCONS (keymap)->cdr) | ||
| 217 | && XTYPE (cadr = XCONS (XCONS (keymap)->cdr)->car) == Lisp_Vector | ||
| 218 | && XVECTOR (cadr)->size == DENSE_TABLE_SIZE) | ||
| 219 | return cadr; | ||
| 220 | else | ||
| 221 | return Qnil; | ||
| 222 | } | ||
| 223 | |||
| 224 | |||
| 225 | /* Look up IDX in MAP. IDX may be any sort of event. | 206 | /* Look up IDX in MAP. IDX may be any sort of event. |
| 226 | Note that this does only one level of lookup; IDX must | 207 | |
| 227 | be a single event, not a sequence. */ | 208 | Note that this does only one level of lookup; IDX must be a single |
| 209 | event, not a sequence. If IDX is unbound in MAP but MAP has a | ||
| 210 | binding for Qt, then Qt's binding is returned; this makes bindings | ||
| 211 | of Qt act like "default" bindings. */ | ||
| 228 | 212 | ||
| 229 | Lisp_Object | 213 | Lisp_Object |
| 230 | access_keymap (map, idx) | 214 | access_keymap (map, idx) |
| @@ -239,26 +223,39 @@ access_keymap (map, idx) | |||
| 239 | 223 | ||
| 240 | if (XTYPE (idx) == Lisp_Int | 224 | if (XTYPE (idx) == Lisp_Int |
| 241 | && (XINT (idx) < 0 || XINT (idx) >= DENSE_TABLE_SIZE)) | 225 | && (XINT (idx) < 0 || XINT (idx) >= DENSE_TABLE_SIZE)) |
| 242 | error ("Command key is not an ASCII character"); | 226 | error ("only ASCII characters may used as keymap indices"); |
| 243 | 227 | ||
| 244 | { | 228 | /* If idx is a symbol, it might have modifiers, which need to |
| 245 | Lisp_Object table = keymap_table (map); | 229 | be put in the canonical order. */ |
| 230 | else if (XTYPE (idx) == Lisp_Symbol) | ||
| 231 | idx = reorder_modifiers (idx); | ||
| 246 | 232 | ||
| 247 | /* A dense keymap indexed by a character? */ | 233 | { |
| 248 | if (XTYPE (idx) == Lisp_Int | 234 | Lisp_Object tail; |
| 249 | && ! NILP (table)) | 235 | Lisp_Object t_binding = Qnil; |
| 250 | return XVECTOR (table)->contents[XFASTINT (idx)]; | ||
| 251 | 236 | ||
| 252 | /* This lookup will not involve a vector reference. */ | 237 | for (tail = map; CONSP (tail); tail = XCONS (tail)->cdr) |
| 253 | else | ||
| 254 | { | 238 | { |
| 255 | /* If idx is a symbol, it might have modifiers, which need to | 239 | Lisp_Object binding = XCONS (tail)->car; |
| 256 | be put in the canonical order. */ | 240 | |
| 257 | if (XTYPE (idx) == Lisp_Symbol) | 241 | switch (XTYPE (binding)) |
| 258 | idx = reorder_modifiers (idx); | 242 | { |
| 259 | 243 | case Lisp_Cons: | |
| 260 | return Fcdr (Fassq (idx, map)); | 244 | if (EQ (XCONS (binding)->car, idx)) |
| 245 | return XCONS (binding)->cdr; | ||
| 246 | if (EQ (XCONS (binding)->car, Qt)) | ||
| 247 | t_binding = XCONS (binding)->cdr; | ||
| 248 | break; | ||
| 249 | |||
| 250 | case Lisp_Vector: | ||
| 251 | if (XVECTOR (binding)->size == DENSE_TABLE_SIZE | ||
| 252 | && XTYPE (idx) == Lisp_Int) | ||
| 253 | return XVECTOR (binding)->contents[XINT (idx)]; | ||
| 254 | break; | ||
| 255 | } | ||
| 261 | } | 256 | } |
| 257 | |||
| 258 | return t_binding; | ||
| 262 | } | 259 | } |
| 263 | } | 260 | } |
| 264 | 261 | ||
| @@ -313,6 +310,10 @@ store_in_keymap (keymap, idx, def) | |||
| 313 | register Lisp_Object idx; | 310 | register Lisp_Object idx; |
| 314 | register Lisp_Object def; | 311 | register Lisp_Object def; |
| 315 | { | 312 | { |
| 313 | if (XTYPE (keymap) != Lisp_Cons | ||
| 314 | || ! EQ (XCONS (keymap)->car, Qkeymap)) | ||
| 315 | error ("attempt to define a key in a non-keymap"); | ||
| 316 | |||
| 316 | /* If idx is a list (some sort of mouse click, perhaps?), | 317 | /* If idx is a list (some sort of mouse click, perhaps?), |
| 317 | the index we want to use is the car of the list, which | 318 | the index we want to use is the car of the list, which |
| 318 | ought to be a symbol. */ | 319 | ought to be a symbol. */ |
| @@ -321,44 +322,71 @@ store_in_keymap (keymap, idx, def) | |||
| 321 | 322 | ||
| 322 | if (XTYPE (idx) == Lisp_Int | 323 | if (XTYPE (idx) == Lisp_Int |
| 323 | && (XINT (idx) < 0 || XINT (idx) >= DENSE_TABLE_SIZE)) | 324 | && (XINT (idx) < 0 || XINT (idx) >= DENSE_TABLE_SIZE)) |
| 324 | error ("Command key is a character outside of the ASCII set."); | 325 | error ("only ASCII characters may be used as keymap indices"); |
| 325 | 326 | ||
| 327 | /* If idx is a symbol, it might have modifiers, which need to | ||
| 328 | be put in the canonical order. */ | ||
| 329 | else if (XTYPE (idx) == Lisp_Symbol) | ||
| 330 | idx = reorder_modifiers (idx); | ||
| 331 | |||
| 332 | |||
| 333 | /* Scan the keymap for a binding of idx. */ | ||
| 326 | { | 334 | { |
| 327 | Lisp_Object table = keymap_table (keymap); | 335 | Lisp_Object tail; |
| 328 | 336 | ||
| 329 | /* A dense keymap indexed by a character? */ | 337 | /* The cons after which we should insert new bindings. If the |
| 330 | if (XTYPE (idx) == Lisp_Int && !NILP (table)) | 338 | keymap has a table element, we record its position here, so new |
| 331 | XVECTOR (table)->contents[XFASTINT (idx)] = def; | 339 | bindings will go after it; this way, the table will stay |
| 340 | towards the front of the alist and character lookups in dense | ||
| 341 | keymaps will remain fast. Otherwise, this just points at the | ||
| 342 | front of the keymap. */ | ||
| 343 | Lisp_Object insertion_point = keymap; | ||
| 332 | 344 | ||
| 333 | /* Must be a sparse keymap, or a dense keymap indexed by a symbol. */ | 345 | for (tail = XCONS (keymap)->cdr; CONSP (tail); tail = XCONS (tail)->cdr) |
| 334 | else | ||
| 335 | { | 346 | { |
| 336 | /* Point to the pointer to the start of the assoc-list part | 347 | Lisp_Object elt = XCONS (tail)->car; |
| 337 | of the keymap. */ | 348 | |
| 338 | register Lisp_Object *assoc_head | 349 | switch (XTYPE (elt)) |
| 339 | = (NILP (table) | 350 | { |
| 340 | ? & XCONS (keymap)->cdr | 351 | case Lisp_Vector: |
| 341 | : & XCONS (XCONS (keymap)->cdr)->cdr); | 352 | if (XTYPE (idx) == Lisp_Int) |
| 342 | register Lisp_Object defining_pair; | 353 | { |
| 343 | 354 | XVECTOR (elt)->contents[XFASTINT (idx)] = def; | |
| 344 | /* If idx is a symbol, it might have modifiers, which need to | 355 | return def; |
| 345 | be put in the canonical order. */ | 356 | } |
| 346 | if (XTYPE (idx) == Lisp_Symbol) | 357 | insertion_point = tail; |
| 347 | idx = reorder_modifiers (idx); | 358 | break; |
| 348 | 359 | ||
| 349 | /* Point to the pair where idx is bound, if any. */ | 360 | case Lisp_Cons: |
| 350 | defining_pair = Fassq (idx, *assoc_head); | 361 | if (EQ (idx, XCONS (elt)->car)) |
| 351 | 362 | { | |
| 352 | if (NILP (defining_pair)) | 363 | XCONS (elt)->cdr = def; |
| 353 | *assoc_head = Fcons (Fcons (idx, def), *assoc_head); | 364 | return def; |
| 354 | else | 365 | } |
| 355 | Fsetcdr (defining_pair, def); | 366 | break; |
| 367 | |||
| 368 | case Lisp_Symbol: | ||
| 369 | /* If we find a 'keymap' symbol in the spine of KEYMAP, | ||
| 370 | then we must have found the start of a second keymap | ||
| 371 | being used as the tail of KEYMAP, and a binding for IDX | ||
| 372 | should be inserted before it. */ | ||
| 373 | if (EQ (elt, Qkeymap)) | ||
| 374 | goto keymap_end; | ||
| 375 | break; | ||
| 376 | } | ||
| 356 | } | 377 | } |
| 357 | } | ||
| 358 | 378 | ||
| 379 | keymap_end: | ||
| 380 | /* We have scanned the entire keymap, and not found a binding for | ||
| 381 | IDX. Let's add one. */ | ||
| 382 | XCONS (insertion_point)->cdr = | ||
| 383 | Fcons (Fcons (idx, def), XCONS (insertion_point)->cdr); | ||
| 384 | } | ||
| 385 | |||
| 359 | return def; | 386 | return def; |
| 360 | } | 387 | } |
| 361 | 388 | ||
| 389 | |||
| 362 | DEFUN ("copy-keymap", Fcopy_keymap, Scopy_keymap, 1, 1, 0, | 390 | DEFUN ("copy-keymap", Fcopy_keymap, Scopy_keymap, 1, 1, 0, |
| 363 | "Return a copy of the keymap KEYMAP.\n\ | 391 | "Return a copy of the keymap KEYMAP.\n\ |
| 364 | The copy starts out with the same definitions of KEYMAP,\n\ | 392 | The copy starts out with the same definitions of KEYMAP,\n\ |
| @@ -372,43 +400,29 @@ is not copied.") | |||
| 372 | register Lisp_Object copy, tail; | 400 | register Lisp_Object copy, tail; |
| 373 | 401 | ||
| 374 | copy = Fcopy_alist (get_keymap (keymap)); | 402 | copy = Fcopy_alist (get_keymap (keymap)); |
| 375 | tail = XCONS (copy)->cdr; | ||
| 376 | 403 | ||
| 377 | /* If this is a dense keymap, copy the vector. */ | 404 | for (tail = copy; CONSP (tail); tail = XCONS (tail)->cdr) |
| 378 | if (CONSP (tail)) | ||
| 379 | { | 405 | { |
| 380 | register Lisp_Object table = XCONS (tail)->car; | 406 | Lisp_Object elt = XCONS (tail)->car; |
| 381 | 407 | ||
| 382 | if (XTYPE (table) == Lisp_Vector | 408 | if (XTYPE (elt) == Lisp_Vector |
| 383 | && XVECTOR (table)->size == DENSE_TABLE_SIZE) | 409 | && XVECTOR (elt)->size == DENSE_TABLE_SIZE) |
| 384 | { | 410 | { |
| 385 | register int i; | 411 | int i; |
| 386 | 412 | ||
| 387 | table = Fcopy_sequence (table); | 413 | elt = Fcopy_sequence (elt); |
| 414 | XCONS (tail)->car = elt; | ||
| 388 | 415 | ||
| 389 | for (i = 0; i < DENSE_TABLE_SIZE; i++) | 416 | for (i = 0; i < DENSE_TABLE_SIZE; i++) |
| 390 | if (XTYPE (XVECTOR (copy)->contents[i]) != Lisp_Symbol) | 417 | if (XTYPE (XVECTOR (elt)->contents[i]) != Lisp_Symbol |
| 391 | if (! NILP (Fkeymapp (XVECTOR (table)->contents[i]))) | 418 | && Fkeymapp (XVECTOR (elt)->contents[i])) |
| 392 | XVECTOR (table)->contents[i] | 419 | XVECTOR (elt)->contents[i] = |
| 393 | = Fcopy_keymap (XVECTOR (table)->contents[i]); | 420 | Fcopy_keymap (XVECTOR (elt)->contents[i]); |
| 394 | XCONS (tail)->car = table; | ||
| 395 | |||
| 396 | tail = XCONS (tail)->cdr; | ||
| 397 | } | 421 | } |
| 398 | } | 422 | else if (CONSP (elt) |
| 399 | 423 | && XTYPE (XCONS (elt)->cdr) != Lisp_Symbol | |
| 400 | /* Copy the alist portion of the keymap. */ | 424 | && ! NILP (Fkeymapp (XCONS (elt)->cdr))) |
| 401 | while (CONSP (tail)) | ||
| 402 | { | ||
| 403 | register Lisp_Object elt; | ||
| 404 | |||
| 405 | elt = XCONS (tail)->car; | ||
| 406 | if (CONSP (elt) | ||
| 407 | && XTYPE (XCONS (elt)->cdr) != Lisp_Symbol | ||
| 408 | && ! NILP (Fkeymapp (XCONS (elt)->cdr))) | ||
| 409 | XCONS (elt)->cdr = Fcopy_keymap (XCONS (elt)->cdr); | 425 | XCONS (elt)->cdr = Fcopy_keymap (XCONS (elt)->cdr); |
| 410 | |||
| 411 | tail = XCONS (tail)->cdr; | ||
| 412 | } | 426 | } |
| 413 | 427 | ||
| 414 | return copy; | 428 | return copy; |
| @@ -897,7 +911,6 @@ so that the KEYS increase in length. The first element is (\"\" . KEYMAP).") | |||
| 897 | Lisp_Object maps, tail; | 911 | Lisp_Object maps, tail; |
| 898 | 912 | ||
| 899 | maps = Fcons (Fcons (build_string (""), get_keymap (startmap)), Qnil); | 913 | maps = Fcons (Fcons (build_string (""), get_keymap (startmap)), Qnil); |
| 900 | tail = maps; | ||
| 901 | 914 | ||
| 902 | /* For each map in the list maps, | 915 | /* For each map in the list maps, |
| 903 | look at any other maps it points to, | 916 | look at any other maps it points to, |
| @@ -906,7 +919,7 @@ so that the KEYS increase in length. The first element is (\"\" . KEYMAP).") | |||
| 906 | This is a breadth-first traversal, where tail is the queue of | 919 | This is a breadth-first traversal, where tail is the queue of |
| 907 | nodes, and maps accumulates a list of all nodes visited. */ | 920 | nodes, and maps accumulates a list of all nodes visited. */ |
| 908 | 921 | ||
| 909 | while (!NILP (tail)) | 922 | for (tail = maps; CONSP (tail); tail = XCONS (tail)->cdr) |
| 910 | { | 923 | { |
| 911 | register Lisp_Object thisseq = Fcar (Fcar (tail)); | 924 | register Lisp_Object thisseq = Fcar (Fcar (tail)); |
| 912 | register Lisp_Object thismap = Fcdr (Fcar (tail)); | 925 | register Lisp_Object thismap = Fcdr (Fcar (tail)); |
| @@ -916,14 +929,13 @@ so that the KEYS increase in length. The first element is (\"\" . KEYMAP).") | |||
| 916 | int is_metized = (XINT (last) >= 0 | 929 | int is_metized = (XINT (last) >= 0 |
| 917 | && EQ (Faref (thisseq, last), meta_prefix_char)); | 930 | && EQ (Faref (thisseq, last), meta_prefix_char)); |
| 918 | 931 | ||
| 919 | /* Skip the 'keymap element of the list. */ | 932 | for (; CONSP (thismap); thismap = XCONS (thismap)->cdr) |
| 920 | thismap = Fcdr (thismap); | ||
| 921 | |||
| 922 | if (CONSP (thismap)) | ||
| 923 | { | 933 | { |
| 924 | register Lisp_Object table = XCONS (thismap)->car; | 934 | Lisp_Object elt = XCONS (thismap)->car; |
| 935 | |||
| 936 | QUIT; | ||
| 925 | 937 | ||
| 926 | if (XTYPE (table) == Lisp_Vector) | 938 | if (XTYPE (elt) == Lisp_Vector) |
| 927 | { | 939 | { |
| 928 | register int i; | 940 | register int i; |
| 929 | 941 | ||
| @@ -933,7 +945,7 @@ so that the KEYS increase in length. The first element is (\"\" . KEYMAP).") | |||
| 933 | register Lisp_Object tem; | 945 | register Lisp_Object tem; |
| 934 | register Lisp_Object cmd; | 946 | register Lisp_Object cmd; |
| 935 | 947 | ||
| 936 | cmd = get_keyelt (XVECTOR (table)->contents[i]); | 948 | cmd = get_keyelt (XVECTOR (elt)->contents[i]); |
| 937 | if (NILP (cmd)) continue; | 949 | if (NILP (cmd)) continue; |
| 938 | tem = Fkeymapp (cmd); | 950 | tem = Fkeymapp (cmd); |
| 939 | if (!NILP (tem)) | 951 | if (!NILP (tem)) |
| @@ -946,7 +958,8 @@ so that the KEYS increase in length. The first element is (\"\" . KEYMAP).") | |||
| 946 | /* If the last key in thisseq is meta-prefix-char, | 958 | /* If the last key in thisseq is meta-prefix-char, |
| 947 | turn it into a meta-ized keystroke. We know | 959 | turn it into a meta-ized keystroke. We know |
| 948 | that the event we're about to append is an | 960 | that the event we're about to append is an |
| 949 | ascii keystroke. */ | 961 | ascii keystroke since we're processing a |
| 962 | keymap table. */ | ||
| 950 | if (is_metized) | 963 | if (is_metized) |
| 951 | { | 964 | { |
| 952 | tem = Fcopy_sequence (thisseq); | 965 | tem = Fcopy_sequence (thisseq); |
| @@ -966,20 +979,8 @@ so that the KEYS increase in length. The first element is (\"\" . KEYMAP).") | |||
| 966 | } | 979 | } |
| 967 | } | 980 | } |
| 968 | } | 981 | } |
| 969 | 982 | } | |
| 970 | /* Once finished with the lookup elements of the dense | 983 | else if (CONSP (elt)) |
| 971 | keymap, go on to scan its assoc list. */ | ||
| 972 | thismap = XCONS (thismap)->cdr; | ||
| 973 | } | ||
| 974 | } | ||
| 975 | |||
| 976 | /* The rest is an alist. Scan all the alist elements. */ | ||
| 977 | while (CONSP (thismap)) | ||
| 978 | { | ||
| 979 | Lisp_Object elt = XCONS (thismap)->car; | ||
| 980 | |||
| 981 | /* Ignore elements that are not conses. */ | ||
| 982 | if (CONSP (elt)) | ||
| 983 | { | 984 | { |
| 984 | register Lisp_Object cmd = get_keyelt (XCONS (elt)->cdr); | 985 | register Lisp_Object cmd = get_keyelt (XCONS (elt)->cdr); |
| 985 | register Lisp_Object tem; | 986 | register Lisp_Object tem; |
| @@ -1017,11 +1018,7 @@ so that the KEYS increase in length. The first element is (\"\" . KEYMAP).") | |||
| 1017 | } | 1018 | } |
| 1018 | } | 1019 | } |
| 1019 | } | 1020 | } |
| 1020 | |||
| 1021 | thismap = XCONS (thismap)->cdr; | ||
| 1022 | } | 1021 | } |
| 1023 | |||
| 1024 | tail = Fcdr (tail); | ||
| 1025 | } | 1022 | } |
| 1026 | 1023 | ||
| 1027 | return maps; | 1024 | return maps; |
| @@ -1206,10 +1203,14 @@ indirect definition itself.") | |||
| 1206 | 1203 | ||
| 1207 | for (; !NILP (maps); maps = Fcdr (maps)) | 1204 | for (; !NILP (maps); maps = Fcdr (maps)) |
| 1208 | { | 1205 | { |
| 1209 | register this = Fcar (Fcar (maps)); /* Key sequence to reach map */ | 1206 | /* Key sequence to reach map */ |
| 1210 | register map = Fcdr (Fcar (maps)); /* The map that it reaches */ | 1207 | register Lisp_Object this = Fcar (Fcar (maps)); |
| 1211 | register dense_alist; | 1208 | |
| 1212 | register int i = 0; | 1209 | /* The map that it reaches */ |
| 1210 | register Lisp_Object map = Fcdr (Fcar (maps)); | ||
| 1211 | |||
| 1212 | /* If Fcar (map) is a VECTOR, the current element within that vector. */ | ||
| 1213 | int i = 0; | ||
| 1213 | 1214 | ||
| 1214 | /* In order to fold [META-PREFIX-CHAR CHAR] sequences into | 1215 | /* In order to fold [META-PREFIX-CHAR CHAR] sequences into |
| 1215 | [M-CHAR] sequences, check if last character of the sequence | 1216 | [M-CHAR] sequences, check if last character of the sequence |
| @@ -1217,54 +1218,50 @@ indirect definition itself.") | |||
| 1217 | Lisp_Object last = make_number (XINT (Flength (this)) - 1); | 1218 | Lisp_Object last = make_number (XINT (Flength (this)) - 1); |
| 1218 | int last_is_meta = (XINT (last) >= 0 | 1219 | int last_is_meta = (XINT (last) >= 0 |
| 1219 | && EQ (Faref (this, last), meta_prefix_char)); | 1220 | && EQ (Faref (this, last), meta_prefix_char)); |
| 1220 | |||
| 1221 | /* Skip the 'keymap element of the list. */ | ||
| 1222 | map = Fcdr (map); | ||
| 1223 | |||
| 1224 | /* If the keymap is sparse, map traverses the alist to the end. | ||
| 1225 | 1221 | ||
| 1226 | If the keymap is dense, we set map to the vector and | 1222 | while (CONSP (map)) |
| 1227 | dense_alist to the assoc-list portion of the keymap. When we | ||
| 1228 | are finished dealing with the vector portion, we set map to | ||
| 1229 | dense_alist, and handle the rest like a sparse keymap. */ | ||
| 1230 | if (XTYPE (XCONS (map)->car) == Lisp_Vector) | ||
| 1231 | { | 1223 | { |
| 1232 | dense_alist = XCONS (map)->cdr; | 1224 | /* Because the code we want to run on each binding is rather |
| 1233 | map = XCONS (map)->car; | 1225 | large, we don't want to have two separate loop bodies for |
| 1234 | } | 1226 | sparse keymap bindings and tables; we want to iterate one |
| 1235 | 1227 | loop body over both keymap and vector bindings. | |
| 1236 | while (1) | 1228 | |
| 1237 | { | 1229 | For this reason, if Fcar (map) is a vector, we don't |
| 1238 | register Lisp_Object key, binding, sequence; | 1230 | advance map to the next element until i indicates that we |
| 1231 | have finished off the vector. */ | ||
| 1239 | 1232 | ||
| 1240 | QUIT; | 1233 | Lisp_Object elt = XCONS (map)->car; |
| 1241 | if (XTYPE (map) == Lisp_Vector) | 1234 | Lisp_Object key, binding, sequence; |
| 1235 | |||
| 1236 | /* Set key and binding to the current key and binding, and | ||
| 1237 | advance map and i to the next binding. */ | ||
| 1238 | if (XTYPE (elt) == Lisp_Vector) | ||
| 1242 | { | 1239 | { |
| 1243 | /* In a vector, look at each element. */ | 1240 | /* In a vector, look at each element. */ |
| 1244 | binding = XVECTOR (map)->contents[i]; | 1241 | binding = XVECTOR (elt)->contents[i]; |
| 1245 | XFASTINT (key) = i; | 1242 | XFASTINT (key) = i; |
| 1246 | i++; | 1243 | i++; |
| 1247 | 1244 | ||
| 1248 | /* If we've just finished scanning a vector, switch map to | 1245 | /* If we've just finished scanning a vector, advance map |
| 1249 | the assoc-list at the end of the vector. */ | 1246 | to the next element, and reset i in anticipation of the |
| 1247 | next vector we may find. */ | ||
| 1250 | if (i >= DENSE_TABLE_SIZE) | 1248 | if (i >= DENSE_TABLE_SIZE) |
| 1251 | map = dense_alist; | ||
| 1252 | } | ||
| 1253 | else if (CONSP (map)) | ||
| 1254 | { | ||
| 1255 | /* In an alist, ignore elements that aren't conses. */ | ||
| 1256 | if (! CONSP (XCONS (map)->car)) | ||
| 1257 | { | 1249 | { |
| 1258 | /* Ignore other elements. */ | 1250 | map = XCONS (map)->cdr; |
| 1259 | map = Fcdr (map); | 1251 | i = 0; |
| 1260 | continue; | ||
| 1261 | } | 1252 | } |
| 1262 | binding = Fcdr (Fcar (map)); | 1253 | } |
| 1254 | else if (CONSP (elt)) | ||
| 1255 | { | ||
| 1263 | key = Fcar (Fcar (map)); | 1256 | key = Fcar (Fcar (map)); |
| 1264 | map = Fcdr (map); | 1257 | binding = Fcdr (Fcar (map)); |
| 1258 | |||
| 1259 | map = XCONS (map)->cdr; | ||
| 1265 | } | 1260 | } |
| 1266 | else | 1261 | else |
| 1267 | break; | 1262 | /* We want to ignore keymap elements that are neither |
| 1263 | vectors nor conses. */ | ||
| 1264 | continue; | ||
| 1268 | 1265 | ||
| 1269 | /* Search through indirections unless that's not wanted. */ | 1266 | /* Search through indirections unless that's not wanted. */ |
| 1270 | if (NILP (noindirect)) | 1267 | if (NILP (noindirect)) |
| @@ -1575,28 +1572,14 @@ describe_map (map, keys, partial, shadow) | |||
| 1575 | else | 1572 | else |
| 1576 | keysdesc = Qnil; | 1573 | keysdesc = Qnil; |
| 1577 | 1574 | ||
| 1578 | /* Skip the 'keymap element of the list. */ | 1575 | describe_map_2 (map, keysdesc, describe_command, partial, shadow); |
| 1579 | map = Fcdr (map); | ||
| 1580 | |||
| 1581 | /* If this is a dense keymap, take care of the table. */ | ||
| 1582 | if (CONSP (map) | ||
| 1583 | && XTYPE (XCONS (map)->car) == Lisp_Vector) | ||
| 1584 | { | ||
| 1585 | describe_vector (XCONS (map)->car, keysdesc, describe_command, | ||
| 1586 | partial, shadow); | ||
| 1587 | map = XCONS (map)->cdr; | ||
| 1588 | } | ||
| 1589 | |||
| 1590 | /* Now map is an alist. */ | ||
| 1591 | describe_alist (map, keysdesc, describe_command, partial, shadow); | ||
| 1592 | } | 1576 | } |
| 1593 | 1577 | ||
| 1594 | /* Insert a description of ALIST into the current buffer. | 1578 | /* Insert a description of KEYMAP into the current buffer. */ |
| 1595 | Note that ALIST is just a plain association list, not a keymap. */ | ||
| 1596 | 1579 | ||
| 1597 | static void | 1580 | static void |
| 1598 | describe_alist (alist, elt_prefix, elt_describer, partial, shadow) | 1581 | describe_map_2 (keymap, elt_prefix, elt_describer, partial, shadow) |
| 1599 | register Lisp_Object alist; | 1582 | register Lisp_Object keymap; |
| 1600 | Lisp_Object elt_prefix; | 1583 | Lisp_Object elt_prefix; |
| 1601 | int (*elt_describer) (); | 1584 | int (*elt_describer) (); |
| 1602 | int partial; | 1585 | int partial; |
| @@ -1613,56 +1596,63 @@ describe_alist (alist, elt_prefix, elt_describer, partial, shadow) | |||
| 1613 | suppress = intern ("suppress-keymap"); | 1596 | suppress = intern ("suppress-keymap"); |
| 1614 | 1597 | ||
| 1615 | /* This vector gets used to present single keys to Flookup_key. Since | 1598 | /* This vector gets used to present single keys to Flookup_key. Since |
| 1616 | that is done once per alist element, we don't want to cons up a | 1599 | that is done once per keymap element, we don't want to cons up a |
| 1617 | fresh vector every time. */ | 1600 | fresh vector every time. */ |
| 1618 | kludge = Fmake_vector (make_number (1), Qnil); | 1601 | kludge = Fmake_vector (make_number (1), Qnil); |
| 1619 | 1602 | ||
| 1620 | GCPRO3 (elt_prefix, tem2, kludge); | 1603 | GCPRO3 (elt_prefix, tem2, kludge); |
| 1621 | 1604 | ||
| 1622 | for (; CONSP (alist); alist = Fcdr (alist)) | 1605 | for (; CONSP (keymap); keymap = Fcdr (keymap)) |
| 1623 | { | 1606 | { |
| 1624 | QUIT; | 1607 | QUIT; |
| 1625 | tem1 = Fcar_safe (Fcar (alist)); | ||
| 1626 | tem2 = get_keyelt (Fcdr_safe (Fcar (alist))); | ||
| 1627 | 1608 | ||
| 1628 | /* Don't show undefined commands or suppressed commands. */ | 1609 | if (XTYPE (XCONS (keymap)->car) == Lisp_Vector) |
| 1629 | if (NILP (tem2)) continue; | 1610 | describe_vector (XCONS (keymap)->car, |
| 1630 | if (XTYPE (tem2) == Lisp_Symbol && partial) | 1611 | elt_prefix, elt_describer, partial, shadow); |
| 1612 | else | ||
| 1631 | { | 1613 | { |
| 1632 | this = Fget (tem2, suppress); | 1614 | tem1 = Fcar_safe (Fcar (keymap)); |
| 1633 | if (!NILP (this)) | 1615 | tem2 = get_keyelt (Fcdr_safe (Fcar (keymap))); |
| 1634 | continue; | ||
| 1635 | } | ||
| 1636 | 1616 | ||
| 1637 | /* Don't show a command that isn't really visible | 1617 | /* Don't show undefined commands or suppressed commands. */ |
| 1638 | because a local definition of the same key shadows it. */ | 1618 | if (NILP (tem2)) continue; |
| 1619 | if (XTYPE (tem2) == Lisp_Symbol && partial) | ||
| 1620 | { | ||
| 1621 | this = Fget (tem2, suppress); | ||
| 1622 | if (!NILP (this)) | ||
| 1623 | continue; | ||
| 1624 | } | ||
| 1639 | 1625 | ||
| 1640 | if (!NILP (shadow)) | 1626 | /* Don't show a command that isn't really visible |
| 1641 | { | 1627 | because a local definition of the same key shadows it. */ |
| 1642 | Lisp_Object tem; | ||
| 1643 | 1628 | ||
| 1644 | XVECTOR (kludge)->contents[0] = tem1; | 1629 | if (!NILP (shadow)) |
| 1645 | tem = Flookup_key (shadow, kludge); | 1630 | { |
| 1646 | if (!NILP (tem)) continue; | 1631 | Lisp_Object tem; |
| 1647 | } | ||
| 1648 | 1632 | ||
| 1649 | if (first) | 1633 | XVECTOR (kludge)->contents[0] = tem1; |
| 1650 | { | 1634 | tem = Flookup_key (shadow, kludge); |
| 1651 | insert ("\n", 1); | 1635 | if (!NILP (tem)) continue; |
| 1652 | first = 0; | 1636 | } |
| 1653 | } | ||
| 1654 | 1637 | ||
| 1655 | if (!NILP (elt_prefix)) | 1638 | if (first) |
| 1656 | insert1 (elt_prefix); | 1639 | { |
| 1640 | insert ("\n", 1); | ||
| 1641 | first = 0; | ||
| 1642 | } | ||
| 1657 | 1643 | ||
| 1658 | /* THIS gets the string to describe the character TEM1. */ | 1644 | if (!NILP (elt_prefix)) |
| 1659 | this = Fsingle_key_description (tem1); | 1645 | insert1 (elt_prefix); |
| 1660 | insert1 (this); | ||
| 1661 | 1646 | ||
| 1662 | /* Print a description of the definition of this character. | 1647 | /* THIS gets the string to describe the character TEM1. */ |
| 1663 | elt_describer will take care of spacing out far enough | 1648 | this = Fsingle_key_description (tem1); |
| 1664 | for alignment purposes. */ | 1649 | insert1 (this); |
| 1665 | (*elt_describer) (tem2); | 1650 | |
| 1651 | /* Print a description of the definition of this character. | ||
| 1652 | elt_describer will take care of spacing out far enough | ||
| 1653 | for alignment purposes. */ | ||
| 1654 | (*elt_describer) (tem2); | ||
| 1655 | } | ||
| 1666 | } | 1656 | } |
| 1667 | 1657 | ||
| 1668 | UNGCPRO; | 1658 | UNGCPRO; |