e2f6b9a393
A change that ended exactly where the previous one started was not considered backward sorted. Leading to some very bad performances in certain cases, like '100000o<esc>u'
98 lines
2.6 KiB
C++
98 lines
2.6 KiB
C++
#include "changes.hh"
|
|
|
|
namespace Kakoune
|
|
{
|
|
void ForwardChangesTracker::update(const Buffer::Change& change)
|
|
{
|
|
kak_assert(change.begin >= cur_pos);
|
|
|
|
if (change.type == Buffer::Change::Insert)
|
|
{
|
|
old_pos = get_old_coord(change.begin);
|
|
cur_pos = change.end;
|
|
}
|
|
else if (change.type == Buffer::Change::Erase)
|
|
{
|
|
old_pos = get_old_coord(change.end);
|
|
cur_pos = change.begin;
|
|
}
|
|
}
|
|
|
|
void ForwardChangesTracker::update(const Buffer& buffer, size_t& timestamp)
|
|
{
|
|
for (auto& change : buffer.changes_since(timestamp))
|
|
update(change);
|
|
timestamp = buffer.timestamp();
|
|
}
|
|
|
|
BufferCoord ForwardChangesTracker::get_old_coord(BufferCoord coord) const
|
|
{
|
|
kak_assert(cur_pos <= coord);
|
|
auto pos_change = cur_pos - old_pos;
|
|
if (cur_pos.line == coord.line)
|
|
{
|
|
kak_assert(pos_change.column <= coord.column);
|
|
coord.column -= pos_change.column;
|
|
}
|
|
coord.line -= pos_change.line;
|
|
kak_assert(old_pos <= coord);
|
|
return coord;
|
|
}
|
|
|
|
BufferCoord ForwardChangesTracker::get_new_coord(BufferCoord coord) const
|
|
{
|
|
kak_assert(old_pos <= coord);
|
|
auto pos_change = cur_pos - old_pos;
|
|
if (old_pos.line == coord.line)
|
|
{
|
|
kak_assert(-pos_change.column <= coord.column);
|
|
coord.column += pos_change.column;
|
|
}
|
|
coord.line += pos_change.line;
|
|
kak_assert(cur_pos <= coord);
|
|
return coord;
|
|
}
|
|
|
|
BufferCoord ForwardChangesTracker::get_new_coord_tolerant(BufferCoord coord) const
|
|
{
|
|
if (coord < old_pos)
|
|
return cur_pos;
|
|
return get_new_coord(coord);
|
|
}
|
|
|
|
bool ForwardChangesTracker::relevant(const Buffer::Change& change, BufferCoord old_coord) const
|
|
{
|
|
auto new_coord = get_new_coord_tolerant(old_coord);
|
|
return change.type == Buffer::Change::Insert ? change.begin <= new_coord
|
|
: change.begin < new_coord;
|
|
}
|
|
|
|
const Buffer::Change* forward_sorted_until(const Buffer::Change* first, const Buffer::Change* last)
|
|
{
|
|
if (first != last) {
|
|
const Buffer::Change* next = first;
|
|
while (++next != last) {
|
|
const auto& ref = first->type == Buffer::Change::Insert ? first->end : first->begin;
|
|
if (next->begin <= ref)
|
|
return next;
|
|
first = next;
|
|
}
|
|
}
|
|
return last;
|
|
}
|
|
|
|
const Buffer::Change* backward_sorted_until(const Buffer::Change* first, const Buffer::Change* last)
|
|
{
|
|
if (first != last) {
|
|
const Buffer::Change* next = first;
|
|
while (++next != last) {
|
|
if (first->begin < next->end)
|
|
return next;
|
|
first = next;
|
|
}
|
|
}
|
|
return last;
|
|
}
|
|
|
|
}
|