commit 8b107f0490e61b4390e925f08d21661ef50d6f49
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.
---
 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 2bbb8b9..538df77 100644
--- a/src/BufferList.cpp
+++ b/src/BufferList.cpp
@@ -268,7 +268,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;
@@ -278,6 +278,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 2eb35a2..b388b9c 100644
--- a/src/Undo.cpp
+++ b/src/Undo.cpp
@@ -569,7 +569,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_;
 }
@@ -593,7 +594,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 b579f62..5d7f559 100644
--- a/src/frontends/qt4/GuiApplication.cpp
+++ b/src/frontends/qt4/GuiApplication.cpp
@@ -1402,7 +1402,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;
@@ -1871,7 +1871,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