Mercurial > emacs
comparison src/keyboard.c @ 6135:bfe9f873bd64
(menu_bar_items): Accept old vector as arg. Return a vector.
(menu_bar_one_keymap, menu_bar_item): Associated changes.
(make_lispy_event): Use FRAME_MENU_BAR_LINES as vector.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Wed, 02 Mar 1994 04:11:11 +0000 |
parents | 9b32ddce536b |
children | 78275962ef1e |
comparison
equal
deleted
inserted
replaced
6134:c656768172d2 | 6135:bfe9f873bd64 |
---|---|
982 /* If it has changed current-menubar from previous value, | 982 /* If it has changed current-menubar from previous value, |
983 really recompute the menubar from the value. */ | 983 really recompute the menubar from the value. */ |
984 if (! NILP (Vlucid_menu_bar_dirty_flag) | 984 if (! NILP (Vlucid_menu_bar_dirty_flag) |
985 && !NILP (Ffboundp (Qrecompute_lucid_menubar))) | 985 && !NILP (Ffboundp (Qrecompute_lucid_menubar))) |
986 call0 (Qrecompute_lucid_menubar); | 986 call0 (Qrecompute_lucid_menubar); |
987 | |
988 #if 0 /* This is done in xdisp.c now. */ | |
989 #ifdef MULTI_FRAME | |
990 for (tem = Vframe_list; CONSP (tem); tem = XCONS (tem)->cdr) | |
991 { | |
992 struct frame *f = XFRAME (XCONS (tem)->car); | |
993 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f)); | |
994 | |
995 /* If the user has switched buffers or windows, we need to | |
996 recompute to reflect the new bindings. But we'll | |
997 recompute when update_mode_lines is set too; that means | |
998 that people can use force-mode-line-update to request | |
999 that the menu bar be recomputed. The adverse effect on | |
1000 the rest of the redisplay algorithm is about the same as | |
1001 windows_or_buffers_changed anyway. */ | |
1002 if (windows_or_buffers_changed | |
1003 || update_mode_lines | |
1004 || (XFASTINT (w->last_modified) < MODIFF | |
1005 && (XFASTINT (w->last_modified) | |
1006 <= XBUFFER (w->buffer)->save_modified))) | |
1007 { | |
1008 struct buffer *prev = current_buffer; | |
1009 current_buffer = XBUFFER (w->buffer); | |
1010 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (); | |
1011 current_buffer = prev; | |
1012 } | |
1013 } | |
1014 #endif /* MULTI_FRAME */ | |
1015 #endif /* 0 */ | |
1016 | 987 |
1017 /* Read next key sequence; i gets its length. */ | 988 /* Read next key sequence; i gets its length. */ |
1018 i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])), Qnil); | 989 i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])), Qnil); |
1019 | 990 |
1020 ++num_input_keys; | 991 ++num_input_keys; |
2507 if (FRAME_EXTERNAL_MENU_BAR (f) && XINT (event->y) == -1) | 2478 if (FRAME_EXTERNAL_MENU_BAR (f) && XINT (event->y) == -1) |
2508 #else | 2479 #else |
2509 if (row < FRAME_MENU_BAR_LINES (f)) | 2480 if (row < FRAME_MENU_BAR_LINES (f)) |
2510 #endif | 2481 #endif |
2511 { | 2482 { |
2512 Lisp_Object items; | 2483 Lisp_Object items, item; |
2513 | 2484 |
2514 #ifdef USE_X_TOOLKIT | 2485 #ifdef USE_X_TOOLKIT |
2515 /* The click happened in the menubar. | 2486 /* The click happened in the menubar. |
2516 Look for the menu item selected. */ | 2487 Look for the menu item selected. */ |
2517 items = map_event_to_object (event, f); | 2488 item = map_event_to_object (event, f); |
2518 | 2489 |
2519 XFASTINT (event->y) = 1; | 2490 XFASTINT (event->y) = 1; |
2520 #else /* not USE_X_TOOLKIT */ | 2491 #else /* not USE_X_TOOLKIT */ |
2521 int hpos; | 2492 int hpos; |
2493 int i; | |
2522 | 2494 |
2523 items = FRAME_MENU_BAR_ITEMS (f); | 2495 items = FRAME_MENU_BAR_ITEMS (f); |
2524 for (; CONSP (items); items = XCONS (items)->cdr) | 2496 for (i = 0; i < XVECTOR (items)->size; i += 3) |
2525 { | 2497 { |
2526 Lisp_Object pos, string; | 2498 Lisp_Object pos, string; |
2527 pos = Fcdr (Fcdr (Fcar (items))); | 2499 string = XVECTOR (items)->contents[i + 1]; |
2528 string = Fcar (Fcdr (Fcar (items))); | 2500 pos = XVECTOR (items)->contents[i + 2]; |
2501 if (NILP (string)) | |
2502 break; | |
2529 if (column >= XINT (pos) | 2503 if (column >= XINT (pos) |
2530 && column < XINT (pos) + XSTRING (string)->size) | 2504 && column < XINT (pos) + XSTRING (string)->size) |
2531 break; | 2505 { |
2506 item = XVECTOR (items)->contents[i]; | |
2507 break; | |
2508 } | |
2532 } | 2509 } |
2533 #endif /* not USE_X_TOOLKIT */ | 2510 #endif /* not USE_X_TOOLKIT */ |
2534 | 2511 |
2535 position | 2512 position |
2536 = Fcons (event->frame_or_window, | 2513 = Fcons (event->frame_or_window, |
2537 Fcons (Qmenu_bar, | 2514 Fcons (Qmenu_bar, |
2538 Fcons (Fcons (event->x, event->y), | 2515 Fcons (Fcons (event->x, event->y), |
2539 Fcons (make_number (event->timestamp), | 2516 Fcons (make_number (event->timestamp), |
2540 Qnil)))); | 2517 Qnil)))); |
2541 | 2518 |
2542 if (CONSP (items)) | 2519 return Fcons (item, Fcons (position, Qnil)); |
2543 return Fcons (Fcar (Fcar (items)), | |
2544 Fcons (position, Qnil)); | |
2545 else | |
2546 return Fcons (Qnil, Fcons (position, Qnil)); | |
2547 } | 2520 } |
2548 | 2521 |
2549 window = window_from_coordinates (f, column, row, &part); | 2522 window = window_from_coordinates (f, column, row, &part); |
2550 | 2523 |
2551 if (XTYPE (window) != Lisp_Window) | 2524 if (XTYPE (window) != Lisp_Window) |
3474 map = Fcdr (map); | 3447 map = Fcdr (map); |
3475 } | 3448 } |
3476 return Qnil; | 3449 return Qnil; |
3477 } | 3450 } |
3478 | 3451 |
3479 static Lisp_Object menu_bar_item (); | 3452 static void menu_bar_item (); |
3480 static Lisp_Object menu_bar_one_keymap (); | 3453 static void menu_bar_one_keymap (); |
3481 | 3454 |
3482 /* Return a list of menu items for a menu bar, appropriate | 3455 /* These variables hold the vector under construction within |
3483 to the current buffer. | 3456 menu_bar_items and its subroutines, and the current index |
3484 The elements have the form (KEY STRING . nil). */ | 3457 for storing into that vector. */ |
3458 static Lisp_Object menu_bar_items_vector; | |
3459 static Lisp_Object menu_bar_items_index; | |
3460 | |
3461 /* Return a vector of menu items for a menu bar, appropriate | |
3462 to the current buffer. Each item has three elements in the vector: | |
3463 KEY STRING nil. | |
3464 | |
3465 OLD is an old vector we can optionally reuse, or nil. */ | |
3485 | 3466 |
3486 Lisp_Object | 3467 Lisp_Object |
3487 menu_bar_items () | 3468 menu_bar_items (old) |
3469 Lisp_Object old; | |
3488 { | 3470 { |
3489 /* The number of keymaps we're scanning right now, and the number of | 3471 /* The number of keymaps we're scanning right now, and the number of |
3490 keymaps we have allocated space for. */ | 3472 keymaps we have allocated space for. */ |
3491 int nmaps; | 3473 int nmaps; |
3492 | 3474 |
3498 | 3480 |
3499 Lisp_Object result; | 3481 Lisp_Object result; |
3500 | 3482 |
3501 int mapno; | 3483 int mapno; |
3502 Lisp_Object oquit; | 3484 Lisp_Object oquit; |
3485 | |
3486 int i; | |
3487 | |
3488 struct gcpro gcpro1; | |
3503 | 3489 |
3504 /* In order to build the menus, we need to call the keymap | 3490 /* In order to build the menus, we need to call the keymap |
3505 accessors. They all call QUIT. But this function is called | 3491 accessors. They all call QUIT. But this function is called |
3506 during redisplay, during which a quit is fatal. So inhibit | 3492 during redisplay, during which a quit is fatal. So inhibit |
3507 quitting while building the menus. | 3493 quitting while building the menus. |
3508 We do this instead of specbind because (1) errors will clear it anyway | 3494 We do this instead of specbind because (1) errors will clear it anyway |
3509 and (2) this avoids risk of specpdl overflow. */ | 3495 and (2) this avoids risk of specpdl overflow. */ |
3510 oquit = Vinhibit_quit; | 3496 oquit = Vinhibit_quit; |
3511 Vinhibit_quit = Qt; | 3497 Vinhibit_quit = Qt; |
3498 | |
3499 if (!NILP (old)) | |
3500 menu_bar_items_vector = old; | |
3501 else | |
3502 menu_bar_items_vector = Fmake_vector (make_number (24), Qnil); | |
3503 menu_bar_items_index = 0; | |
3504 | |
3505 GCPRO1 (menu_bar_items_vector); | |
3512 | 3506 |
3513 /* Build our list of keymaps. | 3507 /* Build our list of keymaps. |
3514 If we recognize a function key and replace its escape sequence in | 3508 If we recognize a function key and replace its escape sequence in |
3515 keybuf with its symbol, or if the sequence starts with a mouse | 3509 keybuf with its symbol, or if the sequence starts with a mouse |
3516 click and we need to switch buffers, we jump back here to rebuild | 3510 click and we need to switch buffers, we jump back here to rebuild |
3549 else | 3543 else |
3550 def = Qnil; | 3544 def = Qnil; |
3551 | 3545 |
3552 tem = Fkeymapp (def); | 3546 tem = Fkeymapp (def); |
3553 if (!NILP (tem)) | 3547 if (!NILP (tem)) |
3554 result = menu_bar_one_keymap (def, result); | 3548 menu_bar_one_keymap (def); |
3555 } | 3549 } |
3550 | |
3551 /* Move to the end those items that should be at the end. */ | |
3556 | 3552 |
3557 for (tail = Vmenu_bar_final_items; CONSP (tail); tail = XCONS (tail)->cdr) | 3553 for (tail = Vmenu_bar_final_items; CONSP (tail); tail = XCONS (tail)->cdr) |
3558 { | 3554 { |
3559 Lisp_Object elt; | 3555 int i; |
3560 | 3556 int end = menu_bar_items_index; |
3561 elt = Fassq (XCONS (tail)->car, result); | 3557 |
3562 if (!NILP (elt)) | 3558 for (i = 0; i < end; i += 3) |
3563 result = Fcons (elt, Fdelq (elt, result)); | 3559 if (EQ (XCONS (tail)->car, XVECTOR (menu_bar_items_vector)->contents[i])) |
3564 } | 3560 { |
3565 | 3561 Lisp_Object tem; |
3566 result = Fnreverse (result); | 3562 end -= 3; |
3563 #define EXCH(a, b) tem = a, a = b, b = tem | |
3564 EXCH (XVECTOR (menu_bar_items_vector)->contents[i], | |
3565 XVECTOR (menu_bar_items_vector)->contents[end]); | |
3566 EXCH (XVECTOR (menu_bar_items_vector)->contents[i + 1], | |
3567 XVECTOR (menu_bar_items_vector)->contents[end + 1]); | |
3568 EXCH (XVECTOR (menu_bar_items_vector)->contents[i + 2], | |
3569 XVECTOR (menu_bar_items_vector)->contents[end + 2]); | |
3570 #undef EXCH | |
3571 i -= 3; | |
3572 } | |
3573 } | |
3574 | |
3575 /* Add nil, nil, nil at the end. */ | |
3576 i = menu_bar_items_index; | |
3577 if (i + 3 > XVECTOR (menu_bar_items_vector)->size) | |
3578 { | |
3579 Lisp_Object tem; | |
3580 int newsize = 2 * i; | |
3581 tem = Fmake_vector (make_number (2 * i), Qnil); | |
3582 bcopy (XVECTOR (menu_bar_items_vector)->contents, | |
3583 XVECTOR (tem)->contents, i * sizeof (Lisp_Object)); | |
3584 menu_bar_items_vector = tem; | |
3585 } | |
3586 /* Add this item. */ | |
3587 XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil; | |
3588 XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil; | |
3589 XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil; | |
3590 menu_bar_items_index = i; | |
3591 | |
3567 Vinhibit_quit = oquit; | 3592 Vinhibit_quit = oquit; |
3568 return result; | 3593 UNGCPRO; |
3594 return menu_bar_items_vector; | |
3569 } | 3595 } |
3570 | 3596 |
3571 /* Scan one map KEYMAP, accumulating any menu items it defines | 3597 /* Scan one map KEYMAP, accumulating any menu items it defines |
3572 that have not yet been seen in RESULT. Return the updated RESULT. */ | 3598 that have not yet been seen in RESULT. Return the updated RESULT. |
3573 | 3599 *OLD is the frame's old menu bar list; we swipe elts from that |
3574 static Lisp_Object | 3600 to avoid consing. */ |
3575 menu_bar_one_keymap (keymap, result) | 3601 |
3576 Lisp_Object keymap, result; | 3602 static void |
3603 menu_bar_one_keymap (keymap) | |
3604 Lisp_Object keymap; | |
3577 { | 3605 { |
3578 Lisp_Object tail, item, key, binding, item_string, table; | 3606 Lisp_Object tail, item, key, binding, item_string, table; |
3579 | 3607 |
3580 /* Loop over all keymap entries that have menu strings. */ | 3608 /* Loop over all keymap entries that have menu strings. */ |
3581 for (tail = keymap; XTYPE (tail) == Lisp_Cons; tail = XCONS (tail)->cdr) | 3609 for (tail = keymap; XTYPE (tail) == Lisp_Cons; tail = XCONS (tail)->cdr) |
3587 binding = XCONS (item)->cdr; | 3615 binding = XCONS (item)->cdr; |
3588 if (XTYPE (binding) == Lisp_Cons) | 3616 if (XTYPE (binding) == Lisp_Cons) |
3589 { | 3617 { |
3590 item_string = XCONS (binding)->car; | 3618 item_string = XCONS (binding)->car; |
3591 if (XTYPE (item_string) == Lisp_String) | 3619 if (XTYPE (item_string) == Lisp_String) |
3592 result = menu_bar_item (key, item_string, | 3620 menu_bar_item (key, item_string, Fcdr (binding)); |
3593 Fcdr (binding), result); | |
3594 } | 3621 } |
3595 else if (EQ (binding, Qundefined)) | 3622 else if (EQ (binding, Qundefined)) |
3596 result = menu_bar_item (key, item_string, | 3623 menu_bar_item (key, item_string, binding); |
3597 binding, result); | |
3598 } | 3624 } |
3599 else if (XTYPE (item) == Lisp_Vector) | 3625 else if (XTYPE (item) == Lisp_Vector) |
3600 { | 3626 { |
3601 /* Loop over the char values represented in the vector. */ | 3627 /* Loop over the char values represented in the vector. */ |
3602 int len = XVECTOR (item)->size; | 3628 int len = XVECTOR (item)->size; |
3608 binding = XVECTOR (item)->contents[c]; | 3634 binding = XVECTOR (item)->contents[c]; |
3609 if (XTYPE (binding) == Lisp_Cons) | 3635 if (XTYPE (binding) == Lisp_Cons) |
3610 { | 3636 { |
3611 item_string = XCONS (binding)->car; | 3637 item_string = XCONS (binding)->car; |
3612 if (XTYPE (item_string) == Lisp_String) | 3638 if (XTYPE (item_string) == Lisp_String) |
3613 result = menu_bar_item (key, item_string, | 3639 menu_bar_item (key, item_string, Fcdr (binding)); |
3614 Fcdr (binding), result); | |
3615 } | 3640 } |
3616 else if (EQ (binding, Qundefined)) | 3641 else if (EQ (binding, Qundefined)) |
3617 result = menu_bar_item (key, item_string, | 3642 menu_bar_item (key, item_string, binding); |
3618 binding, result); | |
3619 } | 3643 } |
3620 } | 3644 } |
3621 } | 3645 } |
3622 | |
3623 return result; | |
3624 } | 3646 } |
3625 | 3647 |
3626 /* This is used as the handler when calling internal_condition_case_1. */ | 3648 /* This is used as the handler when calling internal_condition_case_1. */ |
3627 | 3649 |
3628 static Lisp_Object | 3650 static Lisp_Object |
3630 Lisp_Object arg; | 3652 Lisp_Object arg; |
3631 { | 3653 { |
3632 return Qnil; | 3654 return Qnil; |
3633 } | 3655 } |
3634 | 3656 |
3635 static Lisp_Object | 3657 static void |
3636 menu_bar_item (key, item_string, def, result) | 3658 menu_bar_item (key, item_string, def) |
3637 Lisp_Object key, item_string, def, result; | 3659 Lisp_Object key, item_string, def; |
3638 { | 3660 { |
3639 Lisp_Object tem; | 3661 Lisp_Object tem; |
3640 Lisp_Object enabled; | 3662 Lisp_Object enabled; |
3663 int i; | |
3641 | 3664 |
3642 if (EQ (def, Qundefined)) | 3665 if (EQ (def, Qundefined)) |
3643 { | 3666 { |
3644 /* If a map has an explicit nil as definition, | 3667 /* If a map has an explicit nil as definition, |
3645 discard any previously made menu bar item. */ | 3668 discard any previously made menu bar item. */ |
3646 tem = Fassq (key, result); | 3669 |
3647 return Fdelq (tem, result); | 3670 for (i = 0; i < menu_bar_items_index; i += 3) |
3671 if (EQ (key, XVECTOR (menu_bar_items_vector)->contents[i])) | |
3672 { | |
3673 if (menu_bar_items_index > i + 3) | |
3674 bcopy (&XVECTOR (menu_bar_items_vector)->contents[i + 3], | |
3675 &XVECTOR (menu_bar_items_vector)->contents[i], | |
3676 (menu_bar_items_index - i - 3) * sizeof (Lisp_Object)); | |
3677 menu_bar_items_index -= 3; | |
3678 return; | |
3679 } | |
3648 } | 3680 } |
3649 | 3681 |
3650 /* See if this entry is enabled. */ | 3682 /* See if this entry is enabled. */ |
3651 enabled = Qt; | 3683 enabled = Qt; |
3652 | 3684 |
3660 (error nil)) */ | 3692 (error nil)) */ |
3661 enabled = internal_condition_case_1 (Feval, tem, Qerror, | 3693 enabled = internal_condition_case_1 (Feval, tem, Qerror, |
3662 menu_bar_item_1); | 3694 menu_bar_item_1); |
3663 } | 3695 } |
3664 | 3696 |
3665 /* Add an entry for this key and string | 3697 /* Ignore this item if it's not enabled. */ |
3666 if there is none yet. */ | 3698 if (NILP (enabled)) |
3667 tem = Fassq (key, result); | 3699 return; |
3668 if (!NILP (enabled) && NILP (tem)) | 3700 |
3669 result = Fcons (Fcons (key, Fcons (item_string, Qnil)), result); | 3701 /* If there's already such an item, don't make another. */ |
3670 | 3702 for (i = 0; i < menu_bar_items_index; i += 3) |
3671 return result; | 3703 if (EQ (key, XVECTOR (menu_bar_items_vector)->contents[i])) |
3704 break; | |
3705 | |
3706 /* If we did not find this item, add it at the end. */ | |
3707 if (i == menu_bar_items_index) | |
3708 { | |
3709 /* If vector is too small, get a bigger one. */ | |
3710 if (i + 3 > XVECTOR (menu_bar_items_vector)->size) | |
3711 { | |
3712 Lisp_Object tem; | |
3713 int newsize = 2 * i; | |
3714 tem = Fmake_vector (make_number (2 * i), Qnil); | |
3715 bcopy (XVECTOR (menu_bar_items_vector)->contents, | |
3716 XVECTOR (tem)->contents, i * sizeof (Lisp_Object)); | |
3717 menu_bar_items_vector = tem; | |
3718 } | |
3719 /* Add this item. */ | |
3720 XVECTOR (menu_bar_items_vector)->contents[i++] = key; | |
3721 XVECTOR (menu_bar_items_vector)->contents[i++] = item_string; | |
3722 XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil; | |
3723 menu_bar_items_index = i; | |
3724 } | |
3672 } | 3725 } |
3673 | 3726 |
3674 /* Read a character using menus based on maps in the array MAPS. | 3727 /* Read a character using menus based on maps in the array MAPS. |
3675 NMAPS is the length of MAPS. Return nil if there are no menus in the maps. | 3728 NMAPS is the length of MAPS. Return nil if there are no menus in the maps. |
3676 Return t if we displayed a menu but the user rejected it. | 3729 Return t if we displayed a menu but the user rejected it. |