1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
#include "display_buffer.hh"
#include "assert.hh"
namespace Kakoune
{
BufferString DisplayAtom::content() const
{
if (m_replacement_text.empty())
return m_begin.buffer().string(m_begin, m_end);
else
return m_replacement_text;
}
template<typename Iterator>
static DisplayCoord advance_coord(const DisplayCoord& pos,
Iterator begin, Iterator end)
{
DisplayCoord res = pos;
while (begin != end)
{
if (*begin == '\n')
{
++res.line;
res.column = 0;
}
else
++res.column;
++begin;
}
return res;
}
DisplayCoord DisplayAtom::end_coord() const
{
if (m_replacement_text.empty())
return advance_coord(m_coord, m_begin, m_end);
else
return advance_coord(m_coord, m_replacement_text.begin(),
m_replacement_text.end());
}
BufferIterator DisplayAtom::iterator_at(const DisplayCoord& coord) const
{
if (not m_replacement_text.empty() 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;
else if (coord < pos)
return it;
}
return m_end;
}
DisplayCoord DisplayAtom::line_and_column_at(const BufferIterator& iterator) const
{
assert(iterator >= m_begin and iterator < m_end);
if (not m_replacement_text.empty())
return m_coord;
return advance_coord(m_coord, m_begin, iterator);
}
DisplayBuffer::DisplayBuffer()
{
}
DisplayBuffer::iterator DisplayBuffer::insert(iterator where, const DisplayAtom& atom)
{
iterator res = m_atoms.insert(where, atom);
check_invariant();
return res;
}
DisplayBuffer::iterator DisplayBuffer::atom_containing(const BufferIterator& where)
{
for (iterator it = m_atoms.begin(); it != m_atoms.end(); ++it)
{
if (it->end() > where)
return it;
}
return end();
}
DisplayBuffer::iterator DisplayBuffer::split(iterator atom, const BufferIterator& pos)
{
assert(pos > atom->begin());
assert(pos < atom->end());
DisplayAtom new_atom(atom->coord(), atom->begin(), pos,
atom->fg_color(), atom->bg_color(), atom->attribute());
atom->m_begin = pos;
atom->m_coord = new_atom.end_coord();
iterator res = m_atoms.insert(atom, std::move(new_atom));
check_invariant();
return res;
}
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,
const BufferString& replacement)
{
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;
}
}
}
|