/* Keyboard and mouse input; editor command loop.
- Copyright (C) 1985,86,87,88,89,93,94,95 Free Software Foundation, Inc.
+ Copyright (C) 1985,86,87,88,89,93,94,95,96 Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+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>
/* Symbols to denote kinds of events. */
Lisp_Object Qfunction_key;
Lisp_Object Qmouse_click;
+Lisp_Object Qtimer_event;
/* Lisp_Object Qmouse_movement; - also an event header */
/* Properties of event headers. */
Lisp_Object recursive_edit_unwind (), command_loop ();
Lisp_Object Fthis_command_keys ();
Lisp_Object Qextended_command_history;
+EMACS_TIME timer_check ();
extern char *x_get_keysym_name ();
Lisp_Object Qpolling_period;
+/* List of absolute timers. Appears in order of next scheduled event. */
+Lisp_Object Vtimer_list;
+
+/* List of idle time timers. Appears in order of next scheduled event. */
+Lisp_Object Vtimer_idle_list;
+
+/* Incremented whenever a timer is run. */
+int timers_run;
+
extern Lisp_Object Vprint_level, Vprint_length;
/* Address (if not 0) of EMACS_TIME to zero out if a SIGIO interrupt
/* Nonzero while interrupts are temporarily deferred during redisplay. */
int interrupts_deferred;
-/* nonzero means use ^S/^Q for flow control. */
+/* Nonzero means use ^S/^Q for flow control. */
int flow_control;
/* Allow m- file to inhibit use of FIONREAD. */
current_kboard->echo_after_prompt = len;
- echo ();
+ echo_now ();
}
/* Add C to the echo string, if echoing is going on.
*ptr = 0;
current_kboard->echoptr = ptr;
- echo ();
+ echo_now ();
}
}
current_kboard->echoptr[0] = '-';
current_kboard->echoptr[1] = 0;
- echo ();
+ echo_now ();
}
/* Display the current echo string, and begin echoing if not already
doing so. */
-echo ()
+echo_now ()
{
if (!current_kboard->immediate_echo)
{
Fsit_for (make_number (2), Qnil, Qnil);
unbind_to (count, Qnil);
- echo_area_glyphs = 0;
- no_direct = 1;
+ /* Clear the echo area. */
+ message2 (0);
+
+ /* If a C-g came in before, treat it as input now. */
if (!NILP (Vquit_flag))
{
Vquit_flag = Qnil;
nonundocount = 0;
if (NILP (current_kboard->Vprefix_arg))
Fundo_boundary ();
- Fcommand_execute (this_command, Qnil, Qnil);
+ Fcommand_execute (this_command, Qnil, Qnil, Qnil);
}
directly_done: ;
int count = specpdl_ptr - specpdl;
specbind (Qinhibit_quit, hook);
- internal_condition_case (safe_run_hooks_1, Qerror, safe_run_hooks_error);
+ internal_condition_case (safe_run_hooks_1, Qt, safe_run_hooks_error);
unbind_to (count, Qnil);
}
input_poll_signal (signalnum) /* If we don't have an argument, */
int signalnum; /* some compilers complain in signal calls. */
{
+ /* 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);
- signal (SIGALRM, input_poll_signal);
- alarm (polling_period);
+ /* Turn on the SIGALRM handler and request another alarm. */
+ start_polling ();
}
#endif
goto non_reread;
}
+ timer_start_idle ();
+
/* If in middle of key sequence and minibuffer not active,
start echoing if enough time elapses. */
This is because we are probably about to display a menu,
and we don't want to delay before doing so. */
if (EVENT_HAS_PARAMETERS (prev_event))
- echo ();
+ echo_now ();
else
{
save_getcjmp (save_jump);
tem0 = sit_for (echo_keystrokes, 0, 1, 1);
restore_getcjmp (save_jump);
if (EQ (tem0, Qt))
- echo ();
+ echo_now ();
}
}
&& XINT (Vauto_save_timeout) > 0)
{
Lisp_Object tem0;
- int delay = delay_level * XFASTINT (Vauto_save_timeout) / 4;
save_getcjmp (save_jump);
restore_getcjmp (local_getcjmp);
- tem0 = sit_for (delay, 0, 1, 1);
+ tem0 = sit_for (delay_level * XFASTINT (Vauto_save_timeout) / 4,
+ 0, 1, 1);
restore_getcjmp (save_jump);
if (EQ (tem0, Qt))
= XCONS (current_kboard->kbd_queue)->cdr;
if (NILP (current_kboard->kbd_queue))
current_kboard->kbd_queue_has_data = 0;
- input_pending = readable_events ();
+ input_pending = readable_events (0);
#ifdef MULTI_FRAME
if (EVENT_HAS_PARAMETERS (c)
&& EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qswitch_frame))
non_reread:
+ /* Now that we have read an event, Emacs is not idle--
+ unless the event was a timer event. */
+ if (! (CONSP (c) && EQ (XCONS (c)->car, Qtimer_event)))
+ timer_stop_idle ();
+
start_polling ();
if (NILP (c))
if (!NILP (tem))
{
+ int was_locked = single_kboard;
+
last_input_char = c;
- Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char));
+ Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char), Qt);
+
+ /* Resume allowing input from any kboard, if that was true before. */
+ if (!was_locked)
+ any_kboard_state ();
+
goto retry;
}
input has been processed. If the only input available was
the sort that we have just disabled, then we need to call
redisplay. */
- if (!readable_events ())
+ if (!readable_events (1))
{
redisplay_preserve_echo_area ();
- get_input_pending (&input_pending);
+ get_input_pending (&input_pending, 1);
}
}
}
/* Return true iff there are any events in the queue that read-char
would return. If this returns false, a read-char would block. */
static int
-readable_events ()
+readable_events (do_timers_now)
+ int do_timers_now;
{
+ timer_check (do_timers_now);
if (kbd_fetch_ptr != kbd_store_ptr)
return 1;
#ifdef HAVE_MOUSE
{
register int c;
Lisp_Object obj;
+ EMACS_TIME next_timer_delay;
if (noninteractive)
{
and process it again. */
copy = *event;
kbd_fetch_ptr = event + 1;
- input_pending = readable_events ();
+ input_pending = readable_events (0);
x_handle_selection_request (©);
#else
/* We're getting selection request events, but we don't have
/* Remove it from the buffer before processing it. */
copy = *event;
kbd_fetch_ptr = event + 1;
- input_pending = readable_events ();
+ input_pending = readable_events (0);
x_handle_selection_clear (©);
#else
/* We're getting selection request events, but we don't have
else if (event->kind == menu_bar_activate_event)
{
kbd_fetch_ptr = event + 1;
- input_pending = readable_events ();
+ input_pending = readable_events (0);
x_activate_menubar (XFRAME (event->frame_or_window));
}
#endif
something for us to read! */
abort ();
- input_pending = readable_events ();
+ input_pending = readable_events (0);
#ifdef MULTI_FRAME
Vlast_event_frame = internal_last_event_frame;
then return, without reading any user-visible events. */
void
-swallow_events ()
+swallow_events (do_display)
+ int do_display;
{
+ int old_timers_run;
+
while (kbd_fetch_ptr != kbd_store_ptr)
{
struct input_event *event;
and process it again. */
copy = *event;
kbd_fetch_ptr = event + 1;
- input_pending = readable_events ();
+ input_pending = readable_events (0);
x_handle_selection_request (©);
#else
/* We're getting selection request events, but we don't have
copy = *event;
kbd_fetch_ptr = event + 1;
- input_pending = readable_events ();
+ input_pending = readable_events (0);
x_handle_selection_clear (©);
#else
/* We're getting selection request events, but we don't have
abort ();
#endif
}
+ else if (event->kind == timer_event)
+ {
+ Lisp_Object tem, lisp_event;
+ int was_locked = single_kboard;
+
+ tem = get_keymap_1 (Vspecial_event_map, 0, 0);
+ tem = get_keyelt (access_keymap (tem, Qtimer_event, 0, 0),
+ 1);
+ lisp_event = Fcons (Qtimer_event,
+ Fcons (Fcdr (event->frame_or_window), Qnil));
+ kbd_fetch_ptr = event + 1;
+ if (kbd_fetch_ptr == kbd_store_ptr)
+ input_pending = 0;
+ Fcommand_execute (tem, Qnil, Fvector (1, &lisp_event), Qt);
+ timers_run++;
+ if (do_display)
+ redisplay_preserve_echo_area ();
+
+ /* Resume allowing input from any kboard, if that was true before. */
+ if (!was_locked)
+ any_kboard_state ();
+ }
else
break;
}
- get_input_pending (&input_pending);
+ old_timers_run = timers_run;
+ get_input_pending (&input_pending, 1);
+
+ if (timers_run != old_timers_run && do_display)
+ redisplay_preserve_echo_area ();
+}
+\f
+static EMACS_TIME timer_idleness_start_time;
+
+/* Record the start of when Emacs is idle,
+ for the sake of running idle-time timers. */
+
+timer_start_idle ()
+{
+ Lisp_Object timers;
+
+ /* If we are already in the idle state, do nothing. */
+ if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+ return;
+
+ 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)
+ {
+ Lisp_Object timer;
+
+ timer = XCONS (timers)->car;
+
+ if (!VECTORP (timer) || XVECTOR (timer)->size != 8)
+ continue;
+ XVECTOR (timer)->contents[0] = Qnil;
+ }
+}
+
+/* Record that Emacs is no longer idle, so stop running idle-time timers. */
+
+timer_stop_idle ()
+{
+ EMACS_SET_SECS_USECS (timer_idleness_start_time, -1, -1);
+}
+
+/* This is only for debugging. */
+struct input_event last_timer_event;
+
+/* Check whether a timer has fired. To prevent larger problems we simply
+ disregard elements that are not proper timers. Do not make a circular
+ timer list for the time being.
+
+ Returns the number of seconds to wait until the next timer fires. If a
+ timer is triggering now, return zero seconds.
+ If no timer is active, return -1 seconds.
+
+ If a timer is ripe now, either queue a timer-event,
+ or call the timer's handler function here if DO_IT_NOW is nonzero. */
+
+EMACS_TIME
+timer_check (do_it_now)
+ int do_it_now;
+{
+ EMACS_TIME nexttime;
+ EMACS_TIME now, idleness_now;
+ Lisp_Object timers, idle_timers, chosen_timer;
+ /* Nonzero if we generate some events. */
+ int events_generated = 0;
+ struct gcpro gcpro1, gcpro2, gcpro3;
+
+ EMACS_SET_SECS (nexttime, -1);
+ EMACS_SET_USECS (nexttime, -1);
+
+ /* Always consider the ordinary timers. */
+ timers = Vtimer_list;
+ /* Consider the idle timers only if Emacs is idle. */
+ if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+ idle_timers = Vtimer_idle_list;
+ else
+ idle_timers = Qnil;
+ chosen_timer = Qnil;
+ GCPRO3 (timers, idle_timers, chosen_timer);
+
+ if (CONSP (timers) || CONSP (idle_timers))
+ {
+ EMACS_GET_TIME (now);
+ if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+ EMACS_SUB_TIME (idleness_now, now, timer_idleness_start_time);
+ }
+
+ 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;
+ EMACS_TIME difference, timer_difference, idle_timer_difference;
+
+ /* Skip past invalid timers and timers already handled. */
+ if (!NILP (timers))
+ {
+ timer = XCONS (timers)->car;
+ if (!VECTORP (timer) || XVECTOR (timer)->size != 8)
+ {
+ timers = XCONS (timers)->cdr;
+ continue;
+ }
+ vector = XVECTOR (timer)->contents;
+
+ if (!INTEGERP (vector[1]) || !INTEGERP (vector[2])
+ || !INTEGERP (vector[3])
+ || ! NILP (vector[0]))
+ {
+ timers = XCONS (timers)->cdr;
+ continue;
+ }
+ }
+ if (!NILP (idle_timers))
+ {
+ timer = XCONS (idle_timers)->car;
+ if (!VECTORP (timer) || XVECTOR (timer)->size != 8)
+ {
+ idle_timers = XCONS (idle_timers)->cdr;
+ continue;
+ }
+ vector = XVECTOR (timer)->contents;
+
+ if (!INTEGERP (vector[1]) || !INTEGERP (vector[2])
+ || !INTEGERP (vector[3])
+ || ! NILP (vector[0]))
+ {
+ idle_timers = XCONS (idle_timers)->cdr;
+ continue;
+ }
+ }
+
+ /* Set TIMER, TIMER_TIME and TIMER_DIFFERENCE
+ based on the next ordinary timer.
+ TIMER_DIFFERENCE is the distance in time from NOW to when
+ this timer becomes ripe (negative if it's already ripe). */
+ if (!NILP (timers))
+ {
+ timer = XCONS (timers)->car;
+ vector = XVECTOR (timer)->contents;
+ EMACS_SET_SECS (timer_time,
+ (XINT (vector[1]) << 16) | (XINT (vector[2])));
+ EMACS_SET_USECS (timer_time, XINT (vector[3]));
+ EMACS_SUB_TIME (timer_difference, timer_time, now);
+ }
+
+ /* Set IDLE_TIMER, IDLE_TIMER_TIME and IDLE_TIMER_DIFFERENCE
+ based on the next idle timer. */
+ if (!NILP (idle_timers))
+ {
+ idle_timer = XCONS (idle_timers)->car;
+ vector = XVECTOR (idle_timer)->contents;
+ EMACS_SET_SECS (idle_timer_time,
+ (XINT (vector[1]) << 16) | (XINT (vector[2])));
+ EMACS_SET_USECS (idle_timer_time, XINT (vector[3]));
+ EMACS_SUB_TIME (idle_timer_difference, idle_timer_time, idleness_now);
+ }
+
+ /* Decide which timer is the next timer,
+ and set CHOSEN_TIMER, VECTOR and DIFFERENCE accordingly.
+ Also step down the list where we found that timer. */
+
+ if (! NILP (timers) && ! NILP (idle_timers))
+ {
+ EMACS_TIME temp;
+ EMACS_SUB_TIME (temp, timer_difference, idle_timer_difference);
+ if (EMACS_TIME_NEG_P (temp))
+ {
+ chosen_timer = timer;
+ timers = XCONS (timers)->cdr;
+ difference = timer_difference;
+ }
+ else
+ {
+ chosen_timer = idle_timer;
+ idle_timers = XCONS (idle_timers)->cdr;
+ difference = idle_timer_difference;
+ }
+ }
+ else if (! NILP (timers))
+ {
+ chosen_timer = timer;
+ timers = XCONS (timers)->cdr;
+ difference = timer_difference;
+ }
+ else
+ {
+ chosen_timer = idle_timer;
+ idle_timers = XCONS (idle_timers)->cdr;
+ difference = idle_timer_difference;
+ }
+ vector = XVECTOR (chosen_timer)->contents;
+
+ /* If timer is rupe, run it if it hasn't been run. */
+ if (EMACS_TIME_NEG_P (difference)
+ || (EMACS_SECS (difference) == 0
+ && EMACS_USECS (difference) == 0))
+ {
+ if (NILP (vector[0]))
+ {
+ /* Mark the timer as triggered to prevent problems if the lisp
+ code fails to reschedule it right. */
+ vector[0] = Qt;
+
+ /* Run the timer or queue a timer event. */
+ if (do_it_now)
+ {
+ Lisp_Object tem, event;
+ int was_locked = single_kboard;
+
+ tem = get_keymap_1 (Vspecial_event_map, 0, 0);
+ tem = get_keyelt (access_keymap (tem, Qtimer_event, 0, 0),
+ 1);
+ event = Fcons (Qtimer_event, Fcons (chosen_timer, Qnil));
+ Fcommand_execute (tem, Qnil, Fvector (1, &event), Qt);
+ timers_run++;
+
+ /* Resume allowing input from any kboard, if that was true before. */
+ if (!was_locked)
+ any_kboard_state ();
+
+ /* Since we have handled the event,
+ we don't need to tell the caller to wake up and do it. */
+ }
+ else
+ {
+ /* Generate a timer event so the caller will handle it. */
+ struct input_event event;
+
+ event.kind = timer_event;
+ event.modifiers = 0;
+ event.x = event.y = Qnil;
+ event.timestamp = triggertime;
+ /* Store the timer in the frame slot. */
+ event.frame_or_window
+ = Fcons (Fselected_frame (), chosen_timer);
+ kbd_buffer_store_event (&event);
+
+ last_timer_event = event;
+
+ /* Tell caller to handle this event right away. */
+ events_generated = 1;
+ EMACS_SET_SECS (nexttime, 0);
+ EMACS_SET_USECS (nexttime, 0);
+
+ /* Don't queue more than one event at once.
+ When Emacs is ready for another, it will
+ queue the next one. */
+ UNGCPRO;
+ return nexttime;
+ }
+ }
+ }
+ else
+ /* When we encounter a timer that is still waiting,
+ return the amount of time to wait before it is ripe. */
+ {
+ UNGCPRO;
+ /* But if we generated an event,
+ tell the caller to handle it now. */
+ if (events_generated)
+ return nexttime;
+ return difference;
+ }
+ }
+
+ /* No timers are pending in the future. */
+ /* Return 0 if we generated an event, and -1 if not. */
+ UNGCPRO;
+ return nexttime;
}
\f
/* Caches for modify_event_symbol. */
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, /* VK_LWIN 0x5B */
- 0, /* VK_RWIN 0x5C */
- 0, /* VK_APPS 0x5D */
+ "lwindow", /* VK_LWIN 0x5B */
+ "rwindow", /* VK_RWIN 0x5C */
+ "apps", /* VK_APPS 0x5D */
0, 0, /* 0x5E .. 0x5F */
"kp-numlock", /* VK_NUMLOCK 0x90 */
"scroll", /* VK_SCROLL 0x91 */
- 0, 0, 0, 0, 0, /* 0x92 .. 0x96 */
- 0, 0, 0, 0, 0, /* 0x97 .. 0x9B */
- 0, 0, 0, 0, /* 0x9C .. 0x9F */
-
+ "kp-space", /* VK_NUMPAD_CLEAR 0x92 */
+ "kp-enter", /* VK_NUMPAD_ENTER 0x93 */
+ "kp-prior", /* VK_NUMPAD_PRIOR 0x94 */
+ "kp-next", /* VK_NUMPAD_NEXT 0x95 */
+ "kp-end", /* VK_NUMPAD_END 0x96 */
+ "kp-home", /* VK_NUMPAD_HOME 0x97 */
+ "kp-left", /* VK_NUMPAD_LEFT 0x98 */
+ "kp-up", /* VK_NUMPAD_UP 0x99 */
+ "kp-right", /* VK_NUMPAD_RIGHT 0x9A */
+ "kp-down", /* VK_NUMPAD_DOWN 0x9B */
+ "kp-insert", /* VK_NUMPAD_INSERT 0x9C */
+ "kp-delete", /* VK_NUMPAD_DELETE 0x9D */
+
+ 0, 0, /* 0x9E .. 0x9F */
+
/*
* VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys.
* Used only as parameters to GetAsyncKeyState() and GetKeyState().
/ sizeof (lispy_function_keys[0])));
break;
+ case timer_event:
+ return Fcons (Qtimer_event, Fcons (Fcdr (event->frame_or_window), Qnil));
+
#ifdef HAVE_MOUSE
/* A mouse click. Figure out where it is, decide whether it's
a press, click or drag, and build the appropriate structure. */
event type as a number or a symbol. */
DEFUN ("event-convert-list", Fevent_convert_list, Sevent_convert_list, 1, 1, 0,
- "Convert the event description LIST to an event type.\n\
-LIST should contain one base event type (a character or symbol)\n\
+ "Convert the event description list EVENT-DESC to an event type.\n\
+EVENT-DESC should contain one base event type (a character or symbol)\n\
and zero or more modifier names (control, meta, hyper, super, shift, alt,\n\
drag, down, double or triple).\n\
The return value is an event type (a character or symbol) which\n\
has the same base event type and all the specified modifiers.")
- (event)
- Lisp_Object event;
+ (event_desc)
+ Lisp_Object event_desc;
{
Lisp_Object base;
int modifiers = 0;
Lisp_Object rest;
base = Qnil;
- rest = event;
+ rest = event_desc;
while (CONSP (rest))
{
Lisp_Object elt;
/* Store into *addr a value nonzero if terminal input chars are available.
Serves the purpose of ioctl (0, FIONREAD, addr)
but works even if FIONREAD does not exist.
- (In fact, this may actually read some input.) */
+ (In fact, this may actually read some input.)
+
+ If DO_TIMERS_NOW is nonzero, actually run timer events that are ripe. */
static void
-get_input_pending (addr)
+get_input_pending (addr, do_timers_now)
int *addr;
+ int do_timers_now;
{
/* First of all, have we already counted some input? */
- *addr = !NILP (Vquit_flag) || readable_events ();
+ *addr = !NILP (Vquit_flag) || readable_events (do_timers_now);
/* If input is being read as it arrives, and we have none, there is none. */
if (*addr > 0 || (interrupt_input && ! interrupts_deferred))
/* Try to read some input and see how much we get. */
gobble_input (0);
- *addr = !NILP (Vquit_flag) || readable_events ();
+ *addr = !NILP (Vquit_flag) || readable_events (do_timers_now);
}
/* Interface to read_avail_input, blocking SIGIO or SIGALRM if necessary. */
reinvoke_input_signal ()
{
#ifdef SIGIO
- kill (0, SIGIO);
+ kill (getpid (), SIGIO);
#endif
}
return Qnil ;
}
+/* Buffer in use so far for the minibuf prompts for menu keymaps.
+ We make this bigger when necessary, and never free it. */
+static char *read_char_minibuf_menu_text;
+/* Size of that buffer. */
+static int read_char_minibuf_menu_width;
+
static Lisp_Object
read_char_minibuf_menu_prompt (commandflag, nmaps, maps)
int commandflag ;
register Lisp_Object name;
int nlength;
int width = FRAME_WIDTH (selected_frame) - 4;
- char *menu = (char *) alloca (width + 4);
int idx = -1;
int nobindings = 1;
Lisp_Object rest, vector;
+ char *menu;
if (! menu_prompting)
return Qnil;
+ /* Make sure we have a big enough buffer for the menu text. */
+ if (read_char_minibuf_menu_text == 0)
+ {
+ read_char_minibuf_menu_width = width + 4;
+ read_char_minibuf_menu_text = (char *) xmalloc (width + 4);
+ }
+ else if (width + 4 > read_char_minibuf_menu_width)
+ {
+ read_char_minibuf_menu_width = width + 4;
+ read_char_minibuf_menu_text
+ = (char *) xrealloc (read_char_minibuf_menu_text, width + 4);
+ }
+ menu = read_char_minibuf_menu_text;
+
/* Get the menu name from the first map that has one (a prompt string). */
for (mapno = 0; mapno < nmaps; mapno++)
{
return make_event_array (i, keybuf);
}
\f
-DEFUN ("command-execute", Fcommand_execute, Scommand_execute, 1, 3, 0,
+DEFUN ("command-execute", Fcommand_execute, Scommand_execute, 1, 4, 0,
"Execute CMD as an editor command.\n\
CMD must be a symbol that satisfies the `commandp' predicate.\n\
Optional second arg RECORD-FLAG non-nil\n\
means unconditionally put this command in `command-history'.\n\
Otherwise, that is done only if an arg is read using the minibuffer.\n\
The argument KEYS specifies the value to use instead of (this-command-keys)\n\
-when reading the arguments; if it is nil, (this_command_key_count) is used.")
- (cmd, record, keys)
- Lisp_Object cmd, record, keys;
+when reading the arguments; if it is nil, (this_command_key_count) is used.\n\
+The argument SPECIAL, if non-nil, means that this command is executing\n\
+a special event, so ignore the prefix argument and don't clear it.")
+ (cmd, record_flag, keys, special)
+ Lisp_Object cmd, record_flag, keys, special;
{
register Lisp_Object final;
register Lisp_Object tem;
struct backtrace backtrace;
extern int debug_on_next_call;
- prefixarg = current_kboard->Vprefix_arg;
- current_kboard->Vprefix_arg = Qnil;
- Vcurrent_prefix_arg = prefixarg;
debug_on_next_call = 0;
+ if (NILP (special))
+ {
+ prefixarg = current_kboard->Vprefix_arg;
+ Vcurrent_prefix_arg = prefixarg;
+ current_kboard->Vprefix_arg = Qnil;
+ }
+ else
+ prefixarg = Qnil;
+
if (SYMBOLP (cmd))
{
tem = Fget (cmd, Qdisabled);
/* If requested, place the macro in the command history. For
other sorts of commands, call-interactively takes care of
this. */
- if (!NILP (record))
+ if (!NILP (record_flag))
Vcommand_history
= Fcons (Fcons (Qexecute_kbd_macro,
Fcons (final, Fcons (prefixarg, Qnil))),
backtrace.nargs = 1;
backtrace.evalargs = 0;
- tem = Fcall_interactively (cmd, record, keys);
+ tem = Fcall_interactively (cmd, record_flag, keys);
backtrace_list = backtrace.next;
return tem;
}
}
- return Fcommand_execute (function, Qt, Qnil);
+ return Fcommand_execute (function, Qt, Qnil, Qnil);
}
/* Find the set of keymaps now active.
return nmaps;
}
\f
+/* Return nonzero if input events are pending. */
detect_input_pending ()
{
if (!input_pending)
- get_input_pending (&input_pending);
+ get_input_pending (&input_pending, 0);
+
+ return input_pending;
+}
+
+/* Return nonzero if input events are pending.
+ Execute timers immediately; don't make events for them. */
+
+detect_input_pending_run_timers (do_display)
+ int do_display;
+{
+ int old_timers_run = timers_run;
+
+ if (!input_pending)
+ get_input_pending (&input_pending, 1);
+
+ if (old_timers_run != timers_run && do_display)
+ redisplay_preserve_echo_area ();
return input_pending;
}
if (!NILP (Vunread_command_events) || unread_command_char != -1)
return (Qt);
- return detect_input_pending () ? Qt : Qnil;
+ get_input_pending (&input_pending, 1);
+ return input_pending > 0 ? Qt : Qnil;
}
DEFUN ("recent-keys", Frecent_keys, Srecent_keys, 0, 0, 0,
(file)
Lisp_Object file;
{
- if (NILP (file))
+ if (dribble)
{
- if (dribble)
- {
- fclose (dribble);
- dribble = 0;
- }
+ fclose (dribble);
+ dribble = 0;
}
- else
+ if (!NILP (file))
{
file = Fexpand_file_name (file, Qnil);
dribble = fopen (XSTRING (file)->data, "w");
+ if (dribble == 0)
+ report_file_error ("Opening dribble", Fcons (file, Qnil));
}
return Qnil;
}
/*
* Destroy the contents of a kboard object, but not the object itself.
- * We use this just before deleteing it, or if we're going to initialize
+ * We use this just before deleting it, or if we're going to initialize
* it a second time.
*/
static void
quit_char = Ctl ('g');
Vunread_command_events = Qnil;
unread_command_char = -1;
+ EMACS_SET_SECS_USECS (timer_idleness_start_time, -1, -1);
total_keys = 0;
recent_keys_index = 0;
kbd_fetch_ptr = kbd_buffer;
staticpro (&Qfunction_key);
Qmouse_click = intern ("mouse-click");
staticpro (&Qmouse_click);
+ Qtimer_event = intern ("timer-event");
+ staticpro (&Qtimer_event);
Qmenu_enable = intern ("menu-enable");
staticpro (&Qmenu_enable);
Vpost_command_idle_hook = Qnil;
DEFVAR_INT ("post-command-idle-delay", &post_command_idle_delay,
- "Delay time before running `post-command-idle-delay'.\n\
+ "Delay time before running `post-command-idle-hook'.\n\
This is measured in microseconds.");
post_command_idle_delay = 100000;
DEFVAR_LISP ("column-number-mode", &Vcolumn_number_mode,
"Non-nil enables display of the current column number in the mode line.");
Vcolumn_number_mode = Qnil;
+
+ DEFVAR_LISP ("timer-list", &Vtimer_list,
+ "List of active absolute time timers in order of increasing time");
+ Vtimer_list = Qnil;
+
+ DEFVAR_LISP ("timer-idle-list", &Vtimer_idle_list,
+ "List of active idle-time timers in order of increasing time");
+ Vtimer_idle_list = Qnil;
}
keys_of_keyboard ()