/* Keyboard and mouse input; editor command loop.
- Copyright (C) 1985,86,87,88,89,93,94,95,96,97 Free Software Foundation, Inc.
+ Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99, 2000
+ Free Software Foundation, Inc.
This file is part of GNU Emacs.
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Allow config.h to undefine symbols found here. */
-#include <signal.h>
-
#include <config.h>
+#include <signal.h>
#include <stdio.h>
#include "termchar.h"
#include "termopts.h"
#include "intervals.h"
#include "blockinput.h"
#include "puresize.h"
+#include "systime.h"
+#include "atimer.h"
#include <setjmp.h>
#include <errno.h>
#include "syssignal.h"
#include "systty.h"
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
/* This is to get the definitions of the XK_ symbols. */
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#ifdef HAVE_WINDOW_SYSTEM
/* Make all keyboard buffers much bigger when using X windows. */
+#ifdef macintosh
+/* But not too big (local data > 32K error) if on macintosh */
+#define KBD_BUFFER_SIZE 512
+#else
#define KBD_BUFFER_SIZE 4096
+#endif
#else /* No X-windows, character input */
#define KBD_BUFFER_SIZE 256
#endif /* No X-windows */
extern struct backtrace *backtrace_list;
+/* If non-nil, the function that implements the display of help.
+ It's called with one argument, the help string to display. */
+
+Lisp_Object Vshow_help_function;
+
/* Nonzero means do menu prompting. */
static int menu_prompting;
int waiting_for_input;
/* True while displaying for echoing. Delays C-g throwing. */
+
static int echoing;
-/* True means we can start echoing at the next input pause
- even though there is something in the echo area. */
-static char *ok_to_echo_at_next_pause;
+/* Non-null means we can start echoing at the next input pause even
+ though there is something in the echo area. */
+
+static struct kboard *ok_to_echo_at_next_pause;
+
+/* The kboard currently echoing, or null for none. Set in echo_now to
+ the kboard echoing. Reset to 0 in cancel_echoing. If non-null,
+ and a current echo area message exists, we know that it comes from
+ echoing. */
+
+static struct kboard *echo_kboard;
/* Nonzero means disregard local maps for the menu bar. */
static int inhibit_local_menu_bar_menus;
/* The command being executed by the command loop.
Commands may set this, and the value set will be copied into
current_kboard->Vlast_command instead of the actual command. */
-Lisp_Object this_command;
+Lisp_Object Vthis_command;
+
+/* This is like Vthis_command, except that commands never set it. */
+Lisp_Object real_this_command;
/* The value of point when the last command was executed. */
int last_point_position;
key sequence that it reads. */
Lisp_Object read_key_sequence_cmd;
+/* Echo unfinished commands after this many seconds of pause. */
+Lisp_Object Vecho_keystrokes;
+
/* Form to evaluate (if non-nil) when Emacs is started. */
Lisp_Object Vtop_level;
Lisp_Object Vinput_method_function;
Lisp_Object Qinput_method_function;
+/* When we call Vinput_method_function,
+ this holds the echo area message that was just erased. */
+Lisp_Object Vinput_method_previous_message;
+
/* Non-nil means deactivate the mark at end of this command. */
Lisp_Object Vdeactivate_mark;
Lisp_Object Vdeferred_action_function;
Lisp_Object Qdeferred_action_function;
+Lisp_Object Qinput_method_exit_on_first_char;
+Lisp_Object Qinput_method_use_echo_area;
+
/* 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]. */
-static volatile struct input_event *kbd_store_ptr;
+static struct input_event * volatile kbd_store_ptr;
/* The above pair of variables forms a "queue empty" flag. When we
enqueue a non-hook event, we increment kbd_store_ptr. When we
Lisp_Object Qdelete_frame;
Lisp_Object Qiconify_frame;
Lisp_Object Qmake_frame_visible;
+Lisp_Object Qhelp_echo;
/* Symbols to denote kinds of events. */
Lisp_Object Qfunction_key;
Lisp_Object Qmouse_click;
#ifdef WINDOWSNT
Lisp_Object Qmouse_wheel;
+Lisp_Object Qlanguage_change;
#endif
Lisp_Object Qdrag_n_drop;
/* Lisp_Object Qmouse_movement; - also an event header */
#ifdef HAVE_WINDOW_SYSTEM
#define POLL_FOR_INPUT
#endif
+
+/* After a command is executed, if point is moved into a region that
+ has specific properties (e.g. composition, display), we adjust
+ point to the boundary of the region. But, if a command sets this
+ valiable to non-nil, we suppress this point adjustment. This
+ variable is set to nil before reading a command. */
+Lisp_Object Vdisable_point_adjustment;
+
+/* If non-nil, always disable point adjustment. */
+Lisp_Object Vglobal_disable_point_adjustment;
+
\f
/* Global variable declarations. */
static int parse_solitary_modifier ();
static void save_getcjmp ();
static void restore_getcjmp ();
-
-/* > 0 if we are to echo keystrokes. */
-static int echo_keystrokes;
+static Lisp_Object apply_modifiers P_ ((int, Lisp_Object));
/* Nonzero means don't try to suspend even if the operating system seems
to support it. */
if (INTEGERP (c))
{
- if (ptr - current_kboard->echobuf > ECHOBUFSIZE - 6)
+ if (ptr - current_kboard->echobuf
+ > ECHOBUFSIZE - KEY_DESCRIPTION_SIZE)
return;
ptr = push_key_description (XINT (c), ptr);
}
echoing = 1;
+ echo_kboard = current_kboard;
message2_nolog (current_kboard->echobuf, strlen (current_kboard->echobuf),
! NILP (current_buffer->enable_multibyte_characters));
-
echoing = 0;
if (waiting_for_input && !NILP (Vquit_flag))
current_kboard->echoptr = current_kboard->echobuf;
current_kboard->echo_after_prompt = -1;
ok_to_echo_at_next_pause = 0;
+ echo_kboard = 0;
}
/* Return the length of the current echo string. */
()
{
int count = specpdl_ptr - specpdl;
- Lisp_Object val;
command_loop_level++;
update_mode_lines = 1;
char *context;
{
Lisp_Object stream;
+ int kill_emacs_p = 0;
+ struct frame *sf = SELECTED_FRAME ();
Vquit_flag = Qnil;
Vinhibit_quit = Qt;
- echo_area_glyphs = 0;
+ clear_message (1, 0);
/* If the window system or terminal frame hasn't been initialized
yet, or we're not interactive, it's best to dump this message out
to stderr and exit. */
- if (! FRAME_MESSAGE_BUF (selected_frame)
+ 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))
|| noninteractive)
- stream = Qexternal_debugging_output;
+ {
+ stream = Qexternal_debugging_output;
+ kill_emacs_p = 1;
+ }
else
{
Fdiscard_input ();
/* If the window system or terminal frame hasn't been initialized
yet, or we're in -batch mode, this error should cause Emacs to exit. */
- if (! FRAME_MESSAGE_BUF (selected_frame)
- || noninteractive)
+ if (kill_emacs_p)
{
Fterpri (stream);
Fkill_emacs (make_number (-1));
{
if (command_loop_level > 0 || minibuf_level > 0)
{
- Lisp_Object val = internal_catch (Qexit, command_loop_2, Qnil);
+ Lisp_Object val;
+ val = internal_catch (Qexit, command_loop_2, Qnil);
executing_macro = Qnil;
return val;
}
Lisp_Object Fcommand_execute ();
static int read_key_sequence ();
void safe_run_hooks ();
+static void adjust_point_for_property ();
Lisp_Object
command_loop_1 ()
{
- Lisp_Object cmd, tem;
- int lose, lose2;
+ Lisp_Object cmd;
+ int lose;
int nonundocount;
Lisp_Object keybuf[30];
int i;
- int no_redisplay;
int no_direct;
int prev_modiff;
struct buffer *prev_buffer;
cancel_echoing ();
nonundocount = 0;
- no_redisplay = 0;
this_command_key_count = 0;
this_single_command_key_start = 0;
if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
safe_run_hooks (Qpost_command_hook);
+ /* If displaying a message, resize the echo area window to fit
+ that message's size exactly. */
+ if (!NILP (echo_area_buffer[0]))
+ resize_echo_area_axactly ();
+
if (!NILP (Vdeferred_action_list))
call0 (Vdeferred_action_function);
}
/* Do this after running Vpost_command_hook, for consistency. */
- current_kboard->Vlast_command = this_command;
- current_kboard->Vreal_last_command = this_command;
+ current_kboard->Vlast_command = Vthis_command;
+ current_kboard->Vreal_last_command = real_this_command;
while (1)
{
+ if (! FRAME_LIVE_P (XFRAME (selected_frame)))
+ Fkill_emacs (Qnil);
+
/* Make sure the current window's buffer is selected. */
if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
/* If minibuffer on and echo area in use,
wait 2 sec and redraw minibuffer. */
- if (minibuf_level && echo_area_glyphs
+ if (minibuf_level
+ && !NILP (echo_area_buffer[0])
&& EQ (minibuf_window, echo_area_window))
{
/* Bind inhibit-quit to t so that C-g gets read in
code swallows a switch-frame event, we'll fix things up here.
Is this a good idea? */
if (FRAMEP (internal_last_event_frame)
- && XFRAME (internal_last_event_frame) != selected_frame)
+ && !EQ (internal_last_event_frame, selected_frame))
Fselect_frame (internal_last_event_frame, Qnil);
#endif
/* If it has changed current-menubar from previous value,
before_command_key_count = this_command_key_count;
before_command_echo_length = echo_length ();
- this_command = Qnil;
+ Vthis_command = Qnil;
+ real_this_command = Qnil;
/* Read next key sequence; i gets its length. */
i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
Qnil, 0, 1, 1);
/* A filter may have run while we were reading the input. */
+ if (! FRAME_LIVE_P (XFRAME (selected_frame)))
+ Fkill_emacs (Qnil);
if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
update the whole window properly. */
if (!NILP (XWINDOW (selected_window)->force_start))
{
+ struct buffer *b;
XWINDOW (selected_window)->force_start = Qnil;
- beg_unchanged = end_unchanged = 0;
+ b = XBUFFER (XWINDOW (selected_window)->buffer);
+ BUF_BEG_UNCHANGED (b) = BUF_END_UNCHANGED (b) = 0;
}
cmd = read_key_sequence_cmd;
}
/* Do redisplay processing after this command except in special
- cases identified below that set no_redisplay to 1.
- (actually, there's currently no way to prevent the redisplay,
- and no_redisplay is ignored.
- Perhaps someday we will really implement it.) */
- no_redisplay = 0;
-
+ cases identified below. */
prev_buffer = current_buffer;
prev_modiff = MODIFF;
last_point_position = PT;
XSETBUFFER (last_point_position_buffer, prev_buffer);
+ /* By default, we adjust point to a boundary of a region that
+ has such a property that should be treated intangible
+ (e.g. composition, display). But, some commands will set
+ this variable differently. */
+ Vdisable_point_adjustment = Qnil;
+
/* Execute the command. */
- this_command = cmd;
+ Vthis_command = cmd;
+ real_this_command = cmd;
/* Note that the value cell will never directly contain nil
if the symbol is a local variable. */
if (!NILP (Vpre_command_hook) && !NILP (Vrun_hooks))
safe_run_hooks (Qpre_command_hook);
- if (NILP (this_command))
+ if (NILP (Vthis_command))
{
/* nil means key is undefined. */
bitch_at_user ();
/* Recognize some common commands in common situations and
do them directly. */
- if (EQ (this_command, Qforward_char) && PT < ZV)
+ if (EQ (Vthis_command, Qforward_char) && PT < ZV)
{
struct Lisp_Char_Table *dp
= window_display_table (XWINDOW (selected_window));
&& !detect_input_pending ()
&& NILP (XWINDOW (selected_window)->column_number_displayed)
&& NILP (Vexecuting_macro))
- no_redisplay = direct_output_forward_char (1);
+ direct_output_forward_char (1);
goto directly_done;
}
- else if (EQ (this_command, Qbackward_char) && PT > BEGV)
+ else if (EQ (Vthis_command, Qbackward_char) && PT > BEGV)
{
struct Lisp_Char_Table *dp
= window_display_table (XWINDOW (selected_window));
&& !detect_input_pending ()
&& NILP (XWINDOW (selected_window)->column_number_displayed)
&& NILP (Vexecuting_macro))
- no_redisplay = direct_output_forward_char (-1);
+ direct_output_forward_char (-1);
goto directly_done;
}
- else if (EQ (this_command, Qself_insert_command)
+ else if (EQ (Vthis_command, Qself_insert_command)
/* Try this optimization only on ascii keystrokes. */
&& INTEGERP (last_command_char))
{
unsigned int c = XINT (last_command_char);
int value;
-
if (NILP (Vexecuting_macro)
&& !EQ (minibuf_window, selected_window))
{
}
nonundocount++;
}
+
lose = ((XFASTINT (XWINDOW (selected_window)->last_modified)
< MODIFF)
|| (XFASTINT (XWINDOW (selected_window)->last_overlay_modified)
|| detect_input_pending ()
|| !NILP (XWINDOW (selected_window)->column_number_displayed)
|| !NILP (Vexecuting_macro));
+
value = internal_self_insert (c, 0);
- if (value)
- lose = 1;
+
if (value == 2)
nonundocount = 0;
- if (!lose
- && (PT == ZV || FETCH_BYTE (PT_BYTE) == '\n'))
- {
- struct Lisp_Char_Table *dp
- = window_display_table (XWINDOW (selected_window));
- int lose = c;
-
- /* Add the offset to the character, for Finsert_char.
- We pass internal_self_insert the unmodified character
- because it itself does this offsetting. */
- if (! NILP (current_buffer->enable_multibyte_characters))
- lose = unibyte_char_to_multibyte (lose);
-
- if (dp)
- {
- Lisp_Object obj;
-
- obj = DISP_CHAR_VECTOR (dp, lose);
- if (NILP (obj))
- {
- /* Do it only for char codes
- that by default display as themselves. */
- if (lose >= 0x20 && lose <= 0x7e)
- no_redisplay = direct_output_for_insert (lose);
- }
- else if (VECTORP (obj)
- && XVECTOR (obj)->size == 1
- && (obj = XVECTOR (obj)->contents[0],
- INTEGERP (obj))
- /* Insist face not specified in glyph. */
- && (XINT (obj) & ((-1) << 8)) == 0)
- no_redisplay
- = direct_output_for_insert (XINT (obj));
- }
- else
- {
- if (lose >= 0x20 && lose <= 0x7e)
- no_redisplay = direct_output_for_insert (lose);
- }
- }
+ /* VALUE == 1 when AFTER-CHANGE functions are
+ installed which is the case most of the time
+ because FONT-LOCK installs one. */
+ if (!lose && !value)
+ direct_output_for_insert (c);
goto directly_done;
}
}
/* Here for a command that isn't executed directly */
+#ifdef HAVE_X_WINDOWS
+ if (display_busy_cursor_p)
+ start_busy_cursor ();
+#endif
+
nonundocount = 0;
if (NILP (current_kboard->Vprefix_arg))
Fundo_boundary ();
- Fcommand_execute (this_command, Qnil, Qnil, Qnil);
+ Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil);
+
+#ifdef HAVE_X_WINDOWS
+ if (display_busy_cursor_p)
+ cancel_busy_cursor ();
+#endif
}
directly_done: ;
current_kboard->Vlast_prefix_arg = Vcurrent_prefix_arg;
if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
safe_run_hooks (Qpost_command_hook);
+ /* If displaying a message, resize the echo area window to fit
+ that message's size exactly. */
+ if (!NILP (echo_area_buffer[0]))
+ resize_echo_area_axactly ();
+
if (!NILP (Vdeferred_action_list))
safe_run_hooks (Qdeferred_action_function);
then the above doesn't apply. */
if (NILP (current_kboard->Vprefix_arg) || CONSP (last_command_char))
{
- current_kboard->Vlast_command = this_command;
- current_kboard->Vreal_last_command = this_command;
+ current_kboard->Vlast_command = Vthis_command;
+ current_kboard->Vreal_last_command = real_this_command;
cancel_echoing ();
this_command_key_count = 0;
this_single_command_key_start = 0;
}
finalize:
+
+ if (current_buffer == prev_buffer
+ && last_point_position != PT
+ && NILP (Vdisable_point_adjustment)
+ && NILP (Vglobal_disable_point_adjustment))
+ adjust_point_for_property (last_point_position);
+
/* Install chars successfully executed in kbd macro. */
if (!NILP (current_kboard->defining_kbd_macro)
}
}
+extern Lisp_Object Qcomposition, Qdisplay;
+
+/* Adjust point to a boundary of a region that has such a property
+ that should be treated intangible. For the moment, we check
+ `composition' and `display' property. LAST_PT is the last position
+ of point. */
+
+static void
+adjust_point_for_property (last_pt)
+ int last_pt;
+{
+ int start, end;
+ Lisp_Object val;
+ int check_composition = 1, check_display = 1;
+
+ while (check_composition || check_display)
+ {
+ if (check_composition
+ && PT > BEGV && PT < ZV
+ && get_property_and_range (PT, Qcomposition, &val, &start, &end, Qnil)
+ && COMPOSITION_VALID_P (start, end, val)
+ && start < PT && end > PT
+ && (last_pt <= start || last_pt >= end))
+ {
+ if (PT < last_pt)
+ SET_PT (start);
+ else
+ SET_PT (end);
+ check_display = 1;
+ }
+ check_composition = 0;
+ if (check_display
+ && PT > BEGV && PT < ZV
+ && get_property_and_range (PT, Qdisplay, &val, &start, &end, Qnil)
+ && start < PT && end > PT
+ && (last_pt <= start || last_pt >= end))
+ {
+ if (PT < last_pt)
+ SET_PT (start);
+ else
+ SET_PT (end);
+ check_composition = 1;
+ }
+ check_display = 0;
+ }
+}
+
/* Subroutine for safe_run_hooks: run the hook HOOK. */
static Lisp_Object
safe_run_hooks (hook)
Lisp_Object hook;
{
- Lisp_Object value;
int count = specpdl_ptr - specpdl;
specbind (Qinhibit_quit, hook);
unbind_to (count, Qnil);
}
+
\f
-/* Number of seconds between polling for input. */
+/* Number of seconds between polling for input. This is a Lisp
+ variable that can be bound. */
+
int polling_period;
/* Nonzero means polling for input is temporarily suppressed. */
+
int poll_suppress_count;
-/* Nonzero if polling_for_input is actually being used. */
-int polling_for_input;
+/* Asynchronous timer for polling. */
+
+struct atimer *poll_timer;
+
#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. */
+/* Poll for input, so what we catch a C-g if it comes in. This
+ function is called from x_make_frame_visible, see comment
+ there. */
-SIGTYPE
-input_poll_signal (signalnum) /* If we don't have an argument, */
- int signalnum; /* some compilers complain in signal calls. */
+void
+poll_for_input_1 ()
{
- /* This causes the call to start_polling at the end
- to do its job. It also arranges for a quit or error
- from within read_avail_input to resume polling. */
- poll_suppress_count++;
if (interrupt_input_blocked == 0
&& !waiting_for_input)
read_avail_input (0);
- /* Turn on the SIGALRM handler and request another alarm. */
- start_polling ();
}
-#endif
+/* Timer callback function for poll_timer. TIMER is equal to
+ poll_timer. */
+
+void
+poll_for_input (timer)
+ struct atimer *timer;
+{
+ if (poll_suppress_count == 0)
+ poll_for_input_1 ();
+}
+
+#endif /* POLL_FOR_INPUT */
/* Begin signals to poll for input, if they are appropriate.
This function is called unconditionally from various places. */
#ifdef POLL_FOR_INPUT
if (read_socket_hook && !interrupt_input)
{
- poll_suppress_count--;
- if (poll_suppress_count == 0)
+ /* Turn alarm handling on unconditionally. It might have
+ been turned off in process.c. */
+ turn_on_atimers (1);
+
+ /* If poll timer doesn't exist, are we need one with
+ a different interval, start a new one. */
+ if (poll_timer == NULL
+ || EMACS_SECS (poll_timer->interval) != polling_period)
{
- signal (SIGALRM, input_poll_signal);
- polling_for_input = 1;
- alarm (polling_period);
+ EMACS_TIME interval;
+
+ if (poll_timer)
+ cancel_atimer (poll_timer);
+
+ EMACS_SET_SECS_USECS (interval, polling_period, 0);
+ poll_timer = start_atimer (ATIMER_CONTINUOUS, interval,
+ poll_for_input, NULL);
}
+
+ /* Let the timer's callback function poll for input
+ if this becomes zero. */
+ --poll_suppress_count;
}
#endif
}
{
#ifdef POLL_FOR_INPUT
if (read_socket_hook && !interrupt_input)
- {
- if (poll_suppress_count == 0)
- {
- polling_for_input = 0;
- alarm (0);
- }
- poll_suppress_count++;
- }
+ ++poll_suppress_count;
#endif
}
if (n > new)
new = n;
+ stop_other_atimers (poll_timer);
stop_polling ();
specbind (Qpolling_period, make_number (new));
/* Start a new alarm with the new period. */
MAPS is an array of keymaps; NMAPS is the length of MAPS.
PREV_EVENT is the previous input event, or nil if we are reading
- the first event of a key sequence.
+ the first event of a key sequence (or not reading a key sequence).
+ If PREV_EVENT is t, that is a "magic" value that says
+ not to run input methods, but in other respects to act as if
+ not reading a key sequence.
If USED_MOUSE_MENU is non-null, then we set *USED_MOUSE_MENU to 1
if we used a mouse menu to read the input, or zero otherwise. If
jmp_buf save_jump;
int key_already_recorded = 0;
Lisp_Object tem, save;
+ Lisp_Object previous_echo_area_message;
Lisp_Object also_record;
int reread;
- struct gcpro gcpro1;
+ struct gcpro gcpro1, gcpro2;
also_record = Qnil;
before_command_key_count = this_command_key_count;
before_command_echo_length = echo_length ();
c = Qnil;
+ previous_echo_area_message = Qnil;
- GCPRO1 (c);
+ GCPRO2 (c, previous_echo_area_message);
retry:
reread = 0;
if (CONSP (Vunread_post_input_method_events))
{
- c = XCONS (Vunread_post_input_method_events)->car;
+ c = XCAR (Vunread_post_input_method_events);
Vunread_post_input_method_events
- = XCONS (Vunread_post_input_method_events)->cdr;
+ = XCDR (Vunread_post_input_method_events);
/* Undo what read_char_x_menu_prompt did when it unread
additional keys returned by Fx_popup_menu. */
if (CONSP (c)
- && (SYMBOLP (XCONS (c)->car) || INTEGERP (XCONS (c)->car))
- && NILP (XCONS (c)->cdr))
- c = XCONS (c)->car;
+ && (SYMBOLP (XCAR (c)) || INTEGERP (XCAR (c)))
+ && NILP (XCDR (c)))
+ c = XCAR (c);
reread = 1;
goto reread_first;
if (CONSP (Vunread_command_events))
{
- c = XCONS (Vunread_command_events)->car;
- Vunread_command_events = XCONS (Vunread_command_events)->cdr;
+ c = XCAR (Vunread_command_events);
+ Vunread_command_events = XCDR (Vunread_command_events);
/* Undo what read_char_x_menu_prompt did when it unread
additional keys returned by Fx_popup_menu. */
if (CONSP (c)
- && (SYMBOLP (XCONS (c)->car) || INTEGERP (XCONS (c)->car))
- && NILP (XCONS (c)->cdr))
- c = XCONS (c)->car;
+ && (SYMBOLP (XCAR (c)) || INTEGERP (XCAR (c)))
+ && NILP (XCDR (c)))
+ c = XCAR (c);
reread = 1;
goto reread_for_input_method;
if (CONSP (Vunread_input_method_events))
{
- c = XCONS (Vunread_input_method_events)->car;
- Vunread_input_method_events = XCONS (Vunread_input_method_events)->cdr;
+ c = XCAR (Vunread_input_method_events);
+ Vunread_input_method_events = XCDR (Vunread_input_method_events);
/* Undo what read_char_x_menu_prompt did when it unread
additional keys returned by Fx_popup_menu. */
if (CONSP (c)
- && (SYMBOLP (XCONS (c)->car) || INTEGERP (XCONS (c)->car))
- && NILP (XCONS (c)->cdr))
- c = XCONS (c)->car;
+ && (SYMBOLP (XCAR (c)) || INTEGERP (XCAR (c)))
+ && NILP (XCDR (c)))
+ c = XCAR (c);
reread = 1;
goto reread_for_input_method;
}
}
/* Message turns off echoing unless more keystrokes turn it on again. */
- if (echo_area_glyphs && *echo_area_glyphs
- && echo_area_glyphs != current_kboard->echobuf
- && ok_to_echo_at_next_pause != echo_area_glyphs)
+ if (/* There is a current message. */
+ !NILP (echo_area_buffer[0])
+ /* And we're not echoing from this kboard. */
+ && echo_kboard != current_kboard
+ /* And it's either not ok to echo (ok_to_echo == NULL), or the
+ last char echoed was from a different kboard. */
+ && ok_to_echo_at_next_pause != echo_kboard)
cancel_echoing ();
else
/* If already echoing, continue. */
if (_setjmp (local_getcjmp))
{
XSETINT (c, quit_char);
- XSETFRAME (internal_last_event_frame, selected_frame);
+ internal_last_event_frame = selected_frame;
Vlast_event_frame = internal_last_event_frame;
/* If we report the quit char as an event,
don't do so more than once. */
#ifdef MULTI_KBOARD
{
- KBOARD *kb = FRAME_KBOARD (selected_frame);
+ KBOARD *kb = FRAME_KBOARD (XFRAME (selected_frame));
if (kb != current_kboard)
{
Lisp_Object *tailp = &kb->kbd_queue;
if (single_kboard)
abort ();
while (CONSP (*tailp))
- tailp = &XCONS (*tailp)->cdr;
+ tailp = &XCDR (*tailp);
if (!NILP (*tailp))
abort ();
*tailp = Fcons (c, Qnil);
/* If in middle of key sequence and minibuffer not active,
start echoing if enough time elapses. */
- if (minibuf_level == 0 && !current_kboard->immediate_echo
+ if (minibuf_level == 0
+ && !current_kboard->immediate_echo
&& this_command_key_count > 0
&& ! noninteractive
- && echo_keystrokes > 0
- && (echo_area_glyphs == 0 || *echo_area_glyphs == 0
- || ok_to_echo_at_next_pause == echo_area_glyphs))
+ && (FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
+ && NILP (Fzerop (Vecho_keystrokes))
+ && (/* No message. */
+ NILP (echo_area_buffer[0])
+ /* Or empty message. */
+ || (BUF_BEG (XBUFFER (echo_area_buffer[0]))
+ == BUF_Z (XBUFFER (echo_area_buffer[0])))
+ /* Or already echoing from same kboard. */
+ || (echo_kboard && ok_to_echo_at_next_pause == echo_kboard)
+ /* Or not echoing before and echoing allowed. */
+ || (!echo_kboard && ok_to_echo_at_next_pause)))
{
Lisp_Object tem0;
-
+
/* After a mouse event, start echoing right away.
This is because we are probably about to display a menu,
and we don't want to delay before doing so. */
echo_now ();
else
{
+ int sec, usec;
+ double duration = extract_float (Vecho_keystrokes);
+ sec = (int) duration;
+ usec += (duration - sec) * 1000000;
save_getcjmp (save_jump);
restore_getcjmp (local_getcjmp);
- tem0 = sit_for (echo_keystrokes, 0, 1, 1, 0);
+ tem0 = sit_for (sec, usec, 1, 1, 0);
restore_getcjmp (save_jump);
if (EQ (tem0, Qt)
&& ! CONSP (Vunread_command_events))
if (nmaps > 0 && INTERACTIVE
&& !NILP (prev_event)
&& EVENT_HAS_PARAMETERS (prev_event)
- && !EQ (XCONS (prev_event)->car, Qmenu_bar)
+ && !EQ (XCAR (prev_event), Qmenu_bar)
+ && !EQ (XCAR (prev_event), Qtool_bar)
/* Don't bring up a menu if we already have another event. */
&& NILP (Vunread_command_events)
&& unread_command_char < 0)
or sentinel or filter. */
if (CONSP (Vunread_command_events))
{
- c = XCONS (Vunread_command_events)->car;
- Vunread_command_events = XCONS (Vunread_command_events)->cdr;
+ c = XCAR (Vunread_command_events);
+ Vunread_command_events = XCDR (Vunread_command_events);
}
/* Read something from current KBOARD's side queue, if possible. */
{
if (!CONSP (current_kboard->kbd_queue))
abort ();
- c = XCONS (current_kboard->kbd_queue)->car;
+ c = XCAR (current_kboard->kbd_queue);
current_kboard->kbd_queue
- = XCONS (current_kboard->kbd_queue)->cdr;
+ = XCDR (current_kboard->kbd_queue);
if (NILP (current_kboard->kbd_queue))
current_kboard->kbd_queue_has_data = 0;
input_pending = readable_events (0);
if (EVENT_HAS_PARAMETERS (c)
&& EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qswitch_frame))
- internal_last_event_frame = XCONS (XCONS (c)->cdr)->car;
+ internal_last_event_frame = XCAR (XCDR (c));
Vlast_event_frame = internal_last_event_frame;
}
}
{
Lisp_Object *tailp = &kb->kbd_queue;
while (CONSP (*tailp))
- tailp = &XCONS (*tailp)->cdr;
+ tailp = &XCDR (*tailp);
if (!NILP (*tailp))
abort ();
*tailp = Fcons (c, Qnil);
goto retry;
}
- /* Wipe the echo area. */
- if (echo_area_glyphs)
- safe_run_hooks (Qecho_area_clear_hook);
- echo_area_glyphs = 0;
-
/* Handle things that only apply to characters. */
if (INTEGERP (c))
{
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 (XCDR (c))
&& CONSP (EVENT_START (c))
- && CONSP (XCONS (EVENT_START (c))->cdr))
+ && CONSP (XCDR (EVENT_START (c))))
{
Lisp_Object posn;
posn = POSN_BUFFER_POSN (EVENT_START (c));
/* Handle menu-bar events:
insert the dummy prefix event `menu-bar'. */
- if (EQ (posn, Qmenu_bar))
+ if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar))
{
/* Change menu-bar to (menu-bar) as the event "position". */
POSN_BUFFER_POSN (EVENT_START (c)) = Fcons (posn, Qnil);
if (! NILP (also_record))
record_char (also_record);
+ /* Wipe the echo area.
+ But first, if we are about to use an input method,
+ save the echo area contents for it to refer to. */
+ if (INTEGERP (c)
+ && ! NILP (Vinput_method_function)
+ && (unsigned) XINT (c) >= ' '
+ && (unsigned) XINT (c) < 127)
+ {
+ previous_echo_area_message = Fcurrent_message ();
+ Vinput_method_previous_message = previous_echo_area_message;
+ }
+
+ /* Now wipe the echo area. */
+ if (!NILP (echo_area_buffer[0]))
+ safe_run_hooks (Qecho_area_clear_hook);
+ clear_message (1, 0);
+
reread_for_input_method:
from_macro:
/* Pass this to the input method, if appropriate. */
- if (INTEGERP (c))
- {
- /* If this is a printing character, run the input method. */
- if (! NILP (Vinput_method_function)
- && (unsigned) XINT (c) >= ' '
- && (unsigned) XINT (c) < 127)
+ if (INTEGERP (c)
+ && ! NILP (Vinput_method_function)
+ /* Don't run the input method within a key sequence,
+ after the first event of the key sequence. */
+ && NILP (prev_event)
+ && (unsigned) XINT (c) >= ' '
+ && (unsigned) XINT (c) < 127)
+ {
+ Lisp_Object keys;
+ int key_count;
+ struct gcpro gcpro1;
+ int count = specpdl_ptr - specpdl;
+
+ /* Save the echo status. */
+ int saved_immediate_echo = current_kboard->immediate_echo;
+ struct kboard *saved_ok_to_echo = ok_to_echo_at_next_pause;
+ int saved_echo_after_prompt = current_kboard->echo_after_prompt;
+
+ if (before_command_restore_flag)
{
- int saved = current_kboard->immediate_echo;
- tem = call1 (Vinput_method_function, c);
- current_kboard->immediate_echo = saved;
- /* The input method can return no events. */
- if (! CONSP (tem))
- goto retry;
- /* It returned one event or more. */
- c = XCONS (tem)->car;
- Vunread_post_input_method_events
- = nconc2 (XCONS (tem)->cdr, Vunread_post_input_method_events);
+ this_command_key_count = before_command_key_count_1;
+ if (this_command_key_count < this_single_command_key_start)
+ this_single_command_key_start = this_command_key_count;
+ echo_truncate (before_command_echo_length_1);
+ before_command_restore_flag = 0;
}
+
+ /* Save the this_command_keys status. */
+ key_count = this_command_key_count;
+
+ if (key_count > 0)
+ keys = Fcopy_sequence (this_command_keys);
+ else
+ keys = Qnil;
+ GCPRO1 (keys);
+
+ /* Clear out this_command_keys. */
+ this_command_key_count = 0;
+
+ /* Now wipe the echo area. */
+ if (!NILP (echo_area_buffer[0]))
+ safe_run_hooks (Qecho_area_clear_hook);
+ clear_message (1, 0);
+ echo_truncate (0);
+
+ /* If we are not reading a key sequence,
+ never use the echo area. */
+ if (maps == 0)
+ {
+ specbind (Qinput_method_use_echo_area, Qt);
+ }
+
+ /* Call the input method. */
+ tem = call1 (Vinput_method_function, c);
+
+ tem = unbind_to (count, tem);
+
+ /* Restore the saved echoing state
+ and this_command_keys state. */
+ this_command_key_count = key_count;
+ if (key_count > 0)
+ this_command_keys = keys;
+
+ cancel_echoing ();
+ ok_to_echo_at_next_pause = saved_ok_to_echo;
+ current_kboard->echo_after_prompt = saved_echo_after_prompt;
+ if (saved_immediate_echo)
+ echo_now ();
+
+ UNGCPRO;
+
+ /* The input method can return no events. */
+ if (! CONSP (tem))
+ {
+ /* Bring back the previous message, if any. */
+ if (! NILP (previous_echo_area_message))
+ message_with_string ("%s", previous_echo_area_message, 0);
+ goto retry;
+ }
+ /* It returned one event or more. */
+ c = XCAR (tem);
+ Vunread_post_input_method_events
+ = nconc2 (XCDR (tem), Vunread_post_input_method_events);
}
reread_first:
+ /* Display help if not echoing. */
+ if (CONSP (c)
+ && EQ (XCAR (c), Qhelp_echo))
+ {
+ Lisp_Object msg = XCDR (XCDR (c));
+
+ if (!NILP (Vshow_help_function))
+ call1 (Vshow_help_function, msg);
+ else if (!echoing && !MINI_WINDOW_P (XWINDOW (selected_window)))
+ {
+ if (STRINGP (msg))
+ message3_nolog (msg, XSTRING (msg)->size, STRING_MULTIBYTE (msg));
+ else
+ message (0);
+ }
+
+ goto retry;
+ }
+
if (this_command_key_count == 0 || ! reread)
{
before_command_key_count = this_command_key_count;
before_command_echo_length = echo_length ();
/* Don't echo mouse motion events. */
- if (echo_keystrokes
+ if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
+ && NILP (Fzerop (Vecho_keystrokes))
&& ! (EVENT_HAS_PARAMETERS (c)
&& EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
{
echo_char (also_record);
/* Once we reread a character, echoing can happen
the next time we pause to read a new one. */
- ok_to_echo_at_next_pause = echo_area_glyphs;
+ ok_to_echo_at_next_pause = current_kboard;
}
/* Record this character as part of the current key. */
Lisp_Object c;
{
/* Wipe the echo area. */
- echo_area_glyphs = 0;
+ clear_message (1, 0);
record_char (c);
before_command_echo_length = echo_length ();
/* Don't echo mouse motion events. */
- if (echo_keystrokes)
+ if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
+ && NILP (Fzerop (Vecho_keystrokes)))
{
echo_char (c);
if (EQ (c, Vhelp_char))
return 1;
- for (tail = Vhelp_event_list; CONSP (tail); tail = XCONS (tail)->cdr)
- if (EQ (c, XCONS (tail)->car))
+ for (tail = Vhelp_event_list; CONSP (tail); tail = XCDR (tail))
+ if (EQ (c, XCAR (tail)))
return 1;
return 0;
}
Lisp_Object frame;
frame = event->frame_or_window;
if (CONSP (frame))
- frame = XCONS (frame)->car;
+ frame = XCAR (frame);
else if (WINDOWP (frame))
frame = WINDOW_FRAME (XWINDOW (frame));
Discard the event if it would fill the last slot. */
if (kbd_fetch_ptr - 1 != kbd_store_ptr)
{
- volatile struct input_event *sp = kbd_store_ptr;
+ struct input_event *sp = kbd_store_ptr;
sp->kind = event->kind;
if (event->kind == selection_request_event)
{
{
register int c;
Lisp_Object obj;
- EMACS_TIME next_timer_delay;
if (noninteractive)
{
if (CONSP (Vunread_command_events))
{
Lisp_Object first;
- first = XCONS (Vunread_command_events)->car;
- Vunread_command_events = XCONS (Vunread_command_events)->cdr;
+ first = XCAR (Vunread_command_events);
+ Vunread_command_events = XCDR (Vunread_command_events);
*kbp = current_kboard;
return first;
}
if (FRAME_LIVE_P (XFRAME (event->frame_or_window)))
x_activate_menubar (XFRAME (event->frame_or_window));
}
+#endif
+#ifdef WINDOWSNT
+ else if (event->kind == language_change_event)
+ {
+ /* Make an event (language-change (FRAME CHARSET LCID)). */
+ obj = Fcons (event->modifiers, Qnil);
+ obj = Fcons (event->code, Qnil);
+ obj = Fcons (event->frame_or_window, obj);
+ obj = Fcons (Qlanguage_change, Fcons (obj, Qnil));
+ kbd_fetch_ptr = event + 1;
+ }
#endif
/* Just discard these, by returning nil.
With MULTI_KBOARD, these events are used as placeholders
mouse events during a popup-menu call. */
else if (event->kind == no_event)
kbd_fetch_ptr = event + 1;
-
+ else if (event->kind == HELP_EVENT)
+ {
+ /* The car of event->frame_or_window is a frame,
+ the cdr is the help to display. */
+ obj = Fcons (Qhelp_echo, event->frame_or_window);
+ kbd_fetch_ptr = event + 1;
+ }
/* If this event is on a different frame, return a switch-frame this
time, and leave the event in the queue for next time. */
else
frame = event->frame_or_window;
if (CONSP (frame))
- frame = XCONS (frame)->car;
+ frame = XCAR (frame);
else if (WINDOWP (frame))
frame = WINDOW_FRAME (XWINDOW (frame));
frame = focus;
if (! EQ (frame, internal_last_event_frame)
- && XFRAME (frame) != selected_frame)
+ && !EQ (frame, selected_frame))
obj = make_lispy_switch_frame (frame);
internal_last_event_frame = frame;
we're returning is (menu-bar), though; that indicates the
beginning of the menu sequence, and we might as well leave
that as the `event with parameters' for this selection. */
- if (event->kind == menu_bar_event
- && !(CONSP (obj) && EQ (XCONS (obj)->car, Qmenu_bar))
+ if ((event->kind == menu_bar_event
+ || event->kind == TOOL_BAR_EVENT)
+ && !(CONSP (obj) && EQ (XCAR (obj), Qmenu_bar))
+ && !(CONSP (obj) && EQ (XCAR (obj), Qtool_bar))
&& used_mouse_menu)
*used_mouse_menu = 1;
#endif
XSETFRAME (frame, f);
if (! EQ (frame, internal_last_event_frame)
- && XFRAME (frame) != selected_frame)
+ && !EQ (frame, selected_frame))
obj = make_lispy_switch_frame (frame);
internal_last_event_frame = frame;
}
EMACS_GET_TIME (timer_idleness_start_time);
/* Mark all idle-time timers as once again candidates for running. */
- for (timers = Vtimer_idle_list; CONSP (timers); timers = XCONS (timers)->cdr)
+ for (timers = Vtimer_idle_list; CONSP (timers); timers = XCDR (timers))
{
Lisp_Object timer;
- timer = XCONS (timers)->car;
+ timer = XCAR (timers);
if (!VECTORP (timer) || XVECTOR (timer)->size != 8)
continue;
while (CONSP (timers) || CONSP (idle_timers))
{
- int triggertime = EMACS_SECS (now);
Lisp_Object *vector;
Lisp_Object timer, idle_timer;
EMACS_TIME timer_time, idle_timer_time;
/* Skip past invalid timers and timers already handled. */
if (!NILP (timers))
{
- timer = XCONS (timers)->car;
+ timer = XCAR (timers);
if (!VECTORP (timer) || XVECTOR (timer)->size != 8)
{
- timers = XCONS (timers)->cdr;
+ timers = XCDR (timers);
continue;
}
vector = XVECTOR (timer)->contents;
|| !INTEGERP (vector[3])
|| ! NILP (vector[0]))
{
- timers = XCONS (timers)->cdr;
+ timers = XCDR (timers);
continue;
}
}
if (!NILP (idle_timers))
{
- timer = XCONS (idle_timers)->car;
+ timer = XCAR (idle_timers);
if (!VECTORP (timer) || XVECTOR (timer)->size != 8)
{
- idle_timers = XCONS (idle_timers)->cdr;
+ idle_timers = XCDR (idle_timers);
continue;
}
vector = XVECTOR (timer)->contents;
|| !INTEGERP (vector[3])
|| ! NILP (vector[0]))
{
- idle_timers = XCONS (idle_timers)->cdr;
+ idle_timers = XCDR (idle_timers);
continue;
}
}
this timer becomes ripe (negative if it's already ripe). */
if (!NILP (timers))
{
- timer = XCONS (timers)->car;
+ timer = XCAR (timers);
vector = XVECTOR (timer)->contents;
EMACS_SET_SECS (timer_time,
(XINT (vector[1]) << 16) | (XINT (vector[2])));
based on the next idle timer. */
if (!NILP (idle_timers))
{
- idle_timer = XCONS (idle_timers)->car;
+ idle_timer = XCAR (idle_timers);
vector = XVECTOR (idle_timer)->contents;
EMACS_SET_SECS (idle_timer_time,
(XINT (vector[1]) << 16) | (XINT (vector[2])));
if (EMACS_TIME_NEG_P (temp))
{
chosen_timer = timer;
- timers = XCONS (timers)->cdr;
+ timers = XCDR (timers);
difference = timer_difference;
}
else
{
chosen_timer = idle_timer;
- idle_timers = XCONS (idle_timers)->cdr;
+ idle_timers = XCDR (idle_timers);
difference = idle_timer_difference;
}
}
else if (! NILP (timers))
{
chosen_timer = timer;
- timers = XCONS (timers)->cdr;
+ timers = XCDR (timers);
difference = timer_difference;
}
else
{
chosen_timer = idle_timer;
- idle_timers = XCONS (idle_timers)->cdr;
+ idle_timers = XCDR (idle_timers);
difference = idle_timer_difference;
}
vector = XVECTOR (chosen_timer)->contents;
{
if (NILP (vector[0]))
{
- Lisp_Object tem;
int was_locked = single_kboard;
int count = specpdl_ptr - specpdl;
0, 0, /* 0x0E .. 0x0F */
- "shift", /* VK_SHIFT 0x10 */
- "control", /* VK_CONTROL 0x11 */
- "menu", /* VK_MENU 0x12 */
+ 0, /* VK_SHIFT 0x10 */
+ 0, /* VK_CONTROL 0x11 */
+ 0, /* VK_MENU 0x12 */
"pause", /* VK_PAUSE 0x13 */
- "capital", /* VK_CAPITAL 0x14 */
+ "capslock", /* VK_CAPITAL 0x14 */
0, 0, 0, 0, 0, 0, /* 0x15 .. 0x1A */
- 0, /* VK_ESCAPE 0x1B */
+ "escape", /* VK_ESCAPE 0x1B */
0, 0, 0, 0, /* 0x1C .. 0x1F */
"noname", /* VK_NONAME 0xFC */
"pa1", /* VK_PA1 0xFD */
"oem_clear", /* VK_OEM_CLEAR 0xFE */
+ 0 /* 0xFF */
};
#else /* not HAVE_NTGUI */
/* Scroll bar parts. */
Lisp_Object Qabove_handle, Qhandle, Qbelow_handle;
-Lisp_Object Qup, Qdown;
+Lisp_Object Qup, Qdown, Qbottom, Qend_scroll;
+Lisp_Object Qtop, Qratio;
/* An array of scroll bar parts, indexed by an enum scroll_bar_part value. */
Lisp_Object *scroll_bar_parts[] = {
&Qabove_handle, &Qhandle, &Qbelow_handle,
- &Qup, &Qdown,
+ &Qup, &Qdown, &Qtop, &Qbottom, &Qend_scroll, &Qratio
+};
+
+/* User signal events. */
+Lisp_Object Qusr1_signal, Qusr2_signal;
+
+Lisp_Object *lispy_user_signals[] =
+{
+ &Qusr1_signal, &Qusr2_signal
};
/* 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:
+#ifndef USE_TOOLKIT_SCROLL_BARS
case scroll_bar_click:
+#endif
{
int button = event->code;
int is_double;
FRAME_PTR f = XFRAME (event->frame_or_window);
Lisp_Object window;
Lisp_Object posn;
+ Lisp_Object string_info = Qnil;
int row, column;
/* Ignore mouse events that were made on frame that
if (! FRAME_LIVE_P (f))
return Qnil;
- pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
- &column, &row, NULL, 1);
+ /* EVENT->x and EVENT->y are frame-relative pixel
+ coordinates at this place. Under old redisplay, COLUMN
+ and ROW are set to frame relative glyph coordinates
+ which are then used to determine whether this click is
+ in a menu (non-toolkit version). */
+ pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
+ &column, &row, NULL, 1);
#ifndef USE_X_TOOLKIT
/* In the non-toolkit version, clicks on the menu bar
return Qnil;
#endif
+ /* Find the menu bar item under `column'. */
item = Qnil;
items = FRAME_MENU_BAR_ITEMS (f);
for (i = 0; i < XVECTOR (items)->size; i += 4)
}
}
+ /* ELisp manual 2.4b says (x y) are window relative but
+ code says they are frame-relative. */
position
= Fcons (event->frame_or_window,
Fcons (Qmenu_bar,
}
#endif /* not USE_X_TOOLKIT */
- window = window_from_coordinates (f, column, row, &part);
+ /* Set `window' to the window under frame pixel coordinates
+ event->x/event->y. */
+ window = window_from_coordinates (f, XINT (event->x),
+ XINT (event->y), &part, 0);
if (!WINDOWP (window))
{
}
else
{
- int pixcolumn, pixrow;
- column -= WINDOW_LEFT_MARGIN (XWINDOW (window));
- row -= XINT (XWINDOW (window)->top);
- glyph_to_pixel_coords (f, column, row, &pixcolumn, &pixrow);
- XSETINT (event->x, pixcolumn);
- XSETINT (event->y, pixrow);
-
- if (part == 1)
- posn = Qmode_line;
+ /* It's a click in window window at frame coordinates
+ event->x/ event->y. */
+ struct window *w = XWINDOW (window);
+
+ /* Get window relative coordinates. Original code
+ `rounded' this to glyph boundaries. */
+ int wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (event->x));
+ int wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (event->y));
+
+ /* Set event coordinates to window-relative coordinates
+ for constructing the Lisp event below. */
+ XSETINT (event->x, wx);
+ XSETINT (event->y, wy);
+
+ if (part == 1 || part == 3)
+ {
+ /* Mode line or top line. Look for a string under
+ the mouse that may have a `local-map' property. */
+ Lisp_Object string;
+ int charpos;
+
+ posn = part == 1 ? Qmode_line : Qheader_line;
+ string = mode_line_string (w, wx, wy, part == 1, &charpos);
+ if (STRINGP (string))
+ string_info = Fcons (string, make_number (charpos));
+ }
else if (part == 2)
posn = Qvertical_line;
else
- XSETINT (posn,
- buffer_posn_from_coords (XWINDOW (window),
- column, row));
+ XSETINT (posn, buffer_posn_from_coords (w, &wx, &wy));
}
position
Fcons (posn,
Fcons (Fcons (event->x, event->y),
Fcons (make_number (event->timestamp),
- Qnil))));
+ (NILP (string_info)
+ ? Qnil
+ : Fcons (string_info, Qnil))))));
}
+#ifndef USE_TOOLKIT_SCROLL_BARS
else
{
+ /* It's a scrollbar click. */
Lisp_Object window;
Lisp_Object portion_whole;
Lisp_Object part;
Fcons (make_number (event->timestamp),
Fcons (part, Qnil)))));
}
+#endif /* not USE_TOOLKIT_SCROLL_BARS */
start_pos_ptr = &XVECTOR (button_down_location)->contents[button];
Lisp_Object down;
down = Fnth (make_number (2), start_pos);
- if (EQ (event->x, XCONS (down)->car)
- && EQ (event->y, XCONS (down)->cdr))
+ if (EQ (event->x, XCAR (down))
+ && EQ (event->y, XCDR (down)))
{
event->modifiers |= click_modifier;
}
}
}
+#if USE_TOOLKIT_SCROLL_BARS
+
+ /* We don't have down and up events if using toolkit scroll bars,
+ so make this always a click event. Store in the `part' of
+ the Lisp event a symbol which maps to the following actions:
+
+ `above_handle' page up
+ `below_handle' page down
+ `up' line up
+ `down' line down
+ `top' top of buffer
+ `bottom' bottom of buffer
+ `handle' thumb has been dragged.
+ `end-scroll' end of interaction with scroll bar
+
+ The incoming input_event contains in its `part' member an
+ index of type `enum scroll_bar_part' which we can use as an
+ index in scroll_bar_parts to get the appropriate symbol. */
+
+ case scroll_bar_click:
+ {
+ Lisp_Object position, head, window, portion_whole, part;
+
+ window = event->frame_or_window;
+ portion_whole = Fcons (event->x, event->y);
+ part = *scroll_bar_parts[(int) event->part];
+
+ position
+ = Fcons (window,
+ Fcons (Qvertical_scroll_bar,
+ Fcons (portion_whole,
+ Fcons (make_number (event->timestamp),
+ Fcons (part, Qnil)))));
+
+ /* Always treat scroll bar events as clicks. */
+ event->modifiers |= click_modifier;
+
+ /* Get the symbol we should use for the mouse click. */
+ head = modify_event_symbol (event->code,
+ event->modifiers,
+ Qmouse_click, Qnil,
+ lispy_mouse_names, &mouse_syms,
+ (sizeof (lispy_mouse_names)
+ / sizeof (lispy_mouse_names[0])));
+ return Fcons (head, Fcons (position, Qnil));
+ }
+
+#endif /* USE_TOOLKIT_SCROLL_BARS */
+
#ifdef WINDOWSNT
case w32_scroll_bar_click:
{
return Qnil;
pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
&column, &row, NULL, 1);
- window = window_from_coordinates (f, column, row, &part);
+ window = window_from_coordinates (f, column, row, &part, 0);
if (!WINDOWP (window))
{
posn = Qmode_line;
else if (part == 2)
posn = Qvertical_line;
+ else if (part == 3)
+ posn = Qheader_line;
else
XSETINT (posn,
buffer_posn_from_coords (XWINDOW (window),
FRAME_PTR f;
Lisp_Object window;
Lisp_Object posn;
- Lisp_Object head, position;
Lisp_Object files;
int row, column;
if (! CONSP (event->frame_or_window))
abort ();
- f = XFRAME (XCONS (event->frame_or_window)->car);
- files = XCONS (event->frame_or_window)->cdr;
+ f = XFRAME (XCAR (event->frame_or_window));
+ files = XCDR (event->frame_or_window);
/* Ignore mouse events that were made on frames that
have been deleted. */
return Qnil;
pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
&column, &row, NULL, 1);
- window = window_from_coordinates (f, column, row, &part);
+ window = window_from_coordinates (f, column, row, &part, 0);
if (!WINDOWP (window))
{
- window = XCONS (event->frame_or_window)->car;
+ window = XCAR (event->frame_or_window);
posn = Qnil;
}
else
{
- int pixcolumn, pixrow;
- column -= XINT (XWINDOW (window)->left);
- row -= XINT (XWINDOW (window)->top);
- glyph_to_pixel_coords (f, column, row, &pixcolumn, &pixrow);
- XSETINT (event->x, pixcolumn);
- XSETINT (event->y, pixrow);
+ /* It's an event in window `window' at frame coordinates
+ event->x/ event->y. */
+ struct window *w = XWINDOW (window);
+
+ /* Get window relative coordinates. */
+ int wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (event->x));
+ int wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (event->y));
+
+ /* Set event coordinates to window-relative coordinates
+ for constructing the Lisp event below. */
+ XSETINT (event->x, wx);
+ XSETINT (event->y, wy);
if (part == 1)
posn = Qmode_line;
else if (part == 2)
posn = Qvertical_line;
+ else if (part == 3)
+ posn = Qheader_line;
else
- XSETINT (posn,
- buffer_posn_from_coords (XWINDOW (window),
- column, row));
+ XSETINT (posn, buffer_posn_from_coords (w, &wx, &wy));
}
{
/* The event value is in the cdr of the frame_or_window slot. */
if (!CONSP (event->frame_or_window))
abort ();
- return XCONS (event->frame_or_window)->cdr;
+ return XCDR (event->frame_or_window);
#endif
+ case TOOL_BAR_EVENT:
+ {
+ Lisp_Object key;
+ if (!CONSP (event->frame_or_window))
+ abort ();
+ key = XCDR (event->frame_or_window);
+ if (SYMBOLP (key))
+ key = apply_modifiers (event->modifiers, key);
+ return key;
+ }
+
+ case user_signal:
+ /* A user signal. */
+ return *lispy_user_signals[event->code];
+
/* The 'kind' field of the event is something we don't recognize. */
default:
abort ();
int area;
Lisp_Object window;
Lisp_Object posn;
- int column, row;
if (frame)
- {
- /* It's in a frame; which window on that frame? */
- pixel_to_glyph_coords (frame, XINT (x), XINT (y), &column, &row,
- NULL, 1);
- window = window_from_coordinates (frame, column, row, &area);
- }
+ /* It's in a frame; which window on that frame? */
+ window = window_from_coordinates (frame, XINT (x), XINT (y), &area, 0);
else
window = Qnil;
if (WINDOWP (window))
{
- int pixcolumn, pixrow;
- column -= WINDOW_LEFT_MARGIN (XWINDOW (window));
- row -= XINT (XWINDOW (window)->top);
- glyph_to_pixel_coords (frame, column, row, &pixcolumn, &pixrow);
- XSETINT (x, pixcolumn);
- XSETINT (y, pixrow);
-
+ struct window *w = XWINDOW (window);
+ int wx, wy;
+
+ /* Get window relative coordinates. */
+ wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (x));
+ wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (y));
+ XSETINT (x, wx);
+ XSETINT (y, wy);
+
if (area == 1)
posn = Qmode_line;
else if (area == 2)
posn = Qvertical_line;
+ else if (area == 3)
+ posn = Qheader_line;
else
- XSETINT (posn,
- buffer_posn_from_coords (XWINDOW (window), column, row));
+ XSETINT (posn, buffer_posn_from_coords (w, &wx, &wy));
}
else if (frame != 0)
{
SYMBOL's Qevent_symbol_element_mask property, and maintains the
Qevent_symbol_elements property. */
-static Lisp_Object
+Lisp_Object
parse_modifiers (symbol)
Lisp_Object symbol;
{
entry = assq_no_quit (index, cache);
if (CONSP (entry))
- new_symbol = XCONS (entry)->cdr;
+ new_symbol = XCDR (entry);
else
{
/* We have to create the symbol ourselves. */
Lisp_Object parsed;
parsed = parse_modifiers (symbol);
- return apply_modifiers ((int) XINT (XCONS (XCONS (parsed)->cdr)->car),
- XCONS (parsed)->car);
+ return apply_modifiers ((int) XINT (XCAR (XCDR (parsed))),
+ XCAR (parsed));
}
Lisp_Object elt;
int this = 0;
- elt = XCONS (rest)->car;
- rest = XCONS (rest)->cdr;
+ elt = XCAR (rest);
+ rest = XCDR (rest);
/* Given a symbol, see if it is a modifier name. */
if (SYMBOLP (elt) && CONSP (rest))
if (! CONSP (object))
return 0;
- for (tail = object; CONSP (tail); tail = XCONS (tail)->cdr)
+ for (tail = object; CONSP (tail); tail = XCDR (tail))
{
Lisp_Object elt;
- elt = XCONS (tail)->car;
+ elt = XCAR (tail);
if (! (INTEGERP (elt) || SYMBOLP (elt)))
return 0;
}
cbuf[0] = dos_keyread ();
nread = 1;
#else
- nread = read (input_fd, cbuf, n_to_read);
+ 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
cbuf[i] &= ~0x80;
buf[i].code = cbuf[i];
- XSETFRAME (buf[i].frame_or_window, selected_frame);
+ buf[i].frame_or_window = selected_frame;
}
}
nmaps = current_minor_maps (NULL, &tmaps);
maps = (Lisp_Object *) alloca ((nmaps + 2) * sizeof (maps[0]));
bcopy (tmaps, maps, nmaps * sizeof (maps[0]));
-#ifdef USE_TEXT_PROPERTIES
maps[nmaps++] = get_local_map (PT, current_buffer);
-#else
- maps[nmaps++] = current_buffer->keymap;
-#endif
}
maps[nmaps++] = current_global_map;
}
/* Move to the end those items that should be at the end. */
- for (tail = Vmenu_bar_final_items; CONSP (tail); tail = XCONS (tail)->cdr)
+ for (tail = Vmenu_bar_final_items; CONSP (tail); tail = XCDR (tail))
{
int i;
int end = menu_bar_items_index;
for (i = 0; i < end; i += 4)
- if (EQ (XCONS (tail)->car, XVECTOR (menu_bar_items_vector)->contents[i]))
+ if (EQ (XCAR (tail), XVECTOR (menu_bar_items_vector)->contents[i]))
{
Lisp_Object tem0, tem1, tem2, tem3;
/* Move the item at index I to the end,
if (i + 4 > XVECTOR (menu_bar_items_vector)->size)
{
Lisp_Object tem;
- int newsize = 2 * i;
tem = Fmake_vector (make_number (2 * i), Qnil);
bcopy (XVECTOR (menu_bar_items_vector)->contents,
XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
/* Scan one map KEYMAP, accumulating any menu items it defines
in menu_bar_items_vector. */
+static Lisp_Object menu_bar_one_keymap_changed_items;
+
static void
menu_bar_one_keymap (keymap)
Lisp_Object keymap;
{
- Lisp_Object tail, item, table;
+ Lisp_Object tail, item;
+
+ menu_bar_one_keymap_changed_items = Qnil;
/* Loop over all keymap entries that have menu strings. */
- for (tail = keymap; CONSP (tail); tail = XCONS (tail)->cdr)
+ for (tail = keymap; CONSP (tail); tail = XCDR (tail))
{
- item = XCONS (tail)->car;
+ item = XCAR (tail);
if (CONSP (item))
- menu_bar_item (XCONS (item)->car, XCONS (item)->cdr);
+ menu_bar_item (XCAR (item), XCDR (item));
else if (VECTORP (item))
{
/* Loop over the char values represented in the vector. */
{
struct gcpro gcpro1;
int i;
+ Lisp_Object tem;
if (EQ (item, Qundefined))
{
if (!i)
return;
+ /* If this keymap has already contributed to this KEY,
+ don't contribute to it a second time. */
+ tem = Fmemq (key, menu_bar_one_keymap_changed_items);
+ if (!NILP (tem))
+ return;
+
+ menu_bar_one_keymap_changed_items
+ = Fcons (key, menu_bar_one_keymap_changed_items);
+
item = XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF];
/* Find any existing item for this KEY. */
if (i + 4 > XVECTOR (menu_bar_items_vector)->size)
{
Lisp_Object tem;
- int newsize = 2 * i;
tem = Fmake_vector (make_number (2 * i), Qnil);
bcopy (XVECTOR (menu_bar_items_vector)->contents,
XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
{
/* If we got a quit from within the menu computation,
quit all the way out of it. This takes care of C-] in the debugger. */
- if (CONSP (arg) && EQ (XCONS (arg)->car, Qquit))
+ if (CONSP (arg) && EQ (XCAR (arg), Qquit))
Fsignal (Qquit, Qnil);
return Qnil;
/* Evaluate an expression and return the result (or nil if something
went wrong). Used to evaluate dynamic parts of menu items. */
-static Lisp_Object
+Lisp_Object
menu_item_eval_property (sexpr)
Lisp_Object sexpr;
{
int notreal, inmenubar;
{
Lisp_Object def, tem, item_string, start;
- Lisp_Object cachelist = Qnil;
- Lisp_Object filter = Qnil;
- Lisp_Object keyhint = Qnil;
+ Lisp_Object cachelist;
+ Lisp_Object filter;
+ Lisp_Object keyhint;
int i;
int newcache = 0;
+ cachelist = Qnil;
+ filter = Qnil;
+ keyhint = Qnil;
+
if (!CONSP (item))
return 0;
/* Save the item here to protect it from GC. */
XVECTOR (item_properties)->contents[ITEM_PROPERTY_ITEM] = item;
- item_string = XCONS (item)->car;
+ item_string = XCAR (item);
start = item;
- item = XCONS (item)->cdr;
+ item = XCDR (item);
if (STRINGP (item_string))
{
/* Old format menu item. */
XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME] = item_string;
/* Maybe help string. */
- if (CONSP (item) && STRINGP (XCONS (item)->car))
+ if (CONSP (item) && STRINGP (XCAR (item)))
{
XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]
- = XCONS (item)->car;
+ = XCAR (item);
start = item;
- item = XCONS (item)->cdr;
+ item = XCDR (item);
}
/* Maybee key binding cache. */
- if (CONSP (item) && CONSP (XCONS (item)->car)
- && (NILP (XCONS (XCONS (item)->car)->car)
- || VECTORP (XCONS (XCONS (item)->car)->car)))
+ if (CONSP (item) && CONSP (XCAR (item))
+ && (NILP (XCAR (XCAR (item)))
+ || VECTORP (XCAR (XCAR (item)))))
{
- cachelist = XCONS (item)->car;
- item = XCONS (item)->cdr;
+ cachelist = XCAR (item);
+ item = XCDR (item);
}
/* This is the real definition--the function to run. */
{
/* New format menu item. */
XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME]
- = XCONS (item)->car;
- start = XCONS (item)->cdr;
+ = XCAR (item);
+ start = XCDR (item);
if (CONSP (start))
{
/* We have a real binding. */
XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF]
- = XCONS (start)->car;
+ = XCAR (start);
- item = XCONS (start)->cdr;
+ item = XCDR (start);
/* Is there a cache list with key equivalences. */
- if (CONSP (item) && CONSP (XCONS (item)->car))
+ if (CONSP (item) && CONSP (XCAR (item)))
{
- cachelist = XCONS (item)->car;
- item = XCONS (item)->cdr;
+ cachelist = XCAR (item);
+ item = XCDR (item);
}
/* Parse properties. */
- while (CONSP (item) && CONSP (XCONS (item)->cdr))
+ while (CONSP (item) && CONSP (XCDR (item)))
{
- tem = XCONS (item)->car;
- item = XCONS (item)->cdr;
+ tem = XCAR (item);
+ item = XCDR (item);
if (EQ (tem, QCenable))
XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE]
- = XCONS (item)->car;
+ = XCAR (item);
else if (EQ (tem, QCvisible) && !notreal)
{
/* If got a visible property and that evaluates to nil
then ignore this item. */
- tem = menu_item_eval_property (XCONS (item)->car);
+ tem = menu_item_eval_property (XCAR (item));
if (NILP (tem))
return 0;
}
else if (EQ (tem, QChelp))
XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]
- = XCONS (item)->car;
+ = XCAR (item);
else if (EQ (tem, QCfilter))
filter = item;
else if (EQ (tem, QCkey_sequence))
{
- tem = XCONS (item)->car;
+ tem = XCAR (item);
if (NILP (cachelist)
&& (SYMBOLP (tem) || STRINGP (tem) || VECTORP (tem)))
/* Be GC protected. Set keyhint to item instead of tem. */
}
else if (EQ (tem, QCkeys))
{
- tem = XCONS (item)->car;
- if (CONSP (tem) || STRINGP (tem) && NILP (cachelist))
+ tem = XCAR (item);
+ if (CONSP (tem) || (STRINGP (tem) && NILP (cachelist)))
XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ]
= tem;
}
- else if (EQ (tem, QCbutton) && CONSP (XCONS (item)->car))
+ else if (EQ (tem, QCbutton) && CONSP (XCAR (item)))
{
Lisp_Object type;
- tem = XCONS (item)->car;
- type = XCONS (tem)->car;
+ tem = XCAR (item);
+ type = XCAR (tem);
if (EQ (type, QCtoggle) || EQ (type, QCradio))
{
XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED]
- = XCONS (tem)->cdr;
+ = XCDR (tem);
XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE]
= type;
}
}
- item = XCONS (item)->cdr;
+ item = XCDR (item);
}
}
else if (inmenubar || !NILP (start))
def = XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF];
if (!NILP (filter))
{
- def = menu_item_eval_property (list2 (XCONS (filter)->car,
+ def = menu_item_eval_property (list2 (XCAR (filter),
list2 (Qquote, def)));
XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF] = def;
/* See if this is a separate pane or a submenu. */
def = XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF];
tem = get_keymap_1 (def, 0, 1);
+ /* For a subkeymap, just record its details and exit. */
if (!NILP (tem))
{
XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP] = tem;
XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF] = tem;
return 1;
}
- else if (inmenubar > 0)
- return 0; /* Entries in menu bar must be submenus. */
+ /* At the top level in the menu bar, do likewise for commands also.
+ The menu bar does not display equivalent key bindings anyway.
+ ITEM_PROPERTY_DEF is already set up properly. */
+ if (inmenubar > 0)
+ return 1;
/* This is a command. See if there is an equivalent key binding. */
if (NILP (cachelist))
{
/* We have to create a cachelist. */
CHECK_IMPURE (start);
- XCONS (start)->cdr = Fcons (Fcons (Qnil, Qnil), XCONS (start)->cdr);
- cachelist = XCONS (XCONS (start)->cdr)->car;
+ XCDR (start) = Fcons (Fcons (Qnil, Qnil), XCDR (start));
+ cachelist = XCAR (XCDR (start));
newcache = 1;
tem = XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ];
if (!NILP (keyhint))
{
- XCONS (cachelist)->car = XCONS (keyhint)->car;
+ XCAR (cachelist) = XCAR (keyhint);
newcache = 0;
}
else if (STRINGP (tem))
{
- XCONS (cachelist)->cdr = Fsubstitute_command_keys (tem);
- XCONS (cachelist)->car = Qt;
+ XCDR (cachelist) = Fsubstitute_command_keys (tem);
+ XCAR (cachelist) = Qt;
}
}
- tem = XCONS (cachelist)->car;
+ tem = XCAR (cachelist);
if (!EQ (tem, Qt))
{
int chkcache = 0;
prefix = XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ];
if (CONSP (prefix))
{
- def = XCONS (prefix)->car;
- prefix = XCONS (prefix)->cdr;
+ def = XCAR (prefix);
+ prefix = XCDR (prefix);
}
else
def = XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF];
- if (NILP (XCONS (cachelist)->car)) /* 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
}
/* We had a saved key. Is it still bound to the command? */
else if (NILP (tem)
- || !EQ (tem, def)
- /* If the command is an alias for another
- (such as lmenu.el set it up), check if the
- original command matches the cached command. */
- && !(SYMBOLP (def) && EQ (tem, XSYMBOL (def)->function)))
+ || (!EQ (tem, def)
+ /* If the command is an alias for another
+ (such as lmenu.el set it up), check if the
+ original command matches the cached command. */
+ && !(SYMBOLP (def) && EQ (tem, XSYMBOL (def)->function))))
chkcache = 1; /* Need to recompute key binding. */
if (chkcache)
&& ! NILP (Fget (def, Qmenu_alias)))
def = XSYMBOL (def)->function;
tem = Fwhere_is_internal (def, Qnil, Qt, Qnil);
- XCONS (cachelist)->car = tem;
+ XCAR (cachelist) = tem;
if (NILP (tem))
{
- XCONS (cachelist)->cdr = Qnil;
+ XCDR (cachelist) = Qnil;
chkcache = 0;
}
}
- else if (!NILP (keyhint) && !NILP (XCONS (cachelist)->car))
+ else if (!NILP (keyhint) && !NILP (XCAR (cachelist)))
{
- tem = XCONS (cachelist)->car;
+ tem = XCAR (cachelist);
chkcache = 1;
}
tem = Fkey_description (tem);
if (CONSP (prefix))
{
- if (STRINGP (XCONS (prefix)->car))
- tem = concat2 (XCONS (prefix)->car, tem);
- if (STRINGP (XCONS (prefix)->cdr))
- tem = concat2 (tem, XCONS (prefix)->cdr);
+ if (STRINGP (XCAR (prefix)))
+ tem = concat2 (XCAR (prefix), tem);
+ if (STRINGP (XCDR (prefix)))
+ tem = concat2 (tem, XCDR (prefix));
}
- XCONS (cachelist)->cdr = tem;
+ XCDR (cachelist) = tem;
}
}
- tem = XCONS (cachelist)->cdr;
+ tem = XCDR (cachelist);
if (newcache && !NILP (tem))
{
tem = concat3 (build_string (" ("), tem, build_string (")"));
- XCONS (cachelist)->cdr = tem;
+ XCDR (cachelist) = tem;
}
/* If we only want to precompute equivalent key bindings, stop here. */
return 1;
}
+
+
+\f
+/***********************************************************************
+ Tool-bars
+ ***********************************************************************/
+
+/* A vector holding tool bar items while they are parsed in function
+ tool_bar_items runs Each item occupies TOOL_BAR_ITEM_NSCLOTS elements
+ in the vector. */
+
+static Lisp_Object tool_bar_items_vector;
+
+/* A vector holding the result of parse_tool_bar_item. Layout is like
+ the one for a single item in tool_bar_items_vector. */
+
+static Lisp_Object tool_bar_item_properties;
+
+/* Next free index in tool_bar_items_vector. */
+
+static int ntool_bar_items;
+
+/* The symbols `tool-bar', and `:image'. */
+
+extern Lisp_Object Qtool_bar;
+Lisp_Object QCimage;
+
+/* Function prototypes. */
+
+static void init_tool_bar_items P_ ((Lisp_Object));
+static void process_tool_bar_item P_ ((Lisp_Object, Lisp_Object));
+static int parse_tool_bar_item P_ ((Lisp_Object, Lisp_Object));
+static void append_tool_bar_item P_ ((void));
+
+
+/* Return a vector of tool bar items for keymaps currently in effect.
+ Reuse vector REUSE if non-nil. Return in *NITEMS the number of
+ tool bar items found. */
+
+Lisp_Object
+tool_bar_items (reuse, nitems)
+ Lisp_Object reuse;
+ int *nitems;
+{
+ Lisp_Object *maps;
+ int nmaps, i;
+ Lisp_Object oquit;
+ Lisp_Object *tmaps;
+ extern Lisp_Object Voverriding_local_map_menu_flag;
+ extern Lisp_Object Voverriding_local_map;
+
+ *nitems = 0;
+
+ /* 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
+ quitting while building the menus. We do this instead of
+ specbind because (1) errors will clear it anyway and (2) this
+ avoids risk of specpdl overflow. */
+ oquit = Vinhibit_quit;
+ Vinhibit_quit = Qt;
+
+ /* Initialize tool_bar_items_vector and protect it from GC. */
+ init_tool_bar_items (reuse);
+
+ /* Build list of keymaps in maps. Set nmaps to the number of maps
+ to process. */
+
+ /* Should overriding-terminal-local-map and overriding-local-map apply? */
+ if (!NILP (Voverriding_local_map_menu_flag))
+ {
+ /* Yes, use them (if non-nil) as well as the global map. */
+ maps = (Lisp_Object *) alloca (3 * sizeof (maps[0]));
+ nmaps = 0;
+ if (!NILP (current_kboard->Voverriding_terminal_local_map))
+ maps[nmaps++] = current_kboard->Voverriding_terminal_local_map;
+ if (!NILP (Voverriding_local_map))
+ maps[nmaps++] = Voverriding_local_map;
+ }
+ else
+ {
+ /* No, so use major and minor mode keymaps. */
+ nmaps = current_minor_maps (NULL, &tmaps);
+ maps = (Lisp_Object *) alloca ((nmaps + 2) * sizeof (maps[0]));
+ bcopy (tmaps, maps, nmaps * sizeof (maps[0]));
+ maps[nmaps++] = get_local_map (PT, current_buffer);
+ }
+
+ /* Add global keymap at the end. */
+ maps[nmaps++] = current_global_map;
+
+ /* Process maps in reverse order and look up in each map the prefix
+ key `tool-bar'. */
+ for (i = nmaps - 1; i >= 0; --i)
+ if (!NILP (maps[i]))
+ {
+ Lisp_Object keymap;
+
+ keymap = get_keyelt (access_keymap (maps[i], Qtool_bar, 1, 1), 0);
+ if (!NILP (Fkeymapp (keymap)))
+ {
+ Lisp_Object tail;
+
+ /* KEYMAP is a list `(keymap (KEY . BINDING) ...)'. */
+ for (tail = keymap; CONSP (tail); tail = XCDR (tail))
+ {
+ Lisp_Object keydef = XCAR (tail);
+ if (CONSP (keydef))
+ process_tool_bar_item (XCAR (keydef), XCDR (keydef));
+ }
+ }
+ }
+
+ Vinhibit_quit = oquit;
+ *nitems = ntool_bar_items / TOOL_BAR_ITEM_NSLOTS;
+ return tool_bar_items_vector;
+}
+
+
+/* Process the definition of KEY which is DEF. */
+
+static void
+process_tool_bar_item (key, def)
+ Lisp_Object key, def;
+{
+ int i;
+ extern Lisp_Object Qundefined;
+ struct gcpro gcpro1, gcpro2;
+
+ /* Protect KEY and DEF from GC because parse_tool_bar_item may call
+ eval. */
+ GCPRO2 (key, def);
+
+ if (EQ (def, Qundefined))
+ {
+ /* If a map has an explicit `undefined' as definition,
+ discard any previously made item. */
+ for (i = 0; i < ntool_bar_items; i += TOOL_BAR_ITEM_NSLOTS)
+ {
+ Lisp_Object *v = XVECTOR (tool_bar_items_vector)->contents + i;
+
+ if (EQ (key, v[TOOL_BAR_ITEM_KEY]))
+ {
+ if (ntool_bar_items > i + TOOL_BAR_ITEM_NSLOTS)
+ bcopy (v + TOOL_BAR_ITEM_NSLOTS, v,
+ ((ntool_bar_items - i - TOOL_BAR_ITEM_NSLOTS)
+ * sizeof (Lisp_Object)));
+ ntool_bar_items -= TOOL_BAR_ITEM_NSLOTS;
+ break;
+ }
+ }
+ }
+ else if (parse_tool_bar_item (key, def))
+ /* Append a new tool bar item to tool_bar_items_vector. Accept
+ more than one definition for the same key. */
+ append_tool_bar_item ();
+
+ UNGCPRO;
+}
+
+
+/* Parse a tool bar item specification ITEM for key KEY and return the
+ result in tool_bar_item_properties. Value is zero if ITEM is
+ invalid.
+
+ ITEM is a list `(menu-item CAPTION BINDING PROPS...)'.
+
+ CAPTION is the caption of the item, If it's not a string, it is
+ evaluated to get a string.
+
+ BINDING is the tool bar item's binding. Tool-bar items with keymaps
+ as binding are currently ignored.
+
+ The following properties are recognized:
+
+ - `:enable FORM'.
+
+ FORM is evaluated and specifies whether the tool bar item is
+ enabled or disabled.
+
+ - `:visible FORM'
+
+ FORM is evaluated and specifies whether the tool bar item is visible.
+
+ - `:filter FUNCTION'
+
+ FUNCTION is invoked with one parameter `(quote BINDING)'. Its
+ result is stored as the new binding.
+
+ - `:button (TYPE SELECTED)'
+
+ TYPE must be one of `:radio' or `:toggle'. SELECTED is evaluated
+ and specifies whether the button is selected (pressed) or not.
+
+ - `:image IMAGES'
+
+ IMAGES is either a single image specification or a vector of four
+ image specifications. See enum tool_bar_item_images.
+
+ - `:help HELP-STRING'.
+
+ Gives a help string to display for the tool bar item. */
+
+static int
+parse_tool_bar_item (key, item)
+ Lisp_Object key, item;
+{
+ /* Access slot with index IDX of vector tool_bar_item_properties. */
+#define PROP(IDX) XVECTOR (tool_bar_item_properties)->contents[IDX]
+
+ Lisp_Object filter = Qnil;
+ Lisp_Object caption;
+ extern Lisp_Object QCenable, QCvisible, QChelp, QCfilter;
+ extern Lisp_Object QCbutton, QCtoggle, QCradio;
+ int i;
+
+ /* Defininition looks like `(tool-bar-item CAPTION BINDING
+ PROPS...)'. Rule out items that aren't lists, don't start with
+ `tool-bar-item' or whose rest following `tool-bar-item' is not a
+ list. */
+ if (!CONSP (item)
+ || !EQ (XCAR (item), Qmenu_item)
+ || (item = XCDR (item),
+ !CONSP (item)))
+ return 0;
+
+ /* Create tool_bar_item_properties vector if necessary. Reset it to
+ defaults. */
+ if (VECTORP (tool_bar_item_properties))
+ {
+ for (i = 0; i < TOOL_BAR_ITEM_NSLOTS; ++i)
+ PROP (i) = Qnil;
+ }
+ else
+ tool_bar_item_properties
+ = Fmake_vector (make_number (TOOL_BAR_ITEM_NSLOTS), Qnil);
+
+ /* Set defaults. */
+ PROP (TOOL_BAR_ITEM_KEY) = key;
+ PROP (TOOL_BAR_ITEM_ENABLED_P) = Qt;
+
+ /* Get the caption of the item. If the caption is not a string,
+ evaluate it to get a string. If we don't get a string, skip this
+ item. */
+ caption = XCAR (item);
+ if (!STRINGP (caption))
+ {
+ caption = menu_item_eval_property (caption);
+ if (!STRINGP (caption))
+ return 0;
+ }
+ PROP (TOOL_BAR_ITEM_CAPTION) = caption;
+
+ /* Give up if rest following the caption is not a list. */
+ item = XCDR (item);
+ if (!CONSP (item))
+ return 0;
+
+ /* Store the binding. */
+ PROP (TOOL_BAR_ITEM_BINDING) = XCAR (item);
+ item = XCDR (item);
+
+ /* Process the rest of the properties. */
+ for (; CONSP (item) && CONSP (XCDR (item)); item = XCDR (XCDR (item)))
+ {
+ Lisp_Object key, value;
+
+ key = XCAR (item);
+ value = XCAR (XCDR (item));
+
+ if (EQ (key, QCenable))
+ /* `:enable FORM'. */
+ PROP (TOOL_BAR_ITEM_ENABLED_P) = value;
+ else if (EQ (key, QCvisible))
+ {
+ /* `:visible FORM'. If got a visible property and that
+ evaluates to nil then ignore this item. */
+ if (NILP (menu_item_eval_property (value)))
+ return 0;
+ }
+ else if (EQ (key, QChelp))
+ /* `:help HELP-STRING'. */
+ PROP (TOOL_BAR_ITEM_HELP) = value;
+ else if (EQ (key, QCfilter))
+ /* ':filter FORM'. */
+ filter = value;
+ else if (EQ (key, QCbutton) && CONSP (value))
+ {
+ /* `:button (TYPE . SELECTED)'. */
+ Lisp_Object type, selected;
+
+ type = XCAR (value);
+ selected = XCDR (value);
+ if (EQ (type, QCtoggle) || EQ (type, QCradio))
+ {
+ PROP (TOOL_BAR_ITEM_SELECTED_P) = selected;
+ PROP (TOOL_BAR_ITEM_TYPE) = type;
+ }
+ }
+ else if (EQ (key, QCimage)
+ && (CONSP (value)
+ || (VECTORP (value) && XVECTOR (value)->size == 4)))
+ /* Value is either a single image specification or a vector
+ of 4 such specifications for the different buttion states. */
+ PROP (TOOL_BAR_ITEM_IMAGES) = value;
+ }
+
+ /* If got a filter apply it on binding. */
+ if (!NILP (filter))
+ PROP (TOOL_BAR_ITEM_BINDING)
+ = menu_item_eval_property (list2 (filter,
+ list2 (Qquote,
+ PROP (TOOL_BAR_ITEM_BINDING))));
+
+ /* See if the binding is a keymap. Give up if it is. */
+ if (!NILP (get_keymap_1 (PROP (TOOL_BAR_ITEM_BINDING), 0, 1)))
+ return 0;
+
+ /* Enable or disable selection of item. */
+ if (!EQ (PROP (TOOL_BAR_ITEM_ENABLED_P), Qt))
+ PROP (TOOL_BAR_ITEM_ENABLED_P)
+ = menu_item_eval_property (PROP (TOOL_BAR_ITEM_ENABLED_P));
+
+ /* Handle radio buttons or toggle boxes. */
+ if (!NILP (PROP (TOOL_BAR_ITEM_SELECTED_P)))
+ PROP (TOOL_BAR_ITEM_SELECTED_P)
+ = menu_item_eval_property (PROP (TOOL_BAR_ITEM_SELECTED_P));
+
+ return 1;
+
+#undef PROP
+}
+
+
+/* Initialize tool_bar_items_vector. REUSE, if non-nil, is a vector
+ that can be reused. */
+
+static void
+init_tool_bar_items (reuse)
+ Lisp_Object reuse;
+{
+ if (VECTORP (reuse))
+ tool_bar_items_vector = reuse;
+ else
+ tool_bar_items_vector = Fmake_vector (make_number (64), Qnil);
+ ntool_bar_items = 0;
+}
+
+
+/* Append parsed tool bar item properties from
+ tool_bar_item_properties */
+
+static void
+append_tool_bar_item ()
+{
+ Lisp_Object *to, *from;
+
+ /* Enlarge tool_bar_items_vector if necessary. */
+ if (ntool_bar_items + TOOL_BAR_ITEM_NSLOTS
+ >= XVECTOR (tool_bar_items_vector)->size)
+ {
+ Lisp_Object new_vector;
+ int old_size = XVECTOR (tool_bar_items_vector)->size;
+
+ new_vector = Fmake_vector (make_number (2 * old_size), Qnil);
+ bcopy (XVECTOR (tool_bar_items_vector)->contents,
+ XVECTOR (new_vector)->contents,
+ old_size * sizeof (Lisp_Object));
+ tool_bar_items_vector = new_vector;
+ }
+
+ /* Append entries from tool_bar_item_properties to the end of
+ tool_bar_items_vector. */
+ to = XVECTOR (tool_bar_items_vector)->contents + ntool_bar_items;
+ from = XVECTOR (tool_bar_item_properties)->contents;
+ bcopy (from, to, TOOL_BAR_ITEM_NSLOTS * sizeof *to);
+ ntool_bar_items += TOOL_BAR_ITEM_NSLOTS;
+}
+
+
+
+
\f
/* Read a character using menus based on maps in the array MAPS.
NMAPS is the length of MAPS. Return nil if there are no menus in the maps.
{
int mapno;
register Lisp_Object name;
- Lisp_Object rest, vector;
if (used_mouse_menu)
*used_mouse_menu = 0;
/* If we got to this point via a mouse click,
use a real menu for mouse selection. */
if (EVENT_HAS_PARAMETERS (prev_event)
- && !EQ (XCONS (prev_event)->car, Qmenu_bar))
+ && !EQ (XCAR (prev_event), Qmenu_bar)
+ && !EQ (XCAR (prev_event), Qtool_bar))
{
/* Display the menu and get the selection. */
Lisp_Object *realmaps
{
Lisp_Object tem;
- record_menu_key (XCONS (value)->car);
+ record_menu_key (XCAR (value));
/* If we got multiple events, unread all but
the first.
to indicate that they came from a mouse menu,
so that when present in last_nonmenu_event
they won't confuse things. */
- for (tem = XCONS (value)->cdr; !NILP (tem);
- tem = XCONS (tem)->cdr)
+ for (tem = XCDR (value); !NILP (tem);
+ tem = XCDR (tem))
{
- record_menu_key (XCONS (tem)->car);
- if (SYMBOLP (XCONS (tem)->car)
- || INTEGERP (XCONS (tem)->car))
- XCONS (tem)->car
- = Fcons (XCONS (tem)->car, Qnil);
+ record_menu_key (XCAR (tem));
+ if (SYMBOLP (XCAR (tem))
+ || INTEGERP (XCAR (tem)))
+ XCAR (tem)
+ = Fcons (XCAR (tem), Qnil);
}
/* If we got more than one event, put all but the first
onto this list to be read later.
Return just the first event now. */
Vunread_command_events
- = nconc2 (XCONS (value)->cdr, Vunread_command_events);
- value = XCONS (value)->car;
+ = nconc2 (XCDR (value), Vunread_command_events);
+ value = XCAR (value);
}
else if (NILP (value))
value = Qt;
int mapno;
register Lisp_Object name;
int nlength;
- int width = FRAME_WIDTH (selected_frame) - 4;
+ int width = FRAME_WIDTH (SELECTED_FRAME ()) - 4;
int idx = -1;
int nobindings = 1;
Lisp_Object rest, vector;
int prev_keytran_start;
int prev_keytran_end;
+#if defined (GOBBLE_FIRST_EVENT)
int junk;
+#endif
raw_keybuf_count = 0;
{
if (!NILP (prompt))
echo_prompt (XSTRING (prompt)->data);
- else if (cursor_in_echo_area && echo_keystrokes)
+ else if (cursor_in_echo_area
+ && (FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
+ && NILP (Fzerop (Vecho_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 ();
orig_local_map = get_local_map (PT, current_buffer);
- /* Bind input-method-function so that we can set it to nil
- temporarily after the first input event. */
- specbind (Qinput_method_function, Vinput_method_function);
-
/* 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. */
nmaps_allocated = nmaps + 2;
}
bcopy (maps, submaps, nmaps * sizeof (submaps[0]));
-#ifdef USE_TEXT_PROPERTIES
submaps[nmaps++] = orig_local_map;
-#else
- submaps[nmaps++] = current_buffer->keymap;
-#endif
}
submaps[nmaps++] = current_global_map;
}
{
key = keybuf[t];
add_command_key (key);
- if (echo_keystrokes)
+ if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
+ && NILP (Fzerop (Vecho_keystrokes)))
echo_char (key);
}
/* If not, we should actually read a character. */
else
{
- struct buffer *buf = current_buffer;
-
{
#ifdef MULTI_KBOARD
KBOARD *interrupted_kboard = current_kboard;
- struct frame *interrupted_frame = selected_frame;
+ struct frame *interrupted_frame = SELECTED_FRAME ();
if (setjmp (wrong_kboard_jmpbuf))
{
if (!NILP (delayed_switch_frame))
/* If the side queue is non-empty, ensure it begins with a
switch-frame, so we'll replay it in the right context. */
if (CONSP (interrupted_kboard->kbd_queue)
- && (key = XCONS (interrupted_kboard->kbd_queue)->car,
+ && (key = XCAR (interrupted_kboard->kbd_queue),
!(EVENT_HAS_PARAMETERS (key)
&& EQ (EVENT_HEAD_KIND (EVENT_HEAD (key)),
Qswitch_frame))))
#endif
key = read_char (NILP (prompt), nmaps, submaps, last_nonmenu_event,
&used_mouse_menu);
-
- /* Turn off input methods after a prefix character. */
- Vinput_method_function = Qnil;
}
/* read_char returns t when it shows a menu and the user rejects it.
This is to be more consistent with the behavior
of the command_loop_1. */
if (fix_current_buffer)
- if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
- Fset_buffer (XWINDOW (selected_window)->buffer);
+ {
+ if (! FRAME_LIVE_P (XFRAME (selected_frame)))
+ Fkill_emacs (Qnil);
+ if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
+ Fset_buffer (XWINDOW (selected_window)->buffer);
+ }
orig_local_map = get_local_map (PT, current_buffer);
goto replay_sequence;
window = POSN_WINDOW (EVENT_START (key));
posn = POSN_BUFFER_POSN (EVENT_START (key));
+
if (CONSP (posn))
{
/* We're looking at the second event of a
emacsclient). */
record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+ if (! FRAME_LIVE_P (XFRAME (selected_frame)))
+ Fkill_emacs (Qnil);
set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
orig_local_map = get_local_map (PT, current_buffer);
goto replay_sequence;
}
+
/* 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)
+ if (last_real_key_start == 0
+ && CONSP (XCDR (key))
&& ! localized_local_map)
{
Lisp_Object map_here, start, pos;
localized_local_map = 1;
start = EVENT_START (key);
- if (CONSP (start) && CONSP (XCONS (start)->cdr))
+
+ if (CONSP (start) && CONSP (XCDR (start)))
{
pos = POSN_BUFFER_POSN (start);
if (INTEGERP (pos)
keybuf[t] = posn;
keybuf[t+1] = key;
mock_input = t + 2;
-
+
/* Zap the position in key, so we know that we've
expanded it, and don't try to do so again. */
POSN_BUFFER_POSN (EVENT_START (key))
= Fcons (posn, Qnil);
+
+ /* If on a mode line string with a local keymap,
+ reconsider the key sequence with that keymap. */
+ if (CONSP (POSN_STRING (EVENT_START (key))))
+ {
+ Lisp_Object string, pos, map;
+
+ string = POSN_STRING (EVENT_START (key));
+ pos = XCDR (string);
+ string = XCAR (string);
+
+ if (pos >= 0
+ && pos < XSTRING (string)->size
+ && (map = Fget_text_property (pos, Qlocal_map,
+ string),
+ !NILP (map)))
+ {
+ orig_local_map = map;
+ goto replay_sequence;
+ }
+ }
+
goto replay_key;
}
}
- else if (CONSP (XCONS (key)->cdr)
+ else if (CONSP (XCDR (key))
&& CONSP (EVENT_START (key))
- && CONSP (XCONS (EVENT_START (key))->cdr))
+ && CONSP (XCDR (EVENT_START (key))))
{
Lisp_Object posn;
posn = POSN_BUFFER_POSN (EVENT_START (key));
/* Handle menu-bar events:
insert the dummy prefix event `menu-bar'. */
- if (EQ (posn, Qmenu_bar))
+ if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar))
{
if (t + 1 >= bufsize)
error ("Key sequence too long");
int modifiers;
breakdown = parse_modifiers (head);
- modifiers = XINT (XCONS (XCONS (breakdown)->cdr)->car);
+ modifiers = XINT (XCAR (XCDR (breakdown)));
/* Attempt to reduce an unbound mouse event to a simpler
event that is bound:
Drags reduce to clicks.
}
new_head
- = apply_modifiers (modifiers, XCONS (breakdown)->car);
+ = apply_modifiers (modifiers, XCAR (breakdown));
new_click
= Fcons (new_head, Fcons (EVENT_START (key), Qnil));
fkey_next = fkey_map;
fkey_next
- = get_keyelt (access_keymap (fkey_next, key, 1, 0), 0);
+ = get_keyelt (access_keymap (fkey_next, key, 1, 0), 1);
+
+ /* Handle symbol with autoload definition. */
+ if (SYMBOLP (fkey_next) && ! NILP (Ffboundp (fkey_next))
+ && CONSP (XSYMBOL (fkey_next)->function)
+ && EQ (XCAR (XSYMBOL (fkey_next)->function), Qautoload))
+ do_autoload (XSYMBOL (fkey_next)->function,
+ fkey_next);
+
+ /* Handle a symbol whose function definition is a keymap
+ or an array. */
+ if (SYMBOLP (fkey_next) && ! NILP (Ffboundp (fkey_next))
+ && (!NILP (Farrayp (XSYMBOL (fkey_next)->function))
+ || !NILP (Fkeymapp (XSYMBOL (fkey_next)->function))))
+ fkey_next = XSYMBOL (fkey_next)->function;
#if 0 /* I didn't turn this on, because it might cause trouble
for the mapping of return into C-m and tab into C-i. */
fkey_start = fkey_end = t;
fkey_map = Vfunction_key_map;
- /* Do pass the results through key-translation-map. */
- keytran_start = keytran_end = 0;
+ /* Do pass the results through key-translation-map.
+ But don't retranslate what key-translation-map
+ has already translated. */
+ keytran_end = keytran_start;
keytran_map = Vkey_translation_map;
goto replay_sequence;
keytran_next = keytran_map;
keytran_next
- = get_keyelt (access_keymap (keytran_next, key, 1, 0), 0);
+ = get_keyelt (access_keymap (keytran_next, key, 1, 0), 1);
+
+ /* Handle symbol with autoload definition. */
+ if (SYMBOLP (keytran_next) && ! NILP (Ffboundp (keytran_next))
+ && CONSP (XSYMBOL (keytran_next)->function)
+ && EQ (XCAR (XSYMBOL (keytran_next)->function), Qautoload))
+ do_autoload (XSYMBOL (keytran_next)->function,
+ keytran_next);
+ /* Handle a symbol whose function definition is a keymap
+ or an array. */
+ if (SYMBOLP (keytran_next) && ! NILP (Ffboundp (keytran_next))
+ && (!NILP (Farrayp (XSYMBOL (keytran_next)->function))
+ || !NILP (Fkeymapp (XSYMBOL (keytran_next)->function))))
+ keytran_next = XSYMBOL (keytran_next)->function;
+
/* If the key translation map gives a function, not an
- array, then call the function with no args and use
+ array, then call the function with one arg and use
its value instead. */
if (SYMBOLP (keytran_next) && ! NILP (Ffboundp (keytran_next))
&& keytran_end == t)
/* Don't pass the results of key-translation-map
through function-key-map. */
fkey_start = fkey_end = t;
- fkey_map = Vkey_translation_map;
+ fkey_map = Vfunction_key_map;
goto replay_sequence;
}
int modifiers;
breakdown = parse_modifiers (key);
- modifiers = XINT (XCONS (XCONS (breakdown)->cdr)->car);
+ modifiers = XINT (XCAR (XCDR (breakdown)));
if (modifiers & shift_modifier)
{
Lisp_Object new_key;
modifiers &= ~shift_modifier;
new_key = apply_modifiers (modifiers,
- XCONS (breakdown)->car);
+ XCAR (breakdown));
keybuf[t - 1] = new_key;
mock_input = t;
Better ideas? */
for (; t < mock_input; t++)
{
- if (echo_keystrokes)
+ if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
+ && NILP (Fzerop (Vecho_keystrokes)))
echo_char (keybuf[t]);
add_command_key (keybuf[t]);
}
\n\
`read-key-sequence' checks `function-key-map' for function key\n\
sequences, where they wouldn't conflict with ordinary bindings. See\n\
-`function-key-map' for more details.")
- (prompt, continue_echo, dont_downcase_last, can_return_switch_frame)
+`function-key-map' for more details.\n\
+\n\
+The optional fifth argument COMMAND-LOOP, if non-nil, means\n\
+that this key sequence is being read by something that will\n\
+read commands one after another. It should be nil if the caller\n\
+will read just one key sequence.")
+ (prompt, continue_echo, dont_downcase_last, can_return_switch_frame, command-loop)
#endif
-DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 4, 0,
+DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 5, 0,
0)
- (prompt, continue_echo, dont_downcase_last, can_return_switch_frame)
+ (prompt, continue_echo, dont_downcase_last, can_return_switch_frame,
+ command_loop)
Lisp_Object prompt, continue_echo, dont_downcase_last;
- Lisp_Object can_return_switch_frame;
+ Lisp_Object can_return_switch_frame, command_loop;
{
Lisp_Object keybuf[30];
register int i;
- struct gcpro gcpro1, gcpro2;
+ struct gcpro gcpro1;
+ int count = specpdl_ptr - specpdl;
if (!NILP (prompt))
CHECK_STRING (prompt, 0);
QUIT;
+ specbind (Qinput_method_exit_on_first_char,
+ (NILP (command_loop) ? Qt : Qnil));
+ specbind (Qinput_method_use_echo_area,
+ (NILP (command_loop) ? Qt : Qnil));
+
bzero (keybuf, sizeof keybuf);
GCPRO1 (keybuf[0]);
gcpro1.nvars = (sizeof keybuf/sizeof (keybuf[0]));
this_single_command_key_start = 0;
}
+#ifdef HAVE_X_WINDOWS
+ if (display_busy_cursor_p)
+ cancel_busy_cursor ();
+#endif
+
i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])),
prompt, ! NILP (dont_downcase_last),
! NILP (can_return_switch_frame), 0);
+#ifdef HAVE_X_WINDOWS
+ if (display_busy_cursor_p)
+ start_busy_cursor ();
+#endif
+
if (i == -1)
{
Vquit_flag = Qt;
QUIT;
}
UNGCPRO;
- return make_event_array (i, keybuf);
+ return unbind_to (count, make_event_array (i, keybuf));
}
DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,
- Sread_key_sequence_vector, 1, 4, 0,
+ Sread_key_sequence_vector, 1, 5, 0,
"Like `read-key-sequence' but always return a vector.")
- (prompt, continue_echo, dont_downcase_last, can_return_switch_frame)
+ (prompt, continue_echo, dont_downcase_last, can_return_switch_frame,
+ command_loop)
Lisp_Object prompt, continue_echo, dont_downcase_last;
- Lisp_Object can_return_switch_frame;
+ Lisp_Object can_return_switch_frame, command_loop;
{
Lisp_Object keybuf[30];
register int i;
- struct gcpro gcpro1, gcpro2;
+ struct gcpro gcpro1;
+ int count = specpdl_ptr - specpdl;
if (!NILP (prompt))
CHECK_STRING (prompt, 0);
QUIT;
+ specbind (Qinput_method_exit_on_first_char,
+ (NILP (command_loop) ? Qt : Qnil));
+ specbind (Qinput_method_use_echo_area,
+ (NILP (command_loop) ? Qt : Qnil));
+
bzero (keybuf, sizeof keybuf);
GCPRO1 (keybuf[0]);
gcpro1.nvars = (sizeof keybuf/sizeof (keybuf[0]));
this_single_command_key_start = 0;
}
+#ifdef HAVE_X_WINDOWS
+ if (display_busy_cursor_p)
+ cancel_busy_cursor ();
+#endif
+
i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])),
prompt, ! NILP (dont_downcase_last),
! NILP (can_return_switch_frame), 0);
+#ifdef HAVE_X_WINDOWS
+ if (display_busy_cursor_p)
+ start_busy_cursor ();
+#endif
+
if (i == -1)
{
Vquit_flag = Qt;
QUIT;
}
UNGCPRO;
- return Fvector (i, keybuf);
+ return unbind_to (count, Fvector (i, keybuf));
}
\f
DEFUN ("command-execute", Fcommand_execute, Scommand_execute, 1, 4, 0,
{
tem = Fnthcdr (Vhistory_length, Vcommand_history);
if (CONSP (tem))
- XCONS (tem)->cdr = Qnil;
+ XCDR (tem) = Qnil;
}
}
if (EQ (prefixarg, Qminus))
strcpy (buf, "- ");
- else if (CONSP (prefixarg) && XINT (XCONS (prefixarg)->car) == 4)
+ else if (CONSP (prefixarg) && XINT (XCAR (prefixarg)) == 4)
strcpy (buf, "C-u ");
- else if (CONSP (prefixarg) && INTEGERP (XCONS (prefixarg)->car))
+ else if (CONSP (prefixarg) && INTEGERP (XCAR (prefixarg)))
{
if (sizeof (int) == sizeof (EMACS_INT))
- sprintf (buf, "%d ", XINT (XCONS (prefixarg)->car));
+ sprintf (buf, "%d ", XINT (XCAR (prefixarg)));
else if (sizeof (long) == sizeof (EMACS_INT))
- sprintf (buf, "%ld ", XINT (XCONS (prefixarg)->car));
+ sprintf (buf, "%ld ", (long) XINT (XCAR (prefixarg)));
else
abort ();
}
if (sizeof (int) == sizeof (EMACS_INT))
sprintf (buf, "%d ", XINT (prefixarg));
else if (sizeof (long) == sizeof (EMACS_INT))
- sprintf (buf, "%ld ", XINT (prefixarg));
+ sprintf (buf, "%ld ", (long) XINT (prefixarg));
else
abort ();
}
function = Fintern (function, Qnil);
current_kboard->Vprefix_arg = prefixarg;
- this_command = function;
+ Vthis_command = function;
+ real_this_command = function;
/* If enabled, show which key runs this command. */
if (!NILP (Vsuggest_key_bindings)
{
/* But first wait, and skip the message if there is input. */
int delay_time;
- if (echo_area_glyphs != 0)
+ if (!NILP (echo_area_buffer[0]))
/* This command displayed something in the echo area;
so wait a few seconds, then display our suggestion message. */
delay_time = (NUMBERP (Vsuggest_key_bindings)
{
Lisp_Object binding;
char *newmessage;
- char *oldmessage = echo_area_glyphs;
- int oldmessage_len = echo_area_glyphs_length;
- int oldmultibyte = message_enable_multibyte;
+ int message_p = push_message ();
binding = Fkey_description (bindings);
STRING_MULTIBYTE (binding));
if (!NILP (Fsit_for ((NUMBERP (Vsuggest_key_bindings)
? Vsuggest_key_bindings : make_number (2)),
- Qnil, Qnil)))
- message2_nolog (oldmessage, oldmessage_len, oldmultibyte);
+ Qnil, Qnil))
+ && message_p)
+ restore_message ();
+
+ pop_message ();
}
}
nmaps = current_minor_maps (NULL, &tmaps);
maps = (Lisp_Object *) xmalloc ((nmaps + 2) * sizeof (maps[0]));
bcopy (tmaps, maps, nmaps * sizeof (maps[0]));
-#ifdef USE_TEXT_PROPERTIES
maps[nmaps++] = get_local_map (PT, current_buffer);
-#else
- maps[nmaps++] = current_buffer->keymap;
-#endif
}
maps[nmaps++] = current_global_map;
get_input_pending (&input_pending, 1);
if (old_timers_run != timers_run && do_display)
- redisplay_preserve_echo_area ();
+ {
+ redisplay_preserve_echo_area ();
+ /* The following fixes a bug when using lazy-lock with
+ lazy-lock-defer-on-the-fly set to t, i.e. when fontifying
+ 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);
+ }
return input_pending;
}
before_command_restore_flag = 1;
before_command_key_count_1 = before_command_key_count;
before_command_echo_length_1 = before_command_echo_length;
+ return Qnil;
+}
+
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,
+ Sclear_this_command_keys, 0, 0, 0,
+ "Clear out the vector that `this-command-keys' returns.\n\
+Clear vector containing last 100 events.")
+ ()
+{
+ int i;
+
+ this_command_key_count = 0;
+
+ for (i = 0; i < XVECTOR (recent_keys)->size; ++i)
+ XVECTOR (recent_keys)->contents[i] = Qnil;
+ total_keys = 0;
+ recent_keys_index = 0;
+ return Qnil;
}
DEFUN ("recursion-depth", Frecursion_depth, Srecursion_depth, 0, 0, 0,
discard_tty_input ();
- /* Without the cast, GCC complains that this assignment loses the
- volatile qualifier of kbd_store_ptr. Is there anything wrong
- with that? */
- kbd_fetch_ptr = (struct input_event *) kbd_store_ptr;
+ kbd_fetch_ptr = kbd_store_ptr;
Ffillarray (kbd_buffer_frame_or_window, Qnil);
input_pending = 0;
(stuffstring)
Lisp_Object stuffstring;
{
- Lisp_Object tem;
int count = specpdl_ptr - specpdl;
int old_height, old_width;
int width, height;
- struct gcpro gcpro1, gcpro2;
+ struct gcpro gcpro1;
if (!NILP (stuffstring))
CHECK_STRING (stuffstring, 0);
with a window system; but suspend should be disabled in that case. */
get_frame_size (&width, &height);
if (width != old_width || height != old_height)
- change_frame_size (selected_frame, height, width, 0, 0);
+ change_frame_size (SELECTED_FRAME (), height, width, 0, 0, 0);
/* Run suspend-resume-hook. */
if (!NILP (Vrun_hooks))
char c;
/* Must preserve main program's value of errno. */
int old_errno = errno;
+ struct frame *sf = SELECTED_FRAME ();
#if defined (USG) && !defined (POSIX_SIGNALS)
if (!read_socket_hook && NILP (Vwindow_system))
cancel_echoing ();
if (!NILP (Vquit_flag)
- && (FRAME_TERMCAP_P (selected_frame) || FRAME_MSDOS_P (selected_frame)))
+ && (FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf)))
{
/* If SIGINT isn't blocked, don't let us be interrupted by
another SIGINT, it might be harmful due to non-reentrancy
void
quit_throw_to_read_char ()
{
- quit_error_check ();
sigfree ();
/* Prevent another signal from doing this before we finish. */
clear_waiting_for_input ();
#endif
#endif
if (FRAMEP (internal_last_event_frame)
- && XFRAME (internal_last_event_frame) != selected_frame)
+ && !EQ (internal_last_event_frame, selected_frame))
do_switch_frame (make_lispy_switch_frame (internal_last_event_frame),
Qnil, 0);
void
syms_of_keyboard ()
{
+ /* Tool-bars. */
+ QCimage = intern (":image");
+ staticpro (&QCimage);
+
+ staticpro (&Qhelp_echo);
+ Qhelp_echo = intern ("help-echo");
+
staticpro (&item_properties);
item_properties = Qnil;
+ staticpro (&tool_bar_item_properties);
+ tool_bar_item_properties = Qnil;
+ staticpro (&tool_bar_items_vector);
+ tool_bar_items_vector = Qnil;
+
+ staticpro (&real_this_command);
+ real_this_command = Qnil;
+
Qtimer_event_handler = intern ("timer-event-handler");
staticpro (&Qtimer_event_handler);
#ifdef WINDOWSNT
Qmouse_wheel = intern ("mouse-wheel");
staticpro (&Qmouse_wheel);
+ Qlanguage_change = intern ("language-change");
+ staticpro (&Qlanguage_change);
#endif
Qdrag_n_drop = intern ("drag-n-drop");
staticpro (&Qdrag_n_drop);
+ Qusr1_signal = intern ("usr1-signal");
+ staticpro (&Qusr1_signal);
+ Qusr2_signal = intern ("usr2-signal");
+ staticpro (&Qusr2_signal);
+
Qmenu_enable = intern ("menu-enable");
staticpro (&Qmenu_enable);
Qmenu_alias = intern ("menu-alias");
staticpro (&QCenable);
QCvisible = intern (":visible");
staticpro (&QCvisible);
+ QChelp = intern (":help");
+ staticpro (&QChelp);
QCfilter = intern (":filter");
staticpro (&QCfilter);
QCbutton = intern (":button");
staticpro (&Qup);
Qdown = intern ("down");
staticpro (&Qdown);
+ Qtop = intern ("top");
+ staticpro (&Qtop);
+ Qbottom = intern ("bottom");
+ staticpro (&Qbottom);
+ Qend_scroll = intern ("end-scroll");
+ staticpro (&Qend_scroll);
+ Qratio = intern ("ratio");
+ staticpro (&Qratio);
Qevent_kind = intern ("event-kind");
staticpro (&Qevent_kind);
Qinput_method_function = intern ("input-method-function");
staticpro (&Qinput_method_function);
+ Qinput_method_exit_on_first_char = intern ("input-method-exit-on-first-char");
+ staticpro (&Qinput_method_exit_on_first_char);
+ Qinput_method_use_echo_area = intern ("input-method-use-echo-area");
+ staticpro (&Qinput_method_use_echo_area);
+
+ Fset (Qinput_method_exit_on_first_char, Qnil);
+ Fset (Qinput_method_use_echo_area, Qnil);
+
{
struct event_head *p;
read_key_sequence_cmd = Qnil;
staticpro (&read_key_sequence_cmd);
+ menu_bar_one_keymap_changed_items = Qnil;
+ staticpro (&menu_bar_one_keymap_changed_items);
+
defsubr (&Sevent_convert_list);
defsubr (&Sread_key_sequence);
defsubr (&Sread_key_sequence_vector);
defsubr (&Sthis_single_command_keys);
defsubr (&Sthis_single_command_raw_keys);
defsubr (&Sreset_this_command_lengths);
+ defsubr (&Sclear_this_command_keys);
defsubr (&Ssuspend_emacs);
defsubr (&Sabort_recursive_edit);
defsubr (&Sexit_recursive_edit);
Vunread_input_method_events = Qnil;
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.");
+ "Meta-prefix character code.\n\
+Meta-foo as command input turns into this character followed by foo.");
XSETINT (meta_prefix_char, 033);
DEFVAR_KBOARD ("last-command", Vlast_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.\n\
+ "The last command executed.\n\
+Normally a symbol with a function definition, but can be whatever was found\n\
+in the keymap, or whatever the variable `this-command' was set to by that\n\
+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\
DEFVAR_KBOARD ("real-last-command", Vreal_last_command,
"Same as `last-command', but never altered by Lisp code.");
- DEFVAR_LISP ("this-command", &this_command,
+ DEFVAR_LISP ("this-command", &Vthis_command,
"The command now being executed.\n\
The command can set this variable; whatever is put here\n\
will be in `last-command' during the following command.");
- this_command = Qnil;
+ Vthis_command = Qnil;
DEFVAR_INT ("auto-save-interval", &auto_save_interval,
- "*Number of keyboard input characters between auto-saves.\n\
+ "*Number of input events between auto-saves.\n\
Zero means disable autosaving due to number of characters typed.");
auto_save_interval = 300;
Emacs also does a garbage collection if that seems to be warranted.");
XSETFASTINT (Vauto_save_timeout, 30);
- DEFVAR_INT ("echo-keystrokes", &echo_keystrokes,
- "*Nonzero means echo unfinished commands after this many seconds of pause.");
- echo_keystrokes = 1;
+ DEFVAR_LISP ("echo-keystrokes", &Vecho_keystrokes,
+ "*Nonzero means echo unfinished commands after this many seconds of pause.\n\
+The value may be integer or floating point.");
+ Vecho_keystrokes = make_number (1);
DEFVAR_INT ("polling-period", &polling_period,
"*Interval between polling for input during Lisp execution.\n\
Vkeyboard_translate_table = Qnil;
DEFVAR_BOOL ("cannot-suspend", &cannot_suspend,
- "Non-nil means to always spawn a subshell instead of suspending,\n\
-even if the operating system has support for stopping a process.");
+ "Non-nil means to always spawn a subshell instead of suspending.\n\
+\(Even if the operating system has support for stopping a process.\)");
cannot_suspend = 0;
DEFVAR_BOOL ("menu-prompting", &menu_prompting,
DEFVAR_LISP ("pre-command-hook", &Vpre_command_hook,
"Normal hook run before each command is executed.\n\
-Errors running the hook are caught and ignored.");
+If an unhandled error happens in running this hook,\n\
+the hook value is set to nil, since otherwise the error\n\
+might happen repeatedly and make Emacs nonfunctional.");
Vpre_command_hook = Qnil;
DEFVAR_LISP ("post-command-hook", &Vpost_command_hook,
"Normal hook run after each command is executed.\n\
-Errors running the hook are caught and ignored.");
+If an unhandled error happens in running this hook,\n\
+the hook value is set to nil, since otherwise the error\n\
+might happen repeatedly and make Emacs nonfunctional.");
Vpost_command_hook = Qnil;
DEFVAR_LISP ("post-command-idle-hook", &Vpost_command_idle_hook,
The function should return a list of zero or more events\n\
to be used as input. If it wants to put back some events\n\
to be reconsidered, separately, by the input method,\n\
-it can add them to the beginning of `unread-command-events'.");
+it can add them to the beginning of `unread-command-events'.\n\
+\n\
+The input method function can find in `input-method-previous-method'\n\
+the previous echo area message.\n\
+\n\
+The input method function should refer to the variables\n\
+`input-method-use-echo-area' and `input-method-exit-on-first-char'\n\
+for guidance on what to do.");
Vinput_method_function = Qnil;
+
+ DEFVAR_LISP ("input-method-previous-message",
+ &Vinput_method_previous_message,
+ "When `input-method-function' is called, hold the previous echo area message.\n\
+This variable exists because `read-event' clears the echo area\n\
+before running the input method. It is nil if there was no message.");
+ Vinput_method_previous_message = Qnil;
+
+ DEFVAR_LISP ("show-help-function", &Vshow_help_function,
+ "If non-nil, the function that implements the display of help.\n\
+It's called with one argument, the help string to display.");
+ Vshow_help_function = Qnil;
+
+ DEFVAR_LISP ("disable-point-adjustment", &Vdisable_point_adjustment,
+ "If non-nil, suppress point adjustment after executing a command.\n\
+\n\
+After a command is executed, if point is moved into a region that has\n\
+special properties (e.g. composition, display), we adjust point to\n\
+the boundary of the region. But, several special commands sets this\n\
+variable to non-nil, then we suppress the point adjustment.\n\
+\n\
+This variable is set to nil before reading a command, and is checked\n\
+just after executing the command");
+ Vdisable_point_adjustment = Qnil;
+
+ DEFVAR_LISP ("global-disable-point-adjustment",
+ &Vglobal_disable_point_adjustment,
+ "*If non-nil, always suppress point adjustment.\n\
+\n\
+The default value is nil, in which case, point adjustment are\n\
+suppressed only after special commands that set\n\
+`disable-point-adjustment' (which see) to non-nil.");
+ Vglobal_disable_point_adjustment = Qnil;
}
void