#include "systime.h"
#include "atimer.h"
#include "process.h"
+#include "guile.h"
#include <errno.h>
#ifdef HAVE_PTHREAD
/* For longjmp to where kbd input is being done. */
-static sys_jmp_buf getcjmp;
+static Lisp_Object getctag;
/* True while doing kbd input. */
bool waiting_for_input;
static Lisp_Object make_lispy_focus_out (Lisp_Object);
#endif /* HAVE_WINDOW_SYSTEM */
static bool help_char_p (Lisp_Object);
-static void save_getcjmp (sys_jmp_buf *);
-static void restore_getcjmp (sys_jmp_buf *);
static Lisp_Object apply_modifiers (int, Lisp_Object);
static void clear_event (struct input_event *);
static void restore_kboard_configuration (int);
Lisp_Object
recursive_edit_1 (void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object val;
if (command_loop_level > 0)
if (STRINGP (val))
xsignal1 (Qerror, val);
- return unbind_to (count, Qnil);
+ dynwind_end ();
+ return Qnil;
}
/* When an auto-save happens, record the "time", and don't do again soon. */
This function is called by the editor initialization to begin editing. */)
(void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object buffer;
/* If we enter while input is blocked, don't lock up here.
This may happen through the debugger during redisplay. */
- if (input_blocked_p ())
+ if (input_blocked_p ()) {
+ dynwind_end ();
return Qnil;
+ }
if (command_loop_level >= 0
&& current_buffer != XBUFFER (XWINDOW (selected_window)->contents))
temporarily_switch_to_single_kboard (SELECTED_FRAME ());
recursive_edit_1 ();
- return unbind_to (count, Qnil);
+ dynwind_end ();
+ return Qnil;
}
void
value to us. A value of nil means that command_loop_1 itself
returned due to end of file (or end of kbd macro). */
+static Lisp_Object
+command_loop_2_body (void *ignore)
+{
+ return command_loop_1 ();
+}
+
+static Lisp_Object
+command_loop_2_handler (void *ignore, SCM key, SCM args)
+{
+ return Fsignal (Qerror,
+ list3 (build_string ("Scheme error"), key, args));
+}
+
+static Lisp_Object
+command_loop_2_inner (void)
+{
+ return scm_c_with_throw_handler (SCM_BOOL_T,
+ command_loop_2_body, NULL,
+ command_loop_2_handler, NULL,
+ 0);
+}
+
static Lisp_Object
command_loop_2 (Lisp_Object ignore)
{
register Lisp_Object val;
do
- val = internal_condition_case (command_loop_1, Qerror, cmd_error);
+ val = internal_condition_case (command_loop_2_inner, Qerror, cmd_error);
while (!NILP (val));
return Qnil;
}
static Lisp_Object
-top_level_2 (void)
+top_level_2_body (void *ignore)
{
return Feval (Vtop_level, Qnil);
}
+static Lisp_Object
+top_level_2 (void)
+{
+ return scm_c_with_throw_handler (SCM_BOOL_T,
+ top_level_2_body, NULL,
+ command_loop_2_handler, NULL,
+ 0);
+}
+
static Lisp_Object
top_level_1 (Lisp_Object ignore)
{
}
}
-DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0,
+DEFUN ("call-with-track-mouse", Ftrack_mouse, Strack_mouse, 1, 1, 0,
doc: /* Evaluate BODY with mouse movement events enabled.
Within a `track-mouse' form, mouse motion generates input events that
you can read with `read-event'.
Normally, mouse motion is ignored.
usage: (track-mouse BODY...) */)
- (Lisp_Object args)
+ (Lisp_Object thunk)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object val;
record_unwind_protect (tracking_off, do_mouse_tracking);
do_mouse_tracking = Qt;
- val = Fprogn (args);
- return unbind_to (count, val);
+ val = call0 (thunk);
+ dynwind_end ();
+ return val;
}
/* If mouse has moved on some frame, return one of those frames.
read_menu_command (void)
{
Lisp_Object keybuf[30];
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
int i;
/* We don't want to echo the keystrokes while navigating the
i = read_key_sequence (keybuf, ARRAYELTS (keybuf),
Qnil, 0, 1, 1, 1);
- unbind_to (count, Qnil);
+ dynwind_end ();
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
Fkill_emacs (Qnil);
/* FIXME: our `internal_condition_case' does not provide any way to pass data
to its body or to its handlers other than via globals such as
dynamically-bound variables ;-) */
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
specbind (Qinhibit_quit, hook);
run_hook_with_args (1, &hook, safe_run_hook_funcall);
- unbind_to (count, Qnil);
+ dynwind_end ();
}
\f
-/* Nonzero means polling for input is temporarily suppressed. */
-
-int poll_suppress_count;
-
-
#ifdef POLL_FOR_INPUT
/* Asynchronous timer for polling. */
static void
poll_for_input (struct atimer *timer)
{
- if (poll_suppress_count == 0)
- pending_signals = 1;
}
#endif /* POLL_FOR_INPUT */
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
}
#endif
}
-/* Turn off polling. */
-
-void
-stop_polling (void)
-{
-#ifdef POLL_FOR_INPUT
- /* XXX This condition was (read_socket_hook && !interrupt_input),
- but read_socket_hook is not global anymore. Let's pretend that
- it's always set. */
- if (!interrupt_input)
- ++poll_suppress_count;
-#endif
-}
-
-/* Set the value of poll_suppress_count to COUNT
- and start or stop polling accordingly. */
-
-void
-set_poll_suppress_count (int count)
-{
-#ifdef POLL_FOR_INPUT
- if (count == 0 && poll_suppress_count != 0)
- {
- poll_suppress_count = 1;
- start_polling ();
- }
- else if (count != 0 && poll_suppress_count == 0)
- {
- stop_polling ();
- }
- poll_suppress_count = count;
-#endif
-}
-
/* Bind polling_period to a value at least N.
But don't decrease it. */
bind_polling_period (int n)
{
#ifdef POLL_FOR_INPUT
- EMACS_INT new = polling_period;
+ EMACS_INT new = max (polling_period, new);
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. */
start_polling ();
Fset_window_configuration (window_config);
}
-#define STOP_POLLING \
-do { if (! polling_stopped_here) stop_polling (); \
- polling_stopped_here = 1; } while (0)
-
-#define RESUME_POLLING \
-do { if (polling_stopped_here) start_polling (); \
- polling_stopped_here = 0; } while (0)
-
static Lisp_Object
read_event_from_main_queue (struct timespec *end_time,
- sys_jmp_buf *local_getcjmp,
+ Lisp_Object local_tag,
bool *used_mouse_menu)
{
Lisp_Object c = Qnil;
+ Lisp_Object save_tag = Qnil;
sys_jmp_buf *save_jump = xmalloc (sizeof *save_jump);
KBOARD *kb IF_LINT (= NULL);
return c;
/* Actually read a character, waiting if necessary. */
- save_getcjmp (save_jump);
- restore_getcjmp (local_getcjmp);
+ save_tag = getctag;
+ getctag = local_tag;
if (!end_time)
timer_start_idle ();
c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time);
- restore_getcjmp (save_jump);
+ getctag = save_tag;
if (! NILP (c) && (kb != current_kboard))
{
to tty input. */
static Lisp_Object
read_decoded_event_from_main_queue (struct timespec *end_time,
- sys_jmp_buf *local_getcjmp,
+ Lisp_Object local_getcjmp,
Lisp_Object prev_event,
bool *used_mouse_menu)
{
bool *used_mouse_menu;
struct timespec *end_time;
Lisp_Object c;
- ptrdiff_t jmpcount;
- sys_jmp_buf *local_getcjmp;
- sys_jmp_buf *save_jump;
+ Lisp_Object tag;
+ Lisp_Object local_tag;
+ Lisp_Object save_tag;
Lisp_Object previous_echo_area_message;
Lisp_Object also_record;
bool reread;
static Lisp_Object read_char_1 (bool, volatile struct read_char_state *);
+static Lisp_Object
+read_char_thunk (void *data)
+{
+ return read_char_1 (false, data);
+}
+
+static Lisp_Object
+read_char_handle_quit (void *data, Lisp_Object k)
+{
+ struct read_char_state *state = data;
+ /* Handle quits while reading the keyboard. */
+ /* We must have saved the outer value of getcjmp here,
+ so restore it now. */
+ getctag = state->save_tag;
+ XSETINT (state->c, quit_char);
+ 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. */
+ if (!NILP (Vinhibit_quit))
+ Vquit_flag = Qnil;
+
+ {
+ KBOARD *kb = FRAME_KBOARD (XFRAME (selected_frame));
+ if (kb != current_kboard)
+ {
+ Lisp_Object last = KVAR (kb, kbd_queue);
+ /* We shouldn't get here if we were in single-kboard mode! */
+ if (single_kboard)
+ emacs_abort ();
+ if (CONSP (last))
+ {
+ while (CONSP (XCDR (last)))
+ last = XCDR (last);
+ if (!NILP (XCDR (last)))
+ emacs_abort ();
+ }
+ if (!CONSP (last))
+ kset_kbd_queue (kb, list1 (state->c));
+ else
+ XSETCDR (last, list1 (state->c));
+ kb->kbd_queue_has_data = 1;
+ current_kboard = kb;
+ /* This is going to exit from read_char
+ so we had better get rid of this frame's stuff. */
+ UNGCPRO;
+ return make_number (-2); /* wrong_kboard_jmpbuf */
+ }
+ }
+ return read_char_1 (true, state);
+}
+
/* {{coccinelle:skip_start}} */
Lisp_Object
read_char (int commandflag, Lisp_Object map,
Lisp_Object prev_event,
bool *used_mouse_menu, struct timespec *end_time)
{
- volatile struct read_char_state *state = xmalloc (sizeof *state);
+ struct read_char_state *state = xmalloc (sizeof *state);
state->commandflag = commandflag;
state->map = map;
state->used_mouse_menu = used_mouse_menu;
state->end_time = end_time;
state->c = Qnil;
- state->local_getcjmp = xmalloc (sizeof (*state->local_getcjmp));
- state->save_jump = xmalloc (sizeof (*state->save_jump));
+ state->local_tag = Qnil;
+ state->save_tag = Qnil;
state->previous_echo_area_message = Qnil;
state->also_record = Qnil;
state->reread = false;
around any call to sit_for or kbd_buffer_get_event;
it *must not* be in effect when we call redisplay. */
- state->jmpcount = SPECPDL_INDEX ();
- if (sys_setjmp (*state->local_getcjmp))
- {
- /* Handle quits while reading the keyboard. */
- /* We must have saved the outer value of getcjmp here,
- so restore it now. */
- restore_getcjmp (state->save_jump);
- pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
- unbind_to (state->jmpcount, Qnil);
- XSETINT (state->c, quit_char);
- 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. */
- if (!NILP (Vinhibit_quit))
- Vquit_flag = Qnil;
-
- {
- KBOARD *kb = FRAME_KBOARD (XFRAME (selected_frame));
- if (kb != current_kboard)
- {
- Lisp_Object last = KVAR (kb, kbd_queue);
- /* We shouldn't get here if we were in single-kboard mode! */
- if (single_kboard)
- emacs_abort ();
- if (CONSP (last))
- {
- while (CONSP (XCDR (last)))
- last = XCDR (last);
- if (!NILP (XCDR (last)))
- emacs_abort ();
- }
- if (!CONSP (last))
- kset_kbd_queue (kb, list1 (state->c));
- else
- XSETCDR (last, list1 (state->c));
- kb->kbd_queue_has_data = 1;
- current_kboard = kb;
- /* This is going to exit from read_char
- so we had better get rid of this frame's stuff. */
- UNGCPRO;
- return make_number (-2); /* wrong_kboard_jmpbuf */
- }
- }
- return read_char_1 (true, state);
- }
+ state->tag = state->local_tag = make_prompt_tag ();
- return read_char_1 (false, state);
+ return call_with_prompt (state->tag,
+ make_c_closure (read_char_thunk, state, 0, 0),
+ make_c_closure (read_char_handle_quit, state, 1, 0));
}
static Lisp_Object
#define end_time state->end_time
#define c state->c
#define jmpcount state->jmpcount
-#define local_getcjmp state->local_getcjmp
-#define save_jump state->save_jump
+#define local_getcjmp state->local_tag
+#define save_jump state->save_tag
#define previous_echo_area_message state->previous_echo_area_message
#define also_record state->also_record
#define reread state->reread
#define polling_stopped_here state->polling_stopped_here
#define orig_kboard state->orig_kboard
+#define save_getcjmp(x) (x = getctag)
+#define restore_getcjmp(x) (getctag = x)
Lisp_Object tem, save;
if (jump)
wrong_kboard:
- STOP_POLLING;
-
if (NILP (c))
{
c = read_decoded_event_from_main_queue (end_time, local_getcjmp,
if (!end_time)
timer_stop_idle ();
- RESUME_POLLING;
if (NILP (c))
{
}
exit:
- RESUME_POLLING;
RETURN_UNGCPRO (c);
#undef commandflag
#undef map
#undef reread
#undef polling_stopped_here
#undef orig_kboard
+#undef save_getcjmp
+#undef restore_getcjmp
}
/* {{coccinelle:skip_end}} */
unblock_input ();
}
}
-
-/* Copy out or in the info on where C-g should throw to.
- This is used when running Lisp code from within get_char,
- in case get_char is called recursively.
- See read_process_output. */
-
-static void
-save_getcjmp (sys_jmp_buf *temp)
-{
- memcpy (*temp, getcjmp, sizeof getcjmp);
-}
-
-static void
-restore_getcjmp (sys_jmp_buf *temp)
-{
- memcpy (getcjmp, *temp, sizeof getcjmp);
-}
\f
/* Low level keyboard/mouse input.
kbd_buffer_store_event places events in kbd_buffer, and
hold_keyboard_input ();
if (!noninteractive)
ignore_sigio ();
- stop_polling ();
}
#endif /* subprocesses */
}
/* Start reading input again because we have processed enough to
be able to accept new events again. */
unhold_keyboard_input ();
- start_polling ();
}
#endif /* subprocesses */
{
if (NILP (AREF (chosen_timer, 0)))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object old_deactivate_mark = Vdeactivate_mark;
/* Mark the timer as triggered to prevent problems if the lisp
call1 (Qtimer_event_handler, chosen_timer);
Vdeactivate_mark = old_deactivate_mark;
timers_run++;
- unbind_to (count, Qnil);
+ dynwind_end ();
/* Since we have handled the event,
we don't need to tell the caller to wake up and do it. */
event.arg = Qnil;
/* Make sure no interrupt happens while storing the event. */
-#ifdef USABLE_SIGIO
- if (interrupt_input)
- kbd_buffer_store_event (&event);
- else
-#endif
- {
- stop_polling ();
- kbd_buffer_store_event (&event);
- start_polling ();
- }
+ kbd_buffer_store_event (&event);
}
}
Lisp_Object
menu_item_eval_property (Lisp_Object sexpr)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object val;
specbind (Qinhibit_redisplay, Qt);
val = internal_condition_case_1 (eval_dyn, sexpr, Qerror,
menu_item_eval_property_1);
- return unbind_to (count, val);
+ dynwind_end ();
+ return val;
}
/* This function parses a menu item and leaves the result in the
(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, SYMBOL_FUNCTION (def)))))
keys = Qnil;
}
/* Handle a symbol whose function definition is a keymap
or an array. */
if (SYMBOLP (next) && !NILP (Ffboundp (next))
- && (ARRAYP (XSYMBOL (next)->function)
- || KEYMAPP (XSYMBOL (next)->function)))
- next = Fautoload_do_load (XSYMBOL (next)->function, next, Qnil);
+ && (ARRAYP (SYMBOL_FUNCTION (next))
+ || KEYMAPP (SYMBOL_FUNCTION (next))))
+ next = Fautoload_do_load (SYMBOL_FUNCTION (next),
+ next, Qnil);
/* If the keymap gives a function, not an
array, then call the function with one arg and use
Lisp_Object keybuf[30];
register int i;
struct gcpro gcpro1;
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
if (!NILP (prompt))
CHECK_STRING (prompt);
QUIT;
}
UNGCPRO;
- return unbind_to (count,
- ((allow_string ? make_event_array : Fvector)
- (i, keybuf)));
+ Lisp_Object tem0 = ((allow_string ? make_event_array : Fvector) (i, keybuf));
+ dynwind_end ();
+ return tem0;
}
DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 5, 0,
On such systems, Emacs starts a subshell instead of suspending. */)
(Lisp_Object stuffstring)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
int old_height, old_width;
int width, height;
struct gcpro gcpro1;
sys_subshell ();
else
sys_suspend ();
- unbind_to (count, Qnil);
+ dynwind_end ();
/* Check if terminal/window size has changed.
Note that this is not useful when we are running directly
do_switch_frame (make_lispy_switch_frame (internal_last_event_frame),
0, 0, Qnil);
- sys_longjmp (getcjmp, 1);
+ abort_to_prompt (getctag, SCM_EOL);
}
\f
DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,
if (new_interrupt_input != interrupt_input)
{
-#ifdef POLL_FOR_INPUT
- stop_polling ();
-#endif
#ifndef DOS_NT
/* this causes startup screen to be restored and messes with the mouse */
reset_all_sys_modes ();
#endif
#ifdef POLL_FOR_INPUT
- poll_suppress_count = 1;
start_polling ();
#endif
}
#ifdef POLL_FOR_INPUT
poll_timer = NULL;
- poll_suppress_count = 1;
start_polling ();
#endif
}