utf8 awareness in editor, highlighters and ncurses

This commit is contained in:
Maxime Coste 2012-10-08 14:27:43 +02:00
parent 5a267ab627
commit 7e046e3f0b
3 changed files with 43 additions and 23 deletions

View File

@ -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);
} }
} }

View File

@ -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; });
} }
} }

View File

@ -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;
} }