Mercurial > emacs
changeset 93369:ed10c3092847
* 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.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Sat, 29 Mar 2008 01:46:10 +0000 |
parents | 411d7b7dfe32 |
children | eaf6138f43e7 |
files | etc/NEWS src/ChangeLog src/frame.c src/keyboard.c src/lisp.h src/terminal.c src/xdisp.c src/xterm.c |
diffstat | 8 files changed, 113 insertions(+), 55 deletions(-) [+] |
line wrap: on
line diff
--- a/etc/NEWS Sat Mar 29 01:09:45 2008 +0000 +++ b/etc/NEWS Sat Mar 29 01:46:10 2008 +0000 @@ -614,6 +614,7 @@ * 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 @@ * 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.
--- a/src/ChangeLog Sat Mar 29 01:09:45 2008 +0000 +++ b/src/ChangeLog Sat Mar 29 01:46:10 2008 +0000 @@ -1,3 +1,19 @@ +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.
--- a/src/frame.c Sat Mar 29 01:09:45 2008 +0000 +++ b/src/frame.c Sat Mar 29 01:46:10 2008 +0000 @@ -129,7 +129,7 @@ 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 @@ 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 @@ 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 @@ 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.
--- a/src/keyboard.c Sat Mar 29 01:09:45 2008 +0000 +++ b/src/keyboard.c Sat Mar 29 01:46:10 2008 +0000 @@ -4505,6 +4505,13 @@ /* 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 @@ 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 @@ void syms_of_keyboard () { + pending_funcalls = Qnil; + Vpre_help_message = Qnil; staticpro (&Vpre_help_message);
--- a/src/lisp.h Sat Mar 29 01:09:45 2008 +0000 +++ b/src/lisp.h Sat Mar 29 01:46:10 2008 +0000 @@ -2776,6 +2776,7 @@ 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_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));
--- a/src/terminal.c Sat Mar 29 01:09:45 2008 +0000 +++ b/src/terminal.c Sat Mar 29 01:46:10 2008 +0000 @@ -295,6 +295,10 @@ #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 @@ 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 @@ 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);
--- a/src/xdisp.c Sat Mar 29 01:09:45 2008 +0000 +++ b/src/xdisp.c Sat Mar 29 01:46:10 2008 +0000 @@ -2316,33 +2316,6 @@ /* 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 @@ 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 @@ { Lisp_Object msg; - if (NILP (echo_area_buffer[0])) + if (!BUFFERP (echo_area_buffer[0])) msg = Qnil; else { @@ -24359,6 +24353,9 @@ 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");
--- a/src/xterm.c Sat Mar 29 01:09:45 2008 +0000 +++ b/src/xterm.c Sat Mar 29 01:46:10 2008 +0000 @@ -8144,7 +8144,11 @@ /* 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 @@ 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); }