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