aboutsummaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
authorAlan Mackenzie2021-02-11 21:37:45 +0000
committerAlan Mackenzie2021-02-11 21:37:45 +0000
commit203e61ff837128b397eb313a5bb1b703f0eae0ec (patch)
treefa2a96312dd4ec237bcf2a2baa7439ed83f351d2 /src/eval.c
parent4f63b4bfc6c16abeaf9d8a9e9de76cc42d772567 (diff)
downloademacs-203e61ff837128b397eb313a5bb1b703f0eae0ec.tar.gz
emacs-203e61ff837128b397eb313a5bb1b703f0eae0ec.zip
Make recursive minibuffers and recursive edits work together
* lisp/minibuffer.el (exit-minibuffer): When in a minibuffer, throw an error should the command loop nesting level be wrong. * src/lisp.h (minibuffer_quit_level): declare as an extern. (command_loop_level): Move definition from src/window.h * src/window.h (command_loop_level): move definition to src/lisp.h. * src/eval.c (minibuffer_quit_level): Move this variable to file level from being a static inside internal_catch. (internal_catch): Simplify the logic. * src/minibuf.c (Vcommand_loop_level_list): New variable. (move_minibuffer_onto_frame): Set the major mode of *Minibuf-0*. (Fminibuffer_innermost_command_loop_p): New primitive. (Fabort_minibuffers): Check the command loop level before throwing t to 'exit, and set minibuffer_quit_level too. (read_minibuf): New variable calling_window. Before stacking up minibuffers on the current mini-window, check that the mini-window is not the current one. Do not call choose_minibuf_frame from read_minibuf's unwinding process. Bind calling_frame and calling_window over the recursive edit. Set the new minibuffer's major mode directly. Remove the switching away from the minibuffer after the recursive edit. (get_minibuffer): Record the command loop level in new variable Vcommand_loop_level_list. No longer set the major mode of a returned minibuffer. (minibuf_c_loop_level): New function. (read_minibuf_unwind): New variables calling_frame, calling_window are unbound from the binding stack. Remove old variable `window', which could not be set reliably to the expired mini-window. The expired minibuffer is determined as the nth in the list, rather than the contents of the current or previous mini-window. Switch the current window away from the mini-window here (moved from read_minibuf).
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c32
1 files changed, 14 insertions, 18 deletions
diff --git a/src/eval.c b/src/eval.c
index 3aff3b56d52..91fc4e68377 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1165,21 +1165,23 @@ usage: (catch TAG BODY...) */)
1165 FUNC should return a Lisp_Object. 1165 FUNC should return a Lisp_Object.
1166 This is how catches are done from within C code. */ 1166 This is how catches are done from within C code. */
1167 1167
1168/* MINIBUFFER_QUIT_LEVEL is to handle quitting from nested minibuffers by
1169 throwing t to tag `exit'.
1170 0 means there is no (throw 'exit t) in progress, or it wasn't from
1171 a minibuffer which isn't the most nested;
1172 N > 0 means the `throw' was done from the minibuffer at level N which
1173 wasn't the most nested. */
1174EMACS_INT minibuffer_quit_level = 0;
1175
1168Lisp_Object 1176Lisp_Object
1169internal_catch (Lisp_Object tag, 1177internal_catch (Lisp_Object tag,
1170 Lisp_Object (*func) (Lisp_Object), Lisp_Object arg) 1178 Lisp_Object (*func) (Lisp_Object), Lisp_Object arg)
1171{ 1179{
1172 /* MINIBUFFER_QUIT_LEVEL is to handle quitting from nested minibuffers by
1173 throwing t to tag `exit'.
1174 Value -1 means there is no (throw 'exit t) in progress;
1175 0 means the `throw' wasn't done from an active minibuffer;
1176 N > 0 means the `throw' was done from the minibuffer at level N. */
1177 static EMACS_INT minibuffer_quit_level = -1;
1178 /* This structure is made part of the chain `catchlist'. */ 1180 /* This structure is made part of the chain `catchlist'. */
1179 struct handler *c = push_handler (tag, CATCHER); 1181 struct handler *c = push_handler (tag, CATCHER);
1180 1182
1181 if (EQ (tag, Qexit)) 1183 if (EQ (tag, Qexit))
1182 minibuffer_quit_level = -1; 1184 minibuffer_quit_level = 0;
1183 1185
1184 /* Call FUNC. */ 1186 /* Call FUNC. */
1185 if (! sys_setjmp (c->jmp)) 1187 if (! sys_setjmp (c->jmp))
@@ -1194,22 +1196,16 @@ internal_catch (Lisp_Object tag,
1194 Lisp_Object val = handlerlist->val; 1196 Lisp_Object val = handlerlist->val;
1195 clobbered_eassert (handlerlist == c); 1197 clobbered_eassert (handlerlist == c);
1196 handlerlist = handlerlist->next; 1198 handlerlist = handlerlist->next;
1197 if (EQ (tag, Qexit) && EQ (val, Qt)) 1199 if (EQ (tag, Qexit) && EQ (val, Qt) && minibuffer_quit_level > 0)
1198 /* If we've thrown t to tag `exit' from within a minibuffer, we 1200 /* If we've thrown t to tag `exit' from within a minibuffer, we
1199 exit all minibuffers more deeply nested than the current 1201 exit all minibuffers more deeply nested than the current
1200 one. */ 1202 one. */
1201 { 1203 {
1202 EMACS_INT mini_depth = this_minibuffer_depth (Qnil); 1204 if (minibuf_level > minibuffer_quit_level
1203 if (mini_depth && mini_depth != minibuffer_quit_level) 1205 && !NILP (Fminibuffer_innermost_command_loop_p (Qnil)))
1204 { 1206 Fthrow (Qexit, Qt);
1205 if (minibuffer_quit_level == -1)
1206 minibuffer_quit_level = mini_depth;
1207 if (minibuffer_quit_level
1208 && (minibuf_level > minibuffer_quit_level))
1209 Fthrow (Qexit, Qt);
1210 }
1211 else 1207 else
1212 minibuffer_quit_level = -1; 1208 minibuffer_quit_level = 0;
1213 } 1209 }
1214 return val; 1210 return val;
1215 } 1211 }