]> git.lyx.org Git - features.git/blob - src/PosIterator.C
use std::advance and std::distance instead of home-grown versions
[features.git] / src / PosIterator.C
1 /* \file PosIterator.C
2  * This file is part of LyX, the document processor.
3  * Licence details can be found in the file COPYING.
4  *
5  * \author Alfredo Braunstein
6  *
7  * Full author contact details are available in file CREDITS.
8  */
9
10
11 #include <config.h>
12
13 #include "PosIterator.h"
14
15 #include "buffer.h"
16 #include "BufferView.h"
17 #include "cursor.h"
18 #include "iterators.h"
19 #include "lyxtext.h"
20 #include "paragraph.h"
21
22 #include "insets/insettext.h"
23 #include "insets/updatableinset.h"
24 #include "insets/inset.h"
25
26 #include <boost/next_prior.hpp>
27
28 using boost::prior;
29
30
31 PosIterator & PosIterator::operator++()
32 {
33         BOOST_ASSERT(!stack_.empty());
34         while (true) {
35                 PosIteratorItem & p = stack_.back();
36
37                 if (p.pos < p.pit->size()) {
38                         if (InsetBase * inset = p.pit->getInset(p.pos)) {
39                                 if (LyXText * text = inset->getText(p.index)) {
40                                         ParagraphList & pl = text->paragraphs();
41                                         p.index++;
42                                         stack_.push_back(PosIteratorItem(&pl, pl.begin(), 0));
43                                         return *this;
44                                 }
45                         }
46                         p.index = 0;
47                         ++p.pos;
48                 } else {
49                         ++p.pit;
50                         p.pos = 0;
51                 }
52
53                 if (p.pit != p.pl->end() || stack_.size() == 1)
54                         return *this;
55
56                 stack_.pop_back();
57         }
58         return *this;
59 }
60
61
62 PosIterator & PosIterator::operator--()
63 {
64         BOOST_ASSERT(!stack_.empty());
65
66         // try to go one position backwards: if on the start of the
67         // ParagraphList, pops an item
68         PosIteratorItem & p = stack_.back();
69         if (p.pos > 0) {
70                 --p.pos;
71                 InsetBase * inset = p.pit->getInset(p.pos);
72                 if (inset)
73                         p.index = inset->numParagraphs();
74         } else {
75                 if (p.pit == p.pl->begin()) {
76                         if (stack_.size() == 1)
77                                 return *this;
78                         stack_.pop_back();
79                         --stack_.back().index;
80                 } else {
81                         --p.pit;
82                         p.pos = p.pit->size();
83                 }
84         }
85         // try to push an item if there is some left unexplored
86         PosIteratorItem & q = stack_.back();
87         if (q.pos < q.pit->size()) {
88                 InsetBase * inset = q.pit->getInset(q.pos);
89                 if (inset && q.index > 0) {
90                         LyXText * text = inset->getText(q.index - 1);
91                         BOOST_ASSERT(text);
92                         ParagraphList & pl = text->paragraphs();
93                         stack_.push_back(PosIteratorItem(&pl, prior(pl.end()), pl.back().size()));
94                 }
95         }
96         return *this;
97 }
98
99
100 bool operator!=(PosIterator const & lhs, PosIterator const & rhs)
101 {
102         return !(lhs == rhs);
103 }
104
105
106 bool operator==(PosIterator const & lhs, PosIterator const & rhs)
107 {
108
109         PosIteratorItem const & li = lhs.stack_.back();
110         PosIteratorItem const & ri = rhs.stack_.back();
111
112         return (li.pl == ri.pl && li.pit == ri.pit &&
113                 (li.pit == li.pl->end() || li.pos == ri.pos));
114 }
115
116
117 bool PosIterator::at_end() const
118 {
119         return pos() == pit()->size();
120 }
121
122
123 PosIterator::PosIterator(ParagraphList * pl, ParagraphList::iterator pit,
124                          lyx::pos_type pos)
125 {
126         stack_.push_back(PosIteratorItem(pl, pit, pos));
127 }
128
129
130 PosIterator::PosIterator(BufferView & bv)
131 {
132         LyXText * text = bv.getLyXText();
133         lyx::pos_type pos = bv.cursor().pos();
134         ParagraphList::iterator pit = text->cursorPar();
135
136         ParIterator par = bv.buffer()->par_iterator_begin();
137         ParIterator end = bv.buffer()->par_iterator_end();
138         for ( ; par != end; ++par) {
139                 if (par.pit() == pit)
140                         break;
141         }
142
143         operator=(par.asPosIterator(pos));
144 }
145
146
147 InsetBase * PosIterator::inset() const
148 {
149         if (stack_.size() == 1)
150                 return 0;
151         PosIteratorItem const & pi = stack_[stack_.size() - 2];
152         return pi.pit->getInset(pi.pos);
153 }