#include "dispextern.h"
#include "syntax.h"
#include "intervals.h"
+#include "keymap.h"
#include "blockinput.h"
#include "puresize.h"
#include "systime.h"
#define KBD_BUFFER_SIZE 4096
#endif
#else /* No X-windows, character input */
-#define KBD_BUFFER_SIZE 256
+#define KBD_BUFFER_SIZE 4096
#endif /* No X-windows */
+#define abs(x) ((x) >= 0 ? (x) : -(x))
+
/* Following definition copied from eval.c */
struct backtrace
Lisp_Object Vshow_help_function;
+/* If a string, the message displayed before displaying a help-echo
+ in the echo area. */
+
+Lisp_Object Vpre_help_message;
+
/* Nonzero means do menu prompting. */
+
static int menu_prompting;
/* Character to see next line of menu prompt. */
+
static Lisp_Object menu_prompt_more_char;
/* For longjmp to where kbd input is being done. */
+
static jmp_buf getcjmp;
/* True while doing kbd input. */
exists, and echo_message_buffer is eq to the current message
buffer, we know that the message comes from echo_kboard. */
-static struct kboard *echo_kboard;
+struct kboard *echo_kboard;
/* The buffer used for echoing. Set in echo_now, reset in
cancel_echoing. */
Lisp_Object Vglobal_disable_point_adjustment;
+/* The time when Emacs started being idle. */
+
+static EMACS_TIME timer_idleness_start_time;
+
\f
/* Global variable declarations. */
static void restore_getcjmp P_ ((jmp_buf));
static Lisp_Object apply_modifiers P_ ((int, Lisp_Object));
static void clear_event P_ ((struct input_event *));
+static void any_kboard_state P_ ((void));
/* Nonzero means don't try to suspend even if the operating system seems
to support it. */
static int cannot_suspend;
-#define min(a,b) ((a)<(b)?(a):(b))
-#define max(a,b) ((a)>(b)?(a):(b))
-
/* Install the string STR as the beginning of the string of echoing,
so that it serves as a prompt for the next character.
Also start echoing. */
add_command_key (key)
Lisp_Object key;
{
- int size = XVECTOR (this_command_keys)->size;
-
/* If reset-this-command-length was called recently, obey it now.
See the doc string of that function for an explanation of why. */
if (before_command_restore_flag)
before_command_restore_flag = 0;
}
- if (this_command_key_count >= size)
- {
- Lisp_Object new_keys;
-
- new_keys = Fmake_vector (make_number (size * 2), Qnil);
- bcopy (XVECTOR (this_command_keys)->contents,
- XVECTOR (new_keys)->contents,
- size * sizeof (Lisp_Object));
-
- this_command_keys = new_keys;
- }
+ if (this_command_key_count >= ASIZE (this_command_keys))
+ this_command_keys = larger_vector (this_command_keys,
+ 2 * ASIZE (this_command_keys),
+ Qnil);
- XVECTOR (this_command_keys)->contents[this_command_key_count++] = key;
+ AREF (this_command_keys, this_command_key_count) = key;
+ ++this_command_key_count;
}
+
\f
Lisp_Object
recursive_edit_1 ()
()
{
int count = specpdl_ptr - specpdl;
+ Lisp_Object buffer;
command_loop_level++;
update_mode_lines = 1;
+ if (command_loop_level
+ && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
+ buffer = Fcurrent_buffer ();
+ else
+ buffer = Qnil;
+
+ /* If we leave recursive_edit_1 below with a `throw' for instance,
+ like it is done in the splash screen display, we have to
+ make sure that we restore single_kboard as command_loop_1
+ would have done if it were left normally. */
record_unwind_protect (recursive_edit_unwind,
- (command_loop_level
- && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
- ? Fcurrent_buffer ()
- : Qnil);
+ Fcons (buffer, single_kboard ? Qt : Qnil));
+
recursive_edit_1 ();
return unbind_to (count, Qnil);
}
Lisp_Object
-recursive_edit_unwind (buffer)
- Lisp_Object buffer;
+recursive_edit_unwind (info)
+ Lisp_Object info;
{
- if (!NILP (buffer))
- Fset_buffer (buffer);
-
+ if (BUFFERP (XCAR (info)))
+ Fset_buffer (XCAR (info));
+
+ if (NILP (XCDR (info)))
+ any_kboard_state ();
+ else
+ single_kboard_state ();
+
command_loop_level--;
update_mode_lines = 1;
return Qnil;
}
+
\f
static void
any_kboard_state ()
/* This is the actual command reading loop,
sans error-handling encapsulation. */
-EXFUN (Fcommand_execute, 4);
static int read_key_sequence P_ ((Lisp_Object *, int, Lisp_Object,
int, int, int));
void safe_run_hooks P_ ((Lisp_Object));
/* 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 ();
+ resize_echo_area_exactly ();
if (!NILP (Vdeferred_action_list))
call0 (Vdeferred_action_function);
/* 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 ();
+ resize_echo_area_exactly ();
if (!NILP (Vdeferred_action_list))
safe_run_hooks (Qdeferred_action_function);
{
if (STRINGP (help))
{
- int count = specpdl_ptr - specpdl;
+ int count = BINDING_STACK_SIZE ();
+
+ if (!help_echo_showing_p)
+ Vpre_help_message = current_message ();
+
specbind (Qmessage_truncate_lines, Qt);
message3_nolog (help, STRING_BYTES (XSTRING (help)),
STRING_MULTIBYTE (help));
unbind_to (count, Qnil);
}
+ else if (STRINGP (Vpre_help_message))
+ {
+ message3_nolog (Vpre_help_message,
+ STRING_BYTES (XSTRING (Vpre_help_message)),
+ STRING_MULTIBYTE (Vpre_help_message));
+ Vpre_help_message = Qnil;
+ }
else
- message (0);
+ message (0);
}
help_echo_showing_p = STRINGP (help);
volatile Lisp_Object also_record;
volatile int reread;
struct gcpro gcpro1, gcpro2;
+ EMACS_TIME last_idle_start;
also_record = Qnil;
/* Undo what read_char_x_menu_prompt did when it unread
additional keys returned by Fx_popup_menu. */
if (CONSP (c)
- && (SYMBOLP (XCAR (c)) || INTEGERP (XCAR (c)))
- && NILP (XCDR (c)))
+ && EQ (XCDR (c), Qdisabled)
+ && (SYMBOLP (XCAR (c)) || INTEGERP (XCAR (c))))
c = XCAR (c);
-
+
/* If the queued event is something that used the mouse,
set used_mouse_menu accordingly. */
if (used_mouse_menu
KBOARD *kb = FRAME_KBOARD (XFRAME (selected_frame));
if (kb != current_kboard)
{
- Lisp_Object *tailp = &kb->kbd_queue;
+ Lisp_Object link = kb->kbd_queue;
/* We shouldn't get here if we were in single-kboard mode! */
if (single_kboard)
abort ();
- while (CONSP (*tailp))
- tailp = &XCDR (*tailp);
- if (!NILP (*tailp))
- abort ();
- *tailp = Fcons (c, Qnil);
+ if (CONSP (link))
+ {
+ while (CONSP (XCDR (link)))
+ link = XCDR (link);
+ if (!NILP (XCDR (link)))
+ abort ();
+ }
+ if (!CONSP (link))
+ kb->kbd_queue = Fcons (c, Qnil);
+ else
+ XSETCDR (link, Fcons (c, Qnil));
kb->kbd_queue_has_data = 1;
current_kboard = kb;
/* This is going to exit from read_char
#ifdef MULTI_KBOARD
if (! NILP (c) && (kb != current_kboard))
{
- Lisp_Object *tailp = &kb->kbd_queue;
- while (CONSP (*tailp))
- tailp = &XCDR (*tailp);
- if (!NILP (*tailp))
- abort ();
- *tailp = Fcons (c, Qnil);
+ Lisp_Object link = kb->kbd_queue;
+ if (CONSP (link))
+ {
+ while (CONSP (XCDR (link)))
+ link = XCDR (link);
+ if (!NILP (XCDR (link)))
+ abort ();
+ }
+ if (!CONSP (link))
+ kb->kbd_queue = Fcons (c, Qnil);
+ else
+ XSETCDR (link, Fcons (c, Qnil));
kb->kbd_queue_has_data = 1;
c = Qnil;
if (single_kboard)
non_reread:
+ /* Record the last idle start time so that we can reset it
+ should the next event read be a help-echo. */
+ last_idle_start = timer_idleness_start_time;
timer_stop_idle ();
start_polling ();
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);
+ POSN_BUFFER_SET_POSN (EVENT_START (c), Fcons (posn, Qnil));
also_record = c;
Vunread_command_events = Fcons (c, Vunread_command_events);
/* Now wipe the echo area, except for help events which do their
own stuff with the echo area. */
- if (!CONSP (c) || !(EQ (Qhelp_echo, XCAR (c))))
+ if (!CONSP (c)
+ || (!(EQ (Qhelp_echo, XCAR (c)))
+ && !(EQ (Qswitch_frame, XCAR (c)))))
{
if (!NILP (echo_area_buffer[0]))
safe_run_hooks (Qecho_area_clear_hook);
object = Fnth (make_number (4), c);
position = Fnth (make_number (5), c);
show_help_echo (help, window, object, position, 0);
+
+ /* We stopped being idle for this event; undo that. */
+ timer_idleness_start_time = last_idle_start;
goto retry;
}
redisplay_preserve_echo_area (7);
}
\f
-static EMACS_TIME timer_idleness_start_time;
-
/* Record the start of when Emacs is idle,
for the sake of running idle-time timers. */
static int last_mouse_y;
static unsigned long button_down_time;
-/* The maximum time between clicks to make a double-click,
- or Qnil to disable double-click detection,
- or Qt for no time limit. */
+/* The maximum time between clicks to make a double-click, or Qnil to
+ disable double-click detection, or Qt for no time limit. */
+
Lisp_Object Vdouble_click_time;
+/* Maximum number of pixels the mouse may be moved between clicks
+ to make a double-click. */
+
+int double_click_fuzz;
+
/* The number of clicks in this multiple-click. */
int double_click_count;
/ sizeof (iso_lispy_function_keys[0])));
else
#endif
- return modify_event_symbol (event->code - FUNCTION_KEY_OFFSET,
- event->modifiers,
- Qfunction_key, Qnil,
- lispy_function_keys, &func_key_syms,
- (sizeof (lispy_function_keys)
- / sizeof (lispy_function_keys[0])));
+
+#ifdef HAVE_X_WINDOWS
+ if (event->code - FUNCTION_KEY_OFFSET < 0
+ || (event->code - FUNCTION_KEY_OFFSET
+ >= sizeof lispy_function_keys / sizeof *lispy_function_keys))
+ {
+ /* EVENT->code is an unknown keysym, for example someone
+ assigned `ccaron' to a key in a locale where
+ XmbLookupString doesn't return a translation for it. */
+ char *name;
+ Lisp_Object symbol;
+
+ BLOCK_INPUT;
+ /* This returns a pointer to a static area. Don't free it. */
+ name = XKeysymToString (event->code);
+ symbol = name ? intern (name) : Qnil;
+ UNBLOCK_INPUT;
+
+ if (!NILP (symbol))
+ return apply_modifiers (event->modifiers, symbol);
+ }
+#endif /* HAVE_X_WINDOWS */
+
+ return modify_event_symbol (event->code - FUNCTION_KEY_OFFSET,
+ event->modifiers,
+ Qfunction_key, Qnil,
+ lispy_function_keys, &func_key_syms,
+ (sizeof (lispy_function_keys)
+ / sizeof (lispy_function_keys[0])));
#ifdef HAVE_MOUSE
/* A mouse click. Figure out where it is, decide whether it's
Lisp_Object position;
Lisp_Object *start_pos_ptr;
Lisp_Object start_pos;
+ Lisp_Object window;
position = Qnil;
if (event->kind == mouse_click)
{
int part;
- FRAME_PTR f = XFRAME (event->frame_or_window);
- Lisp_Object window;
+ struct frame *f = XFRAME (event->frame_or_window);
Lisp_Object posn;
Lisp_Object string_info = Qnil;
int row, column;
else
{
/* It's a scrollbar click. */
- Lisp_Object window;
Lisp_Object portion_whole;
Lisp_Object part;
start_pos = *start_pos_ptr;
*start_pos_ptr = Qnil;
- is_double = (button == last_mouse_button
- && XINT (event->x) == last_mouse_x
- && XINT (event->y) == last_mouse_y
- && button_down_time != 0
- && (EQ (Vdouble_click_time, Qt)
- || (INTEGERP (Vdouble_click_time)
- && ((int)(event->timestamp - button_down_time)
- < XINT (Vdouble_click_time)))));
+ {
+ /* On window-system frames, use the value of
+ double-click-fuzz as is. On other frames, interpret it
+ as a multiple of 1/8 characters. */
+ struct frame *f;
+ int fuzz;
+
+ if (WINDOWP (event->frame_or_window))
+ f = XFRAME (XWINDOW (event->frame_or_window)->frame);
+ else if (FRAMEP (event->frame_or_window))
+ f = XFRAME (event->frame_or_window);
+ else
+ abort ();
+
+ if (FRAME_WINDOW_P (f))
+ fuzz = double_click_fuzz;
+ else
+ fuzz = double_click_fuzz / 8;
+
+ is_double = (button == last_mouse_button
+ && (abs (XINT (event->x) - last_mouse_x) <= fuzz)
+ && (abs (XINT (event->y) - last_mouse_y) <= fuzz)
+ && button_down_time != 0
+ && (EQ (Vdouble_click_time, Qt)
+ || (INTEGERP (Vdouble_click_time)
+ && ((int)(event->timestamp - button_down_time)
+ < XINT (Vdouble_click_time)))));
+ }
+
last_mouse_button = button;
last_mouse_x = XINT (event->x);
last_mouse_y = XINT (event->y);
STRING_BYTES (XSYMBOL (symbol)->name) - end),
Qnil);
- if (modifiers & ~(((EMACS_INT)1 << VALBITS) - 1))
+ if (modifiers & ~VALMASK)
abort ();
XSETFASTINT (mask, modifiers);
elements = Fcons (unmodified, Fcons (mask, Qnil));
Lisp_Object cache, index, entry, new_symbol;
/* Mask out upper bits. We don't know where this value's been. */
- modifiers &= ((EMACS_INT)1 << VALBITS) - 1;
+ modifiers &= VALMASK;
/* The click modifier never figures into cache indices. */
cache = Fget (base, Qmodifier_cache);
\f
-/* Return the prompt-string of a sparse keymap.
- This is the first element which is a string.
- Return nil if there is none. */
-
-Lisp_Object
-map_prompt (map)
- Lisp_Object map;
-{
- while (CONSP (map))
- {
- register Lisp_Object tem;
- tem = Fcar (map);
- if (STRINGP (tem))
- return tem;
- map = Fcdr (map);
- }
- return Qnil;
-}
-
static void menu_bar_item P_ ((Lisp_Object, Lisp_Object));
static void menu_bar_one_keymap P_ ((Lisp_Object));
{
/* We have to create a cachelist. */
CHECK_IMPURE (start);
- XCDR (start) = Fcons (Fcons (Qnil, Qnil), XCDR (start));
+ XSETCDR (start, Fcons (Fcons (Qnil, Qnil), XCDR (start)));
cachelist = XCAR (XCDR (start));
newcache = 1;
tem = AREF (item_properties, ITEM_PROPERTY_KEYEQ);
if (!NILP (keyhint))
{
- XCAR (cachelist) = XCAR (keyhint);
+ XSETCAR (cachelist, XCAR (keyhint));
newcache = 0;
}
else if (STRINGP (tem))
{
- XCDR (cachelist) = Fsubstitute_command_keys (tem);
- XCAR (cachelist) = Qt;
+ XSETCDR (cachelist, Fsubstitute_command_keys (tem));
+ XSETCAR (cachelist, Qt);
}
}
&& ! NILP (Fget (def, Qmenu_alias)))
def = XSYMBOL (def)->function;
tem = Fwhere_is_internal (def, Qnil, Qt, Qnil);
- XCAR (cachelist) = tem;
+ XSETCAR (cachelist, tem);
if (NILP (tem))
{
- XCDR (cachelist) = Qnil;
+ XSETCDR (cachelist, Qnil);
chkcache = 0;
}
}
if (STRINGP (XCDR (prefix)))
tem = concat2 (tem, XCDR (prefix));
}
- XCDR (cachelist) = tem;
+ XSETCDR (cachelist, tem);
}
}
if (newcache && !NILP (tem))
{
tem = concat3 (build_string (" ("), tem, build_string (")"));
- XCDR (cachelist) = tem;
+ XSETCDR (cachelist, tem);
}
/* If we only want to precompute equivalent key bindings, stop here. */
/* Get the menu name from the first map that has one (a prompt string). */
for (mapno = 0; mapno < nmaps; mapno++)
{
- name = map_prompt (maps[mapno]);
+ name = Fkeymap_prompt (maps[mapno]);
if (!NILP (name))
break;
}
to indicate that they came from a mouse menu,
so that when present in last_nonmenu_event
they won't confuse things. */
- for (tem = XCDR (value); !NILP (tem);
- tem = XCDR (tem))
+ for (tem = XCDR (value); !NILP (tem); tem = XCDR (tem))
{
record_menu_key (XCAR (tem));
if (SYMBOLP (XCAR (tem))
|| INTEGERP (XCAR (tem)))
- XCAR (tem)
- = Fcons (XCAR (tem), Qnil);
+ XSETCAR (tem, Fcons (XCAR (tem), Qdisabled));
}
/* If we got more than one event, put all but the first
/* Get the menu name from the first map that has one (a prompt string). */
for (mapno = 0; mapno < nmaps; mapno++)
{
- name = map_prompt (maps[mapno]);
+ name = Fkeymap_prompt (maps[mapno]);
if (!NILP (name))
break;
}
/* If we have a quit that was typed in another frame, and
quit_throw_to_read_char switched buffers,
replay to get the right keymap. */
- if (XINT (key) == quit_char && current_buffer != starting_buffer)
+ if (INTEGERP (key)
+ && XINT (key) == quit_char
+ && current_buffer != starting_buffer)
{
GROW_RAW_KEYBUF;
XVECTOR (raw_keybuf)->contents[raw_keybuf_count++] = key;
/* 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);
+ POSN_BUFFER_SET_POSN (EVENT_START (key),
+ Fcons (posn, Qnil));
mock_input = t + 2;
goto replay_sequence;
{
tem = Fnthcdr (Vhistory_length, Vcommand_history);
if (CONSP (tem))
- XCDR (tem) = Qnil;
+ XSETCDR (tem, Qnil);
}
}
void
syms_of_keyboard ()
{
+ Vpre_help_message = Qnil;
+ staticpro (&Vpre_help_message);
+
Vlispy_mouse_stem = build_string ("mouse");
staticpro (&Vlispy_mouse_stem);
-
+
/* Tool-bars. */
QCimage = intern (":image");
staticpro (&QCimage);
by position only.");
Vdouble_click_time = make_number (500);
+ DEFVAR_INT ("double-click-fuzz", &double_click_fuzz,
+ "*Maximum mouse movement between clicks to make a double-click.\n\
+On window-system frames, value is the number of pixels the mouse may have\n\
+moved horizontally or vertically between two clicks to make a double-click.\n\
+On non window-system frames, value is interpreted in units of 1/8 characters\n\
+instead of pixels.");
+ double_click_fuzz = 3;
+
DEFVAR_BOOL ("inhibit-local-menu-bar-menus", &inhibit_local_menu_bar_menus,
"*Non-nil means inhibit local map menu bar menus.");
inhibit_local_menu_bar_menus = 0;
"Normal hook run when clearing the echo area.");
#endif
Qecho_area_clear_hook = intern ("echo-area-clear-hook");
- XSYMBOL (Qecho_area_clear_hook)->value = Qnil;
+ SET_SYMBOL_VALUE (Qecho_area_clear_hook, Qnil);
DEFVAR_LISP ("lucid-menu-bar-dirty-flag", &Vlucid_menu_bar_dirty_flag,
"t means menu bar, specified Lucid style, needs to be recomputed.");