2011-09-02 18:51:20 +02:00
|
|
|
#include "display_buffer.hh"
|
|
|
|
|
2011-09-29 11:10:27 +02:00
|
|
|
#include "assert.hh"
|
2012-04-05 04:00:34 +02:00
|
|
|
#include <algorithm>
|
2011-09-29 10:55:08 +02:00
|
|
|
|
2011-09-02 18:51:20 +02:00
|
|
|
namespace Kakoune
|
|
|
|
{
|
|
|
|
|
2012-03-08 22:23:29 +01:00
|
|
|
String DisplayAtom::content() const
|
2011-10-15 06:45:49 +02:00
|
|
|
{
|
2012-07-03 19:13:16 +02:00
|
|
|
switch (m_content_mode)
|
|
|
|
{
|
|
|
|
case BufferText:
|
2011-10-15 06:45:49 +02:00
|
|
|
return m_begin.buffer().string(m_begin, m_end);
|
2012-07-03 19:13:16 +02:00
|
|
|
case ReplacementText:
|
2011-10-15 06:45:49 +02:00
|
|
|
return m_replacement_text;
|
2012-07-03 19:13:16 +02:00
|
|
|
}
|
|
|
|
assert(false);
|
|
|
|
return "";
|
2011-10-15 06:45:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static DisplayCoord advance_coord(const DisplayCoord& pos,
|
2012-05-29 02:33:55 +02:00
|
|
|
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)
|
2011-10-15 06:45:49 +02:00
|
|
|
{
|
|
|
|
DisplayCoord res = pos;
|
2012-05-29 02:33:55 +02:00
|
|
|
for (auto c : str)
|
2011-10-15 06:45:49 +02:00
|
|
|
{
|
2012-05-29 02:33:55 +02:00
|
|
|
if (c == '\n')
|
2011-10-15 06:45:49 +02:00
|
|
|
{
|
|
|
|
++res.line;
|
|
|
|
res.column = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
++res.column;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2012-07-03 19:13:16 +02:00
|
|
|
|
2011-10-15 06:45:49 +02:00
|
|
|
DisplayCoord DisplayAtom::end_coord() const
|
|
|
|
{
|
2012-07-03 19:13:16 +02:00
|
|
|
switch (m_content_mode)
|
|
|
|
{
|
|
|
|
case BufferText:
|
2011-10-15 06:45:49 +02:00
|
|
|
return advance_coord(m_coord, m_begin, m_end);
|
2012-07-03 19:13:16 +02:00
|
|
|
case ReplacementText:
|
2012-05-29 02:33:55 +02:00
|
|
|
return advance_coord(m_coord, m_replacement_text);
|
2012-07-03 19:13:16 +02:00
|
|
|
}
|
|
|
|
assert(false);
|
|
|
|
return { 0, 0 };
|
2011-10-15 06:45:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2011-10-15 06:45:49 +02:00
|
|
|
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;
|
|
|
|
|
2011-11-16 22:03:32 +01:00
|
|
|
if (coord <= pos)
|
2011-10-15 06:45:49 +02:00
|
|
|
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)
|
2011-10-15 06:45:49 +02:00
|
|
|
return m_coord;
|
|
|
|
|
|
|
|
return advance_coord(m_coord, m_begin, iterator);
|
|
|
|
}
|
|
|
|
|
2011-09-02 18:51:20 +02:00
|
|
|
DisplayBuffer::DisplayBuffer()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-07-03 23:23:07 +02:00
|
|
|
DisplayBuffer::iterator DisplayBuffer::append(BufferIterator begin, BufferIterator end)
|
2011-10-17 21:00:38 +02:00
|
|
|
{
|
2012-07-03 23:23:07 +02:00
|
|
|
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()));
|
2011-10-17 21:00:38 +02:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
DisplayBuffer::iterator DisplayBuffer::atom_containing(const BufferIterator& where)
|
|
|
|
{
|
2011-10-23 22:26:30 +02:00
|
|
|
return atom_containing(where, m_atoms.begin());
|
|
|
|
}
|
|
|
|
|
|
|
|
DisplayBuffer::iterator DisplayBuffer::atom_containing(const BufferIterator& where,
|
|
|
|
iterator start)
|
|
|
|
{
|
2012-07-03 21:12:05 +02:00
|
|
|
if (start == end() or where < start->begin())
|
2012-05-04 08:39:03 +02:00
|
|
|
return end();
|
|
|
|
|
2012-07-03 21:12:05 +02:00
|
|
|
while (start != end())
|
|
|
|
{
|
|
|
|
if (start->end() > where)
|
|
|
|
break;
|
|
|
|
++start;
|
|
|
|
}
|
|
|
|
return start;
|
2011-10-17 21:00:38 +02:00
|
|
|
}
|
|
|
|
|
2011-10-07 16:19:58 +02:00
|
|
|
DisplayBuffer::iterator DisplayBuffer::split(iterator atom, const BufferIterator& pos)
|
2011-09-29 10:55:08 +02:00
|
|
|
{
|
2012-07-03 23:23:07 +02:00
|
|
|
assert(atom->splitable());
|
2011-10-15 06:45:49 +02:00
|
|
|
assert(pos > atom->begin());
|
|
|
|
assert(pos < atom->end());
|
2011-11-14 15:10:11 +01:00
|
|
|
|
|
|
|
BufferIterator end = atom->m_end;
|
|
|
|
atom->m_end = pos;
|
|
|
|
|
|
|
|
DisplayAtom new_atom(atom->end_coord(), pos, end,
|
2011-10-15 06:45:49 +02:00
|
|
|
atom->fg_color(), atom->bg_color(), atom->attribute());
|
2011-09-29 10:55:08 +02:00
|
|
|
|
2011-11-14 15:10:11 +01:00
|
|
|
iterator insert_pos = atom;
|
|
|
|
++insert_pos;
|
|
|
|
m_atoms.insert(insert_pos, std::move(new_atom));
|
2012-07-03 23:23:07 +02:00
|
|
|
check_invariant();
|
2011-11-14 15:10:11 +01:00
|
|
|
return atom;
|
2011-09-29 10:55:08 +02:00
|
|
|
}
|
|
|
|
|
2011-09-29 11:10:27 +02:00
|
|
|
void DisplayBuffer::check_invariant() const
|
|
|
|
{
|
2011-10-18 15:59:32 +02:00
|
|
|
const_iterator prev_it;
|
|
|
|
for (const_iterator it = begin(); it != end(); ++it)
|
2011-09-29 11:10:27 +02:00
|
|
|
{
|
2011-10-18 15:59:32 +02:00
|
|
|
assert(it->end() >= it->begin());
|
|
|
|
if (it != begin())
|
2012-07-03 23:23:07 +02:00
|
|
|
{
|
2011-10-18 15:59:32 +02:00
|
|
|
assert(prev_it->end() == it->begin());
|
2012-07-03 23:23:07 +02:00
|
|
|
assert(prev_it->end_coord() == it->coord());
|
|
|
|
}
|
2011-10-18 15:59:32 +02:00
|
|
|
prev_it = it;
|
2011-10-15 06:45:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisplayBuffer::replace_atom_content(iterator atom,
|
2012-03-08 22:23:29 +01:00
|
|
|
const String& replacement)
|
2011-10-15 06:45:49 +02:00
|
|
|
{
|
2012-07-03 19:13:16 +02:00
|
|
|
atom->m_content_mode = DisplayAtom::ReplacementText;
|
2011-10-15 06:45:49 +02:00
|
|
|
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-29 11:10:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-02 18:51:20 +02:00
|
|
|
}
|