/* 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.
/* 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;
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. */
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;
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;
/* 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))
\f
/* Output a newline in the *Messages* buffer if "needs" one. */
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*")));
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;
}
}
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;
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);
{
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);
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 */
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);
}
}
}
int all_windows;
register int tlbufpos, tlendpos;
struct position pos;
+ int number_of_visible_frames;
if (noninteractive)
return;
return;
#endif
+ retry:
+
if (! FRAME_WINDOW_P (selected_frame)
&& previous_terminal_frame != selected_frame)
{
{
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));
/* 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;
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)
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)
{
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
}
}
}
- 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))
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)
}
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;
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);
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
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)
/* 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);
if (flag)
{
- last_arrow_position = Voverlay_arrow_position;
+ last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
last_arrow_string = Voverlay_arrow_string;
}
else
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
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;
/* 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)
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;
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)
|| 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
&& 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))
{
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))
{
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);
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. */
}
if (to >= s)
- *to = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), facecode);
+ *to = FAST_MAKE_GLYPH (c, facecode);
++to;
++fp;
}
&& !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)
: 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. */
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)
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
{
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;
}
}
+ hpos += WINDOW_LEFT_MARGIN (w);
+
desired_glyphs->bufp[vpos] = start;
p1 = desired_glyphs->glyphs[vpos] + hpos;
p1start = p1;
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)
{
}
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))
}
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
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;
}
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)
{
/* 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)
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
}
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],
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;
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);
}
}
/* 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++;
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 == '%' */
{
else
hpos = display_string (w, vpos, spec, -1,
hpos, 0, 1,
- minendcol, maxendcol);
+ minendcol, maxendcol, -1);
}
}
}
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))
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;
}
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;
}
\f
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;
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;
/* 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))
p, eol_flag);
}
#endif /* subprocesses */
+#endif /* 0 */
*p = 0;
return decode_mode_spec_buf;
}
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;
GLYPH truncate;
int obey_window_width;
int mincol, maxcol;
+ int multibyte;
{
register int c;
int truncated;
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))
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;
{
/* 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';
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\
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 */
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);