/* Keyboard and mouse input; editor command loop.
- Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994, 1995, 1996, 1997,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994, 1995,
+ 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005 Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include <config.h>
#include <signal.h>
#include <stdio.h>
+#include "lisp.h"
#include "termchar.h"
#include "termopts.h"
-#include "lisp.h"
+#include "frame.h"
#include "termhooks.h"
#include "macros.h"
#include "keyboard.h"
-#include "frame.h"
#include "window.h"
#include "commands.h"
#include "buffer.h"
#endif /* not MSDOS */
#include "syssignal.h"
-#include "systty.h"
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
int interrupt_input_pending;
-/* File descriptor to use for input. */
-extern int input_fd;
-
#ifdef HAVE_WINDOW_SYSTEM
/* Make all keyboard buffers much bigger when using X windows. */
#ifdef MAC_OS8
command is stored in this-original-command. It is nil otherwise. */
Lisp_Object Vthis_original_command;
-/* The value of point when the last command was executed. */
+/* The value of point when the last command was started. */
int last_point_position;
/* The buffer that was current when the last command was started. */
Lisp_Object last_point_position_buffer;
+/* The window that was selected when the last command was started. */
+Lisp_Object last_point_position_window;
+
/* 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
generate switch-frame events. This may be cleared by functions
/* Form to evaluate (if non-nil) when Emacs is started. */
Lisp_Object Vtop_level;
-/* User-supplied table to translate input characters. */
-Lisp_Object Vkeyboard_translate_table;
-
-/* Keymap mapping ASCII function key sequences onto their preferred forms. */
-extern Lisp_Object Vfunction_key_map;
-
-/* Another keymap that maps key sequences into key sequences.
- This one takes precedence over ordinary definitions. */
-extern Lisp_Object Vkey_translation_map;
-
/* If non-nil, this implements the current input method. */
Lisp_Object Vinput_method_function;
Lisp_Object Qinput_method_function;
Lisp_Object Qpre_command_hook, Vpre_command_hook;
Lisp_Object Qpost_command_hook, Vpost_command_hook;
Lisp_Object Qcommand_hook_internal, Vcommand_hook_internal;
-/* Hook run after a command if there's no more input soon. */
-Lisp_Object Qpost_command_idle_hook, Vpost_command_idle_hook;
-/* Delay time in microseconds before running post-command-idle-hook. */
-EMACS_INT post_command_idle_delay;
+/* Parent keymap of terminal-local function-key-map instances. */
+Lisp_Object Vfunction_key_map;
+
+/* Parent keymap of terminal-local key-translation-map instances. */
+Lisp_Object Vkey_translation_map;
/* 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. */
/* Nonzero if input is available. */
int input_pending;
-/* 1 if should obey 0200 bit in input chars as "Meta", 2 if should
- keep 0200 bit in input chars. 0 to ignore the 0200 bit. */
-
-int meta_key;
-
-/* Non-zero means force key bindings update in parse_menu_item. */
-
-int update_menu_bindings;
-
extern char *pending_malloc_warning;
/* Circular buffer for pre-read keyboard input. */
#endif
Lisp_Object Qdrag_n_drop;
Lisp_Object Qsave_session;
+#ifdef MAC_OS
+Lisp_Object Qmac_apple_event;
+#endif
/* Lisp_Object Qmouse_movement; - also an event header */
/* Nonzero while interrupts are temporarily deferred during redisplay. */
int interrupts_deferred;
-/* Nonzero means use ^S/^Q for flow control. */
-int flow_control;
-
/* Allow m- file to inhibit use of FIONREAD. */
#ifdef BROKEN_FIONREAD
#undef FIONREAD
static Lisp_Object apply_modifiers P_ ((int, Lisp_Object));
static void clear_event P_ ((struct input_event *));
static void any_kboard_state P_ ((void));
+static Lisp_Object restore_kboard_configuration P_ ((Lisp_Object));
static SIGTYPE interrupt_signal P_ ((int signalnum));
+static void handle_interrupt P_ ((void));
static void timer_start_idle P_ ((void));
static void timer_stop_idle P_ ((void));
static void timer_resume_idle P_ ((void));
doc: /* Invoke the editor command loop recursively.
To get out of the recursive edit, a command can do `(throw 'exit nil)';
that tells this function to return.
-Alternately, `(throw 'exit t)' makes this function signal an error.
+Alternatively, `(throw 'exit t)' makes this function signal an error.
This function is called by the editor initialization to begin editing. */)
()
{
like it is done in the splash screen display, we have to
make sure that we restore single_kboard as command_loop_1
would have done if it were left normally. */
- record_unwind_protect (recursive_edit_unwind,
- Fcons (buffer, single_kboard ? Qt : Qnil));
+ temporarily_switch_to_single_kboard (FRAME_KBOARD (SELECTED_FRAME ()));
+ record_unwind_protect (recursive_edit_unwind, buffer);
recursive_edit_1 ();
return unbind_to (count, Qnil);
}
Lisp_Object
-recursive_edit_unwind (info)
- Lisp_Object info;
+recursive_edit_unwind (buffer)
+ Lisp_Object buffer;
{
- if (BUFFERP (XCAR (info)))
- Fset_buffer (XCAR (info));
-
- if (NILP (XCDR (info)))
- any_kboard_state ();
- else
- single_kboard_state ();
+ if (BUFFERP (buffer))
+ Fset_buffer (buffer);
command_loop_level--;
update_mode_lines = 1;
static struct kboard_stack *kboard_stack;
void
-push_frame_kboard (f)
- FRAME_PTR f;
+push_kboard (k)
+ struct kboard *k;
{
#ifdef MULTI_KBOARD
struct kboard_stack *p
p->kboard = current_kboard;
kboard_stack = p;
- current_kboard = FRAME_KBOARD (f);
+ current_kboard = k;
#endif
}
void
-pop_frame_kboard ()
+push_frame_kboard (f)
+ FRAME_PTR f;
+{
+ push_kboard (f->terminal->kboard);
+}
+
+void
+pop_kboard ()
{
#ifdef MULTI_KBOARD
+ struct terminal *t;
struct kboard_stack *p = kboard_stack;
- current_kboard = p->kboard;
+ current_kboard = NULL;
+ for (t = terminal_list; t; t = t->next_terminal)
+ {
+ if (t->kboard == p->kboard)
+ {
+ current_kboard = p->kboard;
+ break;
+ }
+ }
+ if (current_kboard == NULL)
+ {
+ /* The terminal we remembered has been deleted. */
+ current_kboard = FRAME_KBOARD (SELECTED_FRAME ());
+ }
kboard_stack = p->next;
xfree (p);
#endif
}
+
+/* Switch to single_kboard mode. If K is non-nil, set it as the
+ current keyboard. Use record_unwind_protect to return to the
+ previous state later. */
+
+void
+temporarily_switch_to_single_kboard (k)
+ struct kboard *k;
+{
+#ifdef MULTI_KBOARD
+ int was_locked = single_kboard;
+ if (k != NULL)
+ push_kboard (k);
+ else
+ push_kboard (current_kboard);
+ single_kboard_state ();
+ record_unwind_protect (restore_kboard_configuration,
+ (was_locked ? Qt : Qnil));
+#endif
+}
+
+void
+record_single_kboard_state ()
+{
+ push_kboard (current_kboard);
+ record_unwind_protect (restore_kboard_configuration,
+ (single_kboard ? Qt : Qnil));
+}
+
+static Lisp_Object
+restore_kboard_configuration (was_locked)
+ Lisp_Object was_locked;
+{
+ if (NILP (was_locked))
+ any_kboard_state ();
+ else
+ single_kboard_state ();
+ pop_kboard ();
+ return Qnil;
+}
\f
/* Handle errors that are not handled at inner levels
by printing an error message and returning to the editor command loop. */
cancel_hourglass ();
#endif
- if (!NILP (executing_macro))
+ if (!NILP (executing_kbd_macro))
{
- if (executing_macro_iterations == 1)
+ if (executing_kbd_macro_iterations == 1)
sprintf (macroerror, "After 1 kbd macro iteration: ");
else
sprintf (macroerror, "After %d kbd macro iterations: ",
- executing_macro_iterations);
+ executing_kbd_macro_iterations);
}
else
*macroerror = 0;
Vstandard_output = Qt;
Vstandard_input = Qt;
- Vexecuting_macro = Qnil;
- executing_macro = Qnil;
+ Vexecuting_kbd_macro = Qnil;
+ executing_kbd_macro = Qnil;
current_kboard->Vprefix_arg = Qnil;
current_kboard->Vlast_prefix_arg = Qnil;
cancel_echoing ();
yet, or we're not interactive, it's best to dump this message out
to stderr and exit. */
if (!sf->glyphs_initialized_p
- /* This is the case of the frame dumped with Emacs, when we're
- running under a window system. */
- || (!NILP (Vwindow_system)
- && !inhibit_window_system
- && FRAME_TERMCAP_P (sf))
+ || FRAME_INITIAL_P (sf)
|| noninteractive)
{
stream = Qexternal_debugging_output;
{
Lisp_Object val;
val = internal_catch (Qexit, command_loop_2, Qnil);
- executing_macro = Qnil;
+ executing_kbd_macro = Qnil;
return val;
}
else
while (1)
{
internal_catch (Qtop_level, top_level_1, Qnil);
- /* Reset single_kboard in case top-level set it while
- evaluating an -f option, or we are stuck there for some
- other reason. */
- any_kboard_state ();
+ /* Reset single_kboard in case top-level set it while
+ evaluating an -f option, or we are stuck there for some
+ other reason. */
+ any_kboard_state ();
internal_catch (Qtop_level, command_loop_2, Qnil);
- executing_macro = Qnil;
+ executing_kbd_macro = Qnil;
/* End of file in -batch run causes exit here. */
if (noninteractive)
Lisp_Object keybuf[30];
int i;
int no_direct;
- int prev_modiff;
+ int prev_modiff = 0;
struct buffer *prev_buffer = NULL;
#ifdef MULTI_KBOARD
int was_locked = single_kboard;
#endif
- int already_adjusted;
+ int already_adjusted = 0;
current_kboard->Vprefix_arg = Qnil;
current_kboard->Vlast_prefix_arg = Qnil;
if (!NILP (Vdeferred_action_list))
safe_run_hooks (Qdeferred_action_function);
-
- if (!NILP (Vpost_command_idle_hook) && !NILP (Vrun_hooks))
- {
- if (NILP (Vunread_command_events)
- && NILP (Vunread_input_method_events)
- && NILP (Vunread_post_input_method_events)
- && NILP (Vexecuting_macro)
- && !NILP (sit_for (0, post_command_idle_delay, 0, 1, 1)))
- safe_run_hooks (Qpost_command_idle_hook);
- }
}
- Vmemory_full = Qnil;
-
/* Do this after running Vpost_command_hook, for consistency. */
current_kboard->Vlast_command = Vthis_command;
current_kboard->Vreal_last_command = real_this_command;
Is this a good idea? */
if (FRAMEP (internal_last_event_frame)
&& !EQ (internal_last_event_frame, selected_frame))
- Fselect_frame (internal_last_event_frame, Qnil);
+ Fselect_frame (internal_last_event_frame);
#endif
/* If it has changed current-menubar from previous value,
really recompute the menubar from the value. */
Vthis_command = Qnil;
real_this_command = Qnil;
+ Vthis_original_command = Qnil;
/* Read next key sequence; i gets its length. */
i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
}
cmd = read_key_sequence_cmd;
- if (!NILP (Vexecuting_macro))
+ if (!NILP (Vexecuting_kbd_macro))
{
if (!NILP (Vquit_flag))
{
- Vexecuting_macro = Qt;
+ Vexecuting_kbd_macro = Qt;
QUIT; /* Make some noise. */
/* Will return since macro now empty. */
}
prev_buffer = current_buffer;
prev_modiff = MODIFF;
last_point_position = PT;
+ last_point_position_window = selected_window;
XSETBUFFER (last_point_position_buffer, prev_buffer);
/* By default, we adjust point to a boundary of a region that
&& EQ (current_buffer->selective_display, Qnil)
&& !detect_input_pending ()
&& NILP (XWINDOW (selected_window)->column_number_displayed)
- && NILP (Vexecuting_macro))
+ && NILP (Vexecuting_kbd_macro))
direct_output_forward_char (1);
goto directly_done;
}
&& EQ (current_buffer->selective_display, Qnil)
&& !detect_input_pending ()
&& NILP (XWINDOW (selected_window)->column_number_displayed)
- && NILP (Vexecuting_macro))
+ && NILP (Vexecuting_kbd_macro))
direct_output_forward_char (-1);
goto directly_done;
}
= translate_char (Vtranslation_table_for_input,
XFASTINT (last_command_char), 0, 0, 0);
int value;
- if (NILP (Vexecuting_macro)
+ if (NILP (Vexecuting_kbd_macro)
&& !EQ (minibuf_window, selected_window))
{
if (!nonundocount || nonundocount >= 20)
|| !EQ (current_buffer->selective_display, Qnil)
|| detect_input_pending ()
|| !NILP (XWINDOW (selected_window)->column_number_displayed)
- || !NILP (Vexecuting_macro));
+ || !NILP (Vexecuting_kbd_macro));
value = internal_self_insert (c, 0);
int scount = SPECPDL_INDEX ();
if (display_hourglass_p
- && NILP (Vexecuting_macro))
+ && NILP (Vexecuting_kbd_macro))
{
record_unwind_protect (cancel_hourglass_unwind, Qnil);
start_hourglass ();
hourglass cursor anyway.
But don't cancel the hourglass within a macro
just because a command in the macro finishes. */
- if (NILP (Vexecuting_macro))
+ if (NILP (Vexecuting_kbd_macro))
unbind_to (scount, Qnil);
#endif
}
if (!NILP (Vdeferred_action_list))
safe_run_hooks (Qdeferred_action_function);
- if (!NILP (Vpost_command_idle_hook) && !NILP (Vrun_hooks))
- {
- if (NILP (Vunread_command_events)
- && NILP (Vunread_input_method_events)
- && NILP (Vunread_post_input_method_events)
- && NILP (Vexecuting_macro)
- && !NILP (sit_for (0, post_command_idle_delay, 0, 1, 1)))
- safe_run_hooks (Qpost_command_idle_hook);
- }
-
/* If there is a prefix argument,
1) We don't want Vlast_command to be ``universal-argument''
(that would be dumb), so don't set Vlast_command,
? get_property_and_range (PT, Qdisplay, &val, &beg, &end, Qnil)
: (beg = OVERLAY_POSITION (OVERLAY_START (overlay)),
end = OVERLAY_POSITION (OVERLAY_END (overlay))))
- && beg < PT) /* && end > PT <- It's always the case. */
+ && (beg < PT /* && end > PT <- It's always the case. */
+ || (beg <= PT && STRINGP (val) && SCHARS (val) == 0)))
{
xassert (end > PT);
- SET_PT (PT < last_pt ? beg : end);
+ SET_PT (PT < last_pt
+ ? (STRINGP (val) && SCHARS (val) == 0 ? beg - 1 : beg)
+ : end);
check_composition = check_invisible = 1;
}
check_display = 0;
start_polling ()
{
#ifdef POLL_FOR_INPUT
- if (read_socket_hook && !interrupt_input)
+ /* XXX This condition was (read_socket_hook && !interrupt_input),
+ but read_socket_hook is not global anymore. Let's pretend that
+ it's always set. */
+ if (!interrupt_input)
{
/* Turn alarm handling on unconditionally. It might have
been turned off in process.c. */
input_polling_used ()
{
#ifdef POLL_FOR_INPUT
- return read_socket_hook && !interrupt_input;
+ /* XXX This condition was (read_socket_hook && !interrupt_input),
+ but read_socket_hook is not global anymore. Let's pretend that
+ it's always set. */
+ return !interrupt_input;
#else
return 0;
#endif
stop_polling ()
{
#ifdef POLL_FOR_INPUT
- if (read_socket_hook && !interrupt_input)
+ /* XXX This condition was (read_socket_hook && !interrupt_input),
+ but read_socket_hook is not global anymore. Let's pretend that
+ it's always set. */
+ if (!interrupt_input)
++poll_suppress_count;
#endif
}
this_command_key_count_reset = 0;
- if (!NILP (Vexecuting_macro))
+ if (!NILP (Vexecuting_kbd_macro))
{
/* We set this to Qmacro; since that's not a frame, nobody will
try to switch frames on us, and the selected window will
/* Exit the macro if we are at the end.
Also, some things replace the macro with t
to force an early exit. */
- if (EQ (Vexecuting_macro, Qt)
- || executing_macro_index >= XFASTINT (Flength (Vexecuting_macro)))
+ if (EQ (Vexecuting_kbd_macro, Qt)
+ || executing_kbd_macro_index >= XFASTINT (Flength (Vexecuting_kbd_macro)))
{
XSETINT (c, -1);
goto exit;
}
- c = Faref (Vexecuting_macro, make_number (executing_macro_index));
- if (STRINGP (Vexecuting_macro)
+ c = Faref (Vexecuting_kbd_macro, make_number (executing_kbd_macro_index));
+ if (STRINGP (Vexecuting_kbd_macro)
&& (XINT (c) & 0x80) && (XUINT (c) <= 0xff))
XSETFASTINT (c, CHAR_META | (XINT (c) & ~0x80));
- executing_macro_index++;
+ executing_kbd_macro_index++;
goto from_macro;
}
if (_setjmp (local_getcjmp))
{
+ /* Handle quits while reading the keyboard. */
+ /* We must have saved the outer value of getcjmp here,
+ so restore it now. */
+ restore_getcjmp (save_jump);
XSETINT (c, quit_char);
internal_last_event_frame = selected_frame;
Vlast_event_frame = internal_last_event_frame;
if (XINT (c) == -1)
goto exit;
- if ((STRINGP (Vkeyboard_translate_table)
- && SCHARS (Vkeyboard_translate_table) > (unsigned) XFASTINT (c))
- || (VECTORP (Vkeyboard_translate_table)
- && XVECTOR (Vkeyboard_translate_table)->size > (unsigned) XFASTINT (c))
- || (CHAR_TABLE_P (Vkeyboard_translate_table)
+ if ((STRINGP (current_kboard->Vkeyboard_translate_table)
+ && SCHARS (current_kboard->Vkeyboard_translate_table) > (unsigned) XFASTINT (c))
+ || (VECTORP (current_kboard->Vkeyboard_translate_table)
+ && XVECTOR (current_kboard->Vkeyboard_translate_table)->size > (unsigned) XFASTINT (c))
+ || (CHAR_TABLE_P (current_kboard->Vkeyboard_translate_table)
&& CHAR_VALID_P (XINT (c), 0)))
{
Lisp_Object d;
- d = Faref (Vkeyboard_translate_table, c);
+ d = Faref (current_kboard->Vkeyboard_translate_table, c);
/* nil in keyboard-translate-table means no translation. */
if (!NILP (d))
c = d;
READABLE_EVENTS_FILTER_EVENTS is set, report it as empty. */
if (kbd_fetch_ptr != kbd_store_ptr)
{
- int have_live_event = 1;
-
- if (flags & READABLE_EVENTS_FILTER_EVENTS)
+ if (flags & (READABLE_EVENTS_FILTER_EVENTS
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ | READABLE_EVENTS_IGNORE_SQUEEZABLES
+#endif
+ ))
{
struct input_event *event;
? kbd_fetch_ptr
: kbd_buffer);
- while (have_live_event && event->kind == FOCUS_IN_EVENT)
- {
- event++;
+ do
+ {
+ if (!(
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ (flags & READABLE_EVENTS_FILTER_EVENTS) &&
+#endif
+ event->kind == FOCUS_IN_EVENT)
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ && !((flags & READABLE_EVENTS_IGNORE_SQUEEZABLES)
+ && event->kind == SCROLL_BAR_CLICK_EVENT
+ && event->part == scroll_bar_handle
+ && event->modifiers == 0)
+#endif
+ )
+ return 1;
+ event++;
if (event == kbd_buffer + KBD_BUFFER_SIZE)
event = kbd_buffer;
- if (event == kbd_store_ptr)
- have_live_event = 0;
- }
+ }
+ while (event != kbd_store_ptr);
}
- if (have_live_event) return 1;
+ else
+ return 1;
}
#ifdef HAVE_MOUSE
if (c == quit_char)
{
#ifdef MULTI_KBOARD
- KBOARD *kb;
+ KBOARD *kb = FRAME_KBOARD (XFRAME (event->frame_or_window));
struct input_event *sp;
- if (single_kboard
- && (kb = FRAME_KBOARD (XFRAME (event->frame_or_window)),
- kb != current_kboard))
+ if (single_kboard && kb != current_kboard)
{
kb->kbd_queue
= Fcons (make_lispy_switch_frame (event->frame_or_window),
}
last_event_timestamp = event->timestamp;
- interrupt_signal (0 /* dummy */);
+ handle_interrupt ();
return;
}
kbd_fetch_ptr = event + 1;
}
#endif
-#if defined (HAVE_X11) || defined (HAVE_NTGUI)
+#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS)
else if (event->kind == ICONIFY_EVENT)
{
/* Make an event (iconify-frame (FRAME)). */
unsigned long time;
*kbp = current_kboard;
- /* Note that this uses F to determine which display to look at.
+ /* Note that this uses F to determine which terminal to look at.
If there is no valid info, it does not store anything
so x remains nil. */
x = Qnil;
- (*mouse_position_hook) (&f, 0, &bar_window, &part, &x, &y, &time);
+
+ /* XXX Can f or mouse_position_hook be NULL here? */
+ if (f && FRAME_TERMINAL (f)->mouse_position_hook)
+ (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, 0, &bar_window,
+ &part, &x, &y, &time);
obj = Qnil;
{
if (NILP (vector[0]))
{
- int was_locked = single_kboard;
int count = SPECPDL_INDEX ();
Lisp_Object old_deactivate_mark = Vdeactivate_mark;
+ /* On unbind_to, resume allowing input from any kboard, if that
+ was true before. */
+ record_single_kboard_state ();
+
/* Mark the timer as triggered to prevent problems if the lisp
code fails to reschedule it right. */
vector[0] = Qt;
timers_run++;
unbind_to (count, Qnil);
- /* Resume allowing input from any kboard, if that was true before. */
- if (!was_locked)
- any_kboard_state ();
-
/* Since we have handled the event,
we don't need to tell the caller to wake up and do it. */
}
XSETINT (*x, wx);
XSETINT (*y, wy);
- if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
+ if (part == ON_TEXT)
+ {
+ wx += WINDOW_LEFT_MARGIN_WIDTH (w);
+ }
+ else if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
{
/* Mode line or header line. Look for a string under
the mouse that may have a `local-map' property. */
&object, &dx, &dy, &width, &height);
if (STRINGP (string))
string_info = Fcons (string, make_number (charpos));
+ if (part == ON_LEFT_MARGIN)
+ wx = 0;
+ else
+ wx = window_box_right_offset (w, TEXT_AREA) - 1;
+ }
+ else if (part == ON_LEFT_FRINGE)
+ {
+ posn = Qleft_fringe;
+ rx = 0;
+ dx = wx;
+ wx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+ ? 0
+ : window_box_width (w, LEFT_MARGIN_AREA));
+ dx -= wx;
}
- else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE)
+ else if (part == ON_RIGHT_FRINGE)
{
- posn = (part == ON_LEFT_FRINGE) ? Qleft_fringe : Qright_fringe;
+ posn = Qright_fringe;
rx = 0;
dx = wx;
- if (part == ON_RIGHT_FRINGE)
- dx -= (window_box_width (w, LEFT_MARGIN_AREA)
- + window_box_width (w, TEXT_AREA)
- + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
- ? window_box_width (w, RIGHT_MARGIN_AREA)
- : 0));
- else if (!WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
- dx -= window_box_width (w, LEFT_MARGIN_AREA);
+ wx = (window_box_width (w, LEFT_MARGIN_AREA)
+ + window_box_width (w, TEXT_AREA)
+ + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+ ? window_box_width (w, RIGHT_MARGIN_AREA)
+ : 0));
+ dx -= wx;
+ }
+ else
+ {
+ /* Note: We have no special posn for part == ON_SCROLL_BAR. */
+ wx = max (WINDOW_LEFT_MARGIN_WIDTH (w), wx);
}
if (textpos < 0)
struct display_pos p;
int dx2, dy2;
int width2, height2;
- wx = max (WINDOW_LEFT_MARGIN_WIDTH (w), wx);
string2 = buffer_posn_from_coords (w, &wx, &wy, &p,
&object2, &dx2, &dy2,
&width2, &height2);
if (CONSP (down)
&& INTEGERP (XCAR (down)) && INTEGERP (XCDR (down)))
{
- xdiff = XFASTINT (event->x) - XFASTINT (XCAR (down));
- ydiff = XFASTINT (event->y) - XFASTINT (XCDR (down));
+ xdiff = XINT (event->x) - XINT (XCAR (down));
+ ydiff = XINT (event->y) - XINT (XCDR (down));
}
if (xdiff < double_click_fuzz && xdiff > - double_click_fuzz
- && ydiff < double_click_fuzz
- && ydiff > - double_click_fuzz)
+ && ydiff < double_click_fuzz && ydiff > - double_click_fuzz
+ /* Maybe the mouse has moved a lot, caused scrolling, and
+ eventually ended up at the same screen position (but
+ not buffer position) in which case it is a drag, not
+ a click. */
+ /* FIXME: OTOH if the buffer position has changed
+ because of a timer or process filter rather than
+ because of mouse movement, it should be considered as
+ a click. But mouse-drag-region completely ignores
+ this case and it hasn't caused any real problem, so
+ it's probably OK to ignore it as well. */
+ && EQ (Fcar (Fcdr (start_pos)), Fcar (Fcdr (position))))
/* Mouse hasn't moved (much). */
event->modifiers |= click_modifier;
else
Lisp_Object head, position;
Lisp_Object files;
- /* The frame_or_window field should be a cons of the frame in
- which the event occurred and a list of the filenames
- dropped. */
- if (! CONSP (event->frame_or_window))
- abort ();
-
- f = XFRAME (XCAR (event->frame_or_window));
- files = XCDR (event->frame_or_window);
+ f = XFRAME (event->frame_or_window);
+ files = event->arg;
/* Ignore mouse events that were made on frames that
have been deleted. */
case SAVE_SESSION_EVENT:
return Qsave_session;
+#ifdef MAC_OS
+ case MAC_APPLE_EVENT:
+ {
+ Lisp_Object spec[2];
+
+ spec[0] = event->x;
+ spec[1] = event->y;
+ return Fcons (Qmac_apple_event,
+ Fcons (Fvector (2, spec),
+ Fcons (mac_make_lispy_event_code (event->code),
+ Qnil)));
+ }
+#endif
+
/* The 'kind' field of the event is something we don't recognize. */
default:
abort ();
{
int len = SBYTES (name_alist_or_stem);
char *buf = (char *) alloca (len + 50);
- sprintf (buf, "%s-%ld", SDATA (name_alist_or_stem),
- (long) XINT (symbol_int) + 1);
+ sprintf (buf, "%s-%ld", SDATA (name_alist_or_stem),
+ (long) XINT (symbol_int) + 1);
value = intern (buf);
}
else if (name_table != 0 && name_table[symbol_num])
If READABLE_EVENTS_FILTER_EVENTS is set in FLAGS, ignore internal
events (FOCUS_IN_EVENT).
If READABLE_EVENTS_IGNORE_SQUEEZABLES is set in FLAGS, ignore mouse
- movements. */
+ movements and toolkit scroll bar thumb drags. */
static void
get_input_pending (addr, flags)
}
else
#ifdef POLL_FOR_INPUT
- if (read_socket_hook && !interrupt_input && poll_suppress_count == 0)
+ /* XXX This condition was (read_socket_hook && !interrupt_input),
+ but read_socket_hook is not global anymore. Let's pretend that
+ it's always set. */
+ if (!interrupt_input && poll_suppress_count == 0)
{
SIGMASKTYPE mask;
mask = sigblock (sigmask (SIGALRM));
read_avail_input (expected)
int expected;
{
- register int i;
int nread = 0;
+ int err = 0;
+ struct terminal *t;
- if (read_socket_hook)
+ /* Loop through the available terminals, and call their input hooks. */
+ t = terminal_list;
+ while (t)
{
- int nr;
- struct input_event hold_quit;
+ struct terminal *next = t->next_terminal;
- EVENT_INIT (hold_quit);
- hold_quit.kind = NO_EVENT;
+ if (t->read_socket_hook)
+ {
+ int nr;
+ struct input_event hold_quit;
- /* No need for FIONREAD or fcntl; just say don't wait. */
- while (nr = (*read_socket_hook) (input_fd, expected, &hold_quit), nr > 0)
- {
- nread += nr;
- expected = 0;
- }
- if (hold_quit.kind != NO_EVENT)
- kbd_buffer_store_event (&hold_quit);
+ EVENT_INIT (hold_quit);
+ hold_quit.kind = NO_EVENT;
+
+ /* No need for FIONREAD or fcntl; just say don't wait. */
+ while (nr = (*t->read_socket_hook) (t, expected, &hold_quit), nr > 0)
+ {
+ nread += nr;
+ expected = 0;
+ }
+
+ if (nr == -1) /* Not OK to read input now. */
+ {
+ err = 1;
+ }
+ else if (nr == -2) /* Non-transient error. */
+ {
+ /* The terminal device terminated; it should be closed. */
+
+ /* Kill Emacs if this was our last terminal. */
+ if (!terminal_list->next_terminal)
+ /* Formerly simply reported no input, but that
+ sometimes led to a failure of Emacs to terminate.
+ SIGHUP seems appropriate if we can't reach the
+ terminal. */
+ /* ??? Is it really right to send the signal just to
+ this process rather than to the whole process
+ group? Perhaps on systems with FIONREAD Emacs is
+ alone in its group. */
+ kill (getpid (), SIGHUP);
+
+ /* XXX Is calling delete_terminal safe here? It calls Fdelete_frame. */
+ if (t->delete_terminal_hook)
+ (*t->delete_terminal_hook) (t);
+ else
+ delete_terminal (t);
+ }
+
+ if (hold_quit.kind != NO_EVENT)
+ kbd_buffer_store_event (&hold_quit);
+ }
+
+ t = next;
}
- else
- {
- /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
- 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. */
+ if (err && !nread)
+ nread = -1;
+
+ return nread;
+}
+
+/* This is the tty way of reading available input.
+
+ Note that each terminal device has its own `struct terminal' object,
+ and so this function is called once for each individual termcap
+ terminal. The first parameter indicates which terminal to read from. */
+
+int
+tty_read_avail_input (struct terminal *terminal,
+ int expected,
+ struct input_event *hold_quit)
+{
+ /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
+ 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, i;
+ struct tty_display_info *tty = terminal->display_info.tty;
+ int nread = 0;
+
+ if (terminal->type != output_termcap)
+ abort ();
+
+ /* XXX I think the following code should be moved to separate hook
+ functions in system-dependent files. */
#ifdef WINDOWSNT
- return 0;
+ return 0;
#else /* not WINDOWSNT */
#ifdef MSDOS
- n_to_read = dos_keysns ();
- if (n_to_read == 0)
- return 0;
+ n_to_read = dos_keysns ();
+ if (n_to_read == 0)
+ return 0;
+
+ cbuf[0] = dos_keyread ();
+ nread = 1;
+
#else /* not MSDOS */
+
+ if (! tty->term_initted) /* In case we get called during bootstrap. */
+ return 0;
+
+ if (! tty->input)
+ return 0; /* The terminal is suspended. */
+
+ /* Determine how many characters we should *try* to read. */
#ifdef FIONREAD
- /* Find out how much input is available. */
- 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. */
- /* ??? Is it really right to send the signal just to this process
- rather than to the whole process group?
- Perhaps on systems with FIONREAD Emacs is alone in its group. */
- {
- if (! noninteractive)
- kill (getpid (), SIGHUP);
- else
- n_to_read = 0;
- }
- if (n_to_read == 0)
- return 0;
- if (n_to_read > sizeof cbuf)
- n_to_read = sizeof cbuf;
+ /* Find out how much input is available. */
+ if (ioctl (fileno (tty->input), FIONREAD, &n_to_read) < 0)
+ {
+ if (! noninteractive)
+ return -2; /* Close this terminal. */
+ else
+ n_to_read = 0;
+ }
+ if (n_to_read == 0)
+ return 0;
+ if (n_to_read > sizeof cbuf)
+ n_to_read = sizeof cbuf;
#else /* no FIONREAD */
#if defined (USG) || defined (DGUX) || defined(CYGWIN)
- /* Read some input if available, but don't wait. */
- n_to_read = sizeof cbuf;
- fcntl (input_fd, F_SETFL, O_NDELAY);
+ /* Read some input if available, but don't wait. */
+ n_to_read = sizeof cbuf;
+ fcntl (fileno (tty->input), F_SETFL, O_NDELAY);
#else
- you lose;
+ 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. */
- do
- {
-#ifdef MSDOS
- cbuf[0] = dos_keyread ();
- nread = 1;
-#else
- nread = emacs_read (input_fd, cbuf, n_to_read);
-#endif
- /* POSIX infers that processes which are not in the session leader's
- process group won't get SIGHUP's at logout time. BSDI adheres to
- this part standard and returns -1 from read (0) with errno==EIO
- when the control tty is taken away.
- Jeffrey Honig <jch@bsdi.com> says this is generally safe. */
- if (nread == -1 && errno == EIO)
- kill (0, SIGHUP);
+ /* Now read; for one reason or another, this will not block.
+ NREAD is set to the number of chars read. */
+ do
+ {
+ nread = emacs_read (fileno (tty->input), cbuf, n_to_read);
+ /* POSIX infers that processes which are not in the session leader's
+ process group won't get SIGHUP's at logout time. BSDI adheres to
+ this part standard and returns -1 from read (0) with errno==EIO
+ when the control tty is taken away.
+ Jeffrey Honig <jch@bsdi.com> says this is generally safe. */
+ if (nread == -1 && errno == EIO)
+ return -2; /* Close this terminal. */
#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 (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? */
+ /* 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 (nread == 0)
+ return -2; /* Close this terminal. */
+#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
+ nread < 0 && (errno == EAGAIN
#ifdef EFAULT
- || errno == EFAULT
+ || errno == EFAULT
#endif
#ifdef EBADSLT
- || errno == EBADSLT
+ || errno == EBADSLT
#endif
- )
+ )
#else
- 0
+ 0
#endif
- );
+ );
#ifndef FIONREAD
#if defined (USG) || defined (DGUX) || defined (CYGWIN)
- fcntl (input_fd, F_SETFL, 0);
+ fcntl (fileno (tty->input), F_SETFL, 0);
#endif /* USG or DGUX or CYGWIN */
#endif /* no FIONREAD */
- for (i = 0; i < nread; i++)
- {
- struct input_event buf;
- EVENT_INIT (buf);
- buf.kind = ASCII_KEYSTROKE_EVENT;
- buf.modifiers = 0;
- if (meta_key == 1 && (cbuf[i] & 0x80))
- buf.modifiers = meta_modifier;
- if (meta_key != 2)
- cbuf[i] &= ~0x80;
-
- buf.code = cbuf[i];
- buf.frame_or_window = selected_frame;
- buf.arg = Qnil;
-
- kbd_buffer_store_event (&buf);
- /* Don't look at input that follows a C-g too closely.
- This reduces lossage due to autorepeat on C-g. */
- if (buf.kind == ASCII_KEYSTROKE_EVENT
- && buf.code == quit_char)
- break;
- }
+
+ if (nread <= 0)
+ return nread;
+
+#endif /* not MSDOS */
+#endif /* not WINDOWSNT */
+
+ for (i = 0; i < nread; i++)
+ {
+ struct input_event buf;
+ EVENT_INIT (buf);
+ buf.kind = ASCII_KEYSTROKE_EVENT;
+ buf.modifiers = 0;
+ if (tty->meta_key == 1 && (cbuf[i] & 0x80))
+ buf.modifiers = meta_modifier;
+ if (tty->meta_key != 2)
+ cbuf[i] &= ~0x80;
+
+ buf.code = cbuf[i];
+ /* Set the frame corresponding to the active tty. Note that the
+ value of selected_frame is not reliable here, redisplay tends
+ to temporarily change it. */
+ buf.frame_or_window = tty->top_frame;
+ buf.arg = Qnil;
+
+ kbd_buffer_store_event (&buf);
+ /* Don't look at input that follows a C-g too closely.
+ This reduces lossage due to autorepeat on C-g. */
+ if (buf.kind == ASCII_KEYSTROKE_EVENT
+ && buf.code == quit_char)
+ break;
}
return nread;
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
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
menu_bar_items_index = i;
Vinhibit_quit = oquit;
- UNGCPRO;
return menu_bar_items_vector;
}
\f
else
def = AREF (item_properties, ITEM_PROPERTY_DEF);
- if (!update_menu_bindings)
- chkcache = 0;
- else if (NILP (XCAR (cachelist))) /* Have no saved key. */
+ if (NILP (XCAR (cachelist))) /* Have no saved key. */
{
if (newcache /* Always check first time. */
/* Should we check everything when precomputing key
last_nonmenu_event = Qnil;
delayed_switch_frame = Qnil;
- fkey.map = fkey.parent = Vfunction_key_map;
- keytran.map = keytran.parent = Vkey_translation_map;
- /* If there is no translation-map, turn off scanning. */
- fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1;
- keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1;
-
+
if (INTERACTIVE)
{
if (!NILP (prompt))
keybuf[0..mock_input] holds the sequence we should reread. */
replay_sequence:
+ /* We may switch keyboards between rescans, so we need to
+ reinitialize fkey and keytran before each replay. */
+ fkey.map = fkey.parent = current_kboard->Vlocal_function_key_map;
+ keytran.map = keytran.parent = current_kboard->Vlocal_key_translation_map;
+ /* If there is no translation map, turn off scanning. */
+ fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1;
+ keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1;
+
starting_buffer = current_buffer;
first_unbound = bufsize + 1;
/* If enabled, show which key runs this command. */
if (!NILP (Vsuggest_key_bindings)
- && NILP (Vexecuting_macro)
+ && NILP (Vexecuting_kbd_macro)
&& SYMBOLP (function))
bindings = Fwhere_is_internal (function, Voverriding_local_map,
Qt, Qnil, Qnil);
from an idle timer function. The symptom of the bug is that
the cursor sometimes doesn't become visible until the next X
event is processed. --gerd. */
- if (rif)
- rif->flush_display (NULL);
+ {
+ Lisp_Object tail, frame;
+ FOR_EACH_FRAME (tail, frame)
+ if (FRAME_RIF (XFRAME (frame)))
+ FRAME_RIF (XFRAME (frame))->flush_display (XFRAME (frame));
+ }
}
return input_pending;
int width, height;
struct gcpro gcpro1;
+ if (tty_list && tty_list->next)
+ error ("There are other tty frames open; close them before suspending Emacs");
+
if (!NILP (stuffstring))
CHECK_STRING (stuffstring);
call1 (Vrun_hooks, intern ("suspend-hook"));
GCPRO1 (stuffstring);
- get_frame_size (&old_width, &old_height);
- reset_sys_modes ();
+ get_tty_size (fileno (CURTTY ()->input), &old_width, &old_height);
+ reset_all_sys_modes ();
/* sys_suspend can get an error if it tries to fork a subshell
and the system resources aren't available for that. */
- record_unwind_protect ((Lisp_Object (*) P_ ((Lisp_Object))) init_sys_modes,
+ record_unwind_protect ((Lisp_Object (*) P_ ((Lisp_Object))) init_all_sys_modes,
Qnil);
stuff_buffered_input (stuffstring);
if (cannot_suspend)
/* Check if terminal/window size has changed.
Note that this is not useful when we are running directly
with a window system; but suspend should be disabled in that case. */
- get_frame_size (&width, &height);
+ get_tty_size (fileno (CURTTY ()->input), &width, &height);
if (width != old_width || height != old_height)
change_frame_size (SELECTED_FRAME (), height, width, 0, 0, 0);
{
input_available_clear_time = time_to_clear;
- /* Tell interrupt_signal to throw back to read_char, */
+ /* Tell handle_interrupt to throw back to read_char, */
waiting_for_input = 1;
- /* If interrupt_signal was called before and buffered a C-g,
+ /* If handle_interrupt was called before and buffered a C-g,
make it run again now, to avoid timing error. */
if (!NILP (Vquit_flag))
quit_throw_to_read_char ();
void
clear_waiting_for_input ()
{
- /* Tell interrupt_signal not to throw back to read_char, */
+ /* Tell handle_interrupt not to throw back to read_char, */
waiting_for_input = 0;
input_available_clear_time = 0;
}
-/* This routine is called at interrupt level in response to C-g.
-
- If interrupt_input, this is the handler for SIGINT. Otherwise, it
- is called from kbd_buffer_store_event, in handling SIGIO or
- SIGTINT.
-
- If `waiting_for_input' is non zero, then unless `echoing' is
- nonzero, immediately throw back to read_char.
+/* The SIGINT handler.
- Otherwise it sets the Lisp variable quit-flag not-nil. This causes
- eval to throw, when it gets a chance. If quit-flag is already
- non-nil, it stops the job right away. */
+ If we have a frame on the controlling tty, we assume that the
+ SIGINT was generated by C-g, so we call handle_interrupt.
+ Otherwise, the handler kills Emacs. */
static SIGTYPE
interrupt_signal (signalnum) /* If we don't have an argument, */
int signalnum; /* some compilers complain in signal calls. */
{
- char c;
/* Must preserve main program's value of errno. */
int old_errno = errno;
- struct frame *sf = SELECTED_FRAME ();
+ struct terminal *terminal;
#if defined (USG) && !defined (POSIX_SIGNALS)
- if (!read_socket_hook && NILP (Vwindow_system))
- {
- /* USG systems forget handlers when they are used;
- must reestablish each time */
- signal (SIGINT, interrupt_signal);
- signal (SIGQUIT, interrupt_signal);
- }
+ /* USG systems forget handlers when they are used;
+ must reestablish each time */
+ signal (SIGINT, interrupt_signal);
+ signal (SIGQUIT, interrupt_signal);
#endif /* USG */
SIGNAL_THREAD_CHECK (signalnum);
+
+ /* See if we have an active terminal on our controlling tty. */
+ terminal = get_named_tty (NULL);
+ if (!terminal)
+ {
+ /* If there are no frames there, let's pretend that we are a
+ well-behaving UN*X program and quit. */
+ fatal_error_signal (SIGTERM);
+ }
+ else
+ {
+ /* Otherwise, the SIGINT was probably generated by C-g. */
+
+ /* Set internal_last_event_frame to the top frame of the
+ controlling tty, if we have a frame there. We disable the
+ interrupt key on secondary ttys, so the SIGINT must have come
+ from the controlling tty. */
+ internal_last_event_frame = terminal->display_info.tty->top_frame;
+
+ handle_interrupt ();
+ }
+
+ errno = old_errno;
+}
+
+/* This routine is called at interrupt level in response to C-g.
+
+ It is called from the SIGINT handler or kbd_buffer_store_event.
+
+ If `waiting_for_input' is non zero, then unless `echoing' is
+ nonzero, immediately throw back to read_char.
+
+ Otherwise it sets the Lisp variable quit-flag not-nil. This causes
+ eval to throw, when it gets a chance. If quit-flag is already
+ non-nil, it stops the job right away. */
+
+static void
+handle_interrupt ()
+{
+ char c;
+
cancel_echoing ();
+ /* XXX This code needs to be revised for multi-tty support. */
if (!NILP (Vquit_flag)
- && (FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf)))
+#ifndef MSDOS
+ && get_named_tty (NULL)
+#endif
+ )
{
/* If SIGINT isn't blocked, don't let us be interrupted by
another SIGINT, it might be harmful due to non-reentrancy
sigblock (sigmask (SIGINT));
fflush (stdout);
- reset_sys_modes ();
+ reset_all_sys_modes ();
#ifdef SIGTSTP /* Support possible in later USG versions */
/*
printf ("Continuing...\n");
#endif /* not MSDOS */
fflush (stdout);
- init_sys_modes ();
+ init_all_sys_modes ();
sigfree ();
}
else
}
if (waiting_for_input && !echoing)
- quit_throw_to_read_char ();
-
- errno = old_errno;
+ quit_throw_to_read_char ();
}
/* Handle a C-g by making read_char return C-g. */
_longjmp (getcjmp, 1);
}
\f
-DEFUN ("set-input-mode", Fset_input_mode, Sset_input_mode, 3, 4, 0,
- doc: /* Set mode of reading keyboard input.
-First arg INTERRUPT non-nil means use input interrupts;
- nil means use CBREAK mode.
-Second arg FLOW non-nil means use ^S/^Q flow control for output to terminal
- (no effect except in CBREAK mode).
-Third arg META t means accept 8-bit input (for a Meta key).
- META nil means ignore the top bit, on the assumption it is parity.
- Otherwise, accept 8-bit input and don't use the top bit for Meta.
-Optional fourth arg QUIT if non-nil specifies character to use for quitting.
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode, Sset_input_interrupt_mode, 1, 1, 0,
+ doc: /* Set interrupt mode of reading keyboard input.
+If INTERRUPT is non-nil, Emacs will use input interrupts;
+otherwise Emacs uses CBREAK mode.
+
See also `current-input-mode'. */)
- (interrupt, flow, meta, quit)
- Lisp_Object interrupt, flow, meta, quit;
+ (interrupt)
+ Lisp_Object interrupt;
{
- if (!NILP (quit)
- && (!INTEGERP (quit) || XINT (quit) < 0 || XINT (quit) > 0400))
- error ("set-input-mode: QUIT must be an ASCII character");
-
-#ifdef POLL_FOR_INPUT
- stop_polling ();
-#endif
-
-#ifndef DOS_NT
- /* this causes startup screen to be restored and messes with the mouse */
- reset_sys_modes ();
-#endif
-
+ int new_interrupt_input;
#ifdef SIGIO
/* Note SIGIO has been undef'd if FIONREAD is missing. */
- if (read_socket_hook)
+ if (0
+#ifdef HAVE_X_WINDOWS
+ || x_display_list != NULL
+#endif
+ )
{
/* When using X, don't give the user a real choice,
because we haven't implemented the mechanisms to support it. */
#ifdef NO_SOCK_SIGIO
- interrupt_input = 0;
+ new_interrupt_input = 0;
#else /* not NO_SOCK_SIGIO */
- interrupt_input = 1;
+ new_interrupt_input = 1;
#endif /* NO_SOCK_SIGIO */
}
else
- interrupt_input = !NILP (interrupt);
+ new_interrupt_input = !NILP (interrupt);
#else /* not SIGIO */
- interrupt_input = 0;
+ new_interrupt_input = 0;
#endif /* not SIGIO */
/* Our VMS input only works by interrupts, as of now. */
#ifdef VMS
- interrupt_input = 1;
+ new_interrupt_input = 1;
+#endif
+
+ if (new_interrupt_input != interrupt_input)
+ {
+#ifdef POLL_FOR_INPUT
+ stop_polling ();
+#endif
+#ifndef DOS_NT
+ /* this causes startup screen to be restored and messes with the mouse */
+ reset_all_sys_modes ();
+#endif
+ interrupt_input = new_interrupt_input;
+#ifndef DOS_NT
+ init_all_sys_modes ();
#endif
- flow_control = !NILP (flow);
+#ifdef POLL_FOR_INPUT
+ poll_suppress_count = 1;
+ start_polling ();
+#endif
+ }
+ return Qnil;
+}
+
+DEFUN ("set-output-flow-control", Fset_output_flow_control, Sset_output_flow_control, 1, 2, 0,
+ doc: /* Enable or disable ^S/^Q flow control for output to TERMINAL.
+If FLOW is non-nil, flow control is enabled and you cannot use C-s or
+C-q in key sequences.
+
+This setting only has an effect on tty terminals and only when
+Emacs reads input in CBREAK mode; see `set-input-interrupt-mode'.
+
+See also `current-input-mode'. */)
+ (flow, terminal)
+ Lisp_Object flow, terminal;
+{
+ struct terminal *t = get_terminal (terminal, 1);
+ struct tty_display_info *tty;
+ if (t == NULL || t->type != output_termcap)
+ return Qnil;
+ tty = t->display_info.tty;
+
+ if (tty->flow_control != !NILP (flow))
+ {
+#ifndef DOS_NT
+ /* this causes startup screen to be restored and messes with the mouse */
+ reset_sys_modes (tty);
+#endif
+
+ tty->flow_control = !NILP (flow);
+
+#ifndef DOS_NT
+ init_sys_modes (tty);
+#endif
+ }
+ return Qnil;
+}
+
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode, Sset_input_meta_mode, 1, 2, 0,
+ doc: /* Enable or disable 8-bit input on TERMINAL.
+If META is t, Emacs will accept 8-bit input, and interpret the 8th
+bit as the Meta modifier.
+
+If META is nil, Emacs will ignore the top bit, on the assumption it is
+parity.
+
+Otherwise, Emacs will accept and pass through 8-bit input without
+specially interpreting the top bit.
+
+This setting only has an effect on tty terminal devices.
+
+Optional parameter TERMINAL specifies the tty terminal device to use.
+It may be a terminal id, a frame, or nil for the terminal used by the
+currently selected frame.
+
+See also `current-input-mode'. */)
+ (meta, terminal)
+ Lisp_Object meta, terminal;
+{
+ struct terminal *t = get_terminal (terminal, 1);
+ struct tty_display_info *tty;
+ int new_meta;
+
+ if (t == NULL || t->type != output_termcap)
+ return Qnil;
+ tty = t->display_info.tty;
+
if (NILP (meta))
- meta_key = 0;
+ new_meta = 0;
else if (EQ (meta, Qt))
- meta_key = 1;
+ new_meta = 1;
else
- meta_key = 2;
- if (!NILP (quit))
- /* Don't let this value be out of range. */
- quit_char = XINT (quit) & (meta_key ? 0377 : 0177);
+ new_meta = 2;
+ if (tty->meta_key != new_meta)
+ {
#ifndef DOS_NT
- init_sys_modes ();
+ /* this causes startup screen to be restored and messes with the mouse */
+ reset_sys_modes (tty);
#endif
-#ifdef POLL_FOR_INPUT
- poll_suppress_count = 1;
- start_polling ();
+ tty->meta_key = new_meta;
+
+#ifndef DOS_NT
+ init_sys_modes (tty);
+#endif
+ }
+ return Qnil;
+}
+
+DEFUN ("set-quit-char", Fset_quit_char, Sset_quit_char, 1, 1, 0,
+ doc: /* Specify character used for quitting.
+QUIT must be an ASCII character.
+
+This function only has an effect on the terminal on the controlling
+tty of the Emacs process.
+
+See also `current-input-mode'. */)
+ (quit)
+ Lisp_Object quit;
+{
+ struct terminal *t = get_named_tty (NULL);
+ struct tty_display_info *tty;
+ if (t == NULL || t->type != output_termcap)
+ return Qnil;
+ tty = t->display_info.tty;
+
+#ifndef DOS_NT
+ /* this causes startup screen to be restored and messes with the mouse */
+ reset_sys_modes (tty);
+#endif
+
+ if (NILP (quit) || !INTEGERP (quit) || XINT (quit) < 0 || XINT (quit) > 0400)
+ error ("QUIT must be an ASCII character");
+
+ /* Don't let this value be out of range. */
+ quit_char = XINT (quit) & (tty->meta_key == 0 ? 0177 : 0377);
+
+#ifndef DOS_NT
+ init_sys_modes (tty);
#endif
+
+ return Qnil;
+}
+
+DEFUN ("set-input-mode", Fset_input_mode, Sset_input_mode, 3, 4, 0,
+ doc: /* Set mode of reading keyboard input.
+First arg INTERRUPT non-nil means use input interrupts;
+ nil means use CBREAK mode.
+Second arg FLOW non-nil means use ^S/^Q flow control for output to terminal
+ (no effect except in CBREAK mode).
+Third arg META t means accept 8-bit input (for a Meta key).
+ META nil means ignore the top bit, on the assumption it is parity.
+ Otherwise, accept 8-bit input and don't use the top bit for Meta.
+Optional fourth arg QUIT if non-nil specifies character to use for quitting.
+See also `current-input-mode'. */)
+ (interrupt, flow, meta, quit)
+ Lisp_Object interrupt, flow, meta, quit;
+{
+ Fset_input_interrupt_mode (interrupt);
+ Fset_output_flow_control (flow, Qnil);
+ Fset_input_meta_mode (meta, Qnil);
+ Fset_quit_char (quit);
return Qnil;
}
()
{
Lisp_Object val[4];
+ struct frame *sf = XFRAME (selected_frame);
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;
+ if (FRAME_TERMCAP_P (sf))
+ {
+ val[1] = FRAME_TTY (sf)->flow_control ? Qt : Qnil;
+ val[2] = (FRAME_TTY (sf)->meta_key == 2
+ ? make_number (0)
+ : (CURTTY ()->meta_key == 1 ? Qt : Qnil));
+ }
+ else
+ {
+ val[1] = Qnil;
+ val[2] = Qt;
+ }
XSETFASTINT (val[3], quit_char);
return Flist (sizeof (val) / sizeof (val[0]), val);
DEFUN ("posn-at-x-y", Fposn_at_x_y, Sposn_at_x_y, 2, 4, 0,
doc: /* Return position information for pixel coordinates X and Y.
By default, X and Y are relative to text area of the selected window.
-Optional third arg FRAME_OR_WINDOW non-nil specifies frame or window.
+Optional third arg FRAME-OR-WINDOW non-nil specifies frame or window.
If optional fourth arg WHOLE is non-nil, X is relative to the left
edge of the window.
CHECK_LIVE_WINDOW (frame_or_window);
w = XWINDOW (frame_or_window);
- XSETINT (x, (WINDOW_TO_FRAME_PIXEL_X (w, XINT (x))
+ XSETINT (x, (XINT (x)
+ + WINDOW_LEFT_EDGE_X (w)
+ (NILP (whole)
? window_box_left_offset (w, TEXT_AREA)
- : - (WINDOW_LEFT_SCROLL_BAR_COLS (w)
- * WINDOW_FRAME_COLUMN_WIDTH (w)))));
+ : 0)));
XSETINT (y, WINDOW_TO_FRAME_PIXEL_Y (w, XINT (y)));
frame_or_window = w->frame;
}
{
Lisp_Object tem;
+ if (NILP (window))
+ window = selected_window;
+
tem = Fpos_visible_in_window_p (pos, window, Qt);
if (!NILP (tem))
- tem = Fposn_at_x_y (XCAR (tem), XCAR (XCDR (tem)), window, Qnil);
+ {
+ Lisp_Object x = XCAR (tem);
+ Lisp_Object y = XCAR (XCDR (tem));
+
+ /* Point invisible due to hscrolling? */
+ if (XINT (x) < 0)
+ return Qnil;
+ tem = Fposn_at_x_y (x, y, window, Qnil);
+ }
+
return tem;
}
kb->Voverriding_terminal_local_map = Qnil;
kb->Vlast_command = Qnil;
kb->Vreal_last_command = Qnil;
+ kb->Vkeyboard_translate_table = Qnil;
kb->Vprefix_arg = Qnil;
kb->Vlast_prefix_arg = Qnil;
kb->kbd_queue = Qnil;
kb->reference_count = 0;
kb->Vsystem_key_alist = Qnil;
kb->system_key_syms = Qnil;
+ kb->Vlocal_function_key_map = Fmake_sparse_keymap (Qnil);
+ Fset_keymap_parent (kb->Vlocal_function_key_map, Vfunction_key_map);
+ kb->Vlocal_key_translation_map = Fmake_sparse_keymap (Qnil);
+ Fset_keymap_parent (kb->Vlocal_key_translation_map, Vkey_translation_map);
kb->Vdefault_minibuffer_frame = Qnil;
}
&& FRAMEP (selected_frame)
&& FRAME_LIVE_P (XFRAME (selected_frame)))
{
- current_kboard = XFRAME (selected_frame)->kboard;
+ current_kboard = XFRAME (selected_frame)->terminal->kboard;
if (current_kboard == kb)
abort ();
}
wipe_kboard (current_kboard);
init_kboard (current_kboard);
- if (!noninteractive && !read_socket_hook && NILP (Vwindow_system))
+ if (!noninteractive)
{
+ /* Before multi-tty support, these handlers used to be installed
+ only if the current session was a tty session. Now an Emacs
+ session may have multiple display types, so we always handle
+ SIGINT. There is special code in interrupt_signal to exit
+ Emacs on SIGINT when there are no termcap frames on the
+ controlling terminal. */
signal (SIGINT, interrupt_signal);
#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
/* For systems with SysV TERMIO, C-g is set up for both SIGINT and
poll_suppress_count = 1;
start_polling ();
#endif
-
-#ifdef MAC_OSX
- /* At least provide an escape route since C-g doesn't work. */
- signal (SIGINT, interrupt_signal);
-#endif
}
/* This type's only use is in syms_of_keyboard, to initialize the
Qpost_command_hook = intern ("post-command-hook");
staticpro (&Qpost_command_hook);
- Qpost_command_idle_hook = intern ("post-command-idle-hook");
- staticpro (&Qpost_command_idle_hook);
-
Qdeferred_action_function = intern ("deferred-action-function");
staticpro (&Qdeferred_action_function);
staticpro (&Qdrag_n_drop);
Qsave_session = intern ("save-session");
- staticpro(&Qsave_session);
+ staticpro (&Qsave_session);
+
+#ifdef MAC_OS
+ Qmac_apple_event = intern ("mac-apple-event");
+ staticpro (&Qmac_apple_event);
+#endif
Qusr1_signal = intern ("usr1-signal");
staticpro (&Qusr1_signal);
Fset (Qinput_method_use_echo_area, Qnil);
last_point_position_buffer = Qnil;
+ last_point_position_window = Qnil;
{
struct event_head *p;
menu_bar_one_keymap_changed_items = Qnil;
staticpro (&menu_bar_one_keymap_changed_items);
+ menu_bar_items_vector = Qnil;
+ staticpro (&menu_bar_items_vector);
+
defsubr (&Sevent_convert_list);
defsubr (&Sread_key_sequence);
defsubr (&Sread_key_sequence_vector);
defsubr (&Stop_level);
defsubr (&Sdiscard_input);
defsubr (&Sopen_dribble_file);
+ defsubr (&Sset_input_interrupt_mode);
+ defsubr (&Sset_output_flow_control);
+ defsubr (&Sset_input_meta_mode);
+ defsubr (&Sset_quit_char);
defsubr (&Sset_input_mode);
defsubr (&Scurrent_input_mode);
defsubr (&Sexecute_extended_command);
command exit.
The value `kill-region' is special; it means that the previous command
-was a kill command. */);
+was a kill command.
+
+`last-command' has a separate binding for each terminal device.
+See Info node `(elisp)Multiple displays'. */);
DEFVAR_KBOARD ("real-last-command", Vreal_last_command,
doc: /* Same as `last-command', but never altered by Lisp code. */);
Useful to set before you dump a modified Emacs. */);
Vtop_level = Qnil;
- DEFVAR_LISP ("keyboard-translate-table", &Vkeyboard_translate_table,
- doc: /* Translate table for keyboard input, or nil.
+ DEFVAR_KBOARD ("keyboard-translate-table", Vkeyboard_translate_table,
+ doc: /* Translate table for local keyboard input, or nil.
If non-nil, the value should be a char-table. Each character read
from the keyboard is looked up in this char-table. If the value found
there is non-nil, then it is used instead of the actual input character.
untranslated. In a vector, an element which is nil means "no translation".
This is applied to the characters supplied to input methods, not their
-output. See also `translation-table-for-input'. */);
- Vkeyboard_translate_table = Qnil;
+output. See also `translation-table-for-input'.
+
+This variable has a separate binding for each terminal. See Info node
+`(elisp)Multiple displays'. */);
DEFVAR_BOOL ("cannot-suspend", &cannot_suspend,
doc: /* Non-nil means to always spawn a subshell instead of suspending.
might happen repeatedly and make Emacs nonfunctional. */);
Vpost_command_hook = Qnil;
- DEFVAR_LISP ("post-command-idle-hook", &Vpost_command_idle_hook,
- doc: /* Normal hook run after each command is executed, if idle.
-Errors running the hook are caught and ignored. */);
- Vpost_command_idle_hook = Qnil;
-
- DEFVAR_INT ("post-command-idle-delay", &post_command_idle_delay,
- doc: /* Delay time before running `post-command-idle-hook'.
-This is measured in microseconds. */);
- post_command_idle_delay = 100000;
-
#if 0
DEFVAR_LISP ("echo-area-clear-hook", ...,
doc: /* Normal hook run when clearing the echo area. */);
#endif
Qecho_area_clear_hook = intern ("echo-area-clear-hook");
+ staticpro (&Qecho_area_clear_hook);
SET_SYMBOL_VALUE (Qecho_area_clear_hook, Qnil);
DEFVAR_LISP ("lucid-menu-bar-dirty-flag", &Vlucid_menu_bar_dirty_flag,
It also replaces `overriding-local-map'.
This variable is intended to let commands such as `universal-argument'
-set up a different keymap for reading the next command. */);
+set up a different keymap for reading the next command.
+
+`overriding-terminal-local-map' has a separate binding for each
+terminal device.
+See Info node `(elisp)Multiple displays'. */);
DEFVAR_LISP ("overriding-local-map", &Voverriding_local_map,
doc: /* Keymap that overrides all other local keymaps.
doc: /* Alist of system-specific X windows key symbols.
Each element should have the form (N . SYMBOL) where N is the
numeric keysym code (sans the \"system-specific\" bit 1<<28)
-and SYMBOL is its name. */);
+and SYMBOL is its name.
+
+`system-key-alist' has a separate binding for each terminal device.
+See Info node `(elisp)Multiple displays'. */);
+
+ DEFVAR_KBOARD ("local-function-key-map", Vlocal_function_key_map,
+ doc: /* Keymap that translates key sequences to key sequences during input.
+This is used mainly for mapping ASCII function key sequences into
+real Emacs function key events (symbols).
+
+The `read-key-sequence' function replaces any subsequence bound by
+`local-function-key-map' with its binding. More precisely, when the
+active keymaps have no binding for the current key sequence but
+`local-function-key-map' binds a suffix of the sequence to a vector or
+string, `read-key-sequence' replaces the matching suffix with its
+binding, and continues with the new sequence.
+
+If the binding is a function, it is called with one argument (the prompt)
+and its return value (a key sequence) is used.
+
+The events that come from bindings in `local-function-key-map' are not
+themselves looked up in `local-function-key-map'.
+
+For example, suppose `local-function-key-map' binds `ESC O P' to [f1].
+Typing `ESC O P' to `read-key-sequence' would return [f1]. Typing
+`C-x ESC O P' would return [?\\C-x f1]. If [f1] were a prefix key,
+typing `ESC O P x' would return [f1 x].
+
+`local-function-key-map' has a separate binding for each terminal
+device. See Info node `(elisp)Multiple displays'. If you need to
+define a binding on all terminals, change `function-key-map'
+instead. Initially, `local-function-key-map' is an empty keymap that
+has `function-key-map' as its parent on all terminal devices. */);
+
+ DEFVAR_LISP ("function-key-map", &Vfunction_key_map,
+ doc: /* The parent keymap of all `local-function-key-map' instances.
+Function key definitions that apply to all terminal devices should go
+here. If a mapping is defined in both the current
+`local-function-key-map' binding and this variable, then the local
+definition will take precendence. */);
+ Vfunction_key_map = Fmake_sparse_keymap (Qnil);
+
+ DEFVAR_KBOARD ("local-key-translation-map", Vlocal_key_translation_map,
+ doc: /* Keymap of key translations that can override keymaps.
+This keymap works like `function-key-map', but comes after that,
+and its non-prefix bindings override ordinary bindings.
+
+`key-translation-map' has a separate binding for each terminal device.
+(See Info node `(elisp)Multiple displays'.) If you need to set a key
+translation on all terminals, change `global-key-translation-map' instead. */);
+
+ DEFVAR_LISP ("key-translation-map", &Vkey_translation_map,
+ doc: /* The parent keymap of all `local-key-translation-map' instances.
+Key translations that apply to all terminal devices should go here. */);
+ Vkey_translation_map = Fmake_sparse_keymap (Qnil);
DEFVAR_LISP ("deferred-action-list", &Vdeferred_action_list,
doc: /* List of deferred actions to be performed at a later time.
`disable-point-adjustment' (which see) to non-nil. */);
Vglobal_disable_point_adjustment = Qnil;
- DEFVAR_BOOL ("update-menu-bindings", &update_menu_bindings,
- doc: /* Non-nil means updating menu bindings is allowed.
-A value of nil means menu bindings should not be updated.
-Used during Emacs' startup. */);
- update_menu_bindings = 1;
-
DEFVAR_LISP ("minibuffer-message-timeout", &Vminibuffer_message_timeout,
doc: /* *How long to display an echo-area message when the minibuffer is active.
If the value is not a number, such messages don't time out. */);
mark_object (kb->Voverriding_terminal_local_map);
mark_object (kb->Vlast_command);
mark_object (kb->Vreal_last_command);
+ mark_object (kb->Vkeyboard_translate_table);
mark_object (kb->Vprefix_arg);
mark_object (kb->Vlast_prefix_arg);
mark_object (kb->kbd_queue);
mark_object (kb->Vlast_kbd_macro);
mark_object (kb->Vsystem_key_alist);
mark_object (kb->system_key_syms);
+ mark_object (kb->Vlocal_function_key_map);
+ mark_object (kb->Vlocal_key_translation_map);
mark_object (kb->Vdefault_minibuffer_frame);
mark_object (kb->echo_string);
}