diff options
| author | Richard M. Stallman | 1998-03-21 05:49:49 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1998-03-21 05:49:49 +0000 |
| commit | e8886a1d99b949b889f67d93bb2325a96be51429 (patch) | |
| tree | 864bdabeea25c94ba8fb299cf160dd9e5ef05f55 /src | |
| parent | 2db5082ff442ba59a7cbc572143910aa5d845f88 (diff) | |
| download | emacs-e8886a1d99b949b889f67d93bb2325a96be51429.tar.gz emacs-e8886a1d99b949b889f67d93bb2325a96be51429.zip | |
Include puresize.h for CHECK_IMPURE.
(parse_menu_item): New function.
(menu_item_eval_property_1, menu_item_eval_property) New suroutines.
(menu_bar_one_keymap): Moved some code to menu_bar_item.
(menu_bar_item): Rewritten to use parse_menu_item.
(menu_bar_item_1): Function deleted.
(QCenable, QCvisible, QChelp, QCfilter, QCbutton, QCtoggle, QCradio):
(Qmenu_alias): New variables.
(syms_of_keyboard): Initialize them, and item_properties.
Diffstat (limited to 'src')
| -rw-r--r-- | src/keyboard.c | 441 |
1 files changed, 370 insertions, 71 deletions
diff --git a/src/keyboard.c b/src/keyboard.c index 6e7eb42c7b9..6bb2b0c3627 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -39,6 +39,7 @@ Boston, MA 02111-1307, USA. */ | |||
| 39 | #include "syntax.h" | 39 | #include "syntax.h" |
| 40 | #include "intervals.h" | 40 | #include "intervals.h" |
| 41 | #include "blockinput.h" | 41 | #include "blockinput.h" |
| 42 | #include "puresize.h" | ||
| 42 | #include <setjmp.h> | 43 | #include <setjmp.h> |
| 43 | #include <errno.h> | 44 | #include <errno.h> |
| 44 | 45 | ||
| @@ -456,7 +457,12 @@ Lisp_Object Qmouse_wheel; | |||
| 456 | Lisp_Object Qevent_kind; | 457 | Lisp_Object Qevent_kind; |
| 457 | Lisp_Object Qevent_symbol_elements; | 458 | Lisp_Object Qevent_symbol_elements; |
| 458 | 459 | ||
| 460 | /* menu item parts */ | ||
| 461 | Lisp_Object Qmenu_alias; | ||
| 459 | Lisp_Object Qmenu_enable; | 462 | Lisp_Object Qmenu_enable; |
| 463 | Lisp_Object QCenable, QCvisible, QChelp, QCfilter, QCbutton, QCtoggle, QCradio; | ||
| 464 | extern Lisp_Object Vdefine_key_rebound_commands; | ||
| 465 | extern Lisp_Object Qmenu_item; | ||
| 460 | 466 | ||
| 461 | /* An event header symbol HEAD may have a property named | 467 | /* An event header symbol HEAD may have a property named |
| 462 | Qevent_symbol_element_mask, which is of the form (BASE MODIFIERS); | 468 | Qevent_symbol_element_mask, which is of the form (BASE MODIFIERS); |
| @@ -477,8 +483,6 @@ Lisp_Object Qvertical_line; | |||
| 477 | Lisp_Object Qvertical_scroll_bar; | 483 | Lisp_Object Qvertical_scroll_bar; |
| 478 | Lisp_Object Qmenu_bar; | 484 | Lisp_Object Qmenu_bar; |
| 479 | 485 | ||
| 480 | extern Lisp_Object Qmenu_enable; | ||
| 481 | |||
| 482 | Lisp_Object recursive_edit_unwind (), command_loop (); | 486 | Lisp_Object recursive_edit_unwind (), command_loop (); |
| 483 | Lisp_Object Fthis_command_keys (); | 487 | Lisp_Object Fthis_command_keys (); |
| 484 | Lisp_Object Qextended_command_history; | 488 | Lisp_Object Qextended_command_history; |
| @@ -3505,7 +3509,7 @@ char *lispy_function_keys[] = | |||
| 3505 | 3509 | ||
| 3506 | /* | 3510 | /* |
| 3507 | * VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys. | 3511 | * VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys. |
| 3508 | * Used only as parameters to GetAsyncKeyState() and GetKeyState(). | 3512 | * Used only as parameters to GetAsyncKeyState and GetKeyState. |
| 3509 | * No other API or message will distinguish left and right keys this way. | 3513 | * No other API or message will distinguish left and right keys this way. |
| 3510 | */ | 3514 | */ |
| 3511 | /* 0xA0 .. 0xEF */ | 3515 | /* 0xA0 .. 0xEF */ |
| @@ -4114,12 +4118,12 @@ make_lispy_event (event) | |||
| 4114 | portion_whole = Fcons (event->x, event->y); | 4118 | portion_whole = Fcons (event->x, event->y); |
| 4115 | part = *scroll_bar_parts[(int) event->part]; | 4119 | part = *scroll_bar_parts[(int) event->part]; |
| 4116 | 4120 | ||
| 4117 | position = | 4121 | position |
| 4118 | Fcons (window, | 4122 | = Fcons (window, |
| 4119 | Fcons (Qvertical_scroll_bar, | 4123 | Fcons (Qvertical_scroll_bar, |
| 4120 | Fcons (portion_whole, | 4124 | Fcons (portion_whole, |
| 4121 | Fcons (make_number (event->timestamp), | 4125 | Fcons (make_number (event->timestamp), |
| 4122 | Fcons (part, Qnil))))); | 4126 | Fcons (part, Qnil))))); |
| 4123 | } | 4127 | } |
| 4124 | 4128 | ||
| 4125 | /* Always treat W32 scroll bar events as clicks. */ | 4129 | /* Always treat W32 scroll bar events as clicks. */ |
| @@ -5084,7 +5088,7 @@ read_avail_input (expected) | |||
| 5084 | #endif | 5088 | #endif |
| 5085 | /* POSIX infers that processes which are not in the session leader's | 5089 | /* POSIX infers that processes which are not in the session leader's |
| 5086 | process group won't get SIGHUP's at logout time. BSDI adheres to | 5090 | process group won't get SIGHUP's at logout time. BSDI adheres to |
| 5087 | this part standard and returns -1 from read(0) with errno==EIO | 5091 | this part standard and returns -1 from read (0) with errno==EIO |
| 5088 | when the control tty is taken away. | 5092 | when the control tty is taken away. |
| 5089 | Jeffrey Honig <jch@bsdi.com> says this is generally safe. */ | 5093 | Jeffrey Honig <jch@bsdi.com> says this is generally safe. */ |
| 5090 | if (nread == -1 && errno == EIO) | 5094 | if (nread == -1 && errno == EIO) |
| @@ -5398,25 +5402,14 @@ static void | |||
| 5398 | menu_bar_one_keymap (keymap) | 5402 | menu_bar_one_keymap (keymap) |
| 5399 | Lisp_Object keymap; | 5403 | Lisp_Object keymap; |
| 5400 | { | 5404 | { |
| 5401 | Lisp_Object tail, item, key, binding, item_string, table; | 5405 | Lisp_Object tail, item, table; |
| 5402 | 5406 | ||
| 5403 | /* Loop over all keymap entries that have menu strings. */ | 5407 | /* Loop over all keymap entries that have menu strings. */ |
| 5404 | for (tail = keymap; CONSP (tail); tail = XCONS (tail)->cdr) | 5408 | for (tail = keymap; CONSP (tail); tail = XCONS (tail)->cdr) |
| 5405 | { | 5409 | { |
| 5406 | item = XCONS (tail)->car; | 5410 | item = XCONS (tail)->car; |
| 5407 | if (CONSP (item)) | 5411 | if (CONSP (item)) |
| 5408 | { | 5412 | menu_bar_item (XCONS (item)->car, XCONS (item)->cdr); |
| 5409 | key = XCONS (item)->car; | ||
| 5410 | binding = XCONS (item)->cdr; | ||
| 5411 | if (CONSP (binding)) | ||
| 5412 | { | ||
| 5413 | item_string = XCONS (binding)->car; | ||
| 5414 | if (STRINGP (item_string)) | ||
| 5415 | menu_bar_item (key, item_string, Fcdr (binding)); | ||
| 5416 | } | ||
| 5417 | else if (EQ (binding, Qundefined)) | ||
| 5418 | menu_bar_item (key, Qnil, binding); | ||
| 5419 | } | ||
| 5420 | else if (VECTORP (item)) | 5413 | else if (VECTORP (item)) |
| 5421 | { | 5414 | { |
| 5422 | /* Loop over the char values represented in the vector. */ | 5415 | /* Loop over the char values represented in the vector. */ |
| @@ -5426,45 +5419,25 @@ menu_bar_one_keymap (keymap) | |||
| 5426 | { | 5419 | { |
| 5427 | Lisp_Object character; | 5420 | Lisp_Object character; |
| 5428 | XSETFASTINT (character, c); | 5421 | XSETFASTINT (character, c); |
| 5429 | binding = XVECTOR (item)->contents[c]; | 5422 | menu_bar_item (character, XVECTOR (item)->contents[c]); |
| 5430 | if (CONSP (binding)) | ||
| 5431 | { | ||
| 5432 | item_string = XCONS (binding)->car; | ||
| 5433 | if (STRINGP (item_string)) | ||
| 5434 | menu_bar_item (key, item_string, Fcdr (binding)); | ||
| 5435 | } | ||
| 5436 | else if (EQ (binding, Qundefined)) | ||
| 5437 | menu_bar_item (key, Qnil, binding); | ||
| 5438 | } | 5423 | } |
| 5439 | } | 5424 | } |
| 5440 | } | 5425 | } |
| 5441 | } | 5426 | } |
| 5442 | 5427 | ||
| 5443 | /* This is used as the handler when calling internal_condition_case_1. */ | ||
| 5444 | |||
| 5445 | static Lisp_Object | ||
| 5446 | menu_bar_item_1 (arg) | ||
| 5447 | Lisp_Object arg; | ||
| 5448 | { | ||
| 5449 | return Qnil; | ||
| 5450 | } | ||
| 5451 | |||
| 5452 | /* Add one item to menu_bar_items_vector, for KEY, ITEM_STRING and DEF. | 5428 | /* Add one item to menu_bar_items_vector, for KEY, ITEM_STRING and DEF. |
| 5453 | If there's already an item for KEY, add this DEF to it. */ | 5429 | If there's already an item for KEY, add this DEF to it. */ |
| 5454 | 5430 | ||
| 5431 | Lisp_Object item_properties; | ||
| 5432 | |||
| 5455 | static void | 5433 | static void |
| 5456 | menu_bar_item (key, item_string, def) | 5434 | menu_bar_item (key, item) |
| 5457 | Lisp_Object key, item_string, def; | 5435 | Lisp_Object key, item; |
| 5458 | { | 5436 | { |
| 5459 | Lisp_Object tem; | 5437 | struct gcpro gcpro1; |
| 5460 | Lisp_Object enabled; | ||
| 5461 | int i; | 5438 | int i; |
| 5462 | 5439 | ||
| 5463 | /* Skip menu-bar equiv keys data. */ | 5440 | if (EQ (item, Qundefined)) |
| 5464 | if (CONSP (def) && CONSP (XCONS (def)->car)) | ||
| 5465 | def = XCONS (def)->cdr; | ||
| 5466 | |||
| 5467 | if (EQ (def, Qundefined)) | ||
| 5468 | { | 5441 | { |
| 5469 | /* If a map has an explicit `undefined' as definition, | 5442 | /* If a map has an explicit `undefined' as definition, |
| 5470 | discard any previously made menu bar item. */ | 5443 | discard any previously made menu bar item. */ |
| @@ -5485,25 +5458,14 @@ menu_bar_item (key, item_string, def) | |||
| 5485 | return; | 5458 | return; |
| 5486 | } | 5459 | } |
| 5487 | 5460 | ||
| 5488 | /* See if this entry is enabled. */ | 5461 | GCPRO1 (key); /* Is this necessary? */ |
| 5489 | enabled = Qt; | 5462 | i = parse_menu_item (item, 0, 1); |
| 5490 | 5463 | UNGCPRO; | |
| 5491 | if (SYMBOLP (def)) | 5464 | if (!i) |
| 5492 | { | ||
| 5493 | /* No property, or nil, means enable. | ||
| 5494 | Otherwise, enable if value is not nil. */ | ||
| 5495 | tem = Fget (def, Qmenu_enable); | ||
| 5496 | if (!NILP (tem)) | ||
| 5497 | /* (condition-case nil (eval tem) | ||
| 5498 | (error nil)) */ | ||
| 5499 | enabled = internal_condition_case_1 (Feval, tem, Qerror, | ||
| 5500 | menu_bar_item_1); | ||
| 5501 | } | ||
| 5502 | |||
| 5503 | /* Ignore this item if it's not enabled. */ | ||
| 5504 | if (NILP (enabled)) | ||
| 5505 | return; | 5465 | return; |
| 5506 | 5466 | ||
| 5467 | item = XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF]; | ||
| 5468 | |||
| 5507 | /* Find any existing item for this KEY. */ | 5469 | /* Find any existing item for this KEY. */ |
| 5508 | for (i = 0; i < menu_bar_items_index; i += 4) | 5470 | for (i = 0; i < menu_bar_items_index; i += 4) |
| 5509 | if (EQ (key, XVECTOR (menu_bar_items_vector)->contents[i])) | 5471 | if (EQ (key, XVECTOR (menu_bar_items_vector)->contents[i])) |
| @@ -5522,22 +5484,342 @@ menu_bar_item (key, item_string, def) | |||
| 5522 | XVECTOR (tem)->contents, i * sizeof (Lisp_Object)); | 5484 | XVECTOR (tem)->contents, i * sizeof (Lisp_Object)); |
| 5523 | menu_bar_items_vector = tem; | 5485 | menu_bar_items_vector = tem; |
| 5524 | } | 5486 | } |
| 5487 | |||
| 5525 | /* Add this item. */ | 5488 | /* Add this item. */ |
| 5526 | XVECTOR (menu_bar_items_vector)->contents[i++] = key; | 5489 | XVECTOR (menu_bar_items_vector)->contents[i++] = key; |
| 5527 | XVECTOR (menu_bar_items_vector)->contents[i++] = item_string; | 5490 | XVECTOR (menu_bar_items_vector)->contents[i++] |
| 5528 | XVECTOR (menu_bar_items_vector)->contents[i++] = Fcons (def, Qnil); | 5491 | = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME]; |
| 5492 | XVECTOR (menu_bar_items_vector)->contents[i++] = Fcons (item, Qnil); | ||
| 5529 | XVECTOR (menu_bar_items_vector)->contents[i++] = make_number (0); | 5493 | XVECTOR (menu_bar_items_vector)->contents[i++] = make_number (0); |
| 5530 | menu_bar_items_index = i; | 5494 | menu_bar_items_index = i; |
| 5531 | } | 5495 | } |
| 5532 | /* We did find an item for this KEY. Add DEF to its list of maps. */ | 5496 | /* We did find an item for this KEY. Add ITEM to its list of maps. */ |
| 5533 | else | 5497 | else |
| 5534 | { | 5498 | { |
| 5535 | Lisp_Object old; | 5499 | Lisp_Object old; |
| 5536 | old = XVECTOR (menu_bar_items_vector)->contents[i + 2]; | 5500 | old = XVECTOR (menu_bar_items_vector)->contents[i + 2]; |
| 5537 | XVECTOR (menu_bar_items_vector)->contents[i + 2] = Fcons (def, old); | 5501 | XVECTOR (menu_bar_items_vector)->contents[i + 2] = Fcons (item, old); |
| 5538 | } | 5502 | } |
| 5539 | } | 5503 | } |
| 5540 | 5504 | ||
| 5505 | /* This is used as the handler when calling menu_item_eval_property. */ | ||
| 5506 | static Lisp_Object | ||
| 5507 | menu_item_eval_property_1 (arg) | ||
| 5508 | Lisp_Object arg; | ||
| 5509 | { | ||
| 5510 | /* If we got a quit from within the menu computation, | ||
| 5511 | quit all the way out of it. This takes care of C-] in the debugger. */ | ||
| 5512 | if (CONSP (arg) && EQ (XCONS (arg)->car, Qquit)) | ||
| 5513 | Fsignal (Qquit, Qnil); | ||
| 5514 | |||
| 5515 | return Qnil; | ||
| 5516 | } | ||
| 5517 | |||
| 5518 | /* Evaluate an expression and return the result (or nil if something | ||
| 5519 | went wrong). Used to evaluate dynamic parts of menu items. */ | ||
| 5520 | static Lisp_Object | ||
| 5521 | menu_item_eval_property (sexpr) | ||
| 5522 | Lisp_Object sexpr; | ||
| 5523 | { | ||
| 5524 | Lisp_Object val; | ||
| 5525 | val = internal_condition_case_1 (Feval, sexpr, Qerror, | ||
| 5526 | menu_item_eval_property_1); | ||
| 5527 | return val; | ||
| 5528 | } | ||
| 5529 | |||
| 5530 | /* This function parses a menu item and leaves the result in the | ||
| 5531 | vector item_properties. | ||
| 5532 | ITEM is a key binding, a possible menu item. | ||
| 5533 | If NOTREAL is nonzero, only check for equivalent key bindings, don't | ||
| 5534 | evaluate dynamic expressions in the menu item. | ||
| 5535 | INMENUBAR is true when this is considered for an entry in a menu bar | ||
| 5536 | top level. | ||
| 5537 | parse_menu_item returns true if the item is a menu item and false | ||
| 5538 | otherwise. */ | ||
| 5539 | |||
| 5540 | int | ||
| 5541 | parse_menu_item (item, notreal, inmenubar) | ||
| 5542 | Lisp_Object item; | ||
| 5543 | int notreal, inmenubar; | ||
| 5544 | { | ||
| 5545 | Lisp_Object def, tem; | ||
| 5546 | |||
| 5547 | Lisp_Object type = Qnil; | ||
| 5548 | Lisp_Object cachelist = Qnil; | ||
| 5549 | Lisp_Object filter = Qnil; | ||
| 5550 | Lisp_Object item_string, start; | ||
| 5551 | int i; | ||
| 5552 | struct gcpro gcpro1, gcpro2, gcpro3; | ||
| 5553 | |||
| 5554 | #define RET0 \ | ||
| 5555 | if (1) \ | ||
| 5556 | { \ | ||
| 5557 | UNGCPRO; \ | ||
| 5558 | return 0; \ | ||
| 5559 | } \ | ||
| 5560 | else | ||
| 5561 | |||
| 5562 | if (!CONSP (item)) | ||
| 5563 | return 0; | ||
| 5564 | |||
| 5565 | GCPRO3 (item, notreal, inmenubar); | ||
| 5566 | |||
| 5567 | /* Create item_properties vector if necessary. */ | ||
| 5568 | if (NILP (item_properties)) | ||
| 5569 | item_properties | ||
| 5570 | = Fmake_vector (make_number (ITEM_PROPERTY_ENABLE + 1), Qnil); | ||
| 5571 | |||
| 5572 | /* Initialize optional entries. */ | ||
| 5573 | for (i = ITEM_PROPERTY_DEF; i < ITEM_PROPERTY_ENABLE; i++) | ||
| 5574 | XVECTOR (item_properties)->contents[i] = Qnil; | ||
| 5575 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE] = Qt; | ||
| 5576 | |||
| 5577 | /* Save the item here to protect it from GC. */ | ||
| 5578 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_ITEM] = item; | ||
| 5579 | |||
| 5580 | item_string = XCONS (item)->car; | ||
| 5581 | |||
| 5582 | start = item; | ||
| 5583 | item = XCONS (item)->cdr; | ||
| 5584 | if (STRINGP (item_string)) | ||
| 5585 | { | ||
| 5586 | /* Old format menu item. */ | ||
| 5587 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME] = item_string; | ||
| 5588 | |||
| 5589 | /* Maybe help string. */ | ||
| 5590 | if (CONSP (item) && STRINGP (XCONS (item)->car)) | ||
| 5591 | { | ||
| 5592 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP] | ||
| 5593 | = XCONS (item)->car; | ||
| 5594 | start = item; | ||
| 5595 | item = XCONS (item)->cdr; | ||
| 5596 | } | ||
| 5597 | |||
| 5598 | /* Maybee key binding cache. */ | ||
| 5599 | if (CONSP (item) && CONSP (XCONS (item)->car) | ||
| 5600 | && (NILP (XCONS (XCONS (item)->car)->car) | ||
| 5601 | || VECTORP (XCONS (XCONS (item)->car)->car))) | ||
| 5602 | { | ||
| 5603 | cachelist = XCONS (item)->car; | ||
| 5604 | item = XCONS (item)->cdr; | ||
| 5605 | } | ||
| 5606 | |||
| 5607 | /* This is the real definition--the function to run. */ | ||
| 5608 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF] = item; | ||
| 5609 | |||
| 5610 | /* Get enable property, if any. */ | ||
| 5611 | if (SYMBOLP (item)) | ||
| 5612 | { | ||
| 5613 | tem = Fget (item, Qmenu_enable); | ||
| 5614 | if (!NILP (tem)) | ||
| 5615 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE] = tem; | ||
| 5616 | } | ||
| 5617 | } | ||
| 5618 | else if (EQ (item_string, Qmenu_item) && CONSP (item)) | ||
| 5619 | { | ||
| 5620 | /* New format menu item. */ | ||
| 5621 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME] | ||
| 5622 | = XCONS (item)->car; | ||
| 5623 | start = XCONS (item)->cdr; | ||
| 5624 | if (CONSP (start)) | ||
| 5625 | { | ||
| 5626 | /* We have a real binding. */ | ||
| 5627 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF] | ||
| 5628 | = XCONS (start)->car; | ||
| 5629 | |||
| 5630 | item = XCONS (start)->cdr; | ||
| 5631 | /* Is there a cache list with key equivalences. */ | ||
| 5632 | if (CONSP (item) && CONSP (XCONS (item)->car)) | ||
| 5633 | { | ||
| 5634 | cachelist = XCONS (item)->car; | ||
| 5635 | item = XCONS (item)->cdr; | ||
| 5636 | } | ||
| 5637 | |||
| 5638 | /* Parse properties. */ | ||
| 5639 | while (CONSP (item) && CONSP (XCONS (item)->cdr)) | ||
| 5640 | { | ||
| 5641 | tem = XCONS (item)->car; | ||
| 5642 | item = XCONS (item)->cdr; | ||
| 5643 | |||
| 5644 | if (EQ (tem, QCenable)) | ||
| 5645 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE] | ||
| 5646 | = XCONS (item)->car; | ||
| 5647 | else if (EQ (tem, QCvisible) && !notreal) | ||
| 5648 | { | ||
| 5649 | /* If got a visible property and that evaluates to nil | ||
| 5650 | then ignore this item. */ | ||
| 5651 | tem = menu_item_eval_property (XCONS (item)->car); | ||
| 5652 | if (NILP (tem)) | ||
| 5653 | RET0; | ||
| 5654 | } | ||
| 5655 | else if (EQ (tem, QChelp)) | ||
| 5656 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP] | ||
| 5657 | = XCONS (item)->car; | ||
| 5658 | else if (EQ (tem, QCfilter)) | ||
| 5659 | filter = XCONS (item)->car; | ||
| 5660 | else if (EQ (tem, QCbutton) && CONSP (XCONS (item)->car)) | ||
| 5661 | { | ||
| 5662 | tem = XCONS (item)->car; | ||
| 5663 | type = XCONS (tem)->car; | ||
| 5664 | if (EQ (type, QCtoggle) || EQ (type, QCradio)) | ||
| 5665 | { | ||
| 5666 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED] | ||
| 5667 | = XCONS (tem)->cdr; | ||
| 5668 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE] | ||
| 5669 | = type; | ||
| 5670 | } | ||
| 5671 | } | ||
| 5672 | item = XCONS (item)->cdr; | ||
| 5673 | } | ||
| 5674 | } | ||
| 5675 | else if (inmenubar || !NILP (start)) | ||
| 5676 | RET0; | ||
| 5677 | } | ||
| 5678 | else | ||
| 5679 | RET0; | ||
| 5680 | |||
| 5681 | /* If item string is not a string, evaluate it to get string. | ||
| 5682 | If we don't get a string, skip this item. */ | ||
| 5683 | item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME]; | ||
| 5684 | if (!(STRINGP (item_string) || notreal)) | ||
| 5685 | { | ||
| 5686 | item_string = menu_item_eval_property (item_string); | ||
| 5687 | if (!STRINGP (item_string)) | ||
| 5688 | RET0; | ||
| 5689 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME] = item_string; | ||
| 5690 | } | ||
| 5691 | |||
| 5692 | /* If got a filter apply it on definition. */ | ||
| 5693 | def = XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF]; | ||
| 5694 | if (!NILP (filter)) | ||
| 5695 | { | ||
| 5696 | def = menu_item_eval_property (Fcons (filter, Fcons (def, Qnil))); | ||
| 5697 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF] = def; | ||
| 5698 | } | ||
| 5699 | |||
| 5700 | /* If we got no definition, this item is just unselectable text which | ||
| 5701 | is ok when in a submenu and if there is an item string. */ | ||
| 5702 | item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME]; | ||
| 5703 | if (NILP (def)) | ||
| 5704 | { | ||
| 5705 | UNGCPRO; | ||
| 5706 | return (!inmenubar && STRINGP (item_string) ? 1 : 0); | ||
| 5707 | } | ||
| 5708 | |||
| 5709 | /* Enable or disable selection of item. */ | ||
| 5710 | tem = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE]; | ||
| 5711 | if (!EQ (tem, Qt)) | ||
| 5712 | { | ||
| 5713 | if (notreal) | ||
| 5714 | tem = Qt; | ||
| 5715 | else | ||
| 5716 | tem = menu_item_eval_property (tem); | ||
| 5717 | if (inmenubar && NILP (tem)) | ||
| 5718 | RET0; /* Ignore disabled items in menu bar. */ | ||
| 5719 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE] = tem; | ||
| 5720 | } | ||
| 5721 | |||
| 5722 | /* See if this is a separate pane or a submenu. */ | ||
| 5723 | tem = get_keymap_1 (def, 0, 1); | ||
| 5724 | if (!NILP (tem)) | ||
| 5725 | { | ||
| 5726 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP] = tem; | ||
| 5727 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF] = tem; | ||
| 5728 | UNGCPRO; | ||
| 5729 | return 1; | ||
| 5730 | } | ||
| 5731 | else if (inmenubar) | ||
| 5732 | RET0; /* Entries in menu bar must be submenus. */ | ||
| 5733 | |||
| 5734 | /* This is a command. See if there is an equivalent key binding. */ | ||
| 5735 | if (NILP (cachelist)) | ||
| 5736 | { | ||
| 5737 | /* We have to create a cachelist. */ | ||
| 5738 | CHECK_IMPURE (start); | ||
| 5739 | XCONS (start)->cdr = Fcons (Fcons (Qnil, Qnil), XCONS (start)->cdr); | ||
| 5740 | cachelist = XCONS (XCONS (start)->cdr)->car; | ||
| 5741 | /* We have not checked this before so check it now. */ | ||
| 5742 | tem = def; | ||
| 5743 | } | ||
| 5744 | else if (VECTORP (XCONS (cachelist)->car)) /* Saved key */ | ||
| 5745 | { | ||
| 5746 | tem = Fkey_binding (XCONS (cachelist)->car, Qnil); | ||
| 5747 | if (EQ (tem, def) | ||
| 5748 | /* If the command is an alias for another | ||
| 5749 | (such as easymenu.el and lmenu.el set it up), | ||
| 5750 | check if the original command matches the cached command. */ | ||
| 5751 | || (SYMBOLP (def) && EQ (tem, XSYMBOL (def)->function))) | ||
| 5752 | tem = Qnil; /* Don't need to recompute key binding. */ | ||
| 5753 | else | ||
| 5754 | tem = def; | ||
| 5755 | } | ||
| 5756 | /* If something had no key binding before, don't recheck it | ||
| 5757 | because that is too slow--except if we have a list of rebound | ||
| 5758 | commands in Vdefine_key_rebound_commands, do recheck any command | ||
| 5759 | that appears in that list. */ | ||
| 5760 | else if (!NILP (XCONS (cachelist)->car)) | ||
| 5761 | tem = def; /* Should signal an error here. */ | ||
| 5762 | else if ( | ||
| 5763 | /* Should we check everything when precomputing key bindings? */ | ||
| 5764 | /* notreal || */ | ||
| 5765 | CONSP (Vdefine_key_rebound_commands) | ||
| 5766 | && !NILP (Fmemq (def, Vdefine_key_rebound_commands))) | ||
| 5767 | tem = def; | ||
| 5768 | else | ||
| 5769 | tem = Qnil; | ||
| 5770 | |||
| 5771 | if (!NILP (tem)) | ||
| 5772 | { | ||
| 5773 | /* Recompute equivalent key binding. | ||
| 5774 | If the command is an alias for another | ||
| 5775 | (such as easymenu.el and lmenu.el set it up), | ||
| 5776 | see if the original command name has equivalent keys. | ||
| 5777 | Otherwise look up the specified command itself. | ||
| 5778 | We don't try both, because that makes easymenu menus slow. */ | ||
| 5779 | if (SYMBOLP (def) && SYMBOLP (XSYMBOL (def)->function) | ||
| 5780 | && ! NILP (Fget (def, Qmenu_alias))) | ||
| 5781 | tem = XSYMBOL (def)->function; | ||
| 5782 | tem = Fwhere_is_internal (tem, Qnil, Qt, Qnil); | ||
| 5783 | XCONS (cachelist)->car = tem; | ||
| 5784 | XCONS (cachelist)->cdr | ||
| 5785 | = (NILP (tem) ? Qnil | ||
| 5786 | : | ||
| 5787 | concat2 (build_string (" ("), | ||
| 5788 | concat2 (Fkey_description (tem), build_string (")")))); | ||
| 5789 | } | ||
| 5790 | |||
| 5791 | /* If we only want to precompute equivalent key bindings, stop here. */ | ||
| 5792 | if (notreal) | ||
| 5793 | { | ||
| 5794 | UNGCPRO; | ||
| 5795 | return 1; | ||
| 5796 | } | ||
| 5797 | |||
| 5798 | /* If we have an equivalent key binding, use that. */ | ||
| 5799 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ] | ||
| 5800 | = XCONS (cachelist)->cdr; | ||
| 5801 | |||
| 5802 | /* Include this when menu help is implemented. | ||
| 5803 | tem = XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]; | ||
| 5804 | if (!(NILP (tem) || STRINGP (tem))) | ||
| 5805 | { | ||
| 5806 | tem = menu_item_eval_property (tem); | ||
| 5807 | if (!STRINGP (tem)) | ||
| 5808 | tem = Qnil; | ||
| 5809 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP] = tem; | ||
| 5810 | } | ||
| 5811 | */ | ||
| 5812 | |||
| 5813 | /* Handle radio buttons or toggle boxes. */ | ||
| 5814 | tem = XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED]; | ||
| 5815 | if (!NILP (tem)) | ||
| 5816 | XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED] | ||
| 5817 | = menu_item_eval_property (tem); | ||
| 5818 | |||
| 5819 | UNGCPRO; | ||
| 5820 | return 1; | ||
| 5821 | } | ||
| 5822 | |||
| 5541 | /* Read a character using menus based on maps in the array MAPS. | 5823 | /* Read a character using menus based on maps in the array MAPS. |
| 5542 | NMAPS is the length of MAPS. Return nil if there are no menus in the maps. | 5824 | NMAPS is the length of MAPS. Return nil if there are no menus in the maps. |
| 5543 | Return t if we displayed a menu but the user rejected it. | 5825 | Return t if we displayed a menu but the user rejected it. |
| @@ -8124,6 +8406,9 @@ struct event_head head_table[] = { | |||
| 8124 | 8406 | ||
| 8125 | syms_of_keyboard () | 8407 | syms_of_keyboard () |
| 8126 | { | 8408 | { |
| 8409 | staticpro (&item_properties); | ||
| 8410 | item_properties = Qnil; | ||
| 8411 | |||
| 8127 | Qtimer_event_handler = intern ("timer-event-handler"); | 8412 | Qtimer_event_handler = intern ("timer-event-handler"); |
| 8128 | staticpro (&Qtimer_event_handler); | 8413 | staticpro (&Qtimer_event_handler); |
| 8129 | 8414 | ||
| @@ -8171,6 +8456,20 @@ syms_of_keyboard () | |||
| 8171 | 8456 | ||
| 8172 | Qmenu_enable = intern ("menu-enable"); | 8457 | Qmenu_enable = intern ("menu-enable"); |
| 8173 | staticpro (&Qmenu_enable); | 8458 | staticpro (&Qmenu_enable); |
| 8459 | Qmenu_alias = intern ("menu-alias"); | ||
| 8460 | staticpro (&Qmenu_alias); | ||
| 8461 | QCenable = intern (":enable"); | ||
| 8462 | staticpro (&QCenable); | ||
| 8463 | QCvisible = intern (":visible"); | ||
| 8464 | staticpro (&QCvisible); | ||
| 8465 | QCfilter = intern (":filter"); | ||
| 8466 | staticpro (&QCfilter); | ||
| 8467 | QCbutton = intern (":button"); | ||
| 8468 | staticpro (&QCbutton); | ||
| 8469 | QCtoggle = intern (":toggle"); | ||
| 8470 | staticpro (&QCtoggle); | ||
| 8471 | QCradio = intern (":radio"); | ||
| 8472 | staticpro (&QCradio); | ||
| 8174 | 8473 | ||
| 8175 | Qmode_line = intern ("mode-line"); | 8474 | Qmode_line = intern ("mode-line"); |
| 8176 | staticpro (&Qmode_line); | 8475 | staticpro (&Qmode_line); |