diff options
| author | Richard M. Stallman | 1998-03-21 06:01:22 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1998-03-21 06:01:22 +0000 |
| commit | de57a39c28e6618fc3289a4102aa4762244b94bd (patch) | |
| tree | 76b446c18ccdced3b1989065d8f89bb98d7882f4 /src | |
| parent | a3fc8840a3c1586b17c9d211e959571fba365af6 (diff) | |
| download | emacs-de57a39c28e6618fc3289a4102aa4762244b94bd.tar.gz emacs-de57a39c28e6618fc3289a4102aa4762244b94bd.zip | |
Don't include puresize.h any more as code that needs it
has moved to keyboard.c.
(menu_item_equiv_key, menu_item_enabled_p_1, menu_item_enabled_p):
Functions deleted; code moved to parse_menu_item in keyboard.c.
(single_keymap_panes): Large part of code moved to single_menu_item.
(single_menu_item): New function that uses parse_menu_item.
(Qmenu_alias): Variable deleted.
(QCtoggle, QCradio): New variables.
(syms_of_xmenu): Change initializations of variables.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xmenu.c | 450 |
1 files changed, 162 insertions, 288 deletions
diff --git a/src/xmenu.c b/src/xmenu.c index 9116030f07c..ef51f83ee3c 100644 --- a/src/xmenu.c +++ b/src/xmenu.c | |||
| @@ -41,7 +41,6 @@ Boston, MA 02111-1307, USA. */ | |||
| 41 | #include "window.h" | 41 | #include "window.h" |
| 42 | #include "keyboard.h" | 42 | #include "keyboard.h" |
| 43 | #include "blockinput.h" | 43 | #include "blockinput.h" |
| 44 | #include "puresize.h" | ||
| 45 | #include "buffer.h" | 44 | #include "buffer.h" |
| 46 | 45 | ||
| 47 | #ifdef MSDOS | 46 | #ifdef MSDOS |
| @@ -90,13 +89,10 @@ Lisp_Object Vmenu_updating_frame; | |||
| 90 | 89 | ||
| 91 | Lisp_Object Qdebug_on_next_call; | 90 | Lisp_Object Qdebug_on_next_call; |
| 92 | 91 | ||
| 93 | Lisp_Object Qmenu_alias; | ||
| 94 | |||
| 95 | extern Lisp_Object Qmenu_enable; | ||
| 96 | extern Lisp_Object Qmenu_bar; | 92 | extern Lisp_Object Qmenu_bar; |
| 97 | extern Lisp_Object Qmouse_click, Qevent_kind; | 93 | extern Lisp_Object Qmouse_click, Qevent_kind; |
| 98 | 94 | ||
| 99 | extern Lisp_Object Vdefine_key_rebound_commands; | 95 | extern Lisp_Object QCtoggle, QCradio; |
| 100 | 96 | ||
| 101 | extern Lisp_Object Voverriding_local_map; | 97 | extern Lisp_Object Voverriding_local_map; |
| 102 | extern Lisp_Object Voverriding_local_map_menu_flag; | 98 | extern Lisp_Object Voverriding_local_map_menu_flag; |
| @@ -117,6 +113,7 @@ void popup_get_selection (); | |||
| 117 | static Lisp_Object xmenu_show (); | 113 | static Lisp_Object xmenu_show (); |
| 118 | static void keymap_panes (); | 114 | static void keymap_panes (); |
| 119 | static void single_keymap_panes (); | 115 | static void single_keymap_panes (); |
| 116 | static void single_menu_item (); | ||
| 120 | static void list_of_panes (); | 117 | static void list_of_panes (); |
| 121 | static void list_of_items (); | 118 | static void list_of_items (); |
| 122 | 119 | ||
| @@ -339,152 +336,6 @@ push_menu_item (name, enable, key, def, equiv) | |||
| 339 | XVECTOR (menu_items)->contents[menu_items_used++] = def; | 336 | XVECTOR (menu_items)->contents[menu_items_used++] = def; |
| 340 | } | 337 | } |
| 341 | 338 | ||
| 342 | /* Figure out the current keyboard equivalent of a menu item ITEM1. | ||
| 343 | The item string for menu display should be ITEM_STRING. | ||
| 344 | Store the equivalent keyboard key sequence's | ||
| 345 | textual description into *DESCRIP_PTR. | ||
| 346 | Also cache them in the item itself. | ||
| 347 | Return the real definition to execute. */ | ||
| 348 | |||
| 349 | static Lisp_Object | ||
| 350 | menu_item_equiv_key (item_string, item1, descrip_ptr) | ||
| 351 | Lisp_Object item_string; | ||
| 352 | Lisp_Object item1; | ||
| 353 | Lisp_Object *descrip_ptr; | ||
| 354 | { | ||
| 355 | /* This is the real definition--the function to run. */ | ||
| 356 | Lisp_Object def; | ||
| 357 | /* This is the sublist that records cached equiv key data | ||
| 358 | so we can save time. */ | ||
| 359 | Lisp_Object cachelist; | ||
| 360 | /* These are the saved equivalent keyboard key sequence | ||
| 361 | and its key-description. */ | ||
| 362 | Lisp_Object savedkey, descrip; | ||
| 363 | Lisp_Object def1; | ||
| 364 | int changed = 0; | ||
| 365 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | ||
| 366 | |||
| 367 | /* If a help string follows the item string, skip it. */ | ||
| 368 | if (CONSP (XCONS (item1)->cdr) | ||
| 369 | && STRINGP (XCONS (XCONS (item1)->cdr)->car)) | ||
| 370 | item1 = XCONS (item1)->cdr; | ||
| 371 | |||
| 372 | def = Fcdr (item1); | ||
| 373 | |||
| 374 | /* Get out the saved equivalent-keyboard-key info. */ | ||
| 375 | cachelist = savedkey = descrip = Qnil; | ||
| 376 | if (CONSP (def) && CONSP (XCONS (def)->car) | ||
| 377 | && (NILP (XCONS (XCONS (def)->car)->car) | ||
| 378 | || VECTORP (XCONS (XCONS (def)->car)->car))) | ||
| 379 | { | ||
| 380 | cachelist = XCONS (def)->car; | ||
| 381 | def = XCONS (def)->cdr; | ||
| 382 | savedkey = XCONS (cachelist)->car; | ||
| 383 | descrip = XCONS (cachelist)->cdr; | ||
| 384 | } | ||
| 385 | |||
| 386 | GCPRO4 (def, def1, savedkey, descrip); | ||
| 387 | |||
| 388 | /* Is it still valid? */ | ||
| 389 | def1 = Qnil; | ||
| 390 | if (!NILP (savedkey)) | ||
| 391 | def1 = Fkey_binding (savedkey, Qnil); | ||
| 392 | /* If not, update it. */ | ||
| 393 | if (! EQ (def1, def) | ||
| 394 | /* If the command is an alias for another | ||
| 395 | (such as easymenu.el and lmenu.el set it up), | ||
| 396 | check if the original command matches the cached command. */ | ||
| 397 | && !(SYMBOLP (def) && SYMBOLP (XSYMBOL (def)->function) | ||
| 398 | && EQ (def1, XSYMBOL (def)->function)) | ||
| 399 | /* If something had no key binding before, don't recheck it | ||
| 400 | because that is too slow--except if we have a list of rebound | ||
| 401 | commands in Vdefine_key_rebound_commands, do recheck any command | ||
| 402 | that appears in that list. */ | ||
| 403 | && (NILP (cachelist) || !NILP (savedkey) | ||
| 404 | || (! EQ (Qt, Vdefine_key_rebound_commands) | ||
| 405 | && !NILP (Fmemq (def, Vdefine_key_rebound_commands))))) | ||
| 406 | { | ||
| 407 | changed = 1; | ||
| 408 | descrip = Qnil; | ||
| 409 | /* If the command is an alias for another | ||
| 410 | (such as easymenu.el and lmenu.el set it up), | ||
| 411 | see if the original command name has equivalent keys. */ | ||
| 412 | if (SYMBOLP (def) && SYMBOLP (XSYMBOL (def)->function) | ||
| 413 | && ! NILP (Fget (def, Qmenu_alias))) | ||
| 414 | savedkey = Fwhere_is_internal (XSYMBOL (def)->function, | ||
| 415 | Qnil, Qt, Qnil); | ||
| 416 | else | ||
| 417 | /* Otherwise look up the specified command itself. | ||
| 418 | We don't try both, because that makes easymenu menus slow. */ | ||
| 419 | savedkey = Fwhere_is_internal (def, Qnil, Qt, Qnil); | ||
| 420 | |||
| 421 | if (!NILP (savedkey)) | ||
| 422 | { | ||
| 423 | descrip = Fkey_description (savedkey); | ||
| 424 | descrip = concat2 (make_string (" (", 3), descrip); | ||
| 425 | descrip = concat2 (descrip, make_string (")", 1)); | ||
| 426 | } | ||
| 427 | } | ||
| 428 | |||
| 429 | /* Cache the data we just got in a sublist of the menu binding. */ | ||
| 430 | if (NILP (cachelist)) | ||
| 431 | { | ||
| 432 | CHECK_IMPURE (item1); | ||
| 433 | XCONS (item1)->cdr = Fcons (Fcons (savedkey, descrip), def); | ||
| 434 | } | ||
| 435 | else if (changed) | ||
| 436 | { | ||
| 437 | XCONS (cachelist)->car = savedkey; | ||
| 438 | XCONS (cachelist)->cdr = descrip; | ||
| 439 | } | ||
| 440 | |||
| 441 | UNGCPRO; | ||
| 442 | *descrip_ptr = descrip; | ||
| 443 | return def; | ||
| 444 | } | ||
| 445 | |||
| 446 | /* This is used as the handler when calling internal_condition_case_1. */ | ||
| 447 | |||
| 448 | static Lisp_Object | ||
| 449 | menu_item_enabled_p_1 (arg) | ||
| 450 | Lisp_Object arg; | ||
| 451 | { | ||
| 452 | /* If we got a quit from within the menu computation, | ||
| 453 | quit all the way out of it. This takes care of C-] in the debugger. */ | ||
| 454 | if (CONSP (arg) && EQ (XCONS (arg)->car, Qquit)) | ||
| 455 | Fsignal (Qquit, Qnil); | ||
| 456 | |||
| 457 | return Qnil; | ||
| 458 | } | ||
| 459 | |||
| 460 | /* Return non-nil if the command DEF is enabled when used as a menu item. | ||
| 461 | This is based on looking for a menu-enable property. | ||
| 462 | If NOTREAL is set, don't bother really computing this. */ | ||
| 463 | |||
| 464 | static Lisp_Object | ||
| 465 | menu_item_enabled_p (def, notreal) | ||
| 466 | Lisp_Object def; | ||
| 467 | int notreal; | ||
| 468 | { | ||
| 469 | Lisp_Object enabled, tem; | ||
| 470 | |||
| 471 | enabled = Qt; | ||
| 472 | if (notreal) | ||
| 473 | return enabled; | ||
| 474 | if (SYMBOLP (def)) | ||
| 475 | { | ||
| 476 | /* No property, or nil, means enable. | ||
| 477 | Otherwise, enable if value is not nil. */ | ||
| 478 | tem = Fget (def, Qmenu_enable); | ||
| 479 | if (!NILP (tem)) | ||
| 480 | /* (condition-case nil (eval tem) | ||
| 481 | (error nil)) */ | ||
| 482 | enabled = internal_condition_case_1 (Feval, tem, Qerror, | ||
| 483 | menu_item_enabled_p_1); | ||
| 484 | } | ||
| 485 | return enabled; | ||
| 486 | } | ||
| 487 | |||
| 488 | /* Look through KEYMAPS, a vector of keymaps that is NMAPS long, | 339 | /* Look through KEYMAPS, a vector of keymaps that is NMAPS long, |
| 489 | and generate menu panes for them in menu_items. | 340 | and generate menu panes for them in menu_items. |
| 490 | If NOTREAL is nonzero, | 341 | If NOTREAL is nonzero, |
| @@ -513,8 +364,8 @@ keymap_panes (keymaps, nmaps, notreal) | |||
| 513 | It handles one keymap, KEYMAP. | 364 | It handles one keymap, KEYMAP. |
| 514 | The other arguments are passed along | 365 | The other arguments are passed along |
| 515 | or point to local variables of the previous function. | 366 | or point to local variables of the previous function. |
| 516 | If NOTREAL is nonzero, | 367 | If NOTREAL is nonzero, only check for equivalent key bindings, don't |
| 517 | don't bother really computing whether an item is enabled. | 368 | evaluate expressions in menu items and don't make any menu. |
| 518 | 369 | ||
| 519 | If we encounter submenus deeper than MAXDEPTH levels, ignore them. */ | 370 | If we encounter submenus deeper than MAXDEPTH levels, ignore them. */ |
| 520 | 371 | ||
| @@ -526,88 +377,33 @@ single_keymap_panes (keymap, pane_name, prefix, notreal, maxdepth) | |||
| 526 | int notreal; | 377 | int notreal; |
| 527 | int maxdepth; | 378 | int maxdepth; |
| 528 | { | 379 | { |
| 529 | Lisp_Object pending_maps; | 380 | Lisp_Object pending_maps = Qnil; |
| 530 | Lisp_Object tail, item, item1, item_string, table; | 381 | Lisp_Object tail, item; |
| 531 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | 382 | struct gcpro gcpro1, gcpro2; |
| 383 | int notbuttons = 0; | ||
| 532 | 384 | ||
| 533 | if (maxdepth <= 0) | 385 | if (maxdepth <= 0) |
| 534 | return; | 386 | return; |
| 535 | 387 | ||
| 536 | pending_maps = Qnil; | ||
| 537 | |||
| 538 | push_menu_pane (pane_name, prefix); | 388 | push_menu_pane (pane_name, prefix); |
| 539 | 389 | ||
| 390 | #ifndef HAVE_BOXES | ||
| 391 | /* Remember index for first item in this pane so we can go back and | ||
| 392 | add a prefix when (if) we see the first button. After that, notbuttons | ||
| 393 | is set to 0, to mark that we have seen a button and all non button | ||
| 394 | items need a prefix. */ | ||
| 395 | notbuttons = menu_items_used; | ||
| 396 | #endif | ||
| 397 | |||
| 540 | for (tail = keymap; CONSP (tail); tail = XCONS (tail)->cdr) | 398 | for (tail = keymap; CONSP (tail); tail = XCONS (tail)->cdr) |
| 541 | { | 399 | { |
| 542 | /* Look at each key binding, and if it has a menu string, | 400 | GCPRO2 (keymap, pending_maps); |
| 543 | make a menu item from it. */ | 401 | /* Look at each key binding, and if it is a menu item add it |
| 402 | to this menu. */ | ||
| 544 | item = XCONS (tail)->car; | 403 | item = XCONS (tail)->car; |
| 545 | if (CONSP (item)) | 404 | if (CONSP (item)) |
| 546 | { | 405 | single_menu_item (XCONS (item)->car, XCONS (item)->cdr, |
| 547 | item1 = XCONS (item)->cdr; | 406 | &pending_maps, notreal, maxdepth, ¬buttons); |
| 548 | if (CONSP (item1)) | ||
| 549 | { | ||
| 550 | item_string = XCONS (item1)->car; | ||
| 551 | if (STRINGP (item_string)) | ||
| 552 | { | ||
| 553 | /* This is the real definition--the function to run. */ | ||
| 554 | Lisp_Object def; | ||
| 555 | /* These are the saved equivalent keyboard key sequence | ||
| 556 | and its key-description. */ | ||
| 557 | Lisp_Object descrip; | ||
| 558 | Lisp_Object tem, enabled; | ||
| 559 | |||
| 560 | /* GCPRO because ...enabled_p will call eval | ||
| 561 | and ..._equiv_key may autoload something. | ||
| 562 | Protecting KEYMAP preserves everything we use; | ||
| 563 | aside from that, must protect whatever might be | ||
| 564 | a string. Since there's no GCPRO5, we refetch | ||
| 565 | item_string instead of protecting it. */ | ||
| 566 | descrip = def = Qnil; | ||
| 567 | GCPRO4 (keymap, pending_maps, def, descrip); | ||
| 568 | |||
| 569 | def = menu_item_equiv_key (item_string, item1, &descrip); | ||
| 570 | enabled = menu_item_enabled_p (def, notreal); | ||
| 571 | |||
| 572 | UNGCPRO; | ||
| 573 | |||
| 574 | item_string = XCONS (item1)->car; | ||
| 575 | |||
| 576 | tem = Fkeymapp (def); | ||
| 577 | if (XSTRING (item_string)->data[0] == '@' && !NILP (tem)) | ||
| 578 | pending_maps = Fcons (Fcons (def, Fcons (item_string, XCONS (item)->car)), | ||
| 579 | pending_maps); | ||
| 580 | else | ||
| 581 | { | ||
| 582 | Lisp_Object submap; | ||
| 583 | GCPRO4 (keymap, pending_maps, descrip, item_string); | ||
| 584 | submap = get_keymap_1 (def, 0, 1); | ||
| 585 | UNGCPRO; | ||
| 586 | #ifndef USE_X_TOOLKIT | ||
| 587 | /* Indicate visually that this is a submenu. */ | ||
| 588 | if (!NILP (submap)) | ||
| 589 | item_string = concat2 (item_string, | ||
| 590 | build_string (" >")); | ||
| 591 | #endif | ||
| 592 | /* If definition is nil, pass nil as the key. */ | ||
| 593 | push_menu_item (item_string, enabled, | ||
| 594 | XCONS (item)->car, def, | ||
| 595 | descrip); | ||
| 596 | #ifdef USE_X_TOOLKIT | ||
| 597 | /* Display a submenu using the toolkit. */ | ||
| 598 | if (! NILP (submap)) | ||
| 599 | { | ||
| 600 | push_submenu_start (); | ||
| 601 | single_keymap_panes (submap, Qnil, | ||
| 602 | XCONS (item)->car, notreal, | ||
| 603 | maxdepth - 1); | ||
| 604 | push_submenu_end (); | ||
| 605 | } | ||
| 606 | #endif | ||
| 607 | } | ||
| 608 | } | ||
| 609 | } | ||
| 610 | } | ||
| 611 | else if (VECTORP (item)) | 407 | else if (VECTORP (item)) |
| 612 | { | 408 | { |
| 613 | /* Loop over the char values represented in the vector. */ | 409 | /* Loop over the char values represented in the vector. */ |
| @@ -617,68 +413,11 @@ single_keymap_panes (keymap, pane_name, prefix, notreal, maxdepth) | |||
| 617 | { | 413 | { |
| 618 | Lisp_Object character; | 414 | Lisp_Object character; |
| 619 | XSETFASTINT (character, c); | 415 | XSETFASTINT (character, c); |
| 620 | item1 = XVECTOR (item)->contents[c]; | 416 | single_menu_item (character, XVECTOR (item)->contents[c], |
| 621 | if (CONSP (item1)) | 417 | &pending_maps, notreal, maxdepth, ¬buttons); |
| 622 | { | ||
| 623 | item_string = XCONS (item1)->car; | ||
| 624 | if (STRINGP (item_string)) | ||
| 625 | { | ||
| 626 | Lisp_Object def; | ||
| 627 | |||
| 628 | /* These are the saved equivalent keyboard key sequence | ||
| 629 | and its key-description. */ | ||
| 630 | Lisp_Object descrip; | ||
| 631 | Lisp_Object tem, enabled; | ||
| 632 | |||
| 633 | /* GCPRO because ...enabled_p will call eval | ||
| 634 | and ..._equiv_key may autoload something. | ||
| 635 | Protecting KEYMAP preserves everything we use; | ||
| 636 | aside from that, must protect whatever might be | ||
| 637 | a string. Since there's no GCPRO5, we refetch | ||
| 638 | item_string instead of protecting it. */ | ||
| 639 | GCPRO4 (keymap, pending_maps, def, descrip); | ||
| 640 | descrip = def = Qnil; | ||
| 641 | |||
| 642 | def = menu_item_equiv_key (item_string, item1, &descrip); | ||
| 643 | enabled = menu_item_enabled_p (def, notreal); | ||
| 644 | |||
| 645 | UNGCPRO; | ||
| 646 | |||
| 647 | item_string = XCONS (item1)->car; | ||
| 648 | |||
| 649 | tem = Fkeymapp (def); | ||
| 650 | if (XSTRING (item_string)->data[0] == '@' && !NILP (tem)) | ||
| 651 | pending_maps = Fcons (Fcons (def, Fcons (item_string, character)), | ||
| 652 | pending_maps); | ||
| 653 | else | ||
| 654 | { | ||
| 655 | Lisp_Object submap; | ||
| 656 | GCPRO4 (keymap, pending_maps, descrip, item_string); | ||
| 657 | submap = get_keymap_1 (def, 0, 1); | ||
| 658 | UNGCPRO; | ||
| 659 | #ifndef USE_X_TOOLKIT | ||
| 660 | if (!NILP (submap)) | ||
| 661 | item_string = concat2 (item_string, | ||
| 662 | build_string (" >")); | ||
| 663 | #endif | ||
| 664 | /* If definition is nil, pass nil as the key. */ | ||
| 665 | push_menu_item (item_string, enabled, character, | ||
| 666 | def, descrip); | ||
| 667 | #ifdef USE_X_TOOLKIT | ||
| 668 | if (! NILP (submap)) | ||
| 669 | { | ||
| 670 | push_submenu_start (); | ||
| 671 | single_keymap_panes (submap, Qnil, | ||
| 672 | character, notreal, | ||
| 673 | maxdepth - 1); | ||
| 674 | push_submenu_end (); | ||
| 675 | } | ||
| 676 | #endif | ||
| 677 | } | ||
| 678 | } | ||
| 679 | } | ||
| 680 | } | 418 | } |
| 681 | } | 419 | } |
| 420 | UNGCPRO; | ||
| 682 | } | 421 | } |
| 683 | 422 | ||
| 684 | /* Process now any submenus which want to be panes at this level. */ | 423 | /* Process now any submenus which want to be panes at this level. */ |
| @@ -696,6 +435,144 @@ single_keymap_panes (keymap, pane_name, prefix, notreal, maxdepth) | |||
| 696 | } | 435 | } |
| 697 | } | 436 | } |
| 698 | 437 | ||
| 438 | /* This is a subroutine of single_keymap_panes that handles one | ||
| 439 | keymap entry. | ||
| 440 | KEY is a key in a keymap and ITEM is its binding. | ||
| 441 | PENDING_MAPS_PTR points to a list of keymaps waiting to be made into | ||
| 442 | separate panes. | ||
| 443 | If NOTREAL is nonzero, only check for equivalent key bindings, don't | ||
| 444 | evaluate expressions in menu items and don't make any menu. | ||
| 445 | If we encounter submenus deeper than MAXDEPTH levels, ignore them. | ||
| 446 | NOTBUTTONS_PTR is only used when simulating toggle boxes and radio | ||
| 447 | buttons. It points to variable notbuttons in single_keymap_panes, | ||
| 448 | which keeps track of if we have seen a button in this menu or not. */ | ||
| 449 | |||
| 450 | static void | ||
| 451 | single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth, | ||
| 452 | notbuttons_ptr) | ||
| 453 | Lisp_Object key, item; | ||
| 454 | Lisp_Object *pending_maps_ptr; | ||
| 455 | int maxdepth, notreal; | ||
| 456 | int *notbuttons_ptr; | ||
| 457 | { | ||
| 458 | Lisp_Object def, map, item_string, enabled; | ||
| 459 | struct gcpro gcpro1, gcpro2; | ||
| 460 | int res; | ||
| 461 | |||
| 462 | /* Parse the menu item and leave the result in item_properties. */ | ||
| 463 | GCPRO2 (key, item); | ||
| 464 | res = parse_menu_item (item, notreal, 0); | ||
| 465 | UNGCPRO; | ||
| 466 | if (!res) | ||
| 467 | return; /* Not a menu item. */ | ||
| 468 | |||
| 469 | map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP]; | ||
| 470 | |||
| 471 | if (notreal) | ||
| 472 | { | ||
| 473 | /* We don't want to make a menu, just traverse the keymaps to | ||
| 474 | precompute equivalent key bindings. */ | ||
| 475 | if (!NILP (map)) | ||
| 476 | single_keymap_panes (map, Qnil, key, 1, maxdepth - 1); | ||
| 477 | return; | ||
| 478 | } | ||
| 479 | |||
| 480 | enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE]; | ||
| 481 | item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME]; | ||
| 482 | |||
| 483 | if (!NILP (map) && XSTRING (item_string)->data[0] == '@') | ||
| 484 | { | ||
| 485 | if (!NILP (enabled)) | ||
| 486 | /* An enabled separate pane. Remember this to handle it later. */ | ||
| 487 | *pending_maps_ptr = Fcons (Fcons (map, Fcons (item_string, key)), | ||
| 488 | *pending_maps_ptr); | ||
| 489 | return; | ||
| 490 | } | ||
| 491 | |||
| 492 | #ifndef HAVE_BOXES | ||
| 493 | /* Simulate radio buttons and toggle boxes by putting a prefix in | ||
| 494 | front of them. */ | ||
| 495 | { | ||
| 496 | Lisp_Object prefix = Qnil; | ||
| 497 | Lisp_Object type = XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE]; | ||
| 498 | if (!NILP (type)) | ||
| 499 | { | ||
| 500 | Lisp_Object selected | ||
| 501 | = XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED]; | ||
| 502 | |||
| 503 | if (*notbuttons_ptr) | ||
| 504 | /* The first button. Line up previous items in this menu. */ | ||
| 505 | { | ||
| 506 | int index = *notbuttons_ptr; /* Index for first item this menu. */ | ||
| 507 | int submenu = 0; | ||
| 508 | Lisp_Object tem; | ||
| 509 | while (index < menu_items_used) | ||
| 510 | { | ||
| 511 | tem | ||
| 512 | = XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME]; | ||
| 513 | if (NILP (tem)) | ||
| 514 | { | ||
| 515 | index++; | ||
| 516 | submenu++; /* Skip sub menu. */ | ||
| 517 | } | ||
| 518 | else if (EQ (tem, Qlambda)) | ||
| 519 | { | ||
| 520 | index++; | ||
| 521 | submenu--; /* End sub menu. */ | ||
| 522 | } | ||
| 523 | else if (EQ (tem, Qt)) | ||
| 524 | index += 3; /* Skip new pane marker. */ | ||
| 525 | else if (EQ (tem, Qquote)) | ||
| 526 | index++; /* Skip a left, right divider. */ | ||
| 527 | else | ||
| 528 | { | ||
| 529 | if (!submenu && XSTRING (tem)->data[0] != '\0' | ||
| 530 | && XSTRING (tem)->data[0] != '-') | ||
| 531 | XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME] | ||
| 532 | = concat2 (build_string (" "), tem); | ||
| 533 | index += MENU_ITEMS_ITEM_LENGTH; | ||
| 534 | } | ||
| 535 | } | ||
| 536 | *notbuttons_ptr = 0; | ||
| 537 | } | ||
| 538 | |||
| 539 | /* Calculate prefix, if any, for this item. */ | ||
| 540 | if (EQ (type, QCtoggle)) | ||
| 541 | prefix = build_string (NILP (selected) ? "[ ] " : "[X] "); | ||
| 542 | else if (EQ (type, QCradio)) | ||
| 543 | prefix = build_string (NILP (selected) ? "( ) " : "(*) "); | ||
| 544 | } | ||
| 545 | /* Not a button. If we have earlier buttons, then we need a prefix. */ | ||
| 546 | else if (!*notbuttons_ptr && XSTRING (item_string)->data[0] != '\0' | ||
| 547 | && XSTRING (item_string)->data[0] != '-') | ||
| 548 | prefix = build_string (" "); | ||
| 549 | |||
| 550 | if (!NILP (prefix)) | ||
| 551 | item_string = concat2 (prefix, item_string); | ||
| 552 | } | ||
| 553 | #endif /* not HAVE_BOXES */ | ||
| 554 | |||
| 555 | #ifndef USE_X_TOOLKIT | ||
| 556 | if (!NILP(map)) | ||
| 557 | /* Indicate visually that this is a submenu. */ | ||
| 558 | item_string = concat2 (item_string, build_string (" >")); | ||
| 559 | #endif | ||
| 560 | |||
| 561 | push_menu_item (item_string, enabled, key, | ||
| 562 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF], | ||
| 563 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ]); | ||
| 564 | |||
| 565 | #ifdef USE_X_TOOLKIT | ||
| 566 | /* Display a submenu using the toolkit. */ | ||
| 567 | if (! (NILP (map) || NILP (enabled))) | ||
| 568 | { | ||
| 569 | push_submenu_start (); | ||
| 570 | single_keymap_panes (map, Qnil, key, 0, maxdepth - 1); | ||
| 571 | push_submenu_end (); | ||
| 572 | } | ||
| 573 | #endif | ||
| 574 | } | ||
| 575 | |||
| 699 | /* Push all the panes and items of a menu described by the | 576 | /* Push all the panes and items of a menu described by the |
| 700 | alist-of-alists MENU. | 577 | alist-of-alists MENU. |
| 701 | This handles old-fashioned calls to x-popup-menu. */ | 578 | This handles old-fashioned calls to x-popup-menu. */ |
| @@ -2730,9 +2607,6 @@ syms_of_xmenu () | |||
| 2730 | staticpro (&menu_items); | 2607 | staticpro (&menu_items); |
| 2731 | menu_items = Qnil; | 2608 | menu_items = Qnil; |
| 2732 | 2609 | ||
| 2733 | Qmenu_alias = intern ("menu-alias"); | ||
| 2734 | staticpro (&Qmenu_alias); | ||
| 2735 | |||
| 2736 | Qdebug_on_next_call = intern ("debug-on-next-call"); | 2610 | Qdebug_on_next_call = intern ("debug-on-next-call"); |
| 2737 | staticpro (&Qdebug_on_next_call); | 2611 | staticpro (&Qdebug_on_next_call); |
| 2738 | 2612 | ||