2000-11-15 Miles Bader * xdisp.c (setup_echo_area_for_active_minibuffer): New function. (set_message_1): If there's currently a minibuffer active, insert its contents before the message, so the message appears as if it's appended to the minibuffer. (setup_echo_area_for_printing): Likewise. Also return the place where point should be moved after printing. (clear_echo_area): New function. (with_echo_area_buffer, setup_echo_area_for_printing): Use it. * lisp.h (setup_echo_area_for_printing): Change return type to int. * print.c (PRINTPREPARE): Set old_point/old_point_byte from setup_echo_area_for_printing's return value. (printchar, strout): Get correct point position from setup_echo_area_for_printing, and move there after inserting. Index: src/xdisp.c =================================================================== RCS file: /cvs/emacs/src/xdisp.c,v retrieving revision 1.517 diff -u -r1.517 xdisp.c --- src/xdisp.c 2000/11/14 18:38:07 1.517 +++ src/xdisp.c 2000/11/15 13:22:29 @@ -219,6 +219,8 @@ extern Lisp_Object Voverriding_local_map_menu_flag; extern Lisp_Object Qmenu_item; +extern Lisp_Object Vminibuffer_list; + Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; Lisp_Object Qredisplay_end_trigger_functions; @@ -5749,6 +5751,97 @@ } +/* Set up the current buffer for inserting an echo-area message in the + case where a minibuffer is active; the message should be then + inserted at the current point. If APPEND is non-zero, then the + current buffer is assumed to have already been setup, and point is + moved to the correct position for inserting more text. The return + value is where point should be positioned after inserting the + message; if there's no active minibuffer, 0 is returned. + + The idea behind this function is that the resulting buffer should + look like the active minibuffer, except with the message added. */ + +static int +setup_echo_area_for_active_minibuffer (int append) +{ + /* If the minibuffer is currently in used, insert its contents + before the message, with appropriate delimiters, so that it + looks like the message has been appended to the minibuffer + (ala `minibuffer-message'). We make a special exception if + cursor_in_echo_area is true, because it probably implies + that the "message" is actually a prompt, so we want it to + take over the echo area. */ + if (minibuf_level > 0 && !cursor_in_echo_area) + { + Lisp_Object num, lisp_minibuf; + + XSETFASTINT (num, minibuf_level); + lisp_minibuf = Fnth (num, Vminibuffer_list); + + if (BUFFERP (lisp_minibuf)) + /* Got a minibuffer. */ + { + struct buffer *minibuf = XBUFFER (lisp_minibuf); + + if (! append) + { + if (!NILP (minibuf->enable_multibyte_characters) + && NILP (current_buffer->enable_multibyte_characters)) + /* MINIBUF contains multibyte characters, so we + need to force the current buffer to show them. */ + Fset_buffer_multibyte (Qt); + + /* Insert the minibuffer contents. */ + insert_from_buffer (minibuf, BEG, + BUF_Z(minibuf) - BUF_BEG(minibuf), + 0); + + /* Insert the delimiters separating it from the message. */ + insert_string (" []"); + } + + /* Move point back so the message gets inserted inside + the brackets (if append is true, then point will be + positioned after any previously inserted message). */ + TEMP_SET_PT (Z - 1); + + /* Set the echo-area's point to the same place as the + minibuffer, so that the echo-area looks like it's + still the minibuffer with something added to the end. */ + return BUF_PT (minibuf); + } + } + + /* There's no active minibuffer, so we don't need to position point + specially. */ + return 0; +} + + +/* Erases the contents of the current buffer, ignoring any read-only or + hook text-properties. */ + +static void +clear_echo_area () +{ + /* It's possible for the buffer to contain text with a read-only or + modification-hook properties if the contents of a minibuffer had + been inserted into it, so make sure that can't screw us up + here. */ + Lisp_Object old_inhibit_readonly = Vinhibit_read_only; + int old_inhibit_modification_hooks = inhibit_modification_hooks; + + Vinhibit_read_only = Qt; + inhibit_modification_hooks = 1; + + del_range (BEG, Z); + + Vinhibit_read_only = old_inhibit_readonly; + inhibit_modification_hooks = old_inhibit_modification_hooks; +} + + /* Call FN with args A1..A4 with either the current or last displayed echo_area_buffer as current buffer. @@ -5833,7 +5926,7 @@ current_buffer->read_only = Qnil; if (clear_buffer_p && Z > BEG) - del_range (BEG, Z); + clear_echo_area (); xassert (BEGV >= BEG); xassert (ZV <= Z && ZV >= BEGV); @@ -5925,12 +6018,15 @@ /* Set up the echo area for use by print functions. MULTIBYTE_P - non-zero means we will print multibyte. */ + non-zero means we will print multibyte. Return the position point + should be moved to after printing, or 0 if it doesn't matter. */ -void +int setup_echo_area_for_printing (multibyte_p) int multibyte_p; { + int final_point = 0; + ensure_echo_area_buffers (); if (!message_buf_print) @@ -5945,9 +6041,14 @@ /* Switch to that buffer and clear it. */ set_buffer_internal (XBUFFER (echo_area_buffer[0])); if (Z > BEG) - del_range (BEG, Z); + clear_echo_area (); TEMP_SET_PT_BOTH (BEG, BEG_BYTE); + if (minibuf_level > 0) + /* There's an active minibuffer, so setup the echo area to reflect + that if necessary. */ + final_point = setup_echo_area_for_active_minibuffer (0); + /* Set up the buffer for the multibyteness we need. */ if (multibyte_p != !NILP (current_buffer->enable_multibyte_characters)) @@ -5978,7 +6079,14 @@ if (current_buffer != XBUFFER (echo_area_buffer[0])) /* Someone switched buffers between print requests. */ set_buffer_internal (XBUFFER (echo_area_buffer[0])); + + if (minibuf_level > 0) + /* There's an active minibuffer, so setup the echo area to reflect + that if necessary. */ + final_point = setup_echo_area_for_active_minibuffer (1); } + + return final_point; } @@ -6382,6 +6490,8 @@ { char *s = (char *) a1; Lisp_Object string = a2; + /* If non-zero, leave the point at this position in the echo buffer. */ + int final_point = 0; xassert (BEG == Z); @@ -6395,6 +6505,11 @@ /* Insert new message at BEG. */ TEMP_SET_PT_BOTH (BEG, BEG_BYTE); + if (minibuf_level > 0) + /* There's an active minibuffer, so setup the echo area to reflect + that if necessary. */ + final_point = setup_echo_area_for_active_minibuffer (0); + if (STRINGP (string)) { int nchars; @@ -6448,6 +6563,12 @@ else insert_1 (s, nbytes, 1, 0, 0); } + + if (final_point) + /* If we prepended the minibuffer contents to our message (see + above), then also put the current point at the same place that it + is in the minibuffer. */ + TEMP_SET_PT (final_point); return 0; } Index: src/lisp.h =================================================================== RCS file: /cvs/emacs/src/lisp.h,v retrieving revision 1.344 diff -u -r1.344 lisp.h --- src/lisp.h 2000/11/14 05:41:41 1.344 +++ src/lisp.h 2000/11/15 13:21:20 @@ -2121,7 +2121,7 @@ extern int message_enable_multibyte; extern Lisp_Object echo_area_buffer[2]; extern void check_message_stack P_ ((void)); -extern void setup_echo_area_for_printing P_ ((int)); +extern int setup_echo_area_for_printing P_ ((int)); extern int push_message P_ ((void)); extern void pop_message P_ ((void)); extern void restore_message P_ ((void)); Index: src/print.c =================================================================== RCS file: /cvs/emacs/src/print.c,v retrieving revision 1.151 diff -u -r1.151 print.c --- src/print.c 2000/08/22 22:35:43 1.151 +++ src/print.c 2000/11/15 13:21:29 @@ -246,7 +246,13 @@ print_buffer_pos_byte = 0; \ } \ if (EQ (printcharfun, Qt) && ! noninteractive) \ - setup_echo_area_for_printing (multibyte); + { \ + old_point = setup_echo_area_for_printing (multibyte); \ + if (old_point > 0) \ + old_point_byte = CHAR_TO_BYTE (old_point); \ + else \ + old_point = -1; \ + } #define PRINTFINISH \ if (NILP (printcharfun)) \ @@ -336,9 +342,14 @@ { int multibyte_p = !NILP (current_buffer->enable_multibyte_characters); - - setup_echo_area_for_printing (multibyte_p); + int old_point + = setup_echo_area_for_printing (multibyte_p); + insert_char (ch); + + if (old_point) + TEMP_SET_PT (old_point); + message_dolog (str, len, 0, multibyte_p); } } @@ -393,8 +404,9 @@ int i; int multibyte_p = !NILP (current_buffer->enable_multibyte_characters); - - setup_echo_area_for_printing (multibyte_p); + int old_point + = setup_echo_area_for_printing (multibyte_p); + message_dolog (ptr, size_byte, 0, multibyte_p); if (size == size_byte) @@ -412,6 +424,9 @@ } } + if (old_point) + TEMP_SET_PT (old_point); + #ifdef MAX_PRINT_CHARS if (max_print) print_chars += size;