/* 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.
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <signal.h>
#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"
+#ifdef HAVE_NS
+#include "nsterm.h"
#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. */
Lisp_Object raw_keybuf;
int raw_keybuf_count;
+/* Non-nil if the present key sequence was obtained by shift translation. */
+Lisp_Object Vthis_command_keys_shift_translated;
+
#define GROW_RAW_KEYBUF \
if (raw_keybuf_count == XVECTOR (raw_keybuf)->size) \
raw_keybuf = larger_vector (raw_keybuf, raw_keybuf_count * 2, Qnil) \
Lisp_Object Vshow_help_function;
-/* If a string, the message displayed before displaying a help-echo
- in the echo area. */
-
-Lisp_Object Vpre_help_message;
-
/* Nonzero means do menu prompting. */
static int menu_prompting;
/* 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;
/* Non-nil means deactivate the mark at end of this command. */
Lisp_Object Vdeactivate_mark;
+Lisp_Object Qdeactivate_mark;
/* Menu bar specified in Lucid Emacs fashion. */
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));
2 * ASIZE (this_command_keys),
Qnil);
- AREF (this_command_keys, this_command_key_count) = key;
+ ASET (this_command_keys, this_command_key_count, key);
++this_command_key_count;
}
specbind (Qstandard_input, Qt);
}
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
/* The command loop has started an hourglass timer, so we have to
cancel it here, otherwise it will fire because the recursive edit
can take some time. Do not check for display_hourglass_p here,
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
Lisp_Object old_level, old_length;
char macroerror[50];
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
if (display_hourglass_p)
cancel_hourglass ();
#endif
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_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
if (display_hourglass_p)
cancel_hourglass ();
#endif
/* Cancel hourglass from protect_unwind.
ARG is not used. */
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
static Lisp_Object
cancel_hourglass_unwind (arg)
Lisp_Object arg;
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)
if (minibuf_level
&& !NILP (echo_area_buffer[0])
- && EQ (minibuf_window, echo_area_window))
+ && EQ (minibuf_window, echo_area_window)
+ && NUMBERP (Vminibuffer_message_timeout))
{
/* 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);
- if (NUMBERP (Vminibuffer_message_timeout))
- sit_for (Vminibuffer_message_timeout, 0, 2);
- else
- sit_for (Qt, 0, 2);
+ sit_for (Vminibuffer_message_timeout, 0, 2);
/* Clear the echo area. */
message2 (0, 0, 0);
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. */
Vthis_command = Qnil;
real_this_command = Qnil;
Vthis_original_command = Qnil;
+ Vthis_command_keys_shift_translated = Qnil;
/* Read next key sequence; i gets its length. */
i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
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
/* Recognize some common commands in common situations and
do them directly. */
- if (EQ (Vthis_command, Qforward_char) && PT < ZV)
+ if (EQ (Vthis_command, Qforward_char) && PT < ZV
+ && NILP (Vthis_command_keys_shift_translated)
+ && !CONSP (Vtransient_mark_mode))
{
struct Lisp_Char_Table *dp
= window_display_table (XWINDOW (selected_window));
direct_output_forward_char (1);
goto directly_done;
}
- else if (EQ (Vthis_command, Qbackward_char) && PT > BEGV)
+ else if (EQ (Vthis_command, Qbackward_char) && PT > BEGV
+ && NILP (Vthis_command_keys_shift_translated)
+ && !CONSP (Vtransient_mark_mode))
{
struct Lisp_Char_Table *dp
= window_display_table (XWINDOW (selected_window));
}
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))
/* Here for a command that isn't executed directly */
{
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
int scount = SPECPDL_INDEX ();
if (display_hourglass_p
Fundo_boundary ();
Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil);
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
/* Do not check display_hourglass_p here, because
Fcommand_execute could change it, but we should cancel
hourglass cursor anyway.
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;
if (!NILP (current_buffer->mark_active) && !NILP (Vrun_hooks))
{
- /* Setting transient-mark-mode to `only' is a way of
- turning it on for just one command. */
-
+ /* In Emacs 22, setting transient-mark-mode to `only' was a
+ way of turning it on for just one command. This usage is
+ obsolete, but support it anyway. */
if (EQ (Vtransient_mark_mode, Qidentity))
Vtransient_mark_mode = Qnil;
- if (EQ (Vtransient_mark_mode, Qonly))
+ else if (EQ (Vtransient_mark_mode, Qonly))
Vtransient_mark_mode = Qidentity;
- if (!NILP (Vdeactivate_mark) && !NILP (Vtransient_mark_mode))
- {
- /* We could also call `deactivate'mark'. */
- if (EQ (Vtransient_mark_mode, Qlambda))
- Vtransient_mark_mode = Qnil;
- else
- {
- current_buffer->mark_active = Qnil;
- call1 (Vrun_hooks, intern ("deactivate-mark-hook"));
- }
- }
+ if (!NILP (Vdeactivate_mark))
+ call0 (Qdeactivate_mark);
else if (current_buffer != prev_buffer || MODIFF != prev_modiff)
call1 (Vrun_hooks, intern ("activate-mark-hook"));
}
&& 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
}
}
can't be usefully combined anyway. */
while (check_composition || check_display || check_invisible)
{
+ /* 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 */
{
if (!NILP (Vshow_help_function))
call1 (Vshow_help_function, help);
- else if (/* Don't overwrite minibuffer contents. */
- !MINI_WINDOW_P (XWINDOW (selected_window))
- /* Don't overwrite a keystroke echo. */
- && (NILP (echo_message_buffer)
- || ok_to_overwrite_keystroke_echo)
- /* Don't overwrite a prompt. */
- && !cursor_in_echo_area)
- {
- if (STRINGP (help))
- {
- int count = SPECPDL_INDEX ();
-
- if (!help_echo_showing_p)
- Vpre_help_message = current_message ();
-
- specbind (Qmessage_truncate_lines, Qt);
- message3_nolog (help, SBYTES (help),
- STRING_MULTIBYTE (help));
- unbind_to (count, Qnil);
- }
- else if (STRINGP (Vpre_help_message))
- {
- message3_nolog (Vpre_help_message,
- SBYTES (Vpre_help_message),
- STRING_MULTIBYTE (Vpre_help_message));
- Vpre_help_message = Qnil;
- }
- else
- message (0);
- }
-
help_echo_showing_p = STRINGP (help);
}
}
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)
{
/* Make an event (delete-frame (FRAME)). */
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)
{
/* Make an event (iconify-frame (FRAME)). */
XSETBUFFER (obj, current_buffer);
kbd_fetch_ptr = event + 1;
}
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
- || defined (USE_GTK)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
+ || defined(HAVE_NS) || defined (USE_GTK)
else if (event->kind == MENU_BAR_ACTIVATE_EVENT)
{
kbd_fetch_ptr = event + 1;
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) \
- || defined (USE_GTK)
+#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
we're returning is (menu-bar), though; that indicates the
|| 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);
/* This is only for debugging. */
struct input_event last_timer_event;
+/* List of elisp functions to call, delayed because they were generated in
+ a context where Elisp could not be safely run (e.g. redisplay, signal,
+ ...). Each lement has the form (FUN . ARGS). */
+Lisp_Object pending_funcalls;
+
+extern Lisp_Object Qapply;
+
/* Check whether a timer has fired. To prevent larger problems we simply
disregard elements that are not proper timers. Do not make a circular
timer list for the time being.
chosen_timer = Qnil;
GCPRO3 (timers, idle_timers, chosen_timer);
+ /* First run the code that was delayed. */
+ while (CONSP (pending_funcalls))
+ {
+ Lisp_Object funcall = XCAR (pending_funcalls);
+ pending_funcalls = XCDR (pending_funcalls);
+ safe_call2 (Qapply, XCAR (funcall), XCDR (funcall));
+ }
+
if (CONSP (timers) || CONSP (idle_timers))
{
EMACS_GET_TIME (now);
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:
if (event->kind == MOUSE_CLICK_EVENT)
{
struct frame *f = XFRAME (event->frame_or_window);
-#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
int row, column;
#endif
if (! FRAME_LIVE_P (f))
return Qnil;
-#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
/* EVENT->x and EVENT->y are frame-relative pixel
coordinates at this place. Under old redisplay, COLUMN
and ROW are set to frame relative glyph coordinates
return Fcons (item, Fcons (position, Qnil));
}
-#endif /* not USE_X_TOOLKIT && not USE_GTK */
+#endif /* not USE_X_TOOLKIT && not USE_GTK && not HAVE_NS */
position = make_lispy_position (f, &event->x, &event->y,
event->timestamp);
}
#endif /* HAVE_MOUSE */
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
- || defined (USE_GTK)
+#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))
/* This is the prefix key. We translate this to
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. */
- if (t->delete_terminal_hook)
- (*t->delete_terminal_hook) (t);
- else
- delete_terminal (t);
+ /* XXX Is calling delete_terminal safe here? It calls delete_frame. */
+ {
+ Lisp_Object tmp;
+ XSETTERMINAL (tmp, t);
+ Fdelete_terminal (tmp, Qnoelisp);
+ }
}
if (hold_quit.kind != NO_EVENT)
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)
Jeffrey Honig <jch@bsdi.com> says this is generally safe. */
if (nread == -1 && errno == EIO)
return -2; /* Close this terminal. */
-#if defined (AIX) && (! defined (aix386) && defined (_BSD))
+#if defined (AIX) && defined (_BSD)
/* The kernel sometimes fails to deliver SIGHUP for ptys.
This looks incorrect, but it isn't, because _BSD causes
O_NDELAY to be defined in fcntl.h as O_NONBLOCK,
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 */
/* Initialize optional entries. */
for (i = ITEM_PROPERTY_DEF; i < ITEM_PROPERTY_ENABLE; i++)
- AREF (item_properties, i) = Qnil;
- AREF (item_properties, ITEM_PROPERTY_ENABLE) = Qt;
+ ASET (item_properties, i, Qnil);
+ ASET (item_properties, ITEM_PROPERTY_ENABLE, Qt);
/* Save the item here to protect it from GC. */
- AREF (item_properties, ITEM_PROPERTY_ITEM) = item;
+ ASET (item_properties, ITEM_PROPERTY_ITEM, item);
item_string = XCAR (item);
if (STRINGP (item_string))
{
/* Old format menu item. */
- AREF (item_properties, ITEM_PROPERTY_NAME) = item_string;
+ ASET (item_properties, ITEM_PROPERTY_NAME, item_string);
/* Maybe help string. */
if (CONSP (item) && STRINGP (XCAR (item)))
{
- AREF (item_properties, ITEM_PROPERTY_HELP) = XCAR (item);
+ ASET (item_properties, ITEM_PROPERTY_HELP, XCAR (item));
start = item;
item = XCDR (item);
}
}
/* This is the real definition--the function to run. */
- AREF (item_properties, ITEM_PROPERTY_DEF) = item;
+ ASET (item_properties, ITEM_PROPERTY_DEF, item);
/* Get enable property, if any. */
if (SYMBOLP (item))
{
tem = Fget (item, Qmenu_enable);
if (!NILP (Venable_disabled_menus_and_buttons))
- AREF (item_properties, ITEM_PROPERTY_ENABLE) = Qt;
+ ASET (item_properties, ITEM_PROPERTY_ENABLE, Qt);
else if (!NILP (tem))
- AREF (item_properties, ITEM_PROPERTY_ENABLE) = tem;
+ ASET (item_properties, ITEM_PROPERTY_ENABLE, tem);
}
}
else if (EQ (item_string, Qmenu_item) && CONSP (item))
{
/* New format menu item. */
- AREF (item_properties, ITEM_PROPERTY_NAME) = XCAR (item);
+ ASET (item_properties, ITEM_PROPERTY_NAME, XCAR (item));
start = XCDR (item);
if (CONSP (start))
{
/* We have a real binding. */
- AREF (item_properties, ITEM_PROPERTY_DEF) = XCAR (start);
+ ASET (item_properties, ITEM_PROPERTY_DEF, XCAR (start));
item = XCDR (start);
/* Is there a cache list with key equivalences. */
if (EQ (tem, QCenable))
{
if (!NILP (Venable_disabled_menus_and_buttons))
- AREF (item_properties, ITEM_PROPERTY_ENABLE) = Qt;
+ ASET (item_properties, ITEM_PROPERTY_ENABLE, Qt);
else
- AREF (item_properties, ITEM_PROPERTY_ENABLE) = XCAR (item);
+ ASET (item_properties, ITEM_PROPERTY_ENABLE, XCAR (item));
}
else if (EQ (tem, QCvisible) && !notreal)
{
return 0;
}
else if (EQ (tem, QChelp))
- AREF (item_properties, ITEM_PROPERTY_HELP) = XCAR (item);
+ ASET (item_properties, ITEM_PROPERTY_HELP, XCAR (item));
else if (EQ (tem, QCfilter))
filter = item;
else if (EQ (tem, QCkey_sequence))
{
tem = XCAR (item);
if (CONSP (tem) || (STRINGP (tem) && NILP (cachelist)))
- AREF (item_properties, ITEM_PROPERTY_KEYEQ) = tem;
+ ASET (item_properties, ITEM_PROPERTY_KEYEQ, tem);
}
else if (EQ (tem, QCbutton) && CONSP (XCAR (item)))
{
type = XCAR (tem);
if (EQ (type, QCtoggle) || EQ (type, QCradio))
{
- AREF (item_properties, ITEM_PROPERTY_SELECTED)
- = XCDR (tem);
- AREF (item_properties, ITEM_PROPERTY_TYPE)
- = type;
+ ASET (item_properties, ITEM_PROPERTY_SELECTED,
+ XCDR (tem));
+ ASET (item_properties, ITEM_PROPERTY_TYPE, type);
}
}
item = XCDR (item);
item_string = menu_item_eval_property (item_string);
if (!STRINGP (item_string))
return 0;
- AREF (item_properties, ITEM_PROPERTY_NAME) = item_string;
+ ASET (item_properties, ITEM_PROPERTY_NAME, item_string);
}
/* If got a filter apply it on definition. */
def = menu_item_eval_property (list2 (XCAR (filter),
list2 (Qquote, def)));
- AREF (item_properties, ITEM_PROPERTY_DEF) = def;
+ ASET (item_properties, ITEM_PROPERTY_DEF, def);
}
/* Enable or disable selection of item. */
tem = menu_item_eval_property (tem);
if (inmenubar && NILP (tem))
return 0; /* Ignore disabled items in menu bar. */
- AREF (item_properties, ITEM_PROPERTY_ENABLE) = tem;
+ ASET (item_properties, ITEM_PROPERTY_ENABLE, tem);
}
/* If we got no definition, this item is just unselectable text which
/* For a subkeymap, just record its details and exit. */
if (CONSP (tem))
{
- AREF (item_properties, ITEM_PROPERTY_MAP) = tem;
- AREF (item_properties, ITEM_PROPERTY_DEF) = tem;
+ ASET (item_properties, ITEM_PROPERTY_MAP, tem);
+ ASET (item_properties, ITEM_PROPERTY_DEF, tem);
return 1;
}
if (NILP (cachelist))
{
/* We have to create a cachelist. */
- CHECK_IMPURE (start);
- XSETCDR (start, Fcons (Fcons (Qnil, Qnil), XCDR (start)));
- cachelist = XCAR (XCDR (start));
+ /* With the introduction of where_is_cache, the computation
+ of equivalent key bindings is sufficiently fast that we
+ do not need to cache it here any more. */
+ /* CHECK_IMPURE (start);
+ XSETCDR (start, Fcons (Fcons (Qnil, Qnil), XCDR (start)));
+ cachelist = XCAR (XCDR (start)); */
+ cachelist = Fcons (Qnil, Qnil);
newcache = 1;
tem = AREF (item_properties, ITEM_PROPERTY_KEYEQ);
if (!NILP (keyhint))
&& ! 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 (newcache && !NILP (tem))
{
tem = concat2 (build_string (" "), tem);
- // tem = concat3 (build_string (" ("), tem, build_string (")"));
+ /* tem = concat3 (build_string (" ("), tem, build_string (")")); */
XSETCDR (cachelist, tem);
}
return 1;
/* If we have an equivalent key binding, use that. */
- AREF (item_properties, ITEM_PROPERTY_KEYEQ) = tem;
+ ASET (item_properties, ITEM_PROPERTY_KEYEQ, tem);
/* Include this when menu help is implemented.
tem = XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP];
/* Handle radio buttons or toggle boxes. */
tem = AREF (item_properties, ITEM_PROPERTY_SELECTED);
if (!NILP (tem))
- AREF (item_properties, ITEM_PROPERTY_SELECTED)
- = menu_item_eval_property (tem);
+ ASET (item_properties, ITEM_PROPERTY_SELECTED,
+ menu_item_eval_property (tem));
return 1;
}
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);
/* Likewise, for key_translation_map and input-decode-map. */
volatile keyremap keytran, indec;
+ /* Non-zero if we are trying to map a key by changing an upper-case
+ letter to lower case, or a shifted function key to an unshifted
+ one. */
+ volatile int shift_translated = 0;
+
/* If we receive a `switch-frame' or `select-window' event in the middle of
a key sequence, we put it off for later.
While we're reading, we keep the event here. */
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;
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;
+ submaps[nmaps++] = current_kboard->Voverriding_terminal_local_map;
}
else if (!NILP (Voverriding_local_map))
{
defs = (Lisp_Object *) alloca (2 * sizeof (defs[0]));
nmaps_allocated = 2;
}
- if (!NILP (Voverriding_local_map))
- submaps[nmaps++] = Voverriding_local_map;
+ submaps[nmaps++] = Voverriding_local_map;
}
else
{
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.
}
GROW_RAW_KEYBUF;
- ASET (raw_keybuf, raw_keybuf_count++, key);
+ ASET (raw_keybuf, raw_keybuf_count, key);
+ raw_keybuf_count++;
}
/* Clicks in non-text areas get prefixed by the symbol
{
Lisp_Object window, posn;
- window = POSN_WINDOW (EVENT_START (key));
+ window = POSN_WINDOW (EVENT_START (key));
posn = POSN_POSN (EVENT_START (key));
if (CONSP (posn)
XSETINT (new_key, XINT (key) & ~shift_modifier);
else
XSETINT (new_key, (DOWNCASE (XINT (key) & ~CHAR_MODIFIER_MASK)
- | (XINT (key) & ~CHAR_MODIFIER_MASK)));
+ | (XINT (key) & CHAR_MODIFIER_MASK)));
/* We have to do this unconditionally, regardless of whether
the lower-case char is defined in the keymaps, because they
might get translated through function-key-map. */
keybuf[t - 1] = new_key;
mock_input = max (t, mock_input);
+ shift_translated = 1;
goto replay_sequence;
}
input-decode-map doesn't need to go through it again. */
fkey.start = fkey.end = 0;
keytran.start = keytran.end = 0;
+ shift_translated = 1;
goto replay_sequence;
}
if ((dont_downcase_last || first_binding >= nmaps)
&& t > 0
&& t - 1 == original_uppercase_position)
- keybuf[t - 1] = original_uppercase;
+ {
+ keybuf[t - 1] = original_uppercase;
+ shift_translated = 0;
+ }
+
+ if (shift_translated)
+ Vthis_command_keys_shift_translated = Qt;
/* Occasionally we fabricate events, perhaps by expanding something
according to function-key-map, or by adding a prefix symbol to a
add_command_key (keybuf[t]);
}
-
-
UNGCPRO;
return t;
}
this_single_command_key_start = 0;
}
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
if (display_hourglass_p)
cancel_hourglass ();
#endif
#if 0 /* The following is fine for code reading a key sequence and
then proceeding with a lenghty computation, but it's not good
for code reading keys in a loop, like an input method. */
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
if (display_hourglass_p)
start_hourglass ();
#endif
this_single_command_key_start = 0;
}
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
if (display_hourglass_p)
cancel_hourglass ();
#endif
prompt, ! NILP (dont_downcase_last),
! NILP (can_return_switch_frame), 0);
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
if (display_hourglass_p)
start_hourglass ();
#endif
Lisp_Object saved_keys, saved_last_point_position_buffer;
Lisp_Object bindings, value;
struct gcpro gcpro1, gcpro2, gcpro3;
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
/* The call to Fcompleting_read wil start and cancel the hourglass,
but if the hourglass was already scheduled, this means that no
hourglass will be shown for the actual M-x command itself.
Qt, Qnil, Qextended_command_history, Qnil,
Qnil);
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
if (hstarted) start_hourglass ();
#endif
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
wipe_kboard (kb)
KBOARD *kb;
{
- if (kb->kbd_macro_buffer)
- xfree (kb->kbd_macro_buffer);
+ 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;
void
syms_of_keyboard ()
{
- Vpre_help_message = Qnil;
- staticpro (&Vpre_help_message);
+ pending_funcalls = Qnil;
Vlispy_mouse_stem = build_string ("mouse");
staticpro (&Vlispy_mouse_stem);
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.
will be in `last-command' during the following command. */);
Vthis_command = Qnil;
+ DEFVAR_LISP ("this-command-keys-shift-translated",
+ &Vthis_command_keys_shift_translated,
+ doc: /* Non-nil if the key sequence activating this command was shift-translated.
+Shift-translation occurs when there is no binding for the key sequence
+as entered, but a binding was found by changing an upper-case letter
+to lower-case, or a shifted function key to an unshifted one. */);
+ Vthis_command_keys_shift_translated = Qnil;
+
DEFVAR_LISP ("this-original-command", &Vthis_original_command,
doc: /* The command bound to the current key sequence before remapping.
It equals `this-command' if the original command was not remapped through
and tests the value when the command returns.
Buffer modification stores t in this variable. */);
Vdeactivate_mark = Qnil;
+ Qdeactivate_mark = intern ("deactivate-mark");
+ 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.