sw/inc/crsrsh.hxx                 |    2 ++
 sw/source/core/crsr/crsrsh.cxx    |    9 ++++++++-
 sw/source/uibase/docvw/edtwin.cxx |    5 ++++-
 sw/source/uibase/inc/wrtsh.hxx    |    1 +
 sw/source/uibase/wrtsh/wrtsh1.cxx |    9 ++++++++-
 5 files changed, 23 insertions(+), 3 deletions(-)

New commits:
commit d7a427d9c869729c21285df7c32106f934f66a04
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Mon Aug 8 16:15:36 2022 +0200
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Fri Aug 12 23:29:13 2022 +0200

    sw: fix infinite recursion in SwEditWin::GetSurroundingTextSelection()
    
    The unexpected problem of calling SwCursorShell::Pop() from there ending
    up calling the function itself again, with gtk3 UI, on loading
    forum-mso-en-4034.docx and clicking somewhere or scrolling:
    
    466 SwEditWin::GetSurroundingTextSelection() const at 
sw/source/uibase/docvw/edtwin.cxx:6656
    467 ImplHandleSurroundingTextRequest(vcl::Window*, rtl::OUString&, 
Selection&) at vcl/source/window/winproc.cxx:2487
    468 ImplHandleSalSurroundingTextRequest(vcl::Window*, 
SalSurroundingTextRequestEvent*) at vcl/source/window/winproc.cxx:2497
    469 ImplWindowFrameProc(vcl::Window*, SalEvent, void const*) at 
vcl/source/window/winproc.cxx:2826
    470 SalFrame::CallCallback(SalEvent, void const*) const at 
vcl/inc/salframe.hxx:306
    471 GtkSalFrame::IMHandler::signalIMRetrieveSurrounding(_GtkIMContext*, 
void*) at vcl/unx/gtk3/gtkframe.cxx:5707
    472 _gtk_marshal_BOOLEAN__VOIDv () at /lib64/libgtk-3.so.0
    473 g_signal_emit_valist () at /lib64/libgobject-2.0.so.0
    474 g_signal_emit_by_name () at /lib64/libgobject-2.0.so.0
    475 gtk_im_multicontext_retrieve_surrounding_cb () at /lib64/libgtk-3.so.0
    476 _gtk_marshal_BOOLEAN__VOIDv () at /lib64/libgtk-3.so.0
    477 g_signal_emit_valist () at /lib64/libgobject-2.0.so.0
    478 g_signal_emit_by_name () at /lib64/libgobject-2.0.so.0
    479 enable () at /lib64/libgtk-3.so.0
    480 GtkSalFrame::IMHandler::createIMContext() at 
vcl/unx/gtk3/gtkframe.cxx:5187
    481 GtkSalFrame::IMHandler::IMHandler(GtkSalFrame*) at 
vcl/unx/gtk3/gtkframe.cxx:5153
    482 GtkSalFrame::SetInputContext(SalInputContext*) at 
vcl/unx/gtk3/gtkframe.cxx:2711
    483 vcl::Window::ImplNewInputContext() () at 
vcl/source/window/window.cxx:1781
    484 vcl::Window::SetInputContext(InputContext const&) at 
vcl/source/window/window.cxx:2083
    485 SwView::CheckReadonlySelection() at sw/source/uibase/uiview/view.cxx:699
    486 SwView::AttrChangedNotify(LinkParamNone*) at 
sw/source/uibase/uiview/view.cxx:510
    487 SwView::LinkStubAttrChangedNotify(void*, LinkParamNone*) at 
sw/source/uibase/uiview/view.cxx:499
    488 Link<LinkParamNone*, void>::Call(LinkParamNone*) const at 
include/tools/link.hxx:111
    489 SwCursorShell::CallChgLnk() at sw/source/core/crsr/crsrsh.cxx:2544
    490 SwCallLink::~SwCallLink() at sw/source/core/crsr/callnk.cxx:149
    491 SwCursorShell::Pop(SwCursorShell::PopMode) at 
sw/source/core/crsr/crsrsh.cxx:2327
    492 SwWrtShell::Pop(SwCursorShell::PopMode) at 
sw/source/uibase/wrtsh/wrtsh1.cxx:2016
    493 SwEditWin::GetSurroundingTextSelection() const at 
sw/source/uibase/docvw/edtwin.cxx:6656
    
    This SwCallLink looks unnecessary here, but it's triggered because it
    compares the state before Pop() to the state after Pop(), instead of the
    state before Push() to the state after Pop().
    
    This problem could probably benefit from being solved more generally,
    but with 2 functions involved it gets rather ugly as it can't easily be
    encapsulated in SwCursorShell.
    
    (probably regression from aac9bd235e65b27faf63e64bba3ecd94837381d6)
    
    Change-Id: Ief176b54daf96da378d2e5d57f3dd5b4a0817299
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137987
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 581ba395222e04e43697484bef9181c877d1fd61)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138027
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>

diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index fb6e00106691..9f79a515153a 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -45,6 +45,7 @@
 
 class SfxItemSet;
 class SfxPoolItem;
+class SwCallLink;
 class SwContentFrame;
 class SwUnoCursor;
 class SwFormatField;
@@ -436,6 +437,7 @@ public:
      *      stack
      *  @return <true> if there was one on the stack, <false> otherwise
      */
+    bool Pop(PopMode, ::std::unique_ptr<SwCallLink> pLink);
     bool Pop(PopMode);
     /*
      * Combine 2 Cursors.
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index ebb15bec6107..18199f2ebcd3 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -2269,7 +2269,14 @@ void SwCursorShell::Push()
 */
 bool SwCursorShell::Pop(PopMode const eDelete)
 {
-    SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
+    ::std::unique_ptr<SwCallLink> 
pLink(::std::make_unique<SwCallLink>(*this)); // watch Cursor-Moves; call Link 
if needed
+    return Pop(eDelete, ::std::move(pLink));
+}
+
+bool SwCursorShell::Pop(PopMode const eDelete,
+        [[maybe_unused]] ::std::unique_ptr<SwCallLink> const pLink)
+{
+    assert(pLink); // parameter exists only to be deleted before return
 
     // are there any left?
     if (nullptr == m_pStackCursor)
diff --git a/sw/source/uibase/docvw/edtwin.cxx 
b/sw/source/uibase/docvw/edtwin.cxx
index ac331e1cfa36..efa625bca7ee 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -145,6 +145,7 @@
 #include <sfx2/event.hxx>
 #include <memory>
 
+#include "../../core/crsr/callnk.hxx"
 #include <IDocumentOutlineNodes.hxx>
 #include <ndtxt.hxx>
 #include <cntfrm.hxx>
@@ -6620,13 +6621,15 @@ Selection SwEditWin::GetSurroundingTextSelection() const
         // around the visible cursor.
         TextFrameIndex const nPos(rSh.GetCursorPointAsViewIndex());
 
+        // store shell state *before* Push
+        ::std::unique_ptr<SwCallLink> 
pLink(::std::make_unique<SwCallLink>(rSh));
         rSh.Push();
 
         rSh.HideCursor();
         rSh.GoStartSentence();
         TextFrameIndex const nStartPos(rSh.GetCursorPointAsViewIndex());
 
-        rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+        rSh.Pop(SwCursorShell::PopMode::DeleteCurrent, ::std::move(pLink));
         rSh.ShowCursor();
 
         if (bUnLockView)
diff --git a/sw/source/uibase/inc/wrtsh.hxx b/sw/source/uibase/inc/wrtsh.hxx
index 134c7dc5dbf6..619d7e17b4e1 100644
--- a/sw/source/uibase/inc/wrtsh.hxx
+++ b/sw/source/uibase/inc/wrtsh.hxx
@@ -146,6 +146,7 @@ public:
         // is there a text- or frameselection?
     bool    HasSelection() const { return SwCursorShell::HasSelection() ||
                                         IsMultiSelection() || IsSelFrameMode() 
|| IsObjSelected(); }
+    bool    Pop(SwCursorShell::PopMode, ::std::unique_ptr<SwCallLink> const 
pLink);
     bool    Pop(SwCursorShell::PopMode = SwCursorShell::PopMode::DeleteStack);
 
     void    EnterStdMode();
diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx 
b/sw/source/uibase/wrtsh/wrtsh1.cxx
index ee6ae421be93..6a17c6e80458 100644
--- a/sw/source/uibase/wrtsh/wrtsh1.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh1.cxx
@@ -108,6 +108,7 @@
 #include <svl/zformat.hxx>
 #include <memory>
 
+#include "../../core/crsr/callnk.hxx"
 #include <frmtool.hxx>
 #include <viewopt.hxx>
 
@@ -2010,7 +2011,13 @@ SwWrtShell::~SwWrtShell()
 
 bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete)
 {
-    bool bRet = SwCursorShell::Pop(eDelete);
+    ::std::unique_ptr<SwCallLink> pLink(::std::make_unique<SwCallLink>(*this));
+    return Pop(eDelete, ::std::move(pLink));
+}
+
+bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete, 
::std::unique_ptr<SwCallLink> pLink)
+{
+    bool bRet = SwCursorShell::Pop(eDelete, ::std::move(pLink));
     if( bRet && IsSelection() )
     {
         if (!IsAddMode())

Reply via email to