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