From 50924944274d43149267cd9238625e40b46bbfeb Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Tue, 9 Sep 2014 19:35:54 +0100 Subject: [PATCH] Add support for target column preservation Fixes #64 --- src/buffer.cc | 6 +++--- src/buffer.hh | 2 +- src/coord.hh | 13 +++++++++++++ src/highlighters.cc | 2 +- src/selection.hh | 6 +++--- src/selectors.hh | 6 +++++- src/window.cc | 6 +++--- src/window.hh | 2 +- 8 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/buffer.cc b/src/buffer.cc index c41d7e8a6..e22a29cbd 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -137,14 +137,14 @@ ByteCoord Buffer::offset_coord(ByteCoord coord, CharCount offset) return {coord.line, line.byte_count_to(character)}; } -ByteCoord Buffer::offset_coord(ByteCoord coord, LineCount offset) +ByteCoordAndTarget Buffer::offset_coord(ByteCoordAndTarget coord, LineCount offset) { - auto character = m_lines[coord.line].char_count_to(coord.column); + auto character = coord.target == -1 ? m_lines[coord.line].char_count_to(coord.column) : coord.target; auto line = Kakoune::clamp(coord.line + offset, 0_line, line_count()-1); auto& content = m_lines[line]; character = std::max(0_char, std::min(character, content.char_length() - 2)); - return {line, content.byte_count_to(character)}; + return {line, content.byte_count_to(character), character}; } String Buffer::string(ByteCoord begin, ByteCoord end) const diff --git a/src/buffer.hh b/src/buffer.hh index e9feff660..375b83ded 100644 --- a/src/buffer.hh +++ b/src/buffer.hh @@ -136,7 +136,7 @@ public: ByteCoord clamp(ByteCoord coord) const; ByteCoord offset_coord(ByteCoord coord, CharCount offset); - ByteCoord offset_coord(ByteCoord coord, LineCount offset); + ByteCoordAndTarget offset_coord(ByteCoordAndTarget coord, LineCount offset); const String& name() const { return m_name; } String display_name() const; diff --git a/src/coord.hh b/src/coord.hh index f60be779b..dbae50017 100644 --- a/src/coord.hh +++ b/src/coord.hh @@ -99,6 +99,19 @@ struct CharCoord : LineAndColumn : LineAndColumn(line, column) {} }; +struct ByteCoordAndTarget : ByteCoord +{ + [[gnu::always_inline]] + constexpr ByteCoordAndTarget(LineCount line = 0, ByteCount column = 0, CharCount target = -1) + : ByteCoord(line, column), target(target) {} + + [[gnu::always_inline]] + constexpr ByteCoordAndTarget(ByteCoord coord, CharCount target = -1) + : ByteCoord(coord), target(target) {} + + CharCount target; +}; + } #endif // coord_hh_INCLUDED diff --git a/src/highlighters.cc b/src/highlighters.cc index 9e3fd819b..30214c2fe 100644 --- a/src/highlighters.cc +++ b/src/highlighters.cc @@ -580,7 +580,7 @@ void highlight_selections(const Context& context, HighlightFlags flags, DisplayB auto& sel = context.selections()[i]; const bool forward = sel.anchor() <= sel.cursor(); ByteCoord begin = forward ? sel.anchor() : buffer.char_next(sel.cursor()); - ByteCoord end = forward ? sel.cursor() : buffer.char_next(sel.anchor()); + ByteCoord end = forward ? (ByteCoord)sel.cursor() : buffer.char_next(sel.anchor()); const bool primary = (i == context.selections().main_index()); Face sel_face = get_face(primary ? "PrimarySelection" : "SecondarySelection"); diff --git a/src/selection.hh b/src/selection.hh index c1db3dd65..4bd25e947 100644 --- a/src/selection.hh +++ b/src/selection.hh @@ -21,10 +21,10 @@ struct Selection void merge_with(const Selection& range); ByteCoord& anchor() { return m_anchor; } - ByteCoord& cursor() { return m_cursor; } + ByteCoordAndTarget& cursor() { return m_cursor; } const ByteCoord& anchor() const { return m_anchor; } - const ByteCoord& cursor() const { return m_cursor; } + const ByteCoordAndTarget& cursor() const { return m_cursor; } CaptureList& captures() { return m_captures; } const CaptureList& captures() const { return m_captures; } @@ -42,7 +42,7 @@ struct Selection private: ByteCoord m_anchor; - ByteCoord m_cursor; + ByteCoordAndTarget m_cursor; CaptureList m_captures; }; diff --git a/src/selectors.hh b/src/selectors.hh index c4aa42eaf..940ec222c 100644 --- a/src/selectors.hh +++ b/src/selectors.hh @@ -18,7 +18,11 @@ inline void clear_selections(SelectionList& selections) inline void flip_selections(SelectionList& selections) { for (auto& sel : selections) - std::swap(sel.anchor(), sel.cursor()); + { + ByteCoord tmp = sel.anchor(); + sel.anchor() = sel.cursor(); + sel.cursor() = tmp; + } selections.check_invariant(); } diff --git a/src/window.cc b/src/window.cc index fa6c9af9e..da2b5f066 100644 --- a/src/window.cc +++ b/src/window.cc @@ -253,7 +253,7 @@ ByteCoord Window::offset_coord(ByteCoord coord, CharCount offset) return buffer().offset_coord(coord, offset); } -ByteCoord Window::offset_coord(ByteCoord coord, LineCount offset) +ByteCoordAndTarget Window::offset_coord(ByteCoordAndTarget coord, LineCount offset) { auto line = clamp(coord.line + offset, 0_line, buffer().line_count()-1); DisplayBuffer display_buffer; @@ -267,8 +267,8 @@ ByteCoord Window::offset_coord(ByteCoord coord, LineCount offset) m_highlighters(hook_handler.context(), HighlightFlags::MoveOnly, display_buffer); m_builtin_highlighters(hook_handler.context(), HighlightFlags::MoveOnly, display_buffer); - CharCount column = find_display_column(lines[0], buffer(), coord); - return find_buffer_coord(lines[1], buffer(), column); + CharCount column = coord.target == -1 ? find_display_column(lines[0], buffer(), coord) : coord.target; + return { find_buffer_coord(lines[1], buffer(), column), column }; } void Window::on_option_changed(const Option& option) diff --git a/src/window.hh b/src/window.hh index 8552c304a..6e26c082b 100644 --- a/src/window.hh +++ b/src/window.hh @@ -51,7 +51,7 @@ public: void forget_timestamp() { m_timestamp = -1; } ByteCoord offset_coord(ByteCoord coord, CharCount offset); - ByteCoord offset_coord(ByteCoord coord, LineCount offset); + ByteCoordAndTarget offset_coord(ByteCoordAndTarget coord, LineCount offset); private: Window(const Window&) = delete;