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 581ba395222e04e43697484bef9181c877d1fd61
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Mon Aug 8 16:15:36 2022 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Aug 10 10:57:00 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>

diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index 0b66682b9c92..c2a5d75c454c 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 745fb43f5239..4b7fbcbd377d 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -2268,7 +2268,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 359d01ddec40..b796270b9bdc 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>
@@ -6643,13 +6644,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 db1b89822eb3..d8a0e2559624 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 aef0dc502e9a..d61cb158c93f 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>
 
@@ -2013,7 +2014,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