/* 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, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Emacs.
during the current critical section. */
int interrupt_input_pending;
+/* This var should be (interrupt_input_pending || pending_atimers).
+ The QUIT macro checks this instead of interrupt_input_pending and
+ pending_atimers separately, to reduce code size. So, any code that
+ changes interrupt_input_pending or pending_atimers should update
+ this too. */
+#ifdef SYNC_INPUT
+int pending_signals;
+#endif
+
#define KBD_BUFFER_SIZE 4096
KBOARD *initial_kboard;
/* Total number of times command_loop has read a key sequence. */
EMACS_INT num_input_keys;
-/* Last input character read as a command. */
-Lisp_Object last_command_char;
+/* Last input event read as a command. */
+Lisp_Object last_command_event;
/* Last input character read as a command, not counting menus
reached by the mouse. */
Lisp_Object last_nonmenu_event;
-/* Last input character read for any purpose. */
-Lisp_Object last_input_char;
+/* Last input event read for any purpose. */
+Lisp_Object last_input_event;
/* If not Qnil, a list of objects to be read as subsequent command input. */
Lisp_Object Vunread_command_events;
Lisp_Object Qselect_window;
Lisp_Object Qhelp_echo;
+extern Lisp_Object Qremap;
+
#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
Lisp_Object Qmouse_fixup_help_message;
#endif
/* If the window system or terminal frame hasn't been initialized
yet, or we're not interactive, write the message to stderr and exit. */
else if (!sf->glyphs_initialized_p
- || FRAME_INITIAL_P (sf)
+ /* The initial frame is a special non-displaying frame. It
+ will be current in daemon mode when there are no frames
+ to display, and in non-daemon mode before the real frame
+ has finished initializing. If an error is thrown in the
+ latter case while creating the frame, then the frame
+ will never be displayed, so the safest thing to do is
+ write to stderr and quit. In daemon mode, there are
+ many other potential errors that do not prevent frames
+ from being created, so continuing as normal is better in
+ that case. */
+ || (!IS_DAEMON && FRAME_INITIAL_P (sf))
|| noninteractive)
{
print_error_message (data, Qexternal_debugging_output,
}
DEFUN ("top-level", Ftop_level, Stop_level, 0, 0, "",
- doc: /* Exit all recursive editing levels. */)
+ doc: /* Exit all recursive editing levels.
+This also exits all active minibuffers. */)
()
{
#ifdef HAVE_WINDOW_SYSTEM
/* Do this after running Vpost_command_hook, for consistency. */
current_kboard->Vlast_command = Vthis_command;
current_kboard->Vreal_last_command = real_this_command;
- if (!CONSP (last_command_char))
+ if (!CONSP (last_command_event))
current_kboard->Vlast_repeatable_command = real_this_command;
while (1)
Is this a good idea? */
if (FRAMEP (internal_last_event_frame)
&& !EQ (internal_last_event_frame, selected_frame))
- Fselect_frame (internal_last_event_frame);
+ Fselect_frame (internal_last_event_frame, Qnil);
#endif
/* If it has changed current-menubar from previous value,
really recompute the menubar from the value. */
goto finalize;
}
- last_command_char = keybuf[i - 1];
+ last_command_event = keybuf[i - 1];
/* If the previous command tried to force a specific window-start,
forget about that, in case this command moves point far away
}
else if (EQ (Vthis_command, Qself_insert_command)
/* Try this optimization only on char keystrokes. */
- && NATNUMP (last_command_char)
- && CHAR_VALID_P (XFASTINT (last_command_char), 0))
+ && NATNUMP (last_command_event)
+ && CHAR_VALID_P (XFASTINT (last_command_event), 0))
{
unsigned int c
= translate_char (Vtranslation_table_for_input,
- XFASTINT (last_command_char));
+ XFASTINT (last_command_event));
int value;
if (NILP (Vexecuting_kbd_macro)
&& !EQ (minibuf_window, selected_window))
If the command didn't actually create a prefix arg,
but is merely a frame event that is transparent to prefix args,
then the above doesn't apply. */
- if (NILP (current_kboard->Vprefix_arg) || CONSP (last_command_char))
+ if (NILP (current_kboard->Vprefix_arg) || CONSP (last_command_event))
{
current_kboard->Vlast_command = Vthis_command;
current_kboard->Vreal_last_command = real_this_command;
- if (!CONSP (last_command_char))
+ if (!CONSP (last_command_event))
current_kboard->Vlast_repeatable_command = real_this_command;
cancel_echoing ();
this_command_key_count = 0;
/* FIXME: check `intangible'. */
if (check_composition
&& PT > BEGV && PT < ZV
- && get_property_and_range (PT, Qcomposition, &val, &beg, &end, Qnil)
- && COMPOSITION_VALID_P (beg, end, val)
- && beg < PT /* && end > PT <- It's always the case. */
- && (last_pt <= beg || last_pt >= end))
+ && (beg = composition_adjust_point (last_pt)) != PT)
{
- xassert (end > PT);
- SET_PT (PT < last_pt ? beg : end);
+ SET_PT (beg);
check_display = check_invisible = 1;
}
check_composition = 0;
/* Find boundaries `beg' and `end' of the invisible area, if any. */
while (end < ZV
+ /* Stop if we find a spot between two runs of
+ `invisible' where inserted text would be visible.
+ This is important when we have two invisible
+ boundaries that enclose an area: if the area is
+ empty, we need this test in order to make it
+ possible to place point in the middle rather than
+ skip both boundaries.
+ Note that this will stop anywhere in a non-sticky
+ text-property, but I don't think there's much we
+ can do about that. */
+ && (val = get_pos_property (make_number (end),
+ Qinvisible, Qnil),
+ TEXT_PROP_MEANS_INVISIBLE (val))
+ /* FIXME: write and then use get_pos_property_and_overlay. */
&& !NILP (val = get_char_property_and_overlay
(make_number (end), Qinvisible, Qnil, &overlay))
&& (inv = TEXT_PROP_MEANS_INVISIBLE (val)))
end = NATNUMP (tmp) ? XFASTINT (tmp) : ZV;
}
while (beg > BEGV
+ && (val = get_pos_property (make_number (beg),
+ Qinvisible, Qnil),
+ TEXT_PROP_MEANS_INVISIBLE (val))
&& !NILP (val = get_char_property_and_overlay
(make_number (beg - 1), Qinvisible, Qnil, &overlay))
&& (inv = TEXT_PROP_MEANS_INVISIBLE (val)))
#ifdef POLL_FOR_INPUT
-/* Poll for input, so what we catch a C-g if it comes in. This
+/* Poll for input, so that we catch a C-g if it comes in. This
function is called from x_make_frame_visible, see comment
there. */
void
poll_for_input_1 ()
{
+/* Tell ns_read_socket() it is being called asynchronously so it can avoid
+ doing anything dangerous. */
+#ifdef HAVE_NS
+ ++handling_signal;
+#endif
if (interrupt_input_blocked == 0
&& !waiting_for_input)
read_avail_input (0);
+#ifdef HAVE_NS
+ --handling_signal;
+#endif
}
/* Timer callback function for poll_timer. TIMER is equal to
struct atimer *timer;
{
if (poll_suppress_count == 0)
+ {
#ifdef SYNC_INPUT
- interrupt_input_pending = 1;
+ interrupt_input_pending = 1;
+ pending_signals = 1;
#else
- poll_for_input_1 ();
+ poll_for_input_1 ();
#endif
+ }
}
#endif /* POLL_FOR_INPUT */
static Lisp_Object help_form_saved_window_configs;
static Lisp_Object
-read_char_help_form_unwind (arg)
+read_char_help_form_unwind (Lisp_Object arg)
{
Lisp_Object window_config = XCAR (help_form_saved_window_configs);
help_form_saved_window_configs = XCDR (help_form_saved_window_configs);
if (CONSP (Vunread_command_events))
{
+ int was_disabled = 0;
+
c = XCAR (Vunread_command_events);
Vunread_command_events = XCDR (Vunread_command_events);
if (CONSP (c)
&& EQ (XCDR (c), Qdisabled)
&& (SYMBOLP (XCAR (c)) || INTEGERP (XCAR (c))))
- c = XCAR (c);
+ {
+ was_disabled = 1;
+ c = XCAR (c);
+ }
/* If the queued event is something that used the mouse,
set used_mouse_menu accordingly. */
if (used_mouse_menu
- && (EQ (c, Qtool_bar) || EQ (c, Qmenu_bar)))
+ /* Also check was_disabled so last-nonmenu-event won't return
+ a bad value when submenus are involved. (Bug#447) */
+ && (EQ (c, Qtool_bar) || EQ (c, Qmenu_bar) || was_disabled))
*used_mouse_menu = 1;
goto reread_for_input_method;
record_single_kboard_state ();
#endif
- last_input_char = c;
- Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char), Qt);
+ last_input_event = c;
+ Fcommand_execute (tem, Qnil, Fvector (1, &last_input_event), Qt);
if (CONSP (c) && EQ (XCAR (c), Qselect_window) && !end_time)
/* We stopped being idle for this event; undo that. This
add_command_key (also_record);
}
- last_input_char = c;
+ last_input_event = c;
num_input_events++;
/* Process the help character specially if enabled */
add_command_key (c);
/* Re-reading in the middle of a command */
- last_input_char = c;
+ last_input_event = c;
num_input_events++;
}
register int c;
Lisp_Object obj;
- if (noninteractive)
+ if (noninteractive
+ /* In case we are running as a daemon, only do this before
+ detaching from the terminal. */
+ || (IS_DAEMON && daemon_pipe[1] >= 0))
{
c = getchar ();
XSETINT (obj, c);
#endif
}
+#if defined (HAVE_NS)
+ else if (event->kind == NS_TEXT_EVENT)
+ {
+ if (event->code == KEY_NS_PUT_WORKING_TEXT)
+ obj = Fcons (intern ("ns-put-working-text"), Qnil);
+ else
+ obj = Fcons (intern ("ns-unput-working-text"), Qnil);
+ kbd_fetch_ptr = event + 1;
+ *used_mouse_menu = 1;
+ }
+#endif
+
#if defined (HAVE_X11) || defined (HAVE_NTGUI) \
|| defined (HAVE_NS)
else if (event->kind == DELETE_WINDOW_EVENT)
|| event->kind == TOOL_BAR_EVENT))
*used_mouse_menu = 1;
#endif
+#ifdef HAVE_NS
+ /* certain system events are non-key events */
+ if (event->kind == NS_NONKEY_EVENT)
+ *used_mouse_menu = 1;
+#endif
/* Wipe out this event, to catch bugs. */
clear_event (event);
int count = SPECPDL_INDEX ();
Lisp_Object old_deactivate_mark = Vdeactivate_mark;
-#if 0 /* This shouldn't be necessary anymore. --lorentey */
- /* On unbind_to, resume allowing input from any kboard, if that
- was true before. */
- record_single_kboard_state ();
-#endif
/* Mark the timer as triggered to prevent problems if the lisp
code fails to reschedule it right. */
vector[0] = Qt;
DEFUN ("current-idle-time", Fcurrent_idle_time, Scurrent_idle_time, 0, 0, 0,
doc: /* Return the current length of Emacs idleness, or nil.
-The value when Emacs is idle is 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 value when Emacs is idle is 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 value when Emacs is not idle is nil.
&object, &dx, &dy, &width, &height);
if (STRINGP (string))
string_info = Fcons (string, make_number (charpos));
- if (w == XWINDOW (selected_window))
+ if (w == XWINDOW (selected_window)
+ && current_buffer == XBUFFER (w->buffer))
textpos = PT;
else
textpos = XMARKER (w->pointm)->charpos;
return lispy_c;
}
+#ifdef HAVE_NS
+ /* NS_NONKEY_EVENTs are just like NON_ASCII_KEYSTROKE_EVENTs,
+ except that they are non-key events (last-nonmenu-event is nil). */
+ case NS_NONKEY_EVENT:
+#endif
+
/* A function key. The symbol may need to have modifier prefixes
tacked onto it. */
case NON_ASCII_KEYSTROKE_EVENT:
&& ('0' <= SREF (name, i + 6) && SREF (name, i + 6) <= '9'))
modifiers |= click_modifier;
+ if (! (modifiers & (double_modifier | triple_modifier))
+ && i + 6 < SBYTES (name)
+ && strncmp (SDATA (name) + i, "wheel-", 6) == 0)
+ modifiers |= click_modifier;
+
if (modifier_end)
*modifier_end = i;
alone in its group. */
kill (getpid (), SIGHUP);
- /* XXX Is calling delete_terminal safe here? It calls Fdelete_frame. */
+ /* XXX Is calling delete_terminal safe here? It calls delete_frame. */
{
Lisp_Object tmp;
XSETTERMINAL (tmp, t);
if (!terminal->name) /* Don't read from a dead terminal. */
return 0;
- if (terminal->type != output_termcap)
+ if (terminal->type != output_termcap
+ && terminal->type != output_msdos_raw)
abort ();
/* XXX I think the following code should be moved to separate hook
#ifdef WINDOWSNT
return 0;
#else /* not WINDOWSNT */
+ if (! tty->term_initted) /* In case we get called during bootstrap. */
+ return 0;
+
+ if (! tty->input)
+ return 0; /* The terminal is suspended. */
+
#ifdef MSDOS
n_to_read = dos_keysns ();
if (n_to_read == 0)
nread = 1;
#else /* not MSDOS */
-
- if (! tty->term_initted) /* In case we get called during bootstrap. */
- return 0;
-
- if (! tty->input)
- return 0; /* The terminal is suspended. */
-
#ifdef HAVE_GPM
if (gpm_tty == tty)
{
Gpm_Event event;
struct input_event hold_quit;
- int gpm;
+ int gpm, fd = gpm_fd;
EVENT_INIT (hold_quit);
hold_quit.kind = NO_EVENT;
+ /* gpm==1 if event received.
+ gpm==0 if the GPM daemon has closed the connection, in which case
+ Gpm_GetEvent closes gpm_fd and clears it to -1, which is why
+ we save it in `fd' so close_gpm can remove it from the
+ select masks.
+ gpm==-1 if a protocol error or EWOULDBLOCK; the latter is normal. */
while (gpm = Gpm_GetEvent (&event), gpm == 1) {
nread += handle_one_term_event (tty, &event, &hold_quit);
}
+ if (gpm == 0)
+ /* Presumably the GPM daemon has closed the connection. */
+ close_gpm (fd);
if (hold_quit.kind != NO_EVENT)
kbd_buffer_store_event (&hold_quit);
if (nread)
handle_async_input ()
{
interrupt_input_pending = 0;
-
+#ifdef SYNC_INPUT
+ pending_signals = pending_atimers;
+#endif
+/* Tell ns_read_socket() it is being called asynchronously so it can avoid
+ doing anything dangerous. */
+#ifdef HAVE_NS
+ ++handling_signal;
+#endif
while (1)
{
int nread;
if (nread <= 0)
break;
}
+#ifdef HAVE_NS
+ --handling_signal;
+#endif
+}
+
+void
+process_pending_signals ()
+{
+ if (interrupt_input_pending)
+ handle_async_input ();
+ do_pending_atimers ();
}
#ifdef SIGIO /* for entire page */
#ifdef SYNC_INPUT
interrupt_input_pending = 1;
+ pending_signals = 1;
#else
SIGNAL_THREAD_CHECK (signo);
#endif
&& ! NILP (Fget (def, Qmenu_alias)))
def = XSYMBOL (def)->function;
tem = Fwhere_is_internal (def, Qnil, Qt, Qnil, Qt);
+
+ /* Don't display remap bindings.*/
+ if (VECTORP (tem) && ASIZE (tem) > 0 && EQ (AREF (tem, 0), Qremap))
+ tem = Qnil;
+
XSETCAR (cachelist, tem);
if (NILP (tem))
{
if (! menu_prompting)
return Qnil;
+ /* Get the menu name from the first map that has one (a prompt string). */
+ for (mapno = 0; mapno < nmaps; mapno++)
+ {
+ name = Fkeymap_prompt (maps[mapno]);
+ if (!NILP (name))
+ break;
+ }
+
+ /* If we don't have any menus, just read a character normally. */
+ if (!STRINGP (name))
+ return Qnil;
+
/* Make sure we have a big enough buffer for the menu text. */
+ width = max (width, SBYTES (name));
if (read_char_minibuf_menu_text == 0)
{
read_char_minibuf_menu_width = width + 4;
}
menu = read_char_minibuf_menu_text;
- /* Get the menu name from the first map that has one (a prompt string). */
- for (mapno = 0; mapno < nmaps; mapno++)
- {
- name = Fkeymap_prompt (maps[mapno]);
- if (!NILP (name))
- break;
- }
-
- /* If we don't have any menus, just read a character normally. */
- if (!STRINGP (name))
- return Qnil;
-
/* Prompt string always starts with map's prompt, and a space. */
strcpy (menu, SDATA (name));
nlength = SBYTES (name);
orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
from_string = Qnil;
- /* The multi-tty merge moved the code below to right after
- `replay_sequence' which caused all these translation maps to be applied
- repeatedly, even tho their doc says very clearly they are not applied to
- their own output.
- The reason for this move was: "We may switch keyboards between rescans,
- so we need to reinitialize fkey and keytran before each replay".
- This move was wrong (even if we switch keyboards, keybuf still holds the
- keys we've read already from the original keyboard and some of those keys
- may have already been translated). So there may still be a bug out there
- lurking. */
+ /* We jump here when we need to reinitialize fkey and keytran; this
+ happens if we switch keyboards between rescans. */
+ replay_entire_sequence:
+
indec.map = indec.parent = current_kboard->Vinput_decode_map;
fkey.map = fkey.parent = current_kboard->Vlocal_function_key_map;
keytran.map = keytran.parent = Vkey_translation_map;
/* Don't touch interrupted_kboard when it's been
deleted. */
delayed_switch_frame = Qnil;
- goto replay_sequence;
+ goto replay_entire_sequence;
}
if (!NILP (delayed_switch_frame))
mock_input = 0;
orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
- goto replay_sequence;
+ goto replay_entire_sequence;
}
}
cancel_echoing ();
/* XXX This code needs to be revised for multi-tty support. */
- if (!NILP (Vquit_flag)
-#ifndef MSDOS
- && get_named_tty ("/dev/tty")
-#endif
- )
+ if (!NILP (Vquit_flag) && get_named_tty ("/dev/tty"))
{
/* If SIGINT isn't blocked, don't let us be interrupted by
another SIGINT, it might be harmful due to non-reentrancy
#ifdef MSDOS
/* We must remain inside the screen area when the internal terminal
is used. Note that [Enter] is not echoed by dos. */
- cursor_to (0, 0);
+ cursor_to (SELECTED_FRAME (), 0, 0);
#endif
/* It doesn't work to autosave while GC is in progress;
the code used for auto-saving doesn't cope with the mark bit. */
Vquit_flag = Qt;
}
+/* TODO: The longjmp in this call throws the NS event loop integration off,
+ and it seems to do fine without this. Probably some attention
+ needs to be paid to the setting of waiting_for_input in
+ wait_reading_process_output() under HAVE_NS because of the call
+ to ns_select there (needed because otherwise events aren't picked up
+ outside of polling since we don't get SIGIO like X and we don't have a
+ separate event loop thread like W32. */
+#ifndef HAVE_NS
if (waiting_for_input && !echoing)
quit_throw_to_read_char ();
+#endif
}
/* Handle a C-g by making read_char return C-g. */
if (FRAMEP (internal_last_event_frame)
&& !EQ (internal_last_event_frame, selected_frame))
do_switch_frame (make_lispy_switch_frame (internal_last_event_frame),
- 0, 0);
+ 0, 0, Qnil);
_longjmp (getcjmp, 1);
}
#endif /* NO_SOCK_SIGIO */
}
else
-#endif
+#endif /* HAVE_X_WINDOWS */
new_interrupt_input = !NILP (interrupt);
#else /* not SIGIO */
new_interrupt_input = 0;
{
struct terminal *t = get_terminal (terminal, 1);
struct tty_display_info *tty;
- if (t == NULL || t->type != output_termcap)
+ if (t == NULL || (t->type != output_termcap && t->type != output_msdos_raw))
return Qnil;
tty = t->display_info.tty;
struct tty_display_info *tty;
int new_meta;
- if (t == NULL || t->type != output_termcap)
+ if (t == NULL || (t->type != output_termcap && t->type != output_msdos_raw))
return Qnil;
tty = t->display_info.tty;
{
struct terminal *t = get_named_tty ("/dev/tty");
struct tty_display_info *tty;
- if (t == NULL || t->type != output_termcap)
+ if (t == NULL || (t->type != output_termcap && t->type != output_msdos_raw))
return Qnil;
tty = t->display_info.tty;
struct frame *sf = XFRAME (selected_frame);
val[0] = interrupt_input ? Qt : Qnil;
- if (FRAME_TERMCAP_P (sf))
+ if (FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
{
val[1] = FRAME_TTY (sf)->flow_control ? Qt : Qnil;
val[2] = (FRAME_TTY (sf)->meta_key == 2
input_pending = 0;
interrupt_input_blocked = 0;
interrupt_input_pending = 0;
+#ifdef SYNC_INPUT
+ pending_signals = 0;
+#endif
/* This means that command_loop_1 won't try to select anything the first
time through. */
defsubr (&Sposn_at_point);
defsubr (&Sposn_at_x_y);
- DEFVAR_LISP ("last-command-char", &last_command_char,
- doc: /* Last input event that was part of a command. */);
-
- DEFVAR_LISP_NOPRO ("last-command-event", &last_command_char,
+ DEFVAR_LISP ("last-command-event", &last_command_event,
doc: /* Last input event that was part of a command. */);
DEFVAR_LISP ("last-nonmenu-event", &last_nonmenu_event,
this variable holds the actual mouse event that led to the menu,
so that you can determine whether the command was run by mouse or not. */);
- DEFVAR_LISP ("last-input-char", &last_input_char,
+ DEFVAR_LISP ("last-input-event", &last_input_event,
doc: /* Last input event. */);
- DEFVAR_LISP_NOPRO ("last-input-event", &last_input_char,
- doc: /* Last input event. */);
-
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.
staticpro (&Qdeactivate_mark);
DEFVAR_LISP ("command-hook-internal", &Vcommand_hook_internal,
- doc: /* Temporary storage of pre-command-hook or post-command-hook. */);
+ doc: /* Temporary storage of `pre-command-hook' or `post-command-hook'. */);
Vcommand_hook_internal = Qnil;
DEFVAR_LISP ("pre-command-hook", &Vpre_command_hook,
real Emacs function key events (symbols).
The `read-key-sequence' function replaces any subsequence bound by
-`local-function-key-map' with its binding. Contrary to `function-key-map',
+`input-key-map' with its binding. Contrary to `function-key-map',
this map applies its rebinding regardless of the presence of an ordinary
binding. So it is more like `key-translation-map' except that it applies
before `function-key-map' rather than after.
to be reconsidered, separately, by the input method,
it can add them to the beginning of `unread-command-events'.
-The input method function can find in `input-method-previous-method'
+The input method function can find in `input-method-previous-message'
the previous echo area message.
The input method function should refer to the variables
initial_define_lispy_key (Vspecial_event_map, "delete-frame",
"handle-delete-frame");
+ initial_define_lispy_key (Vspecial_event_map, "ns-put-working-text",
+ "ns-put-working-text");
+ initial_define_lispy_key (Vspecial_event_map, "ns-unput-working-text",
+ "ns-unput-working-text");
/* Here we used to use `ignore-event' which would simple set prefix-arg to
current-prefix-arg, as is done in `handle-switch-frame'.
But `handle-switch-frame is not run from the special-map.