2 #include "dociterator.h"
9 #include "mathed/math_data.h"
10 #include "mathed/math_inset.h"
12 #include <boost/assert.hpp>
17 //we could be able to get rid of this if only every BufferView were
18 //associated to a buffer on construction
19 DocumentIterator::DocumentIterator() : inset_(0)
23 DocumentIterator doc_iterator_begin(InsetBase & inset)
25 DocumentIterator dit(inset);
31 DocumentIterator doc_iterator_end(InsetBase & inset)
33 return DocumentIterator(inset);
37 DocumentIterator::DocumentIterator(InsetBase & inset) : inset_(&inset)
41 InsetBase * DocumentIterator::nextInset()
43 BOOST_ASSERT(!empty());
44 if (pos() == lastpos())
47 return nextAtom().nucleus();
48 return paragraph().isInset(pos()) ? paragraph().getInset(pos()) : 0;
52 InsetBase * DocumentIterator::prevInset()
54 BOOST_ASSERT(!empty());
58 return prevAtom().nucleus();
59 return paragraph().isInset(pos() - 1) ? paragraph().getInset(pos() - 1) : 0;
63 InsetBase const * DocumentIterator::prevInset() const
65 BOOST_ASSERT(!empty());
69 return prevAtom().nucleus();
70 return paragraph().isInset(pos() - 1) ? paragraph().getInset(pos() - 1) : 0;
74 MathAtom const & DocumentIterator::prevAtom() const
76 BOOST_ASSERT(!empty());
77 BOOST_ASSERT(pos() > 0);
78 return cell()[pos() - 1];
82 MathAtom & DocumentIterator::prevAtom()
84 BOOST_ASSERT(!empty());
85 BOOST_ASSERT(pos() > 0);
86 return cell()[pos() - 1];
90 MathAtom const & DocumentIterator::nextAtom() const
92 BOOST_ASSERT(!empty());
93 BOOST_ASSERT(pos() < lastpos());
98 MathAtom & DocumentIterator::nextAtom()
100 BOOST_ASSERT(!empty());
101 BOOST_ASSERT(pos() < lastpos());
102 return cell()[pos()];
106 LyXText * DocumentIterator::text() const
108 BOOST_ASSERT(!empty());
113 Paragraph & DocumentIterator::paragraph()
115 BOOST_ASSERT(inTexted());
116 return top().paragraph();
120 Paragraph const & DocumentIterator::paragraph() const
122 BOOST_ASSERT(inTexted());
123 return top().paragraph();
127 Row & DocumentIterator::textRow()
129 return *paragraph().getRow(pos());
133 Row const & DocumentIterator::textRow() const
135 return *paragraph().getRow(pos());
139 DocumentIterator::par_type DocumentIterator::lastpar() const
141 return inMathed() ? 0 : text()->paragraphs().size() - 1;
145 DocumentIterator::pos_type DocumentIterator::lastpos() const
147 return inMathed() ? cell().size() : paragraph().size();
151 DocumentIterator::row_type DocumentIterator::crow() const
153 return paragraph().row(pos());
157 DocumentIterator::row_type DocumentIterator::lastcrow() const
159 return paragraph().rows.size();
163 DocumentIterator::idx_type DocumentIterator::lastidx() const
165 return top().lastidx();
169 size_t DocumentIterator::nargs() const
171 // assume 1x1 grid for main text
172 return top().nargs();
176 size_t DocumentIterator::ncols() const
178 // assume 1x1 grid for main text
179 return top().ncols();
183 size_t DocumentIterator::nrows() const
185 // assume 1x1 grid for main text
186 return top().nrows();
190 DocumentIterator::row_type DocumentIterator::row() const
196 DocumentIterator::col_type DocumentIterator::col() const
202 MathArray const & DocumentIterator::cell() const
204 BOOST_ASSERT(inMathed());
209 MathArray & DocumentIterator::cell()
211 BOOST_ASSERT(inMathed());
216 bool DocumentIterator::inMathed() const
218 return !empty() && inset().inMathed();
222 bool DocumentIterator::inTexted() const
224 return !empty() && !inset().inMathed();
228 LyXText * DocumentIterator::innerText() const
230 BOOST_ASSERT(!empty());
231 // go up until first non-0 text is hit
232 // (innermost text is 0 in mathed)
233 for (int i = size() - 1; i >= 0; --i)
234 if (operator[](i).text())
235 return operator[](i).text();
240 InsetBase * DocumentIterator::innerInsetOfType(int code) const
242 for (int i = size() - 1; i >= 0; --i)
243 if (operator[](i).inset_->lyxCode() == code)
244 return operator[](i).inset_;
249 void DocumentIterator::forwardPos()
251 //this dog bites his tail
253 push_back(CursorSlice(*inset_));
257 CursorSlice & top = back();
258 //lyxerr << "XXX\n" << *this << endl;
260 // this is used twice and shows up in the profiler!
261 pos_type const lastp = lastpos();
263 // move into an inset to the right if possible
266 if (top.pos() != lastp) {
267 // this is impossible for pos() == size()
269 n = (top.cell().begin() + top.pos())->nucleus();
271 if (paragraph().isInset(top.pos()))
272 n = paragraph().getInset(top.pos());
276 if (n && n->isActive()) {
277 //lyxerr << "... descend" << endl;
278 push_back(CursorSlice(*n));
282 // otherwise move on one position if possible
283 if (top.pos() < lastp) {
284 //lyxerr << "... next pos" << endl;
288 //lyxerr << "... no next pos" << endl;
290 // otherwise move on one paragraph if possible
291 if (top.par() < lastpar()) {
292 //lyxerr << "... next par" << endl;
297 //lyxerr << "... no next par" << endl;
299 // otherwise try to move on one cell if possible
300 if (top.idx() < lastidx()) {
301 //lyxerr << "... next idx" << endl;
307 //lyxerr << "... no next idx" << endl;
309 // otherwise leave inset and jump over inset as a whole
311 // 'top' is invalid now...
317 void DocumentIterator::forwardPar()
320 while (!empty() && (!inTexted() || pos() != 0))
325 void DocumentIterator::forwardChar()
328 while (size() != 0 && pos() == lastpos())
333 void DocumentIterator::forwardInset()
336 while (size() != 0 && (pos() == lastpos() || nextInset() == 0))
341 void DocumentIterator::backwardChar()
344 while (size() != 0 && pos() == lastpos())
349 void DocumentIterator::backwardPos()
351 //this dog bites his tail
353 push_back(CursorSlice(*inset_));
354 back().idx() = lastidx();
355 back().par() = lastpar();
356 back().pos() = lastpos();
360 CursorSlice & top = back();
362 if (top.pos() != 0) {
364 } else if (top.par() != 0) {
366 top.pos() = lastpos();
368 } else if (top.idx() != 0) {
370 top.par() = lastpar();
371 top.pos() = lastpos();
378 // move into an inset to the left if possible
382 n = (top.cell().begin() + top.pos())->nucleus();
384 if (paragraph().isInset(top.pos()))
385 n = paragraph().getInset(top.pos());
388 if (n && n->isActive()) {
389 push_back(CursorSlice(*n));
390 back().idx() = lastidx();
391 back().par() = lastpar();
392 back().pos() = lastpos();
397 std::ostream & operator<<(std::ostream & os, DocumentIterator const & dit)
399 for (size_t i = 0, n = dit.size(); i != n; ++i)
400 os << " " << dit.operator[](i) << "\n";
406 ///////////////////////////////////////////////////////
408 StableDocumentIterator::StableDocumentIterator(const DocumentIterator & dit)
411 for (size_t i = 0, n = data_.size(); i != n; ++i)
417 StableDocumentIterator::asDocumentIterator(InsetBase * inset) const
419 // this function re-creates the cache of inset pointers
420 //lyxerr << "converting:\n" << *this << endl;
421 DocumentIterator dit = DocumentIterator(*inset);
422 for (size_t i = 0, n = data_.size(); i != n; ++i) {
423 dit.push_back(data_[i]);
424 dit.back().inset_ = inset;
426 inset = dit.nextInset();
428 //lyxerr << "convert:\n" << *this << " to:\n" << dit << endl;
433 std::ostream & operator<<(std::ostream & os, StableDocumentIterator const & dit)
435 for (size_t i = 0, n = dit.data_.size(); i != n; ++i)
436 os << " " << dit.data_[i] << "\n";