X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/010a899e5a1750cd6a23198b868134f1091f9842..bab29e15c4971e03f6ef00e35ac7ccb53bf92193:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index 7384985dbc..cc65fff9ae 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -1,5 +1,6 @@ /* Display generation from window structure and buffer text. - Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc. + Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 1997 + Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -113,6 +114,11 @@ Lisp_Object Voverlay_arrow_position; /* String to display for the arrow. */ Lisp_Object Voverlay_arrow_string; +/* Values of those variables at last redisplay. + However, if Voverlay_arrow_position is a marker, + last_arrow_position is its numerical position. */ +static Lisp_Object last_arrow_position, last_arrow_string; + /* Like mode-line-format, but for the titlebar on a visible frame. */ Lisp_Object Vframe_title_format; @@ -124,9 +130,6 @@ Lisp_Object Vicon_title_format; have changed. */ static Lisp_Object Vwindow_size_change_functions; -/* Values of those variables at last redisplay. */ -static Lisp_Object last_arrow_position, last_arrow_string; - Lisp_Object Qmenu_bar_update_hook; /* Nonzero if overlay arrow has been displayed once in this window. */ @@ -152,6 +155,10 @@ static int scroll_conservatively; of the top or bottom of the window. */ int scroll_margin; +/* Number of characters of overlap to show, + when scrolling a one-line window such as a minibuffer. */ +static int minibuffer_scroll_overlap; + /* Nonzero if try_window_id has made blank lines at window bottom since the last redisplay that paused */ static int blank_end_of_window; @@ -210,6 +217,10 @@ int echo_area_glyphs_length; same window currently active as a minibuffer. */ Lisp_Object echo_area_window; +/* Nonzero means multibyte characters were enabled when the echo area + message was specified. */ +int message_enable_multibyte; + /* true iff we should redraw the mode lines on the next redisplay */ int update_mode_lines; @@ -246,6 +257,9 @@ static int line_number_display_limit; /* Number of lines to keep in the message log buffer. t means infinite. nil means don't log at all. */ Lisp_Object Vmessage_log_max; + +#define COERCE_MARKER(X) \ + (MARKERP ((X)) ? Fmarker_position (X) : (X)) /* Output a newline in the *Messages* buffer if "needs" one. */ @@ -271,6 +285,8 @@ message_dolog (m, len, nlflag) struct buffer *oldbuf; int oldpoint, oldbegv, oldzv; int old_windows_or_buffers_changed = windows_or_buffers_changed; + int point_at_end = 0; + int zv_at_end = 0; oldbuf = current_buffer; Fset_buffer (Fget_buffer_create (build_string ("*Messages*"))); @@ -281,12 +297,48 @@ message_dolog (m, len, nlflag) BEGV = BEG; ZV = Z; if (oldpoint == Z) - oldpoint += len + nlflag; + point_at_end = 1; if (oldzv == Z) - oldzv += len + nlflag; + zv_at_end = 1; TEMP_SET_PT (Z); - if (len) + + /* Insert the string--maybe converting multibyte to single byte + or vice versa, so that all the text fits the buffer. */ + if (! NILP (oldbuf->enable_multibyte_characters) + && NILP (current_buffer->enable_multibyte_characters)) + { + int c, i = 0, nbytes; + /* Convert a multibyte string to single-byte + for the *Message* buffer. */ + while (i < len) + { + c = STRING_CHAR (m + i, len - i); + i += XFASTINT (Fchar_bytes (make_number (c))); + /* Truncate the character to its last byte--we can only hope + the user is happy with the character he gets, + since if it isn't right, there is no way to do it right. */ + c &= 0xff; + insert_char (c); + } + } + else if (NILP (oldbuf->enable_multibyte_characters) + && ! NILP (current_buffer->enable_multibyte_characters)) + { + int c, i = 0; + /* Convert a single-byte string to multibyte + for the *Message* buffer. */ + while (i < len) + { + c = m[i++]; + /* Convert non-ascii chars as if for self-insert. */ + if (c >= 0200 && c <= 0377) + c += nonascii_insert_offset; + insert_char (c); + } + } + else if (len) insert_1 (m, len, 1, 0); + if (nlflag) { int this_bol, prev_bol, dup; @@ -336,8 +388,14 @@ message_dolog (m, len, nlflag) } } BEGV = oldbegv; - ZV = oldzv; - TEMP_SET_PT (oldpoint); + if (zv_at_end) + ZV = Z; + else + ZV = oldzv; + if (point_at_end) + TEMP_SET_PT (Z); + else + TEMP_SET_PT (oldpoint); set_buffer_internal (oldbuf); windows_or_buffers_changed = old_windows_or_buffers_changed; message_log_need_newline = !nlflag; @@ -412,12 +470,16 @@ message2_nolog (m, len) char *m; int len; { + message_enable_multibyte + = ! NILP (current_buffer->enable_multibyte_characters); + if (noninteractive) { if (noninteractive_need_newline) putc ('\n', stderr); noninteractive_need_newline = 0; - fwrite (m, len, 1, stderr); + if (m) + fwrite (m, len, 1, stderr); if (cursor_in_echo_area == 0) fprintf (stderr, "\n"); fflush (stderr); @@ -545,10 +607,10 @@ message (m, a1, a2, a3) { int len; #ifdef NO_ARG_ARRAY - EMACS_INT a[3]; - a[0] = a1; - a[1] = a2; - a[2] = a3; + char *a[3]; + a[0] = (char *) a1; + a[1] = (char *) a2; + a[2] = (char *) a3; len = doprnt (FRAME_MESSAGE_BUF (f), FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a); @@ -628,7 +690,9 @@ echo_area_display () echo_area_glyphs ? echo_area_glyphs : "", echo_area_glyphs ? echo_area_glyphs_length : -1, FRAME_LEFT_SCROLL_BAR_WIDTH (f), - 0, 0, 0, FRAME_WIDTH (f)); + 0, 0, 0, + FRAME_WIDTH (f) + FRAME_LEFT_SCROLL_BAR_WIDTH (f), + message_enable_multibyte); #if 0 /* This just gets in the way. update_frame does the job. */ /* If desired cursor location is on this line, put it at end of text */ @@ -646,10 +710,14 @@ echo_area_display () i < vpos + XFASTINT (XWINDOW (mini_window)->height); i++) { get_display_line (f, i, 0); - display_string (XWINDOW (mini_window), vpos, + /* We don't use FRAME_SCROLL_BAR_WIDTH (f) as the starting + hpos, because it is good to clear whatever is behind the + scroll bar. This does not affect the scroll bar itself. */ + display_string (XWINDOW (mini_window), i, "", 0, - FRAME_LEFT_SCROLL_BAR_WIDTH (f), - 0, 0, 0, FRAME_WIDTH (f)); + 0, 0, 0, + 0, FRAME_WIDTH (f) + FRAME_SCROLL_BAR_WIDTH (f), + 0); } } } @@ -864,6 +932,7 @@ redisplay_internal (preserve_echo_area) int all_windows; register int tlbufpos, tlendpos; struct position pos; + int number_of_visible_frames; if (noninteractive) return; @@ -873,6 +942,8 @@ redisplay_internal (preserve_echo_area) return; #endif + retry: + if (! FRAME_WINDOW_P (selected_frame) && previous_terminal_frame != selected_frame) { @@ -891,10 +962,15 @@ redisplay_internal (preserve_echo_area) { Lisp_Object tail, frame; + number_of_visible_frames = 0; + FOR_EACH_FRAME (tail, frame) { FRAME_SAMPLE_VISIBILITY (XFRAME (frame)); + if (FRAME_VISIBLE_P (XFRAME (frame))) + number_of_visible_frames++; + /* Clear out all the display lines in which we will generate the glyphs to display. */ init_desired_glyphs (XFRAME (frame)); @@ -939,7 +1015,7 @@ redisplay_internal (preserve_echo_area) /* If specs for an arrow have changed, do thorough redisplay to ensure we remove any arrow that should no longer exist. */ - if (! EQ (Voverlay_arrow_position, last_arrow_position) + if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position) || ! EQ (Voverlay_arrow_string, last_arrow_string)) all_windows = 1; @@ -967,6 +1043,7 @@ redisplay_internal (preserve_echo_area) if (!all_windows && tlbufpos > 0 && NILP (w->update_mode_line) && !current_buffer->clip_changed && FRAME_VISIBLE_P (XFRAME (w->frame)) + && !FRAME_OBSCURED_P (XFRAME (w->frame)) /* Make sure recorded data applies to current buffer, etc */ && this_line_buffer == current_buffer && current_buffer == XBUFFER (w->buffer) @@ -1086,7 +1163,8 @@ redisplay_internal (preserve_echo_area) then we can't just move the cursor. */ else if (! (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active)) - && w == XWINDOW (current_buffer->last_selected_window) + && (w == XWINDOW (current_buffer->last_selected_window) + || highlight_nonselected_windows) && NILP (w->region_showing) && !cursor_in_echo_area) { @@ -1147,7 +1225,7 @@ redisplay_internal (preserve_echo_area) if (condemn_scroll_bars_hook) (*condemn_scroll_bars_hook) (f); - if (FRAME_VISIBLE_P (f)) + if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f)) redisplay_windows (FRAME_ROOT_WINDOW (f), preserve_echo_area); /* Any scroll bars which redisplay_windows should have nuked @@ -1157,7 +1235,7 @@ redisplay_internal (preserve_echo_area) } } } - else if (FRAME_VISIBLE_P (selected_frame)) + else if (FRAME_VISIBLE_P (selected_frame) && !FRAME_OBSCURED_P (selected_frame)) { redisplay_window (selected_window, 1, preserve_echo_area); if (!WINDOW_FULL_WIDTH_P (w)) @@ -1188,7 +1266,7 @@ update: f = XFRAME (XCONS (tail)->car); if ((FRAME_WINDOW_P (f) || f == selected_frame) - && FRAME_VISIBLE_P (f)) + && FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f)) { pause |= update_frame (f, 0, 0); if (!pause) @@ -1202,7 +1280,7 @@ update: } else { - if (FRAME_VISIBLE_P (selected_frame)) + if (FRAME_VISIBLE_P (selected_frame) && !FRAME_OBSCURED_P (selected_frame)) pause = update_frame (selected_frame, 0, 0); else pause = 0; @@ -1270,8 +1348,18 @@ update: w->last_had_star = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer)) ? Qt : Qnil); + + /* Record if we are showing a region, so can make sure to + update it fully at next redisplay. */ + w->region_showing = (!NILP (Vtransient_mark_mode) + && (w == XWINDOW (current_buffer->last_selected_window) + || highlight_nonselected_windows) + && !NILP (XBUFFER (w->buffer)->mark_active) + ? Fmarker_position (XBUFFER (w->buffer)->mark) + : Qnil); + w->window_end_valid = w->buffer; - last_arrow_position = Voverlay_arrow_position; + last_arrow_position = COERCE_MARKER (Voverlay_arrow_position); last_arrow_string = Voverlay_arrow_string; if (do_verify_charstarts) verify_charstarts (w); @@ -1293,13 +1381,38 @@ update: request_sigio (); start_polling (); + /* If something has become visible now which was not before, + redisplay again, so that we get them. */ + if (!pause) + { + Lisp_Object tail, frame; + int new_count = 0; + + FOR_EACH_FRAME (tail, frame) + { + int this_is_visible = 0; + + if (XFRAME (frame)->visible) + this_is_visible = 1; + FRAME_SAMPLE_VISIBILITY (XFRAME (frame)); + if (XFRAME (frame)->visible) + this_is_visible = 1; + + if (this_is_visible) + new_count++; + } + + if (new_count != number_of_visible_frames) + windows_or_buffers_changed++; + } + /* Change frame size now if a change is pending. */ do_pending_window_change (); - /* If we just did a pending size change, redisplay again - for the new size. */ + /* If we just did a pending size change, or have additional + visible frames, redisplay again. */ if (windows_or_buffers_changed && !pause) - redisplay (); + goto retry; } /* Redisplay, but leave alone any recent echo area message @@ -1310,6 +1423,7 @@ update: area to be cleared. See tracking_off and wait_reading_process_input for examples of these situations. */ +void redisplay_preserve_echo_area () { if (echo_area_glyphs == 0 && previous_echo_glyphs != 0) @@ -1347,7 +1461,8 @@ mark_window_display_accurate (window, flag) /* Record if we are showing a region, so can make sure to update it fully at next redisplay. */ w->region_showing = (!NILP (Vtransient_mark_mode) - && w == XWINDOW (current_buffer->last_selected_window) + && (w == XWINDOW (current_buffer->last_selected_window) + || highlight_nonselected_windows) && !NILP (XBUFFER (w->buffer)->mark_active) ? Fmarker_position (XBUFFER (w->buffer)->mark) : Qnil); @@ -1366,7 +1481,7 @@ mark_window_display_accurate (window, flag) if (flag) { - last_arrow_position = Voverlay_arrow_position; + last_arrow_position = COERCE_MARKER (Voverlay_arrow_position); last_arrow_string = Voverlay_arrow_string; } else @@ -1476,6 +1591,43 @@ redisplay_windows (window, preserve_echo_area) redisplay_window (window, 0, preserve_echo_area); } +/* Return value in display table DP (Lisp_Char_Table *) for character + C. Since a display table doesn't have any parent, we don't have to + follow parent. Do not call this function directly but use the + macro DISP_CHAR_VECTOR. */ +Lisp_Object +disp_char_vector (dp, c) + struct Lisp_Char_Table *dp; + int c; +{ + int code[4], i; + Lisp_Object val; + + if (SINGLE_BYTE_CHAR_P (c)) return (dp->contents[c]); + + SPLIT_NON_ASCII_CHAR (c, code[0], code[1], code[2]); + if (code[0] != CHARSET_COMPOSITION) + { + if (code[1] < 32) code[1] = -1; + else if (code[2] < 32) code[2] = -1; + } + /* Here, the possible range of CODE[0] (== charset ID) is + 128..MAX_CHARSET. Since the top level char table contains data + for multibyte characters after 256th element, we must increment + CODE[0] by 128 to get a correct index. */ + code[0] += 128; + code[3] = -1; /* anchor */ + + for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val)) + { + val = dp->contents[code[i]]; + if (!SUB_CHAR_TABLE_P (val)) + return (NILP (val) ? dp->defalt : val); + } + /* Here, VAL is a sub char table. We return the default value of it. */ + return (dp->defalt); +} + /* Redisplay window WINDOW and its subwindows. */ static void @@ -1536,7 +1688,7 @@ redisplay_window (window, just_this_one, preserve_echo_area) get_display_line (f, vpos + i, 0); display_string (w, vpos + i, "", 0, FRAME_LEFT_SCROLL_BAR_WIDTH (f), - 0, 1, 0, width); + 0, 1, 0, width, 0); } goto finish_scroll_bars; @@ -1741,17 +1893,51 @@ redisplay_window (window, just_this_one, preserve_echo_area) /* If end pos is out of date, scroll bar and percentage will be wrong */ && INTEGERP (w->window_end_vpos) && XFASTINT (w->window_end_vpos) < XFASTINT (w->height) - && !EQ (window, minibuf_window)) + && !EQ (window, minibuf_window) + && (!MARKERP (Voverlay_arrow_position) + || current_buffer != XMARKER (Voverlay_arrow_position)->buffer)) { + /* All positions in this clause are relative to the window edge. */ + int this_scroll_margin = scroll_margin; + int last_point_y = XFASTINT (w->last_point_y) - XINT (w->top); + int last_point_x = (XFASTINT (w->last_point_x) - WINDOW_LEFT_MARGIN (w)); - pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), 0, - PT, height, - /* BUG FIX: See the comment of - Fpos_visible_in_window_p (window.c). */ - - (1 << (BITS_PER_SHORT - 1)), - width, hscroll, - pos_tab_offset (w, startp), w); + /* Find where PT is located now on the frame. */ + /* Check just_this_one as a way of verifying that the + window edges have not changed. */ + if (PT == XFASTINT (w->last_point) && just_this_one) + { + pos.hpos = last_point_x; + pos.vpos = last_point_y; + pos.bufpos = PT; + } + else if (PT > XFASTINT (w->last_point) + && XFASTINT (w->last_point) > startp && just_this_one + /* We can't use this if point is in the left margin of a + hscrolled window, because w->last_point_x has been + clipped to the window edges. */ + && !(last_point_x <= 0 && hscroll)) + { + pos = *compute_motion (XFASTINT (w->last_point), + last_point_y, last_point_x, 0, + PT, height, + /* BUG FIX: See the comment of + Fpos_visible_in_window_p (window.c). */ + - (1 << (BITS_PER_SHORT - 1)), + width, hscroll, + pos_tab_offset (w, startp), w); + } + else + { + pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), 0, + PT, height, + /* BUG FIX: See the comment of + Fpos_visible_in_window_p (window.c). */ + - (1 << (BITS_PER_SHORT - 1)), + width, hscroll, + pos_tab_offset (w, startp), w); + } /* Don't use a scroll margin that is negative or too large. */ if (this_scroll_margin < 0) @@ -1780,6 +1966,11 @@ redisplay_window (window, just_this_one, preserve_echo_area) if (WINDOW_FULL_WIDTH_P (w)) preserve_my_columns (w); */ + if (current_buffer->clip_changed + && ! NILP (Vwindow_scroll_functions)) + run_hook_with_args_2 (Qwindow_scroll_functions, window, + make_number (marker_position (w->start))); + goto done; } /* Don't bother trying redisplay with same start; @@ -1809,7 +2000,7 @@ redisplay_window (window, just_this_one, preserve_echo_area) doesn't display as the end of a line. */ && !(dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, '\n'))) && NILP (w->region_showing) - && EQ (last_arrow_position, Voverlay_arrow_position) + && EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position)) && EQ (last_arrow_string, Voverlay_arrow_string) && (tem = try_window_id (FRAME_SELECTED_WINDOW (f))) && tem != -2) @@ -1844,6 +2035,12 @@ redisplay_window (window, just_this_one, preserve_echo_area) || beg_unchanged < startp) /* Forget any recorded base line for line number display. */ w->base_line_number = Qnil; + + if (current_buffer->clip_changed + && ! NILP (Vwindow_scroll_functions)) + run_hook_with_args_2 (Qwindow_scroll_functions, window, + make_number (marker_position (w->start))); + goto done; } else @@ -1867,25 +2064,32 @@ redisplay_window (window, just_this_one, preserve_echo_area) && startp >= BEGV && startp <= ZV) { int this_scroll_margin = scroll_margin; + int scroll_margin_pos; /* Don't use a scroll margin that is negative or too large. */ if (this_scroll_margin < 0) this_scroll_margin = 0; - if (XINT (w->height) < 4 * scroll_margin) + if (XINT (w->height) < 4 * this_scroll_margin) this_scroll_margin = XINT (w->height) / 4; - if (PT >= Z - XFASTINT (w->window_end_pos)) + scroll_margin_pos = Z - XFASTINT (w->window_end_pos); + if (this_scroll_margin) + { + pos = *vmotion (scroll_margin_pos, -this_scroll_margin, w); + scroll_margin_pos = pos.bufpos; + } + if (PT >= scroll_margin_pos) { struct position pos; - pos = *compute_motion (Z - XFASTINT (w->window_end_pos), 0, 0, 0, + pos = *compute_motion (scroll_margin_pos, 0, 0, 0, PT, XFASTINT (w->height), 0, XFASTINT (w->width), XFASTINT (w->hscroll), pos_tab_offset (w, startp), w); if (pos.vpos > scroll_conservatively) goto scroll_fail_1; - pos = *vmotion (startp, pos.vpos + 1 + this_scroll_margin, w); + pos = *vmotion (startp, pos.vpos + 1, w); if (! NILP (Vwindow_scroll_functions)) { @@ -1906,17 +2110,24 @@ redisplay_window (window, just_this_one, preserve_echo_area) else cancel_my_columns (w); } - if (PT < startp) + + scroll_margin_pos = startp; + if (this_scroll_margin) + { + pos = *vmotion (scroll_margin_pos, this_scroll_margin, w); + scroll_margin_pos = pos.bufpos; + } + if (PT < scroll_margin_pos) { struct position pos; pos = *compute_motion (PT, 0, 0, 0, - startp, XFASTINT (w->height), 0, + scroll_margin_pos, XFASTINT (w->height), 0, XFASTINT (w->width), XFASTINT (w->hscroll), pos_tab_offset (w, startp), w); - if (pos.vpos >= scroll_conservatively) + if (pos.vpos > scroll_conservatively) goto scroll_fail_1; - pos = *vmotion (startp, - pos.vpos - this_scroll_margin, w); + pos = *vmotion (startp, -pos.vpos, w); if (! NILP (Vwindow_scroll_functions)) { @@ -1983,6 +2194,20 @@ recenter: w->base_line_number = Qnil; pos = *vmotion (PT, - (height / 2), w); + + /* The minibuffer is often just one line. Ordinary scrolling + gives little overlap and looks bad. So show 20 chars before point. */ + if (height == 1 + && (pos.bufpos >= PT - minibuffer_scroll_overlap + /* If we scrolled less than 1/2 line forward, we will + get too much overlap, so change to the usual amount. */ + || pos.bufpos < startp + width / 2) + && PT > BEGV + minibuffer_scroll_overlap + /* If we scrolled to an actual line boundary, + that's different; don't ignore line boundaries. */ + && FETCH_CHAR (pos.bufpos - 1) != '\n') + pos.bufpos = PT - minibuffer_scroll_overlap; + /* Set startp here explicitly in case that helps avoid an infinite loop in case the window-scroll-functions functions get errors. */ Fset_marker (w->start, make_number (pos.bufpos), Qnil); @@ -2617,8 +2842,13 @@ copy_part_of_rope (f, to, s, from, len, face) if (! FRAME_TERMCAP_P (f)) while (n--) { - int glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0); + GLYPH glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0); int facecode; + unsigned int c = FAST_GLYPH_CHAR (glyph); + + if (c > MAX_CHAR) + /* For an invalid character code, use space. */ + c = ' '; if (FAST_GLYPH_FACE (glyph) == 0) /* If GLYPH has no face code, use FACE. */ @@ -2634,7 +2864,7 @@ copy_part_of_rope (f, to, s, from, len, face) } if (to >= s) - *to = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), facecode); + *to = FAST_MAKE_GLYPH (c, facecode); ++to; ++fp; } @@ -2728,10 +2958,10 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done) && !WINDOW_FULL_WIDTH_P (w)) || !NILP (current_buffer->truncate_lines)); - /* 1 if we should highlight the region. */ + /* 1 if this buffer has a region to highlight. */ int highlight_region = (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active) - && XWINDOW (current_buffer->last_selected_window) == w); + && XMARKER (current_buffer->mark)->buffer != 0); int region_beg, region_end; int selective = (INTEGERP (current_buffer->selective_display) @@ -2757,8 +2987,10 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done) : default_invis_vector); GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp)) + || !GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (dp))) ? '$' : XINT (DISP_TRUNC_GLYPH (dp))); GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp)) + || !GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (dp))) ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp))); /* If 1, we must handle multibyte characters. */ @@ -2785,15 +3017,16 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done) XSETFASTINT (default_invis_vector[2], '.'); default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2]; - hpos += WINDOW_LEFT_MARGIN (w); get_display_line (f, vpos, WINDOW_LEFT_MARGIN (w)); if (tab_width <= 0 || tab_width > 1000) tab_width = 8; /* Show where to highlight the region. */ - if (highlight_region && XMARKER (current_buffer->mark)->buffer != 0 + if (highlight_region /* Maybe highlight only in selected window. */ && (highlight_nonselected_windows - || w == XWINDOW (selected_window))) + || w == XWINDOW (selected_window) + || (MINI_WINDOW_P (XWINDOW (selected_window)) + && w == XWINDOW (Vminibuf_scroll_window)))) { region_beg = marker_position (current_buffer->mark); if (PT < region_beg) @@ -2806,7 +3039,10 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done) w->region_showing = Qt; } else - region_beg = region_end = -1; + { + region_beg = region_end = -1; + w->region_showing = Qnil; + } if (MINI_WINDOW_P (w) && start == BEG @@ -2814,19 +3050,24 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done) { if (! NILP (minibuf_prompt)) { + int old_width = minibuf_prompt_width; + minibuf_prompt_width = (display_string (w, vpos, XSTRING (minibuf_prompt)->data, - XSTRING (minibuf_prompt)->size, hpos, + XSTRING (minibuf_prompt)->size, + hpos + WINDOW_LEFT_MARGIN (w), /* Display a space if we truncate. */ ' ', 1, -1, /* Truncate the prompt a little before the margin, so user input can at least start on the first line. */ - w->width > 10 ? w->width - 4 : -1) - - hpos); + (XFASTINT (w->width) > 10 + ? XFASTINT (w->width) - 4 : -1), + -1) + - hpos - WINDOW_LEFT_MARGIN (w)); hpos += minibuf_prompt_width; - taboffset -= minibuf_prompt_width; + taboffset -= minibuf_prompt_width - old_width; } else minibuf_prompt_width = 0; @@ -2866,6 +3107,8 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done) } } + hpos += WINDOW_LEFT_MARGIN (w); + desired_glyphs->bufp[vpos] = start; p1 = desired_glyphs->glyphs[vpos] + hpos; p1start = p1; @@ -2891,7 +3134,17 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done) next_boundary = pos; p1prev = p1; prevpos = pos; - while (1) + + /* If the window is hscrolled and point is in the invisible part of the + current line beyond the left margin we can record the cursor location + right away. */ + if (hscroll && start <= PT && PT < pos && cursor_vpos < 0) + { + cursor_vpos = vpos; + cursor_hpos = p1 - leftmargin; + } + + while (p1 < endp) { if (pos >= pause) { @@ -3113,6 +3366,12 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done) } else if (c == '\n') { +#if 0 + /* Same as p1prev, but after the invis_vector_contents text + (if we have that on this line). */ + GLYPH *p1prev_modified; +#endif + invis = 0; if (last_invis_skip == pos && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop)) @@ -3128,23 +3387,30 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done) } if (invis && selective_rlen > 0 && p1 >= leftmargin) { +#if 0 + GLYPH *cs, *csend; + + cs = charstart + (p1 - p1start); +#endif + p1 += selective_rlen; if (p1 - leftmargin > width) p1 = endp; + +#if 0 /* This needs more work; charstarts needs to record + both whether a position ho;ds an ellipsis character + and what buffer position it corresponds to. */ + csend = charstart + (p1 - p1start); + while (cs != csend) + *cs++ = -2; + /* The idea is to use p1prev_modified instead of p1prev + in the loop below over p2x. */ + p1prev_modified = p1; +#endif + copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents, (p1 - p1prev), current_face, rev_dir_bit); } -#ifdef HAVE_FACES - /* Draw the face of the newline character as extending all the - way to the end of the frame line. */ - if (current_face) - { - if (p1 < leftmargin) - p1 = leftmargin; - while (p1 < endp) - *p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit; - } -#endif /* Update charstarts for the newline that ended this line. */ /* Do nothing here for a char that's entirely off the left edge @@ -3163,6 +3429,17 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done) while (p2x < p2) *p2x++ = -1; } +#ifdef HAVE_FACES + /* Draw the face of the newline character as extending all the + way to the end of the frame line. */ + if (current_face) + { + if (p1 < leftmargin) + p1 = leftmargin; + while (p1 < endp) + *p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit; + } +#endif break; } @@ -3224,9 +3501,11 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done) else if (c < 0200 && ctl_arrow) { if (p1 >= leftmargin) - *p1 = (fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp)) - ? XINT (DISP_CTRL_GLYPH (dp)) : '^'), - current_face) + *p1 = (fix_glyph + (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp)) + && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp))) + ? XINT (DISP_CTRL_GLYPH (dp)) : '^'), + current_face) | rev_dir_bit); p1++; if (p1 >= leftmargin && p1 < endp) @@ -3237,9 +3516,11 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done) { /* C is not a multibyte character. */ if (p1 >= leftmargin) - *p1 = (fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp)) - ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'), - current_face) + *p1 = (fix_glyph + (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp)) + && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp))) + ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'), + current_face) | rev_dir_bit); p1++; if (p1 >= leftmargin && p1 < endp) @@ -3443,7 +3724,7 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done) this_line_bufpos = start; this_line_buffer = current_buffer; this_line_vpos = cursor_vpos; - this_line_start_hpos = hpos; + this_line_start_hpos = hpos - WINDOW_LEFT_MARGIN (w); this_line_endpos = Z - lastpos; } else @@ -3485,7 +3766,7 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done) } else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)) *p1++ = (dp && INTEGERP (DISP_BORDER_GLYPH (dp)) - ? DISP_BORDER_GLYPH (dp) + ? XINT (DISP_BORDER_GLYPH (dp)) : '|'); } desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos], @@ -3554,7 +3835,7 @@ display_menu_bar (w) Lisp_Object items, tail; register int vpos = 0; register FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); - int maxendcol = FRAME_WIDTH (f); + int maxendcol = FRAME_WIDTH (f) + WINDOW_LEFT_MARGIN (w); int hpos = 0; int i; @@ -3581,16 +3862,16 @@ display_menu_bar (w) XSETFASTINT (XVECTOR (items)->contents[i + 3], hpos); if (hpos < maxendcol) - hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos, + hpos = display_string (w, vpos, XSTRING (string)->data, XSTRING (string)->size, - hpos, 0, 0, hpos, maxendcol); + hpos, 0, 0, hpos, maxendcol, -1); /* Put a space between items. */ if (hpos < maxendcol) { int hpos1 = hpos + 1; hpos = display_string (w, vpos, "", 0, hpos, 0, 0, - min (hpos1, maxendcol), maxendcol); + min (hpos1, maxendcol), maxendcol, 0); } } @@ -3599,7 +3880,7 @@ display_menu_bar (w) /* Fill out the line with spaces. */ if (maxendcol > hpos) - hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol); + hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol, 0); /* Clear the rest of the lines allocated to the menu bar. */ vpos++; @@ -3724,7 +4005,7 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) hpos = store_frame_title (last, hpos, min (lim, maxendcol)); else hpos = display_string (w, vpos, last, -1, hpos, 0, 1, - hpos, min (lim, maxendcol)); + hpos, min (lim, maxendcol), -1); } else /* c == '%' */ { @@ -3761,7 +4042,7 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) else hpos = display_string (w, vpos, spec, -1, hpos, 0, 1, - minendcol, maxendcol); + minendcol, maxendcol, -1); } } } @@ -3789,7 +4070,7 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) else hpos = display_string (w, vpos, XSTRING (tem)->data, XSTRING (tem)->size, - hpos, 0, 1, minendcol, maxendcol); + hpos, 0, 1, minendcol, maxendcol, -1); } /* Give up right away for nil or t. */ else if (!EQ (tem, elt)) @@ -3883,7 +4164,7 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) hpos = store_frame_title ("*invalid*", minendcol, maxendcol); else hpos = display_string (w, vpos, "*invalid*", -1, hpos, 0, 1, - minendcol, maxendcol); + minendcol, maxendcol, 0); return hpos; } @@ -3891,7 +4172,8 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) if (frame_title_ptr) hpos = store_frame_title ("", minendcol, maxendcol); else - hpos = display_string (w, vpos, "", 0, hpos, 0, 1, minendcol, maxendcol); + hpos = display_string (w, vpos, "", 0, hpos, + 0, 1, minendcol, maxendcol, 0); return hpos; } @@ -3934,31 +4216,53 @@ decode_mode_spec_coding (coding_system, buf, eol_flag) register char *buf; int eol_flag; { - register Lisp_Object val = coding_system; + Lisp_Object val; + int multibyte = !NILP (current_buffer->enable_multibyte_characters); + + val = coding_system; if (NILP (val)) /* Not yet decided. */ { - *buf++ = '-'; - if (eol_flag) *buf++ = eol_mnemonic_undecided; + if (multibyte) + *buf++ = '-'; + if (eol_flag) + *buf++ = eol_mnemonic_undecided; + /* Don't mention EOL conversion if it isn't decided. */ } else { + Lisp_Object eolvalue; + + eolvalue = Fget (coding_system, Qeol_type); + while (!NILP (val) && SYMBOLP (val)) - val = Fget (val, Qcoding_system); - *buf++ = XFASTINT (XVECTOR (val)->contents[1]); + { + val = Fget (val, Qcoding_system); + if (NILP (eolvalue)) + eolvalue = Fget (val, Qeol_type); + } + + if (multibyte) + *buf++ = XFASTINT (XVECTOR (val)->contents[1]); + if (eol_flag) { - val = Fget (coding_system, Qeol_type); - - if (NILP (val)) /* Not yet decided. */ - *buf++ = eol_mnemonic_undecided; - else if (VECTORP (val)) /* Not yet decided. */ - *buf++ = eol_mnemonic_undecided; - else /* INTEGERP (val) -- 1:LF, 2:CRLF, 3:CR */ - *buf++ = (XFASTINT (val) == 1 - ? eol_mnemonic_unix - : (XFASTINT (val) == 2 - ? eol_mnemonic_dos : eol_mnemonic_mac)); + /* The EOL conversion we are using. */ + int eoltype; + /* The EOL conversion that is normal on this system. */ + + if (NILP (eolvalue)) /* Not yet decided. */ + eoltype = eol_mnemonic_undecided; + else if (VECTORP (eolvalue)) /* Not yet decided. */ + eoltype = eol_mnemonic_undecided; + else /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */ + eoltype = (XFASTINT (eolvalue) == 0 + ? eol_mnemonic_unix + : (XFASTINT (eolvalue) == 1 + ? eol_mnemonic_dos : eol_mnemonic_mac)); + + /* Mention the EOL conversion if it is not the usual one. */ + *buf++ = eoltype; } } return buf; @@ -4080,7 +4384,10 @@ decode_mode_spec (w, c, spec_width, maxwidth) case 'F': /* %F displays the frame name. */ - if (!NILP (f->title)) + /* Systems that can only display a single frame at a time should + NOT replace the frame name with the (constant) frame title, + since then they won't be able to tell which frame is that. */ + if (FRAME_WINDOW_P (f) && !NILP (f->title)) return (char *) XSTRING (f->title)->data; if (f->explicit_name || ! FRAME_WINDOW_P (f)) return (char *) XSTRING (f->name)->data; @@ -4293,16 +4600,19 @@ decode_mode_spec (w, c, spec_width, maxwidth) /* coding-system (including end-of-line type) */ { int eol_flag = (c == 'Z'); - char *p; + char *p = decode_mode_spec_buf; - p = decode_mode_spec_coding - (find_symbol_value (Qbuffer_file_coding_system), - decode_mode_spec_buf, eol_flag); - if (FRAME_TERMCAP_P (f)) + if (! FRAME_WINDOW_P (f)) { - p = decode_mode_spec_coding (keyboard_coding.symbol, p, eol_flag); - p = decode_mode_spec_coding (terminal_coding.symbol, p, eol_flag); + /* No need to mention EOL here--the terminal never needs + to do EOL conversion. */ + p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0); + p = decode_mode_spec_coding (terminal_coding.symbol, p, 0); } + p = decode_mode_spec_coding (b->buffer_file_coding_system, + p, eol_flag); + +#if 0 /* This proves to be annoying; I think we can do without. -- rms. */ #ifdef subprocesses obj = Fget_buffer_process (Fcurrent_buffer ()); if (PROCESSP (obj)) @@ -4313,6 +4623,7 @@ decode_mode_spec (w, c, spec_width, maxwidth) p, eol_flag); } #endif /* subprocesses */ +#endif /* 0 */ *p = 0; return decode_mode_spec_buf; } @@ -4475,11 +4786,15 @@ display_count_lines (from, limit, n, pos_ptr) and not display anything beyond there. Otherwise, only MAXCOL controls where to stop output. + MULTIBYTE can be 0 meaning do not display multibyte chars, + 1 meaning do display them, or -1 meaning obey the current buffer's + value of enable_multibyte_characters. + Returns ending hpos. */ static int display_string (w, vpos, string, length, hpos, truncate, - obey_window_width, mincol, maxcol) + obey_window_width, mincol, maxcol, multibyte) struct window *w; unsigned char *string; int length; @@ -4487,6 +4802,7 @@ display_string (w, vpos, string, length, hpos, truncate, GLYPH truncate; int obey_window_width; int mincol, maxcol; + int multibyte; { register int c; int truncated; @@ -4499,24 +4815,27 @@ display_string (w, vpos, string, length, hpos, truncate, struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f); GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos; int window_width = XFASTINT (w->width); - /* If 1, we must display multibyte characters. */ - int multibyte = !NILP (XBUFFER (w->buffer)->enable_multibyte_characters); /* Use the standard display table, not the window's display table. We don't want the mode line in rot13. */ register struct Lisp_Char_Table *dp = 0; int i; + if (multibyte == -1) + multibyte = !NILP (current_buffer->enable_multibyte_characters); + /* Now multibyte is 1 if we should display multibyte characters. */ + if (DISP_TABLE_P (Vstandard_display_table)) dp = XCHAR_TABLE (Vstandard_display_table); if (tab_width <= 0 || tab_width > 1000) tab_width = 8; p1 = p1start; - start = desired_glyphs->glyphs[vpos] + XFASTINT (w->left); + start = desired_glyphs->glyphs[vpos]; if (obey_window_width) { + start += XFASTINT (w->left); end = start + window_width - (truncate != 0); if (!WINDOW_RIGHTMOST_P (w)) @@ -4596,9 +4915,11 @@ display_string (w, vpos, string, length, hpos, truncate, else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow)) { if (p1 >= start) - *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp)) - ? XINT (DISP_CTRL_GLYPH (dp)) : '^'), - 0); + *p1 = (fix_glyph + (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp)) + && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp))) + ? XINT (DISP_CTRL_GLYPH (dp)) : '^'), + 0)); p1++; if (p1 >= start && p1 < end) *p1 = c ^ 0100; @@ -4608,9 +4929,11 @@ display_string (w, vpos, string, length, hpos, truncate, { /* C is a control character or a binary byte data. */ if (p1 >= start) - *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp)) - ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'), - 0); + *p1 = (fix_glyph + (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp)) + && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp))) + ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'), + 0)); p1++; if (p1 >= start && p1 < end) *p1 = (c >> 6) + '0'; @@ -4838,7 +5161,7 @@ of the top or bottom of the window."); DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows, "*Non-nil means highlight region even in nonselected windows."); - highlight_nonselected_windows = 1; + highlight_nonselected_windows = 0; DEFVAR_BOOL ("multiple-frames", &multiple_frames, "Non-nil if more than one frame is visible on this display.\n\ @@ -4884,11 +5207,16 @@ all the functions in the list are called, with the frame as argument."); Vwindow_size_change_functions = Qnil; DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions, - "List of Functions to call before redisplaying a window with scrolling.\n\ + "List of functions to call before redisplaying a window with scrolling.\n\ Each function is called with two arguments, the window\n\ and its new display-start position. Note that the value of `window-end'\n\ is not valid when these functions are called."); Vwindow_scroll_functions = Qnil; + + DEFVAR_INT ("minibuffer-scroll-overlap", &minibuffer_scroll_overlap, + "*Number of characters of overlap when scrolling a one-line window.\n\ +This commonly affects the minibuffer window, hence the name of the variable."); + minibuffer_scroll_overlap = 20; } /* initialize the window system */ @@ -4911,8 +5239,10 @@ init_xdisp () if (!noninteractive) { FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window))); - XSETFASTINT (XWINDOW (root_window)->top, 0); - set_window_height (root_window, FRAME_HEIGHT (f) - 1, 0); + XSETFASTINT (XWINDOW (root_window)->top, FRAME_MENU_BAR_LINES (f)); + set_window_height (root_window, + FRAME_HEIGHT (f) - 1 - FRAME_MENU_BAR_LINES (f), + 0); XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1); set_window_height (minibuf_window, 1, 0);