/* Keyboard and mouse input; editor command loop.
- Copyright (C) 1985,86,87,88,89,93,94,95,96 Free Software Foundation, Inc.
+ Copyright (C) 1985,86,87,88,89,93,94,95,96,97 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "window.h"
#include "commands.h"
#include "buffer.h"
+#include "charset.h"
#include "disptab.h"
#include "dispextern.h"
#include "keyboard.h"
/* Nonzero means C-g should cause immediate error-signal. */
int immediate_quit;
+/* The user's ERASE setting. */
+Lisp_Object Vtty_erase_char;
+
/* Character to recognize as the help char. */
Lisp_Object Vhelp_char;
static Lisp_Object Vauto_save_timeout;
/* Total number of times read_char has returned. */
-int num_input_chars;
+int num_input_events;
/* Total number of times read_char has returned, outside of macros. */
-int num_nonmacro_input_chars;
+int num_nonmacro_input_events;
/* Auto-save automatically when this many characters have been typed
since the last time. */
static int auto_save_interval;
-/* Value of num_nonmacro_input_chars as of last auto save. */
+/* Value of num_nonmacro_input_events as of last auto save. */
int last_auto_save;
Lisp_Object Qforward_char;
Lisp_Object Qbackward_char;
Lisp_Object Qundefined;
+Lisp_Object Qtimer_event_handler;
/* read_key_sequence stores here the command definition of the
key sequence that it reads. */
Lisp_Object Vlucid_menu_bar_dirty_flag;
Lisp_Object Qrecompute_lucid_menubar, Qactivate_menubar_hook;
+Lisp_Object Qecho_area_clear_hook;
+
/* Hooks to run before and after each command. */
Lisp_Object Qpre_command_hook, Vpre_command_hook;
Lisp_Object Qpost_command_hook, Vpost_command_hook;
/* Symbols to denote kinds of events. */
Lisp_Object Qfunction_key;
Lisp_Object Qmouse_click;
-Lisp_Object Qtimer_event;
+#ifdef WINDOWSNT
+Lisp_Object Qmouse_wheel;
+#endif
/* Lisp_Object Qmouse_movement; - also an event header */
/* Properties of event headers. */
extern char *x_get_keysym_name ();
+static void record_menu_key ();
+
+void swallow_events ();
+
Lisp_Object Qpolling_period;
/* List of absolute timers. Appears in order of next scheduled event. */
extern Lisp_Object Vprint_level, Vprint_length;
+extern nonascii_insert_offset;
+
/* Address (if not 0) of EMACS_TIME to zero out if a SIGIO interrupt
happens. */
EMACS_TIME *input_available_clear_time;
record_auto_save ()
{
- last_auto_save = num_nonmacro_input_chars;
+ last_auto_save = num_nonmacro_input_events;
}
/* Make an auto save happen as soon as possible at command level. */
command_loop_1 ()
{
Lisp_Object cmd, tem;
- int lose;
+ int lose, lose2;
int nonundocount;
Lisp_Object keybuf[30];
int i;
{
if (NILP (Vunread_command_events)
&& NILP (Vexecuting_macro)
- && !NILP (sit_for (0, post_command_idle_delay, 0, 1)))
+ && !NILP (sit_for (0, post_command_idle_delay, 0, 1, 1)))
safe_run_hooks (Qpost_command_idle_hook);
}
Fsit_for (make_number (2), Qnil, Qnil);
/* Clear the echo area. */
- message2 (0);
+ message2 (0, 0);
+ safe_run_hooks (Qecho_area_clear_hook);
unbind_to (count, Qnil);
/* Read next key sequence; i gets its length. */
i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
- Qnil, 0, 1);
+ Qnil, 0, 1, 1);
/* A filter may have run while we were reading the input. */
if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
{
struct Lisp_Char_Table *dp
= window_display_table (XWINDOW (selected_window));
- lose = FETCH_CHAR (PT);
- SET_PT (PT + 1);
+ lose = FETCH_BYTE (PT);
+ SET_PT (forward_point (1));
if ((dp
? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1
: (NILP (DISP_CHAR_VECTOR (dp, lose))
&& (lose >= 0x20 && lose < 0x7f)))
: (lose >= 0x20 && lose < 0x7f))
+ /* To extract the case of continuation on
+ wide-column characters. */
+ && (WIDTH_BY_CHAR_HEAD (FETCH_BYTE (PT)) == 1)
&& (XFASTINT (XWINDOW (selected_window)->last_modified)
>= MODIFF)
&& (XFASTINT (XWINDOW (selected_window)->last_overlay_modified)
{
struct Lisp_Char_Table *dp
= window_display_table (XWINDOW (selected_window));
- SET_PT (PT - 1);
- lose = FETCH_CHAR (PT);
+ SET_PT (forward_point (-1));
+ lose = FETCH_BYTE (PT);
if ((dp
? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1
/* Try this optimization only on ascii keystrokes. */
&& INTEGERP (last_command_char))
{
- unsigned char c = XINT (last_command_char);
+ unsigned int c = XINT (last_command_char);
int value;
if (NILP (Vexecuting_macro)
nonundocount = 0;
if (!lose
- && (PT == ZV || FETCH_CHAR (PT) == '\n'))
+ && (PT == ZV || FETCH_BYTE (PT) == '\n'))
{
struct Lisp_Char_Table *dp
= window_display_table (XWINDOW (selected_window));
int lose = c;
+ /* Add the offset to the character, for Finsert_char.
+ We pass internal_self_insert the unmodified character
+ because it itself does this offsetting. */
+ if (lose >= 0200 && lose <= 0377
+ && ! NILP (current_buffer->enable_multibyte_characters))
+ lose += nonascii_insert_offset;
+
if (dp)
{
Lisp_Object obj;
{
if (NILP (Vunread_command_events)
&& NILP (Vexecuting_macro)
- && !NILP (sit_for (0, post_command_idle_delay, 0, 1)))
+ && !NILP (sit_for (0, post_command_idle_delay, 0, 1, 1)))
safe_run_hooks (Qpost_command_idle_hook);
}
Lisp_Object prev_event;
int *used_mouse_menu;
{
- register Lisp_Object c;
+ Lisp_Object c;
int count;
jmp_buf local_getcjmp;
jmp_buf save_jump;
int key_already_recorded = 0;
Lisp_Object tem, save;
Lisp_Object also_record;
+ struct gcpro gcpro1;
+
also_record = Qnil;
before_command_key_count = this_command_key_count;
before_command_echo_length = echo_length ();
+ c = Qnil;
+
+ GCPRO1 (c);
retry:
|| executing_macro_index >= XFASTINT (Flength (Vexecuting_macro)))
{
XSETINT (c, -1);
- return c;
+ RETURN_UNGCPRO (c);
}
c = Faref (Vexecuting_macro, make_number (executing_macro_index));
goto reread_first;
}
- if (commandflag >= 0 && !input_pending
- && !detect_input_pending_run_timers (0))
- redisplay ();
+ if (commandflag >= 0)
+ {
+ if (input_pending
+ || detect_input_pending_run_timers (0))
+ swallow_events (0);
+
+ if (!input_pending)
+ redisplay ();
+ }
/* Message turns off echoing unless more keystrokes turn it on again. */
if (echo_area_glyphs && *echo_area_glyphs
*tailp = Fcons (c, Qnil);
kb->kbd_queue_has_data = 1;
current_kboard = kb;
+ /* This is going to exit from read_char
+ so we had better get rid of this frame's stuff. */
+ UNGCPRO;
longjmp (wrong_kboard_jmpbuf, 1);
}
}
{
save_getcjmp (save_jump);
restore_getcjmp (local_getcjmp);
- tem0 = sit_for (echo_keystrokes, 0, 1, 1);
+ tem0 = sit_for (echo_keystrokes, 0, 1, 1, 0);
restore_getcjmp (save_jump);
- if (EQ (tem0, Qt))
+ if (EQ (tem0, Qt)
+ && ! CONSP (Vunread_command_events))
echo_now ();
}
}
if (commandflag != 0
&& auto_save_interval > 0
- && num_nonmacro_input_chars - last_auto_save > max (auto_save_interval, 20)
+ && num_nonmacro_input_events - last_auto_save > max (auto_save_interval, 20)
&& !detect_input_pending_run_timers (0))
{
Fdo_auto_save (Qnil, Qnil);
/* Don't bring up a menu if we already have another event. */
&& NILP (Vunread_command_events)
&& unread_command_char < 0)
- c = read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu);
+ {
+ c = read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu);
+
+ /* Now that we have read an event, Emacs is not idle. */
+ timer_stop_idle ();
+
+ RETURN_UNGCPRO (c);
+ }
/* Maybe autosave and/or garbage collect due to idleness. */
/* Auto save if enough time goes by without input. */
if (commandflag != 0
- && num_nonmacro_input_chars > last_auto_save
+ && num_nonmacro_input_events > last_auto_save
&& INTEGERP (Vauto_save_timeout)
&& XINT (Vauto_save_timeout) > 0)
{
save_getcjmp (save_jump);
restore_getcjmp (local_getcjmp);
tem0 = sit_for (delay_level * XFASTINT (Vauto_save_timeout) / 4,
- 0, 1, 1);
+ 0, 1, 1, 0);
restore_getcjmp (save_jump);
- if (EQ (tem0, Qt))
+ if (EQ (tem0, Qt)
+ && ! CONSP (Vunread_command_events))
{
Fdo_auto_save (Qnil, Qnil);
}
}
+ /* If this has become non-nil here, it has been set by a timer
+ or sentinel or filter. */
+ if (CONSP (Vunread_command_events))
+ {
+ c = XCONS (Vunread_command_events)->car;
+ Vunread_command_events = XCONS (Vunread_command_events)->cdr;
+ }
+
/* Read something from current KBOARD's side queue, if possible. */
if (NILP (c))
if (kb->kbd_queue_has_data)
{
current_kboard = kb;
+ /* This is going to exit from read_char
+ so we had better get rid of this frame's stuff. */
+ UNGCPRO;
longjmp (wrong_kboard_jmpbuf, 1);
}
}
if (single_kboard)
goto wrong_kboard;
current_kboard = kb;
+ /* This is going to exit from read_char
+ so we had better get rid of this frame's stuff. */
+ UNGCPRO;
longjmp (wrong_kboard_jmpbuf, 1);
}
#endif
non_reread:
- /* Now that we have read an event, Emacs is not idle--
- unless the event was a timer event (not used now). */
- if (! (CONSP (c) && EQ (XCONS (c)->car, Qtimer_event)))
- timer_stop_idle ();
+ timer_stop_idle ();
start_polling ();
non_reread_1:
/* Buffer switch events are only for internal wakeups
- so don't show them to the user. */
- if (BUFFERP (c))
- return c;
-
- if (key_already_recorded)
- return c;
+ so don't show them to the user.
+ Also, don't record a key if we already did. */
+ if (BUFFERP (c) || key_already_recorded)
+ RETURN_UNGCPRO (c);
/* Process special events within read_char
and loop around to read another event. */
}
/* Wipe the echo area. */
+ if (echo_area_glyphs)
+ safe_run_hooks (Qecho_area_clear_hook);
echo_area_glyphs = 0;
/* Handle things that only apply to characters. */
{
/* If kbd_buffer_get_event gave us an EOF, return that. */
if (XINT (c) == -1)
- return c;
+ RETURN_UNGCPRO (c);
if (STRINGP (Vkeyboard_translate_table)
&& XSTRING (Vkeyboard_translate_table)->size > (unsigned) XFASTINT (c))
from_macro:
reread_first:
+
before_command_key_count = this_command_key_count;
before_command_echo_length = echo_length ();
/* Re-reading in the middle of a command */
reread:
last_input_char = c;
- num_input_chars++;
+ num_input_events++;
/* Process the help character specially if enabled */
if (!NILP (Vhelp_form) && help_char_p (c))
}
}
- return c;
+ RETURN_UNGCPRO (c);
+}
+
+/* Record a key that came from a mouse menu.
+ Record it for echoing, for this-command-keys, and so on. */
+
+static void
+record_menu_key (c)
+ Lisp_Object c;
+{
+ /* Wipe the echo area. */
+ echo_area_glyphs = 0;
+
+ record_char (c);
+
+ before_command_key_count = this_command_key_count;
+ before_command_echo_length = echo_length ();
+
+ /* Don't echo mouse motion events. */
+ if (echo_keystrokes)
+ {
+ echo_char (c);
+
+ /* Once we reread a character, echoing can happen
+ the next time we pause to read a new one. */
+ ok_to_echo_at_next_pause = 0;
+ }
+
+ /* Record this character as part of the current key. */
+ add_command_key (c);
+
+ /* Re-reading in the middle of a command */
+ last_input_char = c;
+ num_input_events++;
}
/* Return 1 if should recognize C as "the help character". */
store_kbd_macro_char (c);
- num_nonmacro_input_chars++;
+ num_nonmacro_input_events++;
}
Lisp_Object
}
}
\f
+/* Discard any mouse events in the event buffer by setting them to
+ no_event. */
+void
+discard_mouse_events ()
+{
+ struct input_event *sp;
+ for (sp = kbd_fetch_ptr; sp != kbd_store_ptr; sp++)
+ {
+ if (sp == kbd_buffer + KBD_BUFFER_SIZE)
+ sp = kbd_buffer;
+
+ if (sp->kind == mouse_click
+#ifdef WINDOWSNT
+ || sp->kind == w32_scroll_bar_click
+#endif
+ || sp->kind == scroll_bar_click)
+ {
+ sp->kind = no_event;
+ }
+ }
+}
+\f
/* Read one event from the event buffer, waiting if necessary.
The value is a Lisp object representing the event.
The value is nil for an event that should be ignored,
#endif /* not VMS */
}
+ if (CONSP (Vunread_command_events))
+ {
+ Lisp_Object first;
+ first = XCONS (Vunread_command_events)->car;
+ Vunread_command_events = XCONS (Vunread_command_events)->cdr;
+ *kbp = current_kboard;
+ return first;
+ }
+
/* At this point, we know that there is a readable event available
somewhere. If the event queue is empty, then there must be a
mouse movement enabled and available. */
XSETBUFFER (obj, current_buffer);
kbd_fetch_ptr = event + 1;
}
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
else if (event->kind == menu_bar_activate_event)
{
kbd_fetch_ptr = event + 1;
(They shouldn't otherwise be found in the buffer,
but on some machines it appears they do show up
even without MULTI_KBOARD.) */
+ /* On Windows NT/9X, no_event is used to delete extraneous
+ mouse events during a popup-menu call. */
else if (event->kind == no_event)
kbd_fetch_ptr = event + 1;
abort ();
#endif
}
- /* Note that timer_event is currently never used. */
- else if (event->kind == timer_event)
- {
- Lisp_Object tem, lisp_event;
- int was_locked = single_kboard;
-
- tem = get_keymap_1 (Vspecial_event_map, 0, 0);
- tem = get_keyelt (access_keymap (tem, Qtimer_event, 0, 0),
- 1);
- lisp_event = Fcons (Qtimer_event,
- Fcons (Fcdr (event->frame_or_window), Qnil));
- kbd_fetch_ptr = event + 1;
- if (kbd_fetch_ptr == kbd_store_ptr)
- input_pending = 0;
- Fcommand_execute (tem, Qnil, Fvector (1, &lisp_event), Qt);
- timers_run++;
- if (do_display)
- redisplay_preserve_echo_area ();
-
- /* Resume allowing input from any kboard, if that was true before. */
- if (!was_locked)
- any_kboard_state ();
- }
else
break;
}
EMACS_TIME nexttime;
EMACS_TIME now, idleness_now;
Lisp_Object timers, idle_timers, chosen_timer;
- /* Nonzero if we generate some events. */
- int events_generated = 0;
struct gcpro gcpro1, gcpro2, gcpro3;
EMACS_SET_SECS (nexttime, -1);
{
if (NILP (vector[0]))
{
+ Lisp_Object tem;
+ int was_locked = single_kboard;
+ int count = specpdl_ptr - specpdl;
+
/* Mark the timer as triggered to prevent problems if the lisp
code fails to reschedule it right. */
vector[0] = Qt;
- /* Run the timer or queue a timer event. */
- if (1)
- {
- Lisp_Object tem, event;
- int was_locked = single_kboard;
- int count = specpdl_ptr - specpdl;
+ specbind (Qinhibit_quit, Qt);
- specbind (Qinhibit_quit, Qt);
+ call1 (Qtimer_event_handler, chosen_timer);
+ timers_run++;
- tem = get_keymap_1 (Vspecial_event_map, 0, 0);
- tem = get_keyelt (access_keymap (tem, Qtimer_event, 0, 0),
- 1);
- event = Fcons (Qtimer_event, Fcons (chosen_timer, Qnil));
- Fcommand_execute (tem, Qnil, Fvector (1, &event), Qt);
- timers_run++;
+ unbind_to (count, Qnil);
- unbind_to (count, Qnil);
+ /* Resume allowing input from any kboard, if that was true before. */
+ if (!was_locked)
+ any_kboard_state ();
- /* Resume allowing input from any kboard, if that was true before. */
- if (!was_locked)
- any_kboard_state ();
-
- /* Since we have handled the event,
- we don't need to tell the caller to wake up and do it. */
- }
-#if 0
- else
- {
- /* Generate a timer event so the caller will handle it. */
- struct input_event event;
-
- event.kind = timer_event;
- event.modifiers = 0;
- event.x = event.y = Qnil;
- event.timestamp = triggertime;
- /* Store the timer in the frame slot. */
- event.frame_or_window
- = Fcons (Fselected_frame (), chosen_timer);
- kbd_buffer_store_event (&event);
-
- last_timer_event = event;
-
- /* Tell caller to handle this event right away. */
- events_generated = 1;
- EMACS_SET_SECS (nexttime, 0);
- EMACS_SET_USECS (nexttime, 0);
-
- /* Don't queue more than one event at once.
- When Emacs is ready for another, it will
- queue the next one. */
- UNGCPRO;
- return nexttime;
- }
-#endif /* 0 */
+ /* Since we have handled the event,
+ we don't need to tell the caller to wake up and do it. */
}
}
else
return the amount of time to wait before it is ripe. */
{
UNGCPRO;
- /* But if we generated an event,
- tell the caller to handle it now. */
- if (events_generated)
- return nexttime;
return difference;
}
}
static Lisp_Object accent_key_syms;
static Lisp_Object func_key_syms;
static Lisp_Object mouse_syms;
+#ifdef WINDOWSNT
+static Lisp_Object mouse_wheel_syms;
+#endif
/* This is a list of keysym codes for special "accent" characters.
It parallels lispy_accent_keys. */
"oem_clear", /* VK_OEM_CLEAR 0xFE */
};
-#else
+#else /* not HAVE_NTGUI */
+
+#ifdef XK_kana_A
+static char *lispy_kana_keys[] =
+ {
+ /* X Keysym value */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x400 .. 0x40f */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x410 .. 0x41f */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x420 .. 0x42f */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x430 .. 0x43f */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x440 .. 0x44f */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x450 .. 0x45f */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x460 .. 0x46f */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,"overline",0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x480 .. 0x48f */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x490 .. 0x49f */
+ 0, "kana-fullstop", "kana-openingbracket", "kana-closingbracket",
+ "kana-comma", "kana-conjunctive", "kana-WO", "kana-a",
+ "kana-i", "kana-u", "kana-e", "kana-o",
+ "kana-ya", "kana-yu", "kana-yo", "kana-tsu",
+ "prolongedsound", "kana-A", "kana-I", "kana-U",
+ "kana-E", "kana-O", "kana-KA", "kana-KI",
+ "kana-KU", "kana-KE", "kana-KO", "kana-SA",
+ "kana-SHI", "kana-SU", "kana-SE", "kana-SO",
+ "kana-TA", "kana-CHI", "kana-TSU", "kana-TE",
+ "kana-TO", "kana-NA", "kana-NI", "kana-NU",
+ "kana-NE", "kana-NO", "kana-HA", "kana-HI",
+ "kana-FU", "kana-HE", "kana-HO", "kana-MA",
+ "kana-MI", "kana-MU", "kana-ME", "kana-MO",
+ "kana-YA", "kana-YU", "kana-YO", "kana-RA",
+ "kana-RI", "kana-RU", "kana-RE", "kana-RO",
+ "kana-WA", "kana-N", "voicedsound", "semivoicedsound",
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x4e0 .. 0x4ef */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x4f0 .. 0x4ff */
+ };
+#endif /* XK_kana_A */
#define FUNCTION_KEY_OFFSET 0xff00
0, 0, 0, 0, 0, 0, 0,
"escape",
0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff20...2f */
+ 0, "kanji", "muhenkan",
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff20...2f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff30...3f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff40...4f */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, /* 0xfff0 */
0, 0, 0, 0, 0, 0, 0, "delete"
- };
+ };
-#endif /* HAVE_NTGUI */
+/* ISO 9995 Function and Modifier Keys; the first byte is 0xFE. */
+#define ISO_FUNCTION_KEY_OFFSET 0xfe00
+
+static char *iso_lispy_function_keys[] =
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xfe00 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xfe08 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xfe10 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xfe18 */
+ "iso-lefttab", /* 0xfe20 */
+ "iso-move-line-up", "iso-move-line-down",
+ "iso-partial-line-up", "iso-partial-line-down",
+ "iso-partial-space-left", "iso-partial-space-right",
+ "iso-set-margin-left", "iso-set-margin-right", /* 0xffe27, 28 */
+ "iso-release-margin-left", "iso-release-margin-right",
+ "iso-release-both-margins",
+ "iso-fast-cursor-left", "iso-fast-cursor-right",
+ "iso-fast-cursor-up", "iso-fast-cursor-down",
+ "iso-continuous-underline", "iso-discontinuous-underline", /* 0xfe30, 31 */
+ "iso-emphasize", "iso-center-object", "iso-enter", /* ... 0xfe34 */
+ };
+
+#endif /* not HAVE_NTGUI */
static char *lispy_mouse_names[] =
{
"mouse-1", "mouse-2", "mouse-3", "mouse-4", "mouse-5"
};
+#ifdef WINDOWSNT
+/* mouse-wheel events are generated by the wheel on devices such as
+ the MS Intellimouse. The wheel sits in between the left and right
+ mouse buttons, and is typically used to scroll or zoom the window
+ underneath the pointer. mouse-wheel events specify the object on
+ which they operate, and a delta corresponding to the amount and
+ direction that the wheel is rotated. Clicking the mouse-wheel
+ generates a mouse-2 event. */
+static char *lispy_mouse_wheel_names[] =
+{
+ "mouse-wheel"
+};
+#endif /* WINDOWSNT */
+
/* Scroll bar parts. */
Lisp_Object Qabove_handle, Qhandle, Qbelow_handle;
Lisp_Object Qup, Qdown;
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;
(unsigned)-1);
}
- return modify_event_symbol (event->code - FUNCTION_KEY_OFFSET,
- event->modifiers,
- Qfunction_key, Qnil,
- lispy_function_keys, &func_key_syms,
- (sizeof (lispy_function_keys)
- / sizeof (lispy_function_keys[0])));
- break;
-
- /* Note that timer_event is currently never used. */
- case timer_event:
- return Fcons (Qtimer_event, Fcons (Fcdr (event->frame_or_window), Qnil));
+#ifdef XK_kana_A
+ if (event->code >= 0x400 && event->code < 0x500)
+ return modify_event_symbol (event->code - 0x400,
+ event->modifiers & ~shift_modifier,
+ Qfunction_key, Qnil,
+ lispy_kana_keys, &func_key_syms,
+ (sizeof (lispy_kana_keys)
+ / sizeof (lispy_kana_keys[0])));
+#endif /* XK_kana_A */
+
+#ifdef ISO_FUNCTION_KEY_OFFSET
+ if (event->code < FUNCTION_KEY_OFFSET
+ && event->code >= ISO_FUNCTION_KEY_OFFSET)
+ return modify_event_symbol (event->code - ISO_FUNCTION_KEY_OFFSET,
+ event->modifiers,
+ Qfunction_key, Qnil,
+ iso_lispy_function_keys, &func_key_syms,
+ (sizeof (iso_lispy_function_keys)
+ / sizeof (iso_lispy_function_keys[0])));
+ else
+#endif
+ return modify_event_symbol (event->code - FUNCTION_KEY_OFFSET,
+ event->modifiers,
+ Qfunction_key, Qnil,
+ lispy_function_keys, &func_key_syms,
+ (sizeof (lispy_function_keys)
+ / sizeof (lispy_function_keys[0])));
#ifdef HAVE_MOUSE
/* A mouse click. Figure out where it is, decide whether it's
Qnil));
}
}
-#endif
+ case mouse_wheel:
+ {
+ int part;
+ FRAME_PTR f = XFRAME (event->frame_or_window);
+ Lisp_Object window;
+ Lisp_Object posn;
+ Lisp_Object head, position;
+ int row, column;
+
+ /* Ignore mouse events that were made on frame that
+ have been deleted. */
+ if (! FRAME_LIVE_P (f))
+ return Qnil;
+ pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
+ &column, &row, NULL, 1);
+ window = window_from_coordinates (f, column, row, &part);
+
+ if (!WINDOWP (window))
+ {
+ window = event->frame_or_window;
+ posn = Qnil;
+ }
+ else
+ {
+ int pixcolumn, pixrow;
+ column -= XINT (XWINDOW (window)->left);
+ row -= XINT (XWINDOW (window)->top);
+ glyph_to_pixel_coords (f, column, row, &pixcolumn, &pixrow);
+ XSETINT (event->x, pixcolumn);
+ XSETINT (event->y, pixrow);
+
+ if (part == 1)
+ posn = Qmode_line;
+ else if (part == 2)
+ posn = Qvertical_line;
+ else
+ XSETINT (posn,
+ buffer_posn_from_coords (XWINDOW (window),
+ column, row));
+ }
+ {
+ Lisp_Object head, position;
+
+ position
+ = Fcons (window,
+ Fcons (posn,
+ Fcons (Fcons (event->x, event->y),
+ Fcons (make_number (event->timestamp),
+ Qnil))));
+
+ head = modify_event_symbol (0, event->modifiers,
+ Qmouse_wheel, Qnil,
+ lispy_mouse_wheel_names,
+ &mouse_wheel_syms, 1);
+ return Fcons (head,
+ Fcons (position,
+ Fcons (make_number (event->code),
+ Qnil)));
+ }
+ }
+#endif /* WINDOWSNT */
#endif /* HAVE_MOUSE */
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
#else
nread = read (input_fd, cbuf, n_to_read);
#endif
+ /* POSIX infers that processes which are not in the session leader's
+ process group won't get SIGHUP's at logout time. BSDI adheres to
+ this part standard and returns -1 from read(0) with errno==EIO
+ when the control tty is taken away.
+ Jeffrey Honig <jch@bsdi.com> says this is generally safe. */
+ if (nread == -1 && errno == EIO)
+ kill (0, SIGHUP);
#if defined (AIX) && (! defined (aix386) && defined (_BSD))
/* The kernel sometimes fails to deliver SIGHUP for ptys.
This looks incorrect, but it isn't, because _BSD causes
for (mapno = nmaps - 1; mapno >= 0; mapno--)
{
if (! NILP (maps[mapno]))
- def = get_keyelt (access_keymap (maps[mapno], Qmenu_bar, 1, 0));
+ def = get_keyelt (access_keymap (maps[mapno], Qmenu_bar, 1, 0), 0);
else
def = Qnil;
{
Lisp_Object tem;
+ record_menu_key (XCONS (value)->car);
+
/* If we got multiple events, unread all but
the first.
There is no way to prevent those unread events
they won't confuse things. */
for (tem = XCONS (value)->cdr; !NILP (tem);
tem = XCONS (tem)->cdr)
- if (SYMBOLP (XCONS (tem)->car)
- || INTEGERP (XCONS (tem)->car))
- XCONS (tem)->car
- = Fcons (XCONS (tem)->car, Qnil);
+ {
+ record_menu_key (XCONS (tem)->car);
+ if (SYMBOLP (XCONS (tem)->car)
+ || INTEGERP (XCONS (tem)->car))
+ XCONS (tem)->car
+ = Fcons (XCONS (tem)->car, Qnil);
+ }
/* If we got more than one event, put all but the first
onto this list to be read later.
{
Lisp_Object def;
def = get_keyelt (access_keymap (current[i],
- meta_prefix_char, 1, 0));
+ meta_prefix_char, 1, 0), 0);
/* Note that since we pass the resulting bindings through
get_keymap_1, non-prefix bindings for meta-prefix-char
else
map = current[i];
- defs[i] = get_keyelt (access_keymap (map, key, 1, 0));
+ defs[i] = get_keyelt (access_keymap (map, key, 1, 0), 0);
if (! NILP (defs[i]))
first_binding = i;
}
If the user switches frames in the midst of a key sequence, we put
off the switch-frame event until later; the next call to
- read_char will return it. */
+ read_char will return it.
+
+ If FIX_CURRENT_BUFFER is nonzero, we restore current_buffer
+ from the selected window's buffer. */
static int
read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
- can_return_switch_frame)
+ can_return_switch_frame, fix_current_buffer)
Lisp_Object *keybuf;
int bufsize;
Lisp_Object prompt;
int dont_downcase_last;
int can_return_switch_frame;
+ int fix_current_buffer;
{
int count = specpdl_ptr - specpdl;
/* Save the status of key translation before each step,
so that we can restore this after downcasing. */
Lisp_Object prev_fkey_map;
- Lisp_Object prev_fkey_start;
- Lisp_Object prev_fkey_end;
+ int prev_fkey_start;
+ int prev_fkey_end;
Lisp_Object prev_keytran_map;
- Lisp_Object prev_keytran_start;
- Lisp_Object prev_keytran_end;
+ int prev_keytran_start;
+ int prev_keytran_end;
int junk;
if (BUFFERP (key))
{
mock_input = t;
+ /* Reset the current buffer from the selected window
+ in case something changed the former and not the latter.
+ This is to be more consistent with the behavior
+ of the command_loop_1. */
+ if (fix_current_buffer)
+ if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
+ Fset_buffer (XWINDOW (selected_window)->buffer);
+
orig_local_map = get_local_map (PT, current_buffer);
goto replay_sequence;
}
fkey_next
= get_keymap_1
(get_keyelt
- (access_keymap (fkey_map, meta_prefix_char, 1, 0)),
+ (access_keymap (fkey_map, meta_prefix_char, 1, 0), 0),
0, 1);
XSETFASTINT (key, XFASTINT (key) & ~meta_modifier);
}
fkey_next = fkey_map;
fkey_next
- = get_keyelt (access_keymap (fkey_next, key, 1, 0));
+ = get_keyelt (access_keymap (fkey_next, key, 1, 0), 0);
#if 0 /* I didn't turn this on, because it might cause trouble
for the mapping of return into C-m and tab into C-i. */
keytran_next
= get_keymap_1
(get_keyelt
- (access_keymap (keytran_map, meta_prefix_char, 1, 0)),
+ (access_keymap (keytran_map, meta_prefix_char, 1, 0), 0),
0, 1);
XSETFASTINT (key, XFASTINT (key) & ~meta_modifier);
}
keytran_next = keytran_map;
keytran_next
- = get_keyelt (access_keymap (keytran_next, key, 1, 0));
+ = get_keyelt (access_keymap (keytran_next, key, 1, 0), 0);
/* If the key translation map gives a function, not an
array, then call the function with no args and use
i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])),
prompt, ! NILP (dont_downcase_last),
- ! NILP (can_return_switch_frame));
+ ! NILP (can_return_switch_frame), 0);
if (i == -1)
{
history list. */
function = Fcompleting_read (build_string (buf),
Vobarray, Qcommandp,
- Qt, Qnil, Qextended_command_history);
+ Qt, Qnil, Qextended_command_history, Qnil,
+ Qnil);
if (STRINGP (function) && XSTRING (function)->size == 0)
error ("No command name given");
/* But first wait, and skip the message if there is input. */
if (!NILP (Fsit_for ((NUMBERP (Vsuggest_key_bindings)
? Vsuggest_key_bindings : make_number (2)),
- Qnil, Qnil)))
+ Qnil, Qnil))
+ && ! CONSP (Vunread_command_events))
{
Lisp_Object binding;
char *newmessage;
cancel_echoing ();
- if (!NILP (Vquit_flag) && FRAME_TERMCAP_P (selected_frame))
+ if (!NILP (Vquit_flag)
+ && (FRAME_TERMCAP_P (selected_frame) || FRAME_MSDOS_P (selected_frame)))
{
+ /* If SIGINT isn't blocked, don't let us be interrupted by
+ another SIGINT, it might be harmful due to non-reentrancy
+ in I/O functions. */
+ sigblock (sigmask (SIGINT));
+
fflush (stdout);
reset_sys_modes ();
- sigfree ();
+
#ifdef SIGTSTP /* Support possible in later USG versions */
/*
* On systems which can suspend the current process and return to the original
#endif /* not MSDOS */
fflush (stdout);
init_sys_modes ();
+ sigfree ();
}
else
{
stop_polling ();
#endif
-#ifndef MSDOS
+#ifndef DOS_NT
/* this causes startup screen to be restored and messes with the mouse */
reset_sys_modes ();
#endif
/* Don't let this value be out of range. */
quit_char = XINT (quit) & (meta_key ? 0377 : 0177);
-#ifndef MSDOS
+#ifndef DOS_NT
init_sys_modes ();
#endif
syms_of_keyboard ()
{
+ Qtimer_event_handler = intern ("timer-event-handler");
+ staticpro (&Qtimer_event_handler);
+
Qdisabled_command_hook = intern ("disabled-command-hook");
staticpro (&Qdisabled_command_hook);
staticpro (&Qfunction_key);
Qmouse_click = intern ("mouse-click");
staticpro (&Qmouse_click);
- Qtimer_event = intern ("timer-event");
- staticpro (&Qtimer_event);
+#ifdef WINDOWSNT
+ Qmouse_wheel = intern ("mouse-wheel");
+ staticpro (&Qmouse_wheel);
+#endif
Qmenu_enable = intern ("menu-enable");
staticpro (&Qmenu_enable);
mouse_syms = Qnil;
staticpro (&mouse_syms);
+#ifdef WINDOWSNT
+ mouse_wheel_syms = Qnil;
+ staticpro (&mouse_wheel_syms);
+#endif
+
unread_switch_frame = Qnil;
staticpro (&unread_switch_frame);
inhibit_local_menu_bar_menus = 0;
DEFVAR_INT ("num-input-keys", &num_input_keys,
- "Number of complete key sequences read from the keyboard so far.\n\
+ "Number of complete key sequences read as input so far.\n\
This includes key sequences read from keyboard macros.\n\
The number is effectively the number of interactive command invocations.");
num_input_keys = 0;
+ DEFVAR_INT ("num-nonmacro-input-events", &num_nonmacro_input_events,
+ "Number of input events read from the keyboard so far.\n\
+This does not include events generated by keyboard macros.");
+ num_nonmacro_input_events = 0;
+
DEFVAR_LISP ("last-event-frame", &Vlast_event_frame,
"The frame in which the most recently read event occurred.\n\
If the last event came from a keyboard macro, this is set to `macro'.");
Vlast_event_frame = Qnil;
+ /* This variable is set up in sysdep.c. */
+ DEFVAR_LISP ("tty-erase-char", &Vtty_erase_char,
+ "The ERASE character as set by the user with stty.");
+
DEFVAR_LISP ("help-char", &Vhelp_char,
"Character to recognize as meaning Help.\n\
When it is read, do `(eval help-form)', and display result if it's a string.\n\
This is measured in microseconds.");
post_command_idle_delay = 100000;
+#if 0
+ DEFVAR_LISP ("echo-area-clear-hook", ...,
+ "Normal hook run when clearing the echo area.");
+#endif
+ Qecho_area_clear_hook = intern ("echo-area-clear-hook");
+ XSYMBOL (Qecho_area_clear_hook)->value = Qnil;
+
DEFVAR_LISP ("lucid-menu-bar-dirty-flag", &Vlucid_menu_bar_dirty_flag,
"t means menu bar, specified Lucid style, needs to be recomputed.");
Vlucid_menu_bar_dirty_flag = Qnil;
DEFVAR_KBOARD ("overriding-terminal-local-map",
Voverriding_terminal_local_map,
- "Keymap that overrides all other local keymaps.\n\
+ "Per-terminal keymap that overrides all other local keymaps.\n\
If this variable is non-nil, it is used as a keymap instead of the\n\
-buffer's local map, and the minor mode keymaps and text property keymaps.");
+buffer's local map, and the minor mode keymaps and text property keymaps.\n\
+This variable is intended to let commands such as `universal-argumemnt'\n\
+set up a different keymap for reading the next command.");
DEFVAR_LISP ("overriding-local-map", &Voverriding_local_map,
"Keymap that overrides all other local keymaps.\n\