Commit 6de3804e authored by Chong Yidong's avatar Chong Yidong
Browse files

(Vtruncate_partial_width_windows): New Lisp_Object, replacing

truncate_partial_width_windows.
(init_iterator): If Vtruncate_partial_width_windows is an integer,
truncate only if the window width is below that integer.
(start_display. resize_mini_window, produce_stretch_glyph)
(display_string, move_it_in_display_line_to): Use line_wrap.
(back_to_previous_visible_line_start, reseat_1): Reset
string_from_display_prop_p.
(display_line): Extend default face to end of line when wrapping.
(display_line, move_it_in_display_line_to): Add ability
to wrap continued lines at word boundaries.
parent 81b6a665
......@@ -420,7 +420,7 @@ static struct buffer *this_line_buffer;
/* Nonzero means truncate lines in all windows less wide than the
frame. */
 
int truncate_partial_width_windows;
Lisp_Object Vtruncate_partial_width_windows;
 
/* A flag to control how to display unibyte 8-bit character. */
 
......@@ -2634,19 +2634,27 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
it->tab_width = 8;
 
/* Are lines in the display truncated? */
it->truncate_lines_p
= (base_face_id != DEFAULT_FACE_ID
|| XINT (it->w->hscroll)
|| (truncate_partial_width_windows
&& !WINDOW_FULL_WIDTH_P (it->w))
|| !NILP (current_buffer->truncate_lines));
if (base_face_id != DEFAULT_FACE_ID
|| XINT (it->w->hscroll)
|| (! WINDOW_FULL_WIDTH_P (it->w)
&& ((!NILP (Vtruncate_partial_width_windows)
&& !INTEGERP (Vtruncate_partial_width_windows))
|| (INTEGERP (Vtruncate_partial_width_windows)
&& (WINDOW_TOTAL_COLS (it->w)
< XINT (Vtruncate_partial_width_windows))))))
it->line_wrap = TRUNCATE;
else if (NILP (current_buffer->truncate_lines))
it->line_wrap = NILP (current_buffer->word_wrap)
? WINDOW_WRAP : WORD_WRAP;
else
it->line_wrap = TRUNCATE;
 
/* Get dimensions of truncation and continuation glyphs. These are
displayed as fringe bitmaps under X, so we don't need them for such
frames. */
if (!FRAME_WINDOW_P (it->f))
{
if (it->truncate_lines_p)
if (it->line_wrap == TRUNCATE)
{
/* We will need the truncation glyph. */
xassert (it->glyph_row == NULL);
......@@ -2696,7 +2704,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
for window-based redisplay. */
if (!FRAME_WINDOW_P (it->f))
{
if (it->truncate_lines_p)
if (it->line_wrap == TRUNCATE)
it->last_visible_x -= it->truncation_pixel_width;
else
it->last_visible_x -= it->continuation_pixel_width;
......@@ -2769,7 +2777,7 @@ start_display (it, w, pos)
 
/* Don't reseat to previous visible line start if current start
position is in a string or image. */
if (it->method == GET_FROM_BUFFER && !it->truncate_lines_p)
if (it->method == GET_FROM_BUFFER && it->line_wrap != TRUNCATE)
{
int start_at_line_beg_p;
int first_y = it->current_y;
......@@ -2794,7 +2802,7 @@ start_display (it, w, pos)
taken us to the start of the continuation line but to the
end of the continued line. */
if (it->current_x > 0
&& !it->truncate_lines_p /* Lines are continued. */
&& it->line_wrap != TRUNCATE /* Lines are continued. */
&& (/* And glyph doesn't fit on the line. */
new_x > it->last_visible_x
/* Or it fits exactly and we're on a window
......@@ -5432,6 +5440,7 @@ back_to_previous_visible_line_start (it)
pos = --IT_CHARPOS (it2);
--IT_BYTEPOS (it2);
it2.sp = 0;
it2.string_from_display_prop_p = 0;
if (handle_display_prop (&it2) == HANDLED_RETURN
&& !NILP (val = get_char_property_and_overlay
(make_number (pos), Qdisplay, Qnil, &overlay))
......@@ -5582,6 +5591,7 @@ reseat_1 (it, pos, set_stop_p)
IT_STRING_CHARPOS (*it) = -1;
IT_STRING_BYTEPOS (*it) = -1;
it->string = Qnil;
it->string_from_display_prop_p = 0;
it->method = GET_FROM_BUFFER;
it->object = it->w->buffer;
it->area = TEXT_AREA;
......@@ -6643,11 +6653,20 @@ move_it_in_display_line_to (struct it *it,
{
enum move_it_result result = MOVE_UNDEFINED;
struct glyph_row *saved_glyph_row;
struct it wrap_it, atpos_it;
int may_wrap = 0;
 
/* Don't produce glyphs in produce_glyphs. */
saved_glyph_row = it->glyph_row;
it->glyph_row = NULL;
 
/* Use wrap_it to save a copy of IT wherever a word wrap could
occur. Use atpos_it to save a copy of IT at the desired
position, if found, so that we can scan ahead and check if the
word later overshoots the window edge. */
wrap_it.sp = -1;
atpos_it.sp = -1;
#define BUFFER_POS_REACHED_P() \
((op & MOVE_TO_POS) != 0 \
&& BUFFERP (it->object) \
......@@ -6667,36 +6686,77 @@ move_it_in_display_line_to (struct it *it,
&& it->method == GET_FROM_BUFFER
&& IT_CHARPOS (*it) > to_charpos)
{
result = MOVE_POS_MATCH_OR_ZV;
break;
if (it->line_wrap == WORD_WRAP)
{
/* If wrap_it is valid, the current position might be in
a word that is wrapped to the next line, so continue
to see if that happens. */
if (wrap_it.sp < 0)
{
result = MOVE_POS_MATCH_OR_ZV;
break;
}
if (atpos_it.sp < 0)
atpos_it = *it;
}
else
{
result = MOVE_POS_MATCH_OR_ZV;
break;
}
}
 
/* Stop when ZV reached.
We used to stop here when TO_CHARPOS reached as well, but that is
too soon if this glyph does not fit on this line. So we handle it
explicitly below. */
if (!get_next_display_element (it)
|| (it->truncate_lines_p
&& BUFFER_POS_REACHED_P ()))
if (!get_next_display_element (it))
{
result = MOVE_POS_MATCH_OR_ZV;
break;
}
 
/* The call to produce_glyphs will get the metrics of the
display element IT is loaded with. We record in x the
x-position before this display element in case it does not
fit on the line. */
x = it->current_x;
/* Remember the line height so far in case the next element doesn't
fit on the line. */
if (!it->truncate_lines_p)
if (it->line_wrap == TRUNCATE)
{
if (BUFFER_POS_REACHED_P ())
{
result = MOVE_POS_MATCH_OR_ZV;
break;
}
}
else
{
/* Remember the line height so far in case the next element
doesn't fit on the line. */
ascent = it->max_ascent;
descent = it->max_descent;
if (it->line_wrap == WORD_WRAP)
{
if (it->what == IT_CHARACTER
&& (it->c == ' ' || it->c == '\t'))
may_wrap = 1;
else if (may_wrap)
{
/* We are done if the position is already found. */
if (atpos_it.sp >= 0)
{
*it = atpos_it;
atpos_it.sp = -1;
goto buffer_pos_reached;
}
wrap_it = *it;
may_wrap = 0;
}
}
}
 
/* The call to produce_glyphs will get the metrics of the
display element IT is loaded with. Record the x-position
before this display element, in case it doesn't fit on the
line. */
x = it->current_x;
PRODUCE_GLYPHS (it);
 
if (it->area != TEXT_AREA)
......@@ -6740,19 +6800,30 @@ move_it_in_display_line_to (struct it *it,
if ((op & MOVE_TO_X) && new_x > to_x)
{
if (BUFFER_POS_REACHED_P ())
goto buffer_pos_reached;
{
if (it->line_wrap == WORD_WRAP)
{
if (wrap_it.sp < 0)
goto buffer_pos_reached;
if (atpos_it.sp < 0)
atpos_it = *it;
}
else
goto buffer_pos_reached;
}
it->current_x = x;
result = MOVE_X_REACHED;
break;
}
else if (/* Lines are continued. */
!it->truncate_lines_p
&& (/* And glyph doesn't fit on the line. */
new_x > it->last_visible_x
/* Or it fits exactly and we're on a window
system frame. */
|| (new_x == it->last_visible_x
&& FRAME_WINDOW_P (it->f))))
if (/* Lines are continued. */
it->line_wrap != TRUNCATE
&& (/* And glyph doesn't fit on the line. */
new_x > it->last_visible_x
/* Or it fits exactly and we're on a window
system frame. */
|| (new_x == it->last_visible_x
&& FRAME_WINDOW_P (it->f))))
{
if (/* IT->hpos == 0 means the very first glyph
doesn't fit on the line, e.g. a wide image. */
......@@ -6811,24 +6882,37 @@ move_it_in_display_line_to (struct it *it,
it->max_descent = descent;
}
 
if (wrap_it.sp >= 0)
{
*it = wrap_it;
atpos_it.sp = -1;
}
TRACE_MOVE ((stderr, "move_it_in: continued at %d\n",
IT_CHARPOS (*it)));
result = MOVE_LINE_CONTINUED;
break;
}
else if (BUFFER_POS_REACHED_P ())
goto buffer_pos_reached;
else if (new_x > it->first_visible_x)
if (BUFFER_POS_REACHED_P ())
{
if (it->line_wrap == WORD_WRAP)
{
if (wrap_it.sp < 0)
goto buffer_pos_reached;
if (atpos_it.sp < 0)
atpos_it = *it;
}
else
goto buffer_pos_reached;
}
if (new_x > it->first_visible_x)
{
/* Glyph is visible. Increment number of glyphs that
would be displayed. */
++it->hpos;
}
else
{
/* Glyph is completely off the left margin of the display
area. Nothing to do. */
}
}
 
if (result != MOVE_UNDEFINED)
......@@ -6867,7 +6951,7 @@ move_it_in_display_line_to (struct it *it,
 
/* Stop if lines are truncated and IT's current x-position is
past the right edge of the window now. */
if (it->truncate_lines_p
if (it->line_wrap == TRUNCATE
&& it->current_x >= it->last_visible_x)
{
#ifdef HAVE_WINDOW_SYSTEM
......@@ -6893,6 +6977,11 @@ move_it_in_display_line_to (struct it *it,
 
#undef BUFFER_POS_REACHED_P
 
/* If we scanned beyond to_pos and didn't find a point to wrap at,
return iterator at to_pos. */
if (atpos_it.sp >= 0)
*it = atpos_it;
/* Restore the iterator settings altered at the beginning of this
function. */
it->glyph_row = saved_glyph_row;
......@@ -8555,7 +8644,7 @@ resize_mini_window (w, exact_p)
max_height = min (total_height, max_height);
 
/* Find out the height of the text in the window. */
if (it.truncate_lines_p)
if (it.line_wrap == TRUNCATE)
height = 1;
else
{
......@@ -15997,7 +16086,8 @@ extend_face_to_end_of_line (it)
&& it->glyph_row->displays_text_p
&& face->box == FACE_NO_BOX
&& face->background == FRAME_BACKGROUND_PIXEL (f)
&& !face->stipple)
&& !face->stipple
&& it->line_wrap != WORD_WRAP)
return;
 
/* Set the glyph row flag indicating that the face of the last glyph
......@@ -16212,6 +16302,11 @@ display_line (it)
{
struct glyph_row *row = it->glyph_row;
Lisp_Object overlay_arrow_string;
struct it wrap_it;
int may_wrap = 0, wrap_x;
int wrap_row_used = -1, wrap_row_ascent, wrap_row_height;
int wrap_row_phys_ascent, wrap_row_phys_height;
int wrap_row_extra_line_spacing;
 
/* We always start displaying at hpos zero even if hscrolled. */
xassert (it->hpos == 0 && it->current_x == 0);
......@@ -16306,12 +16401,31 @@ display_line (it)
 
/* Remember the line height so far in case the next element doesn't
fit on the line. */
if (!it->truncate_lines_p)
if (it->line_wrap != TRUNCATE)
{
ascent = it->max_ascent;
descent = it->max_descent;
phys_ascent = it->max_phys_ascent;
phys_descent = it->max_phys_descent;
if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
{
if (it->what == IT_CHARACTER
&& (it->c == ' ' || it->c == '\t'))
may_wrap = 1;
else if (may_wrap)
{
wrap_it = *it;
wrap_x = x;
wrap_row_used = row->used[TEXT_AREA];
wrap_row_ascent = row->ascent;
wrap_row_height = row->height;
wrap_row_phys_ascent = row->phys_ascent;
wrap_row_phys_height = row->phys_height;
wrap_row_extra_line_spacing = row->extra_line_spacing;
may_wrap = 0;
}
}
}
 
PRODUCE_GLYPHS (it);
......@@ -16371,7 +16485,7 @@ display_line (it)
new_x = x + glyph->pixel_width;
 
if (/* Lines are continued. */
!it->truncate_lines_p
it->line_wrap != TRUNCATE
&& (/* Glyph doesn't fit on the line. */
new_x > it->last_visible_x
/* Or it fits exactly on a window system frame. */
......@@ -16412,6 +16526,8 @@ display_line (it)
}
}
#endif /* HAVE_WINDOW_SYSTEM */
if (wrap_row_used > 0)
goto back_to_wrap;
}
}
else if (CHAR_GLYPH_PADDING_P (*glyph)
......@@ -16439,6 +16555,26 @@ display_line (it)
it->max_phys_ascent = phys_ascent;
it->max_phys_descent = phys_descent;
}
else if (wrap_row_used > 0)
{
back_to_wrap:
*it = wrap_it;
it->continuation_lines_width += wrap_x;
row->used[TEXT_AREA] = wrap_row_used;
row->ascent = wrap_row_ascent;
row->height = wrap_row_height;
row->phys_ascent = wrap_row_phys_ascent;
row->phys_height = wrap_row_phys_height;
row->extra_line_spacing = wrap_row_extra_line_spacing;
row->continued_p = 1;
row->ends_at_zv_p = 0;
row->exact_window_width_line_p = 0;
it->continuation_lines_width += x;
/* Make sure that a non-default face is extended
up to the right margin of the window. */
extend_face_to_end_of_line (it);
}
else if (it->c == '\t' && FRAME_WINDOW_P (it->f))
{
/* A TAB that extends past the right edge of the
......@@ -16554,7 +16690,7 @@ display_line (it)
 
/* If we truncate lines, we are done when the last displayed
glyphs reach past the right margin of the window. */
if (it->truncate_lines_p
if (it->line_wrap == TRUNCATE
&& (FRAME_WINDOW_P (it->f)
? (it->current_x >= it->last_visible_x)
: (it->current_x > it->last_visible_x)))
......@@ -18579,7 +18715,7 @@ display_string (string, lisp_string, face_string, face_string_pos,
{
struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
 
if (!it->truncate_lines_p
if (it->line_wrap != TRUNCATE
&& x + glyph->pixel_width > max_x)
{
/* End of continued line or max_x reached. */
......@@ -18635,7 +18771,7 @@ display_string (string, lisp_string, face_string, face_string_pos,
set_iterator_to_next (it, 1);
 
/* Stop if truncating at the right edge. */
if (it->truncate_lines_p
if (it->line_wrap == TRUNCATE
&& it->current_x >= it->last_visible_x)
{
/* Add truncation mark, but don't do it if the line is
......@@ -20583,7 +20719,7 @@ produce_stretch_glyph (it)
else
ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
 
if (width > 0 && !it->truncate_lines_p
if (width > 0 && it->line_wrap != TRUNCATE
&& it->current_x + width > it->last_visible_x)
width = it->last_visible_x - it->current_x - 1;
 
......@@ -24538,11 +24674,18 @@ Value is a number or a cons (WIDTH-DPI . HEIGHT-DPI). */);
DEFVAR_INT ("debug-end-pos", &debug_end_pos, doc: /* Don't ask. */);
#endif
 
DEFVAR_BOOL ("truncate-partial-width-windows",
&truncate_partial_width_windows,
doc: /* *Non-nil means truncate lines in all windows less than full frame wide.
DEFVAR_LISP ("truncate-partial-width-windows",
&Vtruncate_partial_width_windows,
doc: /* Non-nil means truncate lines in windows with less than the frame width.
For an integer value, truncate lines in each window with less than the
full frame width, provided the window width is less than that integer;
otherwise, respect the value of `truncate-lines'.
For any other non-nil value, truncate lines in all windows with
less than the full frame width.
Nil means to respect the value of `truncate-lines'. */);
truncate_partial_width_windows = 1;
Vtruncate_partial_width_windows = make_number (30);
 
DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
doc: /* When nil, display the mode-line/header-line/menu-bar in the default face.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment