]> git.lyx.org Git - lyx.git/blob - src/iterators.C
Add #include <boost/assert.hpp>.
[lyx.git] / src / iterators.C
1 /* \file iterators.C
2  * This file is part of LyX, the document processor.
3  * Licence details can be found in the file COPYING.
4  *
5  * \author unknown
6  * \author Lars Gullik Bjønnes
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11
12 #include <config.h>
13
14 #include "iterators.h"
15 #include "paragraph.h"
16
17 #include <boost/next_prior.hpp>
18 #include <boost/optional.hpp>
19
20 // it's conceptionally a stack, but undo needs random access...
21 //#include <stack>
22
23 using boost::next;
24 using boost::optional;
25 using std::vector;
26
27 ///
28 /// ParPosition
29 ///
30
31 class ParPosition {
32 public:
33         ///
34         ParPosition(ParagraphList::iterator p, ParagraphList const & pl);
35         ///
36         ParagraphList::iterator pit;
37         ///
38         ParagraphList const * plist;
39         ///
40         optional<InsetList::iterator> it;
41         ///
42         optional<int> index;
43 };
44
45
46 ParPosition::ParPosition(ParagraphList::iterator p, ParagraphList const & pl)
47         : pit(p), plist(&pl)
48 {
49         if (p != const_cast<ParagraphList&>(pl).end()) {
50                 it.reset(p->insetlist.begin());
51         }
52 }
53
54
55 bool operator==(ParPosition const & pos1, ParPosition const & pos2)
56 {
57         return pos1.pit == pos2.pit;
58 }
59
60
61 bool operator!=(ParPosition const & pos1, ParPosition const & pos2)
62 {
63         return !(pos1 == pos2);
64 }
65
66
67 ///
68 /// ParIterator
69 ///
70
71 struct ParIterator::Pimpl {
72         typedef vector<ParPosition> PosHolder;
73         PosHolder positions;
74 };
75
76 ParIterator::ParIterator(ParagraphList::iterator pit, ParagraphList const & pl)
77         : pimpl_(new Pimpl)
78 {
79         pimpl_->positions.push_back(ParPosition(pit, pl));
80 }
81
82
83 ParIterator::~ParIterator()
84 {}
85
86
87 ParIterator::ParIterator(ParIterator const & pi)
88         : pimpl_(new Pimpl(*pi.pimpl_))
89 {}
90
91
92 void ParIterator::operator=(ParIterator const & pi)
93 {
94         ParIterator tmp(pi);
95         pimpl_.swap(tmp.pimpl_);
96 }
97
98
99 ParIterator & ParIterator::operator++()
100 {
101         while (!pimpl_->positions.empty()) {
102                 ParPosition & p = pimpl_->positions.back();
103
104                 // Does the current inset contain more "cells" ?
105                 if (p.index) {
106                         ++(*p.index);
107                         ParagraphList * plist = (*p.it)->inset->getParagraphs(*p.index);
108                         if (plist && !plist->empty()) {
109                                 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
110                                 return *this;
111                         }
112                         ++(*p.it);
113                 } else
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());
118
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()) {
124                                 p.index.reset(0);
125                                 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
126                                 return *this;
127                         }
128                 }
129
130                 // Try to go to the next paragarph
131                 if (next(p.pit) != const_cast<ParagraphList*>(p.plist)->end()
132                     || pimpl_->positions.size() == 1) {
133                         ++p.pit;
134                         p.index.reset();
135                         p.it.reset();
136
137                         return *this;
138                 }
139
140                 // Drop end and move up in the stack.
141                 pimpl_->positions.pop_back();
142         }
143         return *this;
144 }
145
146
147 Paragraph & ParIterator::operator*() const
148 {
149         return *pimpl_->positions.back().pit;
150 }
151
152
153 ParagraphList::iterator ParIterator::pit() const
154 {
155         return pimpl_->positions.back().pit;
156 }
157
158
159 ParagraphList::iterator ParIterator::operator->() const
160 {
161         return pimpl_->positions.back().pit;
162 }
163
164
165 ParagraphList::iterator ParIterator::outerPar() const
166 {
167         return pimpl_->positions[0].pit;
168 }
169
170
171 size_t ParIterator::size() const
172 {
173         return pimpl_->positions.size();
174 }
175
176
177 ParagraphList & ParIterator::plist() const
178 {
179         return *const_cast<ParagraphList*>(pimpl_->positions.back().plist);
180 }
181
182
183 bool operator==(ParIterator const & iter1, ParIterator const & iter2)
184 {
185         return iter1.pimpl_->positions == iter2.pimpl_->positions;
186 }
187
188
189 bool operator!=(ParIterator const & iter1, ParIterator const & iter2)
190 {
191         return !(iter1 == iter2);
192 }
193
194
195 ///
196 /// ParConstIterator
197 ///
198
199
200 struct ParConstIterator::Pimpl {
201         typedef vector<ParPosition> PosHolder;
202         PosHolder positions;
203 };
204
205
206 ParConstIterator::ParConstIterator(ParagraphList::iterator pit,
207                                    ParagraphList const & pl)
208         : pimpl_(new Pimpl)
209 {
210         pimpl_->positions.push_back(ParPosition(pit, pl));
211 }
212
213
214 ParConstIterator::~ParConstIterator()
215 {}
216
217
218 ParConstIterator::ParConstIterator(ParConstIterator const & pi)
219         : pimpl_(new Pimpl(*pi.pimpl_))
220 {}
221
222
223 ParConstIterator & ParConstIterator::operator++()
224 {
225         while (!pimpl_->positions.empty()) {
226                 ParPosition & p = pimpl_->positions.back();
227
228                 // Does the current inset contain more "cells" ?
229                 if (p.index) {
230                         ++(*p.index);
231                         ParagraphList * plist = (*p.it)->inset->getParagraphs(*p.index);
232                         if (plist && !plist->empty()) {
233                                 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
234                                 return *this;
235                         }
236                         ++(*p.it);
237                 } else
238                         // The following line is needed because the value of
239                         // p.it may be invalid if inset was added/removed to
240                         // the paragraph pointed by the iterator
241                         p.it.reset(p.pit->insetlist.begin());
242
243                 // Try to find the next inset that contains paragraphs
244                 InsetList::iterator end = p.pit->insetlist.end();
245                 for (; *p.it != end; ++(*p.it)) {
246                         ParagraphList * plist = (*p.it)->inset->getParagraphs(0);
247                         if (plist && !plist->empty()) {
248                                 p.index.reset(0);
249                                 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
250                                 return *this;
251                         }
252                 }
253
254                 // Try to go to the next paragarph
255                 if (next(p.pit) != const_cast<ParagraphList*>(p.plist)->end()
256                     || pimpl_->positions.size() == 1) {
257                         ++p.pit;
258                         p.index.reset();
259                         p.it.reset();
260
261                         return *this;
262                 }
263
264                 // Drop end and move up in the stack.
265                 pimpl_->positions.pop_back();
266         }
267
268         return *this;
269 }
270
271
272 Paragraph const & ParConstIterator::operator*() const
273 {
274         return *pimpl_->positions.back().pit;
275 }
276
277
278 ParagraphList::const_iterator ParConstIterator::pit() const
279 {
280         return pimpl_->positions.back().pit;
281 }
282
283
284 ParagraphList::const_iterator ParConstIterator::operator->() const
285 {
286         return pimpl_->positions.back().pit;
287 }
288
289
290 ParagraphList const & ParConstIterator::plist() const
291 {
292         return *pimpl_->positions.back().plist;
293 }
294
295
296 size_t ParConstIterator::size() const
297 {
298         return pimpl_->positions.size();
299 }
300
301
302 bool operator==(ParConstIterator const & iter1, ParConstIterator const & iter2)
303 {
304         return iter1.pimpl_->positions == iter2.pimpl_->positions;
305 }
306
307
308 bool operator!=(ParConstIterator const & iter1, ParConstIterator const & iter2)
309 {
310         return !(iter1 == iter2);
311 }