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>
23 // it's conceptionally a stack, but undo needs random access...
27 using boost::optional;
37 ParPosition(ParagraphList::iterator p, ParagraphList const & pl);
39 ParagraphList::iterator pit;
41 ParagraphList const * plist;
43 optional<InsetList::iterator> it;
49 ParPosition::ParPosition(ParagraphList::iterator p, ParagraphList const & pl)
52 if (p != const_cast<ParagraphList&>(pl).end()) {
53 it.reset(p->insetlist.begin());
58 bool operator==(ParPosition const & pos1, ParPosition const & pos2)
60 return pos1.pit == pos2.pit;
64 bool operator!=(ParPosition const & pos1, ParPosition const & pos2)
66 return !(pos1 == pos2);
74 struct ParIterator::Pimpl {
75 typedef vector<ParPosition> PosHolder;
79 ParIterator::ParIterator(ParagraphList::iterator pit, ParagraphList const & pl)
82 pimpl_->positions.push_back(ParPosition(pit, pl));
86 ParIterator::~ParIterator()
90 ParIterator::ParIterator(ParIterator const & pi)
91 : pimpl_(new Pimpl(*pi.pimpl_))
95 void ParIterator::operator=(ParIterator const & pi)
98 pimpl_.swap(tmp.pimpl_);
102 ParIterator & ParIterator::operator++()
104 while (!pimpl_->positions.empty()) {
105 ParPosition & p = pimpl_->positions.back();
107 // Does the current inset contain more "cells" ?
110 ParagraphList * plist = (*p.it)->inset->getParagraphs(*p.index);
111 if (plist && !plist->empty()) {
112 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
117 // The following line is needed because the value of
118 // p.it may be invalid if inset was added/removed to
119 // the paragraph pointed by the iterator
120 p.it.reset(p.pit->insetlist.begin());
122 // Try to find the next inset that contains paragraphs
123 InsetList::iterator end = p.pit->insetlist.end();
124 for (; *p.it != end; ++(*p.it)) {
125 ParagraphList * plist = (*p.it)->inset->getParagraphs(0);
126 if (plist && !plist->empty()) {
128 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
133 // Try to go to the next paragarph
134 if (next(p.pit) != const_cast<ParagraphList*>(p.plist)->end()
135 || pimpl_->positions.size() == 1) {
143 // Drop end and move up in the stack.
144 pimpl_->positions.pop_back();
150 LyXText * ParIterator::text() const
152 //lyxerr << "positions.size: " << pimpl_->positions.size() << std::endl;
153 if (pimpl_->positions.size() <= 1)
156 ParPosition const & pos = pimpl_->positions[pimpl_->positions.size() - 2];
157 return (*pos.it)->inset->getText(*pos.index);
161 InsetOld * ParIterator::inset() const
163 //lyxerr << "positions.size: " << pimpl_->positions.size() << std::endl;
164 if (pimpl_->positions.size() <= 1)
167 ParPosition const & pos = pimpl_->positions[pimpl_->positions.size() - 2];
168 return (*pos.it)->inset;
172 int ParIterator::index() const
174 if (pimpl_->positions.size() <= 1)
177 return *(pimpl_->positions[pimpl_->positions.size() - 2].index);
181 Paragraph & ParIterator::operator*() const
183 return *pimpl_->positions.back().pit;
187 ParagraphList::iterator ParIterator::pit() const
189 return pimpl_->positions.back().pit;
193 ParagraphList::iterator ParIterator::operator->() const
195 return pimpl_->positions.back().pit;
199 ParagraphList::iterator ParIterator::outerPar() const
201 return pimpl_->positions[0].pit;
205 size_t ParIterator::size() const
207 return pimpl_->positions.size();
211 ParagraphList & ParIterator::plist() const
213 return *const_cast<ParagraphList*>(pimpl_->positions.back().plist);
217 bool operator==(ParIterator const & iter1, ParIterator const & iter2)
219 return iter1.pimpl_->positions == iter2.pimpl_->positions;
223 bool operator!=(ParIterator const & iter1, ParIterator const & iter2)
225 return !(iter1 == iter2);
234 struct ParConstIterator::Pimpl {
235 typedef vector<ParPosition> PosHolder;
240 ParConstIterator::ParConstIterator(ParagraphList::iterator pit,
241 ParagraphList const & pl)
244 pimpl_->positions.push_back(ParPosition(pit, pl));
248 ParConstIterator::~ParConstIterator()
252 ParConstIterator::ParConstIterator(ParConstIterator const & pi)
253 : pimpl_(new Pimpl(*pi.pimpl_))
257 ParConstIterator & ParConstIterator::operator++()
259 while (!pimpl_->positions.empty()) {
260 ParPosition & p = pimpl_->positions.back();
262 // Does the current inset contain more "cells" ?
265 ParagraphList * plist = (*p.it)->inset->getParagraphs(*p.index);
266 if (plist && !plist->empty()) {
267 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
272 // The following line is needed because the value of
273 // p.it may be invalid if inset was added/removed to
274 // the paragraph pointed by the iterator
275 p.it.reset(p.pit->insetlist.begin());
277 // Try to find the next inset that contains paragraphs
278 InsetList::iterator end = p.pit->insetlist.end();
279 for (; *p.it != end; ++(*p.it)) {
280 ParagraphList * plist = (*p.it)->inset->getParagraphs(0);
281 if (plist && !plist->empty()) {
283 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
288 // Try to go to the next paragarph
289 if (next(p.pit) != const_cast<ParagraphList*>(p.plist)->end()
290 || pimpl_->positions.size() == 1) {
298 // Drop end and move up in the stack.
299 pimpl_->positions.pop_back();
306 Paragraph const & ParConstIterator::operator*() const
308 return *pimpl_->positions.back().pit;
312 ParagraphList::const_iterator ParConstIterator::pit() const
314 return pimpl_->positions.back().pit;
318 ParagraphList::const_iterator ParConstIterator::operator->() const
320 return pimpl_->positions.back().pit;
324 ParagraphList const & ParConstIterator::plist() const
326 return *pimpl_->positions.back().plist;
330 size_t ParConstIterator::size() const
332 return pimpl_->positions.size();
336 bool operator==(ParConstIterator const & iter1, ParConstIterator const & iter2)
338 return iter1.pimpl_->positions == iter2.pimpl_->positions;
342 bool operator!=(ParConstIterator const & iter1, ParConstIterator const & iter2)
344 return !(iter1 == iter2);