/* 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 Free Software Foundation, Inc.
+ 2005, 2006, 2007, 2008 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;
-
-#ifdef HAVE_WINDOW_SYSTEM
-/* Make all keyboard buffers much bigger when using X windows. */
-#ifdef MAC_OS8
-/* But not too big (local data > 32K error) if on Mac OS Classic. */
-#define KBD_BUFFER_SIZE 512
-#else
#define KBD_BUFFER_SIZE 4096
-#endif
-#else /* No X-windows, character input */
-#define KBD_BUFFER_SIZE 4096
-#endif /* No X-windows */
-
-/* Following definition copied from eval.c */
-
-struct backtrace
- {
- struct backtrace *next;
- Lisp_Object *function;
- Lisp_Object *args; /* Points to vector of args. */
- int nargs; /* length of vector. If nargs is UNEVALLED,
- args points to slot holding list of
- unevalled args */
- char evalargs;
- /* Nonzero means call value of debugger when done with this operation. */
- char debug_on_exit;
- };
-#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) \
extern int message_enable_multibyte;
-extern struct backtrace *backtrace_list;
-
/* If non-nil, the function that implements the display of help.
It's called with one argument, the help string to display. */
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. */
/* 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;
+#ifdef HAVE_DBUS
+Lisp_Object Qdbus_event;
#endif
-
/* Lisp_Object Qmouse_movement; - also an event header */
/* Properties of event headers. */
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);
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;
int nonundocount;
Lisp_Object keybuf[30];
int i;
- int no_direct;
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;
current_kboard->Vprefix_arg = Qnil;
while (pending_malloc_warning)
display_malloc_warning ();
- no_direct = 0;
-
Vdeactivate_mark = Qnil;
/* If minibuffer on and echo area in use,
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);
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],
}
else
{
- if (NILP (current_kboard->Vprefix_arg) && ! no_direct)
+ if (NILP (current_kboard->Vprefix_arg))
{
/* In case we jump to directly_done. */
Vcurrent_prefix_arg = current_kboard->Vprefix_arg;
/* 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"));
}
&& 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)
/* Save the upper bits here. */
int upper = c & ~0177;
+ if (! ASCII_BYTE_P (c))
+ return c |= ctrl_modifier;
+
c &= 0177;
/* Everything in the columns containing the upper-case letters
{
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);
}
}
USED_MOUSE_MENU is null, we don't dereference it.
Value is -2 when we find input on another keyboard. A second call
- to read_char will read it.
+ to read_char will read it.
If END_TIME is non-null, it is a pointer to an EMACS_TIME
specifying the maximum time to wait until. If no input arrives by
/* if redisplay was requested */
if (commandflag >= 0)
{
+ int echo_current = EQ (echo_message_buffer, echo_area_buffer[0]);
+
/* If there is pending input, process any events which are not
user-visible, such as X selection_request events. */
if (input_pending
swallow_events (0);
/* If that cleared input_pending, try again to redisplay. */
}
+
+ /* Prevent the redisplay we just did
+ from messing up echoing of the input after the prompt. */
+ if (commandflag == 0 && echo_current)
+ echo_message_buffer = echo_area_buffer[0];
+
}
/* Message turns off echoing unless more keystrokes turn it on again.
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. */
int count = SPECPDL_INDEX ();
record_single_kboard_state ();
#endif
-
+
last_input_char = c;
Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char), Qt);
/* 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)
{
if (sp->kind == MOUSE_CLICK_EVENT
|| sp->kind == WHEEL_EVENT
|| sp->kind == HORIZ_WHEEL_EVENT
-#ifdef WINDOWSNT
- || sp->kind == W32_SCROLL_BAR_CLICK_EVENT
-#endif
#ifdef HAVE_GPM
|| sp->kind == GPM_CLICK_EVENT
#endif
events. */
if (CONSP (Vunread_command_events))
break;
-
+
if (kbd_fetch_ptr != kbd_store_ptr)
break;
#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
/* 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_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;
}
internal_last_event_frame = frame;
kbd_fetch_ptr = event + 1;
}
+#ifdef HAVE_DBUS
+ else if (event->kind == DBUS_EVENT)
+ {
+ obj = make_lispy_event (event);
+ kbd_fetch_ptr = event + 1;
+ }
+#endif
else
{
/* If this event is on a different frame, return a switch-frame this
{
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
/* 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);
}
DEFUN ("current-idle-time", Fcurrent_idle_time, Scurrent_idle_time, 0, 0, 0,
- doc: /* Return the current length of Emacs idleness.
-The value is returned as a list of three integers. The first has the
+ 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 not idle is nil.
+
The microsecond count is zero on systems that do not provide
resolution finer than a second. */)
()
0, /* VK_MENU 0x12 */
"pause", /* VK_PAUSE 0x13 */
"capslock", /* VK_CAPITAL 0x14 */
-
- 0, 0, 0, 0, 0, 0, /* 0x15 .. 0x1A */
-
+ "kana", /* VK_KANA/VK_HANGUL 0x15 */
+ 0, /* 0x16 */
+ "junja", /* VK_JUNJA 0x17 */
+ "final", /* VK_FINAL 0x18 */
+ "kanji", /* VK_KANJI/VK_HANJA 0x19 */
+ 0, /* 0x1A */
"escape", /* VK_ESCAPE 0x1B */
-
- 0, 0, 0, 0, /* 0x1C .. 0x1F */
-
+ "convert", /* VK_CONVERT 0x1C */
+ "non-convert", /* VK_NONCONVERT 0x1D */
+ "accept", /* VK_ACCEPT 0x1E */
+ "mode-change", /* VK_MODECHANGE 0x1F */
0, /* VK_SPACE 0x20 */
"prior", /* VK_PRIOR 0x21 */
"next", /* VK_NEXT 0x22 */
"lwindow", /* VK_LWIN 0x5B */
"rwindow", /* VK_RWIN 0x5C */
"apps", /* VK_APPS 0x5D */
-
- 0, 0, /* 0x5E .. 0x5F */
-
+ 0, /* 0x5E */
+ "sleep",
"kp-0", /* VK_NUMPAD0 0x60 */
"kp-1", /* VK_NUMPAD1 0x61 */
"kp-2", /* VK_NUMPAD2 0x62 */
"kp-numlock", /* VK_NUMLOCK 0x90 */
"scroll", /* VK_SCROLL 0x91 */
-
+ /* Not sure where the following block comes from.
+ Windows headers have NEC and Fujitsu specific keys in
+ this block, but nothing generic. */
"kp-space", /* VK_NUMPAD_CLEAR 0x92 */
"kp-enter", /* VK_NUMPAD_ENTER 0x93 */
"kp-prior", /* VK_NUMPAD_PRIOR 0x94 */
* VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys.
* Used only as parameters to GetAsyncKeyState and GetKeyState.
* No other API or message will distinguish left and right keys this way.
+ * 0xA0 .. 0xA5
*/
- /* 0xA0 .. 0xEF */
+ 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Multimedia keys. These are handled as WM_APPCOMMAND, which allows us
+ to enable them selectively, and gives access to a few more functions.
+ See lispy_multimedia_keys below. */
+ 0, 0, 0, 0, 0, 0, 0, /* 0xA6 .. 0xAC Browser */
+ 0, 0, 0, /* 0xAD .. 0xAF Volume */
+ 0, 0, 0, 0, /* 0xB0 .. 0xB3 Media */
+ 0, 0, 0, 0, /* 0xB4 .. 0xB7 Apps */
- /* 0xF0 .. 0xF5 */
+ /* 0xB8 .. 0xC0 "OEM" keys - all seem to be punctuation. */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
+ /* 0xC1 - 0xDA unallocated, 0xDB-0xDF more OEM keys */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, /* 0xE0 */
+ "ax", /* VK_OEM_AX 0xE1 */
+ 0, /* VK_OEM_102 0xE2 */
+ "ico-help", /* VK_ICO_HELP 0xE3 */
+ "ico-00", /* VK_ICO_00 0xE4 */
+ 0, /* VK_PROCESSKEY 0xE5 */
+ "ico-clear", /* VK_ICO_CLEAR 0xE6 */
+ "packet", /* VK_PACKET 0xE7 */
+ 0, /* 0xE8 */
+ "reset", /* VK_OEM_RESET 0xE9 */
+ "jump", /* VK_OEM_JUMP 0xEA */
+ "oem-pa1", /* VK_OEM_PA1 0xEB */
+ "oem-pa2", /* VK_OEM_PA2 0xEC */
+ "oem-pa3", /* VK_OEM_PA3 0xED */
+ "wsctrl", /* VK_OEM_WSCTRL 0xEE */
+ "cusel", /* VK_OEM_CUSEL 0xEF */
+ "oem-attn", /* VK_OEM_ATTN 0xF0 */
+ "finish", /* VK_OEM_FINISH 0xF1 */
+ "copy", /* VK_OEM_COPY 0xF2 */
+ "auto", /* VK_OEM_AUTO 0xF3 */
+ "enlw", /* VK_OEM_ENLW 0xF4 */
+ "backtab", /* VK_OEM_BACKTAB 0xF5 */
"attn", /* VK_ATTN 0xF6 */
"crsel", /* VK_CRSEL 0xF7 */
"exsel", /* VK_EXSEL 0xF8 */
0 /* 0xFF */
};
+/* Some of these duplicate the "Media keys" on newer keyboards,
+ but they are delivered to the application in a different way. */
+static char *lispy_multimedia_keys[] =
+ {
+ 0,
+ "browser-back",
+ "browser-forward",
+ "browser-refresh",
+ "browser-stop",
+ "browser-search",
+ "browser-favorites",
+ "browser-home",
+ "volume-mute",
+ "volume-down",
+ "volume-up",
+ "media-next",
+ "media-previous",
+ "media-stop",
+ "media-play-pause",
+ "mail",
+ "media-select",
+ "app-1",
+ "app-2",
+ "bass-down",
+ "bass-boost",
+ "bass-up",
+ "treble-down",
+ "treble-up",
+ "mic-volume-mute",
+ "mic-volume-down",
+ "mic-volume-up",
+ "help",
+ "find",
+ "new",
+ "open",
+ "close",
+ "save",
+ "print",
+ "undo",
+ "redo",
+ "copy",
+ "cut",
+ "paste",
+ "mail-reply",
+ "mail-forward",
+ "mail-send",
+ "spell-check",
+ "toggle-dictate-command",
+ "mic-toggle",
+ "correction-list",
+ "media-play",
+ "media-pause",
+ "media-record",
+ "media-fast-forward",
+ "media-rewind",
+ "media-channel-up",
+ "media-channel-down"
+ };
+
#else /* not HAVE_NTGUI */
/* This should be dealt with in XTread_socket now, and that doesn't
{
/* A simple keystroke. */
case ASCII_KEYSTROKE_EVENT:
- {
- Lisp_Object lispy_c;
- int c = event->code & 0377;
- /* Turn ASCII characters into control characters
- when proper. */
- if (event->modifiers & ctrl_modifier)
- c = make_ctrl_char (c);
-
- /* Add in the other modifier bits. We took care of ctrl_modifier
- just above, and the shift key was taken care of by the X code,
- and applied to control characters by make_ctrl_char. */
- c |= (event->modifiers
- & (meta_modifier | alt_modifier
- | hyper_modifier | super_modifier));
- /* Distinguish Shift-SPC from SPC. */
- if ((event->code & 0377) == 040
- && event->modifiers & shift_modifier)
- c |= shift_modifier;
- button_down_time = 0;
- XSETFASTINT (lispy_c, c);
- return lispy_c;
- }
-
case MULTIBYTE_CHAR_KEYSTROKE_EVENT:
{
Lisp_Object lispy_c;
int c = event->code;
+ if (event->kind == ASCII_KEYSTROKE_EVENT)
+ {
+ c &= 0377;
+ eassert (c == event->code);
+ /* Turn ASCII characters into control characters
+ when proper. */
+ if (event->modifiers & ctrl_modifier)
+ {
+ c = make_ctrl_char (c);
+ event->modifiers &= ~ctrl_modifier;
+ }
+ }
- /* Add in the other modifier bits. We took care of ctrl_modifier
- just above, and the shift key was taken care of by the X code,
- and applied to control characters by make_ctrl_char. */
+ /* Add in the other modifier bits. The shift key was taken care
+ of by the X code. */
c |= (event->modifiers
& (meta_modifier | alt_modifier
| hyper_modifier | super_modifier | ctrl_modifier));
- /* What about the `shift' modifier ? */
+ /* Distinguish Shift-SPC from SPC. */
+ if ((event->code) == 040
+ && event->modifiers & shift_modifier)
+ c |= shift_modifier;
button_down_time = 0;
XSETFASTINT (lispy_c, c);
return lispy_c;
(sizeof (lispy_function_keys)
/ sizeof (lispy_function_keys[0])));
+#ifdef WINDOWSNT
+ case MULTIMEDIA_KEY_EVENT:
+ if (event->code < (sizeof (lispy_multimedia_keys)
+ / sizeof (lispy_multimedia_keys[0]))
+ && event->code > 0 && lispy_multimedia_keys[event->code])
+ {
+ return modify_event_symbol (event->code, event->modifiers,
+ Qfunction_key, Qnil,
+ lispy_multimedia_keys, &func_key_syms,
+ (sizeof (lispy_multimedia_keys)
+ / sizeof (lispy_multimedia_keys[0])));
+ }
+ return Qnil;
+#endif
+
#ifdef HAVE_MOUSE
/* A mouse click. Figure out where it is, decide whether it's
a press, click or drag, and build the appropriate structure. */
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 /* USE_TOOLKIT_SCROLL_BARS */
-#ifdef WINDOWSNT
- case W32_SCROLL_BAR_CLICK_EVENT:
- {
- int button = event->code;
- int is_double;
- Lisp_Object position;
- Lisp_Object *start_pos_ptr;
- Lisp_Object start_pos;
-
- {
- Lisp_Object window;
- Lisp_Object portion_whole;
- Lisp_Object part;
-
- window = event->frame_or_window;
- portion_whole = Fcons (event->x, event->y);
- part = *scroll_bar_parts[(int) event->part];
-
- position
- = Fcons (window,
- Fcons (Qvertical_scroll_bar,
- Fcons (portion_whole,
- Fcons (make_number (event->timestamp),
- Fcons (part, Qnil)))));
- }
-
- /* Always treat W32 scroll bar events as clicks. */
- event->modifiers |= click_modifier;
-
- {
- /* Get the symbol we should use for the mouse click. */
- Lisp_Object head;
-
- head = modify_event_symbol (button,
- event->modifiers,
- Qmouse_click,
- Vlispy_mouse_stem,
- NULL, &mouse_syms,
- XVECTOR (mouse_syms)->size);
- return Fcons (head,
- Fcons (position,
- Qnil));
- }
- }
-#endif /* WINDOWSNT */
-
case DRAG_N_DROP_EVENT:
{
FRAME_PTR f;
}
#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:
+#ifdef HAVE_DBUS
+ case DBUS_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)));
+ return Fcons (Qdbus_event, event->arg);
}
-#endif
+#endif /* HAVE_DBUS */
#ifdef HAVE_GPM
case GPM_CLICK_EVENT:
SYMBOL's Qevent_symbol_element_mask property, and maintains the
Qevent_symbol_elements property. */
+#define KEY_TO_CHAR(k) (XINT (k) & ((1 << CHARACTERBITS) - 1))
+
Lisp_Object
parse_modifiers (symbol)
Lisp_Object symbol;
{
Lisp_Object elements;
+ if (INTEGERP (symbol))
+ return (Fcons (make_number (KEY_TO_CHAR (symbol)),
+ Fcons (make_number (XINT (symbol) & CHAR_MODIFIER_MASK),
+ Qnil)));
+ else if (!SYMBOLP (symbol))
+ return Qnil;
+
elements = Fget (symbol, Qevent_symbol_element_mask);
if (CONSP (elements))
return elements;
}
}
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,
+ Sevent_symbol_parse_modifiers, 1, 1, 0,
+ doc: /* Parse the event symbol. For internal use. */)
+ (symbol)
+ Lisp_Object symbol;
+{
+ /* Fill the cache if needed. */
+ parse_modifiers (symbol);
+ /* Ignore the result (which is stored on Qevent_symbol_element_mask)
+ and use the Lispier representation stored on Qevent_symbol_elements
+ instead. */
+ return Fget (symbol, Qevent_symbol_elements);
+}
+
/* Apply the modifiers MODIFIERS to the symbol BASE.
BASE must be unmodified.
/* Mask out upper bits. We don't know where this value's been. */
modifiers &= INTMASK;
+ if (INTEGERP (base))
+ return make_number (XINT (base) | modifiers);
+
/* The click modifier never figures into cache indices. */
cache = Fget (base, Qmodifier_cache);
XSETFASTINT (index, (modifiers & ~click_modifier));
/* 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);
gobble_input (expected)
int expected;
{
-#ifndef VMS
+#ifdef HAVE_DBUS
+ /* Check whether a D-Bus message has arrived. */
+ xd_read_queued_messages ();
+#endif /* HAVE_DBUS */
+
#ifdef SIGIO
if (interrupt_input)
{
sigsetmask (mask);
}
else
-#endif
#endif
read_avail_input (expected);
#endif
}
}
\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. */
nread += nr;
expected = 0;
}
-
+
if (nr == -1) /* Not OK to read input now. */
{
err = 1;
else if (nr == -2) /* Non-transient error. */
{
/* The terminal device terminated; it should be closed. */
-
+
/* Kill Emacs if this was our last terminal. */
if (!terminal_list->next_terminal)
/* Formerly simply reported no input, but that
group? Perhaps on systems with FIONREAD Emacs is
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);
+ {
+ Lisp_Object tmp;
+ XSETTERMINAL (tmp, t);
+ Fdelete_terminal (tmp, Qnoelisp);
+ }
}
if (hold_quit.kind != NO_EVENT)
int nread = 0;
if (!terminal->name) /* Don't read from a dead terminal. */
- return;
+ return 0;
if (terminal->type != output_termcap)
abort ();
if (n_to_read > sizeof cbuf)
n_to_read = sizeof cbuf;
#else /* no FIONREAD */
-#if defined (USG) || defined (DGUX) || defined(CYGWIN)
+#if defined (USG) || defined(CYGWIN)
/* Read some input if available, but don't wait. */
n_to_read = sizeof cbuf;
fcntl (fileno (tty->input), F_SETFL, O_NDELAY);
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,
);
#ifndef FIONREAD
-#if defined (USG) || defined (DGUX) || defined (CYGWIN)
+#if defined (USG) || defined (CYGWIN)
fcntl (fileno (tty->input), F_SETFL, 0);
-#endif /* USG or DGUX or CYGWIN */
+#endif /* USG or CYGWIN */
#endif /* no FIONREAD */
if (nread <= 0)
buf.modifiers = meta_modifier;
if (tty->meta_key != 2)
cbuf[i] &= ~0x80;
-
+
buf.code = cbuf[i];
/* Set the frame corresponding to the active tty. Note that the
value of selected_frame is not reliable here, redisplay tends
to temporarily change it. */
buf.frame_or_window = tty->top_frame;
buf.arg = Qnil;
-
+
kbd_buffer_store_event (&buf);
/* Don't look at input that follows a C-g too closely.
This reduces lossage due to autorepeat on C-g. */
return nread;
}
-#endif /* not VMS */
\f
void
handle_async_input ()
{
-#ifdef BSD4_1
- extern int select_alarmed;
-#endif
-
interrupt_input_pending = 0;
while (1)
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
}
}
signal (signo, input_available_signal);
#endif /* USG */
-#ifdef BSD4_1
- sigisheld (SIGIO);
-#endif
-
#ifdef SYNC_INPUT
interrupt_input_pending = 1;
#else
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))
tem = XCDR (cachelist);
if (newcache && !NILP (tem))
{
- tem = concat3 (build_string (" ("), tem, build_string (")"));
+ tem = concat2 (build_string (" "), tem);
+ /* 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;
}
/* 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. */
last_nonmenu_event = Qnil;
delayed_switch_frame = Qnil;
-
+
if (INTERACTIVE)
{
if (!NILP (prompt))
from_string = Qnil;
/* The multi-tty merge moved the code below to right after
- `replay_sequence' which caused alll these translation maps to be applied
+ `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,
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;
orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
goto replay_sequence;
}
-#endif
}
/* read_char returns t when it shows a menu and the user rejects it.
}
GROW_RAW_KEYBUF;
- XVECTOR (raw_keybuf)->contents[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;
}
and is a shifted function key,
use the corresponding unshifted function key instead. */
if (first_binding >= nmaps
- && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t
- && SYMBOLP (key))
- {
- Lisp_Object breakdown;
- int modifiers;
-
- breakdown = parse_modifiers (key);
- modifiers = XINT (XCAR (XCDR (breakdown)));
- if (modifiers & shift_modifier)
+ && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t)
+ {
+ Lisp_Object breakdown = parse_modifiers (key);
+ int modifiers
+ = CONSP (breakdown) ? (XINT (XCAR (XCDR (breakdown)))) : 0;
+
+ if (modifiers & shift_modifier
+ /* Treat uppercase keys as shifted. */
+ || (INTEGERP (key)
+ && (KEY_TO_CHAR (key)
+ < XCHAR_TABLE (current_buffer->downcase_table)->size)
+ && UPPERCASEP (KEY_TO_CHAR (key))))
{
- Lisp_Object new_key;
+ Lisp_Object new_key
+ = (modifiers & shift_modifier
+ ? apply_modifiers (modifiers & ~shift_modifier,
+ XCAR (breakdown))
+ : make_number (DOWNCASE (KEY_TO_CHAR (key)) | modifiers));
original_uppercase = key;
original_uppercase_position = t - 1;
- modifiers &= ~shift_modifier;
- new_key = apply_modifiers (modifiers,
- XCAR (breakdown));
-
+ /* 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);
+ /* Reset fkey (and consequently keytran) to apply
+ function-key-map on the result, so that S-backspace is
+ correctly mapped to DEL (via backspace). OTOH,
+ 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 (!dummyflag)
read_key_sequence_cmd = (first_binding < nmaps
? defs[first_binding]
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
register Lisp_Object final;
register Lisp_Object tem;
Lisp_Object prefixarg;
- struct backtrace backtrace;
extern int debug_on_next_call;
debug_on_next_call = 0;
}
if (CONSP (final) || SUBRP (final) || COMPILEDP (final))
- {
- backtrace.next = backtrace_list;
- backtrace_list = &backtrace;
- backtrace.function = &Qcall_interactively;
- backtrace.args = &cmd;
- backtrace.nargs = 1;
- backtrace.evalargs = 0;
- backtrace.debug_on_exit = 0;
+ /* Don't call Fcall_interactively directly because we want to make
+ sure the backtrace has an entry for `call-interactively'.
+ For the same reason, pass `cmd' rather than `final'. */
+ return call3 (Qcall_interactively, cmd, record_flag, keys);
- tem = Fcall_interactively (cmd, record_flag, keys);
-
- backtrace_list = backtrace.next;
- return tem;
- }
return Qnil;
}
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
bindings = Qnil;
value = Qnil;
- GCPRO2 (bindings, value);
+ GCPRO3 (bindings, value, function);
value = Fcommand_execute (function, Qt, Qnil, Qnil);
/* If the command has a key binding, print it now. */
*/
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
#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')
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)
+ if (new_interrupt_input != interrupt_input)
{
#ifdef POLL_FOR_INPUT
stop_polling ();
struct terminal *t = get_terminal (terminal, 1);
struct tty_display_info *tty;
int new_meta;
-
+
if (t == NULL || t->type != output_termcap)
return Qnil;
tty = t->display_info.tty;
else
new_meta = 2;
- if (tty->meta_key != new_meta)
+ if (tty->meta_key != new_meta)
{
#ifndef DOS_NT
/* this causes startup screen to be restored and messes with the mouse */
#endif
tty->meta_key = new_meta;
-
+
#ifndef DOS_NT
init_sys_modes (tty);
#endif
/* this causes startup screen to be restored and messes with the mouse */
reset_sys_modes (tty);
#endif
-
+
/* Don't let this value be out of range. */
quit_char = XINT (quit) & (tty->meta_key == 0 ? 0177 : 0377);
return Qnil;
}
-
+
DEFUN ("set-input-mode", Fset_input_mode, Sset_input_mode, 3, 4, 0,
doc: /* Set mode of reading keyboard input.
First arg INTERRUPT non-nil means use input interrupts;
kb->reference_count = 0;
kb->Vsystem_key_alist = Qnil;
kb->system_key_syms = Qnil;
+ kb->Vwindow_system = Qt; /* Unset. */
kb->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
kb->Vlocal_function_key_map = Fmake_sparse_keymap (Qnil);
Fset_keymap_parent (kb->Vlocal_function_key_map, Vfunction_key_map);
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 ()
{
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);
+ /* A value of nil for Vwindow_system normally means a tty, but we also use
+ it for the initial terminal since there is no window system there. */
+ current_kboard->Vwindow_system = Qnil;
if (!noninteractive)
{
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);
+#ifdef HAVE_DBUS
+ Qdbus_event = intern ("dbus-event");
+ staticpro (&Qdbus_event);
#endif
Qmenu_enable = intern ("menu-enable");
staticpro (&help_form_saved_window_configs);
defsubr (&Scurrent_idle_time);
+ defsubr (&Sevent_symbol_parse_modifiers);
defsubr (&Sevent_convert_list);
defsubr (&Sread_key_sequence);
defsubr (&Sread_key_sequence_vector);
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. */);
`local-function-key-map' binding and this variable, then the local
definition will take precendence. */);
Vfunction_key_map = Fmake_sparse_keymap (Qnil);
-
+
DEFVAR_LISP ("key-translation-map", &Vkey_translation_map,
doc: /* Keymap of key translations that can override keymaps.
This keymap works like `function-key-map', but comes after that,
Help functions bind this to allow help on disabled menu items
and tool-bar buttons. */);
Venable_disabled_menus_and_buttons = Qnil;
+
+ /* 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;
}
void
* "handle-select-window"); */
initial_define_lispy_key (Vspecial_event_map, "save-session",
"handle-save-session");
+
+#ifdef HAVE_DBUS
+ /* Define a special event which is raised for dbus callback
+ functions. */
+ initial_define_lispy_key (Vspecial_event_map, "dbus-event",
+ "dbus-handle-event");
+#endif
}
/* Mark the pointers in the kboard objects.
mark_object (kb->Vlast_kbd_macro);
mark_object (kb->Vsystem_key_alist);
mark_object (kb->system_key_syms);
+ mark_object (kb->Vwindow_system);
mark_object (kb->Vinput_decode_map);
mark_object (kb->Vlocal_function_key_map);
mark_object (kb->Vdefault_minibuffer_frame);