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 <boost/assert.hpp>
35 std::ostream & operator<<(std::ostream & os, LCursor const & cursor)
38 for (size_t i = 0, n = cursor.data_.size(); i != n; ++i)
39 os << " " << cursor.data_[i] << "\n";
44 LCursor::LCursor(BufferView * bv)
49 DispatchResult LCursor::dispatch(FuncRequest const & cmd0)
51 lyxerr << "\nLCursor::dispatch: " << *this << endl;
52 FuncRequest cmd = cmd0;
54 for (int i = data_.size() - 1; i >= 1; --i) {
55 CursorSlice const & citem = data_[i];
56 lyxerr << "trying to dispatch to inset " << citem.inset_ << endl;
57 DispatchResult res = citem.inset_->dispatch(cmd);
58 if (res.dispatched()) {
59 lyxerr << " successfully dispatched to inset " << citem.inset_ << endl;
60 return DispatchResult(true, true);
62 // remove one level of cursor
66 cmd = FuncRequest(bv_, LFUN_FINISHED_LEFT);
70 cmd = FuncRequest(bv_, LFUN_FINISHED_RIGHT);
74 cmd = FuncRequest(bv_, LFUN_FINISHED_UP);
78 cmd = FuncRequest(bv_, LFUN_FINISHED_DOWN);
81 lyxerr << "not handled on level " << i << " val: " << res.val() << endl;
85 lyxerr << "trying to dispatch to main text " << bv_->text() << endl;
86 DispatchResult res = bv_->text()->dispatch(cmd);
87 lyxerr << " result: " << res.val() << endl;
89 if (!res.dispatched()) {
90 lyxerr << "trying to dispatch to bv " << bv_ << endl;
91 bool sucess = bv_->dispatch(cmd);
92 lyxerr << " result: " << sucess << endl;
93 res.dispatched(sucess);
100 void LCursor::push(UpdatableInset * inset)
102 lyxerr << "LCursor::push() inset: " << inset << endl;
103 data_.push_back(CursorSlice(inset));
109 void LCursor::pop(int depth)
111 lyxerr << "LCursor::pop() to " << depth << endl;
112 while (data_.size() > 1 && depth < data_.size()) {
113 lyxerr << "LCursor::pop a level " << endl;
121 lyxerr << "LCursor::pop() " << endl;
122 //BOOST_ASSERT(!data_.empty());
123 if (data_.size() <= 1)
124 lyxerr << "### TRYING TO POP FROM EMPTY CURSOR" << endl;
130 UpdatableInset * LCursor::innerInset() const
132 return data_.size() <= 1 ? 0 : data_.back().asUpdatableInset();
136 LyXText * LCursor::innerText() const
138 if (data_.size() > 1) {
139 // go up until first non-0 text is hit
140 // (innermost text is 0 e.g. for mathed and the outer tabular level)
141 for (int i = data_.size() - 1; i >= 1; --i)
143 return data_[i].text();
149 void LCursor::updatePos()
151 if (data_.size() > 1)
152 cached_y_ = bv_->top_y() + innerInset()->y();
156 void LCursor::getDim(int & asc, int & desc) const
158 LyXText * txt = innerText();
161 Row const & row = *txt->cursorRow();
162 asc = row.baseline();
163 desc = row.height() - asc;
165 innerInset()->getCursorDim(asc, desc);
169 void LCursor::getPos(int & x, int & y) const
171 if (data_.size() <= 1) {
172 x = bv_->text()->cursorX();
173 y = bv_->text()->cursorY();
174 // y -= bv_->top_y();
176 // Would be nice to clean this up to make some understandable sense...
177 UpdatableInset * inset = innerInset();
178 // Non-obvious. The reason we have to have these
179 // extra checks is that the ->getCursor() calls rely
180 // on the inset's own knowledge of its screen position.
181 // If we scroll up or down in a big enough increment, the
182 // inset->draw() is not called: this doesn't update
183 // inset.top_baseline, so getCursor() returns an old value.
185 inset->getCursorPos(data_.back().idx_, x, y);
192 UpdatableInset * LCursor::innerInsetOfType(int code) const
194 for (int i = data_.size() - 1; i >= 1; --i)
195 if (data_[i].asUpdatableInset()->lyxCode() == code)
196 return data_[i].asUpdatableInset();
201 InsetTabular * LCursor::innerInsetTabular() const
203 return static_cast<InsetTabular *>
204 (innerInsetOfType(InsetOld::TABULAR_CODE));
208 void LCursor::cell(int idx)
210 BOOST_ASSERT(!data_.empty());
211 data_.back().idx_ = idx;
215 int LCursor::cell() const
217 BOOST_ASSERT(!data_.empty());
218 return data_.back().idx_;