2 #include "dociterator.h"
4 #include "BufferView.h"
10 #include "mathed/math_data.h"
11 #include "mathed/math_inset.h"
13 #include <boost/assert.hpp>
17 DocumentIterator::DocumentIterator()
22 DocumentIterator::DocumentIterator(BufferView & bv)
23 : std::vector<CursorSlice>(1), bv_(&bv)
27 InsetBase * DocumentIterator::nextInset()
29 if (pos() == lastpos())
32 return nextAtom().nucleus();
33 return paragraph().isInset(pos()) ? paragraph().getInset(pos()) : 0;
37 InsetBase * DocumentIterator::prevInset()
42 return prevAtom().nucleus();
43 return paragraph().isInset(pos() - 1) ? paragraph().getInset(pos() - 1) : 0;
47 InsetBase const * DocumentIterator::prevInset() const
52 return prevAtom().nucleus();
53 return paragraph().isInset(pos() - 1) ? paragraph().getInset(pos() - 1) : 0;
57 MathAtom const & DocumentIterator::prevAtom() const
59 BOOST_ASSERT(pos() > 0);
60 return cell()[pos() - 1];
64 MathAtom & DocumentIterator::prevAtom()
66 BOOST_ASSERT(pos() > 0);
67 return cell()[pos() - 1];
71 MathAtom const & DocumentIterator::nextAtom() const
73 BOOST_ASSERT(pos() < lastpos());
78 MathAtom & DocumentIterator::nextAtom()
80 BOOST_ASSERT(pos() < lastpos());
85 LyXText * DocumentIterator::text() const
87 return size() > 1 ? top().text() : bv().text();
91 Paragraph & DocumentIterator::paragraph()
93 BOOST_ASSERT(inTexted());
94 return size() > 1 ? top().paragraph() : *bv().text()->getPar(par());
98 Paragraph const & DocumentIterator::paragraph() const
100 BOOST_ASSERT(inTexted());
101 return size() > 1 ? top().paragraph() : *bv().text()->getPar(par());
105 Row & DocumentIterator::textRow()
107 return *paragraph().getRow(pos());
111 Row const & DocumentIterator::textRow() const
113 return *paragraph().getRow(pos());
117 DocumentIterator::par_type DocumentIterator::lastpar() const
119 return inMathed() ? 0 : text()->paragraphs().size() - 1;
123 DocumentIterator::pos_type DocumentIterator::lastpos() const
125 return inMathed() ? cell().size() : paragraph().size();
129 DocumentIterator::row_type DocumentIterator::crow() const
131 return paragraph().row(pos());
135 DocumentIterator::row_type DocumentIterator::lastcrow() const
137 return paragraph().rows.size();
141 DocumentIterator::idx_type DocumentIterator::lastidx() const
143 return size() > 1 ? top().lastidx() : 0;
147 size_t DocumentIterator::nargs() const
149 // assume 1x1 grid for main text
150 return size() > 1 ? top().nargs() : 1;
154 size_t DocumentIterator::ncols() const
156 // assume 1x1 grid for main text
157 return size() > 1 ? top().ncols() : 1;
161 size_t DocumentIterator::nrows() const
163 // assume 1x1 grid for main text
164 return size() > 1 ? top().nrows() : 1;
168 DocumentIterator::row_type DocumentIterator::row() const
170 return size() > 1 ? top().row() : 0;
174 DocumentIterator::col_type DocumentIterator::col() const
176 return size() > 1 ? top().col() : 0;
180 MathArray const & DocumentIterator::cell() const
182 BOOST_ASSERT(size() > 1);
187 MathArray & DocumentIterator::cell()
189 BOOST_ASSERT(size() > 1);
194 bool DocumentIterator::inMathed() const
196 return size() > 1 && inset()->inMathed();
200 bool DocumentIterator::inTexted() const
206 LyXText * DocumentIterator::innerText() const
208 BOOST_ASSERT(!empty());
210 // go up until first non-0 text is hit
211 // (innermost text is 0 in mathed)
212 for (int i = size() - 1; i >= 1; --i)
213 if (operator[](i).text())
214 return operator[](i).text();
220 CursorSlice const & DocumentIterator::innerTextSlice() const
222 BOOST_ASSERT(!empty());
224 // go up until first non-0 text is hit
225 // (innermost text is 0 in mathed)
226 for (int i = size() - 1; i >= 1; --i)
227 if (operator[](i).text())
228 return operator[](i);
230 return operator[](0);
234 InsetBase * DocumentIterator::innerInsetOfType(int code) const
236 for (int i = size() - 1; i >= 1; --i)
237 if (operator[](i).inset_->lyxCode() == code)
238 return operator[](i).inset_;
243 void DocumentIterator::forwardPos()
245 CursorSlice & top = back();
246 //lyxerr << "XXX\n" << *this << std::endl;
248 // move into an inset to the right if possible
250 if (top.pos() != lastpos()) {
251 // this is impossible for pos() == size()
253 n = (top.cell().begin() + top.pos())->nucleus();
255 if (paragraph().isInset(top.pos()))
256 n = paragraph().getInset(top.pos());
260 if (n && n->isActive()) {
261 //lyxerr << "... descend" << std::endl;
262 push_back(CursorSlice(n));
266 // otherwise move on one cell back if possible
267 if (top.pos() < lastpos()) {
268 //lyxerr << "... next pos" << std::endl;
272 //lyxerr << "... no next pos" << std::endl;
274 // otherwise move on one cell back if possible
275 if (top.par() < lastpar()) {
276 //lyxerr << "... next par" << std::endl;
281 //lyxerr << "... no next par" << std::endl;
283 // otherwise try to move on one cell if possible
284 // [stupid hack for necessary for MathScriptInset]
285 while (top.idx() < lastidx()) {
286 //lyxerr << "... next idx" << std::endl;
290 if (top.inset() && top.inset()->validCell(top.idx())) {
291 //lyxerr << " ... ok" << std::endl;
295 //lyxerr << "... no next idx" << std::endl;
297 // otherwise leave inset an jump over inset as a whole
299 // 'top' is invalid now...
303 // lyxerr << "... no slice left" << std::endl;
307 void DocumentIterator::forwardPar()
309 CursorSlice & top = back();
310 lyxerr << "XXX " << *this << std::endl;
312 // move into an inset to the right if possible
314 if (top.pos() != lastpos()) {
315 // this is impossible for pos() == size()
317 n = (top.cell().begin() + top.pos())->nucleus();
319 if (paragraph().isInset(top.pos()))
320 n = paragraph().getInset(top.pos());
324 if (n && n->isActive()) {
325 lyxerr << "... descend" << std::endl;
326 push_back(CursorSlice(n));
330 // otherwise move on one cell back if possible
331 if (top.pos() < lastpos()) {
332 lyxerr << "... next pos" << std::endl;
337 // otherwise move on one cell back if possible
338 if (top.par() < lastpar()) {
339 lyxerr << "... next par" << std::endl;
345 // otherwise try to move on one cell if possible
346 // [stupid hack for necessary for MathScriptInset]
347 while (top.idx() < top.lastidx()) {
348 lyxerr << "... next idx"
349 << " was: " << top.idx() << " max: " << top.lastidx() << std::endl;
353 if (top.inset() && top.inset()->validCell(top.idx())) {
354 lyxerr << " ... ok" << std::endl;
359 // otherwise leave inset an jump over inset as a whole
361 // 'top' is invalid now...
367 DocumentIterator bufferBegin(BufferView & bv)
369 return DocumentIterator(bv);
373 DocumentIterator bufferEnd()
375 return DocumentIterator();
379 DocumentIterator insetBegin(BufferView & bv, InsetBase * p)
381 DocumentIterator it(bv);
382 it.back() = CursorSlice(p);
387 DocumentIterator insetEnd()
389 return DocumentIterator();
393 std::ostream & operator<<(std::ostream & os, DocumentIterator const & dit)
395 os << "bv: " << &dit.bv() << "\n";
396 for (size_t i = 0, n = dit.size(); i != n; ++i)
397 os << " " << dit.operator[](i) << "\n";
403 ///////////////////////////////////////////////////////
405 StableDocumentIterator::StableDocumentIterator(const DocumentIterator & dit)
408 for (size_t i = 0, n = data_.size(); i != n; ++i)
414 StableDocumentIterator::asDocumentIterator(BufferView & bv) const
416 // this function re-creates the cache of inset pointers
417 //lyxerr << "converting:\n" << *this << std::endl;
418 DocumentIterator dit(bv);
420 InsetBase * inset = 0;
421 for (size_t i = 0, n = data_.size(); i != n; ++i) {
422 dit.push_back(data_[i]);
423 dit.back().inset_ = inset;
425 inset = dit.nextInset();
427 //lyxerr << "convert:\n" << *this << " to:\n" << dit << std::endl;
432 std::ostream & operator<<(std::ostream & os, StableDocumentIterator const & dit)
434 for (size_t i = 0, n = dit.data_.size(); i != n; ++i)
435 os << " " << dit.data_[i] << "\n";