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