2000-11-16 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. (echo_area_message): New function. (current_message_1): Use it to get messages. (clear_echo_area): New function. (with_echo_area_buffer, setup_echo_area_for_printing): Use it. (minibuffer_append_messages): New variable. (syms_of_xdisp): Initialize 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. * dispnew.c (update_frame_1): When `minibuffer_append_messages' is true, don't move the cursor to the end just because there's a message showing. Index: src/xdisp.c =================================================================== RCS file: /cvs/emacs/src/xdisp.c,v retrieving revision 1.519 diff -u -r1.519 xdisp.c --- src/xdisp.c 2000/11/16 05:05:12 1.519 +++ src/xdisp.c 2000/11/16 06:19:27 @@ -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; @@ -331,6 +333,15 @@ int multiple_frames; +/* Nonzero means messages are appended to active minibuffers, inside brackets. + Zero means messages replace active minibuffers in the echo-area temporarily. + + An exception to this rule is that if `cursor_in_echo_area' is non-zero, + messages always use the whole echo-area; this is because such messages + are usually prompts. */ + +int minibuffer_append_messages; + Lisp_Object Vglobal_mode_string; /* Marker for where to display an arrow on top of the buffer text. */ @@ -5752,6 +5763,142 @@ } +/* 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 (append) + 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 (minibuffer_append_messages && 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; +} + + +/* Return the message displayed in the echo area; the current + buffer should be the buffer holding the echo-area contents. + + Any interaction with `minibuffer_append_messages' is handled + correctly (just the message portion of the buffer is returned, + if a minibuffer and a message have been combined for display). */ + +static Lisp_Object +echo_area_message () +{ + if (minibuffer_append_messages && minibuf_level > 0 && !cursor_in_echo_area) + { + Lisp_Object num, minibuf; + + XSETFASTINT (num, minibuf_level); + minibuf = Fnth (num, Vminibuffer_list); + + if (BUFFERP (minibuf)) + /* Got a minibuffer. */ + { + /* The message portion of the echo-area should start + at the end of the minibuffer portion, plus 2 + characters for the intervening delimiter (" ["). */ + int beg = BUF_Z (XBUFFER (minibuf)) + 2; + /* The message portion of the echo-area should end + one character before the end of the current buffer + (it's followed by "]"). */ + int end = Z - 1; + + /* Make sure our numbers are not messed up, and if + they aren't, return the message portion of the + current buffer. */ + if (beg < end + && FETCH_BYTE (CHAR_TO_BYTE (beg - 1)) == '[' + && FETCH_BYTE (Z_BYTE - 1) == ']') + return make_buffer_string (beg, end, 1); + } + } + + /* Simply return the whole buffer. */ + return make_buffer_string (BEG, Z, 1); +} + + +/* 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. @@ -5836,7 +5983,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); @@ -5928,12 +6075,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) @@ -5948,9 +6098,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)) @@ -5981,7 +6136,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; } @@ -6245,7 +6407,7 @@ Lisp_Object *msg = (Lisp_Object *) a1; if (Z > BEG) - *msg = make_buffer_string (BEG, Z, 1); + *msg = echo_area_message (); else *msg = Qnil; return 0; @@ -6385,6 +6547,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); @@ -6398,6 +6562,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; @@ -6452,6 +6621,12 @@ 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; } @@ -13940,6 +14115,15 @@ "Normal hook run for clicks on menu bar, before displaying a submenu.\n\ Can be used to update submenus whose contents should vary."); Vmenu_bar_update_hook = Qnil; + + DEFVAR_BOOL ("minibuffer-append-messages", &minibuffer_append_messages, + "If non-nil, messages are appended to active minibuffers, inside brackets.\n\ +If nil, messages replace active minibuffers in the echo-area temporarily.\n\ +\n\ +An exception to this rule is that if `cursor-in-echo-area' is non-nil,\n\ +messages always use the whole echo-area; this is because such messages\n\ +are usually prompts."); + minibuffer_append_messages = 1; } @@ -13994,5 +14178,3 @@ help_echo_showing_p = 0; } - - 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/16 06:19:04 @@ -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; Index: src/dispnew.c =================================================================== RCS file: /cvs/emacs/src/dispnew.c,v retrieving revision 1.242 diff -u -r1.242 dispnew.c --- src/dispnew.c 2000/11/16 00:53:28 1.242 +++ src/dispnew.c 2000/11/16 06:19:01 @@ -1,5 +1,5 @@ /* Updating of data structures for redisplay. - Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 1999 + Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 1999, 2000 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -247,6 +247,7 @@ Lisp_Object Qdisplay_table, Qredisplay_dont_pause; +extern int minibuffer_append_messages; /* defined in xdisp.c */ /* The currently selected frame. In a single-frame version, this variable always equals the_only_frame. */ @@ -4800,7 +4801,8 @@ /* If we are showing a message instead of the mini-buffer, show the cursor for the message instead of for the (now hidden) mini-buffer contents. */ - || (EQ (minibuf_window, selected_window) + || (!minibuffer_append_messages + && EQ (minibuf_window, selected_window) && EQ (minibuf_window, echo_area_window) && !NILP (echo_area_buffer[0]))) /* These cases apply only to the frame that contains Index: src/lisp.h =================================================================== RCS file: /cvs/emacs/src/lisp.h,v retrieving revision 1.345 diff -u -r1.345 lisp.h --- src/lisp.h 2000/11/15 19:24:35 1.345 +++ src/lisp.h 2000/11/16 06:19:03 @@ -2123,7 +2123,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));