]> git.lyx.org Git - lyx.git/blob - src/PosIterator.C
f89ef75b9ff4825343b93fb3713d00918cbb40b6
[lyx.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 "iterators.h"
18 #include "lyxtext.h"
19 #include "paragraph.h"
20
21 #include "insets/insettext.h"
22 #include "insets/updatableinset.h"
23 #include "insets/inset.h"
24
25 #include <boost/next_prior.hpp>
26
27 using boost::prior;
28
29 PosIterator & PosIterator::operator++()
30 {
31         BOOST_ASSERT(!stack_.empty());
32         while (true) {
33                 PosIteratorItem & p = stack_.top();
34                 
35                 if (p.pos < p.pit->size()) {
36                         InsetOld * inset = p.pit->getInset(p.pos);
37                         if (inset) {
38                                 ParagraphList * pl = inset->getParagraphs(p.index);
39                                 if (pl) {
40                                         p.index++;
41                                         stack_.push(PosIteratorItem(pl));
42                                         return *this;
43                                 }
44                         }
45                         p.index = 0;
46                         ++p.pos;
47                 } else {
48                         ++p.pit;
49                         p.pos = 0;
50                 }
51                 
52                 if (p.pit != p.pl->end() || stack_.size() == 1)
53                         return *this;
54                 
55                 stack_.pop();
56         }
57         return *this;
58 }
59
60
61 PosIterator & PosIterator::operator--()
62 {
63         BOOST_ASSERT(!stack_.empty());
64         
65         // try to go one position backwards: if on the start of the
66         // ParagraphList, pops an item 
67         PosIteratorItem & p = stack_.top();
68         if (p.pos > 0) {
69                 --p.pos;
70                 InsetOld * inset = p.pit->getInset(p.pos);
71                 if (inset)
72                         p.index = inset->numParagraphs();
73         } else {
74                 if (p.pit == p.pl->begin()) {
75                         if (stack_.size() == 1)
76                                 return *this;
77                         stack_.pop();
78                         --stack_.top().index;
79                 } else {
80                         --p.pit;
81                         p.pos = p.pit->size();
82                 }
83         }
84         // try to push an item if there is some left unexplored
85         PosIteratorItem & q = stack_.top();
86         if (q.pos < q.pit->size()) {
87                 InsetOld * inset = q.pit->getInset(q.pos);
88                 if (inset && q.index > 0) {
89                         ParagraphList *
90                                 pl = inset->getParagraphs(q.index - 1);
91                         BOOST_ASSERT(pl);
92                         stack_.push(PosIteratorItem(pl, prior(pl->end()), pl->back().size()));
93                 }
94         }
95         return *this;
96 }
97
98
99 bool operator!=(PosIterator const & lhs, PosIterator const & rhs)
100 {
101         return !(lhs == rhs);
102 }
103
104
105 bool operator==(PosIterator const & lhs, PosIterator const & rhs)
106 {
107         
108         PosIteratorItem const & li = lhs.stack_.top();
109         PosIteratorItem const & ri = rhs.stack_.top();
110         
111         return (li.pl == ri.pl && li.pit == ri.pit &&
112                 (li.pit == li.pl->end() || li.pos == ri.pos));
113 }
114
115
116 bool PosIterator::at_end() const
117 {
118         return pos() == pit()->size();
119 }
120
121
122 PosIterator::PosIterator(ParagraphList * pl, ParagraphList::iterator pit,
123                          lyx::pos_type pos)
124 {
125         stack_.push(PosIteratorItem(pl, pit, pos));
126 }
127
128
129 PosIterator::PosIterator(ParagraphList * pl)
130 {
131         stack_.push(PosIteratorItem(pl, pl->begin(), 0));
132 }
133
134
135 PosIterator::PosIterator(BufferView & bv)
136 {
137         LyXText * text = bv.getLyXText();
138         lyx::pos_type pos = text->cursor.pos();
139         ParagraphList::iterator pit = text->cursorPar();
140         
141         ParIterator par = bv.buffer()->par_iterator_begin();
142         ParIterator end = bv.buffer()->par_iterator_end();
143         for ( ; par != end; ++par) {
144                 if (par.pit() == pit)
145                         break;
146         }
147
148         operator=(par.asPosIterator(pos));
149 }