Wrap: rework logic to avoid infinite loop with multiple wrap highlighters

The display is still going to be wrong, as wrapping is going to take place
multiple times, but Kakoune should not freeze anymore.
This commit is contained in:
Maxime Coste 2017-11-03 19:30:31 +08:00
parent 9d6420caae
commit 400ef6d48c

View File

@ -758,10 +758,10 @@ struct WrapHighlighter : Highlighter
setup.scroll_offset.column = 0; setup.scroll_offset.column = 0;
setup.full_lines = true; setup.full_lines = true;
const LineCount win_height = context.window().dimensions().line;
LineCount win_line = 0; LineCount win_line = 0;
for (auto buf_line = setup.window_pos.line; for (auto buf_line = setup.window_pos.line;
buf_line < setup.window_pos.line + setup.window_range.line; buf_line < setup.window_pos.line + setup.window_range.line or
buf_line <= cursor.line;
++buf_line) ++buf_line)
{ {
if (buf_line >= buffer.line_count()) if (buf_line >= buffer.line_count())
@ -774,36 +774,32 @@ struct WrapHighlighter : Highlighter
const auto wrap_count = line_wrap_count(buf_line, indent); const auto wrap_count = line_wrap_count(buf_line, indent);
setup.window_range.line -= wrap_count; setup.window_range.line -= wrap_count;
if (win_line < setup.cursor_pos.line) if (buf_line == cursor.line)
setup.cursor_pos.line += wrap_count;
// Place the cursor correctly after its line gets wrapped
else if (win_line == setup.cursor_pos.line)
{ {
BufferCoord coord{buf_line}; BufferCoord coord{buf_line};
while (true) for (LineCount count = 0; true; ++count)
{ {
auto split_coord = next_split_coord(buffer, wrap_column - (coord.column == 0 ? 0_col : indent), auto split_coord = next_split_coord(buffer, wrap_column - (coord.column == 0 ? 0_col : indent),
tabstop, coord); tabstop, coord);
if (split_coord.column > cursor.column) if (split_coord.column > cursor.column)
{ {
setup.cursor_pos.column = get_column(buffer, tabstop, cursor) - get_column(buffer, tabstop, coord); setup.cursor_pos = DisplayCoord{
if (coord.column != 0) win_line + count,
setup.cursor_pos.column += indent; get_column(buffer, tabstop, cursor) -
get_column(buffer, tabstop, coord) +
(coord.column != 0 ? indent : 0_col)
};
break; break;
} }
++setup.cursor_pos.line;
coord = split_coord; coord = split_coord;
} }
kak_assert(setup.cursor_pos.column >= 0 and setup.cursor_pos.column < setup.window_range.column); kak_assert(setup.cursor_pos.column >= 0 and setup.cursor_pos.column < setup.window_range.column);
if (setup.cursor_pos.line >= win_height) // In that case we will remove some lines from the top
setup.cursor_pos.line = win_height - 1;
} }
win_line += wrap_count + 1; win_line += wrap_count + 1;
// scroll window to keep cursor visible, and update range as lines gets removed // scroll window to keep cursor visible, and update range as lines gets removed
while (setup.window_pos.line < cursor.line and while (setup.window_pos.line < cursor.line and
setup.cursor_pos.line >= win_height - setup.scroll_offset.line) cursor.line + setup.scroll_offset.line >= setup.window_pos.line + setup.window_range.line)
{ {
auto removed_lines = 1 + line_wrap_count(setup.window_pos.line++, indent); auto removed_lines = 1 + line_wrap_count(setup.window_pos.line++, indent);
setup.cursor_pos.line -= removed_lines; setup.cursor_pos.line -= removed_lines;
@ -826,14 +822,14 @@ struct WrapHighlighter : Highlighter
auto column = get_column(buffer, tabstop, coord); auto column = get_column(buffer, tabstop, coord);
auto col = get_byte_to_column( auto col = get_byte_to_column(
buffer, tabstop, {coord.line, column + wrap_column}); buffer, tabstop, {coord.line, column + wrap_column});
StringView line = buffer[coord.line];
if (col == coord.column) // Can happen if we try to wrap on a tab char if (col == coord.column) // Can happen if we try to wrap on a tab char
col = buffer.char_next(coord).column; col = line.byte_count_to(line.char_count_to(coord.column)+1);
BufferCoord split_coord{coord.line, col}; BufferCoord split_coord{coord.line, col};
if (m_word_wrap) if (m_word_wrap)
{ {
StringView line = buffer[coord.line];
utf8::iterator<const char*> it{&line[col], line}; utf8::iterator<const char*> it{&line[col], line};
while (it != line.end() and it != line.begin() and is_word<WORD>(*it)) while (it != line.end() and it != line.begin() and is_word<WORD>(*it))
--it; --it;