]> git.lyx.org Git - lyx.git/blob - src/PosIterator.C
more cursor dispatch
[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 "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
29 using boost::prior;
30
31
32 PosIterator::PosIterator(ParagraphList * pl, ParagraphList::iterator pit,
33                          lyx::pos_type pos)
34 {
35         stack_.push_back(PosIteratorItem(pl, pit, pos));
36 }
37
38
39 PosIterator::PosIterator(BufferView & bv)
40 {
41         LyXText * text = bv.getLyXText();
42         lyx::pos_type pos = text->cursor().pos();
43         ParagraphList::iterator pit = text->cursorPar();
44
45         ParIterator par = bv.buffer()->par_iterator_begin();
46         ParIterator end = bv.buffer()->par_iterator_end();
47         for (; par != end; ++par) {
48                 if (par.pit() == pit)
49                         break;
50         }
51         setFrom(par, pos);
52 }
53
54
55 PosIterator::PosIterator(ParIterator const & par, lyx::pos_type pos)
56 {
57         setFrom(par, pos);
58 }
59
60
61 void PosIterator::setFrom(ParIterator const & par, lyx::pos_type pos)
62 {
63         BOOST_ASSERT(par.size() > 0);
64
65         ParIterator::PosHolder const & ph = par.positions();
66
67         int const last = par.size() - 1;
68         for (int i = 0; i < last; ++i) {
69                 ParPosition const & pp = ph[i];
70                 stack_.push_back(
71                         PosIteratorItem(const_cast<ParagraphList *>(pp.plist),
72                                         pp.pit, (*pp.it)->pos, *pp.index + 1));
73         }
74         ParPosition const & pp = ph[last];
75         stack_.push_back(
76                 PosIteratorItem(const_cast<ParagraphList *>(pp.plist), pp.pit, pos, 0));
77 }
78
79
80 PosIterator & PosIterator::operator++()
81 {
82         BOOST_ASSERT(!stack_.empty());
83         while (true) {
84                 PosIteratorItem & p = stack_.back();
85
86                 if (p.pos < p.pit->size()) {
87                         if (InsetBase * inset = p.pit->getInset(p.pos)) {
88                                 if (LyXText * text = inset->getText(p.index)) {
89                                         ParagraphList & pl = text->paragraphs();
90                                         p.index++;
91                                         stack_.push_back(PosIteratorItem(&pl, pl.begin(), 0));
92                                         return *this;
93                                 }
94                         }
95                         p.index = 0;
96                         ++p.pos;
97                 } else {
98                         ++p.pit;
99                         p.pos = 0;
100                 }
101
102                 if (p.pit != p.pl->end() || stack_.size() == 1)
103                         return *this;
104
105                 stack_.pop_back();
106         }
107         return *this;
108 }
109
110
111 PosIterator & PosIterator::operator--()
112 {
113         BOOST_ASSERT(!stack_.empty());
114
115         // try to go one position backwards: if on the start of the
116         // ParagraphList, pops an item
117         PosIteratorItem & p = stack_.back();
118         if (p.pos > 0) {
119                 --p.pos;
120                 InsetBase * inset = p.pit->getInset(p.pos);
121                 if (inset)
122                         p.index = inset->numParagraphs();
123         } else {
124                 if (p.pit == p.pl->begin()) {
125                         if (stack_.size() == 1)
126                                 return *this;
127                         stack_.pop_back();
128                         --stack_.back().index;
129                 } else {
130                         --p.pit;
131                         p.pos = p.pit->size();
132                 }
133         }
134         // try to push an item if there is some left unexplored
135         PosIteratorItem & q = stack_.back();
136         if (q.pos < q.pit->size()) {
137                 InsetBase * inset = q.pit->getInset(q.pos);
138                 if (inset && q.index > 0) {
139                         LyXText * text = inset->getText(q.index - 1);
140                         BOOST_ASSERT(text);
141                         ParagraphList & pl = text->paragraphs();
142                         stack_.push_back(PosIteratorItem(&pl, prior(pl.end()), pl.back().size()));
143                 }
144         }
145         return *this;
146 }
147
148
149 bool operator==(PosIterator const & lhs, PosIterator const & rhs)
150 {
151         PosIteratorItem const & li = lhs.stack_.back();
152         PosIteratorItem const & ri = rhs.stack_.back();
153
154         return (li.pl == ri.pl && li.pit == ri.pit &&
155                 (li.pit == li.pl->end() || li.pos == ri.pos));
156 }
157
158
159 bool PosIterator::at_end() const
160 {
161         return pos() == pit()->size();
162 }
163
164
165 InsetBase * PosIterator::inset() const
166 {
167         if (stack_.size() == 1)
168                 return 0;
169         PosIteratorItem const & pi = stack_[stack_.size() - 2];
170         return pi.pit->getInset(pi.pos);
171 }