]> git.lyx.org Git - features.git/commitdiff
1. switch LFUN_UP/DOWN handling to a structural approach, i.e. the
authorStefan Schimanski <sts@lyx.org>
Tue, 29 May 2007 20:53:32 +0000 (20:53 +0000)
committerStefan Schimanski <sts@lyx.org>
Tue, 29 May 2007 20:53:32 +0000 (20:53 +0000)
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

12 files changed:
src/Cursor.cpp
src/Cursor.h
src/LyXAction.cpp
src/Text.h
src/Text2.cpp
src/Text3.cpp
src/insets/Inset.h
src/insets/InsetTabular.cpp
src/insets/InsetText.h
src/lfuns.h
src/mathed/InsetMathHull.cpp
src/mathed/InsetMathNest.cpp

index 123de2cd2dc6dc3f2fd9479f5ea30a7bc8358f6f..b3bdadeb6cf3cbe65ba4500a0e550481dfa16253 100644 (file)
@@ -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 <config.h>
 
+#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<InsetMathScript*>(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<InsetMathScript*>(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;
index 87c701c51d22abb16c5543addc70ad4a51aa5872..c33478d523356f1ce029e343097223f192a9ec31 100644 (file)
@@ -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?
index f1a5a52d5180642f775c2e8d50c1a43d397c0ff7..fdae8d0ed712aec42913c7fe166ccdb7b4f8e1c3 100644 (file)
@@ -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 },
index 5e078964ba1c73dde9e5d3a337641c10ab53e8bf..e88ef85fcb23268a62998fca906ee25e1a98b7d8 100644 (file)
@@ -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.
index 6bc12fc156951b6f96672606dc3bb9af65398a51..27b70aabb0646283a283643816b6289af8bbad05 100644 (file)
@@ -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;
index 3ebb1db41b7a0631dc0b3cfca19dac0010be4867..968b893a01ed308918c98cd1ead073d88bbb9bee 100644 (file)
@@ -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);
index a99f66c68817cb01cf345202fbc209bba8808d36..c77efa52e0252784695675e5f8ccb8da9387133c 100644 (file)
@@ -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;
 
index 005bf089337268d358fb8eba97ca6874174f8a64..53a6efd01fc219f7801644e55746fce7085861f9 100644 (file)
@@ -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;
index 90b7c0306028fdc7f447bf19d9e63dd9d945858a..232476fb2e3878aea6bc43fa2542c1d0e97e90ac 100644 (file)
@@ -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;
index b5260611b4108f465cb352222fe11177aa9bc4df..8ac3c0a17aa1ea7273495c67f9a32c5e99c2d156 100644 (file)
@@ -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
 };
index 5f874f4469c2d1aa711cfda617c77783318dd385..38f0226bc77fd97799cf8bef6f9f7be1239f6e1d 100644 (file)
@@ -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:
index 188fa3a525984afad3926dd9d54ff5bf6b6b2123..26b6eb1d1011ba112cb85871f9acf5fdad536f28 100644 (file)
@@ -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;