summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2018-06-03 21:08:45 +1000
committerMaxime Coste <mawww@kakoune.org>2018-07-05 07:54:28 +1000
commit124a5d49059c1eb8ade653ef35ca9595041fc249 (patch)
tree941010800dd29aed6a3af4a3e642ef6e56ea4b93 /src
parented123a2cc90c56b18669ea99ff5da49f3650eaae (diff)
Tolerate restoring invalid coordinates from register
Clamp those selection after updating them to the current timestamp Fixes #2078
Diffstat (limited to 'src')
-rw-r--r--src/normal.cc19
-rw-r--r--src/selection.cc47
-rw-r--r--src/selection.hh4
3 files changed, 50 insertions, 20 deletions
diff --git a/src/normal.cc b/src/normal.cc
index e66045a3..fb295f4d 100644
--- a/src/normal.cc
+++ b/src/normal.cc
@@ -1734,11 +1734,22 @@ SelectionList read_selections_from_register(char reg, Context& context)
const auto desc = content[0] | split<StringView>('@') | static_gather<error, 3>();
Buffer& buffer = BufferManager::instance().get_buffer(desc[0]);
const size_t timestamp = str_to_int(desc[1]);
- const size_t main = str_to_int(desc[2]);
+ size_t main = str_to_int(desc[2]);
+
+ if (timestamp > buffer.timestamp())
+ throw runtime_error{"register '{}' refers to an invalid timestamp"};
auto sels = content | skip(1) | transform(selection_from_string) | gather<Vector<Selection>>();
+ sort_selections(sels, main);
+ merge_overlapping_selections(sels, main);
+ if (timestamp < buffer.timestamp())
+ update_selections(sels, main, buffer, timestamp);
+ else
+ clamp_selections(sels, buffer);
- return {SelectionList::UnsortedTag{}, buffer, std::move(sels), timestamp, main};
+ SelectionList res{buffer, std::move(sels)};
+ res.set_main_index(main);
+ return res;
}
enum class CombineOp
@@ -2012,9 +2023,7 @@ void move_cursor(Context& context, NormalParams params)
sel.anchor() = mode == SelectMode::Extend ? sel.anchor() : cursor;
sel.cursor() = cursor;
}
- selections.sort();
-
- selections.merge_overlapping();
+ selections.sort_and_merge_overlapping();
}
void select_whole_buffer(Context& context, NormalParams)
diff --git a/src/selection.cc b/src/selection.cc
index 02358fea..c8ab543b 100644
--- a/src/selection.cc
+++ b/src/selection.cc
@@ -212,6 +212,12 @@ static void clamp(Selection& sel, const Buffer& buffer)
sel.cursor() = buffer.clamp(sel.cursor());
}
+void clamp_selections(Vector<Selection>& selections, const Buffer& buffer)
+{
+ for (auto& sel : selections)
+ clamp(sel, buffer);
+}
+
void update_selections(Vector<Selection>& selections, size_t& main, Buffer& buffer, size_t timestamp)
{
if (timestamp == buffer.timestamp())
@@ -286,30 +292,41 @@ void SelectionList::check_invariant() const
#endif
}
-void SelectionList::sort()
+void sort_selections(Vector<Selection>& selections, size_t& main_index)
{
- if (size() == 1)
+ if (selections.size() == 1)
return;
- const auto& main = this->main();
+ const auto& main = selections[main_index];
const auto main_begin = main.min();
- m_main = std::count_if(begin(), end(), [&](const Selection& sel) {
- auto begin = sel.min();
- if (begin == main_begin)
- return &sel < &main;
- else
- return begin < main_begin;
- });
- std::stable_sort(begin(), end(), compare_selections);
+ main_index = std::count_if(selections.begin(), selections.end(),
+ [&](const Selection& sel) {
+ auto begin = sel.min();
+ if (begin == main_begin)
+ return &sel < &main;
+ else
+ return begin < main_begin;
+ });
+ std::stable_sort(selections.begin(), selections.end(), compare_selections);
}
-void SelectionList::merge_overlapping()
+void merge_overlapping_selections(Vector<Selection>& selections, size_t& main_index)
{
- if (size() == 1)
+ if (selections.size() == 1)
return;
- m_selections.erase(Kakoune::merge_overlapping(begin(), end(),
- m_main, overlaps), end());
+ selections.erase(Kakoune::merge_overlapping(selections.begin(), selections.end(),
+ main_index, overlaps), selections.end());
+}
+
+void SelectionList::sort()
+{
+ sort_selections(m_selections, m_main);
+}
+
+void SelectionList::merge_overlapping()
+{
+ merge_overlapping_selections(m_selections, m_main);
}
void SelectionList::merge_consecutive()
diff --git a/src/selection.hh b/src/selection.hh
index 1ab93aa5..510f999b 100644
--- a/src/selection.hh
+++ b/src/selection.hh
@@ -65,6 +65,10 @@ inline bool overlaps(const Selection& lhs, const Selection& rhs)
void update_selections(Vector<Selection>& selections, size_t& main,
Buffer& buffer, size_t timestamp);
+void sort_selections(Vector<Selection>& selections, size_t& main);
+void merge_overlapping_selections(Vector<Selection>& selections, size_t& main);
+void clamp_selections(Vector<Selection>& sel, const Buffer& buffer);
+
enum class InsertMode : unsigned
{
Insert,