136 |
static void keymap_panes P_ ((Lisp_Object *, int, int)); |
static void keymap_panes P_ ((Lisp_Object *, int, int)); |
137 |
static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object, |
static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object, |
138 |
int, int)); |
int, int)); |
|
static void single_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object *, |
|
|
int, int, int *)); |
|
139 |
static void list_of_panes P_ ((Lisp_Object)); |
static void list_of_panes P_ ((Lisp_Object)); |
140 |
static void list_of_items P_ ((Lisp_Object)); |
static void list_of_items P_ ((Lisp_Object)); |
141 |
|
|
408 |
finish_menu_items (); |
finish_menu_items (); |
409 |
} |
} |
410 |
|
|
411 |
|
/* Args passed between single_keymap_panes and single_menu_item. */ |
412 |
|
struct skp |
413 |
|
{ |
414 |
|
Lisp_Object pending_maps; |
415 |
|
int maxdepth, notreal; |
416 |
|
int notbuttons; |
417 |
|
}; |
418 |
|
|
419 |
|
static void single_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object, |
420 |
|
struct skp*)); |
421 |
|
|
422 |
/* This is a recursive subroutine of keymap_panes. |
/* This is a recursive subroutine of keymap_panes. |
423 |
It handles one keymap, KEYMAP. |
It handles one keymap, KEYMAP. |
424 |
The other arguments are passed along |
The other arguments are passed along |
436 |
int notreal; |
int notreal; |
437 |
int maxdepth; |
int maxdepth; |
438 |
{ |
{ |
439 |
Lisp_Object pending_maps = Qnil; |
struct skp skp; |
440 |
Lisp_Object tail, item; |
struct gcpro gcpro1; |
441 |
struct gcpro gcpro1, gcpro2; |
|
442 |
int notbuttons = 0; |
skp.pending_maps = Qnil; |
443 |
|
skp.maxdepth = maxdepth; |
444 |
|
skp.notreal = notreal; |
445 |
|
skp.notbuttons = 0; |
446 |
|
|
447 |
if (maxdepth <= 0) |
if (maxdepth <= 0) |
448 |
return; |
return; |
454 |
add a prefix when (if) we see the first button. After that, notbuttons |
add a prefix when (if) we see the first button. After that, notbuttons |
455 |
is set to 0, to mark that we have seen a button and all non button |
is set to 0, to mark that we have seen a button and all non button |
456 |
items need a prefix. */ |
items need a prefix. */ |
457 |
notbuttons = menu_items_used; |
skp.notbuttons = menu_items_used; |
458 |
#endif |
#endif |
459 |
|
|
460 |
for (tail = keymap; CONSP (tail); tail = XCDR (tail)) |
GCPRO1 (skp.pending_maps); |
461 |
{ |
map_keymap (keymap, single_menu_item, Qnil, &skp, 1); |
462 |
GCPRO2 (keymap, pending_maps); |
UNGCPRO; |
|
/* Look at each key binding, and if it is a menu item add it |
|
|
to this menu. */ |
|
|
item = XCAR (tail); |
|
|
if (CONSP (item)) |
|
|
single_menu_item (XCAR (item), XCDR (item), |
|
|
&pending_maps, notreal, maxdepth, ¬buttons); |
|
|
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); |
|
|
single_menu_item (character, XVECTOR (item)->contents[c], |
|
|
&pending_maps, notreal, maxdepth, ¬buttons); |
|
|
} |
|
|
} |
|
|
UNGCPRO; |
|
|
} |
|
463 |
|
|
464 |
/* Process now any submenus which want to be panes at this level. */ |
/* Process now any submenus which want to be panes at this level. */ |
465 |
while (!NILP (pending_maps)) |
while (CONSP (skp.pending_maps)) |
466 |
{ |
{ |
467 |
Lisp_Object elt, eltcdr, string; |
Lisp_Object elt, eltcdr, string; |
468 |
elt = Fcar (pending_maps); |
elt = XCAR (skp.pending_maps); |
469 |
eltcdr = XCDR (elt); |
eltcdr = XCDR (elt); |
470 |
string = XCAR (eltcdr); |
string = XCAR (eltcdr); |
471 |
/* We no longer discard the @ from the beginning of the string here. |
/* We no longer discard the @ from the beginning of the string here. |
472 |
Instead, we do this in xmenu_show. */ |
Instead, we do this in xmenu_show. */ |
473 |
single_keymap_panes (Fcar (elt), string, |
single_keymap_panes (Fcar (elt), string, |
474 |
XCDR (eltcdr), notreal, maxdepth - 1); |
XCDR (eltcdr), notreal, maxdepth - 1); |
475 |
pending_maps = Fcdr (pending_maps); |
skp.pending_maps = XCDR (skp.pending_maps); |
476 |
} |
} |
477 |
} |
} |
478 |
|
|
479 |
/* This is a subroutine of single_keymap_panes that handles one |
/* This is a subroutine of single_keymap_panes that handles one |
480 |
keymap entry. |
keymap entry. |
481 |
KEY is a key in a keymap and ITEM is its binding. |
KEY is a key in a keymap and ITEM is its binding. |
482 |
PENDING_MAPS_PTR points to a list of keymaps waiting to be made into |
SKP->PENDING_MAPS_PTR is a list of keymaps waiting to be made into |
483 |
separate panes. |
separate panes. |
484 |
If NOTREAL is nonzero, only check for equivalent key bindings, don't |
If SKP->NOTREAL is nonzero, only check for equivalent key bindings, don't |
485 |
evaluate expressions in menu items and don't make any menu. |
evaluate expressions in menu items and don't make any menu. |
486 |
If we encounter submenus deeper than MAXDEPTH levels, ignore them. |
If we encounter submenus deeper than SKP->MAXDEPTH levels, ignore them. |
487 |
NOTBUTTONS_PTR is only used when simulating toggle boxes and radio |
SKP->NOTBUTTONS is only used when simulating toggle boxes and radio |
488 |
buttons. It points to variable notbuttons in single_keymap_panes, |
buttons. It keeps track of if we have seen a button in this menu or |
489 |
which keeps track of if we have seen a button in this menu or not. */ |
not. */ |
490 |
|
|
491 |
static void |
static void |
492 |
single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth, |
single_menu_item (key, item, dummy, skp) |
493 |
notbuttons_ptr) |
Lisp_Object key, item, dummy; |
494 |
Lisp_Object key, item; |
struct skp *skp; |
|
Lisp_Object *pending_maps_ptr; |
|
|
int maxdepth, notreal; |
|
|
int *notbuttons_ptr; |
|
495 |
{ |
{ |
496 |
Lisp_Object map, item_string, enabled; |
Lisp_Object map, item_string, enabled; |
497 |
struct gcpro gcpro1, gcpro2; |
struct gcpro gcpro1, gcpro2; |
499 |
|
|
500 |
/* Parse the menu item and leave the result in item_properties. */ |
/* Parse the menu item and leave the result in item_properties. */ |
501 |
GCPRO2 (key, item); |
GCPRO2 (key, item); |
502 |
res = parse_menu_item (item, notreal, 0); |
res = parse_menu_item (item, skp->notreal, 0); |
503 |
UNGCPRO; |
UNGCPRO; |
504 |
if (!res) |
if (!res) |
505 |
return; /* Not a menu item. */ |
return; /* Not a menu item. */ |
506 |
|
|
507 |
map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP]; |
map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP]; |
508 |
|
|
509 |
if (notreal) |
if (skp->notreal) |
510 |
{ |
{ |
511 |
/* We don't want to make a menu, just traverse the keymaps to |
/* We don't want to make a menu, just traverse the keymaps to |
512 |
precompute equivalent key bindings. */ |
precompute equivalent key bindings. */ |
513 |
if (!NILP (map)) |
if (!NILP (map)) |
514 |
single_keymap_panes (map, Qnil, key, 1, maxdepth - 1); |
single_keymap_panes (map, Qnil, key, 1, skp->maxdepth - 1); |
515 |
return; |
return; |
516 |
} |
} |
517 |
|
|
522 |
{ |
{ |
523 |
if (!NILP (enabled)) |
if (!NILP (enabled)) |
524 |
/* An enabled separate pane. Remember this to handle it later. */ |
/* An enabled separate pane. Remember this to handle it later. */ |
525 |
*pending_maps_ptr = Fcons (Fcons (map, Fcons (item_string, key)), |
skp->pending_maps = Fcons (Fcons (map, Fcons (item_string, key)), |
526 |
*pending_maps_ptr); |
skp->pending_maps); |
527 |
return; |
return; |
528 |
} |
} |
529 |
|
|
538 |
Lisp_Object selected |
Lisp_Object selected |
539 |
= XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED]; |
= XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED]; |
540 |
|
|
541 |
if (*notbuttons_ptr) |
if (skp->notbuttons) |
542 |
/* The first button. Line up previous items in this menu. */ |
/* The first button. Line up previous items in this menu. */ |
543 |
{ |
{ |
544 |
int index = *notbuttons_ptr; /* Index for first item this menu. */ |
int index = skp->notbuttons; /* Index for first item this menu. */ |
545 |
int submenu = 0; |
int submenu = 0; |
546 |
Lisp_Object tem; |
Lisp_Object tem; |
547 |
while (index < menu_items_used) |
while (index < menu_items_used) |
571 |
index += MENU_ITEMS_ITEM_LENGTH; |
index += MENU_ITEMS_ITEM_LENGTH; |
572 |
} |
} |
573 |
} |
} |
574 |
*notbuttons_ptr = 0; |
skp->notbuttons = 0; |
575 |
} |
} |
576 |
|
|
577 |
/* Calculate prefix, if any, for this item. */ |
/* Calculate prefix, if any, for this item. */ |
581 |
prefix = build_string (NILP (selected) ? "( ) " : "(*) "); |
prefix = build_string (NILP (selected) ? "( ) " : "(*) "); |
582 |
} |
} |
583 |
/* Not a button. If we have earlier buttons, then we need a prefix. */ |
/* Not a button. If we have earlier buttons, then we need a prefix. */ |
584 |
else if (!*notbuttons_ptr && SREF (item_string, 0) != '\0' |
else if (!skp->notbuttons && SREF (item_string, 0) != '\0' |
585 |
&& SREF (item_string, 0) != '-') |
&& SREF (item_string, 0) != '-') |
586 |
prefix = build_string (" "); |
prefix = build_string (" "); |
587 |
|
|
608 |
if (! (NILP (map) || NILP (enabled))) |
if (! (NILP (map) || NILP (enabled))) |
609 |
{ |
{ |
610 |
push_submenu_start (); |
push_submenu_start (); |
611 |
single_keymap_panes (map, Qnil, key, 0, maxdepth - 1); |
single_keymap_panes (map, Qnil, key, 0, skp->maxdepth - 1); |
612 |
push_submenu_end (); |
push_submenu_end (); |
613 |
} |
} |
614 |
#endif |
#endif |