/* 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.
#include "msdos.h"
#include <time.h>
#else /* not MSDOS */
-#ifndef VMS
#include <sys/ioctl.h>
-#endif
#endif /* not MSDOS */
#include "syssignal.h"
#include "w32term.h"
#endif /* HAVE_NTGUI */
-#ifdef MAC_OS
-#include "macterm.h"
-#endif
-
#ifdef HAVE_NS
#include "nsterm.h"
-extern Lisp_Object Qsuper;
#endif
#ifndef USE_CRT_DLL
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
-#ifdef MULTI_KBOARD
KBOARD *initial_kboard;
KBOARD *current_kboard;
KBOARD *all_kboards;
int single_kboard;
-#else
-KBOARD the_only_kboard;
-#endif
/* Non-nil disable property on a command means
do not execute it; call disabled-command-function's value instead. */
/* 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
/* Symbols to denote kinds of events. */
Lisp_Object Qfunction_key;
Lisp_Object Qmouse_click;
-#if defined (WINDOWSNT) || defined (MAC_OS)
+#if defined (WINDOWSNT)
Lisp_Object Qlanguage_change;
#endif
Lisp_Object Qdrag_n_drop;
Lisp_Object Qsave_session;
-#ifdef MAC_OS
-Lisp_Object Qmac_apple_event;
-#endif
#ifdef HAVE_DBUS
Lisp_Object Qdbus_event;
#endif
Lisp_Object, char **,
Lisp_Object *, unsigned));
static Lisp_Object make_lispy_switch_frame P_ ((Lisp_Object));
-static int parse_solitary_modifier P_ ((Lisp_Object));
-static int parse_solitary_modifier ();
static void save_getcjmp P_ ((jmp_buf));
static void save_getcjmp ();
static void restore_getcjmp P_ ((jmp_buf));
static Lisp_Object apply_modifiers P_ ((int, Lisp_Object));
static void clear_event P_ ((struct input_event *));
-#ifdef MULTI_KBOARD
static Lisp_Object restore_kboard_configuration P_ ((Lisp_Object));
-#endif
static SIGTYPE interrupt_signal P_ ((int signalnum));
static void handle_interrupt P_ ((void));
static void timer_start_idle P_ ((void));
static void
any_kboard_state ()
{
-#ifdef MULTI_KBOARD
#if 0 /* Theory: if there's anything in Vunread_command_events,
it will right away be read by read_key_sequence,
and then if we do switch KBOARDS, it will go into the side
Vunread_command_events = Qnil;
#endif
single_kboard = 0;
-#endif
}
/* Switch to the single-kboard state, making current_kboard
void
single_kboard_state ()
{
-#ifdef MULTI_KBOARD
single_kboard = 1;
-#endif
}
#endif
not_single_kboard_state (kboard)
KBOARD *kboard;
{
-#ifdef MULTI_KBOARD
if (kboard == current_kboard)
single_kboard = 0;
-#endif
}
/* Maintain a stack of kboards, so other parts of Emacs
push_kboard (k)
struct kboard *k;
{
-#ifdef MULTI_KBOARD
struct kboard_stack *p
= (struct kboard_stack *) xmalloc (sizeof (struct kboard_stack));
kboard_stack = p;
current_kboard = k;
-#endif
}
void
pop_kboard ()
{
-#ifdef MULTI_KBOARD
struct terminal *t;
struct kboard_stack *p = kboard_stack;
int found = 0;
}
kboard_stack = p->next;
xfree (p);
-#endif
}
/* Switch to single_kboard mode, making current_kboard the only KBOARD
temporarily_switch_to_single_kboard (f)
struct frame *f;
{
-#ifdef MULTI_KBOARD
int was_locked = single_kboard;
if (was_locked)
{
single_kboard = 1;
record_unwind_protect (restore_kboard_configuration,
(was_locked ? Qt : Qnil));
-#endif
}
#if 0 /* This function is not needed anymore. */
}
#endif
-#ifdef MULTI_KBOARD
static Lisp_Object
restore_kboard_configuration (was_locked)
Lisp_Object was_locked;
}
return Qnil;
}
-#endif
\f
/* Handle errors that are not handled at inner levels
Vinhibit_quit = Qnil;
#if 0 /* This shouldn't be necessary anymore. --lorentey */
-#ifdef MULTI_KBOARD
if (command_loop_level == 0 && minibuf_level == 0)
any_kboard_state ();
-#endif
#endif
return make_number (0);
/* 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
int prev_modiff = 0;
struct buffer *prev_buffer = NULL;
#if 0 /* This shouldn't be necessary anymore. --lorentey */
-#ifdef MULTI_KBOARD
int was_locked = single_kboard;
-#endif
#endif
int already_adjusted = 0;
/* 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;
&& NILP (current_kboard->Vprefix_arg))
finalize_kbd_macro_chars ();
#if 0 /* This shouldn't be necessary anymore. --lorentey */
-#ifdef MULTI_KBOARD
if (!was_locked)
any_kboard_state ();
-#endif
#endif
}
}
/* 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;
if (!NILP (Vinhibit_quit))
Vquit_flag = Qnil;
-#ifdef MULTI_KBOARD
{
KBOARD *kb = FRAME_KBOARD (XFRAME (selected_frame));
if (kb != current_kboard)
return make_number (-2); /* wrong_kboard_jmpbuf */
}
}
-#endif
goto non_reread;
}
}
}
-#ifdef MULTI_KBOARD
/* If current_kboard's side queue is empty check the other kboards.
If one of them has data that we have not yet seen here,
switch to it and process the data waiting for it.
return make_number (-2); /* wrong_kboard_jmpbuf */
}
}
-#endif
wrong_kboard:
c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time);
restore_getcjmp (save_jump);
-#ifdef MULTI_KBOARD
if (! NILP (c) && (kb != current_kboard))
{
Lisp_Object link = kb->kbd_queue;
UNGCPRO;
return make_number (-2);
}
-#endif
}
/* Terminate Emacs in batch mode if at eof. */
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++;
}
/* Set this for debugging, to have a way to get out */
int stop_character;
-#ifdef MULTI_KBOARD
static KBOARD *
event_to_kboard (event)
struct input_event *event;
else
return FRAME_KBOARD (XFRAME (frame));
}
-#endif
Lisp_Object Vthrow_on_input;
if (c == quit_char)
{
-#ifdef MULTI_KBOARD
KBOARD *kb = FRAME_KBOARD (XFRAME (event->frame_or_window));
struct input_event *sp;
}
return;
}
-#endif
if (hold_quit)
{
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);
/* One way or another, wait until input is available; then, if
interrupt handlers have not read it, read it now. */
-#ifdef OLDVMS
- wait_for_kbd_input ();
-#else
/* Note SIGIO has been undef'd if FIONREAD is missing. */
#ifdef SIGIO
gobble_input (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);
-#endif /* not VMS */
}
if (CONSP (Vunread_command_events))
last_event_timestamp = event->timestamp;
-#ifdef MULTI_KBOARD
*kbp = event_to_kboard (event);
if (*kbp == 0)
*kbp = current_kboard; /* Better than returning null ptr? */
-#else
- *kbp = &the_only_kboard;
-#endif
obj = Qnil;
#endif
}
-#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+#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)
{
kbd_fetch_ptr = event + 1;
}
#endif
-#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+#if defined (HAVE_X11) || defined (HAVE_NTGUI) \
|| defined (HAVE_NS)
else if (event->kind == ICONIFY_EVENT)
{
XSETBUFFER (obj, current_buffer);
kbd_fetch_ptr = event + 1;
}
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
|| defined(HAVE_NS) || defined (USE_GTK)
else if (event->kind == MENU_BAR_ACTIVATE_EVENT)
{
x_activate_menubar (XFRAME (event->frame_or_window));
}
#endif
-#if defined (WINDOWSNT) || defined (MAC_OS)
+#if defined (WINDOWSNT)
else if (event->kind == LANGUAGE_CHANGE_EVENT)
{
-#ifdef MAC_OS
- /* Make an event (language-change (KEY_SCRIPT)). */
- obj = Fcons (make_number (event->code), Qnil);
-#else
/* Make an event (language-change (FRAME CHARSET LCID)). */
obj = Fcons (event->frame_or_window, Qnil);
-#endif
obj = Fcons (Qlanguage_change, Fcons (obj, Qnil));
kbd_fetch_ptr = event + 1;
}
{
obj = make_lispy_event (event);
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined(MAC_OS) \
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
|| defined(HAVE_NS) || defined (USE_GTK)
/* If this was a menu selection, then set the flag to inhibit
writing to last_nonmenu_event. Don't do this if the 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:
}
#endif /* HAVE_MOUSE */
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
|| defined(HAVE_NS) || defined (USE_GTK)
case MENU_BAR_EVENT:
if (EQ (event->arg, event->frame_or_window))
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
-
#ifdef HAVE_DBUS
case DBUS_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;
/* Try to recognize SYMBOL as a modifier name.
Return the modifier flag bit, or 0 if not recognized. */
-static int
-parse_solitary_modifier (symbol)
- Lisp_Object symbol;
+int
+parse_solitary_modifier (Lisp_Object symbol)
{
Lisp_Object name = SYMBOL_NAME (symbol);
xd_read_queued_messages ();
#endif /* HAVE_DBUS */
-#ifndef VMS
#ifdef SIGIO
if (interrupt_input)
{
#endif
#endif
read_avail_input (expected);
-#endif
}
/* Put a BUFFER_SWITCH_EVENT in the buffer
}
}
\f
-#ifndef VMS
-
/* Read any terminal input already buffered up by the system
into the kbd_buffer, but do not wait.
EXPECTED should be nonzero if the caller knows there is some input.
- Except on VMS, all input is read by this function.
- If interrupt_input is nonzero, this function MUST be called
- only when SIGIO is blocked.
-
Returns the number of keyboard chars read, or -1 meaning
this is a bad time to try to read input. */
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)
return nread;
}
-#endif /* not VMS */
\f
void
handle_async_input ()
{
-#ifdef BSD4_1
- extern int select_alarmed;
-#endif
-
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;
0 means there was no keyboard input available. */
if (nread <= 0)
break;
-
-#ifdef BSD4_1
- select_alarmed = 1; /* Force the select emulator back to life */
-#endif
}
+#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 */
signal (signo, input_available_signal);
#endif /* USG */
-#ifdef BSD4_1
- sigisheld (SIGIO);
-#endif
-
#ifdef SYNC_INPUT
interrupt_input_pending = 1;
+ pending_signals = 1;
#else
SIGNAL_THREAD_CHECK (signo);
#endif
handle_async_input ();
#endif
-#ifdef BSD4_1
- sigfree ();
-#endif
errno = old_errno;
}
#endif /* SIGIO */
&& SYMBOLP (XSYMBOL (def)->function)
&& ! NILP (Fget (def, Qmenu_alias)))
def = XSYMBOL (def)->function;
-#ifdef HAVE_NS
- /* prefer 'super' bindings */
- tem = Fwhere_is_internal (def, Qnil, Qsuper, Qt, Qt);
-#else
tem = Fwhere_is_internal (def, Qnil, Qt, Qnil, Qt);
-#endif
+
+ /* 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;
else
{
{
-#ifdef MULTI_KBOARD
KBOARD *interrupted_kboard = current_kboard;
struct frame *interrupted_frame = SELECTED_FRAME ();
-#endif
key = read_char (NILP (prompt), nmaps,
(Lisp_Object *) submaps, last_nonmenu_event,
&used_mouse_menu, NULL);
-#ifdef MULTI_KBOARD
if (INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */
{
int found = 0;
/* 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;
}
-#endif
}
/* read_char returns t when it shows a menu and the user rejects it.
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
*/
sys_suspend ();
#else
-#ifdef VMS
- if (sys_suspend () == -1)
- {
- printf ("Not running as a subprocess;\n");
- printf ("you can continue or abort.\n");
- }
-#else /* not VMS */
/* Perhaps should really fork an inferior shell?
But that would not provide any way to get back
to the original shell, ever. */
printf ("No support for stopping a process on this operating system;\n");
printf ("you can continue or abort.\n");
-#endif /* not VMS */
#endif /* not SIGTSTP */
#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. */
#ifdef MSDOS
printf ("\r\nAbort? (y or n) ");
#else /* not MSDOS */
-#ifdef VMS
- printf ("Abort (and enter debugger)? (y or n) ");
-#else /* not VMS */
printf ("Abort (and dump core)? (y or n) ");
-#endif /* not VMS */
#endif /* not MSDOS */
fflush (stdout);
if (((c = getchar ()) & ~040) == 'Y')
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;
#endif /* not SIGIO */
-/* Our VMS input only works by interrupts, as of now. */
-#ifdef VMS
- new_interrupt_input = 1;
-#endif
-
if (new_interrupt_input != interrupt_input)
{
#ifdef POLL_FOR_INPUT
{
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
xfree (kb->kbd_macro_buffer);
}
-#ifdef MULTI_KBOARD
-
/* Free KB and memory referenced from it. */
void
xfree (kb);
}
-#endif /* MULTI_KBOARD */
-
void
init_keyboard ()
{
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. */
internal_last_event_frame = Qnil;
Vlast_event_frame = internal_last_event_frame;
-#ifdef MULTI_KBOARD
current_kboard = initial_kboard;
-#endif
/* Re-initialize the keyboard again. */
wipe_kboard (current_kboard);
init_kboard (current_kboard);
interrupt_input = 0;
#endif
-/* Our VMS input only works by interrupts, as of now. */
-#ifdef VMS
- interrupt_input = 1;
-#endif
-
sigfree ();
dribble = 0;
staticpro (&Qfunction_key);
Qmouse_click = intern ("mouse-click");
staticpro (&Qmouse_click);
-#if defined (WINDOWSNT) || defined (MAC_OS)
+#if defined (WINDOWSNT)
Qlanguage_change = intern ("language-change");
staticpro (&Qlanguage_change);
#endif
Qsave_session = intern ("save-session");
staticpro (&Qsave_session);
-#ifdef MAC_OS
- Qmac_apple_event = intern ("mac-apple-event");
- staticpro (&Qmac_apple_event);
-#endif
-
#ifdef HAVE_DBUS
Qdbus_event = intern ("dbus-event");
staticpro (&Qdbus_event);
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
and tool-bar buttons. */);
Venable_disabled_menus_and_buttons = Qnil;
-#ifdef MULTI_KBOARD
/* Create the initial keyboard. */
initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
init_kboard (initial_kboard);
/* Vwindow_system is left at t for now. */
initial_kboard->next_kboard = all_kboards;
all_kboards = initial_kboard;
-#endif
}
void
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.