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"
17 #include <boost/next_prior.hpp>
18 #include <boost/optional.hpp>
23 using boost::optional;
33 ParPosition(ParagraphList::iterator p, ParagraphList const & pl);
35 ParagraphList::iterator pit;
37 ParagraphList const * plist;
39 optional<InsetList::iterator> it;
45 ParPosition::ParPosition(ParagraphList::iterator p, ParagraphList const & pl)
49 it.reset(p->insetlist.begin());
54 bool operator==(ParPosition const & pos1, ParPosition const & pos2)
56 return pos1.pit == pos2.pit;
60 bool operator!=(ParPosition const & pos1, ParPosition const & pos2)
62 return !(pos1 == pos2);
70 struct ParIterator::Pimpl {
71 typedef stack<ParPosition> PosHolder;
75 ParIterator::ParIterator(ParagraphList::iterator pit, ParagraphList const & pl)
78 pimpl_->positions.push(ParPosition(pit, pl));
82 ParIterator::~ParIterator()
86 ParIterator::ParIterator(ParIterator const & pi)
87 : pimpl_(new Pimpl(*pi.pimpl_))
91 ParIterator & ParIterator::operator++()
93 while (!pimpl_->positions.empty()) {
94 ParPosition & p = pimpl_->positions.top();
96 // Does the current inset contain more "cells" ?
99 ParagraphList * plist = p.it->getInset()->getParagraphs(*p.index);
100 if (plist && !plist->empty()) {
101 pimpl_->positions.push(ParPosition(plist->begin(), *plist));
106 // The following line is needed because the value of
107 // p.it may be invalid if inset was added/removed to
108 // the paragraph pointed by the iterator
109 p.it.reset(p.pit->insetlist.begin());
111 // Try to find the next inset that contains paragraphs
112 InsetList::iterator end = p.pit->insetlist.end();
113 for (; *p.it != end; ++(*p.it)) {
114 ParagraphList * plist = p.it->getInset()->getParagraphs(0);
115 if (plist && !plist->empty()) {
117 pimpl_->positions.push(ParPosition(plist->begin(), *plist));
122 // Try to go to the next paragarph
123 if (next(p.pit) != p.plist->end()
124 || pimpl_->positions.size() == 1) {
132 // Drop end and move up in the stack.
133 pimpl_->positions.pop();
139 ParagraphList::iterator ParIterator::operator*() const
141 return pimpl_->positions.top().pit;
145 ParagraphList::iterator ParIterator::operator->() const
147 return pimpl_->positions.top().pit;
151 size_t ParIterator::size() const
153 return pimpl_->positions.size();
157 bool operator==(ParIterator const & iter1, ParIterator const & iter2)
159 return iter1.pimpl_->positions == iter2.pimpl_->positions;
163 bool operator!=(ParIterator const & iter1, ParIterator const & iter2)
165 return !(iter1 == iter2);
174 struct ParConstIterator::Pimpl {
175 typedef stack<ParPosition> PosHolder;
180 ParConstIterator::ParConstIterator(ParagraphList::iterator pit,
181 ParagraphList const & pl)
184 pimpl_->positions.push(ParPosition(pit, pl));
188 ParConstIterator::~ParConstIterator()
192 ParConstIterator::ParConstIterator(ParConstIterator const & pi)
193 : pimpl_(new Pimpl(*pi.pimpl_))
197 ParConstIterator & ParConstIterator::operator++()
199 while (!pimpl_->positions.empty()) {
200 ParPosition & p = pimpl_->positions.top();
202 // Does the current inset contain more "cells" ?
205 ParagraphList * plist = p.it->getInset()->getParagraphs(*p.index);
206 if (plist && !plist->empty()) {
207 pimpl_->positions.push(ParPosition(plist->begin(), *plist));
212 // The following line is needed because the value of
213 // p.it may be invalid if inset was added/removed to
214 // the paragraph pointed by the iterator
215 p.it.reset(p.pit->insetlist.begin());
217 // Try to find the next inset that contains paragraphs
218 InsetList::iterator end = p.pit->insetlist.end();
219 for (; *p.it != end; ++(*p.it)) {
220 ParagraphList * plist = p.it->getInset()->getParagraphs(0);
221 if (plist && !plist->empty()) {
223 pimpl_->positions.push(ParPosition(plist->begin(), *plist));
228 // Try to go to the next paragarph
229 if (next(p.pit) != p.plist->end()
230 || pimpl_->positions.size() == 1) {
238 // Drop end and move up in the stack.
239 pimpl_->positions.pop();
246 ParagraphList::iterator ParConstIterator::operator*() const
248 return pimpl_->positions.top().pit;
252 ParagraphList::iterator ParConstIterator::operator->() const
254 return pimpl_->positions.top().pit;
258 size_t ParConstIterator::size() const
260 return pimpl_->positions.size();
264 bool operator==(ParConstIterator const & iter1, ParConstIterator const & iter2)
266 return iter1.pimpl_->positions == iter2.pimpl_->positions;
270 bool operator!=(ParConstIterator const & iter1, ParConstIterator const & iter2)
272 return !(iter1 == iter2);