/* True while displaying for echoing. Delays C-g throwing. */
-static int echoing;
+int echoing;
/* Non-null means we can start echoing at the next input pause even
though there is something in the echo area. */
/* The buffer used for echoing. Set in echo_now, reset in
cancel_echoing. */
-static Lisp_Object echo_message_buffer;
+Lisp_Object echo_message_buffer;
/* Nonzero means disregard local maps for the menu bar. */
static int inhibit_local_menu_bar_menus;
Lisp_Object Vglobal_disable_point_adjustment;
+/* The time when Emacs started being idle. */
+
+static EMACS_TIME timer_idleness_start_time;
+
\f
/* Global variable declarations. */
/* This is the actual command reading loop,
sans error-handling encapsulation. */
-Lisp_Object Fcommand_execute ();
-static int read_key_sequence ();
-void safe_run_hooks ();
-static void adjust_point_for_property ();
+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));
+static void adjust_point_for_property P_ ((int));
Lisp_Object
command_loop_1 ()
this variable differently. */
Vdisable_point_adjustment = Qnil;
+ /* Process filters and timers may have messed with deactivate-mark.
+ reset it before we execute the command. */
+ Vdeactivate_mark = Qnil;
+
/* Execute the command. */
Vthis_command = cmd;
volatile Lisp_Object also_record;
volatile int reread;
struct gcpro gcpro1, gcpro2;
+ EMACS_TIME last_idle_start;
also_record = Qnil;
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 ();
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. */
if (NILP (vector[0]))
{
int was_locked = single_kboard;
- int count = specpdl_ptr - specpdl;
+ int count = BINDING_STACK_SIZE ();
+ Lisp_Object old_deactivate_mark = Vdeactivate_mark;
/* Mark the timer as triggered to prevent problems if the lisp
code fails to reschedule it right. */
vector[0] = Qt;
specbind (Qinhibit_quit, Qt);
-
+
call1 (Qtimer_event_handler, chosen_timer);
+ Vdeactivate_mark = old_deactivate_mark;
timers_run++;
-
unbind_to (count, Qnil);
/* Resume allowing input from any kboard, if that was true before. */
for (i = 0; i < XVECTOR (items)->size; i += 4)
{
Lisp_Object pos, string;
- string = XVECTOR (items)->contents[i + 1];
- pos = XVECTOR (items)->contents[i + 3];
+ string = AREF (items, i + 1);
+ pos = AREF (items, i + 3);
if (NILP (string))
break;
if (column >= XINT (pos)
&& column < XINT (pos) + XSTRING (string)->size)
{
- item = XVECTOR (items)->contents[i];
+ item = AREF (items, i);
break;
}
}
else if (part == 2)
posn = Qvertical_line;
else
- XSETINT (posn, buffer_posn_from_coords (w, &wx, &wy));
+ {
+ Lisp_Object object;
+ struct display_pos p;
+ buffer_posn_from_coords (w, &wx, &wy, &object, &p);
+ posn = make_number (CHARPOS (p.pos));
+ if (STRINGP (object))
+ string_info
+ = Fcons (object,
+ make_number (CHARPOS (p.string_pos)));
+ }
}
position
}
#endif /* not USE_TOOLKIT_SCROLL_BARS */
- if (button >= XVECTOR (button_down_location)->size)
+ if (button >= ASIZE (button_down_location))
{
button_down_location = larger_vector (button_down_location,
button + 1, Qnil);
mouse_syms = larger_vector (mouse_syms, button + 1, Qnil);
}
- start_pos_ptr = &XVECTOR (button_down_location)->contents[button];
-
+ start_pos_ptr = &AREF (button_down_location, button);
start_pos = *start_pos_ptr;
*start_pos_ptr = Qnil;
see if this was a click or a drag. */
else if (event->modifiers & up_modifier)
{
- /* If we did not see a down before this up,
- ignore the up. Probably this happened because
- the down event chose a menu item.
- It would be an annoyance to treat the release
- of the button that chose the menu item
- as a separate event. */
+ /* If we did not see a down before this up, ignore the up.
+ Probably this happened because the down event chose a
+ menu item. It would be an annoyance to treat the
+ release of the button that chose the menu item as a
+ separate event. */
if (!CONSP (start_pos))
return Qnil;
Lisp_Object down;
down = Fnth (make_number (2), start_pos);
- if (EQ (event->x, XCAR (down))
- && EQ (event->y, XCDR (down)))
- {
- event->modifiers |= click_modifier;
- }
+ if (EQ (event->x, XCAR (down)) && EQ (event->y, XCDR (down)))
+ /* Mouse hasn't moved. */
+ event->modifiers |= click_modifier;
else
{
- button_down_time = 0;
- event->modifiers |= drag_modifier;
+ Lisp_Object window1, window2, posn1, posn2;
+
+ /* Avoid generating a drag event if the mouse
+ hasn't actually moved off the buffer position. */
+ window1 = Fnth (make_number (0), position);
+ posn1 = Fnth (make_number (1), position);
+ window2 = Fnth (make_number (0), start_pos);
+ posn2 = Fnth (make_number (1), start_pos);
+
+ if (EQ (window1, window2) && EQ (posn1, posn2))
+ event->modifiers |= click_modifier;
+ else
+ {
+ button_down_time = 0;
+ event->modifiers |= drag_modifier;
+ }
}
+
/* Don't check is_double; treat this as multiple
if the down-event was multiple. */
if (double_click_count > 1)
else if (part == 3)
posn = Qheader_line;
else
- XSETINT (posn,
- buffer_posn_from_coords (XWINDOW (window),
- &column, &row));
+ {
+ Lisp_Object object;
+ struct display_pos p;
+ buffer_posn_from_coords (XWINDOW (window), &column, &row,
+ &object, &p);
+ posn = make_number (CHARPOS (p.pos));
+ }
}
{
else if (part == 3)
posn = Qheader_line;
else
- XSETINT (posn, buffer_posn_from_coords (w, &wx, &wy));
+ {
+ Lisp_Object object;
+ struct display_pos p;
+ buffer_posn_from_coords (w, &wx, &wy, &object, &p);
+ posn = make_number (CHARPOS (p.pos));
+ }
}
{
else if (area == 3)
posn = Qheader_line;
else
- XSETINT (posn, buffer_posn_from_coords (w, &wx, &wy));
+ {
+ Lisp_Object object;
+ struct display_pos p;
+ buffer_posn_from_coords (w, &wx, &wy, &object, &p);
+ posn = make_number (CHARPOS (p.pos));
+ }
}
else if (frame != 0)
{
int can_return_switch_frame;
int fix_current_buffer;
{
+ volatile Lisp_Object from_string;
volatile int count = specpdl_ptr - specpdl;
/* How many keys there are in the current key sequence. */
volatile int function_key_possible = 0;
volatile int key_translation_possible = 0;
+ /* List of events for which a fake prefix key has been generated. */
+ volatile Lisp_Object fake_prefixed_keys = Qnil;
+
/* Save the status of key translation before each step,
so that we can restore this after downcasing. */
Lisp_Object prev_fkey_map;
int junk;
#endif
+ struct gcpro gcpro1;
+
+ GCPRO1 (fake_prefixed_keys);
raw_keybuf_count = 0;
last_nonmenu_event = Qnil;
orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
+ from_string = Qnil;
/* 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,
if (EQ (key, Qt))
{
unbind_to (count, Qnil);
+ UNGCPRO;
return -1;
}
window = POSN_WINDOW (EVENT_START (key));
posn = POSN_BUFFER_POSN (EVENT_START (key));
- if (CONSP (posn))
+ if (CONSP (posn)
+ || (!NILP (fake_prefixed_keys)
+ && !NILP (Fmemq (key, fake_prefixed_keys))))
{
- /* We're looking at the second event of a
- sequence which we expanded before. Set
+ /* We're looking a second time at an event for which
+ we generated a fake prefix key. Set
last_real_key_start appropriately. */
if (t > 0)
last_real_key_start = t - 1;
/* Expand mode-line and scroll-bar events into two events:
use posn as a fake prefix key. */
- if (SYMBOLP (posn))
+ if (SYMBOLP (posn)
+ && (NILP (fake_prefixed_keys)
+ || NILP (Fmemq (key, fake_prefixed_keys))))
{
if (t + 1 >= bufsize)
error ("Key sequence too long");
- 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);
+ keybuf[t] = posn;
+ keybuf[t + 1] = key;
+ mock_input = t + 2;
+
+ /* Record that a fake prefix key has been generated
+ for KEY. Don't modify the event; this would
+ prevent proper action when the event is pushed
+ back tino unread-command-events. */
+ fake_prefixed_keys = Fcons (key, fake_prefixed_keys);
/* If on a mode line string with a local keymap,
reconsider the key sequence with that keymap. */
goto replay_key;
}
+ else if (CONSP (POSN_STRING (EVENT_START (key)))
+ && NILP (from_string))
+ {
+ /* For a click on a string, i.e. overlay string or a
+ string displayed via the `display' property,
+ consider `local-map' and `keymap' properties of
+ that string. */
+ Lisp_Object string, pos, map, map2;
+
+ string = POSN_STRING (EVENT_START (key));
+ pos = XCDR (string);
+ string = XCAR (string);
+ if (XINT (pos) >= 0
+ && XINT (pos) < XSTRING (string)->size)
+ {
+ map = Fget_text_property (pos, Qlocal_map, string);
+ if (!NILP (map))
+ orig_local_map = map;
+ map2 = Fget_text_property (pos, Qkeymap, string);
+ if (!NILP (map2))
+ orig_keymap = map2;
+
+ if (!NILP (map) || !NILP (map2))
+ {
+ from_string = string;
+ goto replay_sequence;
+ }
+ }
+ }
}
else if (CONSP (XCDR (key))
&& CONSP (EVENT_START (key))
+ UNGCPRO;
return t;
}
if (FRAMEP (internal_last_event_frame)
&& !EQ (internal_last_event_frame, selected_frame))
do_switch_frame (make_lispy_switch_frame (internal_last_event_frame),
- Qnil, 0);
+ 0, 0);
_longjmp (getcjmp, 1);
}
}
#ifdef MULTI_KBOARD
+
+/* Free KB and memory referenced from it. */
+
void
delete_kboard (kb)
- KBOARD *kb;
+ KBOARD *kb;
{
KBOARD **kbp;
+
for (kbp = &all_kboards; *kbp != kb; kbp = &(*kbp)->next_kboard)
if (*kbp == NULL)
abort ();
*kbp = kb->next_kboard;
+
+ /* Prevent a dangling reference to KB. */
+ if (kb == current_kboard
+ && FRAMEP (selected_frame)
+ && FRAME_LIVE_P (XFRAME (selected_frame)))
+ {
+ current_kboard = XFRAME (selected_frame)->kboard;
+ if (current_kboard == kb)
+ abort ();
+ }
+
wipe_kboard (kb);
xfree (kb);
}
-#endif
+
+#endif /* MULTI_KBOARD */
void
init_keyboard ()
"Per-terminal keymap that overrides all other local keymaps.\n\
If this variable is non-nil, it is used as a keymap instead of the\n\
buffer's local map, and the minor mode keymaps and text property keymaps.\n\
-This variable is intended to let commands such as `universal-argumemnt'\n\
+This variable is intended to let commands such as `universal-argument'\n\
set up a different keymap for reading the next command.");
DEFVAR_LISP ("overriding-local-map", &Voverriding_local_map,