/* Keyboard and mouse input; editor command loop.
- Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1985,86,87,88,89,93,94 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <setjmp.h>
#include <errno.h>
+#ifdef MSDOS
+#include "msdos.h"
+#include <time.h>
+#else /* not MSDOS */
#ifndef VMS
#include <sys/ioctl.h>
#endif
+#endif /* not MSDOS */
#include "syssignal.h"
#include "systty.h"
/* True while displaying for echoing. Delays C-g throwing. */
static int echoing;
-/* Nonzero means C-G should cause immediate error-signal. */
+/* Nonzero means C-g should cause immediate error-signal. */
int immediate_quit;
/* Character to recognize as the help char. */
extern Lisp_Object current_global_map;
extern int minibuf_level;
+/* If non-nil, this is a map that overrides all other local maps. */
+Lisp_Object Voverriding_local_map;
+
/* Current depth in recursive edits. */
int command_loop_level;
Lisp_Object last_input_char;
/* If not Qnil, a list of objects to be read as subsequent command input. */
-Lisp_Object unread_command_events;
+Lisp_Object Vunread_command_events;
/* If not -1, an event to be read as subsequent command input. */
int unread_command_char;
instead of the actual command. */
Lisp_Object this_command;
+/* The value of point when the last command was executed. */
+int last_point_position;
+
+/* The buffer that was current when the last command was started. */
+Lisp_Object last_point_position_buffer;
+
#ifdef MULTI_FRAME
/* The frame in which the last input event occurred, or Qmacro if the
last event came from a macro. We use this to determine when to
like Fselect_frame, to make sure that a switch-frame event is
generated by the next character. */
Lisp_Object internal_last_event_frame;
+#endif
/* A user-visible version of the above, intended to allow users to
figure out where the last event came from, if the event doesn't
carry that information itself (i.e. if it was a character). */
Lisp_Object Vlast_event_frame;
-#endif
/* The timestamp of the last input event we received from the X server.
X Windows wants this for selection ownership. */
/* Hooks to run before and after each command. */
Lisp_Object Qpre_command_hook, Qpost_command_hook;
Lisp_Object Vpre_command_hook, Vpost_command_hook;
+Lisp_Object Qcommand_hook_internal, Vcommand_hook_internal;
/* File in which we write all commands we read. */
FILE *dribble;
Lisp_Object Fthis_command_keys ();
Lisp_Object Qextended_command_history;
+Lisp_Object Qpolling_period;
+
/* Address (if not 0) of EMACS_TIME to zero out if a SIGIO interrupt
happens. */
EMACS_TIME *input_available_clear_time;
static int read_avail_input ();
static void get_input_pending ();
static int readable_events ();
-static Lisp_Object read_char_menu_prompt ();
+static Lisp_Object read_char_x_menu_prompt ();
+static Lisp_Object read_char_minibuf_menu_prompt ();
static Lisp_Object make_lispy_event ();
static Lisp_Object make_lispy_movement ();
static Lisp_Object modify_event_symbol ();
/* Where to append more text to echobuf if we want to. */
static char *echoptr;
+/* Nonzero means don't try to suspend even if the operating system seems
+ to support it. */
+static int cannot_suspend;
+
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
immediate_echo = 1;
for (i = 0; i < this_command_key_count; i++)
- echo_char (XVECTOR (this_command_keys)->contents[i]);
+ {
+ Lisp_Object c;
+ c = XVECTOR (this_command_keys)->contents[i];
+ if (! (EVENT_HAS_PARAMETERS (c)
+ && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
+ echo_char (c);
+ }
echo_dash ();
}
{
echobuf[len] = '\0';
echoptr = echobuf + len;
+ truncate_echo_area (len);
}
\f
if (this_command_key_count >= size)
{
- Lisp_Object new_keys = Fmake_vector (make_number (size * 2), Qnil);
+ Lisp_Object new_keys;
+ new_keys = Fmake_vector (make_number (size * 2), Qnil);
bcopy (XVECTOR (this_command_keys)->contents,
XVECTOR (new_keys)->contents,
size * sizeof (Lisp_Object));
}
/* When an auto-save happens, record the "time", and don't do again soon. */
+
record_auto_save ()
{
last_auto_save = num_nonmacro_input_chars;
}
+
+/* Make an auto save happen as soon as possible at command level. */
+
+force_auto_save_soon ()
+{
+ last_auto_save = - auto_save_interval - 1;
+
+ record_asynch_buffer_change ();
+}
\f
DEFUN ("recursive-edit", Frecursive_edit, Srecursive_edit, 0, 0, "",
"Invoke the editor command loop recursively.\n\
Lisp_Object Fcommand_execute ();
static int read_key_sequence ();
+static void safe_run_hooks ();
Lisp_Object
command_loop_1 ()
waiting_for_input = 0;
cancel_echoing ();
- /* Don't clear out last_command at the beginning of a macro. */
- if (XTYPE (Vexecuting_macro) != Lisp_String)
- last_command = Qt;
-
nonundocount = 0;
no_redisplay = 0;
this_command_key_count = 0;
/* Make sure this hook runs after commands that get errors and
throw to top level. */
- if (!NILP (Vpost_command_hook))
- call1 (Vrun_hooks, Qpost_command_hook);
+ if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
+ safe_run_hooks (&Vpost_command_hook);
+
+ /* Do this after running Vpost_command_hook, for consistency. */
+ last_command = this_command;
while (1)
{
if (!NILP (Vquit_flag))
{
Vquit_flag = Qnil;
- unread_command_events = Fcons (make_number (quit_char), Qnil);
+ Vunread_command_events = Fcons (make_number (quit_char), Qnil);
}
}
&& !NILP (Ffboundp (Qrecompute_lucid_menubar)))
call0 (Qrecompute_lucid_menubar);
-#if 0 /* This is done in xdisp.c now. */
-#ifdef MULTI_FRAME
- for (tem = Vframe_list; CONSP (tem); tem = XCONS (tem)->cdr)
- {
- struct frame *f = XFRAME (XCONS (tem)->car);
- struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
-
- /* If the user has switched buffers or windows, we need to
- recompute to reflect the new bindings. But we'll
- recompute when update_mode_lines is set too; that means
- that people can use force-mode-line-update to request
- that the menu bar be recomputed. The adverse effect on
- the rest of the redisplay algorithm is about the same as
- windows_or_buffers_changed anyway. */
- if (windows_or_buffers_changed
- || update_mode_lines
- || (XFASTINT (w->last_modified) < MODIFF
- && (XFASTINT (w->last_modified)
- <= XBUFFER (w->buffer)->save_modified)))
- {
- struct buffer *prev = current_buffer;
- current_buffer = XBUFFER (w->buffer);
- FRAME_MENU_BAR_ITEMS (f) = menu_bar_items ();
- current_buffer = prev;
- }
- }
-#endif /* MULTI_FRAME */
-#endif /* 0 */
-
/* Read next key sequence; i gets its length. */
i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])), Qnil);
}
/* Do redisplay processing after this command except in special
- cases identified below that set no_redisplay to 1. */
+ cases identified below that set no_redisplay to 1.
+ (actually, there's currently no way to prevent the redisplay,
+ and no_redisplay is ignored.
+ Perhaps someday we will really implement it. */
no_redisplay = 0;
prev_buffer = current_buffer;
prev_modiff = MODIFF;
+ last_point_position = PT;
+ XSET (last_point_position_buffer, Lisp_Buffer, prev_buffer);
/* Execute the command. */
this_command = cmd;
- if (!NILP (Vpre_command_hook))
- call1 (Vrun_hooks, Qpre_command_hook);
+ if (!NILP (Vpre_command_hook) && !NILP (Vrun_hooks))
+ safe_run_hooks (&Vpre_command_hook);
if (NILP (this_command))
{
{
/* Recognize some common commands in common situations and
do them directly. */
- if (EQ (this_command, Qforward_char) && point < ZV)
+ if (EQ (this_command, Qforward_char) && PT < ZV)
{
struct Lisp_Vector *dp
= window_display_table (XWINDOW (selected_window));
- lose = FETCH_CHAR (point);
- SET_PT (point + 1);
+ lose = FETCH_CHAR (PT);
+ SET_PT (PT + 1);
if ((dp
- ? (XTYPE (DISP_CHAR_VECTOR (dp, lose)) != Lisp_Vector
+ ? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
&& XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1)
: (lose >= 0x20 && lose < 0x7f))
&& (XFASTINT (XWINDOW (selected_window)->last_modified)
>= MODIFF)
&& (XFASTINT (XWINDOW (selected_window)->last_point)
- == point - 1)
+ == PT - 1)
&& !windows_or_buffers_changed
&& EQ (current_buffer->selective_display, Qnil)
&& !detect_input_pending ()
no_redisplay = direct_output_forward_char (1);
goto directly_done;
}
- else if (EQ (this_command, Qbackward_char) && point > BEGV)
+ else if (EQ (this_command, Qbackward_char) && PT > BEGV)
{
struct Lisp_Vector *dp
= window_display_table (XWINDOW (selected_window));
- SET_PT (point - 1);
- lose = FETCH_CHAR (point);
+ SET_PT (PT - 1);
+ lose = FETCH_CHAR (PT);
if ((dp
- ? (XTYPE (DISP_CHAR_VECTOR (dp, lose)) != Lisp_Vector
+ ? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
&& XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1)
: (lose >= 0x20 && lose < 0x7f))
&& (XFASTINT (XWINDOW (selected_window)->last_modified)
>= MODIFF)
&& (XFASTINT (XWINDOW (selected_window)->last_point)
- == point + 1)
+ == PT + 1)
&& !windows_or_buffers_changed
&& EQ (current_buffer->selective_display, Qnil)
&& !detect_input_pending ()
}
lose = (XFASTINT (XWINDOW (selected_window)->last_modified)
< MODIFF)
- || (XFASTINT (XWINDOW (selected_window)->last_point)
- != point)
+ || (XFASTINT (XWINDOW (selected_window)->last_point) != PT)
|| MODIFF <= current_buffer->save_modified
|| windows_or_buffers_changed
|| !EQ (current_buffer->selective_display, Qnil)
nonundocount = 0;
}
if (!lose &&
- (point == ZV || FETCH_CHAR (point) == '\n'))
+ (PT == ZV || FETCH_CHAR (PT) == '\n'))
{
struct Lisp_Vector *dp
= window_display_table (XWINDOW (selected_window));
if (dp)
{
- Lisp_Object obj = DISP_CHAR_VECTOR (dp, lose);
+ Lisp_Object obj;
+ obj = DISP_CHAR_VECTOR (dp, lose);
if (XTYPE (obj) == Lisp_Vector
&& XVECTOR (obj)->size == 1
&& (XTYPE (obj = XVECTOR (obj)->contents[0])
}
directly_done: ;
- if (!NILP (Vpost_command_hook))
- call1 (Vrun_hooks, Qpost_command_hook);
+ if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
+ safe_run_hooks (&Vpost_command_hook);
/* If there is a prefix argument,
1) We don't want last_command to be ``universal-argument''
this_command_key_count = 0;
}
- if (!NILP (current_buffer->mark_active))
+ if (!NILP (current_buffer->mark_active) && !NILP (Vrun_hooks))
{
if (!NILP (Vdeactivate_mark) && !NILP (Vtransient_mark_mode))
{
}
}
}
+
+/* If we get an error while running the hook, cause the hook variable
+ to be nil. Also inhibit quits, so that C-g won't cause the hook
+ to mysteriously evaporate. */
+static void
+safe_run_hooks (hook)
+ Lisp_Object *hook;
+{
+ int count = specpdl_ptr - specpdl;
+ specbind (Qinhibit_quit, Qt);
+
+ Vcommand_hook_internal = *hook;
+ *hook = Qnil;
+ call1 (Vrun_hooks, Qcommand_hook_internal);
+ *hook = Vcommand_hook_internal;
+
+ unbind_to (count, Qnil);
+}
\f
/* Number of seconds between polling for input. */
int polling_period;
poll_suppress_count = count;
#endif
}
+
+/* Bind polling_period to a value at least N.
+ But don't decrease it. */
+
+bind_polling_period (n)
+ int n;
+{
+#ifdef POLL_FOR_INPUT
+ int new = polling_period;
+
+ if (n > new)
+ new = n;
+
+ stop_polling ();
+ specbind (Qpolling_period, make_number (new));
+ /* Start a new alarm with the new period. */
+ start_polling ();
+#endif
+}
\f
/* Applying the control modifier to CHARACTER. */
int
int count;
jmp_buf save_jump;
- if (CONSP (unread_command_events))
+ if (CONSP (Vunread_command_events))
{
- c = XCONS (unread_command_events)->car;
- unread_command_events = XCONS (unread_command_events)->cdr;
+ c = XCONS (Vunread_command_events)->car;
+ Vunread_command_events = XCONS (Vunread_command_events)->cdr;
if (this_command_key_count == 0)
goto reread_first;
goto reread_first;
}
+ /* Don't bother updating menu bars while doing mouse tracking.
+ We get events very rapidly then, and the menu bar won't be changing.
+ We do update the menu bar once on entry to Ftrack_mouse. */
+ if (commandflag > 0 && !input_pending && !detect_input_pending ())
+ prepare_menu_bars ();
+
/* Save outer setjmp data, in case called recursively. */
save_getcjmp (save_jump);
/* If already echoing, continue. */
echo_dash ();
+ /* Try reading a character via menu prompting in the minibuf.
+ Try this before the sit-for, because the sit-for
+ would do the wrong thing if we are supposed to do
+ menu prompting. If EVENT_HAS_PARAMETERS then we are reading
+ after a mouse event so don't try a minibuf menu. */
+ c = Qnil;
+ if (nmaps > 0 && INTERACTIVE
+ && !NILP (prev_event) && ! EVENT_HAS_PARAMETERS (prev_event)
+ /* Don't bring up a menu if we already have another event. */
+ && NILP (Vunread_command_events)
+ && unread_command_char < 0
+ && !detect_input_pending ())
+ {
+ c = read_char_minibuf_menu_prompt (commandflag, nmaps, maps);
+ if (! NILP (c))
+ return c;
+ }
+
/* If in middle of key sequence and minibuffer not active,
start echoing if enough time elapses. */
if (minibuf_level == 0 && !immediate_echo && this_command_key_count > 0
restore_getcjmp (temp);
}
- /* Try reading a character via menu prompting.
- Try this before the sit-for, because the sit-for
- would do the wrong thing if we are supposed to do
- menu prompting. */
- c = Qnil;
- if (INTERACTIVE && !NILP (prev_event))
- c = read_char_menu_prompt (nmaps, maps, prev_event, used_mouse_menu);
+ /* Try reading using an X menu.
+ This is never confused with reading using the minibuf
+ because the recursive call of read_char in read_char_minibuf_menu_prompt
+ does not pass on any keymaps. */
+ if (nmaps > 0 && INTERACTIVE
+ && !NILP (prev_event) && EVENT_HAS_PARAMETERS (prev_event)
+ /* 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);
/* Slow down auto saves logarithmically in size of current buffer,
and garbage collect while we're at it. */
&& consing_since_gc > gc_cons_threshold / 2)
{
Fgarbage_collect ();
+ /* prepare_menu_bars isn't safe here, but it should
+ also be unnecessary. */
redisplay ();
}
}
start_polling ();
- echo_area_glyphs = 0;
+ /* Don't wipe the echo area for a trivial event. */
+ if (XTYPE (c) != Lisp_Buffer)
+ echo_area_glyphs = 0;
/* Handle things that only apply to characters. */
if (XTYPE (c) == Lisp_Int)
putc (XINT (c), dribble);
else
{
- Lisp_Object dribblee = c;
+ Lisp_Object dribblee;
/* If it's a structured event, take the event header. */
- dribblee = EVENT_HEAD (dribblee);
+ dribblee = EVENT_HEAD (c);
if (XTYPE (dribblee) == Lisp_Symbol)
{
from_macro:
reread_first:
- /* Record this character as part of the current key.
- Don't record mouse motion; it should never matter. */
+ /* Don't echo mouse motion events. */
if (! (EVENT_HAS_PARAMETERS (c)
&& EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
- {
- echo_char (c);
- add_command_key (c);
- }
+ echo_char (c);
+
+ /* Record this character as part of the current key. */
+ add_command_key (c);
/* Re-reading in the middle of a command */
reread:
internal_with_output_to_temp_buffer ("*Help*", print_help, tem0);
cancel_echoing ();
- c = read_char (0, 0, 0, Qnil, 0);
+ do
+ c = read_char (0, 0, 0, Qnil, 0);
+ while (XTYPE (c) == Lisp_Buffer);
/* Remove the help from the frame */
unbind_to (count, Qnil);
+ prepare_menu_bars ();
redisplay ();
if (EQ (c, make_number (040)))
{
cancel_echoing ();
- c = read_char (0, 0, 0, Qnil, 0);
+ do
+ c = read_char (0, 0, 0, Qnil, 0);
+ while (XTYPE (c) == Lisp_Buffer);
}
}
redisplay. */
if (!readable_events ())
{
+ prepare_menu_bars ();
redisplay_preserve_echo_area ();
get_input_pending (&input_pending);
}
XSET (val, Lisp_Int, do_mouse_tracking);
record_unwind_protect (tracking_off, val);
+ if (!input_pending && !detect_input_pending ())
+ prepare_menu_bars ();
+
do_mouse_tracking = 1;
val = Fprogn (args);
if (event->kind == ascii_keystroke)
{
- register int c = XFASTINT (event->code) & 0377;
+ register int c = event->code & 0377;
if (event->modifiers & ctrl_modifier)
c = make_ctrl_char (c);
get returned to Emacs as an event, the next event read
will set Vlast_event_frame again, so this is safe to do. */
{
- Lisp_Object focus
- = FRAME_FOCUS_FRAME (XFRAME (event->frame_or_window));
+ Lisp_Object focus;
+ focus = FRAME_FOCUS_FRAME (XFRAME (event->frame_or_window));
if (NILP (focus))
internal_last_event_frame = event->frame_or_window;
else
wait_reading_process_input (0, 0, minus_one, 1);
if (!interrupt_input && EVENT_QUEUES_EMPTY)
- {
- read_avail_input (0);
- }
+ /* Pass 1 for EXPECT since we just waited to have input. */
+ read_avail_input (1);
}
#endif /* not VMS */
}
abort ();
#endif
}
+#ifdef HAVE_X11
+ else if (event->kind == delete_window_event)
+ {
+ Lisp_Object tail, frame;
+ struct frame *f;
+
+ /* If the user destroys the only frame, Emacs should exit.
+ Count visible frames and iconified frames. */
+ for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ frame = XCONS (tail)->car;
+ if (XTYPE (frame) != Lisp_Frame || EQ (frame, event->frame_or_window))
+ continue;
+ f = XFRAME (frame);
+ if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
+ break;
+ }
+
+ if (! CONSP (tail))
+ Fkill_emacs (Qnil);
+
+ Fdelete_frame (event->frame_or_window, Qt);
+ kbd_fetch_ptr = event + 1;
+ }
+#endif
+ else if (event->kind == menu_bar_event)
+ {
+ /* The event value is in the frame_or_window slot. */
+ obj = event->frame_or_window;
+ kbd_fetch_ptr = event + 1;
+ }
+ else if (event->kind == buffer_switch_event)
+ {
+ /* The value doesn't matter here; only the type is tested. */
+ XSET (obj, Lisp_Buffer, current_buffer);
+ kbd_fetch_ptr = event + 1;
+ }
/* Just discard these, by returning nil.
(They shouldn't be found in the buffer,
but on some machines it appears they do show up.) */
else
{
#ifdef MULTI_FRAME
- Lisp_Object frame = event->frame_or_window;
+ Lisp_Object frame;
Lisp_Object focus;
+ frame = event->frame_or_window;
if (XTYPE (frame) == Lisp_Window)
frame = WINDOW_FRAME (XWINDOW (frame));
frames. */
if (f)
{
- Lisp_Object frame = FRAME_FOCUS_FRAME (f);
+ Lisp_Object frame;
+ frame = FRAME_FOCUS_FRAME (f);
if (NILP (frame))
XSET (frame, Lisp_Frame, f);
obj = make_lispy_switch_frame (frame);
internal_last_event_frame = frame;
}
-#endif
/* If we didn't decide to make a switch-frame event, go ahead and
return a mouse-motion event. */
if (NILP (obj))
obj = make_lispy_movement (f, bar_window, part, x, y, time);
- }
+#endif
+ }
else
/* We were promised by the above while loop that there was
something for us to read! */
}
\f
/* Caches for modify_event_symbol. */
+static Lisp_Object accent_key_syms;
+static Lisp_Object system_key_syms;
static Lisp_Object func_key_syms;
static Lisp_Object mouse_syms;
+Lisp_Object Vsystem_key_alist;
+
+/* This is a list of keysym codes for special "accent" characters.
+ It parallels lispy_accent_keys. */
+
+static int lispy_accent_codes[] =
+{
+#ifdef XK_dead_circumflex
+ XK_dead_circumflex,
+#else
+ 0,
+#endif
+#ifdef XK_dead_grave
+ XK_dead_grave,
+#else
+ 0,
+#endif
+#ifdef XK_dead_tilde
+ XK_dead_tilde,
+#else
+ 0,
+#endif
+#ifdef XK_dead_diaeresis
+ XK_dead_diaeresis,
+#else
+ 0,
+#endif
+#ifdef XK_dead_macron
+ XK_dead_macron,
+#else
+ 0,
+#endif
+#ifdef XK_dead_degree
+ XK_dead_degree,
+#else
+ 0,
+#endif
+#ifdef XK_dead_acute
+ XK_dead_acute,
+#else
+ 0,
+#endif
+#ifdef XK_dead_cedilla
+ XK_dead_cedilla,
+#else
+ 0,
+#endif
+#ifdef XK_dead_breve
+ XK_dead_breve,
+#else
+ 0,
+#endif
+#ifdef XK_dead_ogonek
+ XK_dead_ogonek,
+#else
+ 0,
+#endif
+#ifdef XK_dead_caron
+ XK_dead_caron,
+#else
+ 0,
+#endif
+#ifdef XK_dead_doubleacute
+ XK_dead_doubleacute,
+#else
+ 0,
+#endif
+#ifdef XK_dead_abovedot
+ XK_dead_abovedot,
+#else
+ 0,
+#endif
+};
+
+/* This is a list of Lisp names for special "accent" characters.
+ It parallels lispy_accent_codes. */
+
+static char *lispy_accent_keys[] =
+{
+ "dead-circumflex",
+ "dead-grave",
+ "dead-tilde",
+ "dead-diaeresis",
+ "dead-macron",
+ "dead-degree",
+ "dead-acute",
+ "dead-cedilla",
+ "dead-breve",
+ "dead-ogonek",
+ "dead-caron",
+ "dead-doubleacute",
+ "dead-abovedot",
+};
+
/* You'll notice that this table is arranged to be conveniently
indexed by X Windows keysym values. */
static char *lispy_function_keys[] =
{
/* X Keysym value */
- "remove", 0, 0, 0, 0, 0, 0, 0, /* 0xff00 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff00 */
"backspace",
"tab",
"linefeed",
"help",
"break", /* 0xff6b */
- /* Here are some keys found mostly on HP keyboards. The X event
- handling code will strip bit 29, which flags vendor-specific
- keysyms. */
- "reset", /* 0x1000ff6c */
- "system",
- "user",
- "clearline",
- "insertline",
- "deleteline",
- "insertchar",
- "deletechar",
- "backtab",
- "kp-backtab", /* 0x1000ff75 */
+ 0, 0, 0, 0, 0, 0, 0, 0, "backtab", 0,
0, /* 0xff76 */
0, 0, 0, 0, 0, 0, 0, 0, "kp-numlock", /* 0xff7f */
"kp-space", /* 0xff80 */ /* IsKeypadKey */
"kp-f2",
"kp-f3",
"kp-f4",
- 0, /* 0xff95 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ "kp-home", /* 0xff95 */
+ "kp-left",
+ "kp-up",
+ "kp-right",
+ "kp-down",
+ "kp-prior", /* kp-page-up */
+ "kp-next", /* kp-page-down */
+ "kp-end",
+ "kp-begin",
+ "kp-insert",
+ "kp-delete",
+ 0, /* 0xffa0 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
"kp-multiply", /* 0xffaa */
"kp-add",
"kp-separator",
int double_click_count;
+#ifdef USE_X_TOOLKIT
+extern Lisp_Object map_event_to_object ();
+#endif /* USE_X_TOOLKIT */
+
/* Given a struct input_event, build the lisp event which represents
it. If EVENT is 0, build a mouse movement event from the mouse
movement buffer, which should have a movement event in it.
make_lispy_event (event)
struct input_event *event;
{
+ int i;
+
#ifdef SWITCH_ENUM_BUG
switch ((int) event->kind)
#else
/* A simple keystroke. */
case ascii_keystroke:
{
- int c = XFASTINT (event->code) & 0377;
+ int c = event->code & 0377;
/* Turn ASCII characters into control characters
when proper. */
if (event->modifiers & ctrl_modifier)
tacked onto it. */
case non_ascii_keystroke:
button_down_time = 0;
- return modify_event_symbol (XFASTINT (event->code), event->modifiers,
- Qfunction_key,
+
+ for (i = 0; i < sizeof (lispy_accent_codes) / sizeof (int); i++)
+ if (event->code == lispy_accent_codes[i])
+ return modify_event_symbol (i,
+ event->modifiers,
+ Qfunction_key, Qnil,
+ lispy_accent_keys, &accent_key_syms,
+ (sizeof (lispy_accent_keys)
+ / sizeof (lispy_accent_keys[0])));
+
+ /* Handle system-specific keysyms. */
+ if (event->code & (1 << 28))
+ {
+ /* We need to use an alist rather than a vector as the cache
+ since we can't make a vector long enuf. */
+ if (NILP (system_key_syms))
+ system_key_syms = Fcons (Qnil, Qnil);
+ return modify_event_symbol (event->code & 0xffffff,
+ event->modifiers,
+ Qfunction_key, Vsystem_key_alist,
+ 0, &system_key_syms, 0xffffff);
+ }
+
+ return modify_event_symbol (event->code - 0xff00,
+ event->modifiers,
+ Qfunction_key, Qnil,
lispy_function_keys, &func_key_syms,
(sizeof (lispy_function_keys)
/ sizeof (lispy_function_keys[0])));
break;
+#if defined(MULTI_FRAME) || defined(HAVE_MOUSE)
/* A mouse click. Figure out where it is, decide whether it's
a press, click or drag, and build the appropriate structure. */
case mouse_click:
case scroll_bar_click:
{
- int button = XFASTINT (event->code);
+ int button = event->code;
int is_double;
Lisp_Object position;
Lisp_Object *start_pos_ptr;
{
int part;
FRAME_PTR f = XFRAME (event->frame_or_window);
- Lisp_Object window
- = window_from_coordinates (f, XINT (event->x), XINT (event->y),
- &part);
+ Lisp_Object window;
Lisp_Object posn;
+ int row, column;
- if (XINT (event->y) < FRAME_MENU_BAR_LINES (f))
+ /* 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, 0, 0);
+
+#ifdef USE_X_TOOLKIT
+ if (FRAME_EXTERNAL_MENU_BAR (f) && XINT (event->y) == -1)
+#else
+ if (row < FRAME_MENU_BAR_LINES (f))
+#endif
{
+ Lisp_Object items, item;
+
+#ifdef USE_X_TOOLKIT
+ /* The click happened in the menubar.
+ Look for the menu item selected. */
+ item = map_event_to_object (event, f);
+
+ XFASTINT (event->y) = 1;
+#else /* not USE_X_TOOLKIT */
int hpos;
- Lisp_Object items;
+ int i;
+
+ item = Qnil;
items = FRAME_MENU_BAR_ITEMS (f);
- for (; CONSP (items); items = XCONS (items)->cdr)
+ for (i = 0; i < XVECTOR (items)->size; i += 3)
{
Lisp_Object pos, string;
- pos = Fcdr (Fcdr (Fcar (items)));
- string = Fcar (Fcdr (Fcar (items)));
- if (XINT (event->x) >= XINT (pos)
- && XINT (event->x) < XINT (pos) + XSTRING (string)->size)
+ string = XVECTOR (items)->contents[i + 1];
+ pos = XVECTOR (items)->contents[i + 2];
+ if (NILP (string))
break;
+ if (column >= XINT (pos)
+ && column < XINT (pos) + XSTRING (string)->size)
+ {
+ item = XVECTOR (items)->contents[i];
+ break;
+ }
}
+#endif /* not USE_X_TOOLKIT */
+
position
= Fcons (event->frame_or_window,
Fcons (Qmenu_bar,
Fcons (make_number (event->timestamp),
Qnil))));
- if (CONSP (items))
- return Fcons (Fcar (Fcar (items)),
- Fcons (position, Qnil));
- else
- return Fcons (Qnil, Fcons (position, Qnil));
+ return Fcons (item, Fcons (position, Qnil));
}
- else if (XTYPE (window) != Lisp_Window)
+
+ window = window_from_coordinates (f, column, row, &part);
+
+ if (XTYPE (window) != Lisp_Window)
posn = Qnil;
else
{
- XSETINT (event->x,
- (XINT (event->x) - XINT (XWINDOW (window)->left)));
- XSETINT (event->y,
- (XINT (event->y) - XINT (XWINDOW (window)->top)));
+ 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
XSET (posn, Lisp_Int,
buffer_posn_from_coords (XWINDOW (window),
- XINT (event->x),
- XINT (event->y)));
+ column, row));
}
position
}
else
{
- Lisp_Object window = event->frame_or_window;
- Lisp_Object portion_whole = Fcons (event->x, event->y);
- Lisp_Object part = *scroll_bar_parts[(int) event->part];
+ 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)))));
+ Fcons (part, Qnil)))));
}
start_pos_ptr = &XVECTOR (button_down_location)->contents[button];
{
/* The third element of every position should be the (x,y)
pair. */
- Lisp_Object down = Fnth (make_number (2), start_pos);
+ Lisp_Object down;
+ down = Fnth (make_number (2), start_pos);
if (EQ (event->x, XCONS (down)->car)
&& EQ (event->y, XCONS (down)->cdr))
{
{
/* Get the symbol we should use for the mouse click. */
- Lisp_Object head
- = modify_event_symbol (button,
- event->modifiers,
- Qmouse_click,
- lispy_mouse_names, &mouse_syms,
- (sizeof (lispy_mouse_names)
- / sizeof (lispy_mouse_names[0])));
-
+ Lisp_Object head;
+
+ head = modify_event_symbol (button,
+ event->modifiers,
+ Qmouse_click, Qnil,
+ lispy_mouse_names, &mouse_syms,
+ (sizeof (lispy_mouse_names)
+ / sizeof (lispy_mouse_names[0])));
if (event->modifiers & drag_modifier)
return Fcons (head,
Fcons (start_pos,
Qnil));
}
}
+#endif /* MULTI_FRAME or HAVE_MOUSE */
/* The 'kind' field of the event is something we don't recognize. */
default:
}
}
+#ifdef MULTI_FRAME
+
static Lisp_Object
make_lispy_movement (frame, bar_window, part, x, y, time)
FRAME_PTR frame;
/* Is it a scroll bar movement? */
if (frame && ! NILP (bar_window))
{
- Lisp_Object part_sym = *scroll_bar_parts[(int) part];
+ Lisp_Object part_sym;
+ part_sym = *scroll_bar_parts[(int) part];
return Fcons (Qscroll_bar_movement,
(Fcons (Fcons (bar_window,
Fcons (Qvertical_scroll_bar,
else
{
int area;
- Lisp_Object window =
- (frame
- ? window_from_coordinates (frame, XINT (x), XINT (y), &area)
- : Qnil);
+ Lisp_Object window;
Lisp_Object posn;
+ int column, row;
+
+ if (frame)
+ {
+ /* It's in a frame; which window on that frame? */
+ pixel_to_glyph_coords (frame, XINT (x), XINT (y), &column, &row, 0, 1);
+ window = window_from_coordinates (frame, column, row, &area);
+ }
+ else
+ window = Qnil;
if (XTYPE (window) == Lisp_Window)
{
- XSETINT (x, XINT (x) - XINT (XWINDOW (window)->left));
- XSETINT (y, XINT (y) - XINT (XWINDOW (window)->top));
+ int pixcolumn, pixrow;
+ column -= XINT (XWINDOW (window)->left);
+ row -= XINT (XWINDOW (window)->top);
+ glyph_to_pixel_coords (frame, column, row, &pixcolumn, &pixrow);
+ XSETINT (x, pixcolumn);
+ XSETINT (y, pixrow);
if (area == 1)
posn = Qmode_line;
posn = Qvertical_line;
else
XSET (posn, Lisp_Int,
- buffer_posn_from_coords (XWINDOW (window),
- XINT (x), XINT (y)));
+ buffer_posn_from_coords (XWINDOW (window), column, row));
+ }
+ else if (frame != 0)
+ {
+ XSET (window, Lisp_Frame, frame);
+ posn = Qnil;
}
else
{
}
}
+#endif /* MULTI_FRAME */
+
/* Construct a switch frame event. */
static Lisp_Object
make_lispy_switch_frame (frame)
}
{
- Lisp_Object new_name = make_uninit_string (mod_len + base_len);
+ Lisp_Object new_name;
+ new_name = make_uninit_string (mod_len + base_len);
bcopy (new_mods, XSTRING (new_name)->data, mod_len);
bcopy (base, XSTRING (new_name)->data + mod_len, base_len);
parse_modifiers (symbol)
Lisp_Object symbol;
{
- Lisp_Object elements = Fget (symbol, Qevent_symbol_element_mask);
+ Lisp_Object elements;
+ elements = Fget (symbol, Qevent_symbol_element_mask);
if (CONSP (elements))
return elements;
else
{
int end;
int modifiers = parse_modifiers_uncached (symbol, &end);
- Lisp_Object unmodified
- = Fintern (make_string (XSYMBOL (symbol)->name->data + end,
- XSYMBOL (symbol)->name->size - end),
- Qnil);
+ Lisp_Object unmodified;
Lisp_Object mask;
+ unmodified = Fintern (make_string (XSYMBOL (symbol)->name->data + end,
+ XSYMBOL (symbol)->name->size - end),
+ Qnil);
+
if (modifiers & ~((1<<VALBITS) - 1))
abort ();
XFASTINT (mask) = modifiers;
Qevent_kind set right as well. */
if (NILP (Fget (new_symbol, Qevent_kind)))
{
- Lisp_Object kind = Fget (base, Qevent_kind);
+ Lisp_Object kind;
+ kind = Fget (base, Qevent_kind);
if (! NILP (kind))
Fput (new_symbol, Qevent_kind, kind);
}
{
/* It's hopefully okay to write the code this way, since everything
will soon be in caches, and no consing will be done at all. */
- Lisp_Object parsed = parse_modifiers (symbol);
+ Lisp_Object parsed;
+ parsed = parse_modifiers (symbol);
return apply_modifiers (XCONS (XCONS (parsed)->cdr)->car,
XCONS (parsed)->car);
}
is the name of the i'th symbol. TABLE_SIZE is the number of elements
in the table.
+ Alternatively, NAME_ALIST is an alist mapping codes into symbol names.
+ NAME_ALIST is used if it is non-nil; otherwise NAME_TABLE is used.
+
SYMBOL_TABLE should be a pointer to a Lisp_Object whose value will
persist between calls to modify_event_symbol that it can use to
store a cache of the symbols it's generated for this NAME_TABLE
- before.
+ before. The object stored there may be a vector or an alist.
SYMBOL_NUM is the number of the base name we want from NAME_TABLE.
in the symbol's name. */
static Lisp_Object
-modify_event_symbol (symbol_num, modifiers, symbol_kind, name_table,
- symbol_table, table_size)
+modify_event_symbol (symbol_num, modifiers, symbol_kind, name_alist,
+ name_table, symbol_table, table_size)
int symbol_num;
unsigned modifiers;
Lisp_Object symbol_kind;
+ Lisp_Object name_alist;
char **name_table;
Lisp_Object *symbol_table;
int table_size;
{
- Lisp_Object *slot;
+ Lisp_Object value;
+ Lisp_Object symbol_int;
+
+ XSET (symbol_int, Lisp_Int, symbol_num);
/* Is this a request for a valid symbol? */
if (symbol_num < 0 || symbol_num >= table_size)
abort ();
+ if (CONSP (*symbol_table))
+ value = Fcdr (assq_no_quit (symbol_int, *symbol_table));
+
/* If *symbol_table doesn't seem to be initialized properly, fix that.
*symbol_table should be a lisp vector TABLE_SIZE elements long,
where the Nth element is the symbol for NAME_TABLE[N], or nil if
we've never used that symbol before. */
- if (XTYPE (*symbol_table) != Lisp_Vector
- || XVECTOR (*symbol_table)->size != table_size)
+ else
{
- Lisp_Object size;
+ if (! VECTORP (*symbol_table)
+ || XVECTOR (*symbol_table)->size != table_size)
+ {
+ Lisp_Object size;
- XFASTINT (size) = table_size;
- *symbol_table = Fmake_vector (size, Qnil);
- }
+ XFASTINT (size) = table_size;
+ *symbol_table = Fmake_vector (size, Qnil);
+ }
- slot = & XVECTOR (*symbol_table)->contents[symbol_num];
+ value = XVECTOR (*symbol_table)->contents[symbol_num];
+ }
/* Have we already used this symbol before? */
- if (NILP (*slot))
+ if (NILP (value))
{
/* No; let's create it. */
- if (name_table[symbol_num])
- *slot = intern (name_table[symbol_num]);
- else
+ if (!NILP (name_alist))
+ value = Fcdr_safe (Fassq (symbol_int, name_alist));
+ else if (name_table[symbol_num])
+ value = intern (name_table[symbol_num]);
+
+ if (NILP (value))
{
char buf[20];
sprintf (buf, "key-%d", symbol_num);
- *slot = intern (buf);
+ value = intern (buf);
}
+ if (CONSP (*symbol_table))
+ *symbol_table = Fcons (value, *symbol_table);
+ else
+ XVECTOR (*symbol_table)->contents[symbol_num] = value;
+
/* Fill in the cache entries for this symbol; this also
builds the Qevent_symbol_elements property, which the user
cares about. */
- apply_modifiers (modifiers & click_modifier, *slot);
- Fput (*slot, Qevent_kind, symbol_kind);
+ apply_modifiers (modifiers & click_modifier, value);
+ Fput (value, Qevent_kind, symbol_kind);
}
/* Apply modifiers to that symbol. */
- return apply_modifiers (modifiers, *slot);
+ return apply_modifiers (modifiers, value);
}
\f
read_avail_input (expected);
#endif
}
+
+/* Put a buffer_switch_event in the buffer
+ so that read_key_sequence will notice the new current buffer. */
+
+record_asynch_buffer_change ()
+{
+ struct input_event event;
+ event.kind = buffer_switch_event;
+ event.frame_or_window = Qnil;
+
+ /* Make sure no interrupt happens while storing the event. */
+#ifdef SIGIO
+ if (interrupt_input)
+ {
+ SIGMASKTYPE mask;
+ mask = sigblockx (SIGIO);
+ kbd_buffer_store_event (&event);
+ sigsetmask (mask);
+ }
+ else
+#endif
+ {
+ stop_polling ();
+ kbd_buffer_store_event (&event);
+ start_polling ();
+ }
+}
\f
#ifndef VMS
the kbd_buffer can really hold. That may prevent loss
of characters on some systems when input is stuffed at us. */
unsigned char cbuf[KBD_BUFFER_SIZE - 1];
+ int n_to_read;
+ /* Determine how many characters we should *try* to read. */
+#ifdef MSDOS
+ n_to_read = dos_keysns ();
+ if (n_to_read == 0)
+ return 0;
+#else /* not MSDOS */
#ifdef FIONREAD
/* Find out how much input is available. */
- if (ioctl (0, FIONREAD, &nread) < 0)
+ if (ioctl (0, FIONREAD, &n_to_read) < 0)
/* Formerly simply reported no input, but that sometimes led to
a failure of Emacs to terminate.
SIGHUP seems appropriate if we can't reach the terminal. */
rather than to the whole process group?
Perhaps on systems with FIONREAD Emacs is alone in its group. */
kill (getpid (), SIGHUP);
- if (nread == 0)
+ if (n_to_read == 0)
return 0;
- if (nread > sizeof cbuf)
- nread = sizeof cbuf;
+ if (n_to_read > sizeof cbuf)
+ n_to_read = sizeof cbuf;
#else /* no FIONREAD */
#if defined(USG) || defined(DGUX)
/* Read some input if available, but don't wait. */
- nread = sizeof cbuf;
+ n_to_read = sizeof cbuf;
fcntl (fileno (stdin), F_SETFL, O_NDELAY);
#else
you lose;
#endif
#endif
+#endif /* not MSDOS */
- /* Now read; for one reason or another, this will not block. */
- while (1)
+ /* Now read; for one reason or another, this will not block.
+ NREAD is set to the number of chars read. */
+ do
{
- int value = read (fileno (stdin), cbuf, nread);
-#ifdef AIX
+#ifdef MSDOS
+ cbuf[0] = dos_keyread();
+ nread = 1;
+#else
+ nread = read (fileno (stdin), cbuf, n_to_read);
+#endif
+#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
O_NDELAY to be defined in fcntl.h as O_NONBLOCK,
and that causes a value other than 0 when there is no input. */
- if (value == 0)
- kill (SIGHUP, 0);
+ if (nread == 0)
+ kill (0, SIGHUP);
+#endif
+ }
+ while (
+ /* We used to retry the read if it was interrupted.
+ But this does the wrong thing when O_NDELAY causes
+ an EAGAIN error. Does anybody know of a situation
+ where a retry is actually needed? */
+#if 0
+ nread < 0 && (errno == EAGAIN
+#ifdef EFAULT
+ || errno == EFAULT
#endif
- /* Retry the read if it is interrupted. */
- if (value >= 0
- || ! (errno == EAGAIN || errno == EFAULT
#ifdef EBADSLT
- || errno == EBADSLT
+ || errno == EBADSLT
#endif
- ))
- {
- nread = value;
- break;
- }
- }
+ )
+#else
+ 0
+#endif
+ );
#ifndef FIONREAD
-#ifdef USG
+#if defined (USG) || defined (DGUX)
fcntl (fileno (stdin), F_SETFL, 0);
-#endif /* USG */
+#endif /* USG or DGUX */
#endif /* no FIONREAD */
for (i = 0; i < nread; i++)
{
return Qnil;
}
-static Lisp_Object menu_bar_item ();
-static Lisp_Object menu_bar_one_keymap ();
+static void menu_bar_item ();
+static void menu_bar_one_keymap ();
+
+/* These variables hold the vector under construction within
+ menu_bar_items and its subroutines, and the current index
+ for storing into that vector. */
+static Lisp_Object menu_bar_items_vector;
+static Lisp_Object menu_bar_items_index;
+
+/* Return a vector of menu items for a menu bar, appropriate
+ to the current buffer. Each item has three elements in the vector:
+ KEY STRING MAPLIST.
-/* Return a list of menu items for a menu bar, appropriate
- to the current buffer.
- The elements have the form (KEY STRING . nil). */
+ OLD is an old vector we can optionally reuse, or nil. */
Lisp_Object
-menu_bar_items ()
+menu_bar_items (old)
+ Lisp_Object old;
{
/* The number of keymaps we're scanning right now, and the number of
keymaps we have allocated space for. */
int mapno;
Lisp_Object oquit;
+ int i;
+
+ struct gcpro gcpro1;
+
/* In order to build the menus, we need to call the keymap
accessors. They all call QUIT. But this function is called
during redisplay, during which a quit is fatal. So inhibit
oquit = Vinhibit_quit;
Vinhibit_quit = Qt;
+ if (!NILP (old))
+ menu_bar_items_vector = old;
+ else
+ menu_bar_items_vector = Fmake_vector (make_number (24), Qnil);
+ menu_bar_items_index = 0;
+
+ GCPRO1 (menu_bar_items_vector);
+
/* Build our list of keymaps.
If we recognize a function key and replace its escape sequence in
keybuf with its symbol, or if the sequence starts with a mouse
{
Lisp_Object *tmaps;
- nmaps = current_minor_maps (0, &tmaps) + 2;
- maps = (Lisp_Object *) alloca (nmaps * sizeof (maps[0]));
- bcopy (tmaps, maps, (nmaps - 2) * sizeof (maps[0]));
+ if (!NILP (Voverriding_local_map))
+ {
+ nmaps = 2;
+ maps = (Lisp_Object *) alloca (nmaps * sizeof (maps[0]));
+ maps[0] = Voverriding_local_map;
+ }
+ else
+ {
+ nmaps = current_minor_maps (0, &tmaps) + 2;
+ maps = (Lisp_Object *) alloca (nmaps * sizeof (maps[0]));
+ bcopy (tmaps, maps, (nmaps - 2) * sizeof (maps[0]));
#ifdef USE_TEXT_PROPERTIES
- maps[nmaps-2] = get_local_map (PT, current_buffer);
+ maps[nmaps-2] = get_local_map (PT, current_buffer);
#else
- maps[nmaps-2] = current_buffer->keymap;
+ maps[nmaps-2] = current_buffer->keymap;
#endif
+ }
maps[nmaps-1] = current_global_map;
}
tem = Fkeymapp (def);
if (!NILP (tem))
- result = menu_bar_one_keymap (def, result);
+ menu_bar_one_keymap (def);
}
+ /* Move to the end those items that should be at the end. */
+
for (tail = Vmenu_bar_final_items; CONSP (tail); tail = XCONS (tail)->cdr)
{
- Lisp_Object elt;
+ int i;
+ int end = menu_bar_items_index;
- elt = Fassq (XCONS (tail)->car, result);
- if (!NILP (elt))
- result = Fcons (elt, Fdelq (elt, result));
+ for (i = 0; i < end; i += 3)
+ if (EQ (XCONS (tail)->car, XVECTOR (menu_bar_items_vector)->contents[i]))
+ {
+ Lisp_Object tem0, tem1, tem2;
+ /* Move the item at index I to the end,
+ shifting all the others forward. */
+ tem0 = XVECTOR (menu_bar_items_vector)->contents[i + 0];
+ tem1 = XVECTOR (menu_bar_items_vector)->contents[i + 1];
+ tem2 = XVECTOR (menu_bar_items_vector)->contents[i + 2];
+ if (end > i + 3)
+ bcopy (&XVECTOR (menu_bar_items_vector)->contents[i + 3],
+ &XVECTOR (menu_bar_items_vector)->contents[i],
+ (end - i - 3) * sizeof (Lisp_Object));
+ XVECTOR (menu_bar_items_vector)->contents[end - 3] = tem0;
+ XVECTOR (menu_bar_items_vector)->contents[end - 2] = tem1;
+ XVECTOR (menu_bar_items_vector)->contents[end - 1] = tem2;
+ break;
+ }
}
- result = Fnreverse (result);
+ /* Add nil, nil, nil at the end. */
+ i = menu_bar_items_index;
+ if (i + 3 > XVECTOR (menu_bar_items_vector)->size)
+ {
+ Lisp_Object tem;
+ int newsize = 2 * i;
+ tem = Fmake_vector (make_number (2 * i), Qnil);
+ bcopy (XVECTOR (menu_bar_items_vector)->contents,
+ XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
+ menu_bar_items_vector = tem;
+ }
+ /* Add this item. */
+ XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
+ XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
+ XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
+ menu_bar_items_index = i;
+
Vinhibit_quit = oquit;
- return result;
+ UNGCPRO;
+ return menu_bar_items_vector;
}
\f
/* Scan one map KEYMAP, accumulating any menu items it defines
- that have not yet been seen in RESULT. Return the updated RESULT. */
+ in menu_bar_items_vector. */
-static Lisp_Object
-menu_bar_one_keymap (keymap, result)
- Lisp_Object keymap, result;
+static void
+menu_bar_one_keymap (keymap)
+ Lisp_Object keymap;
{
Lisp_Object tail, item, key, binding, item_string, table;
{
item_string = XCONS (binding)->car;
if (XTYPE (item_string) == Lisp_String)
- result = menu_bar_item (key, item_string,
- Fcdr (binding), result);
+ menu_bar_item (key, item_string, Fcdr (binding));
}
else if (EQ (binding, Qundefined))
- result = menu_bar_item (key, item_string,
- binding, result);
+ menu_bar_item (key, Qnil, binding);
}
else if (XTYPE (item) == Lisp_Vector)
{
{
item_string = XCONS (binding)->car;
if (XTYPE (item_string) == Lisp_String)
- result = menu_bar_item (key, item_string,
- Fcdr (binding), result);
+ menu_bar_item (key, item_string, Fcdr (binding));
}
else if (EQ (binding, Qundefined))
- result = menu_bar_item (key, item_string,
- binding, result);
+ menu_bar_item (key, Qnil, binding);
}
}
}
-
- return result;
}
+/* This is used as the handler when calling internal_condition_case_1. */
+
static Lisp_Object
-menu_bar_item (key, item_string, def, result)
- Lisp_Object key, item_string, def, result;
+menu_bar_item_1 (arg)
+ Lisp_Object arg;
+{
+ return Qnil;
+}
+
+/* Add one item to menu_bar_items_vector, for KEY, ITEM_STRING and DEF.
+ If there's already an item for KEY, add this DEF to it. */
+
+static void
+menu_bar_item (key, item_string, def)
+ Lisp_Object key, item_string, def;
{
Lisp_Object tem;
Lisp_Object enabled;
+ int i;
if (EQ (def, Qundefined))
{
- /* If a map has an explicit nil as definition,
+ /* If a map has an explicit `undefined' as definition,
discard any previously made menu bar item. */
- tem = Fassq (key, result);
- return Fdelq (tem, result);
+
+ for (i = 0; i < menu_bar_items_index; i += 3)
+ if (EQ (key, XVECTOR (menu_bar_items_vector)->contents[i]))
+ {
+ if (menu_bar_items_index > i + 3)
+ bcopy (&XVECTOR (menu_bar_items_vector)->contents[i + 3],
+ &XVECTOR (menu_bar_items_vector)->contents[i],
+ (menu_bar_items_index - i - 3) * sizeof (Lisp_Object));
+ menu_bar_items_index -= 3;
+ return;
+ }
+
+ /* If there's no definition for this key yet,
+ just ignore `undefined'. */
+ return;
}
/* See if this entry is enabled. */
Otherwise, enable if value is not nil. */
tem = Fget (def, Qmenu_enable);
if (!NILP (tem))
- enabled = Feval (tem);
+ /* (condition-case nil (eval tem)
+ (error nil)) */
+ enabled = internal_condition_case_1 (Feval, tem, Qerror,
+ menu_bar_item_1);
}
- /* Add an entry for this key and string
- if there is none yet. */
- tem = Fassq (key, result);
- if (!NILP (enabled) && NILP (tem))
- result = Fcons (Fcons (key, Fcons (item_string, Qnil)), result);
+ /* Ignore this item if it's not enabled. */
+ if (NILP (enabled))
+ return;
+
+ /* Find any existing item for this KEY. */
+ for (i = 0; i < menu_bar_items_index; i += 3)
+ if (EQ (key, XVECTOR (menu_bar_items_vector)->contents[i]))
+ break;
- return result;
+ /* If we did not find this KEY, add it at the end. */
+ if (i == menu_bar_items_index)
+ {
+ /* If vector is too small, get a bigger one. */
+ if (i + 3 > XVECTOR (menu_bar_items_vector)->size)
+ {
+ Lisp_Object tem;
+ int newsize = 2 * i;
+ tem = Fmake_vector (make_number (2 * i), Qnil);
+ bcopy (XVECTOR (menu_bar_items_vector)->contents,
+ XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
+ menu_bar_items_vector = tem;
+ }
+ /* Add this item. */
+ XVECTOR (menu_bar_items_vector)->contents[i++] = key;
+ XVECTOR (menu_bar_items_vector)->contents[i++] = item_string;
+ XVECTOR (menu_bar_items_vector)->contents[i++] = Fcons (def, Qnil);
+ menu_bar_items_index = i;
+ }
+ /* We did find an item for this KEY. Add DEF to its list of maps. */
+ else
+ {
+ Lisp_Object old;
+ old = XVECTOR (menu_bar_items_vector)->contents[i + 2];
+ XVECTOR (menu_bar_items_vector)->contents[i + 2] = Fcons (def, old);
+ }
}
\f
-static int echo_flag;
-static int echo_now;
-
/* Read a character using menus based on maps in the array MAPS.
NMAPS is the length of MAPS. Return nil if there are no menus in the maps.
Return t if we displayed a menu but the user rejected it.
USED_MOUSE_MENU is zero, *USED_MOUSE_MENU is left alone.
The prompting is done based on the prompt-string of the map
- and the strings associated with various map elements. */
+ and the strings associated with various map elements.
+
+ This can be done with X menus or with menus put in the minibuf.
+ These are done in different ways, depending on how the input will be read.
+ Menus using X are done after auto-saving in read-char, getting the input
+ event from Fx_popup_menu; menus using the minibuf use read_char recursively
+ and do auto-saving in the inner call of read_char. */
static Lisp_Object
-read_char_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
+read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
int nmaps;
Lisp_Object *maps;
Lisp_Object prev_event;
{
int mapno;
register Lisp_Object name;
- int nlength;
- int width = FRAME_WIDTH (selected_frame) - 4;
- char *menu = (char *) alloca (width + 4);
- int idx = -1;
Lisp_Object rest, vector;
if (used_mouse_menu)
/* If we got more than one event, put all but the first
onto this list to be read later.
Return just the first event now. */
- unread_command_events
- = nconc2 (XCONS (value)->cdr, unread_command_events);
+ Vunread_command_events
+ = nconc2 (XCONS (value)->cdr, Vunread_command_events);
value = XCONS (value)->car;
}
- if (NILP (value))
+ else if (NILP (value))
value = Qt;
if (used_mouse_menu)
*used_mouse_menu = 1;
}
#endif /* HAVE_X_MENU */
#endif /* HAVE_X_WINDOWS */
+ return Qnil ;
+}
+
+static Lisp_Object
+read_char_minibuf_menu_prompt (commandflag, nmaps, maps)
+ int commandflag ;
+ int nmaps;
+ Lisp_Object *maps;
+{
+ int mapno;
+ register Lisp_Object name;
+ int nlength;
+ int width = FRAME_WIDTH (selected_frame) - 4;
+ char *menu = (char *) alloca (width + 4);
+ int idx = -1;
+ int nobindings = 1;
+ Lisp_Object rest, vector;
+
+ if (! menu_prompting)
+ return Qnil;
+
+ /* Get the menu name from the first map that has one (a prompt string). */
+ for (mapno = 0; mapno < nmaps; mapno++)
+ {
+ name = map_prompt (maps[mapno]);
+ if (!NILP (name))
+ break;
+ }
+
+ /* If we don't have any menus, just read a character normally. */
+ if (mapno >= nmaps)
+ return Qnil;
/* Prompt string always starts with map's prompt, and a space. */
strcpy (menu, XSTRING (name)->data);
int i = nlength;
Lisp_Object obj;
int ch;
+ int orig_defn_macro ;
/* Loop over elements of map. */
while (i < width)
or end this line if already have something on it. */
if (mapno == nmaps)
{
- if (notfirst)
- break;
- else
- mapno = 0;
+ mapno = 0;
+ if (notfirst || nobindings) break;
}
rest = maps[mapno];
}
else
{
/* An ordinary element. */
- s = Fcar_safe (Fcdr_safe (elt));
+ if ( idx < 0 )
+ s = Fcar_safe (Fcdr_safe (elt)); /* alist */
+ else
+ s = Fcar_safe(elt); /* vector */
if (XTYPE (s) != Lisp_String)
/* Ignore the element if it has no prompt string. */
;
/* If we have room for the prompt string, add it to this line.
If this is the first on the line, always add it. */
- else if (XSTRING (s)->size + i < width
+ else if (XSTRING (s)->size + i + 2 < width
|| !notfirst)
{
int thiswidth;
i += 2;
}
notfirst = 1;
+ nobindings = 0 ;
/* Add as much of string as fits. */
thiswidth = XSTRING (s)->size;
thiswidth = width - i;
bcopy (XSTRING (s)->data, menu + i, thiswidth);
i += thiswidth;
+ menu[i] = 0;
}
else
{
}
/* Move past this element. */
- if (idx >= 0 && idx + 1 >= XVECTOR (rest)->size)
+ if (idx >= 0 && idx + 1 >= XVECTOR (vector)->size)
/* Handle reaching end of dense table. */
idx = -1;
if (idx >= 0)
/* Prompt with that and read response. */
message1 (menu);
- obj = read_char (1, 0, 0, Qnil, 0);
+
+ /* Make believe its not a keyboard macro in case the help char
+ is pressed. Help characters are not recorded because menu prompting
+ is not used on replay.
+ */
+ orig_defn_macro = defining_kbd_macro ;
+ defining_kbd_macro = 0 ;
+ do
+ obj = read_char (commandflag, 0, 0, Qnil, 0);
+ while (XTYPE (obj) == Lisp_Buffer);
+ defining_kbd_macro = orig_defn_macro ;
if (XTYPE (obj) != Lisp_Int)
return obj;
if (! EQ (obj, menu_prompt_more_char)
&& (XTYPE (menu_prompt_more_char) != Lisp_Int
|| ! EQ (obj, make_number (Ctl (XINT (menu_prompt_more_char))))))
- return obj;
+ {
+ if ( defining_kbd_macro )
+ store_kbd_macro_char(obj) ;
+ return obj;
+ }
+ /* Help char - go round again */
}
}
\f
When KEY is not defined in any of the keymaps, if it is an upper
case letter and there are bindings for the corresponding lower-case
letter, return the bindings for the lower-case letter.
+ We store 1 in *CASE_CONVERTED in this case.
+ Otherwise, we don't change *CASE_CONVERTED.
If KEY has no bindings in any of the CURRENT maps, NEXT is left
unmodified.
NEXT may == CURRENT. */
static int
-follow_key (key, nmaps, current, defs, next)
+follow_key (key, nmaps, current, defs, next, case_converted)
Lisp_Object key;
Lisp_Object *current, *defs, *next;
int nmaps;
+ int *case_converted;
{
int i, first_binding;
else
defs[i] = Qnil;
}
+ if (first_binding != nmaps)
+ *case_converted = 1;
}
/* Given the set of bindings we've found, produce the next set of maps. */
struct buffer *starting_buffer;
+ /* Nonzero if we found the binding for one of the chars
+ in this key sequence by downcasing it. */
+ int case_converted = 0;
+
+ /* Nonzero if we seem to have got the beginning of a binding
+ in function_key_map. */
+ int function_key_possible = 0;
+
int junk;
last_nonmenu_event = Qnil;
replay_sequence:
starting_buffer = current_buffer;
+ case_converted = 0;
+ function_key_possible = 0;
/* Build our list of keymaps.
If we recognize a function key and replace its escape sequence in
{
Lisp_Object *maps;
- nmaps = current_minor_maps (0, &maps) + 2;
- if (nmaps > nmaps_allocated)
+ if (!NILP (Voverriding_local_map))
{
- submaps = (Lisp_Object *) alloca (nmaps * sizeof (submaps[0]));
- defs = (Lisp_Object *) alloca (nmaps * sizeof (defs[0]));
- nmaps_allocated = nmaps;
+ nmaps = 2;
+ if (nmaps > nmaps_allocated)
+ {
+ submaps = (Lisp_Object *) alloca (nmaps * sizeof (submaps[0]));
+ defs = (Lisp_Object *) alloca (nmaps * sizeof (defs[0]));
+ nmaps_allocated = nmaps;
+ }
+ submaps[0] = Voverriding_local_map;
}
- bcopy (maps, submaps, (nmaps - 2) * sizeof (submaps[0]));
+ else
+ {
+ nmaps = current_minor_maps (0, &maps) + 2;
+ if (nmaps > nmaps_allocated)
+ {
+ submaps = (Lisp_Object *) alloca (nmaps * sizeof (submaps[0]));
+ defs = (Lisp_Object *) alloca (nmaps * sizeof (defs[0]));
+ nmaps_allocated = nmaps;
+ }
+ bcopy (maps, submaps, (nmaps - 2) * sizeof (submaps[0]));
#ifdef USE_TEXT_PROPERTIES
- submaps[nmaps-2] = get_local_map (PT, current_buffer);
+ submaps[nmaps-2] = get_local_map (PT, current_buffer);
#else
- submaps[nmaps-2] = current_buffer->keymap;
+ submaps[nmaps-2] = current_buffer->keymap;
#endif
+ }
submaps[nmaps-1] = current_global_map;
}
/* These are no-ops the first time through, but if we restart, they
revert the echo area and this_command_keys to their original state. */
this_command_key_count = keys_start;
- if (INTERACTIVE)
+ if (INTERACTIVE && t < mock_input)
echo_truncate (echo_start);
/* If the best binding for the current key sequence is a keymap, or
|| (first_binding >= nmaps
&& keytran_start < t
/* mock input is never part of a function key's sequence. */
- && mock_input <= keytran_start))
+ && mock_input <= keytran_start)
+ /* Don't return in the middle of a possible function key sequence,
+ if the only bindings we found were via case conversion.
+ Thus, if ESC O a has a function-key-map translation
+ and ESC o has a binding, don't return after ESC O,
+ so that we can translate ESC O plus the next character. */
+ || (function_key_possible && case_converted))
{
Lisp_Object key;
int used_mouse_menu = 0;
jumped back up to replay_key; in that case, these restore the
variables to their original state, allowing us to replay the
loop. */
- if (INTERACTIVE)
+ if (INTERACTIVE && t < mock_input)
echo_truncate (echo_local_start);
this_command_key_count = keys_local_start;
first_binding = local_first_binding;
goto done;
}
+ /* If the current buffer has been changed from under us, the
+ keymap may have changed, so replay the sequence. */
+ if (XTYPE (key) == Lisp_Buffer)
+ {
+ mock_input = t;
+ goto replay_sequence;
+ }
+
/* If we have a quit that was typed in another frame, and
quit_throw_to_read_char switched buffers,
replay to get the right keymap. */
Vquit_flag = Qnil;
goto replay_sequence;
}
-
+
Vquit_flag = Qnil;
}
or when user programs play with this-command-keys. */
if (EVENT_HAS_PARAMETERS (key))
{
- Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
+ Lisp_Object kind;
+ kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
if (EQ (kind, Qmouse_click))
{
- Lisp_Object window = POSN_WINDOW (EVENT_START (key));
- Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key));
+ Lisp_Object window, posn;
+ window = POSN_WINDOW (EVENT_START (key));
+ posn = POSN_BUFFER_POSN (EVENT_START (key));
if (XTYPE (posn) == Lisp_Cons)
{
/* We're looking at the second event of a
}
else
{
- Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key));
+ Lisp_Object posn;
+ posn = POSN_BUFFER_POSN (EVENT_START (key));
/* Handle menu-bar events:
insert the dummy prefix event `menu-bar'. */
if (EQ (posn, Qmenu_bar))
if (t + 1 >= bufsize)
error ("key sequence too long");
/* Run the Lucid hook. */
- call1 (Vrun_hooks, Qactivate_menubar_hook);
+ if (!NILP (Vrun_hooks))
+ call1 (Vrun_hooks, Qactivate_menubar_hook);
/* If it has changed current-menubar from previous value,
really recompute the menubar from the value. */
if (! NILP (Vlucid_menu_bar_dirty_flag))
nmaps - first_binding,
submaps + first_binding,
defs + first_binding,
- submaps + first_binding)
+ submaps + first_binding,
+ &case_converted)
+ first_binding);
/* If KEY wasn't bound, we'll try some fallbacks. */
if (first_binding >= nmaps)
{
- Lisp_Object head = EVENT_HEAD (key);
+ Lisp_Object head;
+ head = EVENT_HEAD (key);
if (EQ (head, Vhelp_char))
{
read_key_sequence_cmd = Vprefix_help_command;
if (XTYPE (head) == Lisp_Symbol)
{
- Lisp_Object breakdown = parse_modifiers (head);
- int modifiers = XINT (XCONS (XCONS (breakdown)->cdr)->car);
+ Lisp_Object breakdown;
+ int modifiers;
+ breakdown = parse_modifiers (head);
+ modifiers = XINT (XCONS (XCONS (breakdown)->cdr)->car);
/* Attempt to reduce an unbound mouse event to a simpler
event that is bound:
Drags reduce to clicks.
nmaps - local_first_binding,
submaps + local_first_binding,
defs + local_first_binding,
- submaps + local_first_binding)
+ submaps + local_first_binding,
+ &case_converted)
+ local_first_binding);
/* If that click is bound, go for it. */
off the end of it. We only want to scan real keyboard input
for function key sequences, so if mock_input says that we're
re-reading old events, don't examine it. */
- if (first_binding >= nmaps
+ if ((first_binding >= nmaps || case_converted)
&& t >= mock_input)
{
Lisp_Object fkey_next;
- /* Scan from fkey_end until we find a bound suffix. */
+ /* Continue scan from fkey_end until we find a bound suffix.
+ If we fail, increment fkey_start
+ and start fkey_end from there. */
while (fkey_end < t)
{
Lisp_Object key;
error ("Function in function-key-map returns invalid key sequence");
}
+ function_key_possible = ! NILP (fkey_next);
+
/* If keybuf[fkey_start..fkey_end] is bound in the
function key map and it's a suffix of the current
sequence (i.e. fkey_end == t), replace it with
{
fkey_end = ++fkey_start;
fkey_map = Vfunction_key_map;
+ function_key_possible = 0;
}
}
}
Lisp_Object tem;
tem = keytran_next;
- GCPRO3 (keytran_map, keytran_map, delayed_switch_frame);
+ GCPRO3 (fkey_map, keytran_map, delayed_switch_frame);
keytran_next = call1 (keytran_next, prompt);
UNGCPRO;
/* If the function returned something invalid,
(To ignore it safely, we would need to gcpro a bunch of
other variables.) */
if (! (VECTORP (keytran_next) || STRINGP (keytran_next)))
- error ("Function in function-key-map returns invalid key sequence");
+ error ("Function in key-translation-map returns invalid key sequence");
}
/* If keybuf[keytran_start..keytran_end] is bound in the
if (XTYPE (cmd) == Lisp_Symbol)
{
tem = Fget (cmd, Qdisabled);
- if (!NILP (tem))
+ if (!NILP (tem) && !NILP (Vrun_hooks))
return call1 (Vrun_hooks, Qdisabled_command_hook);
}
Lisp_Object saved_keys;
struct gcpro gcpro1;
- saved_keys = Fthis_command_keys ();
+ saved_keys = Fvector (this_command_key_count,
+ XVECTOR (this_command_keys)->contents);
buf[0] = 0;
GCPRO1 (saved_keys);
function, followed by a RET. */
{
struct Lisp_String *str;
+ Lisp_Object *keys;
int i;
Lisp_Object tem;
this_command_key_count = 0;
- str = XSTRING (saved_keys);
- for (i = 0; i < str->size; i++)
- {
- XFASTINT (tem) = str->data[i];
- add_command_key (tem);
- }
+ keys = XVECTOR (saved_keys)->contents;
+ for (i = 0; i < XVECTOR (saved_keys)->size; i++)
+ add_command_key (keys[i]);
str = XSTRING (function);
for (i = 0; i < str->size; i++)
Actually, the value is nil only if we can be sure that no input is available.")
()
{
- if (!NILP (unread_command_events) || unread_command_char != -1)
+ if (!NILP (Vunread_command_events) || unread_command_char != -1)
return (Qt);
return detect_input_pending () ? Qt : Qnil;
defining_kbd_macro = 0;
update_mode_lines++;
- unread_command_events = Qnil;
+ Vunread_command_events = Qnil;
unread_command_char = -1;
discard_tty_input ();
\f
DEFUN ("suspend-emacs", Fsuspend_emacs, Ssuspend_emacs, 0, 1, "",
"Stop Emacs and return to superior process. You can resume later.\n\
-On systems that don't have job control, run a subshell instead.\n\n\
+If `cannot-suspend' is non-nil, or if the system doesn't support job\n\
+control, run a subshell instead.\n\n\
If optional arg STUFFSTRING is non-nil, its characters are stuffed\n\
to be read as terminal input by Emacs's parent, after suspension.\n\
\n\
and the system resources aren't available for that. */
record_unwind_protect (init_sys_modes, 0);
stuff_buffered_input (stuffstring);
- sys_suspend ();
+ if (cannot_suspend)
+ sys_subshell ();
+ else
+ sys_suspend ();
unbind_to (count, Qnil);
/* Check if terminal/window size has changed.
if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE)
kbd_fetch_ptr = kbd_buffer;
if (kbd_fetch_ptr->kind == ascii_keystroke)
- stuff_char (XINT (kbd_fetch_ptr->code));
+ stuff_char (kbd_fetch_ptr->code);
kbd_fetch_ptr->kind = no_event;
(XVECTOR (kbd_buffer_frame_or_window)->contents[kbd_fetch_ptr
- kbd_buffer]
make it run again now, to avoid timing error. */
if (!NILP (Vquit_flag))
quit_throw_to_read_char ();
-
- /* If alarm has gone off already, echo now. */
- if (echo_flag)
- {
- echo ();
- echo_flag = 0;
- }
}
clear_waiting_for_input ()
printf ("you can continue or abort.\n");
#endif /* not VMS */
#endif /* not SIGTSTP */
+#ifdef MSDOS
+ /* We must remain inside the screen area when the internal terminal
+ is used. Note that [Enter] is not echoed by dos. */
+ cursor_to (0, 0);
+#endif
printf ("Auto-save? (y or n) ");
fflush (stdout);
if (((c = getchar ()) & ~040) == 'Y')
{
Fdo_auto_save (Qt, Qnil);
+#ifdef MSDOS
+ printf ("\r\nAuto-save done");
+#else /* not MSDOS */
printf ("Auto-save done\n");
+#endif /* not MSDOS */
}
while (c != '\n') c = getchar ();
+#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')
abort ();
while (c != '\n') c = getchar ();
+#ifdef MSDOS
+ printf ("\r\nContinuing...\r\n");
+#else /* not MSDOS */
printf ("Continuing...\n");
+#endif /* not MSDOS */
fflush (stdout);
init_sys_modes ();
}
clear_waiting_for_input ();
input_pending = 0;
- unread_command_events = Qnil;
+ Vunread_command_events = Qnil;
unread_command_char = -1;
#ifdef POLL_FOR_INPUT
if (poll_suppress_count == 0)
abort ();
#endif
- if (XFRAME (internal_last_event_frame) != selected_frame)
+#ifdef MULTI_FRAME
+ if (XTYPE (internal_last_event_frame) == Lisp_Frame
+ && XFRAME (internal_last_event_frame) != selected_frame)
Fhandle_switch_frame (make_lispy_switch_frame (internal_last_event_frame));
+#endif
_longjmp (getcjmp, 1);
}
command_loop_level = -1;
immediate_quit = 0;
quit_char = Ctl ('g');
- unread_command_events = Qnil;
+ Vunread_command_events = Qnil;
unread_command_char = -1;
total_keys = 0;
recent_keys_index = 0;
Qpost_command_hook = intern ("post-command-hook");
staticpro (&Qpost_command_hook);
+ Qcommand_hook_internal = intern ("command-hook-internal");
+ staticpro (&Qcommand_hook_internal);
+
Qfunction_key = intern ("function-key");
staticpro (&Qfunction_key);
Qmouse_click = intern ("mouse-click");
Qactivate_menubar_hook = intern ("activate-menubar-hook");
staticpro (&Qactivate_menubar_hook);
+ Qpolling_period = intern ("polling-period");
+ staticpro (&Qpolling_period);
+
{
struct event_head *p;
= Fmake_vector (make_number (KBD_BUFFER_SIZE), Qnil);
staticpro (&kbd_buffer_frame_or_window);
+ accent_key_syms = Qnil;
+ staticpro (&accent_key_syms);
+
func_key_syms = Qnil;
staticpro (&func_key_syms);
+ system_key_syms = Qnil;
+ staticpro (&system_key_syms);
+
mouse_syms = Qnil;
staticpro (&mouse_syms);
DEFVAR_LISP ("last-input-event", &last_input_char,
"Last input event.");
- DEFVAR_LISP ("unread-command-events", &unread_command_events,
+ DEFVAR_LISP ("unread-command-events", &Vunread_command_events,
"List of objects to be read as next command input events.");
DEFVAR_INT ("unread-command-char", &unread_command_char,
"*Number of complete keys read from the keyboard so far.");
num_input_keys = 0;
-#ifdef MULTI_FRAME
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;
-#endif
DEFVAR_LISP ("help-char", &Vhelp_char,
"Character to recognize as meaning Help.\n\
and applies even for keys that have ordinary bindings.");
Vkey_translation_map = Qnil;
+ DEFVAR_BOOL ("cannot-suspend", &cannot_suspend,
+ "Non-nil means to always spawn a subshell instead of suspending,\n\
+even if the operating system has support for stopping a process.");
+ cannot_suspend = 0;
+
DEFVAR_BOOL ("menu-prompting", &menu_prompting,
"Non-nil means prompt with menus when appropriate.\n\
This is done when reading from a keymap that has a prompt string,\n\
Buffer modification stores t in this variable.");
Vdeactivate_mark = Qnil;
+ DEFVAR_LISP ("command-hook-internal", &Vcommand_hook_internal,
+ "Temporary storage of pre-command-hook or post-command-hook.");
+ Vcommand_hook_internal = Qnil;
+
DEFVAR_LISP ("pre-command-hook", &Vpre_command_hook,
- "Normal hook run before each command is executed.");
+ "Normal hook run before each command is executed.\n\
+While the hook is run, its value is temporarily set to nil\n\
+to avoid an unbreakable infinite loop if a hook function gets an error.\n\
+As a result, a hook function cannot straightforwardly alter the value of\n\
+`pre-command-hook'. See the Emacs Lisp manual for a way of\n\
+implementing hook functions that alter the set of hook functions.");
Vpre_command_hook = Qnil;
DEFVAR_LISP ("post-command-hook", &Vpost_command_hook,
- "Normal hook run after each command is executed.");
+ "Normal hook run after each command is executed.\n\
+While the hook is run, its value is temporarily set to nil\n\
+to avoid an unbreakable infinite loop if a hook function gets an error.\n\
+As a result, a hook function cannot straightforwardly alter the value of\n\
+`post-command-hook'. See the Emacs Lisp manual for a way of\n\
+implementing hook functions that alter the set of hook functions.");
Vpost_command_hook = Qnil;
DEFVAR_LISP ("lucid-menu-bar-dirty-flag", &Vlucid_menu_bar_dirty_flag,
"List of menu bar items to move to the end of the menu bar.\n\
The elements of the list are event types that may have menu bar bindings.");
Vmenu_bar_final_items = Qnil;
+
+ DEFVAR_LISP ("overriding-local-map", &Voverriding_local_map,
+ "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.");
+ Voverriding_local_map = Qnil;
+
+ DEFVAR_BOOL ("track-mouse", &do_mouse_tracking,
+ "*Non-nil means generate motion events for mouse motion.");
+
+ DEFVAR_LISP ("system-key-alist", &Vsystem_key_alist,
+ "Alist of system-specific X windows key symbols.\n\
+Each element should have the form (N . SYMBOL) where N is the\n\
+numeric keysym code (sans the \"system-specific\" bit 1<<28)\n\
+and SYMBOL is its name.");
+ Vmenu_bar_final_items = Qnil;
}
keys_of_keyboard ()