3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * Full author contact details are available in file CREDITS.
14 #include "BufferView.h"
17 #include "dispatchresult.h"
18 #include "funcrequest.h"
19 #include "iterators.h"
22 #include "paragraph.h"
25 #include "insets/updatableinset.h"
26 #include "insets/insettabular.h"
27 #include "insets/insettext.h"
29 #include "mathed/math_data.h"
31 #include <boost/assert.hpp>
37 std::ostream & operator<<(std::ostream & os, LCursor const & cur)
40 for (size_t i = 0, n = cur.cursor_.size(); i != n; ++i)
41 os << " (" << cur.cursor_[i] << " | " << cur.anchor_[i] << "\n";
47 : cursor_(1), anchor_(1), bv_(0)
51 LCursor::LCursor(BufferView & bv)
52 : cursor_(1), anchor_(1), bv_(&bv)
56 DispatchResult LCursor::dispatch(FuncRequest const & cmd0)
58 lyxerr << "\nLCursor::dispatch: " << *this << endl;
59 FuncRequest cmd = cmd0;
61 for (int i = cursor_.size() - 1; i >= 1; --i) {
62 CursorSlice const & citem = cursor_[i];
63 lyxerr << "trying to dispatch to inset " << citem.inset_ << endl;
64 DispatchResult res = citem.inset_->dispatch(*bv_, cmd);
65 if (res.dispatched()) {
66 lyxerr << " successfully dispatched to inset " << citem.inset_ << endl;
67 return DispatchResult(true, true);
69 // remove one level of cursor
73 cmd = FuncRequest(LFUN_FINISHED_LEFT);
77 cmd = FuncRequest(LFUN_FINISHED_RIGHT);
81 cmd = FuncRequest(LFUN_FINISHED_UP);
85 cmd = FuncRequest(LFUN_FINISHED_DOWN);
88 lyxerr << "not handled on level " << i << " val: " << res.val() << endl;
92 lyxerr << "trying to dispatch to main text " << bv_->text() << endl;
93 DispatchResult res = bv_->text()->dispatch(*bv_, cmd);
94 lyxerr << " result: " << res.val() << endl;
96 if (!res.dispatched()) {
97 lyxerr << "trying to dispatch to bv " << bv_ << endl;
98 bool sucess = bv_->dispatch(cmd);
99 lyxerr << " result: " << sucess << endl;
100 res.dispatched(sucess);
107 void LCursor::push(InsetBase * inset)
109 lyxerr << "LCursor::push() inset: " << inset << endl;
110 cursor_.push_back(CursorSlice(inset));
111 anchor_.push_back(CursorSlice(inset));
117 void LCursor::pop(int depth)
119 lyxerr << "LCursor::pop() to " << depth << endl;
120 while (cursor_.size() > 1 && depth < cursor_.size()) {
121 lyxerr << "LCursor::pop a level " << endl;
130 lyxerr << "LCursor::pop() " << endl;
131 //BOOST_ASSERT(!cursor_.empty());
132 if (cursor_.size() <= 1)
133 lyxerr << "### TRYING TO POP FROM EMPTY CURSOR" << endl;
141 UpdatableInset * LCursor::innerInset() const
143 return cursor_.size() <= 1 ? 0 : cursor_.back().asUpdatableInset();
147 LyXText * LCursor::innerText() const
149 if (cursor_.size() > 1) {
150 // go up until first non-0 text is hit
151 // (innermost text is 0 e.g. for mathed and the outer tabular level)
152 for (int i = cursor_.size() - 1; i >= 1; --i)
153 if (cursor_[i].text())
154 return cursor_[i].text();
160 void LCursor::updatePos()
162 if (cursor_.size() > 1)
163 cached_y_ = bv_->top_y() + cursor_.back().inset()->y();
167 void LCursor::getDim(int & asc, int & desc) const
169 LyXText * txt = innerText();
172 Row const & row = *txt->cursorRow();
173 asc = row.baseline();
174 desc = row.height() - asc;
176 innerInset()->getCursorDim(asc, desc);
181 void LCursor::getPos(int & x, int & y) const
183 if (cursor_.size() <= 1) {
184 x = bv_->text()->cursorX();
185 y = bv_->text()->cursorY();
186 // y -= bv_->top_y();
188 // Would be nice to clean this up to make some understandable sense...
189 UpdatableInset * inset = innerInset();
190 // Non-obvious. The reason we have to have these
191 // extra checks is that the ->getCursor() calls rely
192 // on the inset's own knowledge of its screen position.
193 // If we scroll up or down in a big enough increment, the
194 // inset->draw() is not called: this doesn't update
195 // inset.top_baseline, so getCursor() returns an old value.
198 inset->getCursorPos(cursor_.back().idx_, x, y);
206 UpdatableInset * LCursor::innerInsetOfType(int code) const
208 for (int i = cursor_.size() - 1; i >= 1; --i)
209 if (cursor_[i].asUpdatableInset()->lyxCode() == code)
210 return cursor_[i].asUpdatableInset();
215 InsetTabular * LCursor::innerInsetTabular() const
217 return static_cast<InsetTabular *>
218 (innerInsetOfType(InsetOld::TABULAR_CODE));
222 void LCursor::resetAnchor()
228 BufferView & LCursor::bv() const
234 MathAtom const & LCursor::prevAtom() const
236 BOOST_ASSERT(pos() > 0);
237 return cell()[pos() - 1];
241 MathAtom & LCursor::prevAtom()
243 BOOST_ASSERT(pos() > 0);
244 return cell()[pos() - 1];
248 MathAtom const & LCursor::nextAtom() const
250 BOOST_ASSERT(pos() < lastpos());
251 return cell()[pos()];
255 MathAtom & LCursor::nextAtom()
257 BOOST_ASSERT(pos() < lastpos());
258 return cell()[pos()];
262 bool LCursor::posLeft()
271 bool LCursor::posRight()
273 if (pos() == lastpos())