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"
16 #include "PosIterator.h"
20 #include "insets/inset.h"
22 #include <boost/next_prior.hpp>
23 #include <boost/optional.hpp>
26 using boost::optional;
36 ParPosition(ParagraphList::iterator p, ParagraphList const & pl);
38 ParagraphList::iterator pit;
40 ParagraphList const * plist;
42 optional<InsetList::iterator> it;
48 ParPosition::ParPosition(ParagraphList::iterator p, ParagraphList const & pl)
51 if (p != const_cast<ParagraphList&>(pl).end()) {
52 it.reset(p->insetlist.begin());
57 bool operator==(ParPosition const & pos1, ParPosition const & pos2)
59 return pos1.pit == pos2.pit;
63 bool operator!=(ParPosition const & pos1, ParPosition const & pos2)
65 return !(pos1 == pos2);
73 struct ParIterator::Pimpl {
74 typedef vector<ParPosition> PosHolder;
78 ParIterator::ParIterator(ParagraphList::iterator pit, ParagraphList const & pl)
81 pimpl_->positions.push_back(ParPosition(pit, pl));
85 ParIterator::~ParIterator()
89 ParIterator::ParIterator(ParIterator const & pi)
90 : pimpl_(new Pimpl(*pi.pimpl_))
94 void ParIterator::operator=(ParIterator const & pi)
97 pimpl_.swap(tmp.pimpl_);
101 ParIterator & ParIterator::operator++()
103 while (!pimpl_->positions.empty()) {
104 ParPosition & p = pimpl_->positions.back();
106 // Does the current inset contain more "cells" ?
109 ParagraphList * plist = (*p.it)->inset->getParagraphs(*p.index);
110 if (plist && !plist->empty()) {
111 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
116 // The following line is needed because the value of
117 // p.it may be invalid if inset was added/removed to
118 // the paragraph pointed by the iterator
119 p.it.reset(p.pit->insetlist.begin());
121 // Try to find the next inset that contains paragraphs
122 InsetList::iterator end = p.pit->insetlist.end();
123 for (; *p.it != end; ++(*p.it)) {
124 ParagraphList * plist = (*p.it)->inset->getParagraphs(0);
125 if (plist && !plist->empty()) {
127 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
132 // Try to go to the next paragarph
133 if (next(p.pit) != const_cast<ParagraphList*>(p.plist)->end()
134 || pimpl_->positions.size() == 1) {
142 // Drop end and move up in the stack.
143 pimpl_->positions.pop_back();
149 LyXText * ParIterator::text() const
151 //lyxerr << "positions.size: " << pimpl_->positions.size() << std::endl;
152 if (pimpl_->positions.size() <= 1)
155 ParPosition const & pos = pimpl_->positions[pimpl_->positions.size() - 2];
156 return (*pos.it)->inset->getText(*pos.index);
160 InsetOld * ParIterator::inset() const
162 //lyxerr << "positions.size: " << pimpl_->positions.size() << std::endl;
163 if (pimpl_->positions.size() <= 1)
166 ParPosition const & pos = pimpl_->positions[pimpl_->positions.size() - 2];
167 return (*pos.it)->inset;
171 int ParIterator::index() const
173 if (pimpl_->positions.size() <= 1)
176 return *(pimpl_->positions[pimpl_->positions.size() - 2].index);
180 void ParIterator::asCursor(Cursor & cursor) const
182 cursor.data_.clear();
183 for (size_t i = 1, n = size(); i < n; ++i) {
184 ParPosition const & pos = pimpl_->positions[i - 1];
186 item.inset_ = (*pos.it)->inset;
187 item.idx_ = (*pos.index);
188 item.text_ = (*pos.it)->inset->getText(*pos.index);
191 cursor.data_.push_back(item);
196 Paragraph & ParIterator::operator*() const
198 return *pimpl_->positions.back().pit;
202 ParagraphList::iterator ParIterator::pit() const
204 return pimpl_->positions.back().pit;
208 ParagraphList::iterator ParIterator::operator->() const
210 return pimpl_->positions.back().pit;
214 ParagraphList::iterator ParIterator::outerPar() const
216 return pimpl_->positions[0].pit;
220 size_t ParIterator::size() const
222 return pimpl_->positions.size();
226 ParagraphList & ParIterator::plist() const
228 return *const_cast<ParagraphList*>(pimpl_->positions.back().plist);
232 bool operator==(ParIterator const & iter1, ParIterator const & iter2)
234 return iter1.pimpl_->positions == iter2.pimpl_->positions;
238 bool operator!=(ParIterator const & iter1, ParIterator const & iter2)
240 return !(iter1 == iter2);
249 struct ParConstIterator::Pimpl {
250 typedef vector<ParPosition> PosHolder;
255 ParConstIterator::ParConstIterator(ParagraphList::iterator pit,
256 ParagraphList const & pl)
259 pimpl_->positions.push_back(ParPosition(pit, pl));
263 ParConstIterator::~ParConstIterator()
267 ParConstIterator::ParConstIterator(ParConstIterator const & pi)
268 : pimpl_(new Pimpl(*pi.pimpl_))
272 ParConstIterator & ParConstIterator::operator++()
274 while (!pimpl_->positions.empty()) {
275 ParPosition & p = pimpl_->positions.back();
277 // Does the current inset contain more "cells" ?
280 ParagraphList * plist = (*p.it)->inset->getParagraphs(*p.index);
281 if (plist && !plist->empty()) {
282 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
287 // The following line is needed because the value of
288 // p.it may be invalid if inset was added/removed to
289 // the paragraph pointed by the iterator
290 p.it.reset(p.pit->insetlist.begin());
292 // Try to find the next inset that contains paragraphs
293 InsetList::iterator end = p.pit->insetlist.end();
294 for (; *p.it != end; ++(*p.it)) {
295 ParagraphList * plist = (*p.it)->inset->getParagraphs(0);
296 if (plist && !plist->empty()) {
298 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
303 // Try to go to the next paragarph
304 if (next(p.pit) != const_cast<ParagraphList*>(p.plist)->end()
305 || pimpl_->positions.size() == 1) {
313 // Drop end and move up in the stack.
314 pimpl_->positions.pop_back();
321 Paragraph const & ParConstIterator::operator*() const
323 return *pimpl_->positions.back().pit;
327 ParagraphList::const_iterator ParConstIterator::pit() const
329 return pimpl_->positions.back().pit;
333 ParagraphList::const_iterator ParConstIterator::operator->() const
335 return pimpl_->positions.back().pit;
339 ParagraphList const & ParConstIterator::plist() const
341 return *pimpl_->positions.back().plist;
345 size_t ParConstIterator::size() const
347 return pimpl_->positions.size();
351 bool operator==(ParConstIterator const & iter1, ParConstIterator const & iter2)
353 return iter1.pimpl_->positions == iter2.pimpl_->positions;
357 bool operator!=(ParConstIterator const & iter1, ParConstIterator const & iter2)
359 return !(iter1 == iter2);
363 PosIterator ParIterator::asPosIterator(lyx::pos_type pos) const
367 int const last = size() - 1;
368 for (int i = 0; i < last; ++i) {
369 ParPosition & pp = pimpl_->positions[i];
370 p.stack_.push(PosIteratorItem(const_cast<ParagraphList *>(pp.plist), pp.pit, (*pp.it)->pos, *pp.index + 1));
372 ParPosition const & pp = pimpl_->positions[last];
373 p.stack_.push(PosIteratorItem(const_cast<ParagraphList *>(pp.plist),