int interrupt_input_pending;
-#ifdef HAVE_X_WINDOWS
-extern Lisp_Object Vmouse_grabbed;
+/* File descriptor to use for input. */
+extern int input_fd;
+#ifdef HAVE_X_WINDOWS
/* Make all keyboard buffers much bigger when using X windows. */
#define KBD_BUFFER_SIZE 4096
#else /* No X-windows, character input */
/* True while displaying for echoing. Delays C-g throwing. */
static int echoing;
+/* Nonzero means disregard local maps for the menu bar. */
+static int inhibit_local_menu_bar_menus;
+
/* Nonzero means C-g should cause immediate error-signal. */
int immediate_quit;
/* If non-nil, this is a map that overrides all other local maps. */
Lisp_Object Voverriding_local_map;
+/* If non-nil, Voverriding_local_map applies to the menu bar. */
+Lisp_Object Voverriding_local_map_menu_flag;
+
/* Current depth in recursive edits. */
int command_loop_level;
Lisp_Object Vpre_command_hook, Vpost_command_hook;
Lisp_Object Qcommand_hook_internal, Vcommand_hook_internal;
+/* List of deferred actions to be performed at a later time.
+ The precise format isn't relevant here; we just check whether it is nil. */
+Lisp_Object Vdeferred_action_list;
+
+/* Function to call to handle deferred actions, when there are any. */
+Lisp_Object Vdeferred_action_function;
+Lisp_Object Qdeferred_action_function;
+
/* File in which we write all commands we read. */
FILE *dribble;
/* Pointer to next place to store character in kbd_buffer. This
may be kbd_buffer + KBD_BUFFER_SIZE, meaning that the next
character should go in kbd_buffer[0]. */
-#ifdef __STDC__
-volatile
-#endif
-static struct input_event *kbd_store_ptr;
+static volatile struct input_event *kbd_store_ptr;
/* The above pair of variables forms a "queue empty" flag. When we
enqueue a non-hook event, we increment kbd_write_count. When we
dequeuing functions? Such a flag could be screwed up by interrupts
at inopportune times. */
-/* If this flag is non-zero, we check mouse_moved to see when the
- mouse moves, and motion events will appear in the input stream. If
- it is zero, mouse motion is ignored. */
-static int do_mouse_tracking;
+#ifdef HAVE_MOUSE
+/* If this flag is a frame, we check mouse_moved to see when the
+ mouse moves, and motion events will appear in the input stream.
+ Otherwise, mouse motion is ignored. */
+static Lisp_Object do_mouse_tracking;
/* The window system handling code should set this if the mouse has
moved since the last call to the mouse_position_hook. Calling that
is readable input; all the events in the queue might be button-up
events, and do_mouse_tracking might be off. */
#define EVENT_QUEUES_EMPTY \
- ((kbd_fetch_ptr == kbd_store_ptr) && (!do_mouse_tracking || !mouse_moved))
+ ((kbd_fetch_ptr == kbd_store_ptr) \
+ && (! FRAMEP (do_mouse_tracking) || !mouse_moved))
+#else /* Not HAVE_MOUSE. */
+#define EVENT_QUEUES_EMPTY (kbd_fetch_ptr == kbd_store_ptr)
+#endif /* HAVE_MOUSE. */
/* Symbols to head events. */
Lisp_Object Qmouse_movement;
Lisp_Object Qscroll_bar_movement;
Lisp_Object Qswitch_frame;
+Lisp_Object Qdelete_frame;
+Lisp_Object Qiconify_frame;
+Lisp_Object Qmake_frame_visible;
/* Symbols to denote kinds of events. */
Lisp_Object Qfunction_key;
/* If someone has passed us a composite event, use its head symbol. */
c = EVENT_HEAD (c);
- if (XTYPE (c) == Lisp_Int)
+ if (INTEGERP (c))
{
if (ptr - echobuf > sizeof echobuf - 6)
return;
ptr = push_key_description (XINT (c), ptr);
}
- else if (XTYPE (c) == Lisp_Symbol)
+ else if (SYMBOLP (c))
{
struct Lisp_String *name = XSYMBOL (c)->name;
if (((ptr - echobuf) + name->size + 4) > sizeof echobuf)
if (!immediate_echo && echoptr == echobuf)
return;
/* Do nothing if we just printed a prompt. */
- if (echo_after_prompt != echoptr - echobuf)
+ if (echo_after_prompt == echoptr - echobuf)
return;
/* Do nothing if not echoing at all. */
if (echoptr == 0)
}
echoing = 1;
- message1 (echobuf);
+ message2_nolog (echobuf, strlen (echobuf));
echoing = 0;
if (waiting_for_input && !NILP (Vquit_flag))
Lisp_Object
cmd_error (data)
Lisp_Object data;
+{
+ Vstandard_output = Qt;
+ Vstandard_input = Qt;
+ Vexecuting_macro = Qnil;
+ cmd_error_internal (data, 0);
+
+ Vquit_flag = Qnil;
+
+ Vinhibit_quit = Qnil;
+
+ return make_number (0);
+}
+
+cmd_error_internal (data, context)
+ Lisp_Object data;
+ char *context;
{
Lisp_Object errmsg, tail, errname, file_error;
Lisp_Object stream;
Vquit_flag = Qnil;
Vinhibit_quit = Qt;
- Vstandard_output = Qt;
- Vstandard_input = Qt;
- Vexecuting_macro = Qnil;
echo_area_glyphs = 0;
/* If the window system or terminal frame hasn't been initialized
stream = Qt;
}
+ if (context != 0)
+ write_string_1 (context, -1, stream);
+
errname = Fcar (data);
if (EQ (errname, Qerror))
if (!NILP (file_error) && !NILP (tail))
errmsg = XCONS (tail)->car, tail = XCONS (tail)->cdr;
- if (XTYPE (errmsg) == Lisp_String)
+ if (STRINGP (errmsg))
Fprinc (errmsg, stream);
else
write_string_1 ("peculiar error", -1, stream);
Fterpri (stream);
Fkill_emacs (make_number (-1));
}
-
- Vquit_flag = Qnil;
-
- Vinhibit_quit = Qnil;
- return make_number (0);
}
\f
Lisp_Object command_loop_1 ();
/* Make sure this hook runs after commands that get errors and
throw to top level. */
- if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
- safe_run_hooks (&Vpost_command_hook);
+ /* Note that the value cell will never directly contain nil
+ if the symbol is a local variable. */
+ if (!NILP (XSYMBOL (Qpost_command_hook)->value) && !NILP (Vrun_hooks))
+ safe_run_hooks (Qpost_command_hook);
+
+ if (!NILP (Vdeferred_action_list))
+ call0 (Vdeferred_action_function);
/* Do this after running Vpost_command_hook, for consistency. */
last_command = this_command;
switch-frame events will take care of this, but if some lisp
code swallows a switch-frame event, we'll fix things up here.
Is this a good idea? */
- if (XTYPE (internal_last_event_frame) == Lisp_Frame
+ if (FRAMEP (internal_last_event_frame)
&& XFRAME (internal_last_event_frame) != selected_frame)
Fselect_frame (internal_last_event_frame, Qnil);
#endif
prev_buffer = current_buffer;
prev_modiff = MODIFF;
last_point_position = PT;
- XSET (last_point_position_buffer, Lisp_Buffer, prev_buffer);
+ XSETBUFFER (last_point_position_buffer, prev_buffer);
/* Execute the command. */
this_command = cmd;
- if (!NILP (Vpre_command_hook) && !NILP (Vrun_hooks))
- safe_run_hooks (&Vpre_command_hook);
+ /* Note that the value cell will never directly contain nil
+ if the symbol is a local variable. */
+ if (!NILP (XSYMBOL (Qpre_command_hook)->value) && !NILP (Vrun_hooks))
+ safe_run_hooks (Qpre_command_hook);
if (NILP (this_command))
{
SET_PT (PT + 1);
if ((dp
? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
- && XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1)
+ ? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1
+ : (NILP (DISP_CHAR_VECTOR (dp, lose))
+ && (lose >= 0x20 && lose < 0x7f)))
: (lose >= 0x20 && lose < 0x7f))
&& (XFASTINT (XWINDOW (selected_window)->last_modified)
>= MODIFF)
lose = FETCH_CHAR (PT);
if ((dp
? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
- && XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1)
+ ? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1
+ : (NILP (DISP_CHAR_VECTOR (dp, lose))
+ && (lose >= 0x20 && lose < 0x7f)))
: (lose >= 0x20 && lose < 0x7f))
&& (XFASTINT (XWINDOW (selected_window)->last_modified)
>= MODIFF)
}
else if (EQ (this_command, Qself_insert_command)
/* Try this optimization only on ascii keystrokes. */
- && XTYPE (last_command_char) == Lisp_Int)
+ && INTEGERP (last_command_char))
{
unsigned char c = XINT (last_command_char);
+ int value;
- if (NILP (Vexecuting_macro) &&
- !EQ (minibuf_window, selected_window))
+ if (NILP (Vexecuting_macro)
+ && !EQ (minibuf_window, selected_window))
{
if (!nonundocount || nonundocount >= 20)
{
}
nonundocount++;
}
- lose = (XFASTINT (XWINDOW (selected_window)->last_modified)
- < MODIFF)
- || (XFASTINT (XWINDOW (selected_window)->last_point) != PT)
- || MODIFF <= current_buffer->save_modified
- || windows_or_buffers_changed
- || !EQ (current_buffer->selective_display, Qnil)
- || detect_input_pending ()
- || !NILP (Vexecuting_macro);
- if (internal_self_insert (c, 0))
- {
- lose = 1;
- nonundocount = 0;
- }
- if (!lose &&
- (PT == ZV || FETCH_CHAR (PT) == '\n'))
+ lose = ((XFASTINT (XWINDOW (selected_window)->last_modified)
+ < MODIFF)
+ || (XFASTINT (XWINDOW (selected_window)->last_point)
+ != PT)
+ || MODIFF <= SAVE_MODIFF
+ || windows_or_buffers_changed
+ || !EQ (current_buffer->selective_display, Qnil)
+ || detect_input_pending ()
+ || !NILP (Vexecuting_macro));
+ value = internal_self_insert (c, 0);
+ if (value)
+ lose = 1;
+ if (value == 2)
+ nonundocount = 0;
+
+ if (!lose
+ && (PT == ZV || FETCH_CHAR (PT) == '\n'))
{
struct Lisp_Vector *dp
= window_display_table (XWINDOW (selected_window));
if (lose >= 0x20 && lose <= 0x7e)
no_redisplay = direct_output_for_insert (lose);
}
- else if (XTYPE (obj) == Lisp_Vector
+ else if (VECTORP (obj)
&& XVECTOR (obj)->size == 1
- && (XTYPE (obj = XVECTOR (obj)->contents[0])
- == Lisp_Int)
+ && (obj = XVECTOR (obj)->contents[0],
+ INTEGERP (obj))
/* Insist face not specified in glyph. */
&& (XINT (obj) & ((-1) << 8)) == 0)
no_redisplay
}
directly_done: ;
- if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
- safe_run_hooks (&Vpost_command_hook);
+ /* Note that the value cell will never directly contain nil
+ if the symbol is a local variable. */
+ if (!NILP (XSYMBOL (Qpost_command_hook)->value) && !NILP (Vrun_hooks))
+ safe_run_hooks (Qpost_command_hook);
+
+ if (!NILP (Vdeferred_action_list))
+ safe_run_hooks (Qdeferred_action_function);
/* If there is a prefix argument,
1) We don't want last_command to be ``universal-argument''
to mysteriously evaporate. */
static void
safe_run_hooks (hook)
- Lisp_Object *hook;
+ Lisp_Object hook;
{
+ Lisp_Object value;
int count = specpdl_ptr - specpdl;
specbind (Qinhibit_quit, Qt);
- Vcommand_hook_internal = *hook;
- *hook = Qnil;
+ /* We read and set the variable with functions,
+ in case it's buffer-local. */
+ value = Vcommand_hook_internal = Fsymbol_value (hook);
+ Fset (hook, Qnil);
call1 (Vrun_hooks, Qcommand_hook_internal);
- *hook = Vcommand_hook_internal;
+ Fset (hook, value);
unbind_to (count, Qnil);
}
/* Nonzero means polling for input is temporarily suppressed. */
int poll_suppress_count;
-#ifdef POLL_FOR_INPUT
+/* Nonzero if polling_for_input is actually being used. */
int polling_for_input;
+#ifdef POLL_FOR_INPUT
+
/* Handle an alarm once each second and read pending input
so as to handle a C-g if it comces in. */
#endif
}
+/* Nonzero if we are using polling to handle input asynchronously. */
+
+int
+input_polling_used ()
+{
+#ifdef POLL_FOR_INPUT
+ return read_socket_hook && !interrupt_input;
+#else
+ return 0;
+#endif
+}
+
/* Turn off polling. */
stop_polling ()
Lisp_Object print_help ();
static Lisp_Object kbd_buffer_get_event ();
+static void record_char ();
/* read a character from the keyboard; call the redisplay if needed */
/* commandflag 0 means do not do auto-saving, but do do redisplay.
register Lisp_Object c;
int count;
jmp_buf save_jump;
+ int key_already_recorded = 0;
+ Lisp_Object also_record;
+ also_record = Qnil;
if (CONSP (Vunread_command_events))
{
if (unread_command_char != -1)
{
- XSET (c, Lisp_Int, unread_command_char);
+ XSETINT (c, unread_command_char);
unread_command_char = -1;
if (this_command_key_count == 0)
if (EQ (Vexecuting_macro, Qt)
|| executing_macro_index >= XFASTINT (Flength (Vexecuting_macro)))
{
- XSET (c, Lisp_Int, -1);
+ XSETINT (c, -1);
return c;
}
c = Faref (Vexecuting_macro, make_number (executing_macro_index));
- if (XTYPE (Vexecuting_macro) == Lisp_String
+ if (STRINGP (Vexecuting_macro)
&& (XINT (c) & 0x80))
- XFASTINT (c) = CHAR_META | (XINT (c) & ~0x80);
+ XSETFASTINT (c, CHAR_META | (XINT (c) & ~0x80));
executing_macro_index++;
if (_setjmp (getcjmp))
{
- XSET (c, Lisp_Int, quit_char);
+ XSETINT (c, quit_char);
#ifdef MULTI_FRAME
- XSET (internal_last_event_frame, Lisp_Frame, selected_frame);
+ XSETFRAME (internal_last_event_frame, selected_frame);
Vlast_event_frame = internal_last_event_frame;
#endif
/* If we report the quit char as an event,
{
c = read_char_minibuf_menu_prompt (commandflag, nmaps, maps);
if (! NILP (c))
- return c;
+ {
+ key_already_recorded = 1;
+ goto non_reread;
+ }
}
/* If in middle of key sequence and minibuffer not active,
jmp_buf temp;
save_getcjmp (temp);
Fdo_auto_save (Qnil, Qnil);
+ /* Hooks can actually change some buffers in auto save. */
+ redisplay ();
restore_getcjmp (temp);
}
/* Auto save if enough time goes by without input. */
if (commandflag != 0
&& num_nonmacro_input_chars > last_auto_save
- && XTYPE (Vauto_save_timeout) == Lisp_Int
+ && INTEGERP (Vauto_save_timeout)
&& XINT (Vauto_save_timeout) > 0)
{
Lisp_Object tem0;
consing going on to make it worthwhile. */
if (!detect_input_pending ()
&& consing_since_gc > gc_cons_threshold / 2)
- {
- Fgarbage_collect ();
- /* prepare_menu_bars isn't safe here, but it should
- also be unnecessary. */
- redisplay ();
- }
+ Fgarbage_collect ();
+ /* prepare_menu_bars isn't safe here, but it should
+ also be unnecessary. */
+ redisplay ();
}
}
}
}
/* Terminate Emacs in batch mode if at eof. */
- if (noninteractive && XTYPE (c) == Lisp_Int && XINT (c) < 0)
+ if (noninteractive && INTEGERP (c) && XINT (c) < 0)
Fkill_emacs (make_number (1));
- if (XTYPE (c) == Lisp_Int)
+ if (INTEGERP (c))
{
/* Add in any extra modifiers, where appropriate. */
if ((extra_keyboard_modifiers & CHAR_CTL)
start_polling ();
- /* Don't wipe the echo area for a trivial event. */
- if (XTYPE (c) != Lisp_Buffer)
- echo_area_glyphs = 0;
+ /* 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;
+
+ /* Wipe the echo area. */
+ echo_area_glyphs = 0;
/* Handle things that only apply to characters. */
- if (XTYPE (c) == Lisp_Int)
+ if (INTEGERP (c))
{
/* If kbd_buffer_get_event gave us an EOF, return that. */
if (XINT (c) == -1)
return c;
- if (XTYPE (Vkeyboard_translate_table) == Lisp_String
+ if (STRINGP (Vkeyboard_translate_table)
&& XSTRING (Vkeyboard_translate_table)->size > XFASTINT (c))
XSETINT (c, XSTRING (Vkeyboard_translate_table)->data[XFASTINT (c)]);
}
- total_keys++;
- XVECTOR (recent_keys)->contents[recent_keys_index] = c;
- if (++recent_keys_index >= NUM_RECENT_KEYS)
- recent_keys_index = 0;
-
- /* Write c to the dribble file. If c is a lispy event, write
- the event's symbol to the dribble file, in <brackets>. Bleaugh.
- If you, dear reader, have a better idea, you've got the source. :-) */
- if (dribble)
+ /* If this event is a mouse click in the menu bar,
+ return just menu-bar for now. Modify the mouse click event
+ so we won't do this twice, then queue it up. */
+ if (EVENT_HAS_PARAMETERS (c)
+ && CONSP (XCONS (c)->cdr)
+ && CONSP (EVENT_START (c))
+ && CONSP (XCONS (EVENT_START (c))->cdr))
{
- if (XTYPE (c) == Lisp_Int)
- putc (XINT (c), dribble);
- else
- {
- Lisp_Object dribblee;
+ Lisp_Object posn;
- /* If it's a structured event, take the event header. */
- dribblee = EVENT_HEAD (c);
+ posn = POSN_BUFFER_POSN (EVENT_START (c));
+ /* Handle menu-bar events:
+ insert the dummy prefix event `menu-bar'. */
+ if (EQ (posn, Qmenu_bar))
+ {
+ /* Change menu-bar to (menu-bar) as the event "position". */
+ POSN_BUFFER_POSN (EVENT_START (c)) = Fcons (posn, Qnil);
- if (XTYPE (dribblee) == Lisp_Symbol)
- {
- putc ('<', dribble);
- fwrite (XSYMBOL (dribblee)->name->data, sizeof (char),
- XSYMBOL (dribblee)->name->size,
- dribble);
- putc ('>', dribble);
- }
+ also_record = c;
+ Vunread_command_events = Fcons (c, Vunread_command_events);
+ c = posn;
}
-
- fflush (dribble);
}
- store_kbd_macro_char (c);
-
- num_nonmacro_input_chars++;
+ record_char (c);
+ if (! NILP (also_record))
+ record_char (also_record);
from_macro:
reread_first:
/* Don't echo mouse motion events. */
- if (! (EVENT_HAS_PARAMETERS (c)
- && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
- echo_char (c);
+ if (echo_keystrokes
+ && ! (EVENT_HAS_PARAMETERS (c)
+ && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
+ {
+ echo_char (c);
+ if (! NILP (also_record))
+ echo_char (also_record);
+ }
/* Record this character as part of the current key. */
add_command_key (c);
+ if (! NILP (also_record))
+ add_command_key (also_record);
/* Re-reading in the middle of a command */
reread:
Fcurrent_window_configuration (Qnil));
tem0 = Feval (Vhelp_form);
- if (XTYPE (tem0) == Lisp_String)
+ if (STRINGP (tem0))
internal_with_output_to_temp_buffer ("*Help*", print_help, tem0);
cancel_echoing ();
do
c = read_char (0, 0, 0, Qnil, 0);
- while (XTYPE (c) == Lisp_Buffer);
+ while (BUFFERP (c));
/* Remove the help from the frame */
unbind_to (count, Qnil);
prepare_menu_bars ();
cancel_echoing ();
do
c = read_char (0, 0, 0, Qnil, 0);
- while (XTYPE (c) == Lisp_Buffer);
+ while (BUFFERP (c));
}
}
return c;
}
+/* Record the input event C in various ways. */
+
+static void
+record_char (c)
+ Lisp_Object c;
+{
+ total_keys++;
+ XVECTOR (recent_keys)->contents[recent_keys_index] = c;
+ if (++recent_keys_index >= NUM_RECENT_KEYS)
+ recent_keys_index = 0;
+
+ /* Write c to the dribble file. If c is a lispy event, write
+ the event's symbol to the dribble file, in <brackets>. Bleaugh.
+ If you, dear reader, have a better idea, you've got the source. :-) */
+ if (dribble)
+ {
+ if (INTEGERP (c))
+ {
+ if (XUINT (c) < 0x100)
+ putc (XINT (c), dribble);
+ else
+ fprintf (dribble, " 0x%x", XUINT (c));
+ }
+ else
+ {
+ Lisp_Object dribblee;
+
+ /* If it's a structured event, take the event header. */
+ dribblee = EVENT_HEAD (c);
+
+ if (SYMBOLP (dribblee))
+ {
+ putc ('<', dribble);
+ fwrite (XSYMBOL (dribblee)->name->data, sizeof (char),
+ XSYMBOL (dribblee)->name->size,
+ dribble);
+ putc ('>', dribble);
+ }
+ }
+
+ fflush (dribble);
+ }
+
+ store_kbd_macro_char (c);
+
+ num_nonmacro_input_chars++;
+}
+
Lisp_Object
print_help (object)
Lisp_Object object;
{
+ struct buffer *old = current_buffer;
Fprinc (object, Qnil);
+ set_buffer_internal (XBUFFER (Vstandard_output));
+ call0 (intern ("help-mode"));
+ set_buffer_internal (old);
return Qnil;
}
}
\f
+#ifdef HAVE_MOUSE
+
/* Restore mouse tracking enablement. See Ftrack_mouse for the only use
of this function. */
+
static Lisp_Object
tracking_off (old_value)
Lisp_Object old_value;
{
- if (! XFASTINT (old_value))
+ do_mouse_tracking = old_value;
+ if (NILP (old_value))
{
- do_mouse_tracking = 0;
-
/* Redisplay may have been preempted because there was input
available, and it assumes it will be called again after the
input has been processed. If the only input available was
int count = specpdl_ptr - specpdl;
Lisp_Object val;
- XSET (val, Lisp_Int, do_mouse_tracking);
- record_unwind_protect (tracking_off, val);
+ record_unwind_protect (tracking_off, do_mouse_tracking);
if (!input_pending && !detect_input_pending ())
prepare_menu_bars ();
- do_mouse_tracking = 1;
+ XSETFRAME (do_mouse_tracking, selected_frame);
val = Fprogn (args);
return unbind_to (count, val);
}
+
+#endif /* HAVE_MOUSE */
\f
/* Low level keyboard/mouse input.
kbd_buffer_store_event places events in kbd_buffer, and
if (noninteractive)
{
c = getchar ();
- XSET (obj, Lisp_Int, c);
+ XSETINT (obj, c);
return obj;
}
{
Lisp_Object minus_one;
- XSET (minus_one, Lisp_Int, -1);
+ XSETINT (minus_one, -1);
wait_reading_process_input (0, 0, minus_one, 1);
if (!interrupt_input && EVENT_QUEUES_EMPTY)
#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);
+ /* Make an event (delete-frame (FRAME)). */
+ obj = Fcons (event->frame_or_window, Qnil);
+ obj = Fcons (Qdelete_frame, Fcons (obj, Qnil));
+ kbd_fetch_ptr = event + 1;
+ }
+ else if (event->kind == iconify_event)
+ {
+ /* Make an event (iconify-frame (FRAME)). */
+ obj = Fcons (event->frame_or_window, Qnil);
+ obj = Fcons (Qiconify_frame, Fcons (obj, Qnil));
+ kbd_fetch_ptr = event + 1;
+ }
+ else if (event->kind == deiconify_event)
+ {
+ /* Make an event (make-frame-visible (FRAME)). */
+ obj = Fcons (event->frame_or_window, Qnil);
+ obj = Fcons (Qmake_frame_visible, Fcons (obj, Qnil));
kbd_fetch_ptr = event + 1;
}
#endif
else if (event->kind == buffer_switch_event)
{
/* The value doesn't matter here; only the type is tested. */
- XSET (obj, Lisp_Buffer, current_buffer);
+ XSETBUFFER (obj, current_buffer);
kbd_fetch_ptr = event + 1;
}
/* Just discard these, by returning nil.
Lisp_Object focus;
frame = event->frame_or_window;
- if (XTYPE (frame) == Lisp_Window)
+ if (WINDOWP (frame))
frame = WINDOW_FRAME (XWINDOW (frame));
focus = FRAME_FOCUS_FRAME (XFRAME (frame));
}
}
}
+#ifdef HAVE_MOUSE
/* Try generating a mouse motion event. */
- else if (do_mouse_tracking && mouse_moved)
+ else if (FRAMEP (do_mouse_tracking) && mouse_moved)
{
- FRAME_PTR f = 0;
+ FRAME_PTR f = XFRAME (do_mouse_tracking);
Lisp_Object bar_window;
enum scroll_bar_part part;
Lisp_Object x, y;
unsigned long time;
+ /* Note that this uses F to determine which display to look at.
+ If there is no valid info, it does not store anything
+ so x remains nil. */
+ x = Qnil;
(*mouse_position_hook) (&f, &bar_window, &part, &x, &y, &time);
obj = Qnil;
/* Decide if we should generate a switch-frame event. Don't
generate switch-frame events for motion outside of all Emacs
frames. */
- if (f)
+ if (!NILP (x) && f)
{
Lisp_Object frame;
frame = FRAME_FOCUS_FRAME (f);
if (NILP (frame))
- XSET (frame, Lisp_Frame, f);
+ XSETFRAME (frame, f);
if (! EQ (frame, internal_last_event_frame)
&& XFRAME (frame) != selected_frame)
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))
+ if (!NILP (x) && NILP (obj))
obj = make_lispy_movement (f, bar_window, part, x, y, time);
-#endif
}
+#endif /* HAVE_MOUSE */
else
/* We were promised by the above while loop that there was
something for us to read! */
/* A simple keystroke. */
case ascii_keystroke:
{
+ Lisp_Object lispy_c;
int c = event->code & 0377;
/* Turn ASCII characters into control characters
when proper. */
& (meta_modifier | alt_modifier
| hyper_modifier | super_modifier));
button_down_time = 0;
- return c;
+ XSETFASTINT (lispy_c, c);
+ return lispy_c;
}
/* A function key. The symbol may need to have modifier prefixes
/ sizeof (lispy_function_keys[0])));
break;
-#if defined(MULTI_FRAME) || defined(HAVE_MOUSE)
+#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:
return Qnil;
pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
- &column, &row, 0, 0);
+ &column, &row, 0, 1);
-#ifdef USE_X_TOOLKIT
- if (FRAME_EXTERNAL_MENU_BAR (f) && XINT (event->y) == -1)
-#else
- if (row < FRAME_MENU_BAR_LINES (f))
-#endif
+#ifndef USE_X_TOOLKIT
+ /* In the non-toolkit version, clicks on the menu bar
+ are ordinary button events in the event buffer.
+ Distinguish them, and invoke the menu.
+
+ (In the toolkit version, the toolkit handles the menu bar
+ and Emacs doesn't know about it until after the user
+ makes a selection.) */
+ if (row >= 0 && row < FRAME_MENU_BAR_LINES (f))
{
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;
int i;
+ /* Activate the menu bar on the down event. If the
+ up event comes in before the menu code can deal with it,
+ just ignore it. */
+ if (! (event->modifiers & down_modifier))
+ return Qnil;
+
item = Qnil;
items = FRAME_MENU_BAR_ITEMS (f);
for (i = 0; i < XVECTOR (items)->size; i += 3)
break;
}
}
-#endif /* not USE_X_TOOLKIT */
position
= Fcons (event->frame_or_window,
return Fcons (item, Fcons (position, Qnil));
}
+#endif /* not USE_X_TOOLKIT */
window = window_from_coordinates (f, column, row, &part);
- if (XTYPE (window) != Lisp_Window)
- posn = Qnil;
+ if (!WINDOWP (window))
+ {
+ window = event->frame_or_window;
+ posn = Qnil;
+ }
else
{
int pixcolumn, pixrow;
else if (part == 2)
posn = Qvertical_line;
else
- XSET (posn, Lisp_Int,
- buffer_posn_from_coords (XWINDOW (window),
- column, row));
+ XSETINT (posn,
+ buffer_posn_from_coords (XWINDOW (window),
+ column, row));
}
position
of the button that chose the menu item
as a separate event. */
- if (XTYPE (start_pos) != Lisp_Cons)
+ if (!CONSP (start_pos))
return Qnil;
event->modifiers &= ~up_modifier;
#if 0 /* Formerly we treated an up with no down as a click event. */
- if (XTYPE (start_pos) != Lisp_Cons)
+ if (!CONSP (start_pos))
event->modifiers |= click_modifier;
else
#endif
if (EQ (event->x, XCONS (down)->car)
&& EQ (event->y, XCONS (down)->cdr))
{
- if (is_double && double_click_count > 1)
- event->modifiers |= ((double_click_count > 2)
- ? triple_modifier
- : double_modifier);
- else
- event->modifiers |= click_modifier;
+ event->modifiers |= click_modifier;
}
else
{
button_down_time = 0;
event->modifiers |= drag_modifier;
}
+ /* Don't check is_double; treat this as multiple
+ if the down-event was multiple. */
+ if (double_click_count > 1)
+ event->modifiers |= ((double_click_count > 2)
+ ? triple_modifier
+ : double_modifier);
}
}
else
}
}
-#ifdef MULTI_FRAME
+#if defined (MULTI_FRAME) || defined (HAVE_MOUSE)
static Lisp_Object
make_lispy_movement (frame, bar_window, part, x, y, time)
Lisp_Object x, y;
unsigned long time;
{
+#ifdef MULTI_FRAME
/* Is it a scroll bar movement? */
if (frame && ! NILP (bar_window))
{
/* Or is it an ordinary mouse movement? */
else
+#endif /* MULTI_FRAME */
{
int area;
Lisp_Object window;
Lisp_Object posn;
int column, row;
+#ifdef MULTI_FRAME
if (frame)
+#else
+ if (1)
+#endif
{
/* It's in a frame; which window on that frame? */
pixel_to_glyph_coords (frame, XINT (x), XINT (y), &column, &row, 0, 1);
else
window = Qnil;
- if (XTYPE (window) == Lisp_Window)
+ if (WINDOWP (window))
{
int pixcolumn, pixrow;
column -= XINT (XWINDOW (window)->left);
else if (area == 2)
posn = Qvertical_line;
else
- XSET (posn, Lisp_Int,
- buffer_posn_from_coords (XWINDOW (window), column, row));
+ XSETINT (posn,
+ buffer_posn_from_coords (XWINDOW (window), column, row));
}
+#ifdef MULTI_FRAME
else if (frame != 0)
{
- XSET (window, Lisp_Frame, frame);
+ XSETFRAME (window, frame);
posn = Qnil;
}
+#endif
else
{
window = Qnil;
posn = Qnil;
- XFASTINT (x) = 0;
- XFASTINT (y) = 0;
+ XSETFASTINT (x, 0);
+ XSETFASTINT (y, 0);
}
return Fcons (Qmouse_movement,
}
}
-#endif /* MULTI_FRAME */
+#endif /* neither MULTI_FRAME nor HAVE_MOUSE */
/* Construct a switch frame event. */
static Lisp_Object
if (modifiers & ~((1<<VALBITS) - 1))
abort ();
- XFASTINT (mask) = modifiers;
+ XSETFASTINT (mask, modifiers);
elements = Fcons (unmodified, Fcons (mask, Qnil));
/* Cache the parsing results on SYMBOL. */
/* The click modifier never figures into cache indices. */
cache = Fget (base, Qmodifier_cache);
- XFASTINT (index) = (modifiers & ~click_modifier);
- entry = Fassq (index, cache);
+ XSETFASTINT (index, (modifiers & ~click_modifier));
+ entry = assq_no_quit (index, cache);
if (CONSP (entry))
new_symbol = XCONS (entry)->cdr;
Fput (base, Qmodifier_cache, Fcons (entry, cache));
/* We have the parsing info now for free, so add it to the caches. */
- XFASTINT (index) = modifiers;
+ XSETFASTINT (index, modifiers);
Fput (new_symbol, Qevent_symbol_element_mask,
Fcons (base, Fcons (index, Qnil)));
Fput (new_symbol, Qevent_symbol_elements,
Lisp_Object value;
Lisp_Object symbol_int;
- XSET (symbol_int, Lisp_Int, symbol_num);
+ XSETINT (symbol_int, symbol_num);
/* Is this a request for a valid symbol? */
if (symbol_num < 0 || symbol_num >= table_size)
{
Lisp_Object size;
- XFASTINT (size) = table_size;
+ XSETFASTINT (size, table_size);
*symbol_table = Fmake_vector (size, Qnil);
}
*addr = !NILP (Vquit_flag) || readable_events ();
}
-/* Interface to read_avail_input, blocking SIGIO if necessary. */
+/* Interface to read_avail_input, blocking SIGIO or SIGALRM if necessary. */
int
gobble_input (expected)
sigsetmask (mask);
}
else
+#ifdef POLL_FOR_INPUT
+ if (read_socket_hook && !interrupt_input && poll_suppress_count == 0)
+ {
+ SIGMASKTYPE mask;
+ mask = sigblockx (SIGALRM);
+ read_avail_input (expected);
+ sigsetmask (mask);
+ }
+ else
+#endif
#endif
read_avail_input (expected);
#endif
record_asynch_buffer_change ()
{
struct input_event event;
+ Lisp_Object tem;
+
event.kind = buffer_switch_event;
event.frame_or_window = Qnil;
+#ifdef subprocesses
+ /* We don't need a buffer-switch event unless Emacs is waiting for input.
+ The purpose of the event is to make read_key_sequence look up the
+ keymaps again. If we aren't in read_key_sequence, we don't need one,
+ and the event could cause trouble by messing up (input-pending-p). */
+ tem = Fwaiting_for_user_input_p ();
+ if (NILP (tem))
+ return;
+#else
+ /* We never need these events if we have no asynchronous subprocesses. */
+ return;
+#endif
+
/* Make sure no interrupt happens while storing the event. */
#ifdef SIGIO
if (interrupt_input)
if (read_socket_hook)
/* No need for FIONREAD or fcntl; just say don't wait. */
- nread = (*read_socket_hook) (0, buf, KBD_BUFFER_SIZE, expected, expected);
+ nread = (*read_socket_hook) (input_fd, buf, KBD_BUFFER_SIZE,
+ expected, expected);
else
{
/* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
int n_to_read;
/* Determine how many characters we should *try* to read. */
+#ifdef WINDOWSNT
+ return 0;
+#else /* not WINDOWSNT */
#ifdef MSDOS
n_to_read = dos_keysns ();
if (n_to_read == 0)
#else /* not MSDOS */
#ifdef FIONREAD
/* Find out how much input is available. */
- if (ioctl (0, FIONREAD, &n_to_read) < 0)
+ if (ioctl (input_fd, 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. */
#if defined(USG) || defined(DGUX)
/* Read some input if available, but don't wait. */
n_to_read = sizeof cbuf;
- fcntl (fileno (stdin), F_SETFL, O_NDELAY);
+ fcntl (input_fd, F_SETFL, O_NDELAY);
#else
you lose;
#endif
#endif
#endif /* not MSDOS */
+#endif /* not WINDOWSNT */
/* Now read; for one reason or another, this will not block.
NREAD is set to the number of chars read. */
cbuf[0] = dos_keyread();
nread = 1;
#else
- nread = read (fileno (stdin), cbuf, n_to_read);
+ nread = read (input_fd, cbuf, n_to_read);
#endif
#if defined (AIX) && (! defined (aix386) && defined (_BSD))
/* The kernel sometimes fails to deliver SIGHUP for ptys.
#ifndef FIONREAD
#if defined (USG) || defined (DGUX)
- fcntl (fileno (stdin), F_SETFL, 0);
+ fcntl (input_fd, F_SETFL, 0);
#endif /* USG or DGUX */
#endif /* no FIONREAD */
for (i = 0; i < nread; i++)
buf[i].modifiers = meta_modifier;
if (meta_key != 2)
cbuf[i] &= ~0x80;
-
- XSET (buf[i].code, Lisp_Int, cbuf[i]);
+
+ buf[i].code = cbuf[i];
#ifdef MULTI_FRAME
- XSET (buf[i].frame_or_window, Lisp_Frame, selected_frame);
+ XSETFRAME (buf[i].frame_or_window, selected_frame);
#else
buf[i].frame_or_window = Qnil;
#endif
/* Don't look at input that follows a C-g too closely.
This reduces lossage due to autorepeat on C-g. */
if (buf[i].kind == ascii_keystroke
- && XINT(buf[i].code) == quit_char)
+ && buf[i].code == quit_char)
break;
}
{
register Lisp_Object tem;
tem = Fcar (map);
- if (XTYPE (tem) == Lisp_String)
+ if (STRINGP (tem))
return tem;
map = Fcdr (map);
}
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;
+static int 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:
{
Lisp_Object *tmaps;
- if (!NILP (Voverriding_local_map))
+ /* Should overriding-local-map apply, here? */
+ if (!NILP (Voverriding_local_map_menu_flag))
{
- nmaps = 2;
- maps = (Lisp_Object *) alloca (nmaps * sizeof (maps[0]));
- maps[0] = Voverriding_local_map;
+ if (NILP (Voverriding_local_map))
+ {
+ /* Yes, and it is nil. Use just global map. */
+ nmaps = 1;
+ maps = (Lisp_Object *) alloca (nmaps * sizeof (maps[0]));
+ }
+ else
+ {
+ /* Yes, and it is non-nil. Use it and the global map. */
+ nmaps = 2;
+ maps = (Lisp_Object *) alloca (nmaps * sizeof (maps[0]));
+ maps[0] = Voverriding_local_map;
+ }
}
else
{
+ /* No, so use major and minor mode keymaps. */
nmaps = current_minor_maps (0, &tmaps) + 2;
maps = (Lisp_Object *) alloca (nmaps * sizeof (maps[0]));
bcopy (tmaps, maps, (nmaps - 2) * sizeof (maps[0]));
Lisp_Object tail, item, key, binding, item_string, table;
/* Loop over all keymap entries that have menu strings. */
- for (tail = keymap; XTYPE (tail) == Lisp_Cons; tail = XCONS (tail)->cdr)
+ for (tail = keymap; CONSP (tail); tail = XCONS (tail)->cdr)
{
item = XCONS (tail)->car;
- if (XTYPE (item) == Lisp_Cons)
+ if (CONSP (item))
{
key = XCONS (item)->car;
binding = XCONS (item)->cdr;
- if (XTYPE (binding) == Lisp_Cons)
+ if (CONSP (binding))
{
item_string = XCONS (binding)->car;
- if (XTYPE (item_string) == Lisp_String)
+ if (STRINGP (item_string))
menu_bar_item (key, item_string, Fcdr (binding));
}
else if (EQ (binding, Qundefined))
menu_bar_item (key, Qnil, binding);
}
- else if (XTYPE (item) == Lisp_Vector)
+ else if (VECTORP (item))
{
/* Loop over the char values represented in the vector. */
int len = XVECTOR (item)->size;
for (c = 0; c < len; c++)
{
Lisp_Object character;
- XFASTINT (character) = c;
+ XSETFASTINT (character, c);
binding = XVECTOR (item)->contents[c];
- if (XTYPE (binding) == Lisp_Cons)
+ if (CONSP (binding))
{
item_string = XCONS (binding)->car;
- if (XTYPE (item_string) == Lisp_String)
+ if (STRINGP (item_string))
menu_bar_item (key, item_string, Fcdr (binding));
}
else if (EQ (binding, Qundefined))
/* See if this entry is enabled. */
enabled = Qt;
- if (XTYPE (def) == Lisp_Symbol)
+ if (SYMBOLP (def))
{
/* No property, or nil, means enable.
Otherwise, enable if value is not nil. */
if (! menu_prompting)
return Qnil;
+ /* Optionally disregard all but the global map. */
+ if (inhibit_local_menu_bar_menus)
+ {
+ maps += (nmaps - 1);
+ nmaps = 1;
+ }
+
/* Get the menu name from the first map that has one (a prompt string). */
for (mapno = 0; mapno < nmaps; mapno++)
{
if (mapno >= nmaps)
return Qnil;
-#ifdef HAVE_X_WINDOWS
-#ifdef HAVE_X_MENU
+#if (defined (HAVE_X_WINDOWS) && defined (HAVE_X_MENU)) || defined (MSDOS)
/* If we got to this point via a mouse click,
use a real menu for mouse selection. */
if (EVENT_HAS_PARAMETERS (prev_event))
*used_mouse_menu = 1;
return value;
}
-#endif /* HAVE_X_MENU */
-#endif /* HAVE_X_WINDOWS */
+#endif /* (HAVE_X_WINDOWS && HAVE_X_MENU) || MSDOS */
return Qnil ;
}
else
elt = Fcar_safe (rest);
- if (idx < 0 && XTYPE (elt) == Lisp_Vector)
+ if (idx < 0 && VECTORP (elt))
{
/* If we found a dense table in the keymap,
advanced past it, but start scanning its contents. */
s = Fcar_safe (Fcdr_safe (elt)); /* alist */
else
s = Fcar_safe(elt); /* vector */
- if (XTYPE (s) != Lisp_String)
+ if (!STRINGP (s))
/* Ignore the element if it has no prompt string. */
;
/* If we have room for the prompt string, add it to this line.
defining_kbd_macro = 0 ;
do
obj = read_char (commandflag, 0, 0, Qnil, 0);
- while (XTYPE (obj) == Lisp_Buffer);
+ while (BUFFERP (obj));
defining_kbd_macro = orig_defn_macro ;
- if (XTYPE (obj) != Lisp_Int)
+ if (!INTEGERP (obj))
return obj;
else
ch = XINT (obj);
if (! EQ (obj, menu_prompt_more_char)
- && (XTYPE (menu_prompt_more_char) != Lisp_Int
+ && (!INTEGERP (menu_prompt_more_char)
|| ! EQ (obj, make_number (Ctl (XINT (menu_prompt_more_char))))))
{
if ( defining_kbd_macro )
CURRENT with non-prefix bindings for meta-prefix-char become nil in
NEXT.
- 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, case_converted)
+follow_key (key, nmaps, current, defs, next)
Lisp_Object key;
Lisp_Object *current, *defs, *next;
int nmaps;
- int *case_converted;
{
int i, first_binding;
/* If KEY is a meta ASCII character, treat it like meta-prefix-char
followed by the corresponding non-meta character. */
- if (XTYPE (key) == Lisp_Int && (XINT (key) & CHAR_META))
+ if (INTEGERP (key) && (XINT (key) & CHAR_META))
{
for (i = 0; i < nmaps; i++)
if (! NILP (current[i]))
next[i] = Qnil;
current = next;
- XSET (key, Lisp_Int, XFASTINT (key) & ~CHAR_META);
+ XSETINT (key, XFASTINT (key) & ~CHAR_META);
}
first_binding = nmaps;
defs[i] = Qnil;
}
- /* 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. */
- if (first_binding == nmaps
- && XTYPE (key) == Lisp_Int
- && ((((XINT (key) & 0x3ffff)
- < XSTRING (current_buffer->downcase_table)->size)
- && UPPERCASEP (XINT (key) & 0x3ffff))
- || (XINT (key) & shift_modifier)))
- {
- if (XINT (key) & shift_modifier)
- XSETINT (key, XINT (key) & ~shift_modifier);
- else
- XSETINT (key, (DOWNCASE (XINT (key) & 0x3ffff)
- | (XINT (key) & ~0x3ffff)));
-
- first_binding = nmaps;
- for (i = nmaps - 1; i >= 0; i--)
- {
- if (! NILP (current[i]))
- {
- defs[i] = get_keyelt (access_keymap (current[i], key, 1, 0));
- if (! NILP (defs[i]))
- first_binding = i;
- }
- 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. */
if (first_binding < nmaps)
for (i = 0; i < nmaps; i++)
in the current keymaps, or nil where it is not a prefix. */
Lisp_Object *submaps;
+ /* The local map to start out with at start of key sequence. */
+ Lisp_Object orig_local_map;
+
+ /* 1 if we have already considered switching to the local-map property
+ of the place where a mouse click occurred. */
+ int localized_local_map = 0;
+
/* The index in defs[] of the first keymap that has a binding for
this key sequence. In other words, the lowest i such that
defs[i] is non-nil. */
Lisp_Object first_event;
#endif
- struct buffer *starting_buffer;
+ /* Gets around Microsoft compiler limitations. */
+ int dummyFlag = 0;
- /* Nonzero if we found the binding for one of the chars
- in this key sequence by downcasing it. */
- int case_converted = 0;
+ struct buffer *starting_buffer;
/* Nonzero if we seem to have got the beginning of a binding
in function_key_map. */
int function_key_possible = 0;
+ int key_translation_possible = 0;
int junk;
{
if (!NILP (prompt))
echo_prompt (XSTRING (prompt)->data);
- else if (cursor_in_echo_area)
+ else if (cursor_in_echo_area && echo_keystrokes)
/* This doesn't put in a dash if the echo buffer is empty, so
you don't always see a dash hanging out in the minibuffer. */
echo_dash ();
&junk);
#endif /* GOBBLE_FIRST_EVENT */
+ orig_local_map = get_local_map (PT, current_buffer);
+
/* We jump here when the key sequence has been thoroughly changed, and
we need to rescan it starting from the beginning. When we jump here,
keybuf[0..mock_input] holds the sequence we should reread. */
replay_sequence:
starting_buffer = current_buffer;
- case_converted = 0;
function_key_possible = 0;
+ key_translation_possible = 0;
/* Build our list of keymaps.
If we recognize a function key and replace its escape sequence in
}
bcopy (maps, submaps, (nmaps - 2) * sizeof (submaps[0]));
#ifdef USE_TEXT_PROPERTIES
- submaps[nmaps-2] = get_local_map (PT, current_buffer);
+ submaps[nmaps-2] = orig_local_map;
#else
submaps[nmaps-2] = current_buffer->keymap;
#endif
&& fkey_start < t
/* mock input is never part of a function key's sequence. */
&& mock_input <= fkey_start)
- || (first_binding >= nmaps
- && keytran_start < t
- /* mock input is never part of a function key's sequence. */
- && mock_input <= keytran_start)
+ || (keytran_start < t && key_translation_possible)
/* 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;
{
key = keybuf[t];
add_command_key (key);
- echo_char (key);
+ if (echo_keystrokes)
+ echo_char (key);
}
/* If not, we should actually read a character. */
/* read_char returns -1 at the end of a macro.
Emacs 18 handles this by returning immediately with a
zero, so that's what we'll do. */
- if (XTYPE (key) == Lisp_Int && XINT (key) == -1)
+ if (INTEGERP (key) && XINT (key) == -1)
{
t = 0;
- goto done;
+ /* The Microsoft C compiler can't handle the goto that
+ would go here. */
+ dummyFlag = 1;
+ break;
}
/* If the current buffer has been changed from under us, the
keymap may have changed, so replay the sequence. */
- if (XTYPE (key) == Lisp_Buffer)
+ if (BUFFERP (key))
{
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. */
- if (EQ (key, quit_char) && current_buffer != starting_buffer)
+ if (XINT (key) == quit_char && current_buffer != starting_buffer)
{
keybuf[t++] = key;
mock_input = t;
window = POSN_WINDOW (EVENT_START (key));
posn = POSN_BUFFER_POSN (EVENT_START (key));
- if (XTYPE (posn) == Lisp_Cons)
+ if (CONSP (posn))
{
/* We're looking at the second event of a
sequence which we expanded before. Set
not the current buffer. If we're at the
beginning of a key sequence, switch buffers. */
if (last_real_key_start == 0
- && XTYPE (window) == Lisp_Window
- && XTYPE (XWINDOW (window)->buffer) == Lisp_Buffer
+ && WINDOWP (window)
+ && BUFFERP (XWINDOW (window)->buffer)
&& XBUFFER (XWINDOW (window)->buffer) != current_buffer)
{
keybuf[t] = key;
record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
+ orig_local_map = get_local_map (PT, current_buffer);
goto replay_sequence;
}
- else if (XTYPE (posn) == Lisp_Symbol)
+ /* For a mouse click, get the local text-property keymap
+ of the place clicked on, rather than point. */
+ if (last_real_key_start == 0 && CONSP (XCONS (key)->cdr)
+ && ! localized_local_map)
{
- /* Expand mode-line and scroll-bar events into two events:
- use posn as a fake prefix key. */
+ Lisp_Object map_here, start, pos;
+
+ localized_local_map = 1;
+ start = EVENT_START (key);
+ if (CONSP (start) && CONSP (XCONS (start)->cdr))
+ {
+ pos = POSN_BUFFER_POSN (start);
+ if (INTEGERP (pos))
+ {
+ map_here = get_local_map (XINT (pos), current_buffer);
+ if (!EQ (map_here, orig_local_map))
+ {
+ orig_local_map = map_here;
+ keybuf[t] = key;
+ mock_input = t + 1;
+
+ goto replay_sequence;
+ }
+ }
+ }
+ }
+ /* Expand mode-line and scroll-bar events into two events:
+ use posn as a fake prefix key. */
+ if (SYMBOLP (posn))
+ {
if (t + 1 >= bufsize)
error ("key sequence too long");
keybuf[t] = posn;
mock_input = t + 2;
goto replay_sequence;
}
- else if (XTYPE (posn) == Lisp_Cons)
+ else if (CONSP (posn))
{
/* We're looking at the second event of a
sequence which we expanded before. Set
nmaps - first_binding,
submaps + first_binding,
defs + first_binding,
- submaps + first_binding,
- &case_converted)
+ submaps + first_binding)
+ first_binding);
/* If KEY wasn't bound, we'll try some fallbacks. */
read_key_sequence_cmd = Vprefix_help_command;
keybuf[t++] = key;
last_nonmenu_event = key;
- goto done;
+ /* The Microsoft C compiler can't handle the goto that
+ would go here. */
+ dummyFlag = 1;
}
- if (XTYPE (head) == Lisp_Symbol)
+ if (SYMBOLP (head))
{
Lisp_Object breakdown;
int modifiers;
Lisp_Object new_head, new_click;
if (modifiers & triple_modifier)
modifiers ^= (double_modifier | triple_modifier);
- else if (modifiers & (drag_modifier | double_modifier))
- modifiers &= ~(drag_modifier | double_modifier);
+ else if (modifiers & double_modifier)
+ modifiers &= ~double_modifier;
+ else if (modifiers & drag_modifier)
+ modifiers &= ~drag_modifier;
else
{
/* Dispose of this `down' event by simply jumping
nmaps - local_first_binding,
submaps + local_first_binding,
defs + local_first_binding,
- submaps + local_first_binding,
- &case_converted)
+ submaps + local_first_binding)
+ 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 || case_converted)
+ if (first_binding >= nmaps
&& t >= mock_input)
{
Lisp_Object fkey_next;
key = keybuf[fkey_end++];
/* Look up meta-characters by prefixing them
with meta_prefix_char. I hate this. */
- if (XTYPE (key) == Lisp_Int && XINT (key) & meta_modifier)
+ if (INTEGERP (key) && XINT (key) & meta_modifier)
{
fkey_next
= get_keymap_1
(get_keyelt
(access_keymap (fkey_map, meta_prefix_char, 1, 0)),
0, 1);
- XFASTINT (key) = XFASTINT (key) & ~meta_modifier;
+ XSETFASTINT (key, XFASTINT (key) & ~meta_modifier);
}
else
fkey_next = fkey_map;
int i;
for (i = 0; i < len; i++)
- XFASTINT (keybuf[fkey_start + i])
- = XSTRING (fkey_next)->data[i];
+ XSETFASTINT (keybuf[fkey_start + i],
+ XSTRING (fkey_next)->data[i]);
}
mock_input = t;
fkey_start = fkey_end = t;
fkey_map = Vfunction_key_map;
+ /* Do pass the results through key-translation-map. */
+ keytran_start = keytran_end = 0;
+ keytran_map = Vkey_translation_map;
+
goto replay_sequence;
}
key = keybuf[keytran_end++];
/* Look up meta-characters by prefixing them
with meta_prefix_char. I hate this. */
- if (XTYPE (key) == Lisp_Int && XINT (key) & meta_modifier)
+ if (INTEGERP (key) && XINT (key) & meta_modifier)
{
keytran_next
= get_keymap_1
(get_keyelt
(access_keymap (keytran_map, meta_prefix_char, 1, 0)),
0, 1);
- XFASTINT (key) = XFASTINT (key) & ~meta_modifier;
+ XSETFASTINT (key, XFASTINT (key) & ~meta_modifier);
}
else
keytran_next = keytran_map;
error ("Function in key-translation-map returns invalid key sequence");
}
+ key_translation_possible = ! NILP (keytran_next);
+
/* If keybuf[keytran_start..keytran_end] is bound in the
key translation map and it's a suffix of the current
sequence (i.e. keytran_end == t), replace it with
int i;
for (i = 0; i < len; i++)
- XFASTINT (keybuf[keytran_start + i])
- = XSTRING (keytran_next)->data[i];
+ XSETFASTINT (keybuf[keytran_start + i],
+ XSTRING (keytran_next)->data[i]);
}
mock_input = t;
keytran_start = keytran_end = t;
keytran_map = Vkey_translation_map;
+ /* Don't pass the results of key-translation-map
+ through function-key-map. */
+ fkey_start = fkey_end = t;
+ fkey_map = Vkey_translation_map;
+
goto replay_sequence;
}
{
keytran_end = ++keytran_start;
keytran_map = Vkey_translation_map;
+ key_translation_possible = 0;
}
}
}
+
+ /* If KEY is not defined in any of the keymaps,
+ and cannot be part of a function key or translation,
+ and is an upper case letter
+ use the corresponding lower-case letter instead. */
+ if (first_binding == nmaps && ! function_key_possible
+ && ! key_translation_possible
+ && INTEGERP (key)
+ && ((((XINT (key) & 0x3ffff)
+ < XSTRING (current_buffer->downcase_table)->size)
+ && UPPERCASEP (XINT (key) & 0x3ffff))
+ || (XINT (key) & shift_modifier)))
+ {
+ if (XINT (key) & shift_modifier)
+ XSETINT (key, XINT (key) & ~shift_modifier);
+ else
+ XSETINT (key, (DOWNCASE (XINT (key) & 0x3ffff)
+ | (XINT (key) & ~0x3ffff)));
+
+ keybuf[t - 1] = key;
+ mock_input = t;
+ goto replay_sequence;
+ }
+ /* If KEY is not defined in any of the keymaps,
+ and cannot be part of a function key or translation,
+ and is a shifted function key,
+ use the corresponding unshifted function key instead. */
+ if (first_binding == nmaps && ! function_key_possible
+ && ! key_translation_possible
+ && SYMBOLP (key))
+ {
+ Lisp_Object breakdown;
+ int modifiers;
+
+ breakdown = parse_modifiers (key);
+ modifiers = XINT (XCONS (XCONS (breakdown)->cdr)->car);
+ if (modifiers & shift_modifier)
+ {
+ modifiers &= ~shift_modifier;
+ key = apply_modifiers (make_number (modifiers),
+ XCONS (breakdown)->car);
+
+ keybuf[t - 1] = key;
+ mock_input = t;
+ goto replay_sequence;
+ }
+ }
}
- read_key_sequence_cmd = (first_binding < nmaps
- ? defs[first_binding]
- : Qnil);
+ if (!dummyFlag)
+ read_key_sequence_cmd = (first_binding < nmaps
+ ? defs[first_binding]
+ : Qnil);
- done:
unread_switch_frame = delayed_switch_frame;
unbind_to (count, Qnil);
Better ideas? */
for (; t < mock_input; t++)
{
- echo_char (keybuf[t]);
+ if (echo_keystrokes)
+ echo_char (keybuf[t]);
add_command_key (keybuf[t]);
}
Vcurrent_prefix_arg = prefixarg;
debug_on_next_call = 0;
- if (XTYPE (cmd) == Lisp_Symbol)
+ if (SYMBOLP (cmd))
{
tem = Fget (cmd, Qdisabled);
if (!NILP (tem) && !NILP (Vrun_hooks))
break;
}
- if (XTYPE (final) == Lisp_String
- || XTYPE (final) == Lisp_Vector)
+ if (STRINGP (final) || VECTORP (final))
{
/* If requested, place the macro in the command history. For
other sorts of commands, call-interactively takes care of
return Fexecute_kbd_macro (final, prefixarg);
}
- if (CONSP (final) || XTYPE (final) == Lisp_Subr
- || XTYPE (final) == Lisp_Compiled)
+ if (CONSP (final) || SUBRP (final) || COMPILEDP (final))
{
backtrace.next = backtrace_list;
backtrace_list = &backtrace;
strcpy (buf, "- ");
else if (CONSP (prefixarg) && XINT (XCONS (prefixarg)->car) == 4)
strcpy (buf, "C-u ");
- else if (CONSP (prefixarg) && XTYPE (XCONS (prefixarg)->car) == Lisp_Int)
+ else if (CONSP (prefixarg) && INTEGERP (XCONS (prefixarg)->car))
sprintf (buf, "%d ", XINT (XCONS (prefixarg)->car));
- else if (XTYPE (prefixarg) == Lisp_Int)
+ else if (INTEGERP (prefixarg))
sprintf (buf, "%d ", XINT (prefixarg));
/* This isn't strictly correct if execute-extended-command
str = XSTRING (function);
for (i = 0; i < str->size; i++)
{
- XFASTINT (tem) = str->data[i];
+ XSETFASTINT (tem, str->data[i]);
add_command_key (tem);
}
- XFASTINT (tem) = '\015';
+ XSETFASTINT (tem, '\015');
add_command_key (tem);
}
()
{
Lisp_Object temp;
- XFASTINT (temp) = command_loop_level + minibuf_level;
+ XSETFASTINT (temp, command_loop_level + minibuf_level);
return temp;
}
{
if (NILP (file))
{
- fclose (dribble);
- dribble = 0;
+ if (dribble)
+ {
+ fclose (dribble);
+ dribble = 0;
+ }
}
else
{
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\
-Before suspending, call the functions in `suspend-hook' with no args.\n\
-If any of them returns nil, don't call the rest and don't suspend.\n\
-Otherwise, suspend normally and after resumption run the normal hook\n\
-`suspend-resume-hook' if that is bound and non-nil.\n\
+Before suspending, run the normal hook `suspend-hook'.\n\
+After resumption run the normal hook `suspend-resume-hook'.\n\
\n\
Some operating systems cannot stop the Emacs process and resume it later.\n\
On such systems, Emacs starts a subshell instead of suspending.")
/* stuff_char works only in BSD, versions 4.2 and up. */
#ifdef BSD
#ifndef BSD4_1
- if (XTYPE (stuffstring) == Lisp_String)
+ if (STRINGP (stuffstring))
{
register int count;
abort ();
#endif
#ifdef MULTI_FRAME
- if (XTYPE (internal_last_event_frame) == Lisp_Frame
+ if (FRAMEP (internal_last_event_frame)
&& XFRAME (internal_last_event_frame) != selected_frame)
Fhandle_switch_frame (make_lispy_switch_frame (internal_last_event_frame));
#endif
Lisp_Object interrupt, flow, meta, quit;
{
if (!NILP (quit)
- && (XTYPE (quit) != Lisp_Int
- || XINT (quit) < 0 || XINT (quit) > 0400))
+ && (!INTEGERP (quit) || XINT (quit) < 0 || XINT (quit) > 0400))
error ("set-input-mode: QUIT must be an ASCII character");
#ifdef POLL_FOR_INPUT
val[0] = interrupt_input ? Qt : Qnil;
val[1] = flow_control ? Qt : Qnil;
val[2] = meta_key == 2 ? make_number (0) : meta_key == 1 ? Qt : Qnil;
- XFASTINT (val[3]) = quit_char;
+ XSETFASTINT (val[3], quit_char);
return Flist (sizeof (val) / sizeof (val[0]), val);
}
recent_keys_index = 0;
kbd_fetch_ptr = kbd_buffer;
kbd_store_ptr = kbd_buffer;
- do_mouse_tracking = 0;
+#ifdef HAVE_MOUSE
+ do_mouse_tracking = Qnil;
+#endif
input_pending = 0;
#ifdef MULTI_FRAME
&Qmouse_movement, "mouse-movement", &Qmouse_movement,
&Qscroll_bar_movement, "scroll-bar-movement", &Qmouse_movement,
&Qswitch_frame, "switch-frame", &Qswitch_frame,
+ &Qdelete_frame, "delete-frame", &Qdelete_frame,
+ &Qiconify_frame, "iconify-frame", &Qiconify_frame,
+ &Qmake_frame_visible, "make-frame-visible", &Qmake_frame_visible,
};
syms_of_keyboard ()
Qpost_command_hook = intern ("post-command-hook");
staticpro (&Qpost_command_hook);
+ Qdeferred_action_function = intern ("deferred-action-function");
+ staticpro (&Qdeferred_action_function);
+
Qcommand_hook_internal = intern ("command-hook-internal");
staticpro (&Qcommand_hook_internal);
defsubr (&Sread_key_sequence);
defsubr (&Srecursive_edit);
+#ifdef HAVE_MOUSE
defsubr (&Strack_mouse);
+#endif
defsubr (&Sinput_pending_p);
defsubr (&Scommand_execute);
defsubr (&Srecent_keys);
DEFVAR_LISP ("last-command-char", &last_command_char,
"Last input event that was part of a command.");
- DEFVAR_LISP ("last-command-event", &last_command_char,
+ DEFVAR_LISP_NOPRO ("last-command-event", &last_command_char,
"Last input event that was part of a command.");
DEFVAR_LISP ("last-nonmenu-event", &last_nonmenu_event,
DEFVAR_LISP ("last-input-char", &last_input_char,
"Last input event.");
- DEFVAR_LISP ("last-input-event", &last_input_char,
+ DEFVAR_LISP_NOPRO ("last-input-event", &last_input_char,
"Last input event.");
DEFVAR_LISP ("unread-command-events", &Vunread_command_events,
DEFVAR_LISP ("meta-prefix-char", &meta_prefix_char,
"Meta-prefix character code. Meta-foo as command input\n\
turns into this character followed by foo.");
- XSET (meta_prefix_char, Lisp_Int, 033);
+ XSETINT (meta_prefix_char, 033);
DEFVAR_LISP ("last-command", &last_command,
"The last command executed. Normally a symbol with a function definition,\n\
but can be whatever was found in the keymap, or whatever the variable\n\
-`this-command' was set to by that command.");
+`this-command' was set to by that command.\n\
+\n\
+The value `mode-exit' is special; it means that the previous command\n\
+read an event that told it to exit, and it did so and unread that event.\n\
+In other words, the present command is the event that made the previous\n\
+command exit.\n\
+\n\
+The value `kill-region' is special; it means that the previous command\n\
+was a kill command.");
last_command = Qnil;
DEFVAR_LISP ("this-command", &this_command,
Zero or nil means disable auto-saving due to idleness.\n\
After auto-saving due to this many seconds of idle time,\n\
Emacs also does a garbage collection if that seems to be warranted.");
- XFASTINT (Vauto_save_timeout) = 30;
+ XSETFASTINT (Vauto_save_timeout, 30);
DEFVAR_INT ("echo-keystrokes", &echo_keystrokes,
"*Nonzero means echo unfinished commands after this many seconds of pause.");
by position only.");
Vdouble_click_time = make_number (500);
+ DEFVAR_BOOL ("inhibit-local-menu-bar-menus", &inhibit_local_menu_bar_menus,
+ "*Non-nil means inhibit local map menu bar menus.");
+ inhibit_local_menu_bar_menus = 0;
+
DEFVAR_INT ("num-input-keys", &num_input_keys,
- "*Number of complete keys read from the keyboard so far.");
+ "Number of complete keys read from the keyboard so far.");
num_input_keys = 0;
DEFVAR_LISP ("last-event-frame", &Vlast_event_frame,
- "*The frame in which the most recently read event occurred.\n\
+ "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;
"Character to recognize as meaning Help.\n\
When it is read, do `(eval help-form)', and display result if it's a string.\n\
If the value of `help-form' is nil, this char can be read normally.");
- XSET (Vhelp_char, Lisp_Int, Ctl ('H'));
+ XSETINT (Vhelp_char, Ctl ('H'));
DEFVAR_LISP ("help-form", &Vhelp_form,
"Form to execute when character `help-char' is read.\n\
DEFVAR_LISP ("menu-prompt-more-char", &menu_prompt_more_char,
"Character to see next line of menu prompt.\n\
Type this character while in a menu prompt to rotate around the lines of it.");
- XSET (menu_prompt_more_char, Lisp_Int, ' ');
+ XSETINT (menu_prompt_more_char, ' ');
DEFVAR_INT ("extra-keyboard-modifiers", &extra_keyboard_modifiers,
"A mask of additional modifier keys to use with every keyboard character.\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,
+ DEFVAR_LISP ("overriding-local-map-menu-flag", &Voverriding_local_map_menu_flag,
+ "Non-nil means `overriding-local-map' applies to the menu bar.\n\
+Otherwise, the menu bar continues to reflect the buffer's local map\n\
+and the minor mode maps regardless of `overriding-local-map'.");
+ Voverriding_local_map_menu_flag = Qnil;
+
+#ifdef HAVE_MOUSE
+ DEFVAR_LISP ("track-mouse", &do_mouse_tracking,
"*Non-nil means generate motion events for mouse motion.");
+#endif
DEFVAR_LISP ("system-key-alist", &Vsystem_key_alist,
"Alist of system-specific X windows key symbols.\n\
numeric keysym code (sans the \"system-specific\" bit 1<<28)\n\
and SYMBOL is its name.");
Vsystem_key_alist = Qnil;
+
+ DEFVAR_LISP ("deferred-action-list", &Vdeferred_action_list,
+ "List of deferred actions to be performed at a later time.\n\
+The precise format isn't relevant here; we just check whether it is nil.");
+ Vdeferred_action_list = Qnil;
+
+ DEFVAR_LISP ("deferred-action-function", &Vdeferred_action_function,
+ "Function to call to handle deferred actions, after each command.\n\
+This function is called with no arguments after each command\n\
+whenever `deferred-action-list' is non-nil.");
+ Vdeferred_action_function = Qnil;
}
keys_of_keyboard ()