X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fcursor.C;h=50d630ec8501b1bb42a8129781f2fe6380658ebf;hb=5ede7e4889b088219326a1d4a94a0a2a732a1379;hp=7f96e6e32908c7e2a00bd3b4621273b5511d75ee;hpb=ca176cc4347a352f3b26f48a457ee7ba94463f37;p=lyx.git diff --git a/src/cursor.C b/src/cursor.C index 7f96e6e329..50d630ec85 100644 --- a/src/cursor.C +++ b/src/cursor.C @@ -20,9 +20,10 @@ #include "funcrequest.h" #include "iterators.h" #include "lfuns.h" +#include "lyxfunc.h" // only for setMessage() #include "lyxrc.h" -#include "lyxtext.h" #include "lyxrow.h" +#include "lyxtext.h" #include "paragraph.h" #include "insets/updatableinset.h" @@ -34,6 +35,9 @@ #include "mathed/math_support.h" #include "support/limited_stack.h" +#include "support/std_sstream.h" + +#include "frontends/LyXView.h" #include @@ -67,7 +71,7 @@ void LCursor::reset() anchor_.push_back(CursorSlice()); current_ = 0; cached_y_ = 0; - x_target_ = -1; + clearTargetX(); selection_ = false; mark_ = false; } @@ -75,53 +79,46 @@ void LCursor::reset() DispatchResult LCursor::dispatch(FuncRequest const & cmd0) { - lyxerr << "\nLCursor::dispatch: " << *this << endl; + lyxerr << "\nLCursor::dispatch: cmd: " << cmd0 << endl << *this << endl; FuncRequest cmd = cmd0; - - for (int i = cursor_.size() - 1; i >= 1; --i) { - current_ = i; - CursorSlice const & citem = cursor_[i]; - lyxerr << "trying to dispatch to inset " << citem.inset_ << endl; - DispatchResult res = inset()->dispatch(*this, cmd); - if (res.dispatched()) { - lyxerr << " successfully dispatched to inset " << citem.inset_ << endl; - return DispatchResult(true, true); - } - // remove one level of cursor - switch (res.val()) { + disp_.update(true); + disp_.val(NONE); + for (current_ = cursor_.size() - 1; current_ >= 1; --current_) { + // the inset's dispatch() is supposed to reset the update and + // val flags if necessary + inset()->dispatch(*this, cmd); + + // "Mutate" the request for semi-handled requests that need + // additional handling in outer levels. + switch (disp_.val()) { + case NONE: + // the inset handled the event fully + current_ = cursor_.size() - 1; + return DispatchResult(true, true); case FINISHED: - pop(i); + // the inset handled the event partially cmd = FuncRequest(LFUN_FINISHED_LEFT); break; case FINISHED_RIGHT: - pop(i); cmd = FuncRequest(LFUN_FINISHED_RIGHT); break; case FINISHED_UP: - pop(i); cmd = FuncRequest(LFUN_FINISHED_UP); break; case FINISHED_DOWN: - pop(i); cmd = FuncRequest(LFUN_FINISHED_DOWN); break; default: - lyxerr << "not handled on level " << i << " val: " << res.val() << endl; + //lyxerr << "not handled on level " << current_ + // << " val: " << disp_.val() << endl; break; } } - lyxerr << "trying to dispatch to main text " << bv_->text() << endl; - DispatchResult res = bv_->text()->dispatch(*this, cmd); - lyxerr << " result: " << res.val() << endl; - - if (!res.dispatched()) { - lyxerr << "trying to dispatch to bv " << bv_ << endl; - bool sucess = bv_->dispatch(cmd); - lyxerr << " result: " << sucess << endl; - res.dispatched(sucess); - } - - return res; + BOOST_ASSERT(current_ == 0); + bv_->text()->dispatch(*this, cmd); + //lyxerr << " result: " << res.val() << endl; + current_ = cursor_.size() - 1; + return disp_; } @@ -137,29 +134,24 @@ void LCursor::push(InsetBase * inset) void LCursor::pop(int depth) { - lyxerr << "LCursor::pop() to depth " << depth << endl; - while (int(cursor_.size()) > depth) + while (int(cursor_.size()) > depth + 1) pop(); + lyxerr << "LCursor::pop() result: " << *this << endl; } void LCursor::pop() { - lyxerr << "LCursor::pop() a level" << endl; - //BOOST_ASSERT(!cursor_.empty()); - if (cursor_.size() <= 1) - lyxerr << "### TRYING TO POP FROM EMPTY CURSOR" << endl; - else { - cursor_.pop_back(); - anchor_.pop_back(); - current_ = cursor_.size() - 1; - } - lyxerr << "LCursor::pop() current now: " << current_ << endl; + BOOST_ASSERT(cursor_.size() >= 1); + cursor_.pop_back(); + anchor_.pop_back(); + current_ = cursor_.size() - 1; } void LCursor::pushLeft(InsetBase * p) { + BOOST_ASSERT(!cursor_.empty()); //lyxerr << "Entering inset " << t << " left" << endl; push(p); p->idxFirst(*this); @@ -168,6 +160,7 @@ void LCursor::pushLeft(InsetBase * p) bool LCursor::popLeft() { + BOOST_ASSERT(!cursor_.empty()); //lyxerr << "Leaving inset to the left" << endl; if (depth() <= 1) { if (depth() == 1) @@ -182,6 +175,7 @@ bool LCursor::popLeft() bool LCursor::popRight() { + BOOST_ASSERT(!cursor_.empty()); //lyxerr << "Leaving inset to the right" << endl; if (depth() <= 1) { if (depth() == 1) @@ -190,13 +184,14 @@ bool LCursor::popRight() } inset()->notifyCursorLeaves(idx()); pop(); - posRight(); + ++pos(); return true; } CursorSlice & LCursor::current() { + BOOST_ASSERT(!cursor_.empty()); //lyxerr << "accessing cursor slice " << current_ // << ": " << cursor_[current_] << endl; return cursor_[current_]; @@ -213,6 +208,7 @@ CursorSlice const & LCursor::current() const int LCursor::currentMode() { + BOOST_ASSERT(!cursor_.empty()); for (int i = cursor_.size() - 1; i >= 1; --i) { int res = cursor_[i].inset()->currentMode(); if (res != MathInset::UNDECIDED_MODE) @@ -224,7 +220,7 @@ int LCursor::currentMode() LyXText * LCursor::innerText() const { - //lyxerr << "LCursor::innerText() depth: " << cursor_.size() << endl; + BOOST_ASSERT(!cursor_.empty()); if (cursor_.size() > 1) { // go up until first non-0 text is hit // (innermost text is 0 in mathed) @@ -238,7 +234,7 @@ LyXText * LCursor::innerText() const CursorSlice const & LCursor::innerTextSlice() const { - //lyxerr << "LCursor::innerTextSlice() depth: " << cursor_.size() << endl; + BOOST_ASSERT(!cursor_.empty()); if (cursor_.size() > 1) { // go up until first non-0 text is hit // (innermost text is 0 in mathed) @@ -252,53 +248,57 @@ CursorSlice const & LCursor::innerTextSlice() const void LCursor::updatePos() { + BOOST_ASSERT(!cursor_.empty()); if (cursor_.size() > 1) - cached_y_ = bv_->top_y() + cursor_.back().inset()->y(); + cached_y_ = bv_->top_y() + cursor_.back().inset()->yo(); + //cached_y_ = cursor_.back().inset()->yo(); } -void LCursor::getDim(int & asc, int & desc) const +void LCursor::getDim(int & asc, int & des) const { - LyXText * txt = innerText(); - - if (txt) { - Row const & row = *txt->cursorRow(); - asc = row.baseline(); - desc = row.height() - asc; - } else { + BOOST_ASSERT(!cursor_.empty()); + if (inMathed()) { + BOOST_ASSERT(inset()); + BOOST_ASSERT(inset()->asMathInset()); + //inset()->asMathInset()->getCursorDim(asc, des); asc = 10; - desc = 10; - //innerInset()->getCursorDim(asc, desc); + des = 10; + } else { + Row const & row = textRow(); + asc = row.baseline(); + des = row.height() - asc; } } void LCursor::getPos(int & x, int & y) const { - if (cursor_.size() <= 1) { - x = bv_->text()->cursorX(); - y = bv_->text()->cursorY(); -// y -= bv_->top_y(); + BOOST_ASSERT(!cursor_.empty()); + x = 0; + y = 0; + if (cursor_.size() == 1) { + x = bv_->text()->cursorX(cursor_.front()); + y = bv_->text()->cursorY(cursor_.front()); } else { - if (inset()->asUpdatableInset()) { - // Would be nice to clean this up to make some understandable sense... - // 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()->asUpdatableInset()->getCursorPos(cursor_.back().idx_, x, y); - x += inset()->asUpdatableInset()->x(); - y += cached_y_; - } else if (inset()->asMathInset()) { - getScreenPos(x, y); - } else { - // this should not happen - BOOST_ASSERT(false); + if (!inset()) { + lyxerr << "#### LCursor::getPos: " << *this << endl; + BOOST_ASSERT(inset()); } + inset()->getCursorPos(cursor_.back(), x, y); + // getCursorPos gives _screen_ coordinates. We need to add + // top_y to get document coordinates. This is hidden in cached_y_. + //y += cached_y_ - inset()->yo(); + // The rest is non-obvious. The reason we have to have these + // extra computation is that the getCursorPos() calls rely + // on the inset's own knowledge of its screen position. + // If we scroll up or down in a big enough increment, + // inset->draw() is not called: this doesn't update + // inset.yo_, so getCursor() returns an old value. + // Ugly as you like. } + //lyxerr << "#### LCursor::getPos: " << *this + // << " x: " << x << " y: " << y << endl; } @@ -397,7 +397,6 @@ CursorSlice const & LCursor::selBegin() const { if (!selection()) return cursor_.back(); - // can't use std::min as this creates a new object return anchor() < cursor_.back() ? anchor() : cursor_.back(); } @@ -406,6 +405,7 @@ CursorSlice & LCursor::selBegin() { if (!selection()) return cursor_.back(); + // can't use std::min as this returns a const ref return anchor() < cursor_.back() ? anchor() : cursor_.back(); } @@ -420,8 +420,9 @@ CursorSlice const & LCursor::selEnd() const CursorSlice & LCursor::selEnd() { - if (selection()) + if (!selection()) return cursor_.back(); + // can't use std::min as this returns a const ref return anchor() > cursor_.back() ? anchor() : cursor_.back(); } @@ -453,9 +454,9 @@ void LCursor::clearSelection() } -void LCursor::x_target(int x) +int & LCursor::x_target() { - x_target_ = x; + return x_target_; } @@ -465,25 +466,66 @@ int LCursor::x_target() const } +void LCursor::clearTargetX() +{ + x_target_ = -1; +} + + +LyXText * LCursor::text() const +{ + return current_ ? current().text() : bv_->text(); +} + + Paragraph & LCursor::paragraph() { + BOOST_ASSERT(inTexted()); return current_ ? current().paragraph() : *bv_->text()->getPar(par()); } Paragraph const & LCursor::paragraph() const { + BOOST_ASSERT(inTexted()); return current_ ? current().paragraph() : *bv_->text()->getPar(par()); } +Row & LCursor::textRow() +{ + return *paragraph().getRow(pos()); +} + + +Row const & LCursor::textRow() const +{ + return *paragraph().getRow(pos()); +} + + +LCursor::par_type LCursor::lastpar() const +{ + return inMathed() ? 0 : text()->paragraphs().size() - 1; +} + + LCursor::pos_type LCursor::lastpos() const { - CursorSlice const & cur = current(); - if (cur.inset() && cur.inset()->asMathInset()) - return cell().size(); - else - return paragraph().size(); + InsetBase * inset = current().inset(); + return inset && inset->asMathInset() ? cell().size() : paragraph().size(); +} + + +LCursor::row_type LCursor::crow() const +{ + return paragraph().row(pos()); +} + + +LCursor::row_type LCursor::lastcrow() const +{ + return paragraph().rows.size(); } @@ -536,15 +578,14 @@ MathArray & LCursor::cell() } -void LCursor::info(std::ostream & os) +void LCursor::info(std::ostream & os) const { for (int i = 1, n = depth(); i < n; ++i) { cursor_[i].inset()->infoize(os); os << " "; } -#warning FIXME - //if (pos() != 0) - // prevAtom()->infoize2(os); + if (pos() != 0) + prevInset()->infoize2(os); // overwite old message os << " "; } @@ -611,8 +652,9 @@ string LCursor::grabSelection() void LCursor::eraseSelection() { - CursorSlice i1 = selBegin(); - CursorSlice i2 = selEnd(); + //lyxerr << "LCursor::eraseSelection" << endl; + CursorSlice const & i1 = selBegin(); + CursorSlice const & i2 = selEnd(); #warning FIXME if (i1.inset()->asMathInset()) { if (i1.idx_ == i2.idx_) { @@ -630,6 +672,7 @@ void LCursor::eraseSelection() } else { lyxerr << "can't erase this selection 1" << endl; } + //lyxerr << "LCursor::eraseSelection end" << endl; } @@ -670,6 +713,7 @@ void LCursor::selCut() void LCursor::selDel() { + //lyxerr << "LCursor::selDel" << endl; if (selection()) { eraseSelection(); selection() = false; @@ -689,6 +733,7 @@ void LCursor::selPaste(size_t n) void LCursor::selHandle(bool sel) { + //lyxerr << "LCursor::selHandle" << endl; if (sel == selection()) return; resetAnchor(); @@ -696,15 +741,9 @@ void LCursor::selHandle(bool sel) } -void LCursor::selStart() -{ - resetAnchor(); - selection() = true; -} - - void LCursor::selClearOrDel() { + //lyxerr << "LCursor::selClearOrDel" << endl; if (lyxrc.auto_region_delete) selDel(); else @@ -714,9 +753,10 @@ void LCursor::selClearOrDel() std::ostream & operator<<(std::ostream & os, LCursor const & cur) { - os << "\n"; for (size_t i = 0, n = cur.cursor_.size(); i != n; ++i) - os << " (" << cur.cursor_[i] << " | " << cur.anchor_[i] << "\n"; + os << " " << cur.cursor_[i] << " | " << cur.anchor_[i] << "\n"; + os << " current: " << cur.current_ << endl; + os << " selection: " << cur.selection_ << endl; return os; } @@ -835,7 +875,7 @@ bool LCursor::openable(MathAtom const & t) // we can't move into anything new during selection if (depth() == anchor_.size()) return false; - if (t.nucleus() != anchor_[depth()].inset()) + if (!ptr_cmp(t.nucleus(), anchor_[depth()].inset())) return false; return true; @@ -851,7 +891,7 @@ bool LCursor::inNucleus() bool LCursor::left() { autocorrect() = false; - x_target(-1); // "no target" + clearTargetX(); if (inMacroMode()) { macroModeClose(); return true; @@ -859,8 +899,8 @@ bool LCursor::left() if (pos() != 0 && openable(prevAtom())) { posLeft(); - push(inset()); - inset()->idxFirst(*this); + push(nextAtom().nucleus()); + inset()->idxLast(*this); return true; } @@ -871,14 +911,15 @@ bool LCursor::left() bool LCursor::right() { autocorrect() = false; - x_target(-1); // "no target" + clearTargetX(); if (inMacroMode()) { macroModeClose(); return true; } if (pos() != lastpos() && openable(nextAtom())) { - pushLeft(inset()); + pushLeft(nextAtom().nucleus()); + inset()->idxFirst(*this); return true; } @@ -893,7 +934,7 @@ bool positionable(CursorBase const & cursor, CursorBase const & anchor) return false; // anchor might be deeper, should have same path then - for (CursorBase::size_type i = 0; i < cursor.size(); ++i) + for (size_t i = 0; i < cursor.size(); ++i) if (cursor[i].inset() != anchor[i].inset()) return false; @@ -911,7 +952,7 @@ void LCursor::setScreenPos(int x, int y) idx() = 0; pos() = 0; } - x_target(-1); // "no target" + clearTargetX(); } @@ -922,7 +963,7 @@ bool LCursor::home() macroModeClose(); if (!inset()->idxHome(*this)) return popLeft(); - x_target(-1); // "no target" + clearTargetX(); return true; } @@ -933,7 +974,7 @@ bool LCursor::end() macroModeClose(); if (!inset()->idxEnd(*this)) return popRight(); - x_target(-1); // "no target" + clearTargetX(); return true; } @@ -963,26 +1004,24 @@ void LCursor::plainInsert(MathAtom const & t) } -void LCursor::insert2(string const & str) -{ - MathArray ar; - asArray(str, ar); - insert(ar); -} - - void LCursor::insert(string const & str) { - //lyxerr << "inserting '" << str << "'" << endl; + lyxerr << "LCursor::insert str '" << str << "'" << endl; selClearOrDel(); +#if 0 for (string::const_iterator it = str.begin(); it != str.end(); ++it) plainInsert(MathAtom(new MathCharInset(*it))); +#else + MathArray ar; + asArray(str, ar); + insert(ar); +#endif } void LCursor::insert(char c) { - //lyxerr << "inserting '" << c << "'" << endl; + //lyxerr << "LCursor::insert char '" << c << "'" << endl; selClearOrDel(); plainInsert(MathAtom(new MathCharInset(c))); } @@ -990,12 +1029,22 @@ void LCursor::insert(char c) void LCursor::insert(MathAtom const & t) { + //lyxerr << "LCursor::insert MathAtom: " << endl; macroModeClose(); selClearOrDel(); plainInsert(t); } +void LCursor::insert(InsetBase * inset) +{ + if (inMathed()) + insert(MathAtom(inset)); + else + text()->insertInset(*this, inset); +} + + void LCursor::niceInsert(string const & t) { MathArray ar; @@ -1015,7 +1064,9 @@ void LCursor::niceInsert(MathAtom const & t) // enter the new inset and move the contents of the selection if possible if (t->isActive()) { posLeft(); - pushLeft(inset()); + // be careful here: don't use 'pushLeft(t)' as this we need to + // push the clone, not the original + pushLeft(nextAtom().nucleus()); paste(safe); } } @@ -1080,9 +1131,8 @@ bool LCursor::erase() } // delete empty cells if possible -#warning FIXME - //if (cell().empty() && inset()->idxDelete(idx())) - // return true; + if (pos() == lastpos() && inset()->idxDelete(idx())) + return true; // special behaviour when in last position of cell if (pos() == lastpos()) { @@ -1163,31 +1213,14 @@ string LCursor::macroName() } -void LCursor::drawSelection(PainterInfo & pi) -{ - if (!selection()) - return; - CursorSlice i1 = selBegin(); - CursorSlice i2 = selEnd(); - i1.asMathInset()->drawSelection(pi, i1.idx_, i1.pos_, i2.idx_, i2.pos_); -} - - void LCursor::handleNest(MathAtom const & a, int c) { - MathAtom at = a; - asArray(grabAndEraseSelection(), at.nucleus()->cell(c)); - insert(at); + //lyxerr << "LCursor::handleNest: " << c << endl; + MathAtom t = a; + asArray(grabAndEraseSelection(), t.nucleus()->cell(c)); + insert(t); posLeft(); - pushLeft(inset()); -} - - -void LCursor::getScreenPos(int & x, int & y) const -{ - BOOST_ASSERT(inset()); - BOOST_ASSERT(inset()->asMathInset()); - inset()->asMathInset()->getScreenPos(idx(), pos(), x, y); + pushLeft(nextAtom().nucleus()); } @@ -1197,16 +1230,18 @@ int LCursor::targetX() const return x_target(); int x = 0; int y = 0; - getScreenPos(x, y); + getPos(x, y); return x; } MathHullInset * LCursor::formula() const { - for (int i = cursor_.size() - 1; i >= 1; --i) - if (cursor_[i].inset()->lyxCode() == InsetBase::MATH_CODE) - return static_cast(cursor_[i].inset()); + for (int i = cursor_.size() - 1; i >= 1; --i) { + MathInset * inset = cursor_[i].inset()->asMathInset(); + if (inset && inset->asHullInset()) + return static_cast(inset); + } return 0; } @@ -1262,17 +1297,15 @@ MathGridInset * LCursor::enclosingGrid(idx_type & idx) const void LCursor::pullArg() { -#warning look here -#if 0 +#warning Look here MathArray ar = cell(); - if (popLeft()) { + if (popLeft() && inMathed()) { plainErase(); cell().insert(pos(), ar); resetAnchor(); } else { - formula()->mutateToText(); + //formula()->mutateToText(); } -#endif } @@ -1295,7 +1328,7 @@ void LCursor::normalize() << idx() << ' ' << nargs() << " in: " << inset() << endl; } - idx() = min(idx(), nargs() - 1); + idx() = min(idx(), lastidx()); if (pos() > lastpos()) { lyxerr << "this should not really happen - 2: " @@ -1327,16 +1360,17 @@ char LCursor::halign() bool LCursor::goUpDown(bool up) { - // Be warned: The 'logic' implemented in this function is highly fragile. - // A distance of one pixel or a '<' vs '<=' _really_ matters. - // So fiddle around with it only if you know what you are doing! + // Be warned: The 'logic' implemented in this function is highly + // fragile. A distance of one pixel or a '<' vs '<=' _really + // matters. So fiddle around with it only if you think you know + // what you are doing! int xo = 0; int yo = 0; - getScreenPos(xo, yo); + getPos(xo, yo); // check if we had something else in mind, if not, this is the future goal if (x_target() == -1) - x_target(xo); + x_target() = xo; else xo = x_target(); @@ -1407,7 +1441,7 @@ bool LCursor::goUpDown(bool up) // any improvement so far? int xnew, ynew; - getScreenPos(xnew, ynew); + getPos(xnew, ynew); if (up ? ynew < yo : ynew > yo) return true; } @@ -1425,7 +1459,8 @@ bool LCursor::bruteFind(int x, int y, int xlow, int xhigh, int ylow, int yhigh) // avoid invalid nesting when selecting if (!selection() || positionable(it, anchor_)) { int xo, yo; - it.back().getScreenPos(xo, yo); + CursorSlice & cur = it.back(); + cur.inset()->getCursorPos(cur, xo, yo); if (xlow <= xo && xo <= xhigh && ylow <= yo && yo <= yhigh) { double d = (x - xo) * (x - xo) + (y - yo) * (y - yo); //lyxerr << "x: " << x << " y: " << y << " d: " << endl; @@ -1454,13 +1489,13 @@ void LCursor::bruteFind2(int x, int y) double best_dist = 1e10; CursorBase it = cursor_; - it.back().pos(0); + it.back().pos() = 0; CursorBase et = cursor_; - int n = et.back().asMathInset()->cell(et.back().idx_).size(); - et.back().pos(n); + et.back().pos() = et.back().asMathInset()->cell(et.back().idx_).size(); for (int i = 0; ; ++i) { int xo, yo; - it.back().getScreenPos(xo, yo); + CursorSlice & cur = it.back(); + cur.inset()->getCursorPos(cur, xo, yo); double d = (x - xo) * (x - xo) + (y - yo) * (y - yo); // '<=' in order to take the last possible position // this is important for clicking behind \sum in e.g. '\sum_i a' @@ -1500,6 +1535,7 @@ bool LCursor::idxRight() bool LCursor::script(bool up) { // Hack to get \\^ and \\_ working + lyxerr << "handling script: up: " << up << endl; if (inMacroMode() && macroName() == "\\") { if (up) niceInsert(createMathInset("mathcircumflex")); @@ -1516,23 +1552,22 @@ bool LCursor::script(bool up) idx() = up; pos() = 0; } else if (pos() != 0 && prevAtom()->asScriptInset()) { - prevAtom().nucleus()->asScriptInset()->ensure(up); - posLeft(); - push(inset()); + --pos(); + nextAtom().nucleus()->asScriptInset()->ensure(up); + push(nextInset()); idx() = up; pos() = lastpos(); } else if (pos() != 0) { --pos(); - cell()[pos()] - = MathAtom(new MathScriptInset(nextAtom(), up)); - push(inset()); + cell()[pos()] = MathAtom(new MathScriptInset(nextAtom(), up)); + push(nextInset()); idx() = up; pos() = 0; } else { plainInsert(MathAtom(new MathScriptInset(up))); - posLeft(); + --pos(); nextAtom().nucleus()->asScriptInset()->ensure(up); - push(inset()); + push(nextInset()); idx() = up; pos() = 0; } @@ -1544,7 +1579,7 @@ bool LCursor::script(bool up) bool LCursor::interpret(char c) { //lyxerr << "interpret 2: '" << c << "'" << endl; - x_target(-1); // "no target" + clearTargetX(); if (inMacroArgMode()) { posLeft(); plainErase(); @@ -1688,7 +1723,7 @@ void LCursor::lockToggle() } else if (popLeft() && pos() != lastpos()) { // ... or enclosing inset if we are in the last inset position nextAtom().nucleus()->lock(!nextAtom()->lock()); - posRight(); + ++pos(); } } @@ -1701,7 +1736,7 @@ CursorSlice LCursor::normalAnchor() } //lyx::BOOST_ASSERT(Anchor_.size() >= cursor.depth()); // use Anchor on the same level as Cursor - CursorSlice normal = anchor_[depth() - 1]; + CursorSlice normal = anchor_[current_]; #if 0 if (depth() < anchor_.size() && !(normal < xx())) { // anchor is behind cursor -> move anchor behind the inset @@ -1718,35 +1753,35 @@ DispatchResult dispatch(LCursor & cur, FuncRequest const & cmd) // mouse clicks are somewhat special // check switch (cmd.action) { - case LFUN_MOUSE_PRESS: - case LFUN_MOUSE_MOTION: - case LFUN_MOUSE_RELEASE: - case LFUN_MOUSE_DOUBLE: { - CursorSlice & pos = cursor_.back(); - int x = 0; - int y = 0; - getScreenPos(x, y); - if (x < cmd.x && pos() != 0) { - DispatchResult const res = prevAtom().nucleus()->dispatch(cmd); - if (res.dispatched()) - return res; - } - if (x > cmd.x && pos() != lastpos()) { - DispatchResult const res = inset()->dispatch(cmd); - if (res.dispatched()) - return res; - } + case LFUN_MOUSE_PRESS: + case LFUN_MOUSE_MOTION: + case LFUN_MOUSE_RELEASE: + case LFUN_MOUSE_DOUBLE: { + CursorSlice & pos = cursor_.back(); + int x = 0; + int y = 0; + getPos(x, y); + if (x < cmd.x && pos() != 0) { + DispatchResult const res = prevAtom().nucleus()->dispatch(cmd); + if (res.dispatched()) + return res; } - default: - break; + if (x > cmd.x && pos() != lastpos()) { + DispatchResult const res = inset()->dispatch(cmd); + if (res.dispatched()) + return res; + } + } + default: + break; } - /... } */ void LCursor::handleFont(string const & font) { + lyxerr << "LCursor::handleFont: " << font << endl; string safe; if (selection()) { macroModeClose(); @@ -1779,14 +1814,148 @@ void LCursor::handleFont(string const & font) } -void LCursor::releaseMathCursor() +bool LCursor::inMathed() const { - if (inMathed()) - formula()->insetUnlock(bv()); + return formula(); } -bool LCursor::inMathed() const +bool LCursor::inTexted() const { - return formula(); + return !formula(); +} + + +InsetBase * LCursor::nextInset() +{ + if (pos() == lastpos()) + return 0; + if (inMathed()) + return nextAtom().nucleus(); + return paragraph().isInset(pos()) ? paragraph().getInset(pos()) : 0; +} + + +InsetBase * LCursor::prevInset() +{ + if (pos() == 0) + return 0; + if (inMathed()) + return prevAtom().nucleus(); + return paragraph().isInset(pos() - 1) ? paragraph().getInset(pos() - 1) : 0; +} + + +InsetBase const * LCursor::prevInset() const +{ + if (pos() == 0) + return 0; + if (inMathed()) + return prevAtom().nucleus(); + return paragraph().isInset(pos() - 1) ? paragraph().getInset(pos() - 1) : 0; +} + + +void LCursor::message(string const & msg) const +{ + bv().owner()->getLyXFunc().setMessage(msg); +} + + +void LCursor::errorMessage(string const & msg) const +{ + bv().owner()->getLyXFunc().setErrorMessage(msg); +} + + +string LCursor::selectionAsString(bool label) const +{ + if (!selection()) + return string(); + + if (inTexted()) { + Buffer const & buffer = *bv().buffer(); + + // should be const ... + ParagraphList::iterator startpit = text()->getPar(selBegin()); + ParagraphList::iterator endpit = text()->getPar(selEnd()); + size_t const startpos = selBegin().pos(); + size_t const endpos = selEnd().pos(); + + if (startpit == endpit) + return startpit->asString(buffer, startpos, endpos, label); + + // First paragraph in selection + string result = + startpit->asString(buffer, startpos, startpit->size(), label) + "\n\n"; + + // The paragraphs in between (if any) + ParagraphList::iterator pit = startpit; + for (++pit; pit != endpit; ++pit) + result += pit->asString(buffer, 0, pit->size(), label) + "\n\n"; + + // Last paragraph in selection + result += endpit->asString(buffer, 0, endpos, label); + + return result; + } + +#warning an mathed? + return string(); +} + + +string LCursor::currentState() +{ + if (inMathed()) { + std::ostringstream os; + info(os); + return os.str(); + } + return text() ? text()->currentState(*this) : string(); +} + + +// only used by the spellchecker +void LCursor::replaceWord(string const & replacestring) +{ + LyXText * t = text(); + BOOST_ASSERT(t); + + t->replaceSelectionWithString(*this, replacestring); + t->setSelectionRange(*this, replacestring.length()); + + // Go back so that replacement string is also spellchecked + for (string::size_type i = 0; i < replacestring.length() + 1; ++i) + t->cursorLeft(*this, true); +} + + +void LCursor::update() +{ + bv().update(); +} + + +string LCursor::getPossibleLabel() +{ + return inMathed() ? "eq:" : text()->getPossibleLabel(*this); +} + + +void LCursor::notdispatched() +{ + disp_.dispatched(false); +} + + +void LCursor::dispatched(dispatch_result_t res) +{ + disp_.val(res); +} + + +void LCursor::noupdate() +{ + disp_.update(false); }