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