X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fcursor.C;h=3ca9d9b9cbaf303887455fea4daab8772d15b3d9;hb=de49e029348c639be64ec77cc9d292c0da6ddc3b;hp=e6e59eae0eb6d7b837cb8a13418eed8c820b43d1;hpb=c1319d2c6738ff3e72283917ea903f4878298d41;p=lyx.git diff --git a/src/cursor.C b/src/cursor.C index e6e59eae0e..3ca9d9b9cb 100644 --- a/src/cursor.C +++ b/src/cursor.C @@ -3,7 +3,7 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * - * \author Jürgen Vigna + * \author André Pönitz * * Full author contact details are available in file CREDITS. */ @@ -15,64 +15,183 @@ #include "cursor.h" #include "debug.h" #include "dispatchresult.h" +#include "funcrequest.h" #include "iterators.h" +#include "lfuns.h" #include "lyxtext.h" #include "paragraph.h" #include "insets/updatableinset.h" +#include "insets/insettabular.h" +#include "insets/insettext.h" + +#include using std::vector; using std::endl; -DispatchResult Cursor::dispatch(FuncRequest const & cmd) +std::ostream & operator<<(std::ostream & os, CursorItem const & item) { - for (int i = data_.size() - 1; i >= 0; --i) { - lyxerr << "trying to dispatch to inset" << data_[i].inset_ << endl; - DispatchResult res = data_[i].inset_->dispatch(cmd); - lyxerr << " result: " << res.val() << endl; + os << " inset: " << item.inset_ + << " text: " << item.text() +// << " par: " << item.par_ +// << " pos: " << item.pos_ + << " x: " << item.inset_->x() + << " y: " << item.inset_->y() +; + return os; +} + + +LyXText * CursorItem::text() const +{ + return inset_->getText(0); +} + + +std::ostream & operator<<(std::ostream & os, LCursor const & cursor) +{ + os << "\n"; + for (size_t i = 0, n = cursor.data_.size(); i != n; ++i) + os << " " << cursor.data_[i] << "\n"; + return os; +} - if (res.dispatched()) - return res; - lyxerr << "# unhandled result: " << res.val() << endl; +LCursor::LCursor(BufferView * bv) + : bv_(bv) +{} + + +DispatchResult LCursor::dispatch(FuncRequest const & cmd0) +{ + lyxerr << "\nLCursor::dispatch: " << *this << endl; + FuncRequest cmd = cmd0; + + for (int i = data_.size() - 1; i >= 0; --i) { + CursorItem const & citem = data_[i]; + lyxerr << "trying to dispatch to inset " << citem.inset_ << endl; + DispatchResult res = citem.inset_->dispatch(cmd); + if (res.update()) + bv_->update(); + if (res.dispatched()) { + lyxerr << " successfully dispatched to inset " << citem.inset_ << endl; + return DispatchResult(true, true); + } + // remove one level of cursor + switch (res.val()) { + case FINISHED: + pop(i); + cmd = FuncRequest(bv_, LFUN_FINISHED_LEFT); + break; + case FINISHED_RIGHT: + pop(i); + cmd = FuncRequest(bv_, LFUN_FINISHED_RIGHT); + break; + case FINISHED_UP: + pop(i); + cmd = FuncRequest(bv_, LFUN_FINISHED_UP); + break; + case FINISHED_DOWN: + pop(i); + cmd = FuncRequest(bv_, LFUN_FINISHED_DOWN); + break; + default: + lyxerr << "not handled on level " << i << " val: " << res.val() << endl; + break; + } } - return DispatchResult(false); + lyxerr << "trying to dispatch to main text " << bv_->text << endl; + DispatchResult res = bv_->text->dispatch(cmd); + lyxerr << " result: " << res.val() << endl; + return res; } -void buildCursor(Cursor & cursor, BufferView & bv) +void LCursor::push(UpdatableInset * inset) { - UpdatableInset * inset = bv.theLockingInset(); - lyxerr << "\nbuildCursor: " << inset << endl; - if (!inset) - return; - - inset = inset->getLockingInset(); - - bool ok = false; - ParIterator pit = bv.buffer()->par_iterator_begin(); - ParIterator end = bv.buffer()->par_iterator_end(); - for ( ; pit != end && !ok; ++pit) { - InsetList::iterator it = pit->insetlist.begin(); - InsetList::iterator iend = pit->insetlist.end(); - for ( ; it != iend && !ok; ++it) - if (it->inset == inset || it->inset == inset->owner()) - ok = true; + lyxerr << "LCursor::push() inset: " << inset << endl; + data_.push_back(CursorItem(inset)); +} + + +void LCursor::pop(int depth) +{ + lyxerr << "LCursor::pop() to " << depth << endl; + while (depth < data_.size()) { + lyxerr << "LCursor::pop a level " << endl; + data_.pop_back(); } +} - if (!ok) { - lyxerr << " tli not found! inset: " << inset << endl; - return; + +void LCursor::pop() +{ + lyxerr << "LCursor::pop() " << endl; + //BOOST_ASSERT(!data_.empty()); + if (data_.empty()) + lyxerr << "### TRYING TO POP FROM EMPTY CURSOR" << endl; + else + data_.pop_back(); +} + + +UpdatableInset * LCursor::innerInset() const +{ + return data_.empty() ? 0 : data_.back().inset_; +} + + +LyXText * LCursor::innerText() const +{ + if (!data_.empty()) { + // go up until first non-0 text is hit + // (innermost text is 0 e.g. for mathed and the outer tabular level) + for (int i = data_.size() - 1; i >= 0; --i) + if (data_[i].text()) + return data_[i].text(); } + return bv_->text; +} + - pit.asCursor(cursor); - for (size_t i = 0, n = cursor.data_.size(); i != n; ++i) { - lyxerr << " inset: " << cursor.data_[i].inset_ - << " idx: " << cursor.data_[i].idx_ - << " text: " << cursor.data_[i].text_ - << " par: " << cursor.data_[i].par_ - << " pos: " << cursor.data_[i].pos_ - << endl; +void LCursor::getPos(int & x, int & y) const +{ + if (data_.empty()) { + x = bv_->text->cursor.x(); + y = bv_->text->cursor.y(); + y -= bv_->top_y(); + } else { + // Would be nice to clean this up to make some understandable sense... + UpdatableInset * inset = innerInset(); + // Non-obvious. The reason we have to have these + // extra checks is that the ->getCursor() calls rely + // on the inset's own knowledge of its screen position. + // If we scroll up or down in a big enough increment, the + // inset->draw() is not called: this doesn't update + // inset.top_baseline, so getCursor() returns an old value. + // Ugly as you like. + //inset->getCursorPos(bv_, x, y); + //y = inset->insetInInsetY() + bv_->text->cursor.y(); + inset->getCursorPos(bv_, x, y); + x += inset->x(); + y += inset->y(); } } + + +UpdatableInset * LCursor::innerInsetOfType(int code) const +{ + for (int i = data_.size() - 1; i >= 0; --i) + if (data_[i].inset_->lyxCode() == code) + return data_[i].inset_; + return 0; +} + + +InsetTabular * LCursor::innerInsetTabular() const +{ + return static_cast + (innerInsetOfType(InsetOld::TABULAR_CODE)); +}