home/src/display_buffer.cc

189 lines
4.5 KiB
C++
Raw Normal View History

2011-09-02 18:51:20 +02:00
#include "display_buffer.hh"
#include "assert.hh"
#include <algorithm>
2011-09-02 18:51:20 +02:00
namespace Kakoune
{
2012-03-08 22:23:29 +01:00
String DisplayAtom::content() const
{
2012-07-03 19:13:16 +02:00
switch (m_content_mode)
{
case BufferText:
return m_begin.buffer().string(m_begin, m_end);
2012-07-03 19:13:16 +02:00
case ReplacementText:
return m_replacement_text;
2012-07-03 19:13:16 +02:00
}
assert(false);
return "";
}
static DisplayCoord advance_coord(const DisplayCoord& pos,
const BufferIterator& begin,
const BufferIterator& end)
{
if (begin.line() == end.line())
return DisplayCoord(pos.line, pos.column + end.column() - begin.column());
else
return DisplayCoord(pos.line + end.line() - begin.line(), end.column());
}
static DisplayCoord advance_coord(const DisplayCoord& pos,
const String& str)
{
DisplayCoord res = pos;
for (auto c : str)
{
if (c == '\n')
{
++res.line;
res.column = 0;
}
else
++res.column;
}
return res;
}
2012-07-03 19:13:16 +02:00
DisplayCoord DisplayAtom::end_coord() const
{
2012-07-03 19:13:16 +02:00
switch (m_content_mode)
{
case BufferText:
return advance_coord(m_coord, m_begin, m_end);
2012-07-03 19:13:16 +02:00
case ReplacementText:
return advance_coord(m_coord, m_replacement_text);
2012-07-03 19:13:16 +02:00
}
assert(false);
return { 0, 0 };
}
BufferIterator DisplayAtom::iterator_at(const DisplayCoord& coord) const
{
2012-07-03 19:13:16 +02:00
if (m_content_mode != BufferText or coord <= m_coord)
return m_begin;
DisplayCoord pos = m_coord;
for (BufferIterator it = m_begin; it != m_end; ++it)
{
if (*it == '\n')
{
++pos.line;
pos.column = 0;
}
else
++pos.column;
if (coord <= pos)
return it+1;
}
return m_end;
}
DisplayCoord DisplayAtom::line_and_column_at(const BufferIterator& iterator) const
{
assert(iterator >= m_begin and iterator < m_end);
2012-07-03 19:13:16 +02:00
if (m_content_mode != BufferText)
return m_coord;
return advance_coord(m_coord, m_begin, iterator);
}
2011-09-02 18:51:20 +02:00
DisplayBuffer::DisplayBuffer()
{
}
DisplayBuffer::iterator DisplayBuffer::append(BufferIterator begin, BufferIterator end)
{
DisplayCoord coord;
if (not m_atoms.empty())
coord = m_atoms.back().end_coord();
m_atoms.push_back(DisplayAtom(std::move(coord), std::move(begin), std::move(end)));
return --(this->end());
}
DisplayBuffer::iterator DisplayBuffer::insert_empty_atom_before(iterator where)
{
assert(where != end());
iterator res = m_atoms.insert(
where, DisplayAtom(where->coord(), where->begin(), where->begin()));
return res;
}
DisplayBuffer::iterator DisplayBuffer::atom_containing(const BufferIterator& where)
{
return atom_containing(where, m_atoms.begin());
}
DisplayBuffer::iterator DisplayBuffer::atom_containing(const BufferIterator& where,
iterator start)
{
if (start == end() or where < start->begin())
return end();
while (start != end())
{
if (start->end() > where)
break;
++start;
}
return start;
}
DisplayBuffer::iterator DisplayBuffer::split(iterator atom, const BufferIterator& pos)
{
assert(atom->splitable());
assert(pos > atom->begin());
assert(pos < atom->end());
BufferIterator end = atom->m_end;
atom->m_end = pos;
DisplayAtom new_atom(atom->end_coord(), pos, end,
atom->fg_color(), atom->bg_color(), atom->attribute());
iterator insert_pos = atom;
++insert_pos;
m_atoms.insert(insert_pos, std::move(new_atom));
check_invariant();
return atom;
}
void DisplayBuffer::check_invariant() const
{
const_iterator prev_it;
for (const_iterator it = begin(); it != end(); ++it)
{
assert(it->end() >= it->begin());
if (it != begin())
{
assert(prev_it->end() == it->begin());
assert(prev_it->end_coord() == it->coord());
}
prev_it = it;
}
}
void DisplayBuffer::replace_atom_content(iterator atom,
2012-03-08 22:23:29 +01:00
const String& replacement)
{
2012-07-03 19:13:16 +02:00
atom->m_content_mode = DisplayAtom::ReplacementText;
atom->m_replacement_text = replacement;
// update coordinates of subsequents atoms
DisplayCoord new_coord = atom->end_coord();
while (true)
{
new_coord = atom->end_coord();
++atom;
if (atom == end() or new_coord == atom->m_coord)
break;
atom->m_coord = new_coord;
}
}
2011-09-02 18:51:20 +02:00
}