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