From 880b6c4d6ebd6f8e36b340a3efa3cb13108cc478 Mon Sep 17 00:00:00 2001 From: Stefan Schimanski Date: Tue, 29 May 2007 20:53:32 +0000 Subject: [PATCH] 1. switch LFUN_UP/DOWN handling to a structural approach, i.e. the dispatchers in mathed and text only do local work, i.e. only try to move the cursor with their local knowledge, not globally as before in the Cursor::goUpDown function before. The old approach used one of brutefind functions as a last way out to really move the cursor up or down. The result was some strange behavior that the nearest inset was selected when jumping from math to text, not one in the next line. 2. removed LFUN_FINISHED_UP/DOWN, as there seem to be no effect and it seems to be obsolete. 3. target_x is working again, mainly by adding a textTargetOffset_ member to the Cursor which keeps the difference between the target_x and the actual position of the cursor on screen. As long as pos+offset=target is fulfilled the target_x is not touched and the cursor keep the column while going up/down. 4. moved the text cursor up/down code to the Cursor class, in analogy to the mathed code. 5. For 1 it is necessary to know the cursor position before the dispatch. So this data is added to the Cursor. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@18569 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/Cursor.cpp | 286 +++++++++++++++++++++++++++-------- src/Cursor.h | 43 ++++-- src/LyXAction.cpp | 2 - src/Text.h | 12 -- src/Text2.cpp | 261 ++++++++++---------------------- src/Text3.cpp | 34 +---- src/insets/Inset.h | 8 +- src/insets/InsetTabular.cpp | 2 +- src/insets/InsetText.h | 2 + src/lfuns.h | 20 ++- src/mathed/InsetMathHull.cpp | 6 +- src/mathed/InsetMathNest.cpp | 17 +-- 12 files changed, 357 insertions(+), 336 deletions(-) diff --git a/src/Cursor.cpp b/src/Cursor.cpp index 123de2cd2d..b3bdadeb6c 100644 --- a/src/Cursor.cpp +++ b/src/Cursor.cpp @@ -6,12 +6,14 @@ * \author Alejandro Aguilar Sierra * \author Alfredo Braunstein * \author André Pönitz + * \author Stefan Schimanski * * Full author contact details are available in file CREDITS. */ #include +#include "Bidi.h" #include "BufferView.h" #include "bufferview_funcs.h" #include "Buffer.h" @@ -262,7 +264,7 @@ namespace { // be careful: this is called from the bv's constructor, too, so // bv functions are not yet available! Cursor::Cursor(BufferView & bv) - : DocIterator(), bv_(&bv), anchor_(), x_target_(-1), + : DocIterator(), bv_(&bv), anchor_(), x_target_(-1), textTargetOffset_(0), selection_(false), mark_(false), logicalpos_(false) {} @@ -296,7 +298,11 @@ void Cursor::dispatch(FuncRequest const & cmd0) fixIfBroken(); FuncRequest cmd = cmd0; Cursor safe = *this; - + + // store some values to be used inside of the handlers + getPos(beforeDispX_, beforeDispY_); + beforeDispDepth_ = depth(); + for (; depth(); pop()) { LYXERR(Debug::DEBUG) << "Cursor::dispatch: cmd: " << cmd0 << endl << *this << endl; @@ -526,9 +532,10 @@ void Cursor::clearSelection() } -int & Cursor::x_target() +void Cursor::setTargetX(int x) { - return x_target_; + x_target_ = x; + textTargetOffset_ = 0; } @@ -541,9 +548,18 @@ int Cursor::x_target() const void Cursor::clearTargetX() { x_target_ = -1; + textTargetOffset_ = 0; } +void Cursor::updateTextTargetOffset() +{ + int x; + int y; + getPos(x, y); + textTargetOffset_ = x - x_target_; +} + void Cursor::info(odocstream & os) const { @@ -662,7 +678,7 @@ bool Cursor::openable(MathAtom const & t) const void Cursor::setScreenPos(int x, int y) { - x_target() = x; + setTargetX(x); bruteFind(*this, x, y, 0, bv().workWidth(), 0, bv().workHeight()); } @@ -876,11 +892,13 @@ bool Cursor::up() { macroModeClose(); DocIterator save = *this; - if (goUpDown(true)) + FuncRequest cmd(selection() ? LFUN_UP_SELECT : LFUN_UP, docstring()); + this->dispatch(cmd); + if (disp_.dispatched()) return true; setCursor(save); autocorrect() = false; - return selection(); + return false; } @@ -888,11 +906,13 @@ bool Cursor::down() { macroModeClose(); DocIterator save = *this; - if (goUpDown(false)) + FuncRequest cmd(selection() ? LFUN_DOWN_SELECT : LFUN_DOWN, docstring()); + this->dispatch(cmd); + if (disp_.dispatched()) return true; setCursor(save); autocorrect() = false; - return selection(); + return false; } @@ -951,17 +971,25 @@ int Cursor::targetX() const } +int Cursor::textTargetOffset() const +{ + return textTargetOffset_; +} + + void Cursor::setTargetX() { int x; int y; getPos(x, y); - x_target_ = x; + setTargetX(x); } bool Cursor::inMacroMode() const { + if (!inMathed()) + return false; if (pos() == 0) return false; InsetMathUnknown const * p = prevAtom()->asUnknownInset(); @@ -1027,26 +1055,52 @@ void Cursor::normalize() } -bool Cursor::goUpDown(bool up) +bool Cursor::upDownInMath(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 think you know // what you are doing! - int xo = 0; int yo = 0; getPos(xo, yo); + xo = beforeDispX_; // check if we had something else in mind, if not, this is the future // target - if (x_target() == -1) - x_target() = xo; - else - xo = x_target(); + if (x_target_ == -1) + setTargetX(xo); + else if (inset().asTextInset() && xo - textTargetOffset() != x_target()) { + // In text mode inside the line (not left or right) possibly set a new target_x, + // but only if we are somewhere else than the previous target-offset. + + // We want to keep the x-target on subsequent up/down movements + // that cross beyond the end of short lines. Thus a special + // handling when the cursor is at the end of line: Use the new + // x-target only if the old one was before the end of line + // or the old one was after the beginning of the line + bool inRTL = isWithinRtlParagraph(*this); + bool left; + bool right; + if (inRTL) { + left = pos() == textRow().endpos(); + right = pos() == textRow().pos(); + } else { + left = pos() == textRow().pos(); + right = pos() == textRow().endpos(); + } + if ((!left && !right) || + (left && !right && xo < x_target_) || + (!left && right && x_target_ < xo)) + setTargetX(xo); + else + xo = targetX(); + } else + xo = targetX(); // try neigbouring script insets - if (!selection()) { + Cursor old = *this; + if (inMathed() && !selection()) { // try left if (pos() != 0) { InsetMathScript const * p = prevAtom()->asScriptInset(); @@ -1055,10 +1109,19 @@ bool Cursor::goUpDown(bool up) push(*const_cast(p)); idx() = p->idxOfScript(up); pos() = lastpos(); - return true; + + // we went in the right direction? Otherwise don't jump into the script + int x; + int y; + getPos(x, y); + if ((!up && y <= beforeDispY_) || + (up && y >= beforeDispY_)) + operator=(old); + else + return true; } } - + // try right if (pos() != lastpos()) { InsetMathScript const * p = nextAtom()->asScriptInset(); @@ -1066,62 +1129,159 @@ bool Cursor::goUpDown(bool up) push(*const_cast(p)); idx() = p->idxOfScript(up); pos() = 0; - return true; + + // we went in the right direction? Otherwise don't jump into the script + int x; + int y; + getPos(x, y); + if ((!up && y <= beforeDispY_) || + (up && y >= beforeDispY_)) + operator=(old); + else + return true; } } } - -// FIXME: Switch this on for more robust movement -#if 0 - - return bruteFind3(*this, xo, yo, up); - -#else - //xarray().boundingBox(xlow, xhigh, ylow, yhigh); - //if (up) - // yhigh = yo - 4; - //else - // ylow = yo + 4; - //if (bruteFind(*this, xo, yo, xlow, xhigh, ylow, yhigh)) { - // lyxerr << "updown: handled by brute find in the same cell" << endl; - // return true; - //} - - // try to find an inset that knows better then we - while (true) { - //lyxerr << "updown: We are in " << &inset() << " idx: " << idx() << endl; - // ask inset first - if (inset().idxUpDown(*this, up)) { - //lyxerr << "idxUpDown triggered" << endl; - // try to find best position within this inset - if (!selection()) - setCursor(bruteFind2(*this, xo, yo)); - return true; - } - - // no such inset found, just take something "above" - if (!popLeft()) { - //lyxerr << "updown: popleft failed (strange case)" << endl; - int ylow = up ? 0 : yo + 1; - int yhigh = up ? yo - 1 : bv().workHeight(); - return bruteFind(*this, xo, yo, 0, bv().workWidth(), ylow, yhigh); - } - - // any improvement so far? + + // try to find an inset that knows better then we, + if (inset().idxUpDown(*this, up)) { + //lyxerr << "idxUpDown triggered" << endl; + // try to find best position within this inset + if (!selection()) + setCursor(bruteFind2(*this, xo, yo)); + return true; + } + + // any improvement going just out of inset? + if (popLeft() && inMathed()) { //lyxerr << "updown: popLeft succeeded" << endl; int xnew; int ynew; getPos(xnew, ynew); - if (up ? ynew < yo : ynew > yo) + if (up ? ynew < beforeDispY_ : ynew > beforeDispY_) return true; } - - // we should not come here. - BOOST_ASSERT(false); -#endif + + // no success, we are probably at the document top or bottom + operator=(old); + return false; } +bool Cursor::upDownInText(bool up) +{ + BOOST_ASSERT(text()); + + // where are we? + int xo = 0; + int yo = 0; + getPos(xo, yo); + xo = beforeDispX_; + + // update the targetX - this is here before the "return false" + // to set a new target which can be used by InsetTexts above + // if we cannot move up/down inside this inset anymore + if (x_target_ == -1) + setTargetX(xo); + else if (xo - textTargetOffset() != x_target() && depth() == beforeDispDepth_) { + // In text mode inside the line (not left or right) possibly set a new target_x, + // but only if we are somewhere else than the previous target-offset. + + // We want to keep the x-target on subsequent up/down movements + // that cross beyond the end of short lines. Thus a special + // handling when the cursor is at the end of line: Use the new + // x-target only if the old one was before the end of line + // or the old one was after the beginning of the line + bool inRTL = isWithinRtlParagraph(*this); + bool left; + bool right; + if (inRTL) { + left = pos() == textRow().endpos(); + right = pos() == textRow().pos(); + } else { + left = pos() == textRow().pos(); + right = pos() == textRow().endpos(); + } + if ((!left && !right) || + (left && !right && xo < x_target_) || + (!left && right && x_target_ < xo)) + setTargetX(xo); + else + xo = targetX(); + } else + xo = targetX(); + + // first get the current line + TextMetrics const & tm = bv_->textMetrics(text()); + ParagraphMetrics const & pm = tm.parMetrics(pit()); + int row; + if (pos() && boundary()) + row = pm.pos2row(pos() - 1); + else + row = pm.pos2row(pos()); + + // are we not at the start or end? + if (up) { + if (pit() == 0 && row == 0) + return false; + } else { + if (pit() + 1 >= int(text()->paragraphs().size()) && + row + 1 >= int(pm.rows().size())) + return false; + } + + // with and without selection are handled differently + if (!selection()) { + int yo = bv_funcs::getPos(bv(), *this, boundary()).y_; + Cursor old = *this; + // To next/previous row + if (up) + text()->editXY(*this, xo, yo - textRow().ascent() - 1); + else + text()->editXY(*this, xo, yo + textRow().descent() + 1); + clearSelection(); + + // This happens when you move out of an inset. + // And to give the DEPM the possibility of doing + // something we must provide it with two different + // cursors. (Lgb) + Cursor dummy = *this; + if (dummy == old) + ++dummy.pos(); + + bool const changed = bv().checkDepm(dummy, old); + + // Make sure that cur gets back whatever happened to dummy(Lgb) + if (changed) + operator=(dummy); + } else { + // if there is a selection, we stay out of any inset, and just jump to the right position: + Cursor old = *this; + if (up) { + if (row > 0) { + top().pos() = std::min(tm.x2pos(pit(), row - 1, xo), top().lastpos()); + } else if (pit() > 0) { + --pit(); + ParagraphMetrics const & pmcur = bv_->parMetrics(text(), pit()); + top().pos() = std::min(tm.x2pos(pit(), pmcur.rows().size() - 1, xo), top().lastpos()); + } + } else { + if (row + 1 < int(pm.rows().size())) { + top().pos() = std::min(tm.x2pos(pit(), row + 1, xo), top().lastpos()); + } else if (pit() + 1 < int(text()->paragraphs().size())) { + ++pit(); + top().pos() = std::min(tm.x2pos(pit(), 0, xo), top().lastpos()); + } + } + + bv().checkDepm(*this, old); + } + + updateTextTargetOffset(); + return true; +} + + void Cursor::handleFont(string const & font) { LYXERR(Debug::DEBUG) << BOOST_CURRENT_FUNCTION << ": " << font << endl; diff --git a/src/Cursor.h b/src/Cursor.h index 87c701c51d..c33478d523 100644 --- a/src/Cursor.h +++ b/src/Cursor.h @@ -121,16 +121,21 @@ public: /// insert a string void insert(docstring const & str); - /// in pixels from left of screen + /// FIXME: rename to something sensible showing difference to x_target() + /// in pixels from left of screen, set to current position if unset int targetX() const; - /// write acess to target x position of cursor - int & x_target(); - /// return target x position of cursor + /// set the targetX to x + void setTargetX(int x); + /// return targetX or -1 if unset int x_target() const; - /// set targetX in current position + /// set targetX to current position void setTargetX(); - /// clear target x position of cursor + /// clear targetX, i.e. set it to -1 void clearTargetX(); + /// set offset to actual position - targetX + void updateTextTargetOffset(); + /// distance between actual and targeted position during last up/down in text + int textTargetOffset() const; /// access to normalized selection anchor CursorSlice anchor() const; @@ -186,11 +191,10 @@ public: //private: /// the anchor position DocIterator anchor_; - + /// DispatchResult disp_; - - + private: /** * The target x position of the cursor. This is used for when @@ -205,6 +209,8 @@ private: * shorter than x() */ int x_target_; + /// if a x_target cannot be hit exactly in a text, put the difference here + int textTargetOffset_; /// do we have a selection? bool selection_; /// are we on the way to get one? @@ -214,7 +220,13 @@ private: // of a big inset spanning a whole row and computing coordinates for // displaying the cursor. bool logicalpos_; - + /// x position before dispatch started + int beforeDispX_; + /// y position before dispatch started + int beforeDispY_; + /// position before dispatch started + size_t beforeDispDepth_; + private: // @@ -243,10 +255,14 @@ public: bool erase(); /// return false for empty math insets bool backspace(); - /// called for LFUN_UP etc + /// move the cursor up by sending an internal LFUN_UP bool up(); - /// called for LFUN_DOWN etc + /// move the cursor up by sending an internal LFUN_DOWN bool down(); + /// move up/down in a text inset, called for LFUN_UP/DOWN + bool upDownInText(bool up); + /// move up/down in math or any non text inset, call for LFUN_UP/DOWN + bool upDownInMath(bool up); /// void plainErase(); /// @@ -294,9 +310,6 @@ public: /// docstring getPossibleLabel(); - /// moves position somehow up or down - bool goUpDown(bool up); - /// the name of the macro we are currently inputting docstring macroName(); /// where in the curent cell does the macro name start? diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp index f1a5a52d51..fdae8d0ed7 100644 --- a/src/LyXAction.cpp +++ b/src/LyXAction.cpp @@ -354,8 +354,6 @@ void LyXAction::init() { LFUN_WORDS_COUNT, "words-count", ReadOnly }, { LFUN_FINISHED_RIGHT, "", ReadOnly }, { LFUN_FINISHED_LEFT, "", ReadOnly }, - { LFUN_FINISHED_UP, "", ReadOnly }, - { LFUN_FINISHED_DOWN, "", ReadOnly }, { LFUN_MOUSE_PRESS, "", ReadOnly }, { LFUN_MOUSE_MOTION, "", ReadOnly | SingleParUpdate }, { LFUN_MOUSE_RELEASE, "", ReadOnly }, diff --git a/src/Text.h b/src/Text.h index 5e078964ba..e88ef85fcb 100644 --- a/src/Text.h +++ b/src/Text.h @@ -208,18 +208,6 @@ public: /// setCursorFromCoordinates() instead of checkInsetHit(). Inset * editXY(Cursor & cur, int x, int y); - /// Move cursor one line up. - /** - * Returns true if an update is needed after the move. - */ - /// FIXME: move to TextMetrics. - bool cursorUp(Cursor & cur); - /// Move cursor one line down. - /** - * Returns true if an update is needed after the move. - */ - /// FIXME: move to TextMetrics. - bool cursorDown(Cursor & cur); /// Move cursor one position left /** * Returns true if an update is needed after the move. diff --git a/src/Text2.cpp b/src/Text2.cpp index 6bc12fc156..27b70aabb0 100644 --- a/src/Text2.cpp +++ b/src/Text2.cpp @@ -760,12 +760,21 @@ void Text::setCurrentFont(Cursor & cur) pos_type pos = cur.pos(); Paragraph & par = cur.paragraph(); - if (cur.boundary() && pos > 0 && pos < cur.lastpos()) { + // ignore empty paragraph + if (par.empty()) + return; + + // if on boundary or at paragraph end, set font of previous char + if ((pos > 0 && cur.boundary()) || pos == cur.lastpos()) --pos; - // We may have just moved to the previous row --- - // we're going to be needing its bidi tables! + + // we changed the line and the bidi tables are outdated? + if (!bidi.inRange(pos)) bidi.computeTables(par, cur.buffer(), cur.textRow()); - } + + // now in range? + if (!bidi.inRange(pos)) + return; if (pos > 0) { if (pos == cur.lastpos()) @@ -911,7 +920,7 @@ Inset * Text::editXY(Cursor & cur, int x, int y) cur.pit() = pit; cur.pos() = pos; cur.boundary(bound); - cur.x_target() = x; + cur.setTargetX(x); // try to descend into nested insets Inset * inset = checkInsetHit(cur.bv(), x, y); @@ -933,8 +942,10 @@ Inset * Text::editXY(Cursor & cur, int x, int y) // Make sure the cursor points to the position before // this inset. - if (inset == insetBefore) + if (inset == insetBefore) { --cur.pos(); + cur.boundary(false); + } // Try to descend recursively inside the inset. inset = inset->editXY(cur, x, y); @@ -975,38 +986,38 @@ bool Text::cursorLeft(Cursor & cur) // Tell BufferView to test for FitCursor in any case! cur.updateFlags(Update::FitCursor); + // not at paragraph start? if (cur.pos() > 0) { - if (cur.boundary()) - return setCursor(cur, cur.pit(), cur.pos(), true, false); - - bool updateNeeded = false; - // If checkAndActivateInset returns true, that means that - // the cursor was placed inside it, so we're done - if (!checkAndActivateInset(cur, false)) { - if (!cur.boundary() && - cur.textRow().pos() == cur.pos() - // FIXME: the following two conditions are copied - // from cursorRight; however, isLineSeparator() - // is definitely wrong here, isNewline I'm not sure - // about. I'm leaving them as comments for now, - // until we understand why they should or shouldn't - // be here. - /*&& - !cur.paragraph().isLineSeparator(cur.pos()-1) && - !cur.paragraph().isNewline(cur.pos() - 1)*/) { - updateNeeded |= setCursor(cur, cur.pit(), cur.pos(), - true, true); - } - updateNeeded |= setCursor(cur, cur.pit(),cur.pos() - 1, - true, false); + // if on right side of boundary (i.e. not at paragraph end, but line end) + // -> skip it, i.e. set boundary to true, i.e. go only logically left + // there are some exceptions to ignore this: lineseps, newlines, spaces +#ifdef DEBUG + bool bound = cur.boundary(); + int rowpos = cur.textRow().pos(); + int pos = cur.pos(); + bool sep = cur.paragraph().isSeparator(cur.pos() - 1); + bool newline = cur.paragraph().isNewline(cur.pos() - 1); + bool linesep = cur.paragraph().isLineSeparator(cur.pos() - 1); +#endif + if (!cur.boundary() && + cur.textRow().pos() == cur.pos() && + !cur.paragraph().isLineSeparator(cur.pos() - 1) && + !cur.paragraph().isNewline(cur.pos() - 1) && + !cur.paragraph().isSeparator(cur.pos() - 1)) { + return setCursor(cur, cur.pit(), cur.pos(), true, true); } - return updateNeeded; + + // go left and try to enter inset + if (checkAndActivateInset(cur, false)) + return false; + + // normal character left + return setCursor(cur, cur.pit(), cur.pos() - 1, true, false); } - if (cur.pit() > 0) { - // Steps into the paragraph above + // move to the previous paragraph or do nothing + if (cur.pit() > 0) return setCursor(cur, cur.pit() - 1, getPar(cur.pit() - 1).size()); - } return false; } @@ -1016,168 +1027,50 @@ bool Text::cursorRight(Cursor & cur) // Tell BufferView to test for FitCursor in any case! cur.updateFlags(Update::FitCursor); + // not at paragraph end? if (cur.pos() != cur.lastpos()) { + // if left of boundary -> just jump to right side if (cur.boundary()) - return setCursor(cur, cur.pit(), cur.pos(), - true, false); - - bool updateNeeded = false; - // If checkAndActivateInset returns true, that means that - // the cursor was placed inside it, so we're done - if (!checkAndActivateInset(cur, true)) { - if (cur.textRow().endpos() == cur.pos() + 1 && - cur.textRow().endpos() != cur.lastpos() && - !cur.paragraph().isLineSeparator(cur.pos()) && - !cur.paragraph().isNewline(cur.pos())) { - cur.boundary(true); - } - updateNeeded |= setCursor(cur, cur.pit(), cur.pos() + 1, true, cur.boundary()); + return setCursor(cur, cur.pit(), cur.pos(), true, false); + + // in front of editable inset, i.e. jump into it? + if (checkAndActivateInset(cur, true)) + return false; + + // next position is left of boundary, + // but go to next line for special cases like space, newline, linesep +#ifdef DEBUG + int endpos = cur.textRow().endpos(); + int lastpos = cur.lastpos(); + int pos = cur.pos(); + bool linesep = cur.paragraph().isLineSeparator(cur.pos()); + bool newline = cur.paragraph().isNewline(cur.pos()); + bool sep = cur.paragraph().isSeparator(cur.pos()); + if (cur.pos() != cur.lastpos()) { + bool linesep2 = cur.paragraph().isLineSeparator(cur.pos()+1); + bool newline2 = cur.paragraph().isNewline(cur.pos()+1); + bool sep2 = cur.paragraph().isSeparator(cur.pos()+1); + } +#endif + if (cur.textRow().endpos() == cur.pos() + 1 && + cur.textRow().endpos() != cur.lastpos() && + !cur.paragraph().isNewline(cur.pos()) && + !cur.paragraph().isLineSeparator(cur.pos()) && + !cur.paragraph().isSeparator(cur.pos())) { + return setCursor(cur, cur.pit(), cur.pos() + 1, true, true); } - return updateNeeded; + + // move right + return setCursor(cur, cur.pit(), cur.pos() + 1, true, false); } + // move to next paragraph if (cur.pit() != cur.lastpit()) return setCursor(cur, cur.pit() + 1, 0); return false; } -bool Text::cursorUp(Cursor & cur) -{ - // Tell BufferView to test for FitCursor in any case! - cur.updateFlags(Update::FitCursor); - - TextMetrics const & tm = cur.bv().textMetrics(this); - ParagraphMetrics const & pm = tm.parMetrics(cur.pit()); - - int row; - if (cur.pos() && cur.boundary()) - row = pm.pos2row(cur.pos()-1); - else - row = pm.pos2row(cur.pos()); - - int x = cur.targetX(); - cur.setTargetX(); - // We want to keep the x-target on subsequent up movements - // that cross beyond the end of short lines. Thus a special - // handling when the cursor is at the end of line: Use the new - // x-target only if the old one was before the end of line. - if (cur.pos() != pm.rows()[row].endpos() - || (!isWithinRtlParagraph(cur) && x < cur.targetX()) - || (isWithinRtlParagraph(cur) && x > cur.targetX())) { - - x = cur.targetX(); - } - - if (!cur.selection()) { - int const y = bv_funcs::getPos(cur.bv(), cur, cur.boundary()).y_; - Cursor old = cur; - // Go to middle of previous row. 16 found to work OK; - // 12 = top/bottom margin of display math - int const margin = 3 * InsetMathHull::displayMargin() / 2; - editXY(cur, x, y - pm.rows()[row].ascent() - margin); - cur.clearSelection(); - - // This happens when you move out of an inset. - // And to give the DEPM the possibility of doing - // something we must provide it with two different - // cursors. (Lgb) - Cursor dummy = cur; - if (dummy == old) - ++dummy.pos(); - - cur.bv().checkDepm(dummy, old); - return false; - } - - bool updateNeeded = false; - - if (row > 0) { - updateNeeded |= setCursor(cur, cur.pit(), - tm.x2pos(cur.pit(), row - 1, x)); - } else if (cur.pit() > 0) { - --cur.pit(); - //cannot use 'par' now - ParagraphMetrics const & pmcur = cur.bv().parMetrics(this, cur.pit()); - updateNeeded |= setCursor(cur, cur.pit(), - tm.x2pos(cur.pit(), pmcur.rows().size() - 1, x)); - } - - cur.x_target() = x; - - return updateNeeded; -} - - -bool Text::cursorDown(Cursor & cur) -{ - // Tell BufferView to test for FitCursor in any case! - cur.updateFlags(Update::FitCursor); - - TextMetrics const & tm = cur.bv().textMetrics(this); - ParagraphMetrics const & pm = tm.parMetrics(cur.pit()); - - int row; - if (cur.pos() && cur.boundary()) - row = pm.pos2row(cur.pos()-1); - else - row = pm.pos2row(cur.pos()); - - int x = cur.targetX(); - cur.setTargetX(); - // We want to keep the x-target on subsequent down movements - // that cross beyond the end of short lines. Thus a special - // handling when the cursor is at the end of line: Use the new - // x-target only if the old one was before the end of line. - if (cur.pos() != pm.rows()[row].endpos() - || (!isWithinRtlParagraph(cur) && x < cur.targetX()) - || (isWithinRtlParagraph(cur) && x > cur.targetX())) { - - x = cur.targetX(); - } - - if (!cur.selection()) { - int const y = bv_funcs::getPos(cur.bv(), cur, cur.boundary()).y_; - Cursor old = cur; - // To middle of next row - int const margin = 3 * InsetMathHull::displayMargin() / 2; - editXY(cur, x, y + pm.rows()[row].descent() + margin); - cur.clearSelection(); - - // This happens when you move out of an inset. - // And to give the DEPM the possibility of doing - // something we must provide it with two different - // cursors. (Lgb) - Cursor dummy = cur; - if (dummy == old) - ++dummy.pos(); - - bool const changed = cur.bv().checkDepm(dummy, old); - - // Make sure that cur gets back whatever happened to dummy(Lgb) - if (changed) - cur = dummy; - - return false; - } - - bool updateNeeded = false; - - if (row + 1 < int(pm.rows().size())) { - updateNeeded |= setCursor(cur, cur.pit(), - tm.x2pos(cur.pit(), row + 1, x)); - } else if (cur.pit() + 1 < int(paragraphs().size())) { - ++cur.pit(); - updateNeeded |= setCursor(cur, cur.pit(), - tm.x2pos(cur.pit(), 0, x)); - } - - cur.x_target() = x; - - return updateNeeded; -} - - bool Text::cursorUpParagraph(Cursor & cur) { bool updated = false; diff --git a/src/Text3.cpp b/src/Text3.cpp index 3ebb1db41b..968b893a01 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -470,14 +470,11 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_UP_SELECT: //lyxerr << "handle LFUN_UP[SEL]:\n" << cur << endl; needsUpdate |= cur.selHandle(cmd.action == LFUN_UP_SELECT); - - needsUpdate |= cursorUp(cur); + needsUpdate |= cur.upDownInText(true); if (!needsUpdate && oldTopSlice == cur.top() - && cur.boundary() == oldBoundary) { + && cur.boundary() == oldBoundary) cur.undispatched(); - cmd = FuncRequest(LFUN_FINISHED_UP); - } if (cur.selection()) saveSelection(cur); break; @@ -486,14 +483,11 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_DOWN_SELECT: //lyxerr << "handle LFUN_DOWN[SEL]:\n" << cur << endl; needsUpdate |= cur.selHandle(cmd.action == LFUN_DOWN_SELECT); - needsUpdate |= cursorDown(cur); + needsUpdate |= cur.upDownInText(false); if (!needsUpdate && oldTopSlice == cur.top() && cur.boundary() == oldBoundary) - { cur.undispatched(); - cmd = FuncRequest(LFUN_FINISHED_DOWN); - } if (cur.selection()) saveSelection(cur); break; @@ -517,10 +511,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_SCREEN_UP: case LFUN_SCREEN_UP_SELECT: needsUpdate |= cur.selHandle(cmd.action == LFUN_SCREEN_UP_SELECT); - if (cur.pit() == 0 && cur.textRow().pos() == 0) { + if (cur.pit() == 0 && cur.textRow().pos() == 0) cur.undispatched(); - cmd = FuncRequest(LFUN_FINISHED_UP); - } else { + else { cursorPrevious(cur); } if (cur.selection()) @@ -531,10 +524,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_SCREEN_DOWN_SELECT: needsUpdate |= cur.selHandle(cmd.action == LFUN_SCREEN_DOWN_SELECT); if (cur.pit() == cur.lastpit() - && cur.textRow().endpos() == cur.lastpos()) { + && cur.textRow().endpos() == cur.lastpos()) cur.undispatched(); - cmd = FuncRequest(LFUN_FINISHED_DOWN); - } else { + else { cursorNext(cur); } if (cur.selection()) @@ -1071,7 +1063,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) int const y = std::max(0, std::min(wh - 1, cmd.y)); setCursorFromCoordinates(cur, cmd.x, y); - cur.x_target() = cmd.x; + cur.setTargetX(cmd.x); if (cmd.y >= wh) lyx::dispatch(FuncRequest(LFUN_DOWN_SELECT)); else if (cmd.y < 0) @@ -1446,16 +1438,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) ++cur.pos(); break; - case LFUN_FINISHED_UP: - LYXERR(Debug::DEBUG) << "handle LFUN_FINISHED_UP:\n" << cur << endl; - cursorUp(cur); - break; - - case LFUN_FINISHED_DOWN: - LYXERR(Debug::DEBUG) << "handle LFUN_FINISHED_DOWN:\n" << cur << endl; - cursorDown(cur); - break; - case LFUN_LAYOUT_PARAGRAPH: { string data; params2string(cur.paragraph(), data); diff --git a/src/insets/Inset.h b/src/insets/Inset.h index a99f66c688..c77efa52e0 100644 --- a/src/insets/Inset.h +++ b/src/insets/Inset.h @@ -80,7 +80,11 @@ public: virtual InsetMath * asInsetMath() { return 0; } /// true for 'math' math inset, but not for e.g. mbox virtual bool inMathed() const { return false; } - + /// is this inset based on the TextInset class? + virtual InsetText * asTextInset() { return 0; } + /// is this inset based on the TextInset class? + virtual InsetText const * asTextInset() const { return 0; } + /// the real dispatcher void dispatch(Cursor & cur, FuncRequest & cmd); /** @@ -244,8 +248,6 @@ public: virtual bool descendable() const { return false; } /// does this contain text that can be change track marked in DVI? virtual bool canTrackChanges() const { return false; } - /// is this inset based on the TextInset class? - virtual InsetText const * asTextInset() const { return 0; } /// return true if the inset should be removed automatically virtual bool autoDelete() const; diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp index 005bf08933..53a6efd01f 100644 --- a/src/insets/InsetTabular.cpp +++ b/src/insets/InsetTabular.cpp @@ -3336,7 +3336,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) } } if (sl == cur.top()) { - cmd = FuncRequest(LFUN_FINISHED_UP); + cmd = FuncRequest(LFUN_UP); cur.undispatched(); } break; diff --git a/src/insets/InsetText.h b/src/insets/InsetText.h index 90b7c03060..232476fb2e 100644 --- a/src/insets/InsetText.h +++ b/src/insets/InsetText.h @@ -64,6 +64,8 @@ public: /// bool canTrackChanges() const { return true; } /// + InsetText * asTextInset() { return this; } + /// InsetText const * asTextInset() const { return this; } /// int latex(Buffer const &, odocstream &, OutputParams const &) const; diff --git a/src/lfuns.h b/src/lfuns.h index b5260611b4..8ac3c0a17a 100644 --- a/src/lfuns.h +++ b/src/lfuns.h @@ -327,61 +327,59 @@ enum kb_action { LFUN_FINISHED_LEFT, // 245 LFUN_FINISHED_RIGHT, - LFUN_FINISHED_UP, - LFUN_FINISHED_DOWN, LFUN_CHARSTYLE_INSERT, LFUN_WORD_FIND, - // 250 LFUN_WORD_REPLACE, LFUN_BUFFER_EXPORT_CUSTOM, + // 250 LFUN_BUFFER_PRINT, LFUN_NEXT_INSET_TOGGLE, LFUN_ALL_INSETS_TOGGLE, - // 255 LFUN_BUFFER_LANGUAGE, LFUN_TEXTCLASS_APPLY, + // 255 LFUN_TEXTCLASS_LOAD, LFUN_BUFFER_SAVE_AS_DEFAULT, LFUN_BUFFER_PARAMS_APPLY, - // 260 LFUN_LYXRC_APPLY, LFUN_GRAPHICS_EDIT, + // 260 LFUN_INSET_REFRESH, LFUN_BUFFER_NEXT, LFUN_BUFFER_PREVIOUS, - // 265 LFUN_WORDS_COUNT, LFUN_CHANGES_OUTPUT, // jspitzm 20050121 + // 265 LFUN_BIBTEX_DATABASE_ADD, LFUN_BIBTEX_DATABASE_DEL, LFUN_CITATION_INSERT, - // 270 LFUN_OUTLINE_UP, // Vermeer 20060323 LFUN_OUTLINE_DOWN, + // 270 LFUN_OUTLINE_IN, LFUN_OUTLINE_OUT, LFUN_PARAGRAPH_MOVE_DOWN, // Edwin 20060408 - // 275 LFUN_PARAGRAPH_MOVE_UP, // Edwin 20060408 LFUN_BUFFER_TOGGLE_COMPRESSION, // bpeng 20060427 + // 275 LFUN_MATH_BIGDELIM, LFUN_CLIPBOARD_PASTE, LFUN_INSET_DISSOLVE, // jspitzm 20060807 - // 280 LFUN_CHANGE_NEXT, LFUN_WINDOW_NEW, // Abdel 20061021 + // 280 LFUN_WINDOW_CLOSE, // Abdel 20061023 LFUN_UNICODE_INSERT, // Lgb 20061022 LFUN_BOOKMARK_CLEAR, // bpeng 20061031 - // 285 LFUN_TOOLBAR_TOGGLE_STATE, // bpeng 20061101 LFUN_NOMENCL_INSERT, // Ugras + // 285 LFUN_NOMENCL_PRINT, // Ugras LFUN_CLEARPAGE_INSERT, // Ugras 20061125 LFUN_CLEARDOUBLEPAGE_INSERT, // Ugras 20061125 - //290 LFUN_LISTING_INSERT, // Herbert 20011110, bpeng 20070502 LFUN_TOOLBAR_TOGGLE, // Edwin 20070521 + //290 LFUN_LASTACTION // end of the table }; diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp index 5f874f4469..38f0226bc7 100644 --- a/src/mathed/InsetMathHull.cpp +++ b/src/mathed/InsetMathHull.cpp @@ -1049,8 +1049,6 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_FINISHED_LEFT: case LFUN_FINISHED_RIGHT: - case LFUN_FINISHED_UP: - case LFUN_FINISHED_DOWN: //lyxerr << "action: " << cmd.action << endl; InsetMathGrid::doDispatch(cur, cmd); notifyCursorLeaves(cur); @@ -1188,8 +1186,8 @@ bool InsetMathHull::getStatus(Cursor & cur, FuncRequest const & cmd, switch (cmd.action) { case LFUN_FINISHED_LEFT: case LFUN_FINISHED_RIGHT: - case LFUN_FINISHED_UP: - case LFUN_FINISHED_DOWN: + case LFUN_UP: + case LFUN_DOWN: status.enabled(true); return true; case LFUN_BREAK_LINE: diff --git a/src/mathed/InsetMathNest.cpp b/src/mathed/InsetMathNest.cpp index 188fa3a525..26b6eb1d10 100644 --- a/src/mathed/InsetMathNest.cpp +++ b/src/mathed/InsetMathNest.cpp @@ -476,15 +476,6 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) cur.bv().cursor() = cur; break; - case LFUN_FINISHED_UP: - cur.bv().cursor() = cur; - break; - - case LFUN_FINISHED_DOWN: - ++cur.pos(); - cur.bv().cursor() = cur; - break; - case LFUN_CHAR_FORWARD: cur.updateFlags(Update::Decoration | Update::FitCursor); case LFUN_CHAR_FORWARD_SELECT: @@ -542,10 +533,8 @@ goto_char_backwards: break; } cur.selHandle(cmd.action == LFUN_UP_SELECT); - if (!cur.up()) { - cmd = FuncRequest(LFUN_FINISHED_UP); + if (!cur.upDownInMath(true)) cur.undispatched(); - } // fixes bug 1598. Please check! cur.normalize(); break; @@ -558,10 +547,8 @@ goto_char_backwards: break; } cur.selHandle(cmd.action == LFUN_DOWN_SELECT); - if (!cur.down()) { - cmd = FuncRequest(LFUN_FINISHED_DOWN); + if (!cur.upDownInMath(false)) cur.undispatched(); - } // fixes bug 1598. Please check! cur.normalize(); break; -- 2.39.2