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"
24 #include "insets/updatableinset.h"
25 #include "insets/insettabular.h"
26 #include "insets/insettext.h"
28 #include <boost/assert.hpp>
34 std::ostream & operator<<(std::ostream & os, CursorItem const & item)
36 os << " inset: " << item.inset_
37 << " text: " << item.text()
38 // << " par: " << item.par_
39 // << " pos: " << item.pos_
40 << " x: " << item.inset_->x()
41 << " y: " << item.inset_->y()
47 LyXText * CursorItem::text() const
49 return inset_->getText(0);
53 std::ostream & operator<<(std::ostream & os, LCursor const & cursor)
56 for (size_t i = 0, n = cursor.data_.size(); i != n; ++i)
57 os << " " << cursor.data_[i] << "\n";
62 LCursor::LCursor(BufferView * bv)
67 DispatchResult LCursor::dispatch(FuncRequest const & cmd0)
69 lyxerr << "\nLCursor::dispatch: " << *this << endl;
70 FuncRequest cmd = cmd0;
72 for (int i = data_.size() - 1; i >= 0; --i) {
73 CursorItem const & citem = data_[i];
74 lyxerr << "trying to dispatch to inset " << citem.inset_ << endl;
75 DispatchResult res = citem.inset_->dispatch(cmd);
78 if (res.dispatched()) {
79 lyxerr << " successfully dispatched to inset " << citem.inset_ << endl;
80 return DispatchResult(true, true);
82 // remove one level of cursor
86 cmd = FuncRequest(bv_, LFUN_FINISHED_LEFT);
90 cmd = FuncRequest(bv_, LFUN_FINISHED_RIGHT);
94 cmd = FuncRequest(bv_, LFUN_FINISHED_UP);
98 cmd = FuncRequest(bv_, LFUN_FINISHED_DOWN);
101 lyxerr << "not handled on level " << i << " val: " << res.val() << endl;
105 lyxerr << "trying to dispatch to main text " << bv_->text << endl;
106 DispatchResult res = bv_->text->dispatch(cmd);
107 lyxerr << " result: " << res.val() << endl;
112 void LCursor::push(UpdatableInset * inset)
114 lyxerr << "LCursor::push() inset: " << inset << endl;
115 data_.push_back(CursorItem(inset));
116 cached_y_ = bv_->top_y() + innerInset()->y();
120 void LCursor::pop(int depth)
122 lyxerr << "LCursor::pop() to " << depth << endl;
123 while (depth < data_.size()) {
124 lyxerr << "LCursor::pop a level " << endl;
132 lyxerr << "LCursor::pop() " << endl;
133 //BOOST_ASSERT(!data_.empty());
135 lyxerr << "### TRYING TO POP FROM EMPTY CURSOR" << endl;
141 UpdatableInset * LCursor::innerInset() const
143 return data_.empty() ? 0 : data_.back().inset_;
147 LyXText * LCursor::innerText() const
149 if (!data_.empty()) {
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 = data_.size() - 1; i >= 0; --i)
154 return data_[i].text();
160 void LCursor::updatePos()
163 cached_y_ = bv_->top_y() + innerInset()->y();
167 void LCursor::getPos(int & x, int & y) const
170 x = bv_->text->cursor.x();
171 y = bv_->text->cursor.y();
172 // y -= bv_->top_y();
174 // Would be nice to clean this up to make some understandable sense...
175 UpdatableInset * inset = innerInset();
176 // Non-obvious. The reason we have to have these
177 // extra checks is that the ->getCursor() calls rely
178 // on the inset's own knowledge of its screen position.
179 // If we scroll up or down in a big enough increment, the
180 // inset->draw() is not called: this doesn't update
181 // inset.top_baseline, so getCursor() returns an old value.
183 //inset->getCursorPos(bv_, x, y);
184 //y = inset->insetInInsetY() + bv_->text->cursor.y();
185 inset->getCursorPos(bv_, x, y);
192 UpdatableInset * LCursor::innerInsetOfType(int code) const
194 for (int i = data_.size() - 1; i >= 0; --i)
195 if (data_[i].inset_->lyxCode() == code)
196 return data_[i].inset_;
201 InsetTabular * LCursor::innerInsetTabular() const
203 return static_cast<InsetTabular *>
204 (innerInsetOfType(InsetOld::TABULAR_CODE));