Commit 58555d81 authored by Stefan Monnier's avatar Stefan Monnier

* keyboard.c (pending_funcalls): New var.

(timer_check): Run it.
(syms_of_keyboard): Initialize it.
* terminal.c (Qrun_hook_with_args, Qdelete_terminal_functions)
(Vdelete_terminal_functions): New vars.
(syms_of_terminal): Initialize them.
(Fdelete_terminal): Run delete-terminal-functions.
* xdisp.c (safe_eval): Rewrite.
(safe_call2): New fun.
* frame.c (Qdelete_frame_functions): New var.
(syms_of_frame): Initialize it.
(Fdelete_frame): Use it and use safe_call2 and pending_funcalls.
* lisp.h (safe_call2, pending_funcalls): Declare.
parent 769087ce
......@@ -614,6 +614,7 @@ for the list of extra keys that are available.
* Incompatible Lisp Changes in Emacs 23.1
+++
** The multibyteness of process filters is determined by the coding-system
used for decoding. The functions `process-filter-multibyte-p' and
`set-process-filter-multibyte' are obsolete.
......@@ -664,6 +665,8 @@ functions and variables (formerly used for Tamil script).
* Lisp Changes in Emacs 23.1
** When deleting a terminal, run the special hook `delete-terminal-functions'.
** The `read-shell-command' function does what its name says, with completion.
It uses the minibuffer-local-shell-command-map for that.
......
2008-03-29 Stefan Monnier <monnier@iro.umontreal.ca>
* keyboard.c (pending_funcalls): New var.
(timer_check): Run it.
(syms_of_keyboard): Initialize it.
* terminal.c (Qrun_hook_with_args, Qdelete_terminal_functions)
(Vdelete_terminal_functions): New vars.
(syms_of_terminal): Initialize them.
(Fdelete_terminal): Run delete-terminal-functions.
* xdisp.c (safe_eval): Rewrite.
(safe_call2): New fun.
* frame.c (Qdelete_frame_functions): New var.
(syms_of_frame): Initialize it.
(Fdelete_frame): Use it and use safe_call2 and pending_funcalls.
* lisp.h (safe_call2, pending_funcalls): Declare.
2008-03-28 Andreas Schwab <schwab@suse.de>
* indent.c (Fmove_to_column): Move declaration before statements.
......
......@@ -129,7 +129,7 @@ Lisp_Object Vdefault_frame_alist;
Lisp_Object Vdefault_frame_scroll_bars;
Lisp_Object Vmouse_position_function;
Lisp_Object Vmouse_highlight;
Lisp_Object Vdelete_frame_functions;
static Lisp_Object Vdelete_frame_functions, Qdelete_frame_functions;
int focus_follows_mouse;
......@@ -1334,6 +1334,8 @@ delete_frame_handler (Lisp_Object arg)
return Qnil;
}
extern Lisp_Object Qrun_hook_with_args;
DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
doc: /* Delete FRAME, permanently eliminating it from use.
If omitted, FRAME defaults to the selected frame.
......@@ -1410,21 +1412,14 @@ But FORCE inhibits this too. */)
unless FORCE is `noelisp' or frame is a tooltip.
FORCE is set to `noelisp' when handling a disconnect from the terminal,
so we don't dare call Lisp code. */
if (!NILP (Vrun_hooks) && !EQ (force, Qnoelisp)
&& NILP (Fframe_parameter (frame, intern ("tooltip"))))
{
Lisp_Object args[2];
struct gcpro gcpro1, gcpro2;
/* Don't let a rogue function in `delete-frame-functions'
prevent the frame deletion. */
GCPRO2 (args[0], args[1]);
args[0] = intern ("delete-frame-functions");
args[1] = frame;
internal_condition_case_2 (Frun_hook_with_args, 2, args,
Qt, delete_frame_handler);
UNGCPRO;
}
if (NILP (Vrun_hooks) || !NILP (Fframe_parameter (frame, intern ("tooltip"))))
;
if (EQ (force, Qnoelisp))
pending_funcalls
= Fcons (list3 (Qrun_hook_with_args, Qdelete_frame_functions, frame),
pending_funcalls);
else
safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
/* The hook may sometimes (indirectly) cause the frame to be deleted. */
if (! FRAME_LIVE_P (f))
......@@ -4526,13 +4521,13 @@ when the mouse is over clickable text. */);
The functions are run with one arg, the frame to be deleted.
See `delete-frame'.
Note that functions in this list may be called twice on the same
frame. In the second invocation, the frame is already deleted, and
the function should do nothing. (You can use `frame-live-p' to check
for this.) This wrinkle happens when an earlier function in
`delete-frame-functions' (indirectly) calls `delete-frame'
recursively. */);
Note that functions in this list may be called just before the frame is
actually deleted, or some time later (or even both when an earlier function
in `delete-frame-functions' (indirectly) calls `delete-frame'
recursively). */);
Vdelete_frame_functions = Qnil;
Qdelete_frame_functions = intern ("delete-frame-functions");
staticpro (&Qdelete_frame_functions);
DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
doc: /* Minibufferless frames use this frame's minibuffer.
......
......@@ -4505,6 +4505,13 @@ timer_resume_idle ()
/* This is only for debugging. */
struct input_event last_timer_event;
/* List of elisp functions to call, delayed because they were generated in
a context where Elisp could not be safely run (e.g. redisplay, signal,
...). Each lement has the form (FUN . ARGS). */
Lisp_Object pending_funcalls;
extern Lisp_Object Qapply;
/* 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.
......@@ -4541,6 +4548,14 @@ timer_check (do_it_now)
chosen_timer = Qnil;
GCPRO3 (timers, idle_timers, chosen_timer);
/* First run the code that was delayed. */
while (CONSP (pending_funcalls))
{
Lisp_Object funcall = XCAR (pending_funcalls);
pending_funcalls = XCDR (pending_funcalls);
safe_call2 (Qapply, XCAR (funcall), XCDR (funcall));
}
if (CONSP (timers) || CONSP (idle_timers))
{
EMACS_GET_TIME (now);
......@@ -11726,6 +11741,8 @@ struct event_head head_table[] = {
void
syms_of_keyboard ()
{
pending_funcalls = Qnil;
Vpre_help_message = Qnil;
staticpro (&Vpre_help_message);
......
......@@ -2776,6 +2776,7 @@ EXFUN (Ffetch_bytecode, 1);
extern void init_eval_once P_ ((void));
extern Lisp_Object safe_call P_ ((int, Lisp_Object *));
extern Lisp_Object safe_call1 P_ ((Lisp_Object, Lisp_Object));
extern Lisp_Object safe_call2 (Lisp_Object, Lisp_Object, Lisp_Object);
extern void init_eval P_ ((void));
extern void syms_of_eval P_ ((void));
......@@ -3025,6 +3026,7 @@ EXFUN (Fset_output_flow_control, 2);
EXFUN (Fset_input_meta_mode, 2);
EXFUN (Fset_quit_char, 1);
EXFUN (Fset_input_mode, 4);
extern Lisp_Object pending_funcalls;
extern int detect_input_pending P_ ((void));
extern int detect_input_pending_ignore_squeezables P_ ((void));
extern int detect_input_pending_run_timers P_ ((int));
......
......@@ -295,6 +295,10 @@ delete_terminal (struct terminal *terminal)
#endif
}
Lisp_Object Qrun_hook_with_args;
static Lisp_Object Qdelete_terminal_functions;
static Lisp_Object Vdelete_terminal_functions;
DEFUN ("delete-terminal", Fdelete_terminal, Sdelete_terminal, 0, 2, 0,
doc: /* Delete TERMINAL by deleting all frames on it and closing the terminal.
TERMINAL may be a terminal id, a frame, or nil (meaning the selected
......@@ -320,6 +324,16 @@ but if the second argument FORCE is non-nil, you may do so. */)
error ("Attempt to delete the sole active display terminal");
}
if (NILP (Vrun_hooks))
;
else if (EQ (force, Qnoelisp))
pending_funcalls
= Fcons (list3 (Qrun_hook_with_args,
Qdelete_terminal_functions, terminal),
pending_funcalls);
else
safe_call2 (Qrun_hook_with_args, Qdelete_terminal_functions, terminal);
if (t->delete_terminal_hook)
(*t->delete_terminal_hook) (t);
else
......@@ -552,6 +566,17 @@ syms_of_terminal ()
The function should accept no arguments. */);
Vring_bell_function = Qnil;
DEFVAR_LISP ("delete-terminal-functions", &Vdelete_terminal_functions,
doc: /* Special hook run when a terminal is deleted.
Each function is called with argument, the terminal.
This may be called just before actually deleting the terminal,
or some time later. */);
Vdelete_terminal_functions = Qnil;
Qdelete_terminal_functions = intern ("delete-terminal-functions");
staticpro (&Qdelete_terminal_functions);
Qrun_hook_with_args = intern ("run-hook-with-args");
staticpro (&Qrun_hook_with_args);
defsubr (&Sdelete_terminal);
defsubr (&Sframe_terminal);
defsubr (&Sterminal_live_p);
......
......@@ -2316,33 +2316,6 @@ safe_eval_handler (arg)
/* Evaluate SEXPR and return the result, or nil if something went
wrong. Prevent redisplay during the evaluation. */
Lisp_Object
safe_eval (sexpr)
Lisp_Object sexpr;
{
Lisp_Object val;
if (inhibit_eval_during_redisplay)
val = Qnil;
else
{
int count = SPECPDL_INDEX ();
struct gcpro gcpro1;
GCPRO1 (sexpr);
specbind (Qinhibit_redisplay, Qt);
/* Use Qt to ensure debugger does not run,
so there is no possibility of wanting to redisplay. */
val = internal_condition_case_1 (Feval, sexpr, Qt,
safe_eval_handler);
UNGCPRO;
val = unbind_to (count, val);
}
return val;
}
/* Call function ARGS[0] with arguments ARGS[1] to ARGS[NARGS - 1].
Return the result, or nil if something went wrong. Prevent
redisplay during the evaluation. */
......@@ -2389,6 +2362,27 @@ safe_call1 (fn, arg)
return safe_call (2, args);
}
static Lisp_Object Qeval;
Lisp_Object
safe_eval (Lisp_Object sexpr)
{
return safe_call1 (Qeval, sexpr);
}
/* Call function FN with one argument ARG.
Return the result, or nil if something went wrong. */
Lisp_Object
safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
{
Lisp_Object args[3];
args[0] = fn;
args[1] = arg1;
args[2] = arg2;
return safe_call (3, args);
}
/***********************************************************************
......@@ -8634,7 +8628,7 @@ current_message ()
{
Lisp_Object msg;
if (NILP (echo_area_buffer[0]))
if (!BUFFERP (echo_area_buffer[0]))
msg = Qnil;
else
{
......@@ -24359,6 +24353,9 @@ syms_of_xdisp ()
staticpro (&Qinhibit_point_motion_hooks);
Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
Qeval = intern ("eval");
staticpro (&Qeval);
QCdata = intern (":data");
staticpro (&QCdata);
Qdisplay = intern ("display");
......
......@@ -8144,7 +8144,11 @@ x_connection_closed (dpy, error_message)
/* We have just closed all frames on this display. */
abort ();
x_delete_display (dpyinfo);
{
Lisp_Object tmp;
XSETTERMINAL (tmp, dpyinfo->terminal);
Fdelete_terminal (tmp, Qnoelisp);
}
}
x_uncatch_errors ();
......@@ -8165,10 +8169,9 @@ x_connection_closed (dpy, error_message)
unbind_to (index, Qnil);
clear_waiting_for_input ();
/* FIXME: This is an asynchronous interrupt w.r.t elisp, so signalling an
error might not be the best thing to do. I'd vote for creating an
elisp event and stuffing it in the queue so people can bind to it via
the global map. --Stef */
/* Here, we absolutely have to use a non-local exit (e.g. signal, throw,
longjmp), because returning from this function would get us back into
Xlib's code which will directly call `exit'. */
error ("%s", error_msg);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment