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 }