Mercurial > emacs
comparison src/keymap.c @ 67904:d2dff317d618
(describe_map): Put sparse map elements into an array,
sort them, then output a sequence of identical bindings on one line.
(struct describe_map_elt): New data type.
(describe_map_compare): New function.
| author | Richard M. Stallman <rms@gnu.org> |
|---|---|
| date | Fri, 30 Dec 2005 04:52:16 +0000 |
| parents | e7b90ba8a38a |
| children | 2e977adcc0e5 c69d44922688 |
comparison
equal
deleted
inserted
replaced
| 67903:a57273fb71d3 | 67904:d2dff317d618 |
|---|---|
| 3172 insert_string ("Prefix Command\n"); | 3172 insert_string ("Prefix Command\n"); |
| 3173 else | 3173 else |
| 3174 insert_string ("??\n"); | 3174 insert_string ("??\n"); |
| 3175 } | 3175 } |
| 3176 | 3176 |
| 3177 /* describe_map puts all the usable elements of a sparse keymap | |
| 3178 into an array of `struct describe_map_elt', | |
| 3179 then sorts them by the events. */ | |
| 3180 | |
| 3181 struct describe_map_elt { Lisp_Object event; Lisp_Object definition; int shadowed; }; | |
| 3182 | |
| 3183 /* qsort comparison function for sorting `struct describe_map_elt' by | |
| 3184 the event field. */ | |
| 3185 | |
| 3186 static int | |
| 3187 describe_map_compare (aa, bb) | |
| 3188 const void *aa, *bb; | |
| 3189 { | |
| 3190 const struct describe_map_elt *a = aa, *b = bb; | |
| 3191 if (INTEGERP (a->event) && INTEGERP (b->event)) | |
| 3192 return ((XINT (a->event) > XINT (b->event)) | |
| 3193 - (XINT (a->event) < XINT (b->event))); | |
| 3194 if (!INTEGERP (a->event) && INTEGERP (b->event)) | |
| 3195 return 1; | |
| 3196 if (INTEGERP (a->event) && !INTEGERP (b->event)) | |
| 3197 return -1; | |
| 3198 if (SYMBOLP (a->event) && SYMBOLP (b->event)) | |
| 3199 return (Fstring_lessp (a->event, b->event) ? -1 | |
| 3200 : Fstring_lessp (b->event, a->event) ? 1 | |
| 3201 : 0); | |
| 3202 return 0; | |
| 3203 } | |
| 3204 | |
| 3177 /* Describe the contents of map MAP, assuming that this map itself is | 3205 /* Describe the contents of map MAP, assuming that this map itself is |
| 3178 reached by the sequence of prefix keys PREFIX (a string or vector). | 3206 reached by the sequence of prefix keys PREFIX (a string or vector). |
| 3179 PARTIAL, SHADOW, NOMENU are as in `describe_map_tree' above. */ | 3207 PARTIAL, SHADOW, NOMENU are as in `describe_map_tree' above. */ |
| 3180 | 3208 |
| 3181 static void | 3209 static void |
| 3195 Lisp_Object suppress; | 3223 Lisp_Object suppress; |
| 3196 Lisp_Object kludge; | 3224 Lisp_Object kludge; |
| 3197 int first = 1; | 3225 int first = 1; |
| 3198 struct gcpro gcpro1, gcpro2, gcpro3; | 3226 struct gcpro gcpro1, gcpro2, gcpro3; |
| 3199 | 3227 |
| 3228 /* These accumulate the values from sparse keymap bindings, | |
| 3229 so we can sort them and handle them in order. */ | |
| 3230 int length_needed = 0; | |
| 3231 struct describe_map_elt *vect; | |
| 3232 int slots_used = 0; | |
| 3233 int i; | |
| 3234 | |
| 3200 suppress = Qnil; | 3235 suppress = Qnil; |
| 3201 | 3236 |
| 3202 if (partial) | 3237 if (partial) |
| 3203 suppress = intern ("suppress-keymap"); | 3238 suppress = intern ("suppress-keymap"); |
| 3204 | 3239 |
| 3205 /* This vector gets used to present single keys to Flookup_key. Since | 3240 /* This vector gets used to present single keys to Flookup_key. Since |
| 3206 that is done once per keymap element, we don't want to cons up a | 3241 that is done once per keymap element, we don't want to cons up a |
| 3207 fresh vector every time. */ | 3242 fresh vector every time. */ |
| 3208 kludge = Fmake_vector (make_number (1), Qnil); | 3243 kludge = Fmake_vector (make_number (1), Qnil); |
| 3209 definition = Qnil; | 3244 definition = Qnil; |
| 3245 | |
| 3246 for (tail = map; CONSP (tail); tail = XCDR (tail)) | |
| 3247 length_needed++; | |
| 3248 | |
| 3249 vect = ((struct describe_map_elt *) | |
| 3250 alloca (sizeof (struct describe_map_elt) * length_needed)); | |
| 3210 | 3251 |
| 3211 GCPRO3 (prefix, definition, kludge); | 3252 GCPRO3 (prefix, definition, kludge); |
| 3212 | 3253 |
| 3213 for (tail = map; CONSP (tail); tail = XCDR (tail)) | 3254 for (tail = map; CONSP (tail); tail = XCDR (tail)) |
| 3214 { | 3255 { |
| 3220 prefix, Qnil, elt_describer, partial, shadow, map, | 3261 prefix, Qnil, elt_describer, partial, shadow, map, |
| 3221 (int *)0, 0, 1, mention_shadow); | 3262 (int *)0, 0, 1, mention_shadow); |
| 3222 else if (CONSP (XCAR (tail))) | 3263 else if (CONSP (XCAR (tail))) |
| 3223 { | 3264 { |
| 3224 int this_shadowed = 0; | 3265 int this_shadowed = 0; |
| 3266 | |
| 3225 event = XCAR (XCAR (tail)); | 3267 event = XCAR (XCAR (tail)); |
| 3226 | 3268 |
| 3227 /* Ignore bindings whose "prefix" are not really valid events. | 3269 /* Ignore bindings whose "prefix" are not really valid events. |
| 3228 (We get these in the frames and buffers menu.) */ | 3270 (We get these in the frames and buffers menu.) */ |
| 3229 if (!(SYMBOLP (event) || INTEGERP (event))) | 3271 if (!(SYMBOLP (event) || INTEGERP (event))) |
| 3260 } | 3302 } |
| 3261 | 3303 |
| 3262 tem = Flookup_key (map, kludge, Qt); | 3304 tem = Flookup_key (map, kludge, Qt); |
| 3263 if (!EQ (tem, definition)) continue; | 3305 if (!EQ (tem, definition)) continue; |
| 3264 | 3306 |
| 3265 if (first) | 3307 vect[slots_used].event = event; |
| 3266 { | 3308 vect[slots_used].definition = definition; |
| 3267 previous_description_column = 0; | 3309 vect[slots_used].shadowed = this_shadowed; |
| 3268 insert ("\n", 1); | 3310 slots_used++; |
| 3269 first = 0; | |
| 3270 } | |
| 3271 | |
| 3272 /* THIS gets the string to describe the character EVENT. */ | |
| 3273 insert1 (Fkey_description (kludge, prefix)); | |
| 3274 | |
| 3275 /* Print a description of the definition of this character. | |
| 3276 elt_describer will take care of spacing out far enough | |
| 3277 for alignment purposes. */ | |
| 3278 (*elt_describer) (definition, Qnil); | |
| 3279 | |
| 3280 if (this_shadowed) | |
| 3281 { | |
| 3282 SET_PT (PT - 1); | |
| 3283 insert_string (" (binding currently shadowed)"); | |
| 3284 SET_PT (PT + 1); | |
| 3285 } | |
| 3286 } | 3311 } |
| 3287 else if (EQ (XCAR (tail), Qkeymap)) | 3312 else if (EQ (XCAR (tail), Qkeymap)) |
| 3288 { | 3313 { |
| 3289 /* The same keymap might be in the structure twice, if we're | 3314 /* The same keymap might be in the structure twice, if we're |
| 3290 using an inherited keymap. So skip anything we've already | 3315 using an inherited keymap. So skip anything we've already |
| 3291 encountered. */ | 3316 encountered. */ |
| 3292 tem = Fassq (tail, *seen); | 3317 tem = Fassq (tail, *seen); |
| 3293 if (CONSP (tem) && !NILP (Fequal (XCAR (tem), prefix))) | 3318 if (CONSP (tem) && !NILP (Fequal (XCAR (tem), prefix))) |
| 3294 break; | 3319 break; |
| 3295 *seen = Fcons (Fcons (tail, prefix), *seen); | 3320 *seen = Fcons (Fcons (tail, prefix), *seen); |
| 3321 } | |
| 3322 } | |
| 3323 | |
| 3324 /* If we found some sparse map events, sort them. */ | |
| 3325 | |
| 3326 qsort (vect, slots_used, sizeof (struct describe_map_elt), | |
| 3327 describe_map_compare); | |
| 3328 | |
| 3329 /* Now output them in sorted order. */ | |
| 3330 | |
| 3331 for (i = 0; i < slots_used; i++) | |
| 3332 { | |
| 3333 Lisp_Object start, end; | |
| 3334 | |
| 3335 if (first) | |
| 3336 { | |
| 3337 previous_description_column = 0; | |
| 3338 insert ("\n", 1); | |
| 3339 first = 0; | |
| 3340 } | |
| 3341 | |
| 3342 ASET (kludge, 0, vect[i].event); | |
| 3343 start = vect[i].event; | |
| 3344 end = start; | |
| 3345 | |
| 3346 definition = vect[i].definition; | |
| 3347 | |
| 3348 /* Find consecutive chars that are identically defined. */ | |
| 3349 if (INTEGERP (vect[i].event)) | |
| 3350 { | |
| 3351 while (i + 1 < slots_used | |
| 3352 && XINT (vect[i + 1].event) == XINT (vect[i].event) + 1 | |
| 3353 && !NILP (Fequal (vect[i + 1].definition, definition)) | |
| 3354 && vect[i].shadowed == vect[i + 1].shadowed) | |
| 3355 i++; | |
| 3356 end = vect[i].event; | |
| 3357 } | |
| 3358 | |
| 3359 /* Now START .. END is the range to describe next. */ | |
| 3360 | |
| 3361 /* Insert the string to describe the event START. */ | |
| 3362 insert1 (Fkey_description (kludge, prefix)); | |
| 3363 | |
| 3364 if (!EQ (start, end)) | |
| 3365 { | |
| 3366 insert (" .. ", 4); | |
| 3367 | |
| 3368 ASET (kludge, 0, end); | |
| 3369 /* Insert the string to describe the character END. */ | |
| 3370 insert1 (Fkey_description (kludge, prefix)); | |
| 3371 } | |
| 3372 | |
| 3373 /* Print a description of the definition of this character. | |
| 3374 elt_describer will take care of spacing out far enough | |
| 3375 for alignment purposes. */ | |
| 3376 (*elt_describer) (vect[i].definition, Qnil); | |
| 3377 | |
| 3378 if (vect[i].shadowed) | |
| 3379 { | |
| 3380 SET_PT (PT - 1); | |
| 3381 insert_string (" (binding currently shadowed)"); | |
| 3382 SET_PT (PT + 1); | |
| 3296 } | 3383 } |
| 3297 } | 3384 } |
| 3298 | 3385 |
| 3299 UNGCPRO; | 3386 UNGCPRO; |
| 3300 } | 3387 } |
