utf8 awareness in editor, highlighters and ncurses
This commit is contained in:
parent
5a267ab627
commit
7e046e3f0b
|
@ -5,6 +5,8 @@
|
||||||
#include "register.hh"
|
#include "register.hh"
|
||||||
#include "register_manager.hh"
|
#include "register_manager.hh"
|
||||||
|
|
||||||
|
#include "utf8_iterator.hh"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
|
@ -104,9 +106,9 @@ void Editor::move_selections(CharCount offset, SelectMode mode)
|
||||||
for (auto& sel : m_selections)
|
for (auto& sel : m_selections)
|
||||||
{
|
{
|
||||||
auto last = sel.last();
|
auto last = sel.last();
|
||||||
last = clamp(last + offset,
|
last = clamp(utf8::advance(last, offset),
|
||||||
buffer().iterator_at_line_begin(last),
|
buffer().iterator_at_line_begin(last),
|
||||||
buffer().iterator_at_line_end(last)-1);
|
utf8::previous(buffer().iterator_at_line_end(last)));
|
||||||
sel.selection = Selection(mode == SelectMode::Extend ? sel.first() : last, last);
|
sel.selection = Selection(mode == SelectMode::Extend ? sel.first() : last, last);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,8 +130,8 @@ void Editor::clear_selections()
|
||||||
check_invariant();
|
check_invariant();
|
||||||
BufferIterator pos = m_selections.back().last();
|
BufferIterator pos = m_selections.back().last();
|
||||||
|
|
||||||
if (*pos == '\n' and not pos.is_begin() and *(pos-1) != '\n')
|
if (*pos == '\n' and not pos.is_begin() and *utf8::previous(pos) != '\n')
|
||||||
--pos;
|
pos = utf8::previous(pos);
|
||||||
|
|
||||||
Selection sel = Selection(pos, pos);
|
Selection sel = Selection(pos, pos);
|
||||||
m_selections.clear();
|
m_selections.clear();
|
||||||
|
@ -227,14 +229,14 @@ public:
|
||||||
void on_insert(const BufferIterator& begin, const BufferIterator& end)
|
void on_insert(const BufferIterator& begin, const BufferIterator& end)
|
||||||
{
|
{
|
||||||
m_first = begin;
|
m_first = begin;
|
||||||
m_last = end-1;
|
m_last = utf8::previous(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_erase(const BufferIterator& begin, const BufferIterator& end)
|
void on_erase(const BufferIterator& begin, const BufferIterator& end)
|
||||||
{
|
{
|
||||||
m_first = begin;
|
m_first = begin;
|
||||||
if (m_first >= m_buffer.end())
|
if (m_first >= m_buffer.end())
|
||||||
m_first = m_buffer.end() - 1;
|
m_first = utf8::previous(m_buffer.end());
|
||||||
m_last = m_first;
|
m_last = m_first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,35 +297,38 @@ void Editor::end_edition()
|
||||||
--m_edition_level;
|
--m_edition_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using utf8_it = utf8::utf8_iterator<BufferIterator>;
|
||||||
|
|
||||||
IncrementalInserter::IncrementalInserter(Editor& editor, InsertMode mode)
|
IncrementalInserter::IncrementalInserter(Editor& editor, InsertMode mode)
|
||||||
: m_editor(editor), m_edition(editor), m_mode(mode)
|
: m_editor(editor), m_edition(editor), m_mode(mode)
|
||||||
{
|
{
|
||||||
m_editor.on_incremental_insertion_begin();
|
m_editor.on_incremental_insertion_begin();
|
||||||
|
Buffer& buffer = editor.m_buffer;
|
||||||
|
|
||||||
if (mode == InsertMode::Change)
|
if (mode == InsertMode::Change)
|
||||||
{
|
{
|
||||||
for (auto& sel : editor.m_selections)
|
for (auto& sel : editor.m_selections)
|
||||||
editor.m_buffer.erase(sel.begin(), sel.end());
|
buffer.erase(sel.begin(), sel.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& sel : m_editor.m_selections)
|
for (auto& sel : m_editor.m_selections)
|
||||||
{
|
{
|
||||||
BufferIterator first, last;
|
utf8_it first, last;
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case InsertMode::Insert: first = sel.end()-1; last = sel.begin(); break;
|
case InsertMode::Insert: first = utf8_it(sel.end()) - 1; last = sel.begin(); break;
|
||||||
case InsertMode::Change: first = sel.end()-1; last = sel.begin(); break;
|
case InsertMode::Change: first = utf8_it(sel.end()) - 1; last = sel.begin(); break;
|
||||||
case InsertMode::Append: first = sel.begin(); last = sel.end(); break;
|
case InsertMode::Append: first = sel.begin(); last = sel.end(); break;
|
||||||
|
|
||||||
case InsertMode::OpenLineBelow:
|
case InsertMode::OpenLineBelow:
|
||||||
case InsertMode::AppendAtLineEnd:
|
case InsertMode::AppendAtLineEnd:
|
||||||
first = m_editor.m_buffer.iterator_at_line_end(sel.end() - 1) - 1;
|
first = utf8_it(buffer.iterator_at_line_end(utf8::previous(sel.end()))) - 1;
|
||||||
last = first;
|
last = first;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InsertMode::OpenLineAbove:
|
case InsertMode::OpenLineAbove:
|
||||||
case InsertMode::InsertAtLineBegin:
|
case InsertMode::InsertAtLineBegin:
|
||||||
first = m_editor.m_buffer.iterator_at_line_begin(sel.begin());
|
first = buffer.iterator_at_line_begin(sel.begin());
|
||||||
if (mode == InsertMode::OpenLineAbove)
|
if (mode == InsertMode::OpenLineAbove)
|
||||||
--first;
|
--first;
|
||||||
else
|
else
|
||||||
|
@ -337,11 +342,11 @@ IncrementalInserter::IncrementalInserter(Editor& editor, InsertMode mode)
|
||||||
last = first;
|
last = first;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (first.is_end())
|
if (first.underlying_iterator().is_end())
|
||||||
--first;
|
--first;
|
||||||
if (last.is_end())
|
if (last.underlying_iterator().is_end())
|
||||||
--last;
|
--last;
|
||||||
sel.selection = Selection(first, last);
|
sel.selection = Selection(first.underlying_iterator(), last.underlying_iterator());
|
||||||
}
|
}
|
||||||
if (mode == InsertMode::OpenLineBelow or mode == InsertMode::OpenLineAbove)
|
if (mode == InsertMode::OpenLineBelow or mode == InsertMode::OpenLineAbove)
|
||||||
{
|
{
|
||||||
|
@ -351,8 +356,8 @@ IncrementalInserter::IncrementalInserter(Editor& editor, InsertMode mode)
|
||||||
for (auto& sel : m_editor.m_selections)
|
for (auto& sel : m_editor.m_selections)
|
||||||
{
|
{
|
||||||
// special case, the --first line above did nothing, so we need to compensate now
|
// special case, the --first line above did nothing, so we need to compensate now
|
||||||
if (sel.first() == buffer().begin() + 1)
|
if (sel.first() == utf8::next(buffer.begin()))
|
||||||
sel.selection = Selection(buffer().begin(), buffer().begin());
|
sel.selection = Selection(buffer.begin(), buffer.begin());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -363,7 +368,7 @@ IncrementalInserter::~IncrementalInserter()
|
||||||
for (auto& sel : m_editor.m_selections)
|
for (auto& sel : m_editor.m_selections)
|
||||||
{
|
{
|
||||||
if (m_mode == InsertMode::Append)
|
if (m_mode == InsertMode::Append)
|
||||||
sel = Selection(sel.first(), sel.last()-1);
|
sel = Selection(sel.first(), utf8::previous(sel.last()));
|
||||||
sel.selection.avoid_eol();
|
sel.selection.avoid_eol();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,7 +397,7 @@ void IncrementalInserter::erase()
|
||||||
for (auto& sel : m_editor.m_selections)
|
for (auto& sel : m_editor.m_selections)
|
||||||
{
|
{
|
||||||
BufferIterator pos = sel.last();
|
BufferIterator pos = sel.last();
|
||||||
m_editor.buffer().erase(pos-1, pos);
|
m_editor.buffer().erase(utf8::previous(pos), pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "color_registry.hh"
|
#include "color_registry.hh"
|
||||||
#include "highlighter_group.hh"
|
#include "highlighter_group.hh"
|
||||||
#include "string.hh"
|
#include "string.hh"
|
||||||
|
#include "utf8.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
@ -223,7 +224,7 @@ void highlight_selections(Window& window, DisplayBuffer& display_buffer)
|
||||||
[](DisplayAtom& atom) { atom.attribute |= Attributes::Underline; });
|
[](DisplayAtom& atom) { atom.attribute |= Attributes::Underline; });
|
||||||
|
|
||||||
const BufferIterator& last = sel.last();
|
const BufferIterator& last = sel.last();
|
||||||
highlight_range(display_buffer, last, last+1, false,
|
highlight_range(display_buffer, last, utf8::next(last), false,
|
||||||
[](DisplayAtom& atom) { atom.attribute |= Attributes::Reverse; });
|
[](DisplayAtom& atom) { atom.attribute |= Attributes::Reverse; });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include "window.hh"
|
#include "window.hh"
|
||||||
#include "register_manager.hh"
|
#include "register_manager.hh"
|
||||||
|
|
||||||
|
#include "utf8_iterator.hh"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#define CTRL(x) x - 'a' + 1
|
#define CTRL(x) x - 'a' + 1
|
||||||
|
@ -72,7 +74,7 @@ static void set_color(Color fg_color, Color bg_color)
|
||||||
|
|
||||||
NCursesUI::NCursesUI()
|
NCursesUI::NCursesUI()
|
||||||
{
|
{
|
||||||
// setlocale(LC_ALL, "");
|
//setlocale(LC_CTYPE, "");
|
||||||
initscr();
|
initscr();
|
||||||
cbreak();
|
cbreak();
|
||||||
noecho();
|
noecho();
|
||||||
|
@ -104,6 +106,13 @@ static void redraw(WINDOW* menu_win)
|
||||||
doupdate();
|
doupdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using utf8_it = utf8::utf8_iterator<String::iterator>;
|
||||||
|
void addutf8str(utf8_it begin, utf8_it end)
|
||||||
|
{
|
||||||
|
while (begin != end)
|
||||||
|
addch(*begin++);
|
||||||
|
}
|
||||||
|
|
||||||
void NCursesUI::draw_window(Window& window)
|
void NCursesUI::draw_window(Window& window)
|
||||||
{
|
{
|
||||||
int max_x,max_y;
|
int max_x,max_y;
|
||||||
|
@ -133,11 +142,16 @@ void NCursesUI::draw_window(Window& window)
|
||||||
getyx(stdscr, y,x);
|
getyx(stdscr, y,x);
|
||||||
if (content[content.length()-1] == '\n' and content.length() - 1 < max_x - x)
|
if (content[content.length()-1] == '\n' and content.length() - 1 < max_x - x)
|
||||||
{
|
{
|
||||||
addnstr(content.c_str(), (int)content.length() - 1);
|
addutf8str(utf8_it(content.begin()), utf8_it(content.end())-1);
|
||||||
addch(' ');
|
addch(' ');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
addnstr(content.c_str(), max_x - x);
|
{
|
||||||
|
utf8_it begin(content.begin()), end(content.end());
|
||||||
|
if (end - begin > max_x - x)
|
||||||
|
end = begin + (max_x - x);
|
||||||
|
addutf8str(begin, end);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++line_index;
|
++line_index;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user