]> git.lyx.org Git - lyx.git/blob - src/iterators.C
Make lyx2lyx output the new external inset format.
[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 ParagraphList::iterator ParIterator::operator*() const
149 {
150         return pimpl_->positions.back().pit;
151 }
152
153
154 ParagraphList::iterator ParIterator::operator->() const
155 {
156         return pimpl_->positions.back().pit;
157 }
158
159
160 ParagraphList::iterator ParIterator::outerPar() const
161 {
162         return pimpl_->positions[0].pit;
163 }
164
165
166 size_t ParIterator::size() const
167 {
168         return pimpl_->positions.size();
169 }
170
171
172 ParagraphList & ParIterator::plist() const
173 {
174         return *const_cast<ParagraphList*>(pimpl_->positions.back().plist);
175 }
176
177
178 bool operator==(ParIterator const & iter1, ParIterator const & iter2)
179 {
180         return iter1.pimpl_->positions == iter2.pimpl_->positions;
181 }
182
183
184 bool operator!=(ParIterator const & iter1, ParIterator const & iter2)
185 {
186         return !(iter1 == iter2);
187 }
188
189
190 ///
191 /// ParConstIterator
192 ///
193
194
195 struct ParConstIterator::Pimpl {
196         typedef vector<ParPosition> PosHolder;
197         PosHolder positions;
198 };
199
200
201 ParConstIterator::ParConstIterator(ParagraphList::iterator pit,
202                                    ParagraphList const & pl)
203         : pimpl_(new Pimpl)
204 {
205         pimpl_->positions.push_back(ParPosition(pit, pl));
206 }
207
208
209 ParConstIterator::~ParConstIterator()
210 {}
211
212
213 ParConstIterator::ParConstIterator(ParConstIterator const & pi)
214         : pimpl_(new Pimpl(*pi.pimpl_))
215 {}
216
217
218 ParConstIterator & ParConstIterator::operator++()
219 {
220         while (!pimpl_->positions.empty()) {
221                 ParPosition & p = pimpl_->positions.back();
222
223                 // Does the current inset contain more "cells" ?
224                 if (p.index) {
225                         ++(*p.index);
226                         ParagraphList * plist = (*p.it)->inset->getParagraphs(*p.index);
227                         if (plist && !plist->empty()) {
228                                 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
229                                 return *this;
230                         }
231                         ++(*p.it);
232                 } else
233                         // The following line is needed because the value of
234                         // p.it may be invalid if inset was added/removed to
235                         // the paragraph pointed by the iterator
236                         p.it.reset(p.pit->insetlist.begin());
237
238                 // Try to find the next inset that contains paragraphs
239                 InsetList::iterator end = p.pit->insetlist.end();
240                 for (; *p.it != end; ++(*p.it)) {
241                         ParagraphList * plist = (*p.it)->inset->getParagraphs(0);
242                         if (plist && !plist->empty()) {
243                                 p.index.reset(0);
244                                 pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
245                                 return *this;
246                         }
247                 }
248
249                 // Try to go to the next paragarph
250                 if (next(p.pit) != const_cast<ParagraphList*>(p.plist)->end()
251                     || pimpl_->positions.size() == 1) {
252                         ++p.pit;
253                         p.index.reset();
254                         p.it.reset();
255
256                         return *this;
257                 }
258
259                 // Drop end and move up in the stack.
260                 pimpl_->positions.pop_back();
261         }
262
263         return *this;
264 }
265
266
267 ParagraphList::iterator ParConstIterator::operator*() const
268 {
269         return pimpl_->positions.back().pit;
270 }
271
272
273 ParagraphList::iterator ParConstIterator::operator->() const
274 {
275         return pimpl_->positions.back().pit;
276 }
277
278
279 size_t ParConstIterator::size() const
280 {
281         return pimpl_->positions.size();
282 }
283
284
285 bool operator==(ParConstIterator const & iter1, ParConstIterator const & iter2)
286 {
287         return iter1.pimpl_->positions == iter2.pimpl_->positions;
288 }
289
290
291 bool operator!=(ParConstIterator const & iter1, ParConstIterator const & iter2)
292 {
293         return !(iter1 == iter2);
294 }