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 "macterm.h"
#endif
+#ifdef HAVE_NS
+#include "nsterm.h"
+extern Lisp_Object Qsuper;
+#endif
+
#ifndef USE_CRT_DLL
extern int errno;
#endif
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;
/* 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. */
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,
Lisp_Object old_level, old_length;
char macroerror[50];
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
if (display_hourglass_p)
cancel_hourglass ();
#endif
doc: /* Exit all recursive editing levels. */)
()
{
-#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;
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],
/* 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));
/* 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 (!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"));
}
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)
{
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);
}
}
#endif
}
-#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS)
+#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+ || 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 (MAC_OS) \
+ || defined (HAVE_NS)
else if (event->kind == ICONIFY_EVENT)
{
/* Make an event (iconify-frame (FRAME)). */
kbd_fetch_ptr = event + 1;
}
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
- || defined (USE_GTK)
+ || defined(HAVE_NS) || defined (USE_GTK)
else if (event->kind == MENU_BAR_ACTIVATE_EVENT)
{
kbd_fetch_ptr = event + 1;
obj = make_lispy_event (event);
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined(MAC_OS) \
- || defined (USE_GTK)
+ || 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
/* 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);
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)
+ || 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
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. */
+/*PENDING: under NS this effect does not hold, perhaps due to the
+ modifier-preference changes to where-is-internal.. */
+#ifdef HAVE_NS
+ CHECK_IMPURE (start);
+ XSETCDR (start, Fcons (Fcons (Qnil, Qnil), XCDR (start)));
+ cachelist = XCAR (XCDR (start));
+#else
+ cachelist = Fcons (Qnil, Qnil);
+#endif
newcache = 1;
tem = AREF (item_properties, ITEM_PROPERTY_KEYEQ);
if (!NILP (keyhint))
&& 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
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);
}
/* 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. */
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
{
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
wipe_kboard (kb)
KBOARD *kb;
{
- if (kb->kbd_macro_buffer)
- xfree (kb->kbd_macro_buffer);
+ xfree (kb->kbd_macro_buffer);
}
#ifdef MULTI_KBOARD
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);
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. */);