Fix selection updating, avoid overlapping selections
This commit is contained in:
parent
8d9ed5e8c7
commit
f7e89bc9f8
|
@ -71,6 +71,9 @@ static bool compare_selections(const Selection& lhs, const Selection& rhs)
|
||||||
template<typename Iterator, typename OverlapsFunc>
|
template<typename Iterator, typename OverlapsFunc>
|
||||||
Iterator merge_overlapping(Iterator begin, Iterator end, size_t& main, OverlapsFunc overlaps)
|
Iterator merge_overlapping(Iterator begin, Iterator end, size_t& main, OverlapsFunc overlaps)
|
||||||
{
|
{
|
||||||
|
if (begin == end)
|
||||||
|
return begin;
|
||||||
|
|
||||||
kak_assert(std::is_sorted(begin, end, compare_selections));
|
kak_assert(std::is_sorted(begin, end, compare_selections));
|
||||||
size_t size = end - begin;
|
size_t size = end - begin;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
@ -148,17 +151,27 @@ bool relevant(const Buffer::Change& change, ByteCoord coord)
|
||||||
: change.begin < coord;
|
: change.begin < coord;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool forward_sorted(const Buffer::Change& lhs, const Buffer::Change& rhs)
|
const Buffer::Change* forward_sorted_until(const Buffer::Change* first, const Buffer::Change* last)
|
||||||
{
|
{
|
||||||
return lhs.begin < rhs.begin;
|
return std::is_sorted_until(first, last,
|
||||||
|
[](const Buffer::Change& lhs, const Buffer::Change& rhs)
|
||||||
|
{ return lhs.begin < rhs.begin; });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool backward_sorted(const Buffer::Change& lhs, const Buffer::Change& rhs)
|
const Buffer::Change* backward_sorted_until(const Buffer::Change* first, const Buffer::Change* last)
|
||||||
{
|
{
|
||||||
return lhs.begin > rhs.end;
|
if (first != last) {
|
||||||
|
const Buffer::Change* next = first;
|
||||||
|
while (++next != last) {
|
||||||
|
if (next->end >= first->begin)
|
||||||
|
return next;
|
||||||
|
first = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return last;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_forward(memoryview<Buffer::Change> changes, std::vector<Selection>& selections)
|
void update_forward(memoryview<Buffer::Change> changes, std::vector<Selection>& selections, size_t& main)
|
||||||
{
|
{
|
||||||
PositionChangesTracker changes_tracker;
|
PositionChangesTracker changes_tracker;
|
||||||
|
|
||||||
|
@ -179,9 +192,12 @@ void update_forward(memoryview<Buffer::Change> changes, std::vector<Selection>&
|
||||||
advance_while_relevant(sel_max);
|
advance_while_relevant(sel_max);
|
||||||
sel_max = changes_tracker.get_new_coord(sel_max);
|
sel_max = changes_tracker.get_new_coord(sel_max);
|
||||||
}
|
}
|
||||||
|
selections.erase(merge_overlapping(selections.begin(), selections.end(), main, overlaps),
|
||||||
|
selections.end());
|
||||||
|
kak_assert(std::is_sorted(selections.begin(), selections.end(), compare_selections));
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_backward(memoryview<Buffer::Change> changes, std::vector<Selection>& selections)
|
void update_backward(memoryview<Buffer::Change> changes, std::vector<Selection>& selections, size_t& main)
|
||||||
{
|
{
|
||||||
PositionChangesTracker changes_tracker;
|
PositionChangesTracker changes_tracker;
|
||||||
|
|
||||||
|
@ -211,6 +227,9 @@ void update_backward(memoryview<Buffer::Change> changes, std::vector<Selection>&
|
||||||
advance_while_relevant(sel_max);
|
advance_while_relevant(sel_max);
|
||||||
sel_max = changes_tracker.get_new_coord(sel_max);
|
sel_max = changes_tracker.get_new_coord(sel_max);
|
||||||
}
|
}
|
||||||
|
selections.erase(merge_overlapping(selections.begin(), selections.end(), main, overlaps),
|
||||||
|
selections.end());
|
||||||
|
kak_assert(std::is_sorted(selections.begin(), selections.end(), compare_selections));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -222,13 +241,15 @@ std::vector<Selection> compute_modified_ranges(Buffer& buffer, size_t timestamp)
|
||||||
auto change_it = changes.begin();
|
auto change_it = changes.begin();
|
||||||
while (change_it != changes.end())
|
while (change_it != changes.end())
|
||||||
{
|
{
|
||||||
auto forward_end = std::is_sorted_until(change_it, changes.end(), forward_sorted);
|
auto forward_end = forward_sorted_until(change_it, changes.end());
|
||||||
auto backward_end = std::is_sorted_until(change_it, changes.end(), backward_sorted);
|
auto backward_end = backward_sorted_until(change_it, changes.end());
|
||||||
|
|
||||||
size_t prev_size = ranges.size();
|
size_t prev_size;
|
||||||
|
size_t dummy = 0;
|
||||||
if (forward_end >= backward_end)
|
if (forward_end >= backward_end)
|
||||||
{
|
{
|
||||||
update_forward({ change_it, forward_end }, ranges);
|
update_forward({ change_it, forward_end }, ranges, dummy);
|
||||||
|
prev_size = ranges.size();
|
||||||
|
|
||||||
PositionChangesTracker changes_tracker;
|
PositionChangesTracker changes_tracker;
|
||||||
for (; change_it != forward_end; ++change_it)
|
for (; change_it != forward_end; ++change_it)
|
||||||
|
@ -242,7 +263,8 @@ std::vector<Selection> compute_modified_ranges(Buffer& buffer, size_t timestamp)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
update_backward({ change_it, backward_end }, ranges);
|
update_backward({ change_it, backward_end }, ranges, dummy);
|
||||||
|
prev_size = ranges.size();
|
||||||
|
|
||||||
using ReverseIt = std::reverse_iterator<const Buffer::Change*>;
|
using ReverseIt = std::reverse_iterator<const Buffer::Change*>;
|
||||||
PositionChangesTracker changes_tracker;
|
PositionChangesTracker changes_tracker;
|
||||||
|
@ -258,7 +280,6 @@ std::vector<Selection> compute_modified_ranges(Buffer& buffer, size_t timestamp)
|
||||||
change_it = backward_end;
|
change_it = backward_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
kak_assert(std::is_sorted(ranges.begin(), ranges.begin() + prev_size, compare_selections));
|
|
||||||
kak_assert(std::is_sorted(ranges.begin() + prev_size, ranges.end(), compare_selections));
|
kak_assert(std::is_sorted(ranges.begin() + prev_size, ranges.end(), compare_selections));
|
||||||
std::inplace_merge(ranges.begin(), ranges.begin() + prev_size, ranges.end(), compare_selections);
|
std::inplace_merge(ranges.begin(), ranges.begin() + prev_size, ranges.end(), compare_selections);
|
||||||
}
|
}
|
||||||
|
@ -291,17 +312,17 @@ void SelectionList::update()
|
||||||
auto change_it = changes.begin();
|
auto change_it = changes.begin();
|
||||||
while (change_it != changes.end())
|
while (change_it != changes.end())
|
||||||
{
|
{
|
||||||
auto forward_end = std::is_sorted_until(change_it, changes.end(), forward_sorted);
|
auto forward_end = forward_sorted_until(change_it, changes.end());
|
||||||
auto backward_end = std::is_sorted_until(change_it, changes.end(), backward_sorted);
|
auto backward_end = backward_sorted_until(change_it, changes.end());
|
||||||
|
|
||||||
if (forward_end >= backward_end)
|
if (forward_end >= backward_end)
|
||||||
{
|
{
|
||||||
update_forward({ change_it, forward_end }, m_selections);
|
update_forward({ change_it, forward_end }, m_selections, m_main);
|
||||||
change_it = forward_end;
|
change_it = forward_end;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
update_backward({ change_it, backward_end }, m_selections);
|
update_backward({ change_it, backward_end }, m_selections, m_main);
|
||||||
change_it = backward_end;
|
change_it = backward_end;
|
||||||
}
|
}
|
||||||
kak_assert(std::is_sorted(m_selections.begin(), m_selections.end(),
|
kak_assert(std::is_sorted(m_selections.begin(), m_selections.end(),
|
||||||
|
|
Loading…
Reference in New Issue
Block a user