2 * This file is part of LyX, the document processor.
3 * Licence details can be found in the file COPYING.
6 * \author Lars Gullik Bjønnes
8 * Full author contact details are available in file CREDITS.
14 #include "iterators.h"
15 #include "paragraph.h"
18 #include "insets/inset.h"
20 #include <boost/next_prior.hpp>
21 #include <boost/optional.hpp>
24 using boost::optional;
34 ParPosition(ParagraphList::iterator p, ParagraphList const & pl);
36 ParagraphList::iterator pit;
38 ParagraphList const * plist;
40 optional<InsetList::iterator> it;
46 ParPosition::ParPosition(ParagraphList::iterator p, ParagraphList const & pl)
49 if (p != const_cast<ParagraphList&>(pl).end()) {
50 it.reset(p->insetlist.begin());
55 bool operator==(ParPosition const & pos1, ParPosition const & pos2)
57 return pos1.pit == pos2.pit;
61 bool operator!=(ParPosition const & pos1, ParPosition const & pos2)
63 return !(pos1 == pos2);
71 struct ParIterator::Pimpl {
72 typedef vector<ParPosition> PosHolder;
76 ParIterator::ParIterator(ParagraphList::iterator pit, ParagraphList const & pl)
79 pimpl_->positions.push_back(ParPosition(pit, pl));
83 ParIterator::~ParIterator()
87 ParIterator::ParIterator(ParIterator const & pi)
88 : pimpl_(new Pimpl(*pi.pimpl_))
92 void ParIterator::operator=(ParIterator const & pi)
95 pimpl_.swap(tmp.pimpl_);
99 ParIterator & ParIterator::operator++()
101 while (!pimpl_->positions.empty()) {
102 ParPosition & p = pimpl_->positions.back();
104 // Does the current inset contain more "cells" ?
107 ParagraphList * plist = (*p.it)->inset->getParagraphs(*p.index);
108 if (plist && !plist->empty()) {
109 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
114 // The following line is needed because the value of
115 // p.it may be invalid if inset was added/removed to
116 // the paragraph pointed by the iterator
117 p.it.reset(p.pit->insetlist.begin());
119 // Try to find the next inset that contains paragraphs
120 InsetList::iterator end = p.pit->insetlist.end();
121 for (; *p.it != end; ++(*p.it)) {
122 ParagraphList * plist = (*p.it)->inset->getParagraphs(0);
123 if (plist && !plist->empty()) {
125 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
130 // Try to go to the next paragarph
131 if (next(p.pit) != const_cast<ParagraphList*>(p.plist)->end()
132 || pimpl_->positions.size() == 1) {
140 // Drop end and move up in the stack.
141 pimpl_->positions.pop_back();
147 LyXText * ParIterator::text() const
149 //lyxerr << "positions.size: " << pimpl_->positions.size() << std::endl;
150 if (pimpl_->positions.size() <= 1)
153 ParPosition const & pos = pimpl_->positions[pimpl_->positions.size() - 2];
154 return (*pos.it)->inset->getText(*pos.index);
158 InsetOld * ParIterator::inset() const
160 //lyxerr << "positions.size: " << pimpl_->positions.size() << std::endl;
161 if (pimpl_->positions.size() <= 1)
164 ParPosition const & pos = pimpl_->positions[pimpl_->positions.size() - 2];
165 return (*pos.it)->inset;
169 int ParIterator::index() const
171 if (pimpl_->positions.size() <= 1)
174 return *(pimpl_->positions[pimpl_->positions.size() - 2].index);
178 void ParIterator::asCursor(Cursor & cursor) const
180 cursor.data_.clear();
181 for (size_t i = 1, n = size(); i < n; ++i) {
182 ParPosition const & pos = pimpl_->positions[i - 1];
184 item.inset_ = (*pos.it)->inset;
185 item.idx_ = (*pos.index);
186 item.text_ = (*pos.it)->inset->getText(*pos.index);
189 cursor.data_.push_back(item);
194 Paragraph & ParIterator::operator*() const
196 return *pimpl_->positions.back().pit;
200 ParagraphList::iterator ParIterator::pit() const
202 return pimpl_->positions.back().pit;
206 ParagraphList::iterator ParIterator::operator->() const
208 return pimpl_->positions.back().pit;
212 ParagraphList::iterator ParIterator::outerPar() const
214 return pimpl_->positions[0].pit;
218 size_t ParIterator::size() const
220 return pimpl_->positions.size();
224 ParagraphList & ParIterator::plist() const
226 return *const_cast<ParagraphList*>(pimpl_->positions.back().plist);
230 bool operator==(ParIterator const & iter1, ParIterator const & iter2)
232 return iter1.pimpl_->positions == iter2.pimpl_->positions;
236 bool operator!=(ParIterator const & iter1, ParIterator const & iter2)
238 return !(iter1 == iter2);
247 struct ParConstIterator::Pimpl {
248 typedef vector<ParPosition> PosHolder;
253 ParConstIterator::ParConstIterator(ParagraphList::iterator pit,
254 ParagraphList const & pl)
257 pimpl_->positions.push_back(ParPosition(pit, pl));
261 ParConstIterator::~ParConstIterator()
265 ParConstIterator::ParConstIterator(ParConstIterator const & pi)
266 : pimpl_(new Pimpl(*pi.pimpl_))
270 ParConstIterator & ParConstIterator::operator++()
272 while (!pimpl_->positions.empty()) {
273 ParPosition & p = pimpl_->positions.back();
275 // Does the current inset contain more "cells" ?
278 ParagraphList * plist = (*p.it)->inset->getParagraphs(*p.index);
279 if (plist && !plist->empty()) {
280 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
285 // The following line is needed because the value of
286 // p.it may be invalid if inset was added/removed to
287 // the paragraph pointed by the iterator
288 p.it.reset(p.pit->insetlist.begin());
290 // Try to find the next inset that contains paragraphs
291 InsetList::iterator end = p.pit->insetlist.end();
292 for (; *p.it != end; ++(*p.it)) {
293 ParagraphList * plist = (*p.it)->inset->getParagraphs(0);
294 if (plist && !plist->empty()) {
296 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
301 // Try to go to the next paragarph
302 if (next(p.pit) != const_cast<ParagraphList*>(p.plist)->end()
303 || pimpl_->positions.size() == 1) {
311 // Drop end and move up in the stack.
312 pimpl_->positions.pop_back();
319 Paragraph const & ParConstIterator::operator*() const
321 return *pimpl_->positions.back().pit;
325 ParagraphList::const_iterator ParConstIterator::pit() const
327 return pimpl_->positions.back().pit;
331 ParagraphList::const_iterator ParConstIterator::operator->() const
333 return pimpl_->positions.back().pit;
337 ParagraphList const & ParConstIterator::plist() const
339 return *pimpl_->positions.back().plist;
343 size_t ParConstIterator::size() const
345 return pimpl_->positions.size();
349 bool operator==(ParConstIterator const & iter1, ParConstIterator const & iter2)
351 return iter1.pimpl_->positions == iter2.pimpl_->positions;
355 bool operator!=(ParConstIterator const & iter1, ParConstIterator const & iter2)
357 return !(iter1 == iter2);