Fix selection updating, avoid overlapping selections

This commit is contained in:
Maxime Coste 2014-06-02 17:36:46 +01:00
parent 8d9ed5e8c7
commit f7e89bc9f8

View File

@ -71,6 +71,9 @@ static bool compare_selections(const Selection& lhs, const Selection& rhs)
template<typename Iterator, typename OverlapsFunc>
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));
size_t size = end - begin;
size_t i = 0;
@ -148,17 +151,27 @@ bool relevant(const Buffer::Change& change, ByteCoord 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;
@ -179,9 +192,12 @@ void update_forward(memoryview<Buffer::Change> changes, std::vector<Selection>&
advance_while_relevant(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;
@ -211,6 +227,9 @@ void update_backward(memoryview<Buffer::Change> changes, std::vector<Selection>&
advance_while_relevant(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();
while (change_it != changes.end())
{
auto forward_end = std::is_sorted_until(change_it, changes.end(), forward_sorted);
auto backward_end = std::is_sorted_until(change_it, changes.end(), backward_sorted);
auto forward_end = forward_sorted_until(change_it, changes.end());
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)
{
update_forward({ change_it, forward_end }, ranges);
update_forward({ change_it, forward_end }, ranges, dummy);
prev_size = ranges.size();
PositionChangesTracker changes_tracker;
for (; change_it != forward_end; ++change_it)
@ -242,7 +263,8 @@ std::vector<Selection> compute_modified_ranges(Buffer& buffer, size_t timestamp)
}
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*>;
PositionChangesTracker changes_tracker;
@ -258,7 +280,6 @@ std::vector<Selection> compute_modified_ranges(Buffer& buffer, size_t timestamp)
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));
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();
while (change_it != changes.end())
{
auto forward_end = std::is_sorted_until(change_it, changes.end(), forward_sorted);
auto backward_end = std::is_sorted_until(change_it, changes.end(), backward_sorted);
auto forward_end = forward_sorted_until(change_it, changes.end());
auto backward_end = backward_sorted_until(change_it, changes.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;
}
else
{
update_backward({ change_it, backward_end }, m_selections);
update_backward({ change_it, backward_end }, m_selections, m_main);
change_it = backward_end;
}
kak_assert(std::is_sorted(m_selections.begin(), m_selections.end(),