aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGerd Moellmann1999-07-21 21:43:52 +0000
committerGerd Moellmann1999-07-21 21:43:52 +0000
commit7ee32cda427368906e23a0209aa4136cf2974781 (patch)
treec59138bae8de4d1004112a973bbb68bd401ea0f0 /src
parent0552666bc1f8989999967b575977b08a5f57ecb7 (diff)
downloademacs-7ee32cda427368906e23a0209aa4136cf2974781.tar.gz
emacs-7ee32cda427368906e23a0209aa4136cf2974781.zip
(read_char): Use message3_nolog to show help-echo.
(make_lispy_event) <TOOLBAR_EVENT>: Apply modifiers. (kbd_store_ptr): Declare it as a volatile pointer instead of a pointer to a volatile input_event. (kbd_buffer_store_event): Remove volatile modifier from declaration of local variable `sp'. (Fdiscard_input): Don't cast when assigning kbd_store_ptr to kbd_fetch_ptr. (make_lispy_event): Handle mouse on top lines. (make_lispy_movement): Ditto. (read_char): Rename local variable echo_area_message because it shadows the global one. (cmd_error_internal): Set echo_areA_message. (command_loop_1): Test echo_areA_message. (read_char): Ditto. (record_menu_key): Set echo_area_message to nil. (Fexecute_extended_command): Test echo_area_message. (Fexecute_extended_command): Handle echo_area_message. (toolbar_items): Call access_keymap with third parameter 1, so that we don't get inherited toolbar item definitions. Ditto. (kbd_buffer_get_event): Set flag to prevent recording TOOLBAR_EVENT events in last_nonmenu_event. (timer_check): Inhibit busy cursor around calls to timer-event-handler. This busy cursor tends to be anoying if fontifying stealthily. (command_loop_1): Display busy cursor. (Vshow_help_function): New. (read_char): Use it. (make_lispy_event): Add string and string position info to mouse-click events. (read_key_sequence): Handle `local-map' property of mode line strings. (Qend_scroll): New. (scroll_bar_parts): Add it. (scroll_bar_parts): Add Qtop and Qbottom. (syms_of_keyboard): Add Qbottom. (make_lispy_event): Handle scroll_bar_click differently when using toolkit scroll bars. (cmd_error_internal): Bug fix. (syms_of_keyboard): Staticpro toolbar_item_properties and toolbar_items_vectors. (Qhelp_echo): New symbol. (read_char): Handle `toolbar' and `help_echo' events. (kbd_buffer_get_event): Handle HELP_ECHO input event. (make_lispy_event): Handle TOOLBAR_EVENT. (toolbar_items): New. (process_toolbar_item): New. (PROP): New. (init_toolbar_items): New. (append_toolbar_item): New. (read_char_x_menu_prompt): Handle `toolbar' event. (read_key_sequence): Ditto. (syms_of_keyboard): Intern `:help'. (toolbar_items): New. (process_toolbar_item): New. (parse_toolbar_item): New. (init_toolbar_items): New. (append_toolbar_item): New. (detect_input_pending_run_timers): Likewise. (detect_input_pending_run_timers): Call gobble_input after redisplaying. (clear_waiting_for_input): Return void. (record_asynch_buffer_change): Return void. (stop_polling): Return void. (start_polling): Ditto. (cmd_error_internal): Write to stderr if selected frame is Vterminal_frame under X. This is the case when a font cannot be loaded when Emacs starts. Replace test for FRAME_MESSAGE_BUF with test for glyphs_initialized_p. (quit_throw_to_read_char): Ditto. (make_lispy_event): mouse clicks; don't do frame glyph position calculations. (make_lispy_movement): Use buffer_posn_from_coords and window relative coordinates. (make_lispy_event): For mouse clicks, use x_y_to_hpos_vpos. (make_lispy_event): Use BUFFER_POSN_FROM_COORDS with window relative pixel coordinates. Use GLYPH_TO_PIXEL_- COORDS mit new arguments. (make_lispy_event): WINDOW_FROM_COORDINATES with pixel coords. (make_lispy_movement): Same. (interrupt_signal): Cursor_to with 4 params. (command_loop_1): Call DIRECT_OUTPUT_FOR_INSERT for any character.
Diffstat (limited to 'src')
-rw-r--r--src/keyboard.c837
1 files changed, 716 insertions, 121 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index 78860dd6496..282ce450297 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -166,6 +166,11 @@ extern int message_enable_multibyte;
166 166
167extern struct backtrace *backtrace_list; 167extern struct backtrace *backtrace_list;
168 168
169/* If non-nil, the function that implements the display of help.
170 It's called with one argument, the help string to display. */
171
172Lisp_Object Vshow_help_function;
173
169/* Nonzero means do menu prompting. */ 174/* Nonzero means do menu prompting. */
170static int menu_prompting; 175static int menu_prompting;
171 176
@@ -459,7 +464,7 @@ static struct input_event *kbd_fetch_ptr;
459/* Pointer to next place to store character in kbd_buffer. This 464/* Pointer to next place to store character in kbd_buffer. This
460 may be kbd_buffer + KBD_BUFFER_SIZE, meaning that the next 465 may be kbd_buffer + KBD_BUFFER_SIZE, meaning that the next
461 character should go in kbd_buffer[0]. */ 466 character should go in kbd_buffer[0]. */
462static volatile struct input_event *kbd_store_ptr; 467static struct input_event * volatile kbd_store_ptr;
463 468
464/* The above pair of variables forms a "queue empty" flag. When we 469/* The above pair of variables forms a "queue empty" flag. When we
465 enqueue a non-hook event, we increment kbd_store_ptr. When we 470 enqueue a non-hook event, we increment kbd_store_ptr. When we
@@ -482,6 +487,7 @@ Lisp_Object Qswitch_frame;
482Lisp_Object Qdelete_frame; 487Lisp_Object Qdelete_frame;
483Lisp_Object Qiconify_frame; 488Lisp_Object Qiconify_frame;
484Lisp_Object Qmake_frame_visible; 489Lisp_Object Qmake_frame_visible;
490Lisp_Object Qhelp_echo;
485 491
486/* Symbols to denote kinds of events. */ 492/* Symbols to denote kinds of events. */
487Lisp_Object Qfunction_key; 493Lisp_Object Qfunction_key;
@@ -600,6 +606,7 @@ static Lisp_Object make_lispy_switch_frame ();
600static int parse_solitary_modifier (); 606static int parse_solitary_modifier ();
601static void save_getcjmp (); 607static void save_getcjmp ();
602static void restore_getcjmp (); 608static void restore_getcjmp ();
609static Lisp_Object apply_modifiers P_ ((int, Lisp_Object));
603 610
604/* > 0 if we are to echo keystrokes. */ 611/* > 0 if we are to echo keystrokes. */
605static int echo_keystrokes; 612static int echo_keystrokes;
@@ -1014,17 +1021,27 @@ cmd_error_internal (data, context)
1014 char *context; 1021 char *context;
1015{ 1022{
1016 Lisp_Object stream; 1023 Lisp_Object stream;
1024 int kill_emacs_p = 0;
1017 1025
1018 Vquit_flag = Qnil; 1026 Vquit_flag = Qnil;
1019 Vinhibit_quit = Qt; 1027 Vinhibit_quit = Qt;
1020 echo_area_glyphs = 0; 1028 echo_area_glyphs = 0;
1029 echo_area_message = Qnil;
1021 1030
1022 /* If the window system or terminal frame hasn't been initialized 1031 /* If the window system or terminal frame hasn't been initialized
1023 yet, or we're not interactive, it's best to dump this message out 1032 yet, or we're not interactive, it's best to dump this message out
1024 to stderr and exit. */ 1033 to stderr and exit. */
1025 if (! FRAME_MESSAGE_BUF (selected_frame) 1034 if (!selected_frame->glyphs_initialized_p
1035 /* This is the case of the frame dumped with Emacs, when we're
1036 running under a window system. */
1037 || (!NILP (Vwindow_system)
1038 && !inhibit_window_system
1039 && !FRAME_WINDOW_P (selected_frame))
1026 || noninteractive) 1040 || noninteractive)
1027 stream = Qexternal_debugging_output; 1041 {
1042 stream = Qexternal_debugging_output;
1043 kill_emacs_p = 1;
1044 }
1028 else 1045 else
1029 { 1046 {
1030 Fdiscard_input (); 1047 Fdiscard_input ();
@@ -1039,8 +1056,7 @@ cmd_error_internal (data, context)
1039 1056
1040 /* If the window system or terminal frame hasn't been initialized 1057 /* If the window system or terminal frame hasn't been initialized
1041 yet, or we're in -batch mode, this error should cause Emacs to exit. */ 1058 yet, or we're in -batch mode, this error should cause Emacs to exit. */
1042 if (! FRAME_MESSAGE_BUF (selected_frame) 1059 if (kill_emacs_p)
1043 || noninteractive)
1044 { 1060 {
1045 Fterpri (stream); 1061 Fterpri (stream);
1046 Fkill_emacs (make_number (-1)); 1062 Fkill_emacs (make_number (-1));
@@ -1222,7 +1238,8 @@ command_loop_1 ()
1222 /* If minibuffer on and echo area in use, 1238 /* If minibuffer on and echo area in use,
1223 wait 2 sec and redraw minibuffer. */ 1239 wait 2 sec and redraw minibuffer. */
1224 1240
1225 if (minibuf_level && echo_area_glyphs 1241 if (minibuf_level
1242 && (echo_area_glyphs || STRINGP (echo_area_message))
1226 && EQ (minibuf_window, echo_area_window)) 1243 && EQ (minibuf_window, echo_area_window))
1227 { 1244 {
1228 /* Bind inhibit-quit to t so that C-g gets read in 1245 /* Bind inhibit-quit to t so that C-g gets read in
@@ -1421,7 +1438,6 @@ command_loop_1 ()
1421 { 1438 {
1422 unsigned int c = XINT (last_command_char); 1439 unsigned int c = XINT (last_command_char);
1423 int value; 1440 int value;
1424
1425 if (NILP (Vexecuting_macro) 1441 if (NILP (Vexecuting_macro)
1426 && !EQ (minibuf_window, selected_window)) 1442 && !EQ (minibuf_window, selected_window))
1427 { 1443 {
@@ -1432,6 +1448,7 @@ command_loop_1 ()
1432 } 1448 }
1433 nonundocount++; 1449 nonundocount++;
1434 } 1450 }
1451
1435 lose = ((XFASTINT (XWINDOW (selected_window)->last_modified) 1452 lose = ((XFASTINT (XWINDOW (selected_window)->last_modified)
1436 < MODIFF) 1453 < MODIFF)
1437 || (XFASTINT (XWINDOW (selected_window)->last_overlay_modified) 1454 || (XFASTINT (XWINDOW (selected_window)->last_overlay_modified)
@@ -1444,58 +1461,33 @@ command_loop_1 ()
1444 || detect_input_pending () 1461 || detect_input_pending ()
1445 || !NILP (XWINDOW (selected_window)->column_number_displayed) 1462 || !NILP (XWINDOW (selected_window)->column_number_displayed)
1446 || !NILP (Vexecuting_macro)); 1463 || !NILP (Vexecuting_macro));
1464
1447 value = internal_self_insert (c, 0); 1465 value = internal_self_insert (c, 0);
1448 if (value) 1466
1449 lose = 1;
1450 if (value == 2) 1467 if (value == 2)
1451 nonundocount = 0; 1468 nonundocount = 0;
1452 1469
1453 if (!lose 1470 /* VALUE == 1 when AFTER-CHANGE functions are
1454 && (PT == ZV || FETCH_BYTE (PT_BYTE) == '\n')) 1471 installed which is the case most of the time
1455 { 1472 because FONT-LOCK installs one. */
1456 struct Lisp_Char_Table *dp 1473 if (!lose && !value)
1457 = window_display_table (XWINDOW (selected_window)); 1474 no_redisplay = direct_output_for_insert (c);
1458 int lose = c;
1459
1460 /* Add the offset to the character, for Finsert_char.
1461 We pass internal_self_insert the unmodified character
1462 because it itself does this offsetting. */
1463 if (! NILP (current_buffer->enable_multibyte_characters))
1464 lose = unibyte_char_to_multibyte (lose);
1465
1466 if (dp)
1467 {
1468 Lisp_Object obj;
1469
1470 obj = DISP_CHAR_VECTOR (dp, lose);
1471 if (NILP (obj))
1472 {
1473 /* Do it only for char codes
1474 that by default display as themselves. */
1475 if (lose >= 0x20 && lose <= 0x7e)
1476 no_redisplay = direct_output_for_insert (lose);
1477 }
1478 else if (VECTORP (obj)
1479 && XVECTOR (obj)->size == 1
1480 && (obj = XVECTOR (obj)->contents[0],
1481 INTEGERP (obj))
1482 /* Insist face not specified in glyph. */
1483 && (XINT (obj) & ((-1) << 8)) == 0)
1484 no_redisplay
1485 = direct_output_for_insert (XINT (obj));
1486 }
1487 else
1488 {
1489 if (lose >= 0x20 && lose <= 0x7e)
1490 no_redisplay = direct_output_for_insert (lose);
1491 }
1492 }
1493 goto directly_done; 1475 goto directly_done;
1494 } 1476 }
1495 } 1477 }
1496 1478
1497 /* Here for a command that isn't executed directly */ 1479 /* Here for a command that isn't executed directly */
1498 1480
1481#ifdef HAVE_X_WINDOWS
1482 if (display_busy_cursor_p)
1483 {
1484 if (inhibit_busy_cursor != 2)
1485 inhibit_busy_cursor = 0;
1486 if (!inhibit_busy_cursor)
1487 Fx_show_busy_cursor ();
1488 }
1489#endif
1490
1499 nonundocount = 0; 1491 nonundocount = 0;
1500 if (NILP (current_kboard->Vprefix_arg)) 1492 if (NILP (current_kboard->Vprefix_arg))
1501 Fundo_boundary (); 1493 Fundo_boundary ();
@@ -1810,7 +1802,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
1810 jmp_buf save_jump; 1802 jmp_buf save_jump;
1811 int key_already_recorded = 0; 1803 int key_already_recorded = 0;
1812 Lisp_Object tem, save; 1804 Lisp_Object tem, save;
1813 Lisp_Object echo_area_message; 1805 Lisp_Object previous_echo_area_message;
1814 Lisp_Object also_record; 1806 Lisp_Object also_record;
1815 int reread; 1807 int reread;
1816 struct gcpro gcpro1, gcpro2; 1808 struct gcpro gcpro1, gcpro2;
@@ -1820,9 +1812,9 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
1820 before_command_key_count = this_command_key_count; 1812 before_command_key_count = this_command_key_count;
1821 before_command_echo_length = echo_length (); 1813 before_command_echo_length = echo_length ();
1822 c = Qnil; 1814 c = Qnil;
1823 echo_area_message = Qnil; 1815 previous_echo_area_message = Qnil;
1824 1816
1825 GCPRO2 (c, echo_area_message); 1817 GCPRO2 (c, previous_echo_area_message);
1826 1818
1827 retry: 1819 retry:
1828 1820
@@ -1958,10 +1950,13 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
1958 } 1950 }
1959 1951
1960 /* Message turns off echoing unless more keystrokes turn it on again. */ 1952 /* Message turns off echoing unless more keystrokes turn it on again. */
1961 if (echo_area_glyphs && *echo_area_glyphs 1953 if (echo_area_glyphs
1954 && *echo_area_glyphs
1962 && echo_area_glyphs != current_kboard->echobuf 1955 && echo_area_glyphs != current_kboard->echobuf
1963 && ok_to_echo_at_next_pause != echo_area_glyphs) 1956 && ok_to_echo_at_next_pause != echo_area_glyphs)
1964 cancel_echoing (); 1957 cancel_echoing ();
1958 else if (STRINGP (echo_area_message))
1959 cancel_echoing ();
1965 else 1960 else
1966 /* If already echoing, continue. */ 1961 /* If already echoing, continue. */
1967 echo_dash (); 1962 echo_dash ();
@@ -2034,10 +2029,12 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
2034 /* If in middle of key sequence and minibuffer not active, 2029 /* If in middle of key sequence and minibuffer not active,
2035 start echoing if enough time elapses. */ 2030 start echoing if enough time elapses. */
2036 2031
2037 if (minibuf_level == 0 && !current_kboard->immediate_echo 2032 if (minibuf_level == 0
2033 && !current_kboard->immediate_echo
2038 && this_command_key_count > 0 2034 && this_command_key_count > 0
2039 && ! noninteractive 2035 && ! noninteractive
2040 && echo_keystrokes > 0 2036 && echo_keystrokes > 0
2037 && !STRINGP (echo_area_message)
2041 && (echo_area_glyphs == 0 || *echo_area_glyphs == 0 2038 && (echo_area_glyphs == 0 || *echo_area_glyphs == 0
2042 || ok_to_echo_at_next_pause == echo_area_glyphs)) 2039 || ok_to_echo_at_next_pause == echo_area_glyphs))
2043 { 2040 {
@@ -2081,6 +2078,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
2081 && !NILP (prev_event) 2078 && !NILP (prev_event)
2082 && EVENT_HAS_PARAMETERS (prev_event) 2079 && EVENT_HAS_PARAMETERS (prev_event)
2083 && !EQ (XCONS (prev_event)->car, Qmenu_bar) 2080 && !EQ (XCONS (prev_event)->car, Qmenu_bar)
2081 && !EQ (XCONS (prev_event)->car, Qtoolbar)
2084 /* Don't bring up a menu if we already have another event. */ 2082 /* Don't bring up a menu if we already have another event. */
2085 && NILP (Vunread_command_events) 2083 && NILP (Vunread_command_events)
2086 && unread_command_char < 0) 2084 && unread_command_char < 0)
@@ -2333,7 +2331,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
2333 posn = POSN_BUFFER_POSN (EVENT_START (c)); 2331 posn = POSN_BUFFER_POSN (EVENT_START (c));
2334 /* Handle menu-bar events: 2332 /* Handle menu-bar events:
2335 insert the dummy prefix event `menu-bar'. */ 2333 insert the dummy prefix event `menu-bar'. */
2336 if (EQ (posn, Qmenu_bar)) 2334 if (EQ (posn, Qmenu_bar) || EQ (posn, Qtoolbar))
2337 { 2335 {
2338 /* Change menu-bar to (menu-bar) as the event "position". */ 2336 /* Change menu-bar to (menu-bar) as the event "position". */
2339 POSN_BUFFER_POSN (EVENT_START (c)) = Fcons (posn, Qnil); 2337 POSN_BUFFER_POSN (EVENT_START (c)) = Fcons (posn, Qnil);
@@ -2357,12 +2355,16 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
2357 && ! NILP (Vinput_method_function) 2355 && ! NILP (Vinput_method_function)
2358 && (unsigned) XINT (c) >= ' ' 2356 && (unsigned) XINT (c) >= ' '
2359 && (unsigned) XINT (c) < 127) 2357 && (unsigned) XINT (c) < 127)
2360 Vinput_method_previous_message = echo_area_message = Fcurrent_message (); 2358 {
2359 previous_echo_area_message = Fcurrent_message ();
2360 Vinput_method_previous_message = previous_echo_area_message;
2361 }
2361 2362
2362 /* Now wipe the echo area. */ 2363 /* Now wipe the echo area. */
2363 if (echo_area_glyphs) 2364 if (echo_area_glyphs || STRINGP (echo_area_message))
2364 safe_run_hooks (Qecho_area_clear_hook); 2365 safe_run_hooks (Qecho_area_clear_hook);
2365 echo_area_glyphs = 0; 2366 echo_area_glyphs = 0;
2367 echo_area_message = Qnil;
2366 2368
2367 reread_for_input_method: 2369 reread_for_input_method:
2368 from_macro: 2370 from_macro:
@@ -2407,9 +2409,10 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
2407 this_command_key_count = 0; 2409 this_command_key_count = 0;
2408 2410
2409 /* Now wipe the echo area. */ 2411 /* Now wipe the echo area. */
2410 if (echo_area_glyphs) 2412 if (echo_area_glyphs || STRINGP (echo_area_message))
2411 safe_run_hooks (Qecho_area_clear_hook); 2413 safe_run_hooks (Qecho_area_clear_hook);
2412 echo_area_glyphs = 0; 2414 echo_area_glyphs = 0;
2415 echo_area_message = Qnil;
2413 echo_truncate (0); 2416 echo_truncate (0);
2414 2417
2415 /* If we are not reading a key sequence, 2418 /* If we are not reading a key sequence,
@@ -2442,8 +2445,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
2442 if (! CONSP (tem)) 2445 if (! CONSP (tem))
2443 { 2446 {
2444 /* Bring back the previous message, if any. */ 2447 /* Bring back the previous message, if any. */
2445 if (! NILP (echo_area_message)) 2448 if (! NILP (previous_echo_area_message))
2446 message_with_string ("%s", echo_area_message, 0); 2449 message_with_string ("%s", previous_echo_area_message, 0);
2447 goto retry; 2450 goto retry;
2448 } 2451 }
2449 /* It returned one event or more. */ 2452 /* It returned one event or more. */
@@ -2454,6 +2457,25 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
2454 2457
2455 reread_first: 2458 reread_first:
2456 2459
2460 /* Display help if not echoing. */
2461 if (CONSP (c)
2462 && EQ (XCAR (c), Qhelp_echo))
2463 {
2464 Lisp_Object msg = XCDR (XCDR (c));
2465
2466 if (!NILP (Vshow_help_function))
2467 call1 (Vshow_help_function, msg);
2468 else if (!echoing && !MINI_WINDOW_P (XWINDOW (selected_window)))
2469 {
2470 if (STRINGP (msg))
2471 message3_nolog (msg, XSTRING (msg)->size, STRING_MULTIBYTE (msg));
2472 else
2473 message (0);
2474 }
2475
2476 goto retry;
2477 }
2478
2457 if (this_command_key_count == 0 || ! reread) 2479 if (this_command_key_count == 0 || ! reread)
2458 { 2480 {
2459 before_command_key_count = this_command_key_count; 2481 before_command_key_count = this_command_key_count;
@@ -2523,6 +2545,7 @@ record_menu_key (c)
2523{ 2545{
2524 /* Wipe the echo area. */ 2546 /* Wipe the echo area. */
2525 echo_area_glyphs = 0; 2547 echo_area_glyphs = 0;
2548 echo_area_message = Qnil;
2526 2549
2527 record_char (c); 2550 record_char (c);
2528 2551
@@ -2855,7 +2878,7 @@ kbd_buffer_store_event (event)
2855 Discard the event if it would fill the last slot. */ 2878 Discard the event if it would fill the last slot. */
2856 if (kbd_fetch_ptr - 1 != kbd_store_ptr) 2879 if (kbd_fetch_ptr - 1 != kbd_store_ptr)
2857 { 2880 {
2858 volatile struct input_event *sp = kbd_store_ptr; 2881 struct input_event *sp = kbd_store_ptr;
2859 sp->kind = event->kind; 2882 sp->kind = event->kind;
2860 if (event->kind == selection_request_event) 2883 if (event->kind == selection_request_event)
2861 { 2884 {
@@ -3100,7 +3123,13 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
3100 mouse events during a popup-menu call. */ 3123 mouse events during a popup-menu call. */
3101 else if (event->kind == no_event) 3124 else if (event->kind == no_event)
3102 kbd_fetch_ptr = event + 1; 3125 kbd_fetch_ptr = event + 1;
3103 3126 else if (event->kind == HELP_EVENT)
3127 {
3128 /* The car of event->frame_or_window is a frame,
3129 the cdr is the help to display. */
3130 obj = Fcons (Qhelp_echo, event->frame_or_window);
3131 kbd_fetch_ptr = event + 1;
3132 }
3104 /* If this event is on a different frame, return a switch-frame this 3133 /* If this event is on a different frame, return a switch-frame this
3105 time, and leave the event in the queue for next time. */ 3134 time, and leave the event in the queue for next time. */
3106 else 3135 else
@@ -3135,8 +3164,10 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
3135 we're returning is (menu-bar), though; that indicates the 3164 we're returning is (menu-bar), though; that indicates the
3136 beginning of the menu sequence, and we might as well leave 3165 beginning of the menu sequence, and we might as well leave
3137 that as the `event with parameters' for this selection. */ 3166 that as the `event with parameters' for this selection. */
3138 if (event->kind == menu_bar_event 3167 if ((event->kind == menu_bar_event
3168 || event->kind == TOOLBAR_EVENT)
3139 && !(CONSP (obj) && EQ (XCONS (obj)->car, Qmenu_bar)) 3169 && !(CONSP (obj) && EQ (XCONS (obj)->car, Qmenu_bar))
3170 && !(CONSP (obj) && EQ (XCONS (obj)->car, Qtoolbar))
3140 && used_mouse_menu) 3171 && used_mouse_menu)
3141 *used_mouse_menu = 1; 3172 *used_mouse_menu = 1;
3142#endif 3173#endif
@@ -3471,6 +3502,9 @@ timer_check (do_it_now)
3471 Lisp_Object tem; 3502 Lisp_Object tem;
3472 int was_locked = single_kboard; 3503 int was_locked = single_kboard;
3473 int count = specpdl_ptr - specpdl; 3504 int count = specpdl_ptr - specpdl;
3505#ifdef HAVE_WINDOW_SYSTEM
3506 int old_inhibit_busy_cursor = inhibit_busy_cursor;
3507#endif
3474 3508
3475 /* Mark the timer as triggered to prevent problems if the lisp 3509 /* Mark the timer as triggered to prevent problems if the lisp
3476 code fails to reschedule it right. */ 3510 code fails to reschedule it right. */
@@ -3478,9 +3512,17 @@ timer_check (do_it_now)
3478 3512
3479 specbind (Qinhibit_quit, Qt); 3513 specbind (Qinhibit_quit, Qt);
3480 3514
3515#ifdef HAVE_WINDOW_SYSTEM
3516 inhibit_busy_cursor = 2;
3517#endif
3518
3481 call1 (Qtimer_event_handler, chosen_timer); 3519 call1 (Qtimer_event_handler, chosen_timer);
3482 timers_run++; 3520 timers_run++;
3483 3521
3522#ifdef HAVE_WINDOW_SYSTEM
3523 inhibit_busy_cursor = old_inhibit_busy_cursor;
3524#endif
3525
3484 unbind_to (count, Qnil); 3526 unbind_to (count, Qnil);
3485 3527
3486 /* Resume allowing input from any kboard, if that was true before. */ 3528 /* Resume allowing input from any kboard, if that was true before. */
@@ -3946,12 +3988,13 @@ static char *lispy_drag_n_drop_names[] =
3946 3988
3947/* Scroll bar parts. */ 3989/* Scroll bar parts. */
3948Lisp_Object Qabove_handle, Qhandle, Qbelow_handle; 3990Lisp_Object Qabove_handle, Qhandle, Qbelow_handle;
3949Lisp_Object Qup, Qdown; 3991Lisp_Object Qup, Qdown, Qbottom, Qend_scroll;
3992Lisp_Object Qtop;
3950 3993
3951/* An array of scroll bar parts, indexed by an enum scroll_bar_part value. */ 3994/* An array of scroll bar parts, indexed by an enum scroll_bar_part value. */
3952Lisp_Object *scroll_bar_parts[] = { 3995Lisp_Object *scroll_bar_parts[] = {
3953 &Qabove_handle, &Qhandle, &Qbelow_handle, 3996 &Qabove_handle, &Qhandle, &Qbelow_handle,
3954 &Qup, &Qdown, 3997 &Qup, &Qdown, &Qtop, &Qbottom, &Qend_scroll
3955}; 3998};
3956 3999
3957/* User signal events. */ 4000/* User signal events. */
@@ -4095,7 +4138,9 @@ make_lispy_event (event)
4095 /* A mouse click. Figure out where it is, decide whether it's 4138 /* A mouse click. Figure out where it is, decide whether it's
4096 a press, click or drag, and build the appropriate structure. */ 4139 a press, click or drag, and build the appropriate structure. */
4097 case mouse_click: 4140 case mouse_click:
4141#ifndef USE_TOOLKIT_SCROLL_BARS
4098 case scroll_bar_click: 4142 case scroll_bar_click:
4143#endif
4099 { 4144 {
4100 int button = event->code; 4145 int button = event->code;
4101 int is_double; 4146 int is_double;
@@ -4113,6 +4158,7 @@ make_lispy_event (event)
4113 FRAME_PTR f = XFRAME (event->frame_or_window); 4158 FRAME_PTR f = XFRAME (event->frame_or_window);
4114 Lisp_Object window; 4159 Lisp_Object window;
4115 Lisp_Object posn; 4160 Lisp_Object posn;
4161 Lisp_Object string_info = Qnil;
4116 int row, column; 4162 int row, column;
4117 4163
4118 /* Ignore mouse events that were made on frame that 4164 /* Ignore mouse events that were made on frame that
@@ -4120,8 +4166,13 @@ make_lispy_event (event)
4120 if (! FRAME_LIVE_P (f)) 4166 if (! FRAME_LIVE_P (f))
4121 return Qnil; 4167 return Qnil;
4122 4168
4123 pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y), 4169 /* EVENT->x and EVENT->y are frame-relative pixel
4124 &column, &row, NULL, 1); 4170 coordinates at this place. Under old redisplay, COLUMN
4171 and ROW are set to frame relative glyph coordinates
4172 which are then used to determine whether this click is
4173 in a menu (non-toolkit version). */
4174 pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
4175 &column, &row, NULL, 1);
4125 4176
4126#ifndef USE_X_TOOLKIT 4177#ifndef USE_X_TOOLKIT
4127 /* In the non-toolkit version, clicks on the menu bar 4178 /* In the non-toolkit version, clicks on the menu bar
@@ -4146,6 +4197,7 @@ make_lispy_event (event)
4146 return Qnil; 4197 return Qnil;
4147#endif 4198#endif
4148 4199
4200 /* Find the menu bar item under `column'. */
4149 item = Qnil; 4201 item = Qnil;
4150 items = FRAME_MENU_BAR_ITEMS (f); 4202 items = FRAME_MENU_BAR_ITEMS (f);
4151 for (i = 0; i < XVECTOR (items)->size; i += 4) 4203 for (i = 0; i < XVECTOR (items)->size; i += 4)
@@ -4163,6 +4215,8 @@ make_lispy_event (event)
4163 } 4215 }
4164 } 4216 }
4165 4217
4218 /* ELisp manual 2.4b says (x y) are window relative but
4219 code says they are frame-relative. */
4166 position 4220 position
4167 = Fcons (event->frame_or_window, 4221 = Fcons (event->frame_or_window,
4168 Fcons (Qmenu_bar, 4222 Fcons (Qmenu_bar,
@@ -4174,7 +4228,10 @@ make_lispy_event (event)
4174 } 4228 }
4175#endif /* not USE_X_TOOLKIT */ 4229#endif /* not USE_X_TOOLKIT */
4176 4230
4177 window = window_from_coordinates (f, column, row, &part); 4231 /* Set `window' to the window under frame pixel coordinates
4232 event->x/event->y. */
4233 window = window_from_coordinates (f, XINT (event->x),
4234 XINT (event->y), &part, 0);
4178 4235
4179 if (!WINDOWP (window)) 4236 if (!WINDOWP (window))
4180 { 4237 {
@@ -4183,21 +4240,36 @@ make_lispy_event (event)
4183 } 4240 }
4184 else 4241 else
4185 { 4242 {
4186 int pixcolumn, pixrow; 4243 /* It's a click in window window at frame coordinates
4187 column -= WINDOW_LEFT_MARGIN (XWINDOW (window)); 4244 event->x/ event->y. */
4188 row -= XINT (XWINDOW (window)->top); 4245 struct window *w = XWINDOW (window);
4189 glyph_to_pixel_coords (f, column, row, &pixcolumn, &pixrow); 4246
4190 XSETINT (event->x, pixcolumn); 4247 /* Get window relative coordinates. Original code
4191 XSETINT (event->y, pixrow); 4248 `rounded' this to glyph boundaries. */
4192 4249 int wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (event->x));
4193 if (part == 1) 4250 int wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (event->y));
4194 posn = Qmode_line; 4251
4252 /* Set event coordinates to window-relative coordinates
4253 for constructing the Lisp event below. */
4254 XSETINT (event->x, wx);
4255 XSETINT (event->y, wy);
4256
4257 if (part == 1 || part == 3)
4258 {
4259 /* Mode line or top line. Look for a string under
4260 the mouse that may have a `local-map' property. */
4261 Lisp_Object string;
4262 int charpos;
4263
4264 posn = part == 1 ? Qmode_line : Qtop_line;
4265 string = mode_line_string (w, wx, wy, part == 1, &charpos);
4266 if (STRINGP (string))
4267 string_info = Fcons (string, make_number (charpos));
4268 }
4195 else if (part == 2) 4269 else if (part == 2)
4196 posn = Qvertical_line; 4270 posn = Qvertical_line;
4197 else 4271 else
4198 XSETINT (posn, 4272 XSETINT (posn, buffer_posn_from_coords (w, &wx, &wy));
4199 buffer_posn_from_coords (XWINDOW (window),
4200 column, row));
4201 } 4273 }
4202 4274
4203 position 4275 position
@@ -4205,10 +4277,14 @@ make_lispy_event (event)
4205 Fcons (posn, 4277 Fcons (posn,
4206 Fcons (Fcons (event->x, event->y), 4278 Fcons (Fcons (event->x, event->y),
4207 Fcons (make_number (event->timestamp), 4279 Fcons (make_number (event->timestamp),
4208 Qnil)))); 4280 (NILP (string_info)
4281 ? Qnil
4282 : Fcons (string_info, Qnil))))));
4209 } 4283 }
4284#ifndef USE_TOOLKIT_SCROLL_BARS
4210 else 4285 else
4211 { 4286 {
4287 /* It's a scrollbar click. */
4212 Lisp_Object window; 4288 Lisp_Object window;
4213 Lisp_Object portion_whole; 4289 Lisp_Object portion_whole;
4214 Lisp_Object part; 4290 Lisp_Object part;
@@ -4224,6 +4300,7 @@ make_lispy_event (event)
4224 Fcons (make_number (event->timestamp), 4300 Fcons (make_number (event->timestamp),
4225 Fcons (part, Qnil))))); 4301 Fcons (part, Qnil)))));
4226 } 4302 }
4303#endif /* not USE_TOOLKIT_SCROLL_BARS */
4227 4304
4228 start_pos_ptr = &XVECTOR (button_down_location)->contents[button]; 4305 start_pos_ptr = &XVECTOR (button_down_location)->contents[button];
4229 4306
@@ -4335,6 +4412,55 @@ make_lispy_event (event)
4335 } 4412 }
4336 } 4413 }
4337 4414
4415#if USE_TOOLKIT_SCROLL_BARS
4416
4417 /* We don't have down and up events if using toolkit scroll bars,
4418 so make this always a click event. Store in the `part' of
4419 the Lisp event a symbol which maps to the following actions:
4420
4421 `above_handle' page up
4422 `below_handle' page down
4423 `up' line up
4424 `down' line down
4425 `top' top of buffer
4426 `bottom' bottom of buffer
4427 `handle' thumb has been dragged.
4428 `end-scroll' end of interaction with scroll bar
4429
4430 The incoming input_event contains in its `part' member an
4431 index of type `enum scroll_bar_part' which we can use as an
4432 index in scroll_bar_parts to get the appropriate symbol. */
4433
4434 case scroll_bar_click:
4435 {
4436 Lisp_Object position, head, window, portion_whole, part;
4437
4438 window = event->frame_or_window;
4439 portion_whole = Fcons (event->x, event->y);
4440 part = *scroll_bar_parts[(int) event->part];
4441
4442 position
4443 = Fcons (window,
4444 Fcons (Qvertical_scroll_bar,
4445 Fcons (portion_whole,
4446 Fcons (make_number (event->timestamp),
4447 Fcons (part, Qnil)))));
4448
4449 /* Always treat scroll bar events as clicks. */
4450 event->modifiers |= click_modifier;
4451
4452 /* Get the symbol we should use for the mouse click. */
4453 head = modify_event_symbol (event->code,
4454 event->modifiers,
4455 Qmouse_click, Qnil,
4456 lispy_mouse_names, &mouse_syms,
4457 (sizeof (lispy_mouse_names)
4458 / sizeof (lispy_mouse_names[0])));
4459 return Fcons (head, Fcons (position, Qnil));
4460 }
4461
4462#endif /* USE_TOOLKIT_SCROLL_BARS */
4463
4338#ifdef WINDOWSNT 4464#ifdef WINDOWSNT
4339 case w32_scroll_bar_click: 4465 case w32_scroll_bar_click:
4340 { 4466 {
@@ -4397,7 +4523,7 @@ make_lispy_event (event)
4397 return Qnil; 4523 return Qnil;
4398 pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y), 4524 pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
4399 &column, &row, NULL, 1); 4525 &column, &row, NULL, 1);
4400 window = window_from_coordinates (f, column, row, &part); 4526 window = window_from_coordinates (f, column, row, &part, 0);
4401 4527
4402 if (!WINDOWP (window)) 4528 if (!WINDOWP (window))
4403 { 4529 {
@@ -4417,6 +4543,8 @@ make_lispy_event (event)
4417 posn = Qmode_line; 4543 posn = Qmode_line;
4418 else if (part == 2) 4544 else if (part == 2)
4419 posn = Qvertical_line; 4545 posn = Qvertical_line;
4546 else if (part == 3)
4547 posn = Qtop_line;
4420 else 4548 else
4421 XSETINT (posn, 4549 XSETINT (posn,
4422 buffer_posn_from_coords (XWINDOW (window), 4550 buffer_posn_from_coords (XWINDOW (window),
@@ -4470,7 +4598,7 @@ make_lispy_event (event)
4470 return Qnil; 4598 return Qnil;
4471 pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y), 4599 pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
4472 &column, &row, NULL, 1); 4600 &column, &row, NULL, 1);
4473 window = window_from_coordinates (f, column, row, &part); 4601 window = window_from_coordinates (f, column, row, &part, 0);
4474 4602
4475 if (!WINDOWP (window)) 4603 if (!WINDOWP (window))
4476 { 4604 {
@@ -4479,21 +4607,27 @@ make_lispy_event (event)
4479 } 4607 }
4480 else 4608 else
4481 { 4609 {
4482 int pixcolumn, pixrow; 4610 /* It's an event in window `window' at frame coordinates
4483 column -= XINT (XWINDOW (window)->left); 4611 event->x/ event->y. */
4484 row -= XINT (XWINDOW (window)->top); 4612 struct window *w = XWINDOW (window);
4485 glyph_to_pixel_coords (f, column, row, &pixcolumn, &pixrow); 4613
4486 XSETINT (event->x, pixcolumn); 4614 /* Get window relative coordinates. */
4487 XSETINT (event->y, pixrow); 4615 int wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (event->x));
4616 int wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (event->y));
4617
4618 /* Set event coordinates to window-relative coordinates
4619 for constructing the Lisp event below. */
4620 XSETINT (event->x, wx);
4621 XSETINT (event->y, wy);
4488 4622
4489 if (part == 1) 4623 if (part == 1)
4490 posn = Qmode_line; 4624 posn = Qmode_line;
4491 else if (part == 2) 4625 else if (part == 2)
4492 posn = Qvertical_line; 4626 posn = Qvertical_line;
4627 else if (part == 3)
4628 posn = Qtop_line;
4493 else 4629 else
4494 XSETINT (posn, 4630 XSETINT (posn, buffer_posn_from_coords (w, &wx, &wy));
4495 buffer_posn_from_coords (XWINDOW (window),
4496 column, row));
4497 } 4631 }
4498 4632
4499 { 4633 {
@@ -4526,6 +4660,17 @@ make_lispy_event (event)
4526 return XCONS (event->frame_or_window)->cdr; 4660 return XCONS (event->frame_or_window)->cdr;
4527#endif 4661#endif
4528 4662
4663 case TOOLBAR_EVENT:
4664 {
4665 Lisp_Object key;
4666 if (!CONSP (event->frame_or_window))
4667 abort ();
4668 key = XCDR (event->frame_or_window);
4669 if (SYMBOLP (key))
4670 key = apply_modifiers (event->modifiers, key);
4671 return key;
4672 }
4673
4529 case user_signal: 4674 case user_signal:
4530 /* A user signal. */ 4675 /* A user signal. */
4531 return *lispy_user_signals[event->code]; 4676 return *lispy_user_signals[event->code];
@@ -4568,34 +4713,34 @@ make_lispy_movement (frame, bar_window, part, x, y, time)
4568 int area; 4713 int area;
4569 Lisp_Object window; 4714 Lisp_Object window;
4570 Lisp_Object posn; 4715 Lisp_Object posn;
4571 int column, row;
4572 4716
4573 if (frame) 4717 if (frame)
4574 { 4718 /* It's in a frame; which window on that frame? */
4575 /* It's in a frame; which window on that frame? */ 4719 window = window_from_coordinates (frame, XINT (x), XINT (y), &area, 0);
4576 pixel_to_glyph_coords (frame, XINT (x), XINT (y), &column, &row,
4577 NULL, 1);
4578 window = window_from_coordinates (frame, column, row, &area);
4579 }
4580 else 4720 else
4581 window = Qnil; 4721 window = Qnil;
4582 4722
4583 if (WINDOWP (window)) 4723 if (WINDOWP (window))
4584 { 4724 {
4585 int pixcolumn, pixrow; 4725 struct window *w = XWINDOW (window);
4586 column -= WINDOW_LEFT_MARGIN (XWINDOW (window)); 4726 int hpos, vpos;
4587 row -= XINT (XWINDOW (window)->top); 4727 int wx, wy;
4588 glyph_to_pixel_coords (frame, column, row, &pixcolumn, &pixrow); 4728 int pos;
4589 XSETINT (x, pixcolumn); 4729
4590 XSETINT (y, pixrow); 4730 /* Get window relative coordinates. */
4591 4731 wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (x));
4732 wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (y));
4733 XSETINT (x, wx);
4734 XSETINT (y, wy);
4735
4592 if (area == 1) 4736 if (area == 1)
4593 posn = Qmode_line; 4737 posn = Qmode_line;
4594 else if (area == 2) 4738 else if (area == 2)
4595 posn = Qvertical_line; 4739 posn = Qvertical_line;
4740 else if (area == 3)
4741 posn = Qtop_line;
4596 else 4742 else
4597 XSETINT (posn, 4743 XSETINT (posn, buffer_posn_from_coords (w, &wx, &wy));
4598 buffer_posn_from_coords (XWINDOW (window), column, row));
4599 } 4744 }
4600 else if (frame != 0) 4745 else if (frame != 0)
4601 { 4746 {
@@ -5846,7 +5991,7 @@ menu_item_eval_property_1 (arg)
5846 5991
5847/* Evaluate an expression and return the result (or nil if something 5992/* Evaluate an expression and return the result (or nil if something
5848 went wrong). Used to evaluate dynamic parts of menu items. */ 5993 went wrong). Used to evaluate dynamic parts of menu items. */
5849static Lisp_Object 5994Lisp_Object
5850menu_item_eval_property (sexpr) 5995menu_item_eval_property (sexpr)
5851 Lisp_Object sexpr; 5996 Lisp_Object sexpr;
5852{ 5997{
@@ -6206,6 +6351,392 @@ parse_menu_item (item, notreal, inmenubar)
6206 6351
6207 return 1; 6352 return 1;
6208} 6353}
6354
6355
6356
6357/***********************************************************************
6358 Tool-bars
6359 ***********************************************************************/
6360
6361/* A vector holding toolbar items while they are parsed in function
6362 toolbar_items runs Each item occupies TOOLBAR_ITEM_NSCLOTS
6363 elements in the vector. */
6364
6365static Lisp_Object toolbar_items_vector;
6366
6367/* A vector holding the result of parse_toolbar_item. Layout is like
6368 the one for a single item in toolbar_items_vector. */
6369
6370static Lisp_Object toolbar_item_properties;
6371
6372/* Next free index in toolbar_items_vector. */
6373
6374static int ntoolbar_items;
6375
6376/* The symbols `toolbar', `toolbar-item', and `:image'. */
6377
6378extern Lisp_Object Qtoolbar;
6379Lisp_Object QCimage;
6380
6381/* Function prototypes. */
6382
6383static void init_toolbar_items P_ ((Lisp_Object));
6384static void process_toolbar_item P_ ((Lisp_Object, Lisp_Object));
6385static int parse_toolbar_item P_ ((Lisp_Object, Lisp_Object));
6386static void append_toolbar_item P_ ((void));
6387
6388
6389/* Return a vector of toolbar items for keymaps currently in effect.
6390 Reuse vector REUSE if non-nil. Return in *NITEMS the number of
6391 toolbar items found. */
6392
6393Lisp_Object
6394toolbar_items (reuse, nitems)
6395 Lisp_Object reuse;
6396 int *nitems;
6397{
6398 Lisp_Object *maps;
6399 int nmaps, i;
6400 Lisp_Object oquit;
6401 Lisp_Object *tmaps;
6402 extern Lisp_Object Voverriding_local_map_menu_flag;
6403 extern Lisp_Object Voverriding_local_map;
6404
6405 *nitems = 0;
6406
6407 /* In order to build the menus, we need to call the keymap
6408 accessors. They all call QUIT. But this function is called
6409 during redisplay, during which a quit is fatal. So inhibit
6410 quitting while building the menus. We do this instead of
6411 specbind because (1) errors will clear it anyway and (2) this
6412 avoids risk of specpdl overflow. */
6413 oquit = Vinhibit_quit;
6414 Vinhibit_quit = Qt;
6415
6416 /* Initialize toolbar_items_vector and protect it from GC. */
6417 init_toolbar_items (reuse);
6418
6419 /* Build list of keymaps in maps. Set nmaps to the number of maps
6420 to process. */
6421
6422 /* Should overriding-terminal-local-map and overriding-local-map apply? */
6423 if (!NILP (Voverriding_local_map_menu_flag))
6424 {
6425 /* Yes, use them (if non-nil) as well as the global map. */
6426 maps = (Lisp_Object *) alloca (3 * sizeof (maps[0]));
6427 nmaps = 0;
6428 if (!NILP (current_kboard->Voverriding_terminal_local_map))
6429 maps[nmaps++] = current_kboard->Voverriding_terminal_local_map;
6430 if (!NILP (Voverriding_local_map))
6431 maps[nmaps++] = Voverriding_local_map;
6432 }
6433 else
6434 {
6435 /* No, so use major and minor mode keymaps. */
6436 nmaps = current_minor_maps (NULL, &tmaps);
6437 maps = (Lisp_Object *) alloca ((nmaps + 2) * sizeof (maps[0]));
6438 bcopy (tmaps, maps, nmaps * sizeof (maps[0]));
6439#ifdef USE_TEXT_PROPERTIES
6440 maps[nmaps++] = get_local_map (PT, current_buffer);
6441#else
6442 maps[nmaps++] = current_buffer->keymap;
6443#endif
6444 }
6445
6446 /* Add global keymap at the end. */
6447 maps[nmaps++] = current_global_map;
6448
6449 /* Process maps in reverse order and look up in each map the prefix
6450 key `toolbar'. */
6451 for (i = nmaps - 1; i >= 0; --i)
6452 if (!NILP (maps[i]))
6453 {
6454 Lisp_Object keymap;
6455
6456 keymap = get_keyelt (access_keymap (maps[i], Qtoolbar, 1, 1), 0);
6457 if (!NILP (Fkeymapp (keymap)))
6458 {
6459 Lisp_Object tail;
6460
6461 /* KEYMAP is a list `(keymap (KEY . BINDING) ...)'. */
6462 for (tail = keymap; CONSP (tail); tail = XCONS (tail)->cdr)
6463 {
6464 Lisp_Object keydef = XCAR (tail);
6465 if (CONSP (keydef))
6466 process_toolbar_item (XCAR (keydef), XCDR (keydef));
6467 }
6468 }
6469 }
6470
6471 Vinhibit_quit = oquit;
6472 *nitems = ntoolbar_items / TOOLBAR_ITEM_NSLOTS;
6473 return toolbar_items_vector;
6474}
6475
6476
6477/* Process the definition of KEY which is DEF. */
6478
6479static void
6480process_toolbar_item (key, def)
6481 Lisp_Object key, def;
6482{
6483 int i;
6484 extern Lisp_Object Qundefined;
6485 struct gcpro gcpro1, gcpro2;
6486
6487 /* Protect KEY and DEF from GC because parse_toolbar_item may call
6488 eval. */
6489 GCPRO2 (key, def);
6490
6491 if (EQ (def, Qundefined))
6492 {
6493 /* If a map has an explicit `undefined' as definition,
6494 discard any previously made item. */
6495 for (i = 0; i < ntoolbar_items; i += TOOLBAR_ITEM_NSLOTS)
6496 {
6497 Lisp_Object *v = XVECTOR (toolbar_items_vector)->contents + i;
6498
6499 if (EQ (key, v[TOOLBAR_ITEM_KEY]))
6500 {
6501 if (ntoolbar_items > i + TOOLBAR_ITEM_NSLOTS)
6502 bcopy (v + TOOLBAR_ITEM_NSLOTS, v,
6503 ((ntoolbar_items - i - TOOLBAR_ITEM_NSLOTS)
6504 * sizeof (Lisp_Object)));
6505 ntoolbar_items -= TOOLBAR_ITEM_NSLOTS;
6506 break;
6507 }
6508 }
6509 }
6510 else if (parse_toolbar_item (key, def))
6511 /* Append a new toolbar item to toolbar_items_vector. Accept
6512 more than one definition for the same key. */
6513 append_toolbar_item ();
6514
6515 UNGCPRO;
6516}
6517
6518
6519/* Parse a toolbar item specification ITEM for key KEY and return the
6520 result in toolbar_item_properties. Value is zero if ITEM is
6521 invalid.
6522
6523 ITEM is a list `(menu-item CAPTION BINDING PROPS...)'.
6524
6525 CAPTION is the caption of the item, If it's not a string, it is
6526 evaluated to get a string.
6527
6528 BINDING is the toolbar item's binding. Toolbar items with keymaps
6529 as binding are currently ignored.
6530
6531 The following properties are recognized:
6532
6533 - `:enable FORM'.
6534
6535 FORM is evaluated and specifies whether the toolbar item is enabled
6536 or disabled.
6537
6538 - `:visible FORM'
6539
6540 FORM is evaluated and specifies whether the toolbar item is visible.
6541
6542 - `:filter FUNCTION'
6543
6544 FUNCTION is invoked with one parameter `(quote BINDING)'. Its
6545 result is stored as the new binding.
6546
6547 - `:button (TYPE SELECTED)'
6548
6549 TYPE must be one of `:radio' or `:toggle'. SELECTED is evaluated
6550 and specifies whether the button is selected (pressed) or not.
6551
6552 - `:image IMAGES'
6553
6554 IMAGES is either a single image specification or a vector of four
6555 image specifications. See enum toolbar_item_images.
6556
6557 - `:help HELP-STRING'.
6558
6559 Gives a help string to display for the toolbar item. */
6560
6561static int
6562parse_toolbar_item (key, item)
6563 Lisp_Object key, item;
6564{
6565 /* Access slot with index IDX of vector toolbar_item_properties. */
6566#define PROP(IDX) XVECTOR (toolbar_item_properties)->contents[IDX]
6567
6568 Lisp_Object filter = Qnil;
6569 Lisp_Object caption;
6570 extern Lisp_Object QCenable, QCvisible, QChelp, QCfilter;
6571 extern Lisp_Object QCbutton, QCtoggle, QCradio;
6572 int i;
6573 struct gcpro gcpro1;
6574
6575 /* Defininition looks like `(toolbar-item CAPTION BINDING
6576 PROPS...)'. Rule out items that aren't lists, don't start with
6577 `toolbar-item' or whose rest following `toolbar-item' is not a
6578 list. */
6579 if (!CONSP (item)
6580 || !EQ (XCAR (item), Qmenu_item)
6581 || (item = XCDR (item),
6582 !CONSP (item)))
6583 return 0;
6584
6585 /* Create toolbar_item_properties vector if necessary. Reset it to
6586 defaults. */
6587 if (VECTORP (toolbar_item_properties))
6588 {
6589 for (i = 0; i < TOOLBAR_ITEM_NSLOTS; ++i)
6590 PROP (i) = Qnil;
6591 }
6592 else
6593 toolbar_item_properties
6594 = Fmake_vector (make_number (TOOLBAR_ITEM_NSLOTS), Qnil);
6595
6596 /* Set defaults. */
6597 PROP (TOOLBAR_ITEM_KEY) = key;
6598 PROP (TOOLBAR_ITEM_ENABLED_P) = Qt;
6599
6600 /* Get the caption of the item. If the caption is not a string,
6601 evaluate it to get a string. If we don't get a string, skip this
6602 item. */
6603 caption = XCAR (item);
6604 if (!STRINGP (caption))
6605 {
6606 caption = menu_item_eval_property (caption);
6607 if (!STRINGP (caption))
6608 return 0;
6609 }
6610 PROP (TOOLBAR_ITEM_CAPTION) = caption;
6611
6612 /* Give up if rest following the caption is not a list. */
6613 item = XCDR (item);
6614 if (!CONSP (item))
6615 return 0;
6616
6617 /* Store the binding. */
6618 PROP (TOOLBAR_ITEM_BINDING) = XCAR (item);
6619 item = XCDR (item);
6620
6621 /* Process the rest of the properties. */
6622 for (; CONSP (item) && CONSP (XCDR (item)); item = XCDR (XCDR (item)))
6623 {
6624 Lisp_Object key, value;
6625
6626 key = XCAR (item);
6627 value = XCAR (XCDR (item));
6628
6629 if (EQ (key, QCenable))
6630 /* `:enable FORM'. */
6631 PROP (TOOLBAR_ITEM_ENABLED_P) = value;
6632 else if (EQ (key, QCvisible))
6633 {
6634 /* `:visible FORM'. If got a visible property and that
6635 evaluates to nil then ignore this item. */
6636 if (NILP (menu_item_eval_property (value)))
6637 return 0;
6638 }
6639 else if (EQ (key, QChelp))
6640 /* `:help HELP-STRING'. */
6641 PROP (TOOLBAR_ITEM_HELP) = value;
6642 else if (EQ (key, QCfilter))
6643 /* ':filter FORM'. */
6644 filter = value;
6645 else if (EQ (key, QCbutton) && CONSP (value))
6646 {
6647 /* `:button (TYPE . SELECTED)'. */
6648 Lisp_Object type, selected;
6649
6650 type = XCAR (value);
6651 selected = XCDR (value);
6652 if (EQ (type, QCtoggle) || EQ (type, QCradio))
6653 {
6654 PROP (TOOLBAR_ITEM_SELECTED_P) = selected;
6655 PROP (TOOLBAR_ITEM_TYPE) = type;
6656 }
6657 }
6658 else if (EQ (key, QCimage)
6659 && (CONSP (value)
6660 || (VECTORP (value) && XVECTOR (value)->size == 4)))
6661 /* Value is either a single image specification or a vector
6662 of 4 such specifications for the different buttion states. */
6663 PROP (TOOLBAR_ITEM_IMAGES) = value;
6664 }
6665
6666 /* If got a filter apply it on binding. */
6667 if (!NILP (filter))
6668 PROP (TOOLBAR_ITEM_BINDING)
6669 = menu_item_eval_property (list2 (filter,
6670 list2 (Qquote,
6671 PROP (TOOLBAR_ITEM_BINDING))));
6672
6673 /* See if the binding is a keymap. Give up if it is. */
6674 if (!NILP (get_keymap_1 (PROP (TOOLBAR_ITEM_BINDING), 0, 1)))
6675 return 0;
6676
6677 /* Enable or disable selection of item. */
6678 if (!EQ (PROP (TOOLBAR_ITEM_ENABLED_P), Qt))
6679 PROP (TOOLBAR_ITEM_ENABLED_P)
6680 = menu_item_eval_property (PROP (TOOLBAR_ITEM_ENABLED_P));
6681
6682 /* Handle radio buttons or toggle boxes. */
6683 if (!NILP (PROP (TOOLBAR_ITEM_SELECTED_P)))
6684 PROP (TOOLBAR_ITEM_SELECTED_P)
6685 = menu_item_eval_property (PROP (TOOLBAR_ITEM_SELECTED_P));
6686
6687 return 1;
6688
6689#undef PROP
6690}
6691
6692
6693/* Initialize Vtoolbar_items. REUSE, if non-nil, is a vector that can
6694 be reused. */
6695
6696static void
6697init_toolbar_items (reuse)
6698 Lisp_Object reuse;
6699{
6700 if (VECTORP (reuse))
6701 toolbar_items_vector = reuse;
6702 else
6703 toolbar_items_vector = Fmake_vector (make_number (64), Qnil);
6704 ntoolbar_items = 0;
6705}
6706
6707
6708/* Append parsed toolbar item properties from toolbar_item_properties */
6709
6710static void
6711append_toolbar_item ()
6712{
6713 Lisp_Object *to, *from;
6714
6715 /* Enlarge toolbar_items_vector if necessary. */
6716 if (ntoolbar_items + TOOLBAR_ITEM_NSLOTS
6717 >= XVECTOR (toolbar_items_vector)->size)
6718 {
6719 Lisp_Object new_vector;
6720 int old_size = XVECTOR (toolbar_items_vector)->size;
6721
6722 new_vector = Fmake_vector (make_number (2 * old_size), Qnil);
6723 bcopy (XVECTOR (toolbar_items_vector)->contents,
6724 XVECTOR (new_vector)->contents,
6725 old_size * sizeof (Lisp_Object));
6726 toolbar_items_vector = new_vector;
6727 }
6728
6729 /* Append entries from toolbar_item_properties to the end of
6730 toolbar_items_vector. */
6731 to = XVECTOR (toolbar_items_vector)->contents + ntoolbar_items;
6732 from = XVECTOR (toolbar_item_properties)->contents;
6733 bcopy (from, to, TOOLBAR_ITEM_NSLOTS * sizeof *to);
6734 ntoolbar_items += TOOLBAR_ITEM_NSLOTS;
6735}
6736
6737
6738
6739
6209 6740
6210/* Read a character using menus based on maps in the array MAPS. 6741/* Read a character using menus based on maps in the array MAPS.
6211 NMAPS is the length of MAPS. Return nil if there are no menus in the maps. 6742 NMAPS is the length of MAPS. Return nil if there are no menus in the maps.
@@ -6269,7 +6800,8 @@ read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
6269 /* If we got to this point via a mouse click, 6800 /* If we got to this point via a mouse click,
6270 use a real menu for mouse selection. */ 6801 use a real menu for mouse selection. */
6271 if (EVENT_HAS_PARAMETERS (prev_event) 6802 if (EVENT_HAS_PARAMETERS (prev_event)
6272 && !EQ (XCONS (prev_event)->car, Qmenu_bar)) 6803 && !EQ (XCONS (prev_event)->car, Qmenu_bar)
6804 && !EQ (XCONS (prev_event)->car, Qtoolbar))
6273 { 6805 {
6274 /* Display the menu and get the selection. */ 6806 /* Display the menu and get the selection. */
6275 Lisp_Object *realmaps 6807 Lisp_Object *realmaps
@@ -7114,6 +7646,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
7114 7646
7115 window = POSN_WINDOW (EVENT_START (key)); 7647 window = POSN_WINDOW (EVENT_START (key));
7116 posn = POSN_BUFFER_POSN (EVENT_START (key)); 7648 posn = POSN_BUFFER_POSN (EVENT_START (key));
7649
7117 if (CONSP (posn)) 7650 if (CONSP (posn))
7118 { 7651 {
7119 /* We're looking at the second event of a 7652 /* We're looking at the second event of a
@@ -7154,15 +7687,18 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
7154 orig_local_map = get_local_map (PT, current_buffer); 7687 orig_local_map = get_local_map (PT, current_buffer);
7155 goto replay_sequence; 7688 goto replay_sequence;
7156 } 7689 }
7690
7157 /* For a mouse click, get the local text-property keymap 7691 /* For a mouse click, get the local text-property keymap
7158 of the place clicked on, rather than point. */ 7692 of the place clicked on, rather than point. */
7159 if (last_real_key_start == 0 && CONSP (XCONS (key)->cdr) 7693 if (last_real_key_start == 0
7694 && CONSP (XCONS (key)->cdr)
7160 && ! localized_local_map) 7695 && ! localized_local_map)
7161 { 7696 {
7162 Lisp_Object map_here, start, pos; 7697 Lisp_Object map_here, start, pos;
7163 7698
7164 localized_local_map = 1; 7699 localized_local_map = 1;
7165 start = EVENT_START (key); 7700 start = EVENT_START (key);
7701
7166 if (CONSP (start) && CONSP (XCONS (start)->cdr)) 7702 if (CONSP (start) && CONSP (XCONS (start)->cdr))
7167 { 7703 {
7168 pos = POSN_BUFFER_POSN (start); 7704 pos = POSN_BUFFER_POSN (start);
@@ -7191,11 +7727,33 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
7191 keybuf[t] = posn; 7727 keybuf[t] = posn;
7192 keybuf[t+1] = key; 7728 keybuf[t+1] = key;
7193 mock_input = t + 2; 7729 mock_input = t + 2;
7194 7730
7195 /* Zap the position in key, so we know that we've 7731 /* Zap the position in key, so we know that we've
7196 expanded it, and don't try to do so again. */ 7732 expanded it, and don't try to do so again. */
7197 POSN_BUFFER_POSN (EVENT_START (key)) 7733 POSN_BUFFER_POSN (EVENT_START (key))
7198 = Fcons (posn, Qnil); 7734 = Fcons (posn, Qnil);
7735
7736 /* If on a mode line string with a local keymap,
7737 reconsider the key sequence with that keymap. */
7738 if (CONSP (POSN_STRING (EVENT_START (key))))
7739 {
7740 Lisp_Object string, pos, map;
7741
7742 string = POSN_STRING (EVENT_START (key));
7743 pos = XCDR (string);
7744 string = XCAR (string);
7745
7746 if (pos >= 0
7747 && pos < XSTRING (string)->size
7748 && (map = Fget_text_property (pos, Qlocal_map,
7749 string),
7750 !NILP (map)))
7751 {
7752 orig_local_map = map;
7753 goto replay_sequence;
7754 }
7755 }
7756
7199 goto replay_key; 7757 goto replay_key;
7200 } 7758 }
7201 } 7759 }
@@ -7208,7 +7766,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
7208 posn = POSN_BUFFER_POSN (EVENT_START (key)); 7766 posn = POSN_BUFFER_POSN (EVENT_START (key));
7209 /* Handle menu-bar events: 7767 /* Handle menu-bar events:
7210 insert the dummy prefix event `menu-bar'. */ 7768 insert the dummy prefix event `menu-bar'. */
7211 if (EQ (posn, Qmenu_bar)) 7769 if (EQ (posn, Qmenu_bar) || EQ (posn, Qtoolbar))
7212 { 7770 {
7213 if (t + 1 >= bufsize) 7771 if (t + 1 >= bufsize)
7214 error ("Key sequence too long"); 7772 error ("Key sequence too long");
@@ -8085,7 +8643,7 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
8085 { 8643 {
8086 /* But first wait, and skip the message if there is input. */ 8644 /* But first wait, and skip the message if there is input. */
8087 int delay_time; 8645 int delay_time;
8088 if (echo_area_glyphs != 0) 8646 if (echo_area_glyphs != 0 || STRINGP (echo_area_message))
8089 /* This command displayed something in the echo area; 8647 /* This command displayed something in the echo area;
8090 so wait a few seconds, then display our suggestion message. */ 8648 so wait a few seconds, then display our suggestion message. */
8091 delay_time = (NUMBERP (Vsuggest_key_bindings) 8649 delay_time = (NUMBERP (Vsuggest_key_bindings)
@@ -8101,6 +8659,7 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
8101 Lisp_Object binding; 8659 Lisp_Object binding;
8102 char *newmessage; 8660 char *newmessage;
8103 char *oldmessage = echo_area_glyphs; 8661 char *oldmessage = echo_area_glyphs;
8662 Lisp_Object oldmessage_string = echo_area_message;
8104 int oldmessage_len = echo_area_glyphs_length; 8663 int oldmessage_len = echo_area_glyphs_length;
8105 int oldmultibyte = message_enable_multibyte; 8664 int oldmultibyte = message_enable_multibyte;
8106 8665
@@ -8119,7 +8678,13 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
8119 if (!NILP (Fsit_for ((NUMBERP (Vsuggest_key_bindings) 8678 if (!NILP (Fsit_for ((NUMBERP (Vsuggest_key_bindings)
8120 ? Vsuggest_key_bindings : make_number (2)), 8679 ? Vsuggest_key_bindings : make_number (2)),
8121 Qnil, Qnil))) 8680 Qnil, Qnil)))
8122 message2_nolog (oldmessage, oldmessage_len, oldmultibyte); 8681 {
8682 if (STRINGP (oldmessage_string))
8683 message3_nolog (oldmessage_string, oldmessage_len,
8684 oldmultibyte);
8685 else
8686 message2_nolog (oldmessage, oldmessage_len, oldmultibyte);
8687 }
8123 } 8688 }
8124 } 8689 }
8125 8690
@@ -8190,7 +8755,16 @@ detect_input_pending_run_timers (do_display)
8190 get_input_pending (&input_pending, 1); 8755 get_input_pending (&input_pending, 1);
8191 8756
8192 if (old_timers_run != timers_run && do_display) 8757 if (old_timers_run != timers_run && do_display)
8193 redisplay_preserve_echo_area (); 8758 {
8759 redisplay_preserve_echo_area ();
8760 /* The following fixes a bug when using lazy-lock with
8761 lazy-lock-defer-on-the-fly set to t, i.e. when fontifying
8762 from an idle timer function. The symptom of the bug is that
8763 the cursor sometimes doesn't become visible until the next X
8764 event is processed. --gerd. */
8765 if (rif)
8766 rif->flush_display (NULL);
8767 }
8194 8768
8195 return input_pending; 8769 return input_pending;
8196} 8770}
@@ -8369,10 +8943,7 @@ Also cancel any kbd macro being defined.")
8369 8943
8370 discard_tty_input (); 8944 discard_tty_input ();
8371 8945
8372 /* Without the cast, GCC complains that this assignment loses the 8946 kbd_fetch_ptr = kbd_store_ptr;
8373 volatile qualifier of kbd_store_ptr. Is there anything wrong
8374 with that? */
8375 kbd_fetch_ptr = (struct input_event *) kbd_store_ptr;
8376 Ffillarray (kbd_buffer_frame_or_window, Qnil); 8947 Ffillarray (kbd_buffer_frame_or_window, Qnil);
8377 input_pending = 0; 8948 input_pending = 0;
8378 8949
@@ -8658,7 +9229,6 @@ interrupt_signal (signalnum) /* If we don't have an argument, */
8658void 9229void
8659quit_throw_to_read_char () 9230quit_throw_to_read_char ()
8660{ 9231{
8661 quit_error_check ();
8662 sigfree (); 9232 sigfree ();
8663 /* Prevent another signal from doing this before we finish. */ 9233 /* Prevent another signal from doing this before we finish. */
8664 clear_waiting_for_input (); 9234 clear_waiting_for_input ();
@@ -8936,9 +9506,21 @@ struct event_head head_table[] = {
8936void 9506void
8937syms_of_keyboard () 9507syms_of_keyboard ()
8938{ 9508{
9509 /* Toolbars. */
9510 QCimage = intern (":image");
9511 staticpro (&QCimage);
9512
9513 staticpro (&Qhelp_echo);
9514 Qhelp_echo = intern ("help-echo");
9515
8939 staticpro (&item_properties); 9516 staticpro (&item_properties);
8940 item_properties = Qnil; 9517 item_properties = Qnil;
8941 9518
9519 staticpro (&toolbar_item_properties);
9520 toolbar_item_properties = Qnil;
9521 staticpro (&toolbar_items_vector);
9522 toolbar_items_vector = Qnil;
9523
8942 staticpro (&real_this_command); 9524 staticpro (&real_this_command);
8943 real_this_command = Qnil; 9525 real_this_command = Qnil;
8944 9526
@@ -9004,6 +9586,8 @@ syms_of_keyboard ()
9004 staticpro (&QCenable); 9586 staticpro (&QCenable);
9005 QCvisible = intern (":visible"); 9587 QCvisible = intern (":visible");
9006 staticpro (&QCvisible); 9588 staticpro (&QCvisible);
9589 QChelp = intern (":help");
9590 staticpro (&QChelp);
9007 QCfilter = intern (":filter"); 9591 QCfilter = intern (":filter");
9008 staticpro (&QCfilter); 9592 staticpro (&QCfilter);
9009 QCbutton = intern (":button"); 9593 QCbutton = intern (":button");
@@ -9036,6 +9620,12 @@ syms_of_keyboard ()
9036 staticpro (&Qup); 9620 staticpro (&Qup);
9037 Qdown = intern ("down"); 9621 Qdown = intern ("down");
9038 staticpro (&Qdown); 9622 staticpro (&Qdown);
9623 Qtop = intern ("top");
9624 staticpro (&Qtop);
9625 Qbottom = intern ("bottom");
9626 staticpro (&Qbottom);
9627 Qend_scroll = intern ("end-scroll");
9628 staticpro (&Qend_scroll);
9039 9629
9040 Qevent_kind = intern ("event-kind"); 9630 Qevent_kind = intern ("event-kind");
9041 staticpro (&Qevent_kind); 9631 staticpro (&Qevent_kind);
@@ -9493,6 +10083,11 @@ for guidance on what to do.");
9493This variable exists because `read-event' clears the echo area\n\ 10083This variable exists because `read-event' clears the echo area\n\
9494before running the input method. It is nil if there was no message."); 10084before running the input method. It is nil if there was no message.");
9495 Vinput_method_previous_message = Qnil; 10085 Vinput_method_previous_message = Qnil;
10086
10087 DEFVAR_LISP ("show-help-function", &Vshow_help_function,
10088 "If non-nil, the function that implements the display of help.\n\
10089It's called with one argument, the help string to display.");
10090 Vshow_help_function = Qnil;
9496} 10091}
9497 10092
9498void 10093void