/* Keyboard and mouse input; editor command loop.
Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994, 1995,
1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005 Free Software Foundation, Inc.
+ 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Emacs.
/* Nonzero means C-g should cause immediate error-signal. */
int immediate_quit;
+/* The user's hook function for outputting an error message. */
+Lisp_Object Vcommand_error_function;
+
/* The user's ERASE setting. */
Lisp_Object Vtty_erase_char;
command is stored in this-original-command. It is nil otherwise. */
Lisp_Object Vthis_original_command;
-/* The value of point when the last command was executed. */
+/* The value of point when the last command was started. */
int last_point_position;
/* The buffer that was current when the last command was started. */
Lisp_Object last_point_position_buffer;
+/* The window that was selected when the last command was started. */
+Lisp_Object last_point_position_window;
+
/* The frame in which the last input event occurred, or Qmacro if the
last event came from a macro. We use this to determine when to
generate switch-frame events. This may be cleared by functions
#endif
Lisp_Object Qdrag_n_drop;
Lisp_Object Qsave_session;
+#ifdef MAC_OS
+Lisp_Object Qmac_apple_event;
+#endif
/* Lisp_Object Qmouse_movement; - also an event header */
static EMACS_TIME timer_last_idleness_start_time;
+/* If non-nil, events produced by disabled menu items and tool-bar
+ buttons are not ignored. Help functions bind this to allow help on
+ those items and buttons. */
+Lisp_Object Venable_disabled_menus_and_buttons;
+
\f
/* Global variable declarations. */
else
echo_string = concat2 (echo_string, build_string (" "));
}
+ else if (STRINGP (echo_string))
+ echo_string = concat2 (echo_string, build_string (" "));
current_kboard->echo_string
= concat2 (echo_string, make_string (buffer, ptr - buffer));
/* Do nothing if we have already put a dash at the end. */
if (SCHARS (current_kboard->echo_string) > 1)
{
- Lisp_Object last_char, prev_char, idx;
+ Lisp_Object last_char, prev_char, idx;
- idx = make_number (SCHARS (current_kboard->echo_string) - 2);
- prev_char = Faref (current_kboard->echo_string, idx);
+ idx = make_number (SCHARS (current_kboard->echo_string) - 2);
+ prev_char = Faref (current_kboard->echo_string, idx);
- idx = make_number (SCHARS (current_kboard->echo_string) - 1);
- last_char = Faref (current_kboard->echo_string, idx);
+ idx = make_number (SCHARS (current_kboard->echo_string) - 1);
+ last_char = Faref (current_kboard->echo_string, idx);
- if (XINT (last_char) == '-' && XINT (prev_char) != ' ')
- return;
+ if (XINT (last_char) == '-' && XINT (prev_char) != ' ')
+ return;
}
/* Put a dash at the end of the buffer temporarily,
/* Handle throw from read_minibuf when using minibuffer
while it's active but we're in another window. */
if (STRINGP (val))
- Fsignal (Qerror, Fcons (val, Qnil));
+ xsignal1 (Qerror, val);
return unbind_to (count, Qnil);
}
Lisp_Object data;
char *context;
{
- Lisp_Object stream;
- int kill_emacs_p = 0;
struct frame *sf = SELECTED_FRAME ();
+ /* The immediate context is not interesting for Quits,
+ since they are asyncronous. */
+ if (EQ (XCAR (data), Qquit))
+ Vsignaling_function = Qnil;
+
Vquit_flag = Qnil;
Vinhibit_quit = Qt;
- clear_message (1, 0);
+ /* Use user's specified output function if any. */
+ if (!NILP (Vcommand_error_function))
+ call3 (Vcommand_error_function, data,
+ build_string (context ? context : ""),
+ Vsignaling_function);
/* If the window system or terminal frame hasn't been initialized
- yet, or we're not interactive, it's best to dump this message out
- to stderr and exit. */
- if (!sf->glyphs_initialized_p
- /* This is the case of the frame dumped with Emacs, when we're
- running under a window system. */
- || (!NILP (Vwindow_system)
- && !inhibit_window_system
- && FRAME_TERMCAP_P (sf))
- || noninteractive)
- {
- stream = Qexternal_debugging_output;
- kill_emacs_p = 1;
+ yet, or we're not interactive, write the message to stderr and exit. */
+ else if (!sf->glyphs_initialized_p
+ /* This is the case of the frame dumped with Emacs, when we're
+ running under a window system. */
+ || (!NILP (Vwindow_system)
+ && !inhibit_window_system
+ && FRAME_TERMCAP_P (sf))
+ || noninteractive)
+ {
+ print_error_message (data, Qexternal_debugging_output,
+ context, Vsignaling_function);
+ Fterpri (Qexternal_debugging_output);
+ Fkill_emacs (make_number (-1));
}
else
{
+ clear_message (1, 0);
Fdiscard_input ();
message_log_maybe_newline ();
bitch_at_user ();
- stream = Qt;
- }
- /* The immediate context is not interesting for Quits,
- since they are asyncronous. */
- if (EQ (XCAR (data), Qquit))
- Vsignaling_function = Qnil;
-
- print_error_message (data, stream, context, Vsignaling_function);
+ print_error_message (data, Qt, context, Vsignaling_function);
+ }
Vsignaling_function = Qnil;
-
- /* If the window system or terminal frame hasn't been initialized
- yet, or we're in -batch mode, this error should cause Emacs to exit. */
- if (kill_emacs_p)
- {
- Fterpri (stream);
- Fkill_emacs (make_number (-1));
- }
}
\f
Lisp_Object command_loop_1 ();
return Qnil;
}
\f
+#ifdef HAVE_MOUSE
+
+/* Restore mouse tracking enablement. See Ftrack_mouse for the only use
+ of this function. */
+
+static Lisp_Object
+tracking_off (old_value)
+ Lisp_Object old_value;
+{
+ do_mouse_tracking = old_value;
+ if (NILP (old_value))
+ {
+ /* Redisplay may have been preempted because there was input
+ available, and it assumes it will be called again after the
+ input has been processed. If the only input available was
+ the sort that we have just disabled, then we need to call
+ redisplay. */
+ if (!readable_events (READABLE_EVENTS_DO_TIMERS_NOW))
+ {
+ redisplay_preserve_echo_area (6);
+ get_input_pending (&input_pending,
+ READABLE_EVENTS_DO_TIMERS_NOW);
+ }
+ }
+ return Qnil;
+}
+
+DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0,
+ doc: /* Evaluate BODY with mouse movement events enabled.
+Within a `track-mouse' form, mouse motion generates input events that
+you can read with `read-event'.
+Normally, mouse motion is ignored.
+usage: (track-mouse BODY ...) */)
+ (args)
+ Lisp_Object args;
+{
+ int count = SPECPDL_INDEX ();
+ Lisp_Object val;
+
+ record_unwind_protect (tracking_off, do_mouse_tracking);
+
+ do_mouse_tracking = Qt;
+
+ val = Fprogn (args);
+ return unbind_to (count, val);
+}
+
+/* If mouse has moved on some frame, return one of those frames.
+ Return 0 otherwise. */
+
+static FRAME_PTR
+some_mouse_moved ()
+{
+ Lisp_Object tail, frame;
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ if (XFRAME (frame)->mouse_moved)
+ return XFRAME (frame);
+ }
+
+ return 0;
+}
+
+#endif /* HAVE_MOUSE */
+\f
/* This is the actual command reading loop,
sans error-handling encapsulation. */
Lisp_Object keybuf[30];
int i;
int no_direct;
- int prev_modiff;
+ int prev_modiff = 0;
struct buffer *prev_buffer = NULL;
#ifdef MULTI_KBOARD
int was_locked = single_kboard;
safe_run_hooks (Qdeferred_action_function);
}
- Vmemory_full = Qnil;
-
/* Do this after running Vpost_command_hook, for consistency. */
current_kboard->Vlast_command = Vthis_command;
current_kboard->Vreal_last_command = real_this_command;
if (minibuf_level
&& !NILP (echo_area_buffer[0])
- && EQ (minibuf_window, echo_area_window)
- && NUMBERP (Vminibuffer_message_timeout))
+ && EQ (minibuf_window, echo_area_window))
{
/* Bind inhibit-quit to t so that C-g gets read in
rather than quitting back to the minibuffer. */
int count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
- Fsit_for (Vminibuffer_message_timeout, Qnil, Qnil);
+ if (NUMBERP (Vminibuffer_message_timeout))
+ sit_for (Vminibuffer_message_timeout, 0, 2);
+ else
+ sit_for (Qt, 0, 2);
+
/* Clear the echo area. */
message2 (0, 0, 0);
safe_run_hooks (Qecho_area_clear_hook);
prev_buffer = current_buffer;
prev_modiff = MODIFF;
last_point_position = PT;
+ last_point_position_window = selected_window;
XSETBUFFER (last_point_position_buffer, prev_buffer);
/* By default, we adjust point to a boundary of a region that
if (SYMBOLP (cmd))
{
Lisp_Object cmd1;
- if (cmd1 = Fcommand_remapping (cmd), !NILP (cmd1))
+ if (cmd1 = Fcommand_remapping (cmd, Qnil), !NILP (cmd1))
cmd = cmd1;
}
safe_run_hooks_1 (hook)
Lisp_Object hook;
{
+ if (NILP (Vrun_hooks))
+ return Qnil;
return call1 (Vrun_hooks, Vinhibit_quit);
}
#ifdef HAVE_MOUSE
if (!noninteractive && STRINGP (help))
- help = call1 (Qmouse_fixup_help_message, help);
+ {
+ /* The mouse-fixup-help-message Lisp function can call
+ mouse_position_hook, which resets the mouse_moved flags.
+ This causes trouble if we are trying to read a mouse motion
+ event (i.e., if we are inside a `track-mouse' form), so we
+ restore the mouse_moved flag. */
+ FRAME_PTR f = NILP (do_mouse_tracking) ? NULL : some_mouse_moved ();
+ help = call1 (Qmouse_fixup_help_message, help);
+ if (f)
+ f->mouse_moved = 1;
+ }
#endif
if (STRINGP (help) || NILP (help))
if we used a mouse menu to read the input, or zero otherwise. If
USED_MOUSE_MENU is null, we don't dereference it.
+ If END_TIME is non-null, it is a pointer to an EMACS_TIME
+ specifying the maximum time to wait until. If no input arrives by
+ that time, stop waiting and return nil.
+
Value is t if we showed a menu and the user rejected it. */
Lisp_Object
-read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
+read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
int commandflag;
int nmaps;
Lisp_Object *maps;
Lisp_Object prev_event;
int *used_mouse_menu;
+ EMACS_TIME *end_time;
{
volatile Lisp_Object c;
- int count;
+ int count, jmpcount;
jmp_buf local_getcjmp;
jmp_buf save_jump;
volatile int key_already_recorded = 0;
c = XCAR (Vunread_command_events);
Vunread_command_events = XCDR (Vunread_command_events);
+ reread = 1;
+
+ /* Undo what sit-for did when it unread additional keys
+ inside universal-argument. */
+
+ if (CONSP (c)
+ && EQ (XCAR (c), Qt))
+ {
+ reread = 0;
+ c = XCDR (c);
+ }
+
/* Undo what read_char_x_menu_prompt did when it unread
additional keys returned by Fx_popup_menu. */
if (CONSP (c)
&& (EQ (c, Qtool_bar) || EQ (c, Qmenu_bar)))
*used_mouse_menu = 1;
- reread = 1;
goto reread_for_input_method;
}
around any call to sit_for or kbd_buffer_get_event;
it *must not* be in effect when we call redisplay. */
+ jmpcount = SPECPDL_INDEX ();
if (_setjmp (local_getcjmp))
{
/* We must have saved the outer value of getcjmp here,
so restore it now. */
restore_getcjmp (save_jump);
+ unbind_to (jmpcount, Qnil);
XSETINT (c, quit_char);
internal_last_event_frame = selected_frame;
Vlast_event_frame = internal_last_event_frame;
goto non_reread;
}
- timer_start_idle ();
+ /* Start idle timers if no time limit is supplied. We don't do it
+ if a time limit is supplied to avoid an infinite recursion in the
+ situation where an idle timer calls `sit-for'. */
+
+ if (!end_time)
+ timer_start_idle ();
/* If in middle of key sequence and minibuffer not active,
start echoing if enough time elapses. */
if (minibuf_level == 0
+ && !end_time
&& !current_kboard->immediate_echo
&& this_command_key_count > 0
&& ! noninteractive
/* Or not echoing before and echoing allowed. */
|| (!echo_kboard && ok_to_echo_at_next_pause)))
{
- Lisp_Object tem0;
-
/* After a mouse event, start echoing right away.
This is because we are probably about to display a menu,
and we don't want to delay before doing so. */
echo_now ();
else
{
- int sec, usec;
- double duration = extract_float (Vecho_keystrokes);
- sec = (int) duration;
- usec = (duration - sec) * 1000000;
+ Lisp_Object tem0;
+
save_getcjmp (save_jump);
restore_getcjmp (local_getcjmp);
- tem0 = sit_for (sec, usec, 1, 1, 0);
+ tem0 = sit_for (Vecho_keystrokes, 1, 1);
restore_getcjmp (save_jump);
if (EQ (tem0, Qt)
&& ! CONSP (Vunread_command_events))
c = read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu);
/* Now that we have read an event, Emacs is not idle. */
- timer_stop_idle ();
+ if (!end_time)
+ timer_stop_idle ();
goto exit;
}
&& XINT (Vauto_save_timeout) > 0)
{
Lisp_Object tem0;
+ int timeout = delay_level * XFASTINT (Vauto_save_timeout) / 4;
save_getcjmp (save_jump);
restore_getcjmp (local_getcjmp);
- tem0 = sit_for (delay_level * XFASTINT (Vauto_save_timeout) / 4,
- 0, 1, 1, 0);
+ tem0 = sit_for (make_number (timeout), 1, 1);
restore_getcjmp (save_jump);
if (EQ (tem0, Qt)
{
KBOARD *kb;
+ if (end_time)
+ {
+ EMACS_TIME now;
+ EMACS_GET_TIME (now);
+ if (EMACS_TIME_GE (now, *end_time))
+ goto exit;
+ }
+
/* Actually read a character, waiting if necessary. */
save_getcjmp (save_jump);
restore_getcjmp (local_getcjmp);
- timer_start_idle ();
- c = kbd_buffer_get_event (&kb, used_mouse_menu);
+ if (!end_time)
+ timer_start_idle ();
+ c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time);
restore_getcjmp (save_jump);
#ifdef MULTI_KBOARD
non_reread:
- timer_stop_idle ();
+ if (!end_time)
+ timer_stop_idle ();
RESUME_POLLING;
if (NILP (c))
last_input_char = c;
Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char), Qt);
- if (CONSP (c) && EQ (XCAR (c), Qselect_window))
+ if (CONSP (c) && EQ (XCAR (c), Qselect_window) && !end_time)
/* We stopped being idle for this event; undo that. This
prevents automatic window selection (under
mouse_autoselect_window from acting as a real input event, for
show_help_echo (help, window, object, position, 0);
/* We stopped being idle for this event; undo that. */
- timer_resume_idle ();
+ if (!end_time)
+ timer_resume_idle ();
goto retry;
}
- if (! reread || this_command_key_count == 0
- || this_command_key_count_reset)
+ if ((! reread || this_command_key_count == 0
+ || this_command_key_count_reset)
+ && !end_time)
{
/* Don't echo mouse motion events. */
cancel_echoing ();
do
- c = read_char (0, 0, 0, Qnil, 0);
+ c = read_char (0, 0, 0, Qnil, 0, NULL);
while (BUFFERP (c));
/* Remove the help from the frame */
unbind_to (count, Qnil);
{
cancel_echoing ();
do
- c = read_char (0, 0, 0, Qnil, 0);
+ c = read_char (0, 0, 0, Qnil, 0, NULL);
while (BUFFERP (c));
}
}
bcopy (temp, getcjmp, sizeof getcjmp);
}
\f
-#ifdef HAVE_MOUSE
-
-/* Restore mouse tracking enablement. See Ftrack_mouse for the only use
- of this function. */
-
-static Lisp_Object
-tracking_off (old_value)
- Lisp_Object old_value;
-{
- do_mouse_tracking = old_value;
- if (NILP (old_value))
- {
- /* Redisplay may have been preempted because there was input
- available, and it assumes it will be called again after the
- input has been processed. If the only input available was
- the sort that we have just disabled, then we need to call
- redisplay. */
- if (!readable_events (READABLE_EVENTS_DO_TIMERS_NOW))
- {
- redisplay_preserve_echo_area (6);
- get_input_pending (&input_pending,
- READABLE_EVENTS_DO_TIMERS_NOW);
- }
- }
- return Qnil;
-}
-
-DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0,
- doc: /* Evaluate BODY with mouse movement events enabled.
-Within a `track-mouse' form, mouse motion generates input events that
-you can read with `read-event'.
-Normally, mouse motion is ignored.
-usage: (track-mouse BODY ...) */)
- (args)
- Lisp_Object args;
-{
- int count = SPECPDL_INDEX ();
- Lisp_Object val;
-
- record_unwind_protect (tracking_off, do_mouse_tracking);
-
- do_mouse_tracking = Qt;
-
- val = Fprogn (args);
- return unbind_to (count, val);
-}
-
-/* If mouse has moved on some frame, return one of those frames.
- Return 0 otherwise. */
-
-static FRAME_PTR
-some_mouse_moved ()
-{
- Lisp_Object tail, frame;
-
- FOR_EACH_FRAME (tail, frame)
- {
- if (XFRAME (frame)->mouse_moved)
- return XFRAME (frame);
- }
-
- return 0;
-}
-
-#endif /* HAVE_MOUSE */
-\f
/* Low level keyboard/mouse input.
kbd_buffer_store_event places events in kbd_buffer, and
kbd_buffer_get_event retrieves them. */
We always read and discard one event. */
static Lisp_Object
-kbd_buffer_get_event (kbp, used_mouse_menu)
+kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
KBOARD **kbp;
int *used_mouse_menu;
+ EMACS_TIME *end_time;
{
register int c;
Lisp_Object obj;
if (!NILP (do_mouse_tracking) && some_mouse_moved ())
break;
#endif
- {
+ if (end_time)
+ {
+ EMACS_TIME duration;
+ EMACS_GET_TIME (duration);
+ if (EMACS_TIME_GE (duration, *end_time))
+ return Qnil; /* finished waiting */
+ else
+ {
+ EMACS_SUB_TIME (duration, *end_time, duration);
+ wait_reading_process_output (EMACS_SECS (duration),
+ EMACS_USECS (duration),
+ -1, 1, Qnil, NULL, 0);
+ }
+ }
+ else
wait_reading_process_output (0, 0, -1, 1, Qnil, NULL, 0);
- if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
- /* Pass 1 for EXPECT since we just waited to have input. */
- read_avail_input (1);
- }
+ if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
+ /* Pass 1 for EXPECT since we just waited to have input. */
+ read_avail_input (1);
#endif /* not VMS */
}
UNGCPRO;
return nexttime;
}
+
+DEFUN ("current-idle-time", Fcurrent_idle_time, Scurrent_idle_time, 0, 0, 0,
+ doc: /* Return the current length of Emacs idleness.
+The value is returned as a list of three integers. The first has the
+most significant 16 bits of the seconds, while the second has the
+least significant 16 bits. The third integer gives the microsecond
+count.
+
+The microsecond count is zero on systems that do not provide
+resolution finer than a second. */)
+ ()
+{
+ if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+ {
+ EMACS_TIME now, idleness_now;
+
+ EMACS_GET_TIME (now);
+ EMACS_SUB_TIME (idleness_now, now, timer_idleness_start_time);
+
+ return list3 (make_number ((EMACS_SECS (idleness_now) >> 16) & 0xffff),
+ make_number ((EMACS_SECS (idleness_now) >> 0) & 0xffff),
+ make_number (EMACS_USECS (idleness_now)));
+ }
+
+ return Qnil;
+}
\f
/* Caches for modify_event_symbol. */
static Lisp_Object accent_key_syms;
XSETINT (*x, wx);
XSETINT (*y, wy);
- if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
+ if (part == ON_TEXT)
+ {
+ wx += WINDOW_LEFT_MARGIN_WIDTH (w);
+ }
+ else if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
{
/* Mode line or header line. Look for a string under
the mouse that may have a `local-map' property. */
&object, &dx, &dy, &width, &height);
if (STRINGP (string))
string_info = Fcons (string, make_number (charpos));
+ if (part == ON_LEFT_MARGIN)
+ wx = 0;
+ else
+ wx = window_box_right_offset (w, TEXT_AREA) - 1;
}
- else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE)
+ else if (part == ON_LEFT_FRINGE)
{
- posn = (part == ON_LEFT_FRINGE) ? Qleft_fringe : Qright_fringe;
+ posn = Qleft_fringe;
rx = 0;
dx = wx;
- if (part == ON_RIGHT_FRINGE)
- dx -= (window_box_width (w, LEFT_MARGIN_AREA)
- + window_box_width (w, TEXT_AREA)
- + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
- ? window_box_width (w, RIGHT_MARGIN_AREA)
- : 0));
- else if (!WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
- dx -= window_box_width (w, LEFT_MARGIN_AREA);
+ wx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+ ? 0
+ : window_box_width (w, LEFT_MARGIN_AREA));
+ dx -= wx;
+ }
+ else if (part == ON_RIGHT_FRINGE)
+ {
+ posn = Qright_fringe;
+ rx = 0;
+ dx = wx;
+ wx = (window_box_width (w, LEFT_MARGIN_AREA)
+ + window_box_width (w, TEXT_AREA)
+ + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+ ? window_box_width (w, RIGHT_MARGIN_AREA)
+ : 0));
+ dx -= wx;
+ }
+ else
+ {
+ /* Note: We have no special posn for part == ON_SCROLL_BAR. */
+ wx = max (WINDOW_LEFT_MARGIN_WIDTH (w), wx);
}
if (textpos < 0)
struct display_pos p;
int dx2, dy2;
int width2, height2;
- wx = max (WINDOW_LEFT_MARGIN_WIDTH (w), wx);
string2 = buffer_posn_from_coords (w, &wx, &wy, &p,
&object2, &dx2, &dy2,
&width2, &height2);
Lisp_Object head, position;
Lisp_Object files;
- /* The frame_or_window field should be a cons of the frame in
- which the event occurred and a list of the filenames
- dropped. */
- if (! CONSP (event->frame_or_window))
- abort ();
-
- f = XFRAME (XCAR (event->frame_or_window));
- files = XCDR (event->frame_or_window);
+ f = XFRAME (event->frame_or_window);
+ files = event->arg;
/* Ignore mouse events that were made on frames that
have been deleted. */
case SAVE_SESSION_EVENT:
return Qsave_session;
+#ifdef MAC_OS
+ case MAC_APPLE_EVENT:
+ {
+ Lisp_Object spec[2];
+
+ spec[0] = event->x;
+ spec[1] = event->y;
+ return Fcons (Qmac_apple_event,
+ Fcons (Fvector (2, spec),
+ Fcons (event->arg, Qnil)));
+ }
+#endif
+
/* The 'kind' field of the event is something we don't recognize. */
default:
abort ();
if (SYMBOLP (item))
{
tem = Fget (item, Qmenu_enable);
- if (!NILP (tem))
+ if (!NILP (Venable_disabled_menus_and_buttons))
+ AREF (item_properties, ITEM_PROPERTY_ENABLE) = Qt;
+ else if (!NILP (tem))
AREF (item_properties, ITEM_PROPERTY_ENABLE) = tem;
}
}
item = XCDR (item);
if (EQ (tem, QCenable))
- AREF (item_properties, ITEM_PROPERTY_ENABLE) = XCAR (item);
+ {
+ if (!NILP (Venable_disabled_menus_and_buttons))
+ AREF (item_properties, ITEM_PROPERTY_ENABLE) = Qt;
+ else
+ AREF (item_properties, ITEM_PROPERTY_ENABLE) = XCAR (item);
+ }
else if (EQ (tem, QCvisible) && !notreal)
{
/* If got a visible property and that evaluates to nil
Lisp_Object prefix;
if (!NILP (tem))
- tem = Fkey_binding (tem, Qnil, Qnil);
+ tem = Fkey_binding (tem, Qnil, Qnil, Qnil);
prefix = AREF (item_properties, ITEM_PROPERTY_KEYEQ);
if (CONSP (prefix))
/* Function prototypes. */
static void init_tool_bar_items P_ ((Lisp_Object));
-static void process_tool_bar_item P_ ((Lisp_Object, Lisp_Object));
+static void process_tool_bar_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object, void*));
static int parse_tool_bar_item P_ ((Lisp_Object, Lisp_Object));
static void append_tool_bar_item P_ ((void));
keymap = get_keymap (access_keymap (maps[i], Qtool_bar, 1, 0, 1), 0, 1);
if (CONSP (keymap))
- {
- Lisp_Object tail;
-
- /* KEYMAP is a list `(keymap (KEY . BINDING) ...)'. */
- for (tail = keymap; CONSP (tail); tail = XCDR (tail))
- {
- Lisp_Object keydef = XCAR (tail);
- if (CONSP (keydef))
- process_tool_bar_item (XCAR (keydef), XCDR (keydef));
- }
- }
+ map_keymap (keymap, process_tool_bar_item, Qnil, NULL, 1);
}
Vinhibit_quit = oquit;
/* Process the definition of KEY which is DEF. */
static void
-process_tool_bar_item (key, def)
- Lisp_Object key, def;
+process_tool_bar_item (key, def, data, args)
+ Lisp_Object key, def, data;
+ void *args;
{
int i;
extern Lisp_Object Qundefined;
value = XCAR (XCDR (item));
if (EQ (key, QCenable))
- /* `:enable FORM'. */
- PROP (TOOL_BAR_ITEM_ENABLED_P) = value;
+ {
+ /* `:enable FORM'. */
+ if (!NILP (Venable_disabled_menus_and_buttons))
+ PROP (TOOL_BAR_ITEM_ENABLED_P) = Qt;
+ else
+ PROP (TOOL_BAR_ITEM_ENABLED_P) = value;
+ }
else if (EQ (key, QCvisible))
{
/* `:visible FORM'. If got a visible property and that
orig_defn_macro = current_kboard->defining_kbd_macro;
current_kboard->defining_kbd_macro = Qnil;
do
- obj = read_char (commandflag, 0, 0, Qt, 0);
+ obj = read_char (commandflag, 0, 0, Qt, 0, NULL);
while (BUFFERP (obj));
current_kboard->defining_kbd_macro = orig_defn_macro;
such as Vfunction_key_map and Vkey_translation_map. */
typedef struct keyremap
{
- Lisp_Object map, parent;
+ /* This is the map originally specified for this use. */
+ Lisp_Object parent;
+ /* This is a submap reached by looking up, in PARENT,
+ the events from START to END. */
+ Lisp_Object map;
+ /* Positions [START, END) in the key sequence buffer
+ are the key that we have scanned so far.
+ Those events are the ones that we will replace
+ if PAREHT maps them into a key sequence. */
int start, end;
} keyremap;
/* Handle a symbol whose function definition is a keymap
or an array. */
if (SYMBOLP (next) && !NILP (Ffboundp (next))
- && (!NILP (Farrayp (XSYMBOL (next)->function))
+ && (ARRAYP (XSYMBOL (next)->function)
|| KEYMAPP (XSYMBOL (next)->function)))
next = XSYMBOL (next)->function;
Lisp_Object next, key;
key = keybuf[fkey->end++];
- next = access_keymap_keyremap (fkey->map, key, prompt, doit);
+
+ if (KEYMAPP (fkey->parent))
+ next = access_keymap_keyremap (fkey->map, key, prompt, doit);
+ else
+ next = Qnil;
/* If keybuf[fkey->start..fkey->end] is bound in the
map and we're in a position to do the key remapping, replace it with
delayed_switch_frame = Qnil;
fkey.map = fkey.parent = Vfunction_key_map;
keytran.map = keytran.parent = Vkey_translation_map;
- /* If there is no translation-map, turn off scanning. */
- fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1;
- keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1;
+ fkey.start = fkey.end = 0;
+ keytran.start = keytran.end = 0;
if (INTERACTIVE)
{
/* Read the first char of the sequence specially, before setting
up any keymaps, in case a filter runs and switches buffers on us. */
first_event = read_char (NILP (prompt), 0, submaps, last_nonmenu_event,
- &junk);
+ &junk, NULL);
#endif /* GOBBLE_FIRST_EVENT */
orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
the initial keymaps from the current buffer. */
nmaps = 0;
- if (!NILP (current_kboard->Voverriding_terminal_local_map)
- || !NILP (Voverriding_local_map))
+ if (!NILP (current_kboard->Voverriding_terminal_local_map))
{
- if (3 > nmaps_allocated)
+ if (2 > nmaps_allocated)
{
- submaps = (Lisp_Object *) alloca (3 * sizeof (submaps[0]));
- defs = (Lisp_Object *) alloca (3 * sizeof (defs[0]));
- nmaps_allocated = 3;
+ submaps = (Lisp_Object *) alloca (2 * sizeof (submaps[0]));
+ defs = (Lisp_Object *) alloca (2 * sizeof (defs[0]));
+ nmaps_allocated = 2;
}
if (!NILP (current_kboard->Voverriding_terminal_local_map))
submaps[nmaps++] = current_kboard->Voverriding_terminal_local_map;
+ }
+ else if (!NILP (Voverriding_local_map))
+ {
+ if (2 > nmaps_allocated)
+ {
+ submaps = (Lisp_Object *) alloca (2 * sizeof (submaps[0]));
+ defs = (Lisp_Object *) alloca (2 * sizeof (defs[0]));
+ nmaps_allocated = 2;
+ }
if (!NILP (Voverriding_local_map))
submaps[nmaps++] = Voverriding_local_map;
}
#endif
key = read_char (NILP (prompt), nmaps,
(Lisp_Object *) submaps, last_nonmenu_event,
- &used_mouse_menu);
+ &used_mouse_menu, NULL);
}
/* read_char returns t when it shows a menu and the user rejects it.
if (!EQ (map_here, orig_local_map))
{
orig_local_map = map_here;
- keybuf[t] = key;
- mock_input = t + 1;
-
- goto replay_sequence;
+ ++localized_local_map;
}
+
map_here = get_local_map (XINT (pos),
current_buffer, Qkeymap);
if (!EQ (map_here, orig_keymap))
{
orig_keymap = map_here;
+ ++localized_local_map;
+ }
+
+ if (localized_local_map > 1)
+ {
keybuf[t] = key;
mock_input = t + 1;
keybuf[t - 1] = new_key;
mock_input = max (t, mock_input);
- fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1;
- keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1;
+ fkey.start = fkey.end = 0;
+ keytran.start = keytran.end = 0;
goto replay_sequence;
}
/* Don't downcase the last character if the caller says don't.
Don't downcase it if the result is undefined, either. */
if ((dont_downcase_last || first_binding >= nmaps)
+ && t > 0
&& t - 1 == original_uppercase_position)
keybuf[t - 1] = original_uppercase;
while (1)
{
- final = Findirect_function (cmd);
+ final = Findirect_function (cmd, Qnil);
if (CONSP (final) && (tem = Fcar (final), EQ (tem, Qautoload)))
{
\f
DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_command,
1, 1, "P",
- doc: /* Read function name, then read its arguments and call it. */)
+ doc: /* Read function name, then read its arguments and call it.
+
+To pass a numeric argument to the command you are invoking with, specify
+the numeric argument to this command.
+
+Noninteractively, the argument PREFIXARG is the prefix argument to
+give to the command you invoke, if it asks for an argument. */)
(prefixarg)
Lisp_Object prefixarg;
{
Qmouse_movement)))
{
/* But first wait, and skip the message if there is input. */
- int delay_time;
- if (!NILP (echo_area_buffer[0]))
- /* This command displayed something in the echo area;
- so wait a few seconds, then display our suggestion message. */
- delay_time = (NUMBERP (Vsuggest_key_bindings)
- ? XINT (Vsuggest_key_bindings) : 2);
+ Lisp_Object waited;
+
+ /* If this command displayed something in the echo area;
+ wait a few seconds, then display our suggestion message. */
+ if (NILP (echo_area_buffer[0]))
+ waited = sit_for (make_number (0), 0, 2);
+ else if (NUMBERP (Vsuggest_key_bindings))
+ waited = sit_for (Vsuggest_key_bindings, 0, 2);
else
- /* This command left the echo area empty,
- so display our message immediately. */
- delay_time = 0;
+ waited = sit_for (make_number (2), 0, 2);
- if (!NILP (Fsit_for (make_number (delay_time), Qnil, Qnil))
- && ! CONSP (Vunread_command_events))
+ if (!NILP (waited) && ! CONSP (Vunread_command_events))
{
Lisp_Object binding;
char *newmessage;
message2_nolog (newmessage,
strlen (newmessage),
STRING_MULTIBYTE (binding));
- if (!NILP (Fsit_for ((NUMBERP (Vsuggest_key_bindings)
- ? Vsuggest_key_bindings : make_number (2)),
- Qnil, Qnil))
- && message_p)
+ if (NUMBERP (Vsuggest_key_bindings))
+ waited = sit_for (Vsuggest_key_bindings, 0, 2);
+ else
+ waited = sit_for (make_number (2), 0, 2);
+
+ if (!NILP (waited) && message_p)
restore_message ();
unbind_to (count, Qnil);
if there is a doubt, the value is t. */)
()
{
- if (!NILP (Vunread_command_events) || unread_command_char != -1)
+ if (!NILP (Vunread_command_events) || unread_command_char != -1
+ || !NILP (Vunread_post_input_method_events)
+ || !NILP (Vunread_input_method_events))
return (Qt);
get_input_pending (&input_pending,
CHECK_LIVE_WINDOW (frame_or_window);
w = XWINDOW (frame_or_window);
- XSETINT (x, (WINDOW_TO_FRAME_PIXEL_X (w, XINT (x))
+ XSETINT (x, (XINT (x)
+ + WINDOW_LEFT_EDGE_X (w)
+ (NILP (whole)
? window_box_left_offset (w, TEXT_AREA)
- : - (WINDOW_LEFT_SCROLL_BAR_COLS (w)
- * WINDOW_FRAME_COLUMN_WIDTH (w)))));
+ : 0)));
XSETINT (y, WINDOW_TO_FRAME_PIXEL_Y (w, XINT (y)));
frame_or_window = w->frame;
}
{
Lisp_Object tem;
+ if (NILP (window))
+ window = selected_window;
+
tem = Fpos_visible_in_window_p (pos, window, Qt);
if (!NILP (tem))
- tem = Fposn_at_x_y (XCAR (tem), XCAR (XCDR (tem)), window, Qnil);
+ {
+ Lisp_Object x = XCAR (tem);
+ Lisp_Object y = XCAR (XCDR (tem));
+
+ /* Point invisible due to hscrolling? */
+ if (XINT (x) < 0)
+ return Qnil;
+ tem = Fposn_at_x_y (x, y, window, Qnil);
+ }
+
return tem;
}
Qsave_session = intern ("save-session");
staticpro (&Qsave_session);
+#ifdef MAC_OS
+ Qmac_apple_event = intern ("mac-apple-event");
+ staticpro (&Qmac_apple_event);
+#endif
+
Qusr1_signal = intern ("usr1-signal");
staticpro (&Qusr1_signal);
Qusr2_signal = intern ("usr2-signal");
Fset (Qinput_method_use_echo_area, Qnil);
last_point_position_buffer = Qnil;
+ last_point_position_window = Qnil;
{
struct event_head *p;
menu_bar_items_vector = Qnil;
staticpro (&menu_bar_items_vector);
+ defsubr (&Scurrent_idle_time);
defsubr (&Sevent_convert_list);
defsubr (&Sread_key_sequence);
defsubr (&Sread_key_sequence_vector);
DEFVAR_LISP ("unread-command-events", &Vunread_command_events,
doc: /* List of events to be read as the command input.
-These events are processed first, before actual keyboard input. */);
+These events are processed first, before actual keyboard input.
+Events read from this list are not normally added to `this-command-keys',
+as they will already have been added once as they were read for the first time.
+An element of the form (t . EVENT) forces EVENT to be added to that list. */);
Vunread_command_events = Qnil;
DEFVAR_INT ("unread-command-char", &unread_command_char,
DEFVAR_LISP ("unread-post-input-method-events", &Vunread_post_input_method_events,
doc: /* List of events to be processed as input by input methods.
-These events are processed after `unread-command-events', but
-before actual keyboard input. */);
+These events are processed before `unread-command-events'
+and actual keyboard input without given to `input-method-function'. */);
Vunread_post_input_method_events = Qnil;
DEFVAR_LISP ("unread-input-method-events", &Vunread_input_method_events,
doc: /* List of events to be processed as input by input methods.
These events are processed after `unread-command-events', but
-before actual keyboard input. */);
+before actual keyboard input.
+If there's an active input method, the events are given to
+`input-method-function'. */);
Vunread_input_method_events = Qnil;
DEFVAR_LISP ("meta-prefix-char", &meta_prefix_char,
The value of that variable is passed to `quit-flag' and later causes a
peculiar kind of quitting. */);
Vthrow_on_input = Qnil;
+
+ DEFVAR_LISP ("command-error-function", &Vcommand_error_function,
+ doc: /* If non-nil, function to output error messages.
+The arguments are the error data, a list of the form
+ (SIGNALED-CONDITIONS . SIGNAL-DATA)
+such as just as `condition-case' would bind its variable to,
+the context (a string which normally goes at the start of the message),
+and the Lisp function within which the error was signaled. */);
+ Vcommand_error_function = Qnil;
+
+ DEFVAR_LISP ("enable-disabled-menus-and-buttons",
+ &Venable_disabled_menus_and_buttons,
+ doc: /* If non-nil, don't ignore events produced by disabled menu items and tool-bar.
+
+Help functions bind this to allow help on disabled menu items
+and tool-bar buttons. */);
+ Venable_disabled_menus_and_buttons = Qnil;
}
void