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.