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