Support codepoints of variable width

Add a ColumnCount type and use it in place of CharCount whenever
more appropriate, take column size of codepoints into account for
vertical movements and docstring wrapping.

Fixes #811
This commit is contained in:
Maxime Coste 2016-09-22 20:36:26 +01:00
parent 6e17ecfb6e
commit 35559b65dd
41 changed files with 639 additions and 540 deletions

View File

@ -161,12 +161,12 @@ void Buffer::update_display_name()
m_display_name = compact_path(m_name);
}
BufferIterator Buffer::iterator_at(ByteCoord coord) const
BufferIterator Buffer::iterator_at(BufferCoord coord) const
{
return is_end(coord) ? end() : BufferIterator(*this, clamp(coord));
}
ByteCoord Buffer::clamp(ByteCoord coord) const
BufferCoord Buffer::clamp(BufferCoord coord) const
{
coord.line = Kakoune::clamp(coord.line, 0_line, line_count() - 1);
ByteCount max_col = std::max(0_byte, m_lines[coord.line].length() - 1);
@ -174,24 +174,24 @@ ByteCoord Buffer::clamp(ByteCoord coord) const
return coord;
}
ByteCoord Buffer::offset_coord(ByteCoord coord, CharCount offset)
BufferCoord Buffer::offset_coord(BufferCoord coord, CharCount offset)
{
StringView line = m_lines[coord.line];
auto target = utf8::advance(&line[coord.column], offset < 0 ? line.begin() : line.end()-1, offset);
return {coord.line, (int)(target - line.begin())};
}
ByteCoordAndTarget Buffer::offset_coord(ByteCoordAndTarget coord, LineCount offset)
BufferCoordAndTarget Buffer::offset_coord(BufferCoordAndTarget coord, LineCount offset)
{
auto character = coord.target == -1 ? m_lines[coord.line].char_count_to(coord.column) : coord.target;
auto column = coord.target == -1 ? m_lines[coord.line].column_count_to(coord.column) : coord.target;
auto line = Kakoune::clamp(coord.line + offset, 0_line, line_count()-1);
StringView content = m_lines[line];
character = std::max(0_char, std::min(character, content.char_length() - 2));
return {line, content.byte_count_to(character), character};
column = std::max(0_col, std::min(column, content.column_length() - 2));
return {line, content.byte_count_to(column), column};
}
String Buffer::string(ByteCoord begin, ByteCoord end) const
String Buffer::string(BufferCoord begin, BufferCoord end) const
{
String res;
for (auto line = begin.line; line <= end.line and line < line_count(); ++line)
@ -213,10 +213,10 @@ struct Buffer::Modification
enum Type { Insert, Erase };
Type type;
ByteCoord coord;
BufferCoord coord;
StringDataPtr content;
Modification(Type type, ByteCoord coord, StringDataPtr content)
Modification(Type type, BufferCoord coord, StringDataPtr content)
: type(type), coord(coord), content(std::move(content)) {}
Modification inverse() const
@ -441,7 +441,7 @@ void Buffer::check_invariant() const
#endif
}
ByteCoord Buffer::do_insert(ByteCoord pos, StringView content)
BufferCoord Buffer::do_insert(BufferCoord pos, StringView content)
{
kak_assert(is_valid(pos));
@ -484,13 +484,13 @@ ByteCoord Buffer::do_insert(ByteCoord pos, StringView content)
std::make_move_iterator(new_lines.end()));
const LineCount last_line = pos.line + new_lines.size() - 1;
const ByteCoord end = ByteCoord{ last_line, m_lines[last_line].length() - suffix.length() };
const BufferCoord end = BufferCoord{ last_line, m_lines[last_line].length() - suffix.length() };
m_changes.push_back({ Change::Insert, at_end, pos, end });
return pos;
}
ByteCoord Buffer::do_erase(ByteCoord begin, ByteCoord end)
BufferCoord Buffer::do_erase(BufferCoord begin, BufferCoord end)
{
kak_assert(is_valid(begin));
kak_assert(is_valid(end));
@ -498,7 +498,7 @@ ByteCoord Buffer::do_erase(ByteCoord begin, ByteCoord end)
StringView suffix = m_lines[end.line].substr(end.column);
String new_line = prefix + suffix;
ByteCoord next;
BufferCoord next;
if (new_line.length() != 0)
{
m_lines.erase(m_lines.begin() + (int)begin.line, m_lines.begin() + (int)end.line);
@ -508,7 +508,7 @@ ByteCoord Buffer::do_erase(ByteCoord begin, ByteCoord end)
else
{
m_lines.erase(m_lines.begin() + (int)begin.line, m_lines.begin() + (int)end.line + 1);
next = is_end(begin) ? end_coord() : ByteCoord{begin.line, 0};
next = is_end(begin) ? end_coord() : BufferCoord{begin.line, 0};
}
m_changes.push_back({ Change::Erase, is_end(begin), begin, end });
@ -518,7 +518,7 @@ ByteCoord Buffer::do_erase(ByteCoord begin, ByteCoord end)
void Buffer::apply_modification(const Modification& modification)
{
StringView content = modification.content->strview();
ByteCoord coord = modification.coord;
BufferCoord coord = modification.coord;
kak_assert(is_valid(coord));
switch (modification.type)
@ -538,7 +538,7 @@ void Buffer::apply_modification(const Modification& modification)
}
}
ByteCoord Buffer::insert(ByteCoord pos, StringView content)
BufferCoord Buffer::insert(BufferCoord pos, StringView content)
{
kak_assert(is_valid(pos));
if (content.empty())
@ -558,13 +558,13 @@ ByteCoord Buffer::insert(ByteCoord pos, StringView content)
return do_insert(pos, real_content->strview());
}
ByteCoord Buffer::erase(ByteCoord begin, ByteCoord end)
BufferCoord Buffer::erase(BufferCoord begin, BufferCoord end)
{
kak_assert(is_valid(begin) and is_valid(end));
// do not erase last \n except if we erase from the start of a line, and normalize
// end coord
if (is_end(end))
end = (begin.column != 0 or begin == ByteCoord{0,0}) ? prev(end) : end_coord();
end = (begin.column != 0 or begin == BufferCoord{0,0}) ? prev(end) : end_coord();
if (begin >= end) // use >= to handle case where begin is {line_count}
return begin;
@ -575,7 +575,7 @@ ByteCoord Buffer::erase(ByteCoord begin, ByteCoord end)
return do_erase(begin, end);
}
ByteCoord Buffer::replace(ByteCoord begin, ByteCoord end, StringView content)
BufferCoord Buffer::replace(BufferCoord begin, BufferCoord end, StringView content)
{
if (not (m_flags & Flags::NoUndo))
m_current_undo_group.emplace_back(Modification::Erase, begin,
@ -613,7 +613,7 @@ void Buffer::notify_saved()
m_fs_timestamp = get_fs_timestamp(m_name);
}
ByteCoord Buffer::advance(ByteCoord coord, ByteCount count) const
BufferCoord Buffer::advance(BufferCoord coord, ByteCount count) const
{
if (count > 0)
{
@ -642,7 +642,7 @@ ByteCoord Buffer::advance(ByteCoord coord, ByteCount count) const
return coord;
}
ByteCoord Buffer::char_next(ByteCoord coord) const
BufferCoord Buffer::char_next(BufferCoord coord) const
{
if (coord.column < m_lines[coord.line].length() - 1)
{
@ -665,7 +665,7 @@ ByteCoord Buffer::char_next(ByteCoord coord) const
return coord;
}
ByteCoord Buffer::char_prev(ByteCoord coord) const
BufferCoord Buffer::char_prev(BufferCoord coord) const
{
kak_assert(is_valid(coord));
if (is_end(coord))
@ -714,7 +714,7 @@ void Buffer::run_hook_in_own_context(StringView hook_name, StringView param)
hooks().run_hook(hook_name, param, hook_handler.context());
}
ByteCoord Buffer::last_modification_coord() const
BufferCoord Buffer::last_modification_coord() const
{
if (m_history_cursor.get() == &m_history)
return {};
@ -788,13 +788,13 @@ UnitTest test_buffer{[]()
BufferIterator pos = buffer.begin();
kak_assert(*pos == 'a');
pos += 6;
kak_assert(pos.coord() == ByteCoord{0, 6});
kak_assert(pos.coord() == BufferCoord{0, 6});
++pos;
kak_assert(pos.coord() == ByteCoord{1, 0});
kak_assert(pos.coord() == BufferCoord{1, 0});
--pos;
kak_assert(pos.coord() == ByteCoord{0, 6});
kak_assert(pos.coord() == BufferCoord{0, 6});
pos += 1;
kak_assert(pos.coord() == ByteCoord{1, 0});
kak_assert(pos.coord() == BufferCoord{1, 0});
buffer.insert(pos.coord(), "tchou kanaky\n");
kak_assert(buffer.line_count() == 5);
BufferIterator pos2 = buffer.end();

View File

@ -58,7 +58,7 @@ public:
using iterator_category = std::random_access_iterator_tag;
BufferIterator() : m_buffer(nullptr) {}
BufferIterator(const Buffer& buffer, ByteCoord coord);
BufferIterator(const Buffer& buffer, BufferCoord coord);
bool operator== (const BufferIterator& iterator) const;
bool operator!= (const BufferIterator& iterator) const;
@ -83,12 +83,12 @@ public:
BufferIterator operator++ (int);
BufferIterator operator-- (int);
const ByteCoord& coord() const { return m_coord; }
const BufferCoord& coord() const { return m_coord; }
private:
SafePtr<const Buffer> m_buffer;
StringView m_line;
ByteCoord m_coord;
BufferCoord m_coord;
LineCount m_last_line;
};
@ -125,9 +125,9 @@ public:
bool set_name(String name);
void update_display_name();
ByteCoord insert(ByteCoord pos, StringView content);
ByteCoord erase(ByteCoord begin, ByteCoord end);
ByteCoord replace(ByteCoord begin, ByteCoord end, StringView content);
BufferCoord insert(BufferCoord pos, StringView content);
BufferCoord erase(BufferCoord begin, BufferCoord end);
BufferCoord replace(BufferCoord begin, BufferCoord end, StringView content);
size_t timestamp() const;
timespec fs_timestamp() const;
@ -139,24 +139,24 @@ public:
bool move_to(size_t history_id) noexcept;
size_t current_history_id() const noexcept;
String string(ByteCoord begin, ByteCoord end) const;
String string(BufferCoord begin, BufferCoord end) const;
const char& byte_at(ByteCoord c) const;
ByteCount distance(ByteCoord begin, ByteCoord end) const;
ByteCoord advance(ByteCoord coord, ByteCount count) const;
ByteCoord next(ByteCoord coord) const;
ByteCoord prev(ByteCoord coord) const;
const char& byte_at(BufferCoord c) const;
ByteCount distance(BufferCoord begin, BufferCoord end) const;
BufferCoord advance(BufferCoord coord, ByteCount count) const;
BufferCoord next(BufferCoord coord) const;
BufferCoord prev(BufferCoord coord) const;
ByteCoord char_next(ByteCoord coord) const;
ByteCoord char_prev(ByteCoord coord) const;
BufferCoord char_next(BufferCoord coord) const;
BufferCoord char_prev(BufferCoord coord) const;
ByteCoord back_coord() const;
ByteCoord end_coord() const;
BufferCoord back_coord() const;
BufferCoord end_coord() const;
bool is_valid(ByteCoord c) const;
bool is_end(ByteCoord c) const;
bool is_valid(BufferCoord c) const;
bool is_end(BufferCoord c) const;
ByteCoord last_modification_coord() const;
BufferCoord last_modification_coord() const;
BufferIterator begin() const;
BufferIterator end() const;
@ -169,13 +169,13 @@ public:
{ return m_lines.get_storage(line); }
// returns an iterator at given coordinates. clamp line_and_column
BufferIterator iterator_at(ByteCoord coord) const;
BufferIterator iterator_at(BufferCoord coord) const;
// returns nearest valid coordinates from given ones
ByteCoord clamp(ByteCoord coord) const;
BufferCoord clamp(BufferCoord coord) const;
ByteCoord offset_coord(ByteCoord coord, CharCount offset);
ByteCoordAndTarget offset_coord(ByteCoordAndTarget coord, LineCount offset);
BufferCoord offset_coord(BufferCoord coord, CharCount offset);
BufferCoordAndTarget offset_coord(BufferCoordAndTarget coord, LineCount offset);
const String& name() const { return m_name; }
const String& display_name() const { return m_display_name; }
@ -200,8 +200,8 @@ public:
enum Type : char { Insert, Erase };
Type type;
bool at_end;
ByteCoord begin;
ByteCoord end;
BufferCoord begin;
BufferCoord end;
};
ConstArrayView<Change> changes_since(size_t timestamp) const;
@ -214,8 +214,8 @@ private:
void on_option_changed(const Option& option) override;
ByteCoord do_insert(ByteCoord pos, StringView content);
ByteCoord do_erase(ByteCoord begin, ByteCoord end);
BufferCoord do_insert(BufferCoord pos, StringView content);
BufferCoord do_erase(BufferCoord begin, BufferCoord end);
struct Modification;

View File

@ -7,13 +7,13 @@ namespace Kakoune
{
[[gnu::always_inline]]
inline const char& Buffer::byte_at(ByteCoord c) const
inline const char& Buffer::byte_at(BufferCoord c) const
{
kak_assert(c.line < line_count() and c.column < m_lines[c.line].length());
return m_lines[c.line][c.column];
}
inline ByteCoord Buffer::next(ByteCoord coord) const
inline BufferCoord Buffer::next(BufferCoord coord) const
{
if (coord.column < m_lines[coord.line].length() - 1)
++coord.column;
@ -27,7 +27,7 @@ inline ByteCoord Buffer::next(ByteCoord coord) const
return coord;
}
inline ByteCoord Buffer::prev(ByteCoord coord) const
inline BufferCoord Buffer::prev(BufferCoord coord) const
{
if (coord.column == 0)
{
@ -39,7 +39,7 @@ inline ByteCoord Buffer::prev(ByteCoord coord) const
return coord;
}
inline ByteCount Buffer::distance(ByteCoord begin, ByteCoord end) const
inline ByteCount Buffer::distance(BufferCoord begin, BufferCoord end) const
{
if (begin > end)
return -distance(end, begin);
@ -53,7 +53,7 @@ inline ByteCount Buffer::distance(ByteCoord begin, ByteCoord end) const
return res;
}
inline bool Buffer::is_valid(ByteCoord c) const
inline bool Buffer::is_valid(BufferCoord c) const
{
if (c.line < 0 or c.column < 0)
return false;
@ -63,7 +63,7 @@ inline bool Buffer::is_valid(ByteCoord c) const
(c.line == line_count() and c.column == 0);
}
inline bool Buffer::is_end(ByteCoord c) const
inline bool Buffer::is_end(BufferCoord c) const
{
return c >= end_coord();
}
@ -97,18 +97,18 @@ inline ConstArrayView<Buffer::Change> Buffer::changes_since(size_t timestamp) co
return {};
}
inline ByteCoord Buffer::back_coord() const
inline BufferCoord Buffer::back_coord() const
{
return { line_count() - 1, m_lines.back().length() - 1 };
}
inline ByteCoord Buffer::end_coord() const
inline BufferCoord Buffer::end_coord() const
{
return m_lines.empty() ?
ByteCoord{0,0} : ByteCoord{ line_count() - 1, m_lines.back().length() };
BufferCoord{0,0} : BufferCoord{ line_count() - 1, m_lines.back().length() };
}
inline BufferIterator::BufferIterator(const Buffer& buffer, ByteCoord coord)
inline BufferIterator::BufferIterator(const Buffer& buffer, BufferCoord coord)
: m_buffer(&buffer), m_coord(coord),
m_line((*m_buffer)[coord.line]),
m_last_line(buffer.line_count()-1)

View File

@ -12,11 +12,11 @@
namespace Kakoune
{
CharCount get_column(const Buffer& buffer,
CharCount tabstop, ByteCoord coord)
ColumnCount get_column(const Buffer& buffer,
ColumnCount tabstop, BufferCoord coord)
{
auto line = buffer[coord.line];
auto col = 0_char;
auto col = 0_col;
for (auto it = line.begin();
it != line.end() and coord.column > (int)(it - line.begin());
it = utf8::next(it, line.end()))
@ -29,10 +29,10 @@ CharCount get_column(const Buffer& buffer,
return col;
}
ByteCount get_byte_to_column(const Buffer& buffer, CharCount tabstop, CharCoord coord)
ByteCount get_byte_to_column(const Buffer& buffer, ColumnCount tabstop, DisplayCoord coord)
{
auto line = buffer[coord.line];
auto col = 0_char;
auto col = 0_col;
auto it = line.begin();
while (it != line.end() and coord.column > col)
{
@ -123,7 +123,7 @@ Buffer* create_fifo_buffer(String name, int fd, bool scroll)
count = read(fifo, data, buffer_size);
auto pos = buffer->back_coord();
const bool prevent_scrolling = pos == ByteCoord{0,0} and not scroll;
const bool prevent_scrolling = pos == BufferCoord{0,0} and not scroll;
if (prevent_scrolling)
pos = buffer->next(pos);

View File

@ -15,12 +15,12 @@ inline String content(const Buffer& buffer, const Selection& range)
return buffer.string(range.min(), buffer.char_next(range.max()));
}
inline ByteCoord erase(Buffer& buffer, const Selection& range)
inline BufferCoord erase(Buffer& buffer, const Selection& range)
{
return buffer.erase(range.min(), buffer.char_next(range.max()));
}
inline ByteCoord replace(Buffer& buffer, const Selection& range, StringView content)
inline BufferCoord replace(Buffer& buffer, const Selection& range, StringView content)
{
return buffer.replace(range.min(), buffer.char_next(range.max()), content);
}
@ -31,44 +31,49 @@ inline CharCount char_length(const Buffer& buffer, const Selection& range)
buffer.iterator_at(buffer.char_next(range.max())));
}
inline CharCount char_length(const Buffer& buffer, const ByteCoord& begin, const ByteCoord& end)
inline CharCount char_length(const Buffer& buffer, const BufferCoord& begin, const BufferCoord& end)
{
return utf8::distance(buffer.iterator_at(begin), buffer.iterator_at(end));
}
inline bool is_bol(ByteCoord coord)
inline ColumnCount column_length(const Buffer& buffer, const BufferCoord& begin, const BufferCoord& end)
{
return utf8::column_distance(buffer.iterator_at(begin), buffer.iterator_at(end));
}
inline bool is_bol(BufferCoord coord)
{
return coord.column == 0;
}
inline bool is_eol(const Buffer& buffer, ByteCoord coord)
inline bool is_eol(const Buffer& buffer, BufferCoord coord)
{
return buffer.is_end(coord) or buffer[coord.line].length() == coord.column+1;
}
inline bool is_bow(const Buffer& buffer, ByteCoord coord)
inline bool is_bow(const Buffer& buffer, BufferCoord coord)
{
auto it = utf8::iterator<BufferIterator>(buffer.iterator_at(coord), buffer);
if (coord == ByteCoord{0,0})
if (coord == BufferCoord{0,0})
return is_word(*it);
return not is_word(*(it-1)) and is_word(*it);
}
inline bool is_eow(const Buffer& buffer, ByteCoord coord)
inline bool is_eow(const Buffer& buffer, BufferCoord coord)
{
if (buffer.is_end(coord) or coord == ByteCoord{0,0})
if (buffer.is_end(coord) or coord == BufferCoord{0,0})
return true;
auto it = utf8::iterator<BufferIterator>(buffer.iterator_at(coord), buffer);
return is_word(*(it-1)) and not is_word(*it);
}
CharCount get_column(const Buffer& buffer,
CharCount tabstop, ByteCoord coord);
ColumnCount get_column(const Buffer& buffer,
ColumnCount tabstop, BufferCoord coord);
ByteCount get_byte_to_column(const Buffer& buffer, CharCount tabstop,
CharCoord coord);
ByteCount get_byte_to_column(const Buffer& buffer, ColumnCount tabstop,
DisplayCoord coord);
Buffer* create_fifo_buffer(String name, int fd, bool scroll = false);
Buffer* open_file_buffer(StringView filename);

View File

@ -205,7 +205,7 @@ void Client::redraw_ifn()
if (m_ui_pending & MenuShow)
{
m_menu.ui_anchor = m_menu.style == MenuStyle::Inline ?
window.display_position(m_menu.anchor) : CharCoord{};
window.display_position(m_menu.anchor) : DisplayCoord{};
m_ui->menu_show(m_menu.items, m_menu.ui_anchor,
get_face("MenuForeground"), get_face("MenuBackground"),
m_menu.style);
@ -218,7 +218,7 @@ void Client::redraw_ifn()
if (m_ui_pending & InfoShow)
{
m_info.ui_anchor = is_inline(m_info.style) ?
window.display_position(m_info.anchor) : CharCoord{};
window.display_position(m_info.anchor) : DisplayCoord{};
m_ui->info_show(m_info.title, m_info.content, m_info.ui_anchor,
get_face("Information"), m_info.style);
}
@ -330,7 +330,7 @@ void Client::on_option_changed(const Option& option)
}
}
void Client::menu_show(Vector<DisplayLine> choices, ByteCoord anchor, MenuStyle style)
void Client::menu_show(Vector<DisplayLine> choices, BufferCoord anchor, MenuStyle style)
{
m_menu = Menu{ std::move(choices), anchor, {}, style, -1 };
m_ui_pending |= MenuShow;
@ -351,7 +351,7 @@ void Client::menu_hide()
m_ui_pending &= ~(MenuShow | MenuSelect);
}
void Client::info_show(String title, String content, ByteCoord anchor, InfoStyle style)
void Client::info_show(String title, String content, BufferCoord anchor, InfoStyle style)
{
m_info = Info{ std::move(title), std::move(content), anchor, {}, style };
m_ui_pending |= InfoShow;

View File

@ -34,16 +34,16 @@ public:
// handle all the keys currently available in the user interface
void handle_available_input(EventMode mode);
void menu_show(Vector<DisplayLine> choices, ByteCoord anchor, MenuStyle style);
void menu_show(Vector<DisplayLine> choices, BufferCoord anchor, MenuStyle style);
void menu_select(int selected);
void menu_hide();
void info_show(String title, String content, ByteCoord anchor, InfoStyle style);
void info_show(String title, String content, BufferCoord anchor, InfoStyle style);
void info_hide();
void print_status(DisplayLine status_line);
CharCoord dimensions() const { return m_ui->dimensions(); }
DisplayCoord dimensions() const { return m_ui->dimensions(); }
void force_redraw();
void redraw_ifn();
@ -100,8 +100,8 @@ private:
struct Menu
{
Vector<DisplayLine> items;
ByteCoord anchor;
CharCoord ui_anchor;
BufferCoord anchor;
DisplayCoord ui_anchor;
MenuStyle style;
int selected;
} m_menu;
@ -110,8 +110,8 @@ private:
{
String title;
String content;
ByteCoord anchor;
CharCoord ui_anchor;
BufferCoord anchor;
DisplayCoord ui_anchor;
InfoStyle style;
} m_info;

View File

@ -80,7 +80,7 @@ public:
StringView str;
ByteCount pos;
CharCoord coord;
DisplayCoord coord;
};
bool is_command_separator(char c)
@ -399,7 +399,7 @@ CommandManager::find_command(const Context& context, const String& name) const
void CommandManager::execute_single_command(CommandParameters params,
Context& context,
const ShellContext& shell_context,
CharCoord pos) const
DisplayCoord pos) const
{
if (params.empty())
return;
@ -429,7 +429,7 @@ void CommandManager::execute(StringView command_line,
if (tokens.empty())
return;
CharCoord command_coord;
DisplayCoord command_coord;
Vector<String> params;
for (auto it = tokens.begin(); it != tokens.end(); ++it)
{

View File

@ -56,20 +56,20 @@ struct Token
};
Token() : m_type(Type::Raw) {}
Token(Type type, ByteCount b, ByteCount e, CharCoord coord, String str = "")
Token(Type type, ByteCount b, ByteCount e, DisplayCoord coord, String str = "")
: m_type(type), m_begin(b), m_end(e), m_coord(coord), m_content(std::move(str)) {}
Type type() const { return m_type; }
ByteCount begin() const { return m_begin; }
ByteCount end() const { return m_end; }
CharCoord coord() const { return m_coord; }
DisplayCoord coord() const { return m_coord; }
const String& content() const { return m_content; }
private:
Type m_type;
ByteCount m_begin;
ByteCount m_end;
CharCoord m_coord;
DisplayCoord m_coord;
String m_content;
};
@ -111,7 +111,7 @@ private:
void execute_single_command(CommandParameters params,
Context& context,
const ShellContext& shell_context,
CharCoord pos) const;
DisplayCoord pos) const;
struct CommandDescriptor
{

View File

@ -1812,14 +1812,14 @@ const CommandDesc info_cmd = {
if (parser.positional_count() > 0)
{
InfoStyle style = InfoStyle::Prompt;
ByteCoord pos;
BufferCoord pos;
if (auto anchor = parser.get_switch("anchor"))
{
auto dot = find(*anchor, '.');
if (dot == anchor->end())
throw runtime_error("expected <line>.<column> for anchor");
pos = ByteCoord{str_to_int({anchor->begin(), dot})-1,
pos = BufferCoord{str_to_int({anchor->begin(), dot})-1,
str_to_int({dot+1, anchor->end()})-1};
style = InfoStyle::Inline;

View File

@ -91,36 +91,36 @@ struct LineAndColumn
}
};
struct ByteCoord : LineAndColumn<ByteCoord, LineCount, ByteCount>
struct BufferCoord : LineAndColumn<BufferCoord, LineCount, ByteCount>
{
[[gnu::always_inline]]
constexpr ByteCoord(LineCount line = 0, ByteCount column = 0)
constexpr BufferCoord(LineCount line = 0, ByteCount column = 0)
: LineAndColumn(line, column) {}
};
struct CharCoord : LineAndColumn<CharCoord, LineCount, CharCount>
struct DisplayCoord : LineAndColumn<DisplayCoord, LineCount, ColumnCount>
{
[[gnu::always_inline]]
constexpr CharCoord(LineCount line = 0, CharCount column = 0)
constexpr DisplayCoord(LineCount line = 0, ColumnCount column = 0)
: LineAndColumn(line, column) {}
static constexpr const char* option_type_name = "coord";
};
struct ByteCoordAndTarget : ByteCoord
struct BufferCoordAndTarget : BufferCoord
{
[[gnu::always_inline]]
constexpr ByteCoordAndTarget(LineCount line = 0, ByteCount column = 0, CharCount target = -1)
: ByteCoord(line, column), target(target) {}
constexpr BufferCoordAndTarget(LineCount line = 0, ByteCount column = 0, ColumnCount target = -1)
: BufferCoord(line, column), target(target) {}
[[gnu::always_inline]]
constexpr ByteCoordAndTarget(ByteCoord coord, CharCount target = -1)
: ByteCoord(coord), target(target) {}
constexpr BufferCoordAndTarget(BufferCoord coord, ColumnCount target = -1)
: BufferCoord(coord), target(target) {}
CharCount target;
ColumnCount target;
};
inline size_t hash_value(const ByteCoordAndTarget& val)
inline size_t hash_value(const BufferCoordAndTarget& val)
{
return hash_values(val.line, val.column, val.target);
}

View File

@ -26,10 +26,10 @@ void option_from_string(StringView str, BufferRange& opt)
if (comma == str.end() or dot_begin == comma or dot_end == str.end())
throw runtime_error(format("'{}' does not follow <line>.<column>,<line>.<column> format", str));
ByteCoord begin{str_to_int({str.begin(), dot_begin}) - 1,
BufferCoord begin{str_to_int({str.begin(), dot_begin}) - 1,
str_to_int({dot_begin+1, comma}) - 1};
ByteCoord end{str_to_int({comma+1, dot_end}) - 1,
BufferCoord end{str_to_int({comma+1, dot_end}) - 1,
str_to_int({dot_end+1, str.end()}) - 1};
opt.begin = begin;
@ -58,37 +58,39 @@ StringView DisplayAtom::content() const
return {};
}
CharCount DisplayAtom::length() const
ColumnCount DisplayAtom::length() const
{
switch (m_type)
{
case BufferRange:
return char_length(*m_buffer, m_range.begin, m_range.end);
return (int)column_length(*m_buffer, m_range.begin, m_range.end);
case Text:
case ReplacedBufferRange:
return m_text.char_length();
return (int)m_text.column_length();
}
kak_assert(false);
return 0;
}
void DisplayAtom::trim_begin(CharCount count)
void DisplayAtom::trim_begin(ColumnCount count)
{
if (m_type == BufferRange)
m_range.begin = utf8::advance(m_buffer->iterator_at(m_range.begin),
m_buffer->iterator_at(m_range.end), count).coord();
m_buffer->iterator_at(m_range.end),
count).coord();
else
m_text = m_text.substr(count).str();
check_invariant();
}
void DisplayAtom::trim_end(CharCount count)
void DisplayAtom::trim_end(ColumnCount count)
{
if (m_type == BufferRange)
m_range.end = utf8::advance(m_buffer->iterator_at(m_range.end),
m_buffer->iterator_at(m_range.begin), -count).coord();
m_buffer->iterator_at(m_range.begin),
-count).coord();
else
m_text = m_text.substr(0, m_text.char_length() - count).str();
m_text = m_text.substr(0, m_text.column_length() - count).str();
check_invariant();
}
@ -109,7 +111,7 @@ DisplayLine::DisplayLine(AtomList atoms)
compute_range();
}
DisplayLine::iterator DisplayLine::split(iterator it, ByteCoord pos)
DisplayLine::iterator DisplayLine::split(iterator it, BufferCoord pos)
{
kak_assert(it->type() == DisplayAtom::BufferRange);
kak_assert(it->begin() < pos);
@ -123,7 +125,7 @@ DisplayLine::iterator DisplayLine::split(iterator it, ByteCoord pos)
return m_atoms.insert(it, std::move(atom));
}
DisplayLine::iterator DisplayLine::split(iterator it, CharCount pos)
DisplayLine::iterator DisplayLine::split(iterator it, ColumnCount pos)
{
kak_assert(it->type() == DisplayAtom::Text);
kak_assert(pos > 0);
@ -203,17 +205,17 @@ void DisplayLine::optimize()
}
}
CharCount DisplayLine::length() const
ColumnCount DisplayLine::length() const
{
CharCount len = 0;
ColumnCount len = 0;
for (auto& atom : m_atoms)
len += atom.length();
return len;
}
void DisplayLine::trim(CharCount first_char, CharCount char_count, bool only_buffer)
void DisplayLine::trim(ColumnCount first_col, ColumnCount col_count, bool only_buffer)
{
for (auto it = begin(); first_char > 0 and it != end(); )
for (auto it = begin(); first_col > 0 and it != end(); )
{
if (only_buffer and not it->has_buffer_range())
{
@ -222,23 +224,23 @@ void DisplayLine::trim(CharCount first_char, CharCount char_count, bool only_buf
}
auto len = it->length();
if (len <= first_char)
if (len <= first_col)
{
m_atoms.erase(it);
first_char -= len;
first_col -= len;
}
else
{
it->trim_begin(first_char);
first_char = 0;
it->trim_begin(first_col);
first_col = 0;
}
}
auto it = begin();
for (; it != end() and char_count > 0; ++it)
char_count -= it->length();
for (; it != end() and col_count > 0; ++it)
col_count -= it->length();
if (char_count < 0)
(it-1)->trim_end(-char_count);
if (col_count < 0)
(it-1)->trim_end(-col_count);
m_atoms.erase(it, end());
compute_range();

View File

@ -11,7 +11,7 @@ namespace Kakoune
{
class Buffer;
struct BufferRange{ ByteCoord begin, end; };
struct BufferRange{ BufferCoord begin, end; };
String option_to_string(BufferRange range);
void option_from_string(StringView str, BufferRange& opt);
@ -32,7 +32,7 @@ struct DisplayAtom : public UseMemoryDomain<MemoryDomain::Display>
public:
enum Type { BufferRange, ReplacedBufferRange, Text };
DisplayAtom(const Buffer& buffer, ByteCoord begin, ByteCoord end)
DisplayAtom(const Buffer& buffer, BufferCoord begin, BufferCoord end)
: m_type(BufferRange), m_buffer(&buffer), m_range{begin, end}
{ check_invariant(); }
@ -41,15 +41,15 @@ public:
{ check_invariant(); }
StringView content() const;
CharCount length() const;
ColumnCount length() const;
const ByteCoord& begin() const
const BufferCoord& begin() const
{
kak_assert(has_buffer_range());
return m_range.begin;
}
const ByteCoord& end() const
const BufferCoord& end() const
{
kak_assert(has_buffer_range());
return m_range.end;
@ -71,8 +71,8 @@ public:
Type type() const { return m_type; }
void trim_begin(CharCount count);
void trim_end(CharCount count);
void trim_begin(ColumnCount count);
void trim_end(ColumnCount count);
void check_invariant() const;
@ -117,24 +117,24 @@ public:
const AtomList& atoms() const { return m_atoms; }
CharCount length() const;
ColumnCount length() const;
const BufferRange& range() const { return m_range; }
// Split atom pointed by it at buffer coord pos,
// returns an iterator to the first atom
iterator split(iterator it, ByteCoord pos);
iterator split(iterator it, BufferCoord pos);
// Split atom pointed by it at its pos character,
// Split atom pointed by it at its pos column,
// returns an iterator to the first atom
iterator split(iterator it, CharCount pos);
iterator split(iterator it, ColumnCount pos);
iterator insert(iterator it, DisplayAtom atom);
iterator erase(iterator beg, iterator end);
void push_back(DisplayAtom atom);
// remove first_char from the begining of the line, and make sure
// the line is less that char_count character
void trim(CharCount first_char, CharCount char_count, bool only_buffer);
// remove first_col from the begining of the line, and make sure
// the line is less that col_count character
void trim(ColumnCount first_col, ColumnCount col_count, bool only_buffer);
void optimize();
private:

View File

@ -26,7 +26,7 @@ namespace Kakoune
template<typename T>
void highlight_range(DisplayBuffer& display_buffer,
ByteCoord begin, ByteCoord end,
BufferCoord begin, BufferCoord end,
bool skip_replaced, T func)
{
if (begin == end or end <= display_buffer.range().begin
@ -68,7 +68,7 @@ void highlight_range(DisplayBuffer& display_buffer,
void apply_highlighter(const Context& context,
HighlightFlags flags,
DisplayBuffer& display_buffer,
ByteCoord begin, ByteCoord end,
BufferCoord begin, BufferCoord end,
Highlighter& highlighter)
{
if (begin == end)
@ -335,8 +335,8 @@ private:
cache.m_regex_version = m_regex_version;
}
const LineCount line_offset = 3;
BufferRange range{std::max<ByteCoord>(buffer_range.begin, display_range.begin.line - line_offset),
std::min<ByteCoord>(buffer_range.end, display_range.end.line + line_offset)};
BufferRange range{std::max<BufferCoord>(buffer_range.begin, display_range.begin.line - line_offset),
std::min<BufferCoord>(buffer_range.end, display_range.end.line + line_offset)};
auto it = std::upper_bound(matches.begin(), matches.end(), range,
[](const BufferRange& lhs, const Cache::RangeAndMatches& rhs)
@ -514,7 +514,7 @@ HighlighterAndId create_line_highlighter(HighlighterParameters params)
return;
auto face = get_face(facespec);
CharCount column = 0;
ColumnCount column = 0;
for (auto atom_it = it->begin(); atom_it != it->end(); ++atom_it)
{
column += atom_it->length();
@ -524,7 +524,7 @@ HighlighterAndId create_line_highlighter(HighlighterParameters params)
kak_assert(atom_it->begin().line == line);
apply_face(face)(*atom_it);
}
const CharCount remaining = context.window().dimensions().column - column;
const ColumnCount remaining = context.window().dimensions().column - column;
if (remaining > 0)
it->push_back({ String{' ', remaining}, face });
};
@ -545,7 +545,7 @@ HighlighterAndId create_column_highlighter(HighlighterParameters params)
auto func = [=](const Context& context, HighlightFlags flags,
DisplayBuffer& display_buffer, BufferRange)
{
CharCount column = -1;
ColumnCount column = -1;
try
{
column = str_to_int_ifp(expand(col_expr, context)).value_or(0) - 1;
@ -566,7 +566,7 @@ HighlighterAndId create_column_highlighter(HighlighterParameters params)
{
const LineCount buf_line = line.range().begin.line;
const ByteCount byte_col = get_byte_to_column(buffer, tabstop, {buf_line, column});
const ByteCoord coord{buf_line, byte_col};
const BufferCoord coord{buf_line, byte_col};
bool found = false;
if (buffer.is_valid(coord) and not buffer.is_end(coord))
{
@ -591,8 +591,8 @@ HighlighterAndId create_column_highlighter(HighlighterParameters params)
}
if (not found)
{
CharCount first_buffer_col = -1;
CharCount first_display_col = 0;
ColumnCount first_buffer_col = -1;
ColumnCount first_display_col = 0;
for (auto& atom : line)
{
if (atom.has_buffer_range())
@ -606,8 +606,8 @@ HighlighterAndId create_column_highlighter(HighlighterParameters params)
if (first_buffer_col == -1)
continue;
CharCount eol_col = line.length();
CharCount count = column + first_display_col - first_buffer_col - eol_col;
ColumnCount eol_col = line.length();
ColumnCount count = column + first_display_col - first_buffer_col - eol_col;
if (count >= 0)
{
if (count > 0)
@ -620,11 +620,11 @@ HighlighterAndId create_column_highlighter(HighlighterParameters params)
{
DisplayAtom& atom = *(atom_it-1);
const CharCount len = atom.length();
const ColumnCount len = atom.length();
if (atom.type() == DisplayAtom::Text and -count <= len)
{
auto it = atom_it - 1;
CharCount pos = len + count;
ColumnCount pos = len + count;
if (pos > 0)
{
it = ++line.split(it, pos);
@ -709,7 +709,7 @@ void show_whitespaces(const Context& context, HighlightFlags flags, DisplayBuffe
{
int column = (int)get_column(buffer, tabstop, it.coord());
int count = tabstop - (column % tabstop);
atom_it->replace("" + String(' ', count-1));
atom_it->replace("" + String(' ', CharCount{count-1}));
}
else if (c == ' ')
atom_it->replace("·");
@ -855,8 +855,8 @@ void highlight_selections(const Context& context, HighlightFlags flags, DisplayB
{
auto& sel = selections[i];
const bool forward = sel.anchor() <= sel.cursor();
ByteCoord begin = forward ? sel.anchor() : buffer.char_next(sel.cursor());
ByteCoord end = forward ? (ByteCoord)sel.cursor() : buffer.char_next(sel.anchor());
BufferCoord begin = forward ? sel.anchor() : buffer.char_next(sel.cursor());
BufferCoord end = forward ? (BufferCoord)sel.cursor() : buffer.char_next(sel.anchor());
const bool primary = (i == selections.main_index());
highlight_range(display_buffer, begin, end, false,
@ -961,7 +961,7 @@ HighlighterAndId create_flag_lines_highlighter(HighlighterParameters params)
atom.face = merge_faces(def_face, atom.face);
}
CharCount width = 0;
ColumnCount width = 0;
for (auto& l : display_lines)
width = std::max(width, l.length());
const DisplayAtom empty{String{' ', width}, def_face};
@ -1070,8 +1070,8 @@ struct RegexMatch
ByteCount begin;
ByteCount end;
ByteCoord begin_coord() const { return { line, begin }; }
ByteCoord end_coord() const { return { line, end }; }
BufferCoord begin_coord() const { return { line, begin }; }
BufferCoord end_coord() const { return { line, end }; }
};
using RegexMatchList = Vector<RegexMatch, MemoryDomain::Highlight>;
@ -1147,18 +1147,18 @@ struct RegionMatches
RegexMatchList end_matches;
RegexMatchList recurse_matches;
static bool compare_to_begin(const RegexMatch& lhs, ByteCoord rhs)
static bool compare_to_begin(const RegexMatch& lhs, BufferCoord rhs)
{
return lhs.begin_coord() < rhs;
}
RegexMatchList::const_iterator find_next_begin(ByteCoord pos) const
RegexMatchList::const_iterator find_next_begin(BufferCoord pos) const
{
return std::lower_bound(begin_matches.begin(), begin_matches.end(),
pos, compare_to_begin);
}
RegexMatchList::const_iterator find_matching_end(ByteCoord beg_pos) const
RegexMatchList::const_iterator find_matching_end(BufferCoord beg_pos) const
{
auto end_it = end_matches.begin();
auto rec_it = recurse_matches.begin();
@ -1247,10 +1247,10 @@ public:
auto& regions = get_regions_for_range(buffer, range);
auto begin = std::lower_bound(regions.begin(), regions.end(), display_range.begin,
[](const Region& r, ByteCoord c) { return r.end < c; });
[](const Region& r, BufferCoord c) { return r.end < c; });
auto end = std::lower_bound(begin, regions.end(), display_range.end,
[](const Region& r, ByteCoord c) { return r.begin < c; });
auto correct = [&](ByteCoord c) -> ByteCoord {
[](const Region& r, BufferCoord c) { return r.begin < c; });
auto correct = [&](BufferCoord c) -> BufferCoord {
if (not buffer.is_end(c) and buffer[c.line].length() == c.column)
return {c.line+1, 0};
return c;
@ -1260,7 +1260,7 @@ public:
const bool apply_default = default_group_it != m_groups.end();
auto last_begin = (begin == regions.begin()) ?
ByteCoord{0,0} : (begin-1)->end;
BufferCoord{0,0} : (begin-1)->end;
kak_assert(begin <= end);
for (; begin != end; ++begin)
{
@ -1350,8 +1350,8 @@ private:
struct Region
{
ByteCoord begin;
ByteCoord end;
BufferCoord begin;
BufferCoord end;
StringView group;
};
using RegionList = Vector<Region, MemoryDomain::Highlight>;
@ -1367,7 +1367,7 @@ private:
using RegionAndMatch = std::pair<size_t, RegexMatchList::const_iterator>;
// find the begin closest to pos in all matches
RegionAndMatch find_next_begin(const Cache& cache, ByteCoord pos) const
RegionAndMatch find_next_begin(const Cache& cache, BufferCoord pos) const
{
RegionAndMatch res{0, cache.matches[0].find_next_begin(pos)};
for (size_t i = 1; i < cache.matches.size(); ++i)

View File

@ -74,7 +74,7 @@ struct MouseHandler
return false;
Buffer& buffer = context.buffer();
ByteCoord cursor;
BufferCoord cursor;
switch (key.modifiers)
{
case Key::Modifiers::MousePress:
@ -117,7 +117,7 @@ struct MouseHandler
private:
bool m_dragging = false;
ByteCoord m_anchor;
BufferCoord m_anchor;
};
constexpr StringView register_doc =
@ -371,7 +371,7 @@ public:
{
if (m_cursor_pos != 0)
{
m_line = m_line.substr(0, m_cursor_pos - 1)
m_line = m_line.substr(0_char, m_cursor_pos - 1)
+ m_line.substr(m_cursor_pos);
--m_cursor_pos;
@ -429,7 +429,7 @@ public:
const String& line() const { return m_line; }
CharCount cursor_pos() const { return m_cursor_pos; }
DisplayLine build_display_line(CharCount width)
DisplayLine build_display_line(ColumnCount in_width)
{
auto cleanup = [](StringView str) {
String res;
@ -448,6 +448,7 @@ public:
return res;
};
CharCount width = (int)in_width; // Todo: proper handling of char/column
kak_assert(m_cursor_pos <= m_line.char_length());
if (m_cursor_pos < m_display_pos)
m_display_pos = m_cursor_pos;
@ -463,10 +464,10 @@ public:
{ cleanup(m_line.substr(m_cursor_pos+1, width - m_cursor_pos + m_display_pos - 1)), get_face("StatusLine") } });
}
private:
CharCount m_cursor_pos = 0;
CharCount m_display_pos = 0;
CharCount m_cursor_pos = 0;
CharCount m_display_pos = 0;
String m_line;
String m_line;
};
class Menu : public InputMode
@ -560,7 +561,7 @@ public:
if (m_edit_filter and context().has_client())
{
auto prompt = "filter:"_str;
auto width = context().client().dimensions().column - prompt.char_length();
auto width = context().client().dimensions().column - prompt.column_length();
auto display_line = m_filter_editor.build_display_line(width);
display_line.insert(display_line.begin(), { prompt, get_face("Prompt") });
context().print_status(display_line);
@ -858,7 +859,7 @@ private:
if (not context().has_client())
return;
auto width = context().client().dimensions().column - m_prompt.char_length();
auto width = context().client().dimensions().column - m_prompt.column_length();
DisplayLine display_line;
if (not (m_flags & PromptFlags::Password))
display_line = m_line_editor.build_display_line(width);
@ -998,7 +999,7 @@ public:
Vector<Selection> sels;
for (auto& sel : context().selections())
{
if (sel.cursor() == ByteCoord{0,0})
if (sel.cursor() == BufferCoord{0,0})
continue;
auto pos = sel.cursor();
sels.push_back({ buffer.char_prev(pos) });
@ -1037,7 +1038,7 @@ public:
{
auto& selections = context().selections();
for (auto& sel : selections)
sel.anchor() = sel.cursor() = ByteCoord{sel.cursor().line, 0};
sel.anchor() = sel.cursor() = BufferCoord{sel.cursor().line, 0};
selections.sort_and_merge_overlapping();
}
else if (key == Key::End)
@ -1186,19 +1187,19 @@ private:
break;
case InsertMode::AppendAtLineEnd:
for (auto& sel : selections)
sel = ByteCoord{sel.max().line, buffer[sel.max().line].length() - 1};
sel = BufferCoord{sel.max().line, buffer[sel.max().line].length() - 1};
break;
case InsertMode::OpenLineBelow:
for (auto& sel : selections)
sel = ByteCoord{sel.max().line, buffer[sel.max().line].length() - 1};
sel = BufferCoord{sel.max().line, buffer[sel.max().line].length() - 1};
insert('\n');
break;
case InsertMode::OpenLineAbove:
for (auto& sel : selections)
{
auto line = sel.min().line;
sel = line > 0 ? ByteCoord{line - 1, buffer[line-1].length() - 1}
: ByteCoord{0, 0};
sel = line > 0 ? BufferCoord{line - 1, buffer[line-1].length() - 1}
: BufferCoord{0, 0};
}
insert('\n');
// fix case where we inserted at begining
@ -1211,7 +1212,7 @@ private:
case InsertMode::InsertAtLineBegin:
for (auto& sel : selections)
{
ByteCoord pos = sel.min().line;
BufferCoord pos = sel.min().line;
auto pos_non_blank = buffer.iterator_at(pos);
while (*pos_non_blank == ' ' or *pos_non_blank == '\t')
++pos_non_blank;
@ -1446,22 +1447,24 @@ void scroll_window(Context& context, LineCount offset)
Window& window = context.window();
Buffer& buffer = context.buffer();
CharCoord win_pos = window.position();
CharCoord win_dim = window.dimensions();
DisplayCoord win_pos = window.position();
DisplayCoord win_dim = window.dimensions();
const CharCoord max_offset{(win_dim.line - 1)/2, (win_dim.column - 1)/2};
const CharCoord scrolloff =
std::min(context.options()["scrolloff"].get<CharCoord>(), max_offset);
const DisplayCoord max_offset{(win_dim.line - 1)/2, (win_dim.column - 1)/2};
const DisplayCoord scrolloff =
std::min(context.options()["scrolloff"].get<DisplayCoord>(), max_offset);
const LineCount line_count = buffer.line_count();
win_pos.line = clamp(win_pos.line + offset, 0_line, line_count-1);
SelectionList& selections = context.selections();
const ByteCoord cursor = selections.main().cursor();
const BufferCoord cursor = selections.main().cursor();
auto clamp_line = [&](LineCount line) { return clamp(line, 0_line, line_count-1); };
auto min_coord = buffer.offset_coord(clamp_line(win_pos.line + scrolloff.line), win_pos.column);
auto max_coord = buffer.offset_coord(clamp_line(win_pos.line + win_dim.line - 1 - scrolloff.line), win_pos.column);
auto min_line = clamp_line(win_pos.line + scrolloff.line);
auto max_line = clamp_line(win_pos.line + win_dim.line - 1 - scrolloff.line);
BufferCoord min_coord{min_line, buffer[min_line].byte_count_to(win_pos.column)};
BufferCoord max_coord{max_line, buffer[max_line].byte_count_to(win_pos.column)};
selections = SelectionList{buffer, clamp(cursor, min_coord, max_coord)};

View File

@ -80,14 +80,14 @@ InsertCompletion complete_word(const SelectionList& sels, const OptionManager& o
auto is_word_pred = [extra_word_char](Codepoint c) { return is_word(c) or contains(extra_word_char, c); };
const Buffer& buffer = sels.buffer();
ByteCoord cursor_pos = sels.main().cursor();
BufferCoord cursor_pos = sels.main().cursor();
using Utf8It = utf8::iterator<BufferIterator>;
Utf8It pos{buffer.iterator_at(cursor_pos), buffer};
if (pos == buffer.begin() or not is_word_pred(*(pos-1)))
return {};
ByteCoord word_begin;
BufferCoord word_begin;
String prefix;
IdMap<int> sel_word_counts;
for (int i = 0; i < sels.size(); ++i)
@ -242,7 +242,7 @@ InsertCompletion complete_option(const SelectionList& sels,
StringView option_name)
{
const Buffer& buffer = sels.buffer();
ByteCoord cursor_pos = sels.main().cursor();
BufferCoord cursor_pos = sels.main().cursor();
const CompletionList& opt = options[option_name].get<CompletionList>();
if (opt.list.empty())
@ -253,7 +253,7 @@ InsertCompletion complete_option(const SelectionList& sels,
MatchResults<String::const_iterator> match;
if (regex_match(desc.begin(), desc.end(), match, re))
{
ByteCoord coord{ str_to_int({match[1].first, match[1].second}) - 1,
BufferCoord coord{ str_to_int({match[1].first, match[1].second}) - 1,
str_to_int({match[2].first, match[2].second}) - 1 };
if (not buffer.is_valid(coord))
return {};
@ -274,8 +274,8 @@ InsertCompletion complete_option(const SelectionList& sels,
StringView query = buffer[coord.line].substr(
coord.column, cursor_pos.column - coord.column);
const CharCount tabstop = options["tabstop"].get<int>();
const CharCount column = get_column(buffer, tabstop, cursor_pos);
const ColumnCount tabstop = options["tabstop"].get<int>();
const ColumnCount column = get_column(buffer, tabstop, cursor_pos);
struct RankedMatchAndInfo : RankedMatch
{
@ -318,10 +318,10 @@ InsertCompletion complete_option(const SelectionList& sels,
InsertCompletion complete_line(const SelectionList& sels, const OptionManager& options)
{
const Buffer& buffer = sels.buffer();
ByteCoord cursor_pos = sels.main().cursor();
BufferCoord cursor_pos = sels.main().cursor();
const CharCount tabstop = options["tabstop"].get<int>();
const CharCount column = get_column(buffer, tabstop, cursor_pos);
const ColumnCount tabstop = options["tabstop"].get<int>();
const ColumnCount column = get_column(buffer, tabstop, cursor_pos);
StringView prefix = buffer[cursor_pos.line].substr(0_byte, cursor_pos.column);
InsertCompletion::CandidateList candidates;

View File

@ -64,8 +64,8 @@ struct InsertCompletion
using CandidateList = Vector<Candidate>;
ByteCoord begin;
ByteCoord end;
BufferCoord begin;
BufferCoord end;
CandidateList candidates;
size_t timestamp;

View File

@ -112,7 +112,7 @@ String to_json(const DisplayLine& line)
return to_json(line.atoms());
}
String to_json(CharCoord coord)
String to_json(DisplayCoord coord)
{
return format(R"(\{ "line": {}, "column": {} })", coord.line, coord.column);
}
@ -197,7 +197,7 @@ Key JsonUI::get_key()
}
void JsonUI::menu_show(ConstArrayView<DisplayLine> items,
CharCoord anchor, Face fg, Face bg,
DisplayCoord anchor, Face fg, Face bg,
MenuStyle style)
{
rpc_call("menu_show", items, anchor, fg, bg, style);
@ -214,7 +214,7 @@ void JsonUI::menu_hide()
}
void JsonUI::info_show(StringView title, StringView content,
CharCoord anchor, Face face,
DisplayCoord anchor, Face face,
InfoStyle style)
{
rpc_call("info_show", title, content, anchor, face, style);
@ -240,7 +240,7 @@ void JsonUI::set_ui_options(const Options& options)
// rpc_call("set_ui_options", options);
}
CharCoord JsonUI::dimensions()
DisplayCoord JsonUI::dimensions()
{
return m_dimensions;
}
@ -391,7 +391,7 @@ void JsonUI::eval_json(const Value& json)
if (params.size() != 2)
throw runtime_error("resize expects 2 parameters");
CharCoord dim{params[0].as<int>(), params[1].as<int>()};
DisplayCoord dim{params[0].as<int>(), params[1].as<int>()};
m_dimensions = dim;
m_pending_keys.push_back(resize(dim));
}

View File

@ -30,13 +30,13 @@ public:
Key get_key() override;
void menu_show(ConstArrayView<DisplayLine> items,
CharCoord anchor, Face fg, Face bg,
DisplayCoord anchor, Face fg, Face bg,
MenuStyle style) override;
void menu_select(int selected) override;
void menu_hide() override;
void info_show(StringView title, StringView content,
CharCoord anchor, Face face,
DisplayCoord anchor, Face face,
InfoStyle style) override;
void info_hide() override;
@ -46,7 +46,7 @@ public:
void set_ui_options(const Options& options) override;
CharCoord dimensions() override;
DisplayCoord dimensions() override;
private:
void parse_requests(EventMode mode);
@ -55,7 +55,7 @@ private:
InputCallback m_input_callback;
FDWatcher m_stdin_watcher;
Vector<Key> m_pending_keys;
CharCoord m_dimensions;
DisplayCoord m_dimensions;
String m_requests;
};

View File

@ -115,7 +115,7 @@ String key_to_str(Key key)
{
if (key.modifiers & Key::Modifiers::MouseEvent)
{
const auto coord = key.coord() + CharCoord{1,1};
const auto coord = key.coord() + DisplayCoord{1,1};
switch (key.modifiers)
{
case Key::Modifiers::MousePos:
@ -133,7 +133,7 @@ String key_to_str(Key key)
}
else if (key.modifiers == Key::Modifiers::Resize)
{
auto size = key.coord() + CharCoord{1,1};
auto size = key.coord() + DisplayCoord{1,1};
return format("<resize:{}.{}>", size.line, size.column);
}

View File

@ -79,7 +79,7 @@ struct Key
constexpr bool operator!=(Key other) const { return val() != other.val(); }
constexpr bool operator<(Key other) const { return val() < other.val(); }
constexpr CharCoord coord() const { return {(int)((key & 0xFFFF0000) >> 16), (int)(key & 0x0000FFFF)}; }
constexpr DisplayCoord coord() const { return {(int)((key & 0xFFFF0000) >> 16), (int)(key & 0x0000FFFF)}; }
Optional<Codepoint> codepoint() const;
};
@ -98,15 +98,15 @@ constexpr Key alt(Codepoint key) { return { Key::Modifiers::Alt, key }; }
constexpr Key ctrl(Codepoint key) { return { Key::Modifiers::Control, key }; }
constexpr Key ctrlalt(Codepoint key) { return { Key::Modifiers::ControlAlt, key }; }
constexpr Codepoint encode_coord(CharCoord coord) { return (Codepoint)(((int)coord.line << 16) | ((int)coord.column & 0x0000FFFF)); }
constexpr Codepoint encode_coord(DisplayCoord coord) { return (Codepoint)(((int)coord.line << 16) | ((int)coord.column & 0x0000FFFF)); }
constexpr Key mouse_press(CharCoord pos) { return { Key::Modifiers::MousePress, encode_coord(pos) }; }
constexpr Key mouse_release(CharCoord pos) { return { Key::Modifiers::MouseRelease, encode_coord(pos) }; }
constexpr Key mouse_pos(CharCoord pos) { return { Key::Modifiers::MousePos, encode_coord(pos) }; }
constexpr Key mouse_wheel_down(CharCoord pos) { return { Key::Modifiers::MouseWheelDown, encode_coord(pos) }; }
constexpr Key mouse_wheel_up(CharCoord pos) { return { Key::Modifiers::MouseWheelUp, encode_coord(pos) }; }
constexpr Key mouse_press(DisplayCoord pos) { return { Key::Modifiers::MousePress, encode_coord(pos) }; }
constexpr Key mouse_release(DisplayCoord pos) { return { Key::Modifiers::MouseRelease, encode_coord(pos) }; }
constexpr Key mouse_pos(DisplayCoord pos) { return { Key::Modifiers::MousePos, encode_coord(pos) }; }
constexpr Key mouse_wheel_down(DisplayCoord pos) { return { Key::Modifiers::MouseWheelDown, encode_coord(pos) }; }
constexpr Key mouse_wheel_up(DisplayCoord pos) { return { Key::Modifiers::MouseWheelUp, encode_coord(pos) }; }
constexpr Key resize(CharCoord dim) { return { Key::Modifiers::Resize, encode_coord(dim) }; }
constexpr Key resize(DisplayCoord dim) { return { Key::Modifiers::Resize, encode_coord(dim) }; }
inline size_t hash_value(const Key& key) { return hash_values(key.modifiers, key.key); }

View File

@ -198,7 +198,7 @@ static void check_indentwidth(const int& val)
if (val < 0) throw runtime_error{"indentwidth should be positive or zero"};
}
static void check_scrolloff(const CharCoord& so)
static void check_scrolloff(const DisplayCoord& so)
{
if (so.line < 0 or so.column < 0)
throw runtime_error{"scroll offset must be positive or zero"};
@ -216,7 +216,7 @@ void register_options()
reg.declare_option<int, check_tabstop>("tabstop", "size of a tab character", 8);
reg.declare_option<int, check_indentwidth>("indentwidth", "indentation width", 4);
reg.declare_option<CharCoord, check_scrolloff>(
reg.declare_option<DisplayCoord, check_scrolloff>(
"scrolloff", "number of lines and columns to keep visible main cursor when scrolling",
{0,0});
reg.declare_option("eolformat", "end of line format", EolFormat::Lf);
@ -318,17 +318,17 @@ std::unique_ptr<UserInterface> make_ui(UIType ui_type)
struct DummyUI : UserInterface
{
DummyUI() { set_signal_handler(SIGINT, SIG_DFL); }
void menu_show(ConstArrayView<DisplayLine>, CharCoord,
void menu_show(ConstArrayView<DisplayLine>, DisplayCoord,
Face, Face, MenuStyle) override {}
void menu_select(int) override {}
void menu_hide() override {}
void info_show(StringView, StringView, CharCoord, Face, InfoStyle) override {}
void info_show(StringView, StringView, DisplayCoord, Face, InfoStyle) override {}
void info_hide() override {}
void draw(const DisplayBuffer&, const Face&, const Face&) override {}
void draw_status(const DisplayLine&, const DisplayLine&, const Face&) override {}
CharCoord dimensions() override { return {24,80}; }
DisplayCoord dimensions() override { return {24,80}; }
bool is_key_available() override { return false; }
Key get_key() override { return Key::Invalid; }
void refresh(bool) override {}
@ -477,7 +477,7 @@ int run_client(StringView session, StringView init_command, UIType ui_type)
int run_server(StringView session, StringView init_command,
bool ignore_kakrc, bool daemon, bool readonly, UIType ui_type,
ConstArrayView<StringView> files, ByteCoord target_coord)
ConstArrayView<StringView> files, BufferCoord target_coord)
{
static bool terminate = false;
if (daemon)
@ -839,7 +839,7 @@ int main(int argc, char* argv[])
}
else
{
ByteCoord target_coord;
BufferCoord target_coord;
Vector<StringView> files;
for (auto& name : parser)
{

View File

@ -266,7 +266,7 @@ NCursesUI::~NCursesUI()
set_signal_handler(SIGCONT, SIG_DFL);
}
void NCursesUI::Window::create(const CharCoord& p, const CharCoord& s)
void NCursesUI::Window::create(const DisplayCoord& p, const DisplayCoord& s)
{
pos = p;
size = s;
@ -277,8 +277,8 @@ void NCursesUI::Window::destroy()
{
delwin(win);
win = nullptr;
pos = CharCoord{};
size = CharCoord{};
pos = DisplayCoord{};
size = DisplayCoord{};
}
void NCursesUI::Window::refresh()
@ -286,7 +286,7 @@ void NCursesUI::Window::refresh()
if (not win)
return;
CharCoord max_pos = pos + size - CharCoord{1,1};
DisplayCoord max_pos = pos + size - DisplayCoord{1,1};
pnoutrefresh(win, 0, 0, (int)pos.line, (int)pos.column,
(int)max_pos.line, (int)max_pos.column);
}
@ -316,7 +316,7 @@ void add_str(WINDOW* win, StringView str)
}
void NCursesUI::draw_line(NCursesWin* window, const DisplayLine& line,
CharCount col_index, CharCount max_column,
ColumnCount col_index, ColumnCount max_column,
const Face& default_face)
{
for (const DisplayAtom& atom : line)
@ -329,16 +329,16 @@ void NCursesUI::draw_line(NCursesWin* window, const DisplayLine& line,
const auto remaining_columns = max_column - col_index;
if (content.back() == '\n' and
content.char_length() - 1 < remaining_columns)
content.column_length() - 1 < remaining_columns)
{
add_str(window, content.substr(0, content.length()-1));
waddch(window, ' ');
}
else
{
content = content.substr(0_char, remaining_columns);
content = content.substr(0_col, remaining_columns);
add_str(window, content);
col_index += content.char_length();
col_index += content.column_length();
}
}
}
@ -391,7 +391,7 @@ void NCursesUI::draw_status(const DisplayLine& status_line,
const auto remaining = m_dimensions.column - status_line.length();
if (mode_len < remaining)
{
CharCount col = m_dimensions.column - mode_len;
ColumnCount col = m_dimensions.column - mode_len;
wmove(m_window, status_line_pos, (int)col);
draw_line(m_window, mode_line, col, m_dimensions.column, default_face);
}
@ -402,7 +402,7 @@ void NCursesUI::draw_status(const DisplayLine& status_line,
trimmed_mode_line.insert(trimmed_mode_line.begin(), { "" });
kak_assert(trimmed_mode_line.length() == remaining - 1);
CharCount col = m_dimensions.column - remaining + 1;
ColumnCount col = m_dimensions.column - remaining + 1;
wmove(m_window, status_line_pos, (int)col);
draw_line(m_window, trimmed_mode_line, col, m_dimensions.column, default_face);
}
@ -444,7 +444,7 @@ void NCursesUI::check_resize(bool force)
intrflush(m_window, false);
keypad(m_window, true);
m_dimensions = CharCoord{ws.ws_row-1, ws.ws_col};
m_dimensions = DisplayCoord{ws.ws_row-1, ws.ws_col};
if (char* csr = tigetstr((char*)"csr"))
putp(tparm(csr, 0, ws.ws_row));
@ -488,7 +488,7 @@ Key NCursesUI::get_key()
MEVENT ev;
if (getmouse(&ev) == OK)
{
CharCoord pos{ ev.y - (m_status_on_top ? 1 : 0), ev.x };
DisplayCoord pos{ ev.y - (m_status_on_top ? 1 : 0), ev.x };
if (BUTTON_PRESS(ev.bstate, 1)) return mouse_press(pos);
if (BUTTON_RELEASE(ev.bstate, 1)) return mouse_release(pos);
if (BUTTON_PRESS(ev.bstate, m_wheel_down_button)) return mouse_wheel_down(pos);
@ -596,7 +596,7 @@ void NCursesUI::draw_menu()
const LineCount& win_height = m_menu.size.line;
kak_assert(win_height <= menu_lines);
const CharCount column_width = (m_menu.size.column - 1) / m_menu.columns;
const ColumnCount column_width = (m_menu.size.column - 1) / m_menu.columns;
const LineCount mark_height = min(div_round_up(sq(win_height), menu_lines),
win_height);
@ -615,7 +615,7 @@ void NCursesUI::draw_menu()
const DisplayLine& item = m_menu.items[item_idx];
draw_line(m_menu.win, item, 0, column_width,
item_idx == m_menu.selected_item ? m_menu.fg : m_menu.bg);
const CharCount pad = column_width - item.length();
const ColumnCount pad = column_width - item.length();
add_str(m_menu.win, String{' ', pad});
}
const bool is_mark = line >= mark_line and
@ -629,7 +629,7 @@ void NCursesUI::draw_menu()
}
void NCursesUI::menu_show(ConstArrayView<DisplayLine> items,
CharCoord anchor, Face fg, Face bg,
DisplayCoord anchor, Face fg, Face bg,
MenuStyle style)
{
menu_hide();
@ -640,11 +640,11 @@ void NCursesUI::menu_show(ConstArrayView<DisplayLine> items,
m_menu.anchor = anchor;
if (style == MenuStyle::Prompt)
anchor = CharCoord{m_status_on_top ? 0_line : m_dimensions.line, 0};
anchor = DisplayCoord{m_status_on_top ? 0_line : m_dimensions.line, 0};
else if (m_status_on_top)
anchor.line += 1;
CharCoord maxsize = m_dimensions;
DisplayCoord maxsize = m_dimensions;
maxsize.column -= anchor.column;
if (maxsize.column <= 2)
return;
@ -652,14 +652,14 @@ void NCursesUI::menu_show(ConstArrayView<DisplayLine> items,
const int item_count = items.size();
m_menu.items.clear(); // make sure it is empty
m_menu.items.reserve(item_count);
CharCount longest = 1;
ColumnCount longest = 1;
for (auto& item : items)
longest = max(longest, item.length());
const bool is_prompt = style == MenuStyle::Prompt;
m_menu.columns = is_prompt ? max((int)((maxsize.column-1) / (longest+1)), 1) : 1;
CharCount maxlen = maxsize.column-1;
ColumnCount maxlen = maxsize.column-1;
if (m_menu.columns > 1 and item_count > 1)
maxlen = maxlen / m_menu.columns - 1;
@ -720,10 +720,10 @@ void NCursesUI::menu_hide()
m_dirty = true;
}
static CharCoord compute_needed_size(StringView str)
static DisplayCoord compute_needed_size(StringView str)
{
CharCoord res{1,0};
CharCount line_len = 0;
DisplayCoord res{1,0};
ColumnCount line_len = 0;
for (auto it = str.begin(), end = str.end();
it != end; it = utf8::next(it, end))
{
@ -746,32 +746,32 @@ static CharCoord compute_needed_size(StringView str)
return res;
}
static CharCoord compute_pos(CharCoord anchor, CharCoord size,
static DisplayCoord compute_pos(DisplayCoord anchor, DisplayCoord size,
NCursesUI::Rect rect, NCursesUI::Rect to_avoid,
bool prefer_above)
{
CharCoord pos;
DisplayCoord pos;
if (prefer_above)
{
pos = anchor - CharCoord{size.line};
pos = anchor - DisplayCoord{size.line};
if (pos.line < 0)
prefer_above = false;
}
auto rect_end = rect.pos + rect.size;
if (not prefer_above)
{
pos = anchor + CharCoord{1_line};
pos = anchor + DisplayCoord{1_line};
if (pos.line + size.line > rect_end.line)
pos.line = max(rect.pos.line, anchor.line - size.line);
}
if (pos.column + size.column > rect_end.column)
pos.column = max(rect.pos.column, rect_end.column - size.column);
if (to_avoid.size != CharCoord{})
if (to_avoid.size != DisplayCoord{})
{
CharCoord to_avoid_end = to_avoid.pos + to_avoid.size;
DisplayCoord to_avoid_end = to_avoid.pos + to_avoid.size;
CharCoord end = pos + size;
DisplayCoord end = pos + size;
// check intersection
if (not (end.line < to_avoid.pos.line or end.column < to_avoid.pos.column or
@ -787,24 +787,24 @@ static CharCoord compute_pos(CharCoord anchor, CharCoord size,
return pos;
}
String make_info_box(StringView title, StringView message, CharCount max_width,
String make_info_box(StringView title, StringView message, ColumnCount max_width,
ConstArrayView<StringView> assistant)
{
CharCoord assistant_size;
DisplayCoord assistant_size;
if (not assistant.empty())
assistant_size = { (int)assistant.size(), assistant[0].char_length() };
assistant_size = { (int)assistant.size(), assistant[0].column_length() };
String result;
const CharCount max_bubble_width = max_width - assistant_size.column - 6;
const ColumnCount max_bubble_width = max_width - assistant_size.column - 6;
if (max_bubble_width < 4)
return result;
Vector<StringView> lines = wrap_lines(message, max_bubble_width);
CharCount bubble_width = title.char_length() + 2;
ColumnCount bubble_width = title.column_length() + 2;
for (auto& line : lines)
bubble_width = max(bubble_width, line.char_length());
bubble_width = max(bubble_width, line.column_length());
auto line_count = max(assistant_size.line-1,
LineCount{(int)lines.size()} + 2);
@ -819,7 +819,7 @@ String make_info_box(StringView title, StringView message, CharCount max_width,
result += "╭─" + String{dash, bubble_width} + "─╮";
else
{
auto dash_count = bubble_width - title.char_length() - 2;
auto dash_count = bubble_width - title.column_length() - 2;
String left{dash, dash_count / 2};
String right{dash, dash_count - dash_count / 2};
result += "╭─" + left + "" + title +"" + right +"─╮";
@ -828,7 +828,7 @@ String make_info_box(StringView title, StringView message, CharCount max_width,
else if (i < lines.size() + 1)
{
auto& line = lines[(int)i - 1];
const CharCount padding = bubble_width - line.char_length();
const ColumnCount padding = bubble_width - line.column_length();
result += "" + line + String{' ', padding} + "";
}
else if (i == lines.size() + 1)
@ -840,7 +840,7 @@ String make_info_box(StringView title, StringView message, CharCount max_width,
}
void NCursesUI::info_show(StringView title, StringView content,
CharCoord anchor, Face face, InfoStyle style)
DisplayCoord anchor, Face face, InfoStyle style)
{
info_hide();
@ -855,18 +855,18 @@ void NCursesUI::info_show(StringView title, StringView content,
{
info_box = make_info_box(m_info.title, m_info.content,
m_dimensions.column, m_assistant);
anchor = CharCoord{m_status_on_top ? 0 : m_dimensions.line,
anchor = DisplayCoord{m_status_on_top ? 0 : m_dimensions.line,
m_dimensions.column-1};
}
else
{
if (m_status_on_top)
anchor.line += 1;
CharCount col = anchor.column;
ColumnCount col = anchor.column;
if (style == InfoStyle::MenuDoc and m_menu)
col = m_menu.pos.column + m_menu.size.column;
const CharCount max_width = m_dimensions.column - col;
const ColumnCount max_width = m_dimensions.column - col;
if (max_width < 4)
return;
@ -874,10 +874,10 @@ void NCursesUI::info_show(StringView title, StringView content,
info_box += line + "\n";
}
CharCoord size = compute_needed_size(info_box), pos;
DisplayCoord size = compute_needed_size(info_box), pos;
const Rect rect = {m_status_on_top ? 1_line : 0_line, m_dimensions};
if (style == InfoStyle::MenuDoc and m_menu)
pos = m_menu.pos + CharCoord{0_line, m_menu.size.column};
pos = m_menu.pos + DisplayCoord{0_line, m_menu.size.column};
else
pos = compute_pos(anchor, size, rect, m_menu, style == InfoStyle::InlineAbove);
@ -916,7 +916,7 @@ void NCursesUI::mark_dirty(const Window& win)
wredrawln(m_window, (int)win.pos.line, (int)win.size.line);
}
CharCoord NCursesUI::dimensions()
DisplayCoord NCursesUI::dimensions()
{
return m_dimensions;
}

View File

@ -34,13 +34,13 @@ public:
Key get_key() override;
void menu_show(ConstArrayView<DisplayLine> items,
CharCoord anchor, Face fg, Face bg,
DisplayCoord anchor, Face fg, Face bg,
MenuStyle style) override;
void menu_select(int selected) override;
void menu_hide() override;
void info_show(StringView title, StringView content,
CharCoord anchor, Face face,
DisplayCoord anchor, Face face,
InfoStyle style) override;
void info_hide() override;
@ -50,14 +50,14 @@ public:
void set_ui_options(const Options& options) override;
CharCoord dimensions() override;
DisplayCoord dimensions() override;
static void abort();
struct Rect
{
CharCoord pos;
CharCoord size;
DisplayCoord pos;
DisplayCoord size;
};
private:
void check_resize(bool force = false);
@ -67,12 +67,12 @@ private:
int get_color_pair(const Face& face);
void set_face(NCursesWin* window, Face face, const Face& default_face);
void draw_line(NCursesWin* window, const DisplayLine& line,
CharCount col_index, CharCount max_column,
ColumnCount col_index, ColumnCount max_column,
const Face& default_face);
NCursesWin* m_window = nullptr;
CharCoord m_dimensions;
DisplayCoord m_dimensions;
using ColorPair = std::pair<Color, Color>;
UnorderedMap<Color, int, MemoryDomain::Faces> m_colors;
@ -81,7 +81,7 @@ private:
struct Window : Rect
{
void create(const CharCoord& pos, const CharCoord& size);
void create(const DisplayCoord& pos, const DisplayCoord& size);
void destroy();
void refresh();
@ -97,7 +97,7 @@ private:
Vector<DisplayLine> items;
Face fg;
Face bg;
CharCoord anchor;
DisplayCoord anchor;
MenuStyle style;
int selected_item = 0;
int columns = 1;
@ -111,7 +111,7 @@ private:
String title;
String content;
Face face;
CharCoord anchor;
DisplayCoord anchor;
InfoStyle style;
} m_info;

View File

@ -71,7 +71,7 @@ void select(Context& context, NormalParams)
}
template<SelectMode mode = SelectMode::Replace>
void select_coord(Buffer& buffer, ByteCoord coord, SelectionList& selections)
void select_coord(Buffer& buffer, BufferCoord coord, SelectionList& selections)
{
coord = buffer.clamp(coord);
if (mode == SelectMode::Replace)
@ -118,7 +118,7 @@ void goto_commands(Context& context, NormalParams params)
case 'g':
case 'k':
context.push_jump();
select_coord<mode>(buffer, ByteCoord{0,0}, context.selections());
select_coord<mode>(buffer, BufferCoord{0,0}, context.selections());
break;
case 'l':
select<mode, select_to_line_end<true>>(context, {});
@ -204,7 +204,7 @@ void goto_commands(Context& context, NormalParams params)
if (pos >= buffer.back_coord())
pos = buffer.back_coord();
else if (buffer[pos.line].length() == pos.column + 1)
pos = ByteCoord{ pos.line+1, 0 };
pos = BufferCoord{ pos.line+1, 0 };
select_coord<mode>(buffer, pos, context.selections());
break;
}
@ -240,7 +240,7 @@ void view_commands(Context& context, NormalParams params)
if (not cp or not context.has_window())
return;
const ByteCoord cursor = context.selections().main().cursor();
const BufferCoord cursor = context.selections().main().cursor();
Window& window = context.window();
switch (to_lower(*cp))
{
@ -250,7 +250,7 @@ void view_commands(Context& context, NormalParams params)
break;
case 'm':
context.window().center_column(
context.buffer()[cursor.line].char_count_to(cursor.column));
context.buffer()[cursor.line].column_count_to(cursor.column));
break;
case 't':
context.window().display_line_at(cursor.line, 0);
@ -259,7 +259,7 @@ void view_commands(Context& context, NormalParams params)
context.window().display_line_at(cursor.line, window.dimensions().line-1);
break;
case 'h':
context.window().scroll(-std::max<CharCount>(1, count));
context.window().scroll(-std::max<ColumnCount>(1, count));
break;
case 'j':
context.window().scroll( std::max<LineCount>(1, count));
@ -268,7 +268,7 @@ void view_commands(Context& context, NormalParams params)
context.window().scroll(-std::max<LineCount>(1, count));
break;
case 'l':
context.window().scroll( std::max<CharCount>(1, count));
context.window().scroll( std::max<ColumnCount>(1, count));
break;
}
}, "view",
@ -592,7 +592,7 @@ void paste_all(Context& context, NormalParams params)
template<typename T>
void regex_prompt(Context& context, String prompt, T func)
{
CharCoord position = context.has_window() ? context.window().position() : CharCoord{};
DisplayCoord position = context.has_window() ? context.window().position() : DisplayCoord{};
SelectionList selections = context.selections();
context.input_handler().prompt(
std::move(prompt), "", get_face("Prompt"), PromptFlags::None, complete_nothing,
@ -875,8 +875,8 @@ void indent(Context& context, NormalParams)
template<bool deindent_incomplete = true>
void deindent(Context& context, NormalParams)
{
CharCount tabstop = context.options()["tabstop"].get<int>();
CharCount indent_width = context.options()["indentwidth"].get<int>();
ColumnCount tabstop = context.options()["tabstop"].get<int>();
ColumnCount indent_width = context.options()["indentwidth"].get<int>();
if (indent_width == 0)
indent_width = tabstop;
@ -888,7 +888,7 @@ void deindent(Context& context, NormalParams)
for (auto line = std::max(sel.min().line, last_line);
line < sel.max().line+1; ++line)
{
CharCount width = 0;
ColumnCount width = 0;
auto content = buffer[line];
for (auto column = 0_byte; column < content.length(); ++column)
{
@ -900,12 +900,12 @@ void deindent(Context& context, NormalParams)
else
{
if (deindent_incomplete and width != 0)
sels.push_back({ line, ByteCoord{line, column-1} });
sels.push_back({ line, BufferCoord{line, column-1} });
break;
}
if (width == indent_width)
{
sels.push_back({ line, ByteCoord{line, column} });
sels.push_back({ line, BufferCoord{line, column} });
break;
}
}
@ -1048,14 +1048,14 @@ void copy_selections_on_next_lines(Context& context, NormalParams params)
{
auto& selections = context.selections();
auto& buffer = context.buffer();
const CharCount tabstop = context.options()["tabstop"].get<int>();
const ColumnCount tabstop = context.options()["tabstop"].get<int>();
Vector<Selection> result;
for (auto& sel : selections)
{
auto anchor = sel.anchor();
auto cursor = sel.cursor();
CharCount cursor_col = get_column(buffer, tabstop, cursor);
CharCount anchor_col = get_column(buffer, tabstop, anchor);
ColumnCount cursor_col = get_column(buffer, tabstop, cursor);
ColumnCount anchor_col = get_column(buffer, tabstop, anchor);
result.push_back(std::move(sel));
for (int i = 0; i < std::max(params.count, 1); ++i)
{
@ -1073,8 +1073,8 @@ void copy_selections_on_next_lines(Context& context, NormalParams params)
if (anchor_byte != buffer[anchor_line].length() and
cursor_byte != buffer[cursor_line].length())
result.emplace_back(ByteCoord{anchor_line, anchor_byte},
ByteCoordAndTarget{cursor_line, cursor_byte, cursor.target});
result.emplace_back(BufferCoord{anchor_line, anchor_byte},
BufferCoordAndTarget{cursor_line, cursor_byte, cursor.target});
}
}
selections = std::move(result);
@ -1206,7 +1206,7 @@ void align(Context& context, NormalParams)
{
auto& selections = context.selections();
auto& buffer = context.buffer();
const CharCount tabstop = context.options()["tabstop"].get<int>();
const ColumnCount tabstop = context.options()["tabstop"].get<int>();
Vector<Vector<const Selection*>> columns;
LineCount last_line = -1;
@ -1227,7 +1227,7 @@ void align(Context& context, NormalParams)
const bool use_tabs = context.options()["aligntab"].get<bool>();
for (auto& col : columns)
{
CharCount maxcol = 0;
ColumnCount maxcol = 0;
for (auto& sel : col)
maxcol = std::max(get_column(buffer, tabstop, sel->cursor()), maxcol);
for (auto& sel : col)
@ -1292,8 +1292,8 @@ void copy_indent(Context& context, NormalParams params)
void tabs_to_spaces(Context& context, NormalParams params)
{
auto& buffer = context.buffer();
const CharCount opt_tabstop = context.options()["tabstop"].get<int>();
const CharCount tabstop = params.count == 0 ? opt_tabstop : params.count;
const ColumnCount opt_tabstop = context.options()["tabstop"].get<int>();
const ColumnCount tabstop = params.count == 0 ? opt_tabstop : params.count;
Vector<Selection> tabs;
Vector<String> spaces;
for (auto& sel : context.selections())
@ -1303,8 +1303,8 @@ void tabs_to_spaces(Context& context, NormalParams params)
{
if (*it == '\t')
{
CharCount col = get_column(buffer, opt_tabstop, it.coord());
CharCount end_col = (col / tabstop + 1) * tabstop;
ColumnCount col = get_column(buffer, opt_tabstop, it.coord());
ColumnCount end_col = (col / tabstop + 1) * tabstop;
tabs.push_back({ it.coord() });
spaces.push_back(String{ ' ', end_col - col });
}
@ -1317,8 +1317,8 @@ void tabs_to_spaces(Context& context, NormalParams params)
void spaces_to_tabs(Context& context, NormalParams params)
{
auto& buffer = context.buffer();
const CharCount opt_tabstop = context.options()["tabstop"].get<int>();
const CharCount tabstop = params.count == 0 ? opt_tabstop : params.count;
const ColumnCount opt_tabstop = context.options()["tabstop"].get<int>();
const ColumnCount tabstop = params.count == 0 ? opt_tabstop : params.count;
Vector<Selection> spaces;
for (auto& sel : context.selections())
{
@ -1329,7 +1329,7 @@ void spaces_to_tabs(Context& context, NormalParams params)
{
auto spaces_beg = it;
auto spaces_end = spaces_beg+1;
CharCount col = get_column(buffer, opt_tabstop, spaces_end.coord());
ColumnCount col = get_column(buffer, opt_tabstop, spaces_end.coord());
while (spaces_end != end and
*spaces_end == ' ' and (col % tabstop) != 0)
{
@ -1570,7 +1570,7 @@ void flip_selections(Context& context, NormalParams)
{
for (auto& sel : context.selections())
{
const ByteCoord tmp = sel.anchor();
const BufferCoord tmp = sel.anchor();
sel.anchor() = sel.cursor();
sel.cursor() = tmp;
}
@ -1581,7 +1581,7 @@ void ensure_forward(Context& context, NormalParams)
{
for (auto& sel : context.selections())
{
const ByteCoord min = sel.min(), max = sel.max();
const BufferCoord min = sel.min(), max = sel.max();
sel.anchor() = min;
sel.cursor() = max;
}

View File

@ -291,17 +291,17 @@ DisplayBuffer MsgReader::read<DisplayBuffer>()
class RemoteUI : public UserInterface
{
public:
RemoteUI(int socket, CharCoord dimensions);
RemoteUI(int socket, DisplayCoord dimensions);
~RemoteUI();
void menu_show(ConstArrayView<DisplayLine> choices,
CharCoord anchor, Face fg, Face bg,
DisplayCoord anchor, Face fg, Face bg,
MenuStyle style) override;
void menu_select(int selected) override;
void menu_hide() override;
void info_show(StringView title, StringView content,
CharCoord anchor, Face face,
DisplayCoord anchor, Face face,
InfoStyle style) override;
void info_hide() override;
@ -317,7 +317,7 @@ public:
bool is_key_available() override;
Key get_key() override;
CharCoord dimensions() override;
DisplayCoord dimensions() override;
void set_input_callback(InputCallback callback) override;
@ -329,7 +329,7 @@ public:
private:
FDWatcher m_socket_watcher;
MsgReader m_reader;
CharCoord m_dimensions;
DisplayCoord m_dimensions;
InputCallback m_input_callback;
SafePtr<Client> m_client;
@ -337,7 +337,7 @@ private:
};
RemoteUI::RemoteUI(int socket, CharCoord dimensions)
RemoteUI::RemoteUI(int socket, DisplayCoord dimensions)
: m_socket_watcher(socket, [this](FDWatcher& watcher, EventMode mode) {
const int sock = watcher.fd();
bool disconnect = false;
@ -380,7 +380,7 @@ RemoteUI::~RemoteUI()
}
void RemoteUI::menu_show(ConstArrayView<DisplayLine> choices,
CharCoord anchor, Face fg, Face bg,
DisplayCoord anchor, Face fg, Face bg,
MenuStyle style)
{
MsgWriter msg{m_socket_watcher.fd(), MessageType::MenuShow};
@ -403,7 +403,7 @@ void RemoteUI::menu_hide()
}
void RemoteUI::info_show(StringView title, StringView content,
CharCoord anchor, Face face,
DisplayCoord anchor, Face face,
InfoStyle style)
{
MsgWriter msg{m_socket_watcher.fd(), MessageType::InfoShow};
@ -466,7 +466,7 @@ Key RemoteUI::get_key()
return key;
}
CharCoord RemoteUI::dimensions()
DisplayCoord RemoteUI::dimensions()
{
return m_dimensions;
}
@ -535,7 +535,7 @@ RemoteClient::RemoteClient(StringView session, std::unique_ptr<UserInterface>&&
case MessageType::MenuShow:
{
auto choices = reader.read_vector<DisplayLine>();
auto anchor = reader.read<CharCoord>();
auto anchor = reader.read<DisplayCoord>();
auto fg = reader.read<Face>();
auto bg = reader.read<Face>();
auto style = reader.read<MenuStyle>();
@ -552,7 +552,7 @@ RemoteClient::RemoteClient(StringView session, std::unique_ptr<UserInterface>&&
{
auto title = reader.read<String>();
auto content = reader.read<String>();
auto anchor = reader.read<CharCoord>();
auto anchor = reader.read<DisplayCoord>();
auto face = reader.read<Face>();
auto style = reader.read<InfoStyle>();
m_ui->info_show(title, content, anchor, face, style);
@ -643,7 +643,7 @@ private:
case MessageType::Connect:
{
auto init_command = m_reader.read<String>();
auto dimensions = m_reader.read<CharCoord>();
auto dimensions = m_reader.read<DisplayCoord>();
auto env_vars = m_reader.read_idmap<String, MemoryDomain::EnvVars>();
RemoteUI* ui = new RemoteUI{sock, dimensions};
if (auto* client = ClientManager::instance().create_client(

View File

@ -38,7 +38,7 @@ SelectionList::SelectionList(Buffer& buffer, Vector<Selection> s)
namespace
{
ByteCoord update_insert(ByteCoord coord, ByteCoord begin, ByteCoord end)
BufferCoord update_insert(BufferCoord coord, BufferCoord begin, BufferCoord end)
{
if (coord < begin)
return coord;
@ -50,7 +50,7 @@ ByteCoord update_insert(ByteCoord coord, ByteCoord begin, ByteCoord end)
}
/* For reference
ByteCoord update_erase(ByteCoord coord, ByteCoord begin, ByteCoord end)
BufferCoord update_erase(BufferCoord coord, BufferCoord begin, BufferCoord end)
{
if (coord < begin)
return coord;
@ -101,8 +101,8 @@ Iterator merge_overlapping(Iterator begin, Iterator end, size_t& main, OverlapsF
// *after* the previous one.
struct ForwardChangesTracker
{
ByteCoord cur_pos; // last change position at current modification
ByteCoord old_pos; // last change position at start
BufferCoord cur_pos; // last change position at current modification
BufferCoord old_pos; // last change position at start
void update(const Buffer::Change& change)
{
@ -127,7 +127,7 @@ struct ForwardChangesTracker
timestamp = buffer.timestamp();
}
ByteCoord get_old_coord(ByteCoord coord) const
BufferCoord get_old_coord(BufferCoord coord) const
{
kak_assert(cur_pos <= coord);
auto pos_change = cur_pos - old_pos;
@ -141,7 +141,7 @@ struct ForwardChangesTracker
return coord;
}
ByteCoord get_new_coord(ByteCoord coord) const
BufferCoord get_new_coord(BufferCoord coord) const
{
kak_assert(old_pos <= coord);
auto pos_change = cur_pos - old_pos;
@ -155,14 +155,14 @@ struct ForwardChangesTracker
return coord;
}
ByteCoord get_new_coord_tolerant(ByteCoord coord) const
BufferCoord get_new_coord_tolerant(BufferCoord coord) const
{
if (coord < old_pos)
return cur_pos;
return get_new_coord(coord);
}
bool relevant(const Buffer::Change& change, ByteCoord old_coord) const
bool 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
@ -202,7 +202,7 @@ void update_forward(ConstArrayView<Buffer::Change> changes, Vector<Selection>& s
ForwardChangesTracker changes_tracker;
auto change_it = changes.begin();
auto advance_while_relevant = [&](const ByteCoord& pos) mutable {
auto advance_while_relevant = [&](const BufferCoord& pos) mutable {
while (change_it != changes.end() and changes_tracker.relevant(*change_it, pos))
changes_tracker.update(*change_it++);
};
@ -227,7 +227,7 @@ void update_backward(ConstArrayView<Buffer::Change> changes, Vector<Selection>&
using ReverseIt = std::reverse_iterator<const Buffer::Change*>;
auto change_it = ReverseIt(changes.end());
auto change_end = ReverseIt(changes.begin());
auto advance_while_relevant = [&](const ByteCoord& pos) mutable {
auto advance_while_relevant = [&](const BufferCoord& pos) mutable {
while (change_it != change_end)
{
auto change = *change_it;
@ -314,7 +314,7 @@ Vector<Selection> compute_modified_ranges(Buffer& buffer, size_t timestamp)
for (auto& range : ranges)
{
range.anchor() = std::min(range.anchor(), end_coord);
range.cursor() = std::min<ByteCoord>(range.cursor(), end_coord);
range.cursor() = std::min<BufferCoord>(range.cursor(), end_coord);
}
auto touches = [&](const Selection& lhs, const Selection& rhs) {
@ -401,7 +401,7 @@ void SelectionList::check_invariant() const
return;
const auto end_coord = buffer.end_coord();
ByteCoord last_min{0,0};
BufferCoord last_min{0,0};
for (auto& sel : m_selections)
{
auto& min = sel.min();
@ -409,11 +409,11 @@ void SelectionList::check_invariant() const
last_min = min;
const auto anchor = sel.anchor();
kak_assert(anchor >= ByteCoord{0,0} and anchor < end_coord);
kak_assert(anchor >= BufferCoord{0,0} and anchor < end_coord);
kak_assert(anchor.column < buffer[anchor.line].length());
const auto cursor = sel.cursor();
kak_assert(cursor >= ByteCoord{0,0} and cursor < end_coord);
kak_assert(cursor >= BufferCoord{0,0} and cursor < end_coord);
kak_assert(cursor.column < buffer[cursor.line].length());
}
#endif
@ -463,7 +463,7 @@ void SelectionList::sort_and_merge_overlapping()
merge_overlapping();
}
static inline void _avoid_eol(const Buffer& buffer, ByteCoord& coord)
static inline void _avoid_eol(const Buffer& buffer, BufferCoord& coord)
{
auto column = coord.column;
auto line = buffer[coord.line];
@ -481,7 +481,7 @@ void SelectionList::avoid_eol()
}
}
ByteCoord prepare_insert(Buffer& buffer, const Selection& sel, InsertMode mode)
BufferCoord prepare_insert(Buffer& buffer, const Selection& sel, InsertMode mode)
{
switch (mode)
{
@ -588,7 +588,7 @@ void SelectionList::erase()
changes_tracker.update(*m_buffer, m_timestamp);
}
ByteCoord back_coord = m_buffer->back_coord();
BufferCoord back_coord = m_buffer->back_coord();
for (auto& sel : m_selections)
{
if (sel.anchor() > back_coord)
@ -624,10 +624,10 @@ Selection selection_from_string(StringView desc)
if (comma == desc.end() or dot_anchor == comma or dot_cursor == desc.end())
throw runtime_error(format("'{}' does not follow <line>.<column>,<line>.<column> format", desc));
ByteCoord anchor{str_to_int({desc.begin(), dot_anchor}) - 1,
BufferCoord anchor{str_to_int({desc.begin(), dot_anchor}) - 1,
str_to_int({dot_anchor+1, comma}) - 1};
ByteCoord cursor{str_to_int({comma+1, dot_cursor}) - 1,
BufferCoord cursor{str_to_int({comma+1, dot_cursor}) - 1,
str_to_int({dot_cursor+1, desc.end()}) - 1};
return Selection{anchor, cursor};

View File

@ -14,19 +14,19 @@ struct Selection
static constexpr MemoryDomain Domain = MemoryDomain::Selections;
Selection() = default;
Selection(ByteCoord pos) : Selection(pos,pos) {}
Selection(ByteCoord anchor, ByteCoord cursor,
Selection(BufferCoord pos) : Selection(pos,pos) {}
Selection(BufferCoord anchor, BufferCoord cursor,
CaptureList captures = {})
: m_anchor{anchor}, m_cursor{cursor},
m_captures(std::move(captures)) {}
void merge_with(const Selection& range);
ByteCoord& anchor() { return m_anchor; }
ByteCoordAndTarget& cursor() { return m_cursor; }
BufferCoord& anchor() { return m_anchor; }
BufferCoordAndTarget& cursor() { return m_cursor; }
const ByteCoord& anchor() const { return m_anchor; }
const ByteCoordAndTarget& cursor() const { return m_cursor; }
const BufferCoord& anchor() const { return m_anchor; }
const BufferCoordAndTarget& cursor() const { return m_cursor; }
CaptureList& captures() { return m_captures; }
const CaptureList& captures() const { return m_captures; }
@ -36,15 +36,15 @@ struct Selection
return m_anchor == other.m_anchor and m_cursor == other.m_cursor;
}
const ByteCoord& min() const { return m_anchor < m_cursor ? m_anchor : m_cursor; }
const ByteCoord& max() const { return m_anchor < m_cursor ? m_cursor : m_anchor; }
const BufferCoord& min() const { return m_anchor < m_cursor ? m_anchor : m_cursor; }
const BufferCoord& max() const { return m_anchor < m_cursor ? m_cursor : m_anchor; }
ByteCoord& min() { return m_anchor < m_cursor ? m_anchor : m_cursor; }
ByteCoord& max() { return m_anchor < m_cursor ? m_cursor : m_anchor; }
BufferCoord& min() { return m_anchor < m_cursor ? m_anchor : m_cursor; }
BufferCoord& max() { return m_anchor < m_cursor ? m_cursor : m_anchor; }
private:
ByteCoord m_anchor;
ByteCoordAndTarget m_cursor;
BufferCoord m_anchor;
BufferCoordAndTarget m_cursor;
CaptureList m_captures;
};

View File

@ -341,7 +341,7 @@ Selection select_paragraph(const Buffer& buffer, const Selection& selection, int
{
BufferIterator first = buffer.iterator_at(selection.cursor());
if (not (flags & ObjectFlags::ToEnd) and first.coord() > ByteCoord{0,1} and
if (not (flags & ObjectFlags::ToEnd) and first.coord() > BufferCoord{0,1} and
*(first-1) == '\n' and *(first-2) == '\n')
--first;
else if ((flags & ObjectFlags::ToEnd) and
@ -565,10 +565,10 @@ Selection select_argument(const Buffer& buffer, const Selection& selection,
Selection select_lines(const Buffer& buffer, const Selection& selection)
{
ByteCoord anchor = selection.anchor();
ByteCoord cursor = selection.cursor();
ByteCoord& to_line_start = anchor <= cursor ? anchor : cursor;
ByteCoord& to_line_end = anchor <= cursor ? cursor : anchor;
BufferCoord anchor = selection.anchor();
BufferCoord cursor = selection.cursor();
BufferCoord& to_line_start = anchor <= cursor ? anchor : cursor;
BufferCoord& to_line_end = anchor <= cursor ? cursor : anchor;
to_line_start.column = 0;
to_line_end.column = buffer[to_line_end.line].length()-1;
@ -578,10 +578,10 @@ Selection select_lines(const Buffer& buffer, const Selection& selection)
Selection trim_partial_lines(const Buffer& buffer, const Selection& selection)
{
ByteCoord anchor = selection.anchor();
ByteCoord cursor = selection.cursor();
ByteCoord& to_line_start = anchor <= cursor ? anchor : cursor;
ByteCoord& to_line_end = anchor <= cursor ? cursor : anchor;
BufferCoord anchor = selection.anchor();
BufferCoord cursor = selection.cursor();
BufferCoord& to_line_start = anchor <= cursor ? anchor : cursor;
BufferCoord& to_line_end = anchor <= cursor ? cursor : anchor;
if (to_line_start.column != 0)
to_line_start = to_line_start.line+1;
@ -591,7 +591,7 @@ Selection trim_partial_lines(const Buffer& buffer, const Selection& selection)
return selection;
auto prev_line = to_line_end.line-1;
to_line_end = ByteCoord{ prev_line, buffer[prev_line].length()-1 };
to_line_end = BufferCoord{ prev_line, buffer[prev_line].length()-1 };
}
if (to_line_start > to_line_end)

View File

@ -14,7 +14,7 @@ namespace Kakoune
inline Selection keep_direction(Selection res, const Selection& ref)
{
if ((res.cursor() < res.anchor()) != (ref.cursor() < ref.anchor()))
std::swap<ByteCoord>(res.cursor(), res.anchor());
std::swap<BufferCoord>(res.cursor(), res.anchor());
return res;
}
@ -117,9 +117,9 @@ Selection select_to_reverse(const Buffer& buffer, const Selection& selection,
template<bool only_move>
Selection select_to_line_end(const Buffer& buffer, const Selection& selection)
{
ByteCoord begin = selection.cursor();
BufferCoord begin = selection.cursor();
LineCount line = begin.line;
ByteCoord end = utf8::previous(buffer.iterator_at({line, buffer[line].length() - 1}),
BufferCoord end = utf8::previous(buffer.iterator_at({line, buffer[line].length() - 1}),
buffer.iterator_at(line)).coord();
if (end < begin) // Do not go backward when cursor is on eol
end = begin;
@ -129,8 +129,8 @@ Selection select_to_line_end(const Buffer& buffer, const Selection& selection)
template<bool only_move>
Selection select_to_line_begin(const Buffer& buffer, const Selection& selection)
{
ByteCoord begin = selection.cursor();
ByteCoord end = begin.line;
BufferCoord begin = selection.cursor();
BufferCoord end = begin.line;
return {only_move ? end : begin, end};
}

View File

@ -366,7 +366,7 @@ bool subsequence_match(StringView str, StringView subseq)
return true;
}
String expand_tabs(StringView line, CharCount tabstop, CharCount col)
String expand_tabs(StringView line, ColumnCount tabstop, ColumnCount col)
{
String res;
res.reserve(line.length());
@ -374,23 +374,23 @@ String expand_tabs(StringView line, CharCount tabstop, CharCount col)
{
if (*it == '\t')
{
CharCount end_col = (col / tabstop + 1) * tabstop;
ColumnCount end_col = (col / tabstop + 1) * tabstop;
res += String{' ', end_col - col};
col = end_col;
++it;
}
else
{
auto char_end = utf8::next(it, end);
res += {it, char_end};
++col;
it = char_end;
auto char_beg = it;
auto cp = utf8::read_codepoint(it, end);
res += {char_beg, it};
col += get_width(cp);
}
}
return res;
}
Vector<StringView> wrap_lines(StringView text, CharCount max_width)
Vector<StringView> wrap_lines(StringView text, ColumnCount max_width)
{
if (max_width <= 0)
throw runtime_error("Invalid max width");
@ -416,9 +416,10 @@ Vector<StringView> wrap_lines(StringView text, CharCount max_width)
while (word_end != end and categorize(*word_end) == cat)
++word_end;
while (word_end > line_begin and word_end - line_begin >= max_width)
while (word_end > line_begin and
StringView{line_begin.base(), word_end.base()}.column_length() >= max_width)
{
auto line_end = last_word_end <= line_begin ? line_begin + max_width
auto line_end = last_word_end <= line_begin ? Utf8It{utf8::advance(line_begin.base(), text.end(), max_width), text}
: last_word_end;
lines.emplace_back(line_begin.base(), line_end.base());

View File

@ -65,18 +65,26 @@ public:
{ return utf8::codepoint(utf8::advance(begin(), end(), pos), end()); }
CharCount char_length() const { return utf8::distance(begin(), end()); }
ColumnCount column_length() const { return utf8::column_distance(begin(), end()); }
[[gnu::always_inline]]
bool empty() const { return type().length() == 0_byte; }
ByteCount byte_count_to(CharCount count) const
{ return utf8::advance(begin(), end(), (int)count) - begin(); }
{ return utf8::advance(begin(), end(), count) - begin(); }
ByteCount byte_count_to(ColumnCount count) const
{ return utf8::advance(begin(), end(), count) - begin(); }
CharCount char_count_to(ByteCount count) const
{ return utf8::distance(begin(), begin() + (int)count); }
ColumnCount column_count_to(ByteCount count) const
{ return utf8::column_distance(begin(), begin() + (int)count); }
StringView substr(ByteCount from, ByteCount length = INT_MAX) const;
StringView substr(CharCount from, CharCount length = INT_MAX) const;
StringView substr(ColumnCount from, ColumnCount length = INT_MAX) const;
private:
[[gnu::always_inline]]
@ -103,6 +111,14 @@ public:
while (count-- > 0)
utf8::dump(std::back_inserter(*this), cp);
}
explicit String(Codepoint cp, ColumnCount count)
{
kak_assert(count % get_width(cp) == 0);
int cp_count = (int)count / get_width(cp);
reserve(utf8::codepoint_size(cp) * cp_count);
while (cp_count-- > 0)
utf8::dump(std::back_inserter(*this), cp);
}
String(const char* begin, const char* end) : m_data(begin, end-begin) {}
[[gnu::always_inline]]
@ -251,7 +267,16 @@ inline StringView StringOps<Type, CharType>::substr(CharCount from, CharCount le
{
if (length < 0)
length = INT_MAX;
auto beg = utf8::advance(begin(), end(), (int)from);
auto beg = utf8::advance(begin(), end(), from);
return StringView{ beg, utf8::advance(beg, end(), length) };
}
template<typename Type, typename CharType>
inline StringView StringOps<Type, CharType>::substr(ColumnCount from, ColumnCount length) const
{
if (length < 0)
length = INT_MAX;
auto beg = utf8::advance(begin(), end(), from);
return StringView{ beg, utf8::advance(beg, end(), length) };
}
@ -358,9 +383,9 @@ inline bool prefix_match(StringView str, StringView prefix)
bool subsequence_match(StringView str, StringView subseq);
String expand_tabs(StringView line, CharCount tabstop, CharCount col = 0);
String expand_tabs(StringView line, ColumnCount tabstop, ColumnCount col = 0);
Vector<StringView> wrap_lines(StringView text, CharCount max_width);
Vector<StringView> wrap_lines(StringView text, ColumnCount max_width);
namespace detail
{

View File

@ -48,6 +48,11 @@ inline bool is_basic_alpha(Codepoint c)
return (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z');
}
inline size_t get_width(Codepoint c)
{
return wcwidth((wchar_t)c);
}
enum class CharCategories
{
Blank,

View File

@ -158,6 +158,18 @@ inline constexpr CharCount operator"" _char(unsigned long long int value)
return CharCount(value);
}
struct ColumnCount : public StronglyTypedNumber<ColumnCount, int>
{
[[gnu::always_inline]]
constexpr ColumnCount(int value = 0) : StronglyTypedNumber<ColumnCount>(value) {}
};
[[gnu::always_inline]]
inline constexpr ColumnCount operator"" _col(unsigned long long int value)
{
return ColumnCount(value);
}
}
#endif // units_hh_INCLUDED

View File

@ -13,7 +13,7 @@ namespace Kakoune
class String;
class DisplayBuffer;
class DisplayLine;
struct CharCoord;
struct DisplayCoord;
struct Face;
struct Key;
@ -42,13 +42,13 @@ public:
virtual ~UserInterface() {}
virtual void menu_show(ConstArrayView<DisplayLine> choices,
CharCoord anchor, Face fg, Face bg,
DisplayCoord anchor, Face fg, Face bg,
MenuStyle style) = 0;
virtual void menu_select(int selected) = 0;
virtual void menu_hide() = 0;
virtual void info_show(StringView title, StringView content,
CharCoord anchor, Face face,
DisplayCoord anchor, Face face,
InfoStyle style) = 0;
virtual void info_hide() = 0;
@ -60,7 +60,7 @@ public:
const DisplayLine& mode_line,
const Face& default_face) = 0;
virtual CharCoord dimensions() = 0;
virtual DisplayCoord dimensions() = 0;
virtual bool is_key_available() = 0;
virtual Key get_key() = 0;

View File

@ -25,97 +25,6 @@ inline bool is_character_start(char c)
return (c & 0xC0) != 0x80;
}
template<typename Iterator>
void to_next(Iterator& it, const Iterator& end)
{
if (it != end and read(it) & 0x80)
while (it != end and (*(it) & 0xC0) == 0x80)
++it;
}
// returns an iterator to next character first byte
template<typename Iterator>
Iterator next(Iterator it, const Iterator& end)
{
to_next(it, end);
return it;
}
// returns it's parameter if it points to a character first byte,
// or else returns next character first byte
template<typename Iterator>
Iterator finish(Iterator it, const Iterator& end)
{
while (it != end and (*(it) & 0xC0) == 0x80)
++it;
return it;
}
template<typename Iterator>
void to_previous(Iterator& it, const Iterator& begin)
{
while (it != begin and (*(--it) & 0xC0) == 0x80)
;
}
// returns an iterator to the previous character first byte
template<typename Iterator>
Iterator previous(Iterator it, const Iterator& begin)
{
to_previous(it, begin);
return it;
}
// returns an iterator pointing to the first byte of the
// dth character after (or before if d < 0) the character
// pointed by it
template<typename Iterator>
Iterator advance(Iterator it, const Iterator& end, CharCount d)
{
if (it == end)
return it;
if (d < 0)
{
while (it != end and d != 0)
{
if (is_character_start(*--it))
++d;
}
}
else if (d > 0)
{
while (it != end and d != 0)
{
if (is_character_start(*++it))
--d;
}
}
return it;
}
// returns the character count between begin and end
template<typename Iterator>
CharCount distance(Iterator begin, const Iterator& end)
{
CharCount dist = 0;
while (begin != end)
{
if (is_character_start(read(begin)))
++dist;
}
return dist;
}
// returns an iterator to the first byte of the character it is into
template<typename Iterator>
Iterator character_start(Iterator it, const Iterator& begin)
{
while (it != begin and not is_character_start(*it))
--it;
return it;
}
namespace InvalidPolicy
{
@ -213,6 +122,139 @@ inline ByteCount codepoint_size(Codepoint cp)
throw invalid_codepoint{};
}
template<typename Iterator>
void to_next(Iterator& it, const Iterator& end)
{
if (it != end and read(it) & 0x80)
while (it != end and (*(it) & 0xC0) == 0x80)
++it;
}
// returns an iterator to next character first byte
template<typename Iterator>
Iterator next(Iterator it, const Iterator& end)
{
to_next(it, end);
return it;
}
// returns it's parameter if it points to a character first byte,
// or else returns next character first byte
template<typename Iterator>
Iterator finish(Iterator it, const Iterator& end)
{
while (it != end and (*(it) & 0xC0) == 0x80)
++it;
return it;
}
template<typename Iterator>
void to_previous(Iterator& it, const Iterator& begin)
{
while (it != begin and (*(--it) & 0xC0) == 0x80)
;
}
// returns an iterator to the previous character first byte
template<typename Iterator>
Iterator previous(Iterator it, const Iterator& begin)
{
to_previous(it, begin);
return it;
}
// returns an iterator pointing to the first byte of the
// dth character after (or before if d < 0) the character
// pointed by it
template<typename Iterator>
Iterator advance(Iterator it, const Iterator& end, CharCount d)
{
if (it == end)
return it;
if (d < 0)
{
while (it != end and d != 0)
{
if (is_character_start(*--it))
++d;
}
}
else if (d > 0)
{
while (it != end and d != 0)
{
if (is_character_start(*++it))
--d;
}
}
return it;
}
// returns an iterator pointing to the first byte of the
// character at the dth column after (or before if d < 0)
// the character pointed by it
template<typename Iterator>
Iterator advance(Iterator it, const Iterator& end, ColumnCount d)
{
if (it == end)
return it;
if (d < 0)
{
while (it != end and d < 0)
{
auto cur = it;
to_previous(it, end);
d += get_width(codepoint(it, cur));
}
}
else if (d > 0)
{
auto begin = it;
while (it != end and d > 0)
{
d -= get_width(read_codepoint(it, end));
if (it != end and d < 0)
to_previous(it, begin);
}
}
return it;
}
// returns the character count between begin and end
template<typename Iterator>
CharCount distance(Iterator begin, const Iterator& end)
{
CharCount dist = 0;
while (begin != end)
{
if (is_character_start(read(begin)))
++dist;
}
return dist;
}
// returns the column count between begin and end
template<typename Iterator>
ColumnCount column_distance(Iterator begin, const Iterator& end)
{
ColumnCount dist = 0;
while (begin != end)
dist += get_width(read_codepoint(begin, end));
return dist;
}
// returns an iterator to the first byte of the character it is into
template<typename Iterator>
Iterator character_start(Iterator it, const Iterator& begin)
{
while (it != begin and not is_character_start(*it))
--it;
return it;
}
template<typename OutputIterator>
void dump(OutputIterator&& it, Codepoint cp)
{

View File

@ -58,20 +58,20 @@ void Window::center_line(LineCount buffer_line)
display_line_at(buffer_line, m_dimensions.line/2_line);
}
void Window::scroll(CharCount offset)
void Window::scroll(ColumnCount offset)
{
m_position.column = std::max(0_char, m_position.column + offset);
m_position.column = std::max(0_col, m_position.column + offset);
}
void Window::display_column_at(CharCount buffer_column, CharCount display_column)
void Window::display_column_at(ColumnCount buffer_column, ColumnCount display_column)
{
if (display_column >= 0 or display_column < m_dimensions.column)
m_position.column = std::max(0_char, buffer_column - display_column);
m_position.column = std::max(0_col, buffer_column - display_column);
}
void Window::center_column(CharCount buffer_column)
void Window::center_column(ColumnCount buffer_column)
{
display_column_at(buffer_column, m_dimensions.column/2_char);
display_column_at(buffer_column, m_dimensions.column/2_col);
}
Window::Setup Window::build_setup(const Context& context) const
@ -117,7 +117,7 @@ const DisplayBuffer& Window::update_display_buffer(const Context& context)
DisplayBuffer::LineList& lines = m_display_buffer.lines();
lines.clear();
if (m_dimensions == CharCoord{0,0})
if (m_dimensions == DisplayCoord{0,0})
return m_display_buffer;
kak_assert(&buffer() == &context.buffer());
@ -154,13 +154,13 @@ const DisplayBuffer& Window::update_display_buffer(const Context& context)
return m_display_buffer;
}
void Window::set_position(CharCoord position)
void Window::set_position(DisplayCoord position)
{
m_position.line = std::max(0_line, position.line);
m_position.column = std::max(0_char, position.column);
m_position.column = std::max(0_col, position.column);
}
void Window::set_dimensions(CharCoord dimensions)
void Window::set_dimensions(DisplayCoord dimensions)
{
if (m_dimensions != dimensions)
{
@ -182,12 +182,12 @@ static LineCount adapt_view_pos(LineCount line, LineCount offset,
return view_pos;
}
static CharCount adapt_view_pos(const DisplayBuffer& display_buffer, CharCount offset,
ByteCoord pos, CharCount view_pos, CharCount view_size)
static ColumnCount adapt_view_pos(const DisplayBuffer& display_buffer, ColumnCount offset,
BufferCoord pos, ColumnCount view_pos, ColumnCount view_size)
{
offset = std::min(offset, (view_size + 1) / 2);
CharCount buffer_column = 0;
CharCount non_buffer_column = 0;
ColumnCount buffer_column = 0;
ColumnCount non_buffer_column = 0;
for (auto& line : display_buffer.lines())
{
for (auto& atom : line)
@ -196,12 +196,12 @@ static CharCount adapt_view_pos(const DisplayBuffer& display_buffer, CharCount o
{
if (atom.begin() <= pos and atom.end() > pos)
{
CharCount pos_beg, pos_end;
ColumnCount pos_beg, pos_end;
if (atom.type() == DisplayAtom::BufferRange)
{
auto& buf = atom.buffer();
pos_beg = buffer_column +
char_length(buf, atom.begin(), pos);
column_length(buf, atom.begin(), pos);
pos_end = pos_beg+1;
}
else
@ -211,7 +211,7 @@ static CharCount adapt_view_pos(const DisplayBuffer& display_buffer, CharCount o
}
if (pos_beg - offset < view_pos)
return std::max(0_char, pos_beg - offset);
return std::max(0_col, pos_beg - offset);
if (pos_end + offset >= view_pos + view_size - non_buffer_column)
return pos_end + offset - view_size + non_buffer_column;
@ -231,7 +231,7 @@ void Window::scroll_to_keep_selection_visible_ifn(const Context& context)
const auto& anchor = selection.anchor();
const auto& cursor = selection.cursor();
const CharCoord offset = options()["scrolloff"].get<CharCoord>();
const DisplayCoord offset = options()["scrolloff"].get<DisplayCoord>();
// scroll lines if needed, try to get as much of the selection visible as possible
m_position.line = adapt_view_pos(anchor.line, offset.line, m_position.line,
@ -262,17 +262,17 @@ void Window::scroll_to_keep_selection_visible_ifn(const Context& context)
namespace
{
CharCount find_display_column(const DisplayLine& line, const Buffer& buffer,
ByteCoord coord)
ColumnCount find_display_column(const DisplayLine& line, const Buffer& buffer,
BufferCoord coord)
{
CharCount column = 0;
ColumnCount column = 0;
for (auto& atom : line)
{
if (atom.has_buffer_range() and
coord >= atom.begin() and coord < atom.end())
{
if (atom.type() == DisplayAtom::BufferRange)
column += char_length(buffer, atom.begin(), coord);
column += column_length(buffer, atom.begin(), coord);
return column;
}
column += atom.length();
@ -280,20 +280,20 @@ CharCount find_display_column(const DisplayLine& line, const Buffer& buffer,
return column;
}
ByteCoord find_buffer_coord(const DisplayLine& line, const Buffer& buffer,
CharCount column)
BufferCoord find_buffer_coord(const DisplayLine& line, const Buffer& buffer,
ColumnCount column)
{
auto& range = line.range();
for (auto& atom : line)
{
CharCount len = atom.length();
ColumnCount len = atom.length();
if (atom.has_buffer_range() and column < len)
{
if (atom.type() == DisplayAtom::BufferRange)
return buffer.clamp(
utf8::advance(buffer.iterator_at(atom.begin()),
buffer.iterator_at(range.end),
std::max(0_char, column)).coord());
std::max(0_col, column)).coord());
return buffer.clamp(atom.begin());
}
column -= len;
@ -302,7 +302,7 @@ ByteCoord find_buffer_coord(const DisplayLine& line, const Buffer& buffer,
}
}
CharCoord Window::display_position(ByteCoord coord) const
DisplayCoord Window::display_position(BufferCoord coord) const
{
LineCount l = 0;
for (auto& line : m_display_buffer.lines())
@ -315,25 +315,25 @@ CharCoord Window::display_position(ByteCoord coord) const
return { 0, 0 };
}
ByteCoord Window::buffer_coord(CharCoord coord) const
BufferCoord Window::buffer_coord(DisplayCoord coord) const
{
if (m_display_buffer.lines().empty())
return {0,0};
if (coord <= 0_line)
coord = {0,0};
if ((int)coord.line >= m_display_buffer.lines().size())
coord = CharCoord{(int)m_display_buffer.lines().size()-1, INT_MAX};
coord = DisplayCoord{(int)m_display_buffer.lines().size()-1, INT_MAX};
return find_buffer_coord(m_display_buffer.lines()[(int)coord.line],
buffer(), coord.column);
}
ByteCoord Window::offset_coord(ByteCoord coord, CharCount offset)
BufferCoord Window::offset_coord(BufferCoord coord, CharCount offset)
{
return buffer().offset_coord(coord, offset);
}
ByteCoordAndTarget Window::offset_coord(ByteCoordAndTarget coord, LineCount offset)
BufferCoordAndTarget Window::offset_coord(BufferCoordAndTarget coord, LineCount offset)
{
auto line = clamp(coord.line + offset, 0_line, buffer().line_count()-1);
DisplayBuffer display_buffer;
@ -349,7 +349,7 @@ ByteCoordAndTarget Window::offset_coord(ByteCoordAndTarget coord, LineCount offs
m_highlighters.highlight(input_handler.context(), HighlightFlags::MoveOnly, display_buffer, range);
m_builtin_highlighters.highlight(input_handler.context(), HighlightFlags::MoveOnly, display_buffer, range);
CharCount column = coord.target == -1 ? find_display_column(lines[0], buffer(), coord) : coord.target;
ColumnCount column = coord.target == -1 ? find_display_column(lines[0], buffer(), coord) : coord.target;
return { find_buffer_coord(lines[1], buffer(), column), column };
}

View File

@ -18,24 +18,24 @@ public:
Window(Buffer& buffer);
~Window();
const CharCoord& position() const { return m_position; }
void set_position(CharCoord position);
const DisplayCoord& position() const { return m_position; }
void set_position(DisplayCoord position);
const CharCoord& dimensions() const { return m_dimensions; }
void set_dimensions(CharCoord dimensions);
const DisplayCoord& dimensions() const { return m_dimensions; }
void set_dimensions(DisplayCoord dimensions);
void scroll(LineCount offset);
void center_line(LineCount buffer_line);
void display_line_at(LineCount buffer_line, LineCount display_line);
void scroll(CharCount offset);
void center_column(CharCount buffer_column);
void display_column_at(CharCount buffer_column, CharCount display_column);
void scroll(ColumnCount offset);
void center_column(ColumnCount buffer_column);
void display_column_at(ColumnCount buffer_column, ColumnCount display_column);
const DisplayBuffer& update_display_buffer(const Context& context);
CharCoord display_position(ByteCoord coord) const;
ByteCoord buffer_coord(CharCoord coord) const;
DisplayCoord display_position(BufferCoord coord) const;
BufferCoord buffer_coord(DisplayCoord coord) const;
Highlighter& highlighters() { return m_highlighters; }
@ -44,8 +44,8 @@ public:
bool needs_redraw(const Context& context) const;
void force_redraw() { m_last_setup = Setup{}; }
ByteCoord offset_coord(ByteCoord coord, CharCount offset);
ByteCoordAndTarget offset_coord(ByteCoordAndTarget coord, LineCount offset);
BufferCoord offset_coord(BufferCoord coord, CharCount offset);
BufferCoordAndTarget offset_coord(BufferCoordAndTarget coord, LineCount offset);
void set_client(Client* client) { m_client = client; }
@ -61,8 +61,8 @@ private:
SafePtr<Buffer> m_buffer;
SafePtr<Client> m_client;
CharCoord m_position;
CharCoord m_dimensions;
DisplayCoord m_position;
DisplayCoord m_dimensions;
DisplayBuffer m_display_buffer;
HighlighterGroup m_highlighters;
@ -70,8 +70,8 @@ private:
struct Setup
{
CharCoord position;
CharCoord dimensions;
DisplayCoord position;
DisplayCoord dimensions;
size_t timestamp;
size_t main_selection;
Vector<BufferRange> selections;

View File

@ -0,0 +1 @@
j

View File

@ -0,0 +1,2 @@
1234%(5)67%(8)9012
一二三四五六

View File

@ -0,0 +1 @@
三:四