]> git.lyx.org Git - features.git/commitdiff
* simplify notifyCursorLeaves logic: We now only call it from strategic
authorStefan Schimanski <sts@lyx.org>
Fri, 22 Feb 2008 20:45:18 +0000 (20:45 +0000)
committerStefan Schimanski <sts@lyx.org>
Fri, 22 Feb 2008 20:45:18 +0000 (20:45 +0000)
  places, i.e.
  - BufferView::setMouseCursor,
  - BufferView::mouseEventDispatch
  - LyXFunc::dispatch
  Before it was called from several dispatch handlers in the middle of the
  dispatch process. Because the cursor might get invalidated, this is
  not a good idea. We had plenty of crashes and odd behaviours because
  of this as nobody really understood those cases.

  This fixes (at least) #2069 and #4163.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23140 a592a061-630c-0410-9148-cb99ea01b6c8

16 files changed:
src/BufferView.cpp
src/Cursor.cpp
src/Cursor.h
src/LyXFunc.cpp
src/Text3.cpp
src/insets/Inset.h
src/mathed/InsetMathHull.cpp
src/mathed/InsetMathHull.h
src/mathed/InsetMathNest.cpp
src/mathed/InsetMathNest.h
src/mathed/InsetMathScript.cpp
src/mathed/InsetMathScript.h
src/mathed/MathMacro.cpp
src/mathed/MathMacro.h
src/mathed/MathMacroTemplate.cpp
src/mathed/MathMacroTemplate.h

index 540ba866dd73e54404e85a9f6baa2ad2d421020b..33e157d58438a8084f47d16b51f2e5c57cca4547 100644 (file)
@@ -1417,6 +1417,7 @@ void BufferView::mouseEventDispatch(FuncRequest const & cmd0)
        // LFUN_FILE_OPEN generated by drag-and-drop.
        FuncRequest cmd = cmd0;
 
+       Cursor old = cursor();
        Cursor cur(*this);
        cur.push(buffer_.inset());
        cur.selection() = d->cursor_.selection();
@@ -1478,13 +1479,19 @@ void BufferView::mouseEventDispatch(FuncRequest const & cmd0)
        if (!cur.result().dispatched())
                cur.dispatch(cmd);
 
-       //Do we have a selection?
+       // Notify left insets
+       if (cur != old) {
+               old.fixIfBroken();
+               bool badcursor = notifyCursorLeaves(old, cur);
+               if (badcursor)
+                       cursor().fixIfBroken();
+       }
+       
+       // Do we have a selection?
        theSelection().haveSelection(cursor().selection());
 
        // If the command has been dispatched,
-       if (cur.result().dispatched()
-               // an update is asked,
-               && cur.result().update())
+       if (cur.result().dispatched() || cur.result().update())
                processUpdateFlags(cur.result().update());
 }
 
@@ -1675,8 +1682,12 @@ bool BufferView::mouseSetCursor(Cursor & cur, bool select)
        // Has the cursor just left the inset?
        bool badcursor = false;
        bool leftinset = (&d->cursor_.inset() != &cur.inset());
-       if (leftinset)
+       if (leftinset) {
+               d->cursor_.fixIfBroken();
                badcursor = notifyCursorLeaves(d->cursor_, cur);
+               if (badcursor)
+                       cur.fixIfBroken();
+       }
 
        // FIXME: shift-mouse selection doesn't work well across insets.
        bool do_selection = select && &d->cursor_.anchor().inset() == &cur.inset();
@@ -1689,24 +1700,7 @@ bool BufferView::mouseSetCursor(Cursor & cur, bool select)
        if (!do_selection && !badcursor && d->cursor_.inTexted())
                update |= checkDepm(cur, d->cursor_);
 
-       // if the cursor was in an empty script inset and the new
-       // position is in the nucleus of the inset, notifyCursorLeaves
-       // will kill the script inset itself. So we check all the
-       // elements of the cursor to make sure that they are correct.
-       // For an example, see bug 2933:
-       // http://bugzilla.lyx.org/show_bug.cgi?id=2933
-       // The code below could maybe be moved to a DocIterator method.
-       //lyxerr << "cur before " << cur << endl;
-       DocIterator dit = doc_iterator_begin(cur.inset());
-       dit.bottom() = cur.bottom();
-       size_t i = 1;
-       while (i < cur.depth() && dit.nextInset() == &cur[i].inset()) {
-               dit.push_back(cur[i]);
-               ++i;
-       }
-       //lyxerr << "5 cur after" << dit <<endl;
-
-       d->cursor_.setCursor(dit);
+       d->cursor_.setCursor(cur);
        d->cursor_.boundary(cur.boundary());
        if (do_selection)
                d->cursor_.setSelection();
index 405d72b4f0af6bc4ea460e155b1506da528329bb..b8e70680fd272bfab7637ceac52aabbcddf64132 100644 (file)
@@ -377,8 +377,6 @@ void Cursor::pushBackward(Inset & p)
 bool Cursor::popBackward()
 {
        BOOST_ASSERT(!empty());
-       //lyxerr << "Leaving inset from in front" << endl;
-       inset().notifyCursorLeaves(*this);
        if (depth() == 1)
                return false;
        pop();
@@ -391,7 +389,6 @@ bool Cursor::popForward()
        BOOST_ASSERT(!empty());
        //lyxerr << "Leaving inset from in back" << endl;
        const pos_type lp = (depth() > 1) ? (*this)[depth() - 2].lastpos() : 0;
-       inset().notifyCursorLeaves(*this);
        if (depth() == 1)
                return false;
        pop();
@@ -1768,7 +1765,7 @@ bool Cursor::fixIfBroken()
 }
 
 
-bool notifyCursorLeaves(DocIterator const & old, Cursor & cur)
+bool notifyCursorLeaves(Cursor const & old, Cursor & cur)
 {
        // find inset in common
        size_type i;
@@ -1780,7 +1777,9 @@ bool notifyCursorLeaves(DocIterator const & old, Cursor & cur)
        // notify everything on top of the common part in old cursor,
        // but stop if the inset claims the cursor to be invalid now
        for (; i < old.depth(); ++i) {
-               if (old[i].inset().notifyCursorLeaves(cur))
+               Cursor insetPos = old;
+               insetPos.cutOff(i);
+               if (old[i].inset().notifyCursorLeaves(insetPos, cur))
                        return true;
        }
        
index 52220585b1db08c51c429018a713f4bcf0aa57d8..073880d9eba60c0c66a6f715cb3aaa4fc37c0e0c 100644 (file)
@@ -398,7 +398,7 @@ public:
  * Sure that the cursor old is valid, i.e. all inset pointers
  * point to valid insets! Use Cursor::fixIfBroken if necessary.
  */
-bool notifyCursorLeaves(DocIterator const & old, Cursor & cur);
+bool notifyCursorLeaves(Cursor const & old, Cursor & cur);
 
 
 } // namespace lyx
index f095a19a9d2b95a129f8e3cfe6d40513e4d2fe12..13b5c091ffc72f99d8db02573f6d029170f31fe2 100644 (file)
@@ -1705,15 +1705,20 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
                        }
 
                        // Let the current Cursor dispatch its own actions.
+                       Cursor old = view()->cursor();
                        view()->cursor().getPos(cursorPosBeforeDispatchX_,
                                                cursorPosBeforeDispatchY_);
                        view()->cursor().dispatch(cmd);
-                       updateFlags = view()->cursor().result().update();
-                       if (!view()->cursor().result().dispatched()) {
-                               // No update needed in this case (e.g. when reaching
-                               // top of document.
-                               updateFlags = Update::None;
+
+                       // notify insets we just left
+                       if (view()->cursor() != old) {
+                               old.fixIfBroken();
+                               bool badcursor = notifyCursorLeaves(old, view()->cursor());
+                               if (badcursor)
+                                       view()->cursor().fixIfBroken();
                        }
+
+                       updateFlags = view()->cursor().result().update();
                }
 
                if (lyx_view_ && lyx_view_->buffer()) {
index b7f9619c96e5f9075d517782adcfcba016857e98..b8e3ce0a200f54b4d061ed9a046c54c0bda2d016 100644 (file)
@@ -590,10 +590,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                bool up = cmd.action == LFUN_UP_SELECT || cmd.action == LFUN_UP;
                bool const successful = cur.upDownInText(up, needsUpdate);
                if (successful) {
-                       // notify insets which were left and get their update flags 
-                       notifyCursorLeaves(cur.beforeDispatchCursor(), cur);
-                       cur.fixIfBroken();
-                       
                        // redraw if you leave mathed (for the decorations)
                        needsUpdate |= cur.beforeDispatchCursor().inMathed();
                } else
index c3b72f4debcade449f5b78f8f0f2f0eaf7f94b6c..c2d5a440c7ec15a1f7d51299cac7890adfce517c 100644 (file)
@@ -34,6 +34,7 @@ class Change;
 class Cursor;
 class CursorSlice;
 class Dimension;
+class DocIterator;
 class FuncRequest;
 class FuncStatus;
 class InsetCollapsable;
@@ -221,9 +222,8 @@ public:
        /// number of columns in gridlike structures
        virtual size_t ncols() const { return 0; }
        /// is called when the cursor leaves this inset
-       /// returns true if cursor is now invalid. The cursor parameter
-       /// is _not_ necessarily pointing to the inset.
-       virtual bool notifyCursorLeaves(Cursor &) { return false; }
+       /// returns true if cursor is now invalid.
+       virtual bool notifyCursorLeaves(Cursor const &, Cursor &) { return false; }
        /// is called when the mouse enter or leave this inset
        /// return true if this inset needs repaint
        virtual bool setMouseHover(bool) { return false; }
index eb5a1a37e6f5b0814c5911f532adbe189f6fefb2..d3b7373bbe195d3d3876a3544bf7ae0bfad66702 100644 (file)
@@ -414,7 +414,7 @@ void InsetMathHull::addPreview(graphics::PreviewLoader & ploader) const
 }
 
 
-bool InsetMathHull::notifyCursorLeaves(Cursor & cur)
+bool InsetMathHull::notifyCursorLeaves(Cursor const & /*old*/, Cursor & cur)
 {
        if (RenderPreview::status() == LyXRC::PREVIEW_ON) {
                Buffer const & buffer = cur.buffer();
@@ -1046,7 +1046,6 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_FINISHED_LEFT:
                //lyxerr << "action: " << cmd.action << endl;
                InsetMathGrid::doDispatch(cur, cmd);
-               notifyCursorLeaves(cur);
                cur.undispatched();
                break;
 
index a7a3701da8fa7b8bf868ceb02c85be030a457cf2..6904d5847a5357871512f7d67d03708465c0f674 100644 (file)
@@ -116,7 +116,7 @@ public:
        virtual void textString(Buffer const &, odocstream &) const;
 
        /// get notification when the cursor leaves this inset
-       bool notifyCursorLeaves(Cursor & cur);
+       bool notifyCursorLeaves(Cursor const & old, Cursor & cur);
        ///
        //bool insetAllowed(InsetCode code) const;
        ///
index 14ec77cfd005027bae184ba56c065c7baeee7d88..f1ab2cdc82e9e1ec350bb1ae1c02da2d5faa79fd 100644 (file)
@@ -371,7 +371,7 @@ bool InsetMathNest::setMouseHover(bool mouse_hover)
 }
 
 
-bool InsetMathNest::notifyCursorLeaves(Cursor & /*cur*/)
+bool InsetMathNest::notifyCursorLeaves(Cursor const & /*old*/, Cursor & /*cur*/)
 {
        // FIXME: look here
 #if 0
@@ -584,12 +584,8 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
                // go up/down
                bool up = cmd.action == LFUN_UP || cmd.action == LFUN_UP_SELECT;
                bool successful = cur.upDownInMath(up);
-               if (successful) {
-                       // notify left insets and give them chance to set update flags
-                       lyx::notifyCursorLeaves(cur.beforeDispatchCursor(), cur);
-                       cur.fixIfBroken();
+               if (successful)
                        break;
-               }
                
                if (cur.fixIfBroken())
                        // FIXME: Something bad happened. We pass the corrected Cursor
index d164fe752558e9ed3d5ec131c14a75f3ebc3f434..d3fc72cc8b78e6093decb4549ecb88df05c5393f 100644 (file)
@@ -97,7 +97,7 @@ public:
        /// access to the lock
        void lock(bool);
        /// get notification when the cursor leaves this inset
-       bool notifyCursorLeaves(Cursor & cur);
+       bool notifyCursorLeaves(Cursor const & old, Cursor & cur);
 
        /// direct access to the cell.
        /// inlined because shows in profile.
index c146e071b15e7fc9008d1e2d99c63c420e401b1f..b1cc23eec00041194408d162004aa21f4a4c4cef 100644 (file)
@@ -660,9 +660,9 @@ void InsetMathScript::infoize2(odocstream & os) const
 }
 
 
-bool InsetMathScript::notifyCursorLeaves(Cursor & cur)
+bool InsetMathScript::notifyCursorLeaves(Cursor const & old, Cursor & cur)
 {
-       InsetMathNest::notifyCursorLeaves(cur);
+       InsetMathNest::notifyCursorLeaves(old, cur);
 
        //LYXERR0("InsetMathScript::notifyCursorLeaves: 1 " << cur);
 
@@ -690,14 +690,13 @@ bool InsetMathScript::notifyCursorLeaves(Cursor & cur)
        if ((nargs() == 2 && cell(1).empty())
            || (nargs() == 3 && cell(1).empty() && cell(2).empty())) {
                // Make undo step. We cannot use cur for this because
-               // it does not necessarily point to us. The BufferView
-               // cursor though should do.
-               int scriptSlice
-               = cur.bv().cursor().find(this);
+               // it does not necessarily point to us anymore. But we
+               // should be on top of the cursor old.
+               Cursor insetCur = old;
+               int scriptSlice = insetCur.find(this);
                BOOST_ASSERT(scriptSlice != -1);
-               Cursor & bvCur = cur.bv().cursor();
-               bvCur.cutOff(scriptSlice);
-               bvCur.recordUndoInset();
+               insetCur.cutOff(scriptSlice);
+               insetCur.recordUndoInset();
 
                // Let the script inset commit suicide. This is
                // modelled on Cursor.pullArg(), but tries not to
@@ -705,12 +704,9 @@ bool InsetMathScript::notifyCursorLeaves(Cursor & cur)
                // cur (since the top slice will be deleted
                // afterwards)
                MathData ar = cell(0);
-               bvCur.pop();
-               bvCur.cell().erase(bvCur.pos());
-               bvCur.cell().insert(bvCur.pos(), ar);
-
-               // put cursor behind
-               bvCur.pos() += ar.size();
+               insetCur.pop();
+               insetCur.cell().erase(insetCur.pos());
+               insetCur.cell().insert(insetCur.pos(), ar);
 
                // redraw
                cur.updateFlags(cur.disp_.update() | Update::SinglePar);
index e851e2b371e4ae02e2c49450bf068494852dc20e..a22cae95f4fd9372984ee01e27662735dcaeffcf 100644 (file)
@@ -129,7 +129,7 @@ private:
        /// where do we have to draw the scripts?
        bool hasLimits() const;
        /// clean up empty cells and return true if a cell has been deleted.
-       bool notifyCursorLeaves(Cursor & cur);
+       bool notifyCursorLeaves(Cursor const & old, Cursor & cur);
 
        /// possible subscript (index 0) and superscript (index 1)
        bool cell_1_is_up_;
index 821ba2326d7027044e3ad65a5b6d6f1d5fe010be..f5f16ef358e5240ec59e720f948b6d2dc6f8ef6d 100644 (file)
@@ -606,10 +606,10 @@ bool MathMacro::idxLast(Cursor & cur) const
 }
 
 
-bool MathMacro::notifyCursorLeaves(Cursor & cur)
+bool MathMacro::notifyCursorLeaves(Cursor const & old, Cursor & cur)
 {
        cur.updateFlags(Update::Force);
-       return InsetMathNest::notifyCursorLeaves(cur);
+       return InsetMathNest::notifyCursorLeaves(old, cur);
 }
 
 
index e0567a6468bbf327b58c75561133aed08350e4d3..8a10a45300f4267226effb6f807f47bc93f75f9e 100644 (file)
@@ -56,7 +56,7 @@ public:
        bool idxLast(Cursor &) const;
 
        ///
-       virtual bool notifyCursorLeaves(Cursor &);
+       virtual bool notifyCursorLeaves(Cursor const & old, Cursor & cur);
        
        /// Remove cell (starting from 0)
        void removeArgument(pos_type pos);
index ff0bc99c6dfcfc90f60a50256d6b2b11a7c65101..70fc28b5dd2488c63f9dd9d4e291a09bfc7dfccd 100644 (file)
@@ -538,11 +538,11 @@ void MathMacroTemplate::edit(Cursor & cur, bool front, EntryDirection entry_from
 }
 
 
-bool MathMacroTemplate::notifyCursorLeaves(Cursor & cur)
+bool MathMacroTemplate::notifyCursorLeaves(Cursor const & old, Cursor & cur)
 {
        updateLook();
        cur.updateFlags(Update::Force);
-       return InsetMathNest::notifyCursorLeaves(cur);
+       return InsetMathNest::notifyCursorLeaves(old, cur);
 }
 
 
index 6f2fa1d3b7e03b7696760bdf4f3390a82fb948a1..f16116738279ac7168ec42fdd77d5f423d7c3d8d 100644 (file)
@@ -40,7 +40,7 @@ public:
        ///
        void edit(Cursor & cur, bool front, EntryDirection entry_from);
        ///
-       bool notifyCursorLeaves(Cursor & cur);
+       bool notifyCursorLeaves(Cursor const & old, Cursor & cur);
        ///
        void read(Buffer const &, Lexer & lex);
        ///