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