diff options
| author | Alan Mackenzie | 2021-02-11 21:37:45 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2021-02-11 21:37:45 +0000 |
| commit | 203e61ff837128b397eb313a5bb1b703f0eae0ec (patch) | |
| tree | fa2a96312dd4ec237bcf2a2baa7439ed83f351d2 | |
| parent | 4f63b4bfc6c16abeaf9d8a9e9de76cc42d772567 (diff) | |
| download | emacs-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).
| -rw-r--r-- | lisp/minibuffer.el | 13 | ||||
| -rw-r--r-- | src/eval.c | 32 | ||||
| -rw-r--r-- | src/lisp.h | 2 | ||||
| -rw-r--r-- | src/minibuf.c | 115 | ||||
| -rw-r--r-- | src/window.h | 4 |
5 files changed, 107 insertions, 59 deletions
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index a899a943d4c..aacb8ab00bb 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el | |||
| @@ -2116,18 +2116,19 @@ variables.") | |||
| 2116 | (defun exit-minibuffer () | 2116 | (defun exit-minibuffer () |
| 2117 | "Terminate this minibuffer argument." | 2117 | "Terminate this minibuffer argument." |
| 2118 | (interactive) | 2118 | (interactive) |
| 2119 | (when (or | 2119 | (when (minibufferp) |
| 2120 | (innermost-minibuffer-p) | 2120 | (when (not (minibuffer-innermost-command-loop-p)) |
| 2121 | (not (minibufferp))) | 2121 | (error "%s" "Not in most nested command loop")) |
| 2122 | (when (not (innermost-minibuffer-p)) | ||
| 2123 | (error "%s" "Not in most nested minibuffer"))) | ||
| 2122 | ;; If the command that uses this has made modifications in the minibuffer, | 2124 | ;; If the command that uses this has made modifications in the minibuffer, |
| 2123 | ;; we don't want them to cause deactivation of the mark in the original | 2125 | ;; we don't want them to cause deactivation of the mark in the original |
| 2124 | ;; buffer. | 2126 | ;; buffer. |
| 2125 | ;; A better solution would be to make deactivate-mark buffer-local | 2127 | ;; A better solution would be to make deactivate-mark buffer-local |
| 2126 | ;; (or to turn it into a list of buffers, ...), but in the mean time, | 2128 | ;; (or to turn it into a list of buffers, ...), but in the mean time, |
| 2127 | ;; this should do the trick in most cases. | 2129 | ;; this should do the trick in most cases. |
| 2128 | (setq deactivate-mark nil) | 2130 | (setq deactivate-mark nil) |
| 2129 | (throw 'exit nil)) | 2131 | (throw 'exit nil)) |
| 2130 | (error "%s" "Not in most nested minibuffer")) | ||
| 2131 | 2132 | ||
| 2132 | (defun self-insert-and-exit () | 2133 | (defun self-insert-and-exit () |
| 2133 | "Terminate minibuffer input." | 2134 | "Terminate minibuffer input." |
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. */ | ||
| 1174 | EMACS_INT minibuffer_quit_level = 0; | ||
| 1175 | |||
| 1168 | Lisp_Object | 1176 | Lisp_Object |
| 1169 | internal_catch (Lisp_Object tag, | 1177 | internal_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 | } |
diff --git a/src/lisp.h b/src/lisp.h index 409a1e70608..0847324d1ff 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -4091,6 +4091,7 @@ intern_c_string (const char *str) | |||
| 4091 | } | 4091 | } |
| 4092 | 4092 | ||
| 4093 | /* Defined in eval.c. */ | 4093 | /* Defined in eval.c. */ |
| 4094 | extern EMACS_INT minibuffer_quit_level; | ||
| 4094 | extern Lisp_Object Vautoload_queue; | 4095 | extern Lisp_Object Vautoload_queue; |
| 4095 | extern Lisp_Object Vrun_hooks; | 4096 | extern Lisp_Object Vrun_hooks; |
| 4096 | extern Lisp_Object Vsignaling_function; | 4097 | extern Lisp_Object Vsignaling_function; |
| @@ -4369,6 +4370,7 @@ extern void syms_of_casetab (void); | |||
| 4369 | 4370 | ||
| 4370 | /* Defined in keyboard.c. */ | 4371 | /* Defined in keyboard.c. */ |
| 4371 | 4372 | ||
| 4373 | extern EMACS_INT command_loop_level; | ||
| 4372 | extern Lisp_Object echo_message_buffer; | 4374 | extern Lisp_Object echo_message_buffer; |
| 4373 | extern struct kboard *echo_kboard; | 4375 | extern struct kboard *echo_kboard; |
| 4374 | extern void cancel_echoing (void); | 4376 | extern void cancel_echoing (void); |
diff --git a/src/minibuf.c b/src/minibuf.c index 949c3d989d5..4b1f4b1ff72 100644 --- a/src/minibuf.c +++ b/src/minibuf.c | |||
| @@ -41,6 +41,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 41 | minibuffer recursions are encountered. */ | 41 | minibuffer recursions are encountered. */ |
| 42 | 42 | ||
| 43 | Lisp_Object Vminibuffer_list; | 43 | Lisp_Object Vminibuffer_list; |
| 44 | Lisp_Object Vcommand_loop_level_list; | ||
| 44 | 45 | ||
| 45 | /* Data to remember during recursive minibuffer invocations. */ | 46 | /* Data to remember during recursive minibuffer invocations. */ |
| 46 | 47 | ||
| @@ -64,6 +65,8 @@ static Lisp_Object minibuf_prompt; | |||
| 64 | static ptrdiff_t minibuf_prompt_width; | 65 | static ptrdiff_t minibuf_prompt_width; |
| 65 | 66 | ||
| 66 | static Lisp_Object nth_minibuffer (EMACS_INT depth); | 67 | static Lisp_Object nth_minibuffer (EMACS_INT depth); |
| 68 | static EMACS_INT minibuf_c_loop_level (EMACS_INT depth); | ||
| 69 | static void set_minibuffer_mode (Lisp_Object buf, EMACS_INT depth); | ||
| 67 | 70 | ||
| 68 | 71 | ||
| 69 | /* Return TRUE when a frame switch causes a minibuffer on the old | 72 | /* Return TRUE when a frame switch causes a minibuffer on the old |
| @@ -181,7 +184,12 @@ void move_minibuffer_onto_frame (void) | |||
| 181 | set_window_buffer (sf->minibuffer_window, nth_minibuffer (i), 0, 0); | 184 | set_window_buffer (sf->minibuffer_window, nth_minibuffer (i), 0, 0); |
| 182 | minibuf_window = sf->minibuffer_window; | 185 | minibuf_window = sf->minibuffer_window; |
| 183 | if (of != sf) | 186 | if (of != sf) |
| 184 | set_window_buffer (of->minibuffer_window, get_minibuffer (0), 0, 0); | 187 | { |
| 188 | Lisp_Object temp = get_minibuffer (0); | ||
| 189 | |||
| 190 | set_window_buffer (of->minibuffer_window, temp, 0, 0); | ||
| 191 | set_minibuffer_mode (temp, 0); | ||
| 192 | } | ||
| 185 | } | 193 | } |
| 186 | } | 194 | } |
| 187 | 195 | ||
| @@ -389,6 +397,21 @@ No argument or nil as argument means use the current buffer as BUFFER. */) | |||
| 389 | : Qnil; | 397 | : Qnil; |
| 390 | } | 398 | } |
| 391 | 399 | ||
| 400 | DEFUN ("minibuffer-innermost-command-loop-p", Fminibuffer_innermost_command_loop_p, | ||
| 401 | Sminibuffer_innermost_command_loop_p, 0, 1, 0, | ||
| 402 | doc: /* Return t if BUFFER is a minibuffer at the current command loop level. | ||
| 403 | No argument or nil as argument means use the current buffer as BUFFER. */) | ||
| 404 | (Lisp_Object buffer) | ||
| 405 | { | ||
| 406 | EMACS_INT depth; | ||
| 407 | if (NILP (buffer)) | ||
| 408 | buffer = Fcurrent_buffer (); | ||
| 409 | depth = this_minibuffer_depth (buffer); | ||
| 410 | return depth && minibuf_c_loop_level (depth) == command_loop_level | ||
| 411 | ? Qt | ||
| 412 | : Qnil; | ||
| 413 | } | ||
| 414 | |||
| 392 | /* Return the nesting depth of the active minibuffer BUFFER, or 0 if | 415 | /* Return the nesting depth of the active minibuffer BUFFER, or 0 if |
| 393 | BUFFER isn't such a thing. If BUFFER is nil, this means use the current | 416 | BUFFER isn't such a thing. If BUFFER is nil, this means use the current |
| 394 | buffer. */ | 417 | buffer. */ |
| @@ -420,12 +443,17 @@ confirm the aborting of the current minibuffer and all contained ones. */) | |||
| 420 | 443 | ||
| 421 | if (!minibuf_depth) | 444 | if (!minibuf_depth) |
| 422 | error ("Not in a minibuffer"); | 445 | error ("Not in a minibuffer"); |
| 446 | if (NILP (Fminibuffer_innermost_command_loop_p (Qnil))) | ||
| 447 | error ("Not in most nested command loop"); | ||
| 423 | if (minibuf_depth < minibuf_level) | 448 | if (minibuf_depth < minibuf_level) |
| 424 | { | 449 | { |
| 425 | array[0] = fmt; | 450 | array[0] = fmt; |
| 426 | array[1] = make_fixnum (minibuf_level - minibuf_depth + 1); | 451 | array[1] = make_fixnum (minibuf_level - minibuf_depth + 1); |
| 427 | if (!NILP (Fyes_or_no_p (Fformat (2, array)))) | 452 | if (!NILP (Fyes_or_no_p (Fformat (2, array)))) |
| 428 | Fthrow (Qexit, Qt); | 453 | { |
| 454 | minibuffer_quit_level = minibuf_depth; | ||
| 455 | Fthrow (Qexit, Qt); | ||
| 456 | } | ||
| 429 | } | 457 | } |
| 430 | else | 458 | else |
| 431 | Fthrow (Qexit, Qt); | 459 | Fthrow (Qexit, Qt); |
| @@ -508,6 +536,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, | |||
| 508 | ptrdiff_t count = SPECPDL_INDEX (); | 536 | ptrdiff_t count = SPECPDL_INDEX (); |
| 509 | Lisp_Object mini_frame, ambient_dir, minibuffer, input_method; | 537 | Lisp_Object mini_frame, ambient_dir, minibuffer, input_method; |
| 510 | Lisp_Object calling_frame = selected_frame; | 538 | Lisp_Object calling_frame = selected_frame; |
| 539 | Lisp_Object calling_window = selected_window; | ||
| 511 | Lisp_Object enable_multibyte; | 540 | Lisp_Object enable_multibyte; |
| 512 | EMACS_INT pos = 0; | 541 | EMACS_INT pos = 0; |
| 513 | /* String to add to the history. */ | 542 | /* String to add to the history. */ |
| @@ -598,7 +627,8 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, | |||
| 598 | 627 | ||
| 599 | if (minibuf_level > 1 | 628 | if (minibuf_level > 1 |
| 600 | && minibuf_moves_frame_when_opened () | 629 | && minibuf_moves_frame_when_opened () |
| 601 | && !minibuf_follows_frame ()) | 630 | && (!minibuf_follows_frame () |
| 631 | || (!EQ (mini_frame, selected_frame)))) | ||
| 602 | { | 632 | { |
| 603 | EMACS_INT i; | 633 | EMACS_INT i; |
| 604 | 634 | ||
| @@ -607,8 +637,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, | |||
| 607 | set_window_buffer (minibuf_window, nth_minibuffer (i), 0, 0); | 637 | set_window_buffer (minibuf_window, nth_minibuffer (i), 0, 0); |
| 608 | } | 638 | } |
| 609 | 639 | ||
| 610 | record_unwind_protect_void (choose_minibuf_frame); | ||
| 611 | |||
| 612 | record_unwind_protect (restore_window_configuration, | 640 | record_unwind_protect (restore_window_configuration, |
| 613 | Fcons (Qt, Fcurrent_window_configuration (Qnil))); | 641 | Fcons (Qt, Fcurrent_window_configuration (Qnil))); |
| 614 | 642 | ||
| @@ -640,7 +668,9 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, | |||
| 640 | minibuf_save_list | 668 | minibuf_save_list |
| 641 | = Fcons (Voverriding_local_map, | 669 | = Fcons (Voverriding_local_map, |
| 642 | Fcons (minibuf_window, | 670 | Fcons (minibuf_window, |
| 643 | minibuf_save_list)); | 671 | Fcons (calling_frame, |
| 672 | Fcons (calling_window, | ||
| 673 | minibuf_save_list)))); | ||
| 644 | minibuf_save_list | 674 | minibuf_save_list |
| 645 | = Fcons (minibuf_prompt, | 675 | = Fcons (minibuf_prompt, |
| 646 | Fcons (make_fixnum (minibuf_prompt_width), | 676 | Fcons (make_fixnum (minibuf_prompt_width), |
| @@ -694,6 +724,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, | |||
| 694 | /* Switch to the minibuffer. */ | 724 | /* Switch to the minibuffer. */ |
| 695 | 725 | ||
| 696 | minibuffer = get_minibuffer (minibuf_level); | 726 | minibuffer = get_minibuffer (minibuf_level); |
| 727 | set_minibuffer_mode (minibuffer, minibuf_level); | ||
| 697 | Fset_buffer (minibuffer); | 728 | Fset_buffer (minibuffer); |
| 698 | 729 | ||
| 699 | /* Defeat (setq-default truncate-lines t), since truncated lines do | 730 | /* Defeat (setq-default truncate-lines t), since truncated lines do |
| @@ -738,6 +769,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, | |||
| 738 | where there is an active minibuffer. | 769 | where there is an active minibuffer. |
| 739 | Set them to point to ` *Minibuf-0*', which is always empty. */ | 770 | Set them to point to ` *Minibuf-0*', which is always empty. */ |
| 740 | empty_minibuf = get_minibuffer (0); | 771 | empty_minibuf = get_minibuffer (0); |
| 772 | set_minibuffer_mode (empty_minibuf, 0); | ||
| 741 | 773 | ||
| 742 | FOR_EACH_FRAME (dummy, frame) | 774 | FOR_EACH_FRAME (dummy, frame) |
| 743 | { | 775 | { |
| @@ -837,20 +869,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, | |||
| 837 | 869 | ||
| 838 | recursive_edit_1 (); | 870 | recursive_edit_1 (); |
| 839 | 871 | ||
| 840 | /* We've exited the recursive edit without an error, so switch the | ||
| 841 | current window away from the expired minibuffer window. */ | ||
| 842 | { | ||
| 843 | Lisp_Object prev = Fprevious_window (minibuf_window, Qnil, Qnil); | ||
| 844 | /* PREV can be on a different frame when we have a minibuffer only | ||
| 845 | frame, the other frame's minibuffer window is MINIBUF_WINDOW, | ||
| 846 | and its "focus window" is also MINIBUF_WINDOW. */ | ||
| 847 | while (!EQ (prev, minibuf_window) | ||
| 848 | && !EQ (selected_frame, WINDOW_FRAME (XWINDOW (prev)))) | ||
| 849 | prev = Fprevious_window (prev, Qnil, Qnil); | ||
| 850 | if (!EQ (prev, minibuf_window)) | ||
| 851 | Fset_frame_selected_window (selected_frame, prev, Qnil); | ||
| 852 | } | ||
| 853 | |||
| 854 | /* If cursor is on the minibuffer line, | 872 | /* If cursor is on the minibuffer line, |
| 855 | show the user we have exited by putting it in column 0. */ | 873 | show the user we have exited by putting it in column 0. */ |
| 856 | if (XWINDOW (minibuf_window)->cursor.vpos >= 0 | 874 | if (XWINDOW (minibuf_window)->cursor.vpos >= 0 |
| @@ -959,11 +977,16 @@ Lisp_Object | |||
| 959 | get_minibuffer (EMACS_INT depth) | 977 | get_minibuffer (EMACS_INT depth) |
| 960 | { | 978 | { |
| 961 | Lisp_Object tail = Fnthcdr (make_fixnum (depth), Vminibuffer_list); | 979 | Lisp_Object tail = Fnthcdr (make_fixnum (depth), Vminibuffer_list); |
| 980 | Lisp_Object cll_tail = Fnthcdr (make_fixnum (depth), | ||
| 981 | Vcommand_loop_level_list); | ||
| 962 | if (NILP (tail)) | 982 | if (NILP (tail)) |
| 963 | { | 983 | { |
| 964 | tail = list1 (Qnil); | 984 | tail = list1 (Qnil); |
| 965 | Vminibuffer_list = nconc2 (Vminibuffer_list, tail); | 985 | Vminibuffer_list = nconc2 (Vminibuffer_list, tail); |
| 986 | cll_tail = list1 (Qnil); | ||
| 987 | Vcommand_loop_level_list = nconc2 (Vcommand_loop_level_list, cll_tail); | ||
| 966 | } | 988 | } |
| 989 | XSETCAR (cll_tail, make_fixnum (depth ? command_loop_level : 0)); | ||
| 967 | Lisp_Object buf = Fcar (tail); | 990 | Lisp_Object buf = Fcar (tail); |
| 968 | if (NILP (buf) || !BUFFER_LIVE_P (XBUFFER (buf))) | 991 | if (NILP (buf) || !BUFFER_LIVE_P (XBUFFER (buf))) |
| 969 | { | 992 | { |
| @@ -973,7 +996,6 @@ get_minibuffer (EMACS_INT depth) | |||
| 973 | buf = Fget_buffer_create (lname, Qnil); | 996 | buf = Fget_buffer_create (lname, Qnil); |
| 974 | /* Do this before set_minibuffer_mode. */ | 997 | /* Do this before set_minibuffer_mode. */ |
| 975 | XSETCAR (tail, buf); | 998 | XSETCAR (tail, buf); |
| 976 | set_minibuffer_mode (buf, depth); | ||
| 977 | /* Although the buffer's name starts with a space, undo should be | 999 | /* Although the buffer's name starts with a space, undo should be |
| 978 | enabled in it. */ | 1000 | enabled in it. */ |
| 979 | Fbuffer_enable_undo (buf); | 1001 | Fbuffer_enable_undo (buf); |
| @@ -985,12 +1007,19 @@ get_minibuffer (EMACS_INT depth) | |||
| 985 | while the buffer doesn't know about them any more. */ | 1007 | while the buffer doesn't know about them any more. */ |
| 986 | delete_all_overlays (XBUFFER (buf)); | 1008 | delete_all_overlays (XBUFFER (buf)); |
| 987 | reset_buffer (XBUFFER (buf)); | 1009 | reset_buffer (XBUFFER (buf)); |
| 988 | set_minibuffer_mode (buf, depth); | ||
| 989 | } | 1010 | } |
| 990 | 1011 | ||
| 991 | return buf; | 1012 | return buf; |
| 992 | } | 1013 | } |
| 993 | 1014 | ||
| 1015 | static EMACS_INT minibuf_c_loop_level (EMACS_INT depth) | ||
| 1016 | { | ||
| 1017 | Lisp_Object cll = Fnth (make_fixnum (depth), Vcommand_loop_level_list); | ||
| 1018 | if (FIXNUMP (cll)) | ||
| 1019 | return XFIXNUM (cll); | ||
| 1020 | return 0; | ||
| 1021 | } | ||
| 1022 | |||
| 994 | static void | 1023 | static void |
| 995 | run_exit_minibuf_hook (void) | 1024 | run_exit_minibuf_hook (void) |
| 996 | { | 1025 | { |
| @@ -1004,17 +1033,16 @@ static void | |||
| 1004 | read_minibuf_unwind (void) | 1033 | read_minibuf_unwind (void) |
| 1005 | { | 1034 | { |
| 1006 | Lisp_Object old_deactivate_mark; | 1035 | Lisp_Object old_deactivate_mark; |
| 1007 | Lisp_Object window; | 1036 | Lisp_Object calling_frame; |
| 1037 | Lisp_Object calling_window; | ||
| 1008 | Lisp_Object future_mini_window; | 1038 | Lisp_Object future_mini_window; |
| 1009 | 1039 | ||
| 1010 | /* If this was a recursive minibuffer, | ||
| 1011 | tie the minibuffer window back to the outer level minibuffer buffer. */ | ||
| 1012 | minibuf_level--; | ||
| 1013 | |||
| 1014 | window = minibuf_window; | ||
| 1015 | /* To keep things predictable, in case it matters, let's be in the | 1040 | /* To keep things predictable, in case it matters, let's be in the |
| 1016 | minibuffer when we reset the relevant variables. */ | 1041 | minibuffer when we reset the relevant variables. Don't depend on |
| 1017 | Fset_buffer (XWINDOW (window)->contents); | 1042 | `minibuf_window' here. This could by now be the mini-window of any |
| 1043 | frame. */ | ||
| 1044 | Fset_buffer (nth_minibuffer (minibuf_level)); | ||
| 1045 | minibuf_level--; | ||
| 1018 | 1046 | ||
| 1019 | /* Restore prompt, etc, from outer minibuffer level. */ | 1047 | /* Restore prompt, etc, from outer minibuffer level. */ |
| 1020 | Lisp_Object key_vec = Fcar (minibuf_save_list); | 1048 | Lisp_Object key_vec = Fcar (minibuf_save_list); |
| @@ -1042,6 +1070,10 @@ read_minibuf_unwind (void) | |||
| 1042 | #endif | 1070 | #endif |
| 1043 | future_mini_window = Fcar (minibuf_save_list); | 1071 | future_mini_window = Fcar (minibuf_save_list); |
| 1044 | minibuf_save_list = Fcdr (minibuf_save_list); | 1072 | minibuf_save_list = Fcdr (minibuf_save_list); |
| 1073 | calling_frame = Fcar (minibuf_save_list); | ||
| 1074 | minibuf_save_list = Fcdr (minibuf_save_list); | ||
| 1075 | calling_window = Fcar (minibuf_save_list); | ||
| 1076 | minibuf_save_list = Fcdr (minibuf_save_list); | ||
| 1045 | 1077 | ||
| 1046 | /* Erase the minibuffer we were using at this level. */ | 1078 | /* Erase the minibuffer we were using at this level. */ |
| 1047 | { | 1079 | { |
| @@ -1059,7 +1091,7 @@ read_minibuf_unwind (void) | |||
| 1059 | mini-window back to its normal size. */ | 1091 | mini-window back to its normal size. */ |
| 1060 | if (minibuf_level == 0 | 1092 | if (minibuf_level == 0 |
| 1061 | || !EQ (selected_frame, WINDOW_FRAME (XWINDOW (future_mini_window)))) | 1093 | || !EQ (selected_frame, WINDOW_FRAME (XWINDOW (future_mini_window)))) |
| 1062 | resize_mini_window (XWINDOW (window), 0); | 1094 | resize_mini_window (XWINDOW (minibuf_window), 0); |
| 1063 | 1095 | ||
| 1064 | /* Deal with frames that should be removed when exiting the | 1096 | /* Deal with frames that should be removed when exiting the |
| 1065 | minibuffer. */ | 1097 | minibuffer. */ |
| @@ -1090,6 +1122,24 @@ read_minibuf_unwind (void) | |||
| 1090 | to make sure we don't leave around bindings and stuff which only | 1122 | to make sure we don't leave around bindings and stuff which only |
| 1091 | made sense during the read_minibuf invocation. */ | 1123 | made sense during the read_minibuf invocation. */ |
| 1092 | call0 (intern ("minibuffer-inactive-mode")); | 1124 | call0 (intern ("minibuffer-inactive-mode")); |
| 1125 | |||
| 1126 | /* We've exited the recursive edit, so switch the current windows | ||
| 1127 | away from the expired minibuffer window, both in the current | ||
| 1128 | minibuffer's frame and the original calling frame. */ | ||
| 1129 | choose_minibuf_frame (); | ||
| 1130 | if (!EQ (WINDOW_FRAME (XWINDOW (minibuf_window)), calling_frame)) | ||
| 1131 | { | ||
| 1132 | Lisp_Object prev = Fprevious_window (minibuf_window, Qnil, Qnil); | ||
| 1133 | /* PREV can be on a different frame when we have a minibuffer only | ||
| 1134 | frame, the other frame's minibuffer window is MINIBUF_WINDOW, | ||
| 1135 | and its "focus window" is also MINIBUF_WINDOW. */ | ||
| 1136 | if (!EQ (prev, minibuf_window) | ||
| 1137 | && EQ (WINDOW_FRAME (XWINDOW (prev)), | ||
| 1138 | WINDOW_FRAME (XWINDOW (minibuf_window)))) | ||
| 1139 | Fset_frame_selected_window (selected_frame, prev, Qnil); | ||
| 1140 | } | ||
| 1141 | else | ||
| 1142 | Fset_frame_selected_window (calling_frame, calling_window, Qnil); | ||
| 1093 | } | 1143 | } |
| 1094 | 1144 | ||
| 1095 | 1145 | ||
| @@ -2137,6 +2187,7 @@ void | |||
| 2137 | init_minibuf_once (void) | 2187 | init_minibuf_once (void) |
| 2138 | { | 2188 | { |
| 2139 | staticpro (&Vminibuffer_list); | 2189 | staticpro (&Vminibuffer_list); |
| 2190 | staticpro (&Vcommand_loop_level_list); | ||
| 2140 | pdumper_do_now_and_after_load (init_minibuf_once_for_pdumper); | 2191 | pdumper_do_now_and_after_load (init_minibuf_once_for_pdumper); |
| 2141 | } | 2192 | } |
| 2142 | 2193 | ||
| @@ -2150,6 +2201,7 @@ init_minibuf_once_for_pdumper (void) | |||
| 2150 | restore from a dump file. pdumper doesn't try to preserve | 2201 | restore from a dump file. pdumper doesn't try to preserve |
| 2151 | frames, windows, and so on, so reset everything related here. */ | 2202 | frames, windows, and so on, so reset everything related here. */ |
| 2152 | Vminibuffer_list = Qnil; | 2203 | Vminibuffer_list = Qnil; |
| 2204 | Vcommand_loop_level_list = Qnil; | ||
| 2153 | minibuf_level = 0; | 2205 | minibuf_level = 0; |
| 2154 | minibuf_prompt = Qnil; | 2206 | minibuf_prompt = Qnil; |
| 2155 | minibuf_save_list = Qnil; | 2207 | minibuf_save_list = Qnil; |
| @@ -2380,6 +2432,7 @@ instead. */); | |||
| 2380 | 2432 | ||
| 2381 | defsubr (&Sminibufferp); | 2433 | defsubr (&Sminibufferp); |
| 2382 | defsubr (&Sinnermost_minibuffer_p); | 2434 | defsubr (&Sinnermost_minibuffer_p); |
| 2435 | defsubr (&Sminibuffer_innermost_command_loop_p); | ||
| 2383 | defsubr (&Sabort_minibuffers); | 2436 | defsubr (&Sabort_minibuffers); |
| 2384 | defsubr (&Sminibuffer_prompt_end); | 2437 | defsubr (&Sminibuffer_prompt_end); |
| 2385 | defsubr (&Sminibuffer_contents); | 2438 | defsubr (&Sminibuffer_contents); |
diff --git a/src/window.h b/src/window.h index 79eb44e7a38..b6f88e8f55f 100644 --- a/src/window.h +++ b/src/window.h | |||
| @@ -1120,10 +1120,6 @@ void set_window_buffer (Lisp_Object window, Lisp_Object buffer, | |||
| 1120 | 1120 | ||
| 1121 | extern Lisp_Object echo_area_window; | 1121 | extern Lisp_Object echo_area_window; |
| 1122 | 1122 | ||
| 1123 | /* Depth in recursive edits. */ | ||
| 1124 | |||
| 1125 | extern EMACS_INT command_loop_level; | ||
| 1126 | |||
| 1127 | /* Non-zero if we should redraw the mode lines on the next redisplay. | 1123 | /* Non-zero if we should redraw the mode lines on the next redisplay. |
| 1128 | Usually set to a unique small integer so we can track the main causes of | 1124 | Usually set to a unique small integer so we can track the main causes of |
| 1129 | full redisplays in `redisplay--mode-lines-cause'. */ | 1125 | full redisplays in `redisplay--mode-lines-cause'. */ |