]> git.lyx.org Git - lyx.git/blob - src/iterators.C
The "I want this in now" patch.
[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 #include <stack>
21
22 using boost::next;
23 using boost::optional;
24 using std::stack;
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 != 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 stack<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(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.top();
102
103                 // Does the current inset contain more "cells" ?
104                 if (p.index) {
105                         ++(*p.index);
106                         ParagraphList * plist = p.it->getInset()->getParagraphs(*p.index);
107                         if (plist && !plist->empty()) {
108                                 pimpl_->positions.push(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->getInset()->getParagraphs(0);
122                         if (plist && !plist->empty()) {
123                                 p.index.reset(0);
124                                 pimpl_->positions.push(ParPosition(plist->begin(), *plist));
125                                 return *this;
126                         }
127                 }
128
129                 // Try to go to the next paragarph
130                 if (next(p.pit) != 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();
141         }
142         return *this;
143 }
144
145
146 ParagraphList::iterator ParIterator::operator*() const
147 {
148         return pimpl_->positions.top().pit;
149 }
150
151
152 ParagraphList::iterator ParIterator::operator->() const
153 {
154         return pimpl_->positions.top().pit;
155 }
156
157
158 size_t ParIterator::size() const
159 {
160         return pimpl_->positions.size();
161 }
162
163
164 bool operator==(ParIterator const & iter1, ParIterator const & iter2)
165 {
166         return iter1.pimpl_->positions == iter2.pimpl_->positions;
167 }
168
169
170 bool operator!=(ParIterator const & iter1, ParIterator const & iter2)
171 {
172         return !(iter1 == iter2);
173 }
174
175
176 ///
177 /// ParConstIterator
178 ///
179
180
181 struct ParConstIterator::Pimpl {
182         typedef stack<ParPosition> PosHolder;
183         PosHolder positions;
184 };
185
186
187 ParConstIterator::ParConstIterator(ParagraphList::iterator pit,
188                                    ParagraphList const & pl)
189         : pimpl_(new Pimpl)
190 {
191         pimpl_->positions.push(ParPosition(pit, pl));
192 }
193
194
195 ParConstIterator::~ParConstIterator()
196 {}
197
198
199 ParConstIterator::ParConstIterator(ParConstIterator const & pi)
200         : pimpl_(new Pimpl(*pi.pimpl_))
201 {}
202
203
204 ParConstIterator & ParConstIterator::operator++()
205 {
206         while (!pimpl_->positions.empty()) {
207                 ParPosition & p = pimpl_->positions.top();
208
209                 // Does the current inset contain more "cells" ?
210                 if (p.index) {
211                         ++(*p.index);
212                         ParagraphList * plist = p.it->getInset()->getParagraphs(*p.index);
213                         if (plist && !plist->empty()) {
214                                 pimpl_->positions.push(ParPosition(plist->begin(), *plist));
215                                 return *this;
216                         }
217                         ++(*p.it);
218                 } else
219                         // The following line is needed because the value of
220                         // p.it may be invalid if inset was added/removed to
221                         // the paragraph pointed by the iterator
222                         p.it.reset(p.pit->insetlist.begin());
223
224                 // Try to find the next inset that contains paragraphs
225                 InsetList::iterator end = p.pit->insetlist.end();
226                 for (; *p.it != end; ++(*p.it)) {
227                         ParagraphList * plist = p.it->getInset()->getParagraphs(0);
228                         if (plist && !plist->empty()) {
229                                 p.index.reset(0);
230                                 pimpl_->positions.push(ParPosition(plist->begin(), *plist));
231                                 return *this;
232                         }
233                 }
234
235                 // Try to go to the next paragarph
236                 if (next(p.pit) != p.plist->end()
237                     || pimpl_->positions.size() == 1) {
238                         ++p.pit;
239                         p.index.reset();
240                         p.it.reset();
241
242                         return *this;
243                 }
244
245                 // Drop end and move up in the stack.
246                 pimpl_->positions.pop();
247         }
248
249         return *this;
250 }
251
252
253 ParagraphList::iterator ParConstIterator::operator*() const
254 {
255         return pimpl_->positions.top().pit;
256 }
257
258
259 ParagraphList::iterator ParConstIterator::operator->() const
260 {
261         return pimpl_->positions.top().pit;
262 }
263
264
265 size_t ParConstIterator::size() const
266 {
267         return pimpl_->positions.size();
268 }
269
270
271 bool operator==(ParConstIterator const & iter1, ParConstIterator const & iter2)
272 {
273         return iter1.pimpl_->positions == iter2.pimpl_->positions;
274 }
275
276
277 bool operator!=(ParConstIterator const & iter1, ParConstIterator const & iter2)
278 {
279         return !(iter1 == iter2);
280 }