commit 87d291ee237cd24419ced6237b52518a53a4f474
Author: Jean-Marc Lasgouttes <[email protected]>
Date:   Wed Dec 13 10:38:47 2017 +0100

    Handle properly undo groups in embedded work areas
    
    When a buffer is in an embedded work area (adv. find&replace), it is
    not found by BufferList:::exists(), and therefore the undo group
    created in GuiApplication::dispatch and in the handling of
    LFUN_COMMAND_SEQUENCE will not be closed.. Crashes can ensue, as
    described in Ubuntu bug:
    https://bugs.launchpad.net/bugs/1737429
    
    The solution is to introduce BufferList::isInternal and act on it.
    
    Fixes bug #10847.
    
    (cherry picked from commit 8b107f0490e61b4390e925f08d21661ef50d6f49)
---
 src/BufferList.cpp                   |   12 +++++++++++-
 src/BufferList.h                     |    3 +++
 src/Undo.cpp                         |    6 ++++--
 src/frontends/qt4/GuiApplication.cpp |    4 ++--
 4 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/src/BufferList.cpp b/src/BufferList.cpp
index a61b0bf..5e83c7b 100644
--- a/src/BufferList.cpp
+++ b/src/BufferList.cpp
@@ -269,7 +269,7 @@ bool BufferList::exists(FileName const & fname) const
 }
 
 
- bool BufferList::isLoaded(Buffer const * b) const
+bool BufferList::isLoaded(Buffer const * b) const
 {
        if (!b)
                return false;
@@ -279,6 +279,16 @@ bool BufferList::exists(FileName const & fname) const
 }
 
 
+bool BufferList::isInternal(Buffer const * b) const
+{
+       if (!b)
+               return false;
+       BufferStorage::const_iterator cit =
+               find(binternal.begin(), binternal.end(), b);
+       return cit != binternal.end();
+}
+
+
 bool BufferList::isOthersChild(Buffer * parent, Buffer * child)
 {
        LASSERT(parent, return false);
diff --git a/src/BufferList.h b/src/BufferList.h
index 01698af..ca55abe 100644
--- a/src/BufferList.h
+++ b/src/BufferList.h
@@ -84,6 +84,9 @@ public:
        /// returns true if the buffer is loaded
        bool isLoaded(Buffer const * b) const;
 
+       /// returns true if the buffer is known as internal buffer
+       bool isInternal(Buffer const * b) const;
+
        /// \return index of named buffer in buffer list
        int bufferNum(support::FileName const & name) const;
 
diff --git a/src/Undo.cpp b/src/Undo.cpp
index a479728..f7ee482 100644
--- a/src/Undo.cpp
+++ b/src/Undo.cpp
@@ -562,7 +562,8 @@ void Undo::beginUndoGroup()
        if (d->group_level_ == 0) {
                // create a new group
                ++d->group_id_;
-               LYXERR(Debug::UNDO, "+++++++Creating new group " << 
d->group_id_);
+               LYXERR(Debug::UNDO, "+++++++ Creating new group " << 
d->group_id_
+                      << " for buffer " << &d->buffer_);
        }
        ++d->group_level_;
 }
@@ -586,7 +587,8 @@ void Undo::endUndoGroup()
        if (d->group_level_ == 0) {
                // real end of the group
                d->group_cur_before_ = CursorData();
-               LYXERR(Debug::UNDO, "-------End of group " << d->group_id_);
+               LYXERR(Debug::UNDO, "------- End of group " << d->group_id_
+                      << " of buffer " << &d->buffer_);
        }
 }
 
diff --git a/src/frontends/qt4/GuiApplication.cpp 
b/src/frontends/qt4/GuiApplication.cpp
index 1e84746..97a60e9 100644
--- a/src/frontends/qt4/GuiApplication.cpp
+++ b/src/frontends/qt4/GuiApplication.cpp
@@ -1407,7 +1407,7 @@ DispatchResult const & 
GuiApplication::dispatch(FuncRequest const & cmd)
        updateCurrentView(cmd, dr);
 
        // the buffer may have been closed by one action
-       if (theBufferList().isLoaded(buffer))
+       if (theBufferList().isLoaded(buffer) || 
theBufferList().isInternal(buffer))
                buffer->undo().endUndoGroup();
 
        d->dispatch_result_ = dr;
@@ -1883,7 +1883,7 @@ void GuiApplication::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
                        dispatch(func);
                }
                // the buffer may have been closed by one action
-               if (theBufferList().isLoaded(buffer))
+               if (theBufferList().isLoaded(buffer) || 
theBufferList().isInternal(buffer))
                        buffer->undo().endUndoGroup();
                break;
        }

Reply via email to