[Libreoffice-commits] core.git: Branch 'feature/perf-mail-merge' - 21 commits - chart2/source cui/source desktop/source drawinglayer/source editeng/source external/boost framework/source include/sal include/vcl sc/inc sc/source sd/source sfx2/source solenv/bin solenv/gdb svtools/source svx/source sw/inc sw/qa sw/source vcl/inc vcl/source vcl/unx

Jan-Marek Glogowski glogow at fbihome.de
Thu Aug 25 15:13:00 UTC 2016


Rebased ref, commits from common ancestor:
commit 0cad0d6204e784660769c24133a7c7de8f24e45a
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Thu Aug 11 18:45:21 2016 +0200

    MM don't keep undo information
    
    Doen't make much sense to store undo information for all merge
    based progress. Actually it even prevents crahes when undoing a
    merged ODT document.
    
    Change-Id: Ic3a3982f3e5eb4f6de9f027a6a5e376c2833e8a5

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index b21c6d8..d1c13d0 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -78,6 +78,7 @@
 #include <IDocumentLinksAdministration.hxx>
 #include <IDocumentContentOperations.hxx>
 #include <IDocumentFieldsAccess.hxx>
+#include <IDocumentUndoRedo.hxx>
 #include <swwait.hxx>
 #include <swunohelper.hxx>
 #include <dbui.hrc>
@@ -990,6 +991,7 @@ static SfxObjectShell* lcl_CreateWorkingDocument(
     pWorkWrtShell->GetViewOptions()->SetIdle( false );
     pWorkView->AttrChangedNotify( pWorkWrtShell );// in order for SelectShell to be called
     SwDoc* pWorkDoc = pWorkWrtShell->GetDoc();
+    pWorkDoc->GetIDocumentUndoRedo().DoUndo( false );
     pWorkDoc->ReplaceDocumentProperties( *pSourceDoc );
 
     if( aType == WorkingDocType::TARGET )
@@ -1530,6 +1532,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
         pTargetShell->CalcLayout();
         SAL_INFO( "sw.pageframe", "MergeMailFiles pTargetShell->CalcLayout out)" );
         pTargetShell->GetViewOptions()->SetIdle( true );
+        pTargetDoc->GetIDocumentUndoRedo().DoUndo( true );
         for ( auto aLayout : pTargetShell->GetDoc()->GetAllLayouts() )
         {
             aLayout->FreezeLayout(false);
commit b94e24f02d4212e1c9401623d522c9f3ac958f47
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Thu Aug 11 18:39:20 2016 +0200

    Fix SwDoc::AppendDoc for trailing sections
    
    We already treat the StartOfContent node special in the CopyRange
    function to prevent merging of SwTextNodes.
    
    For trailing sections, we have to expand the code to treat
    EndOfContent special too, because the supplied SwPaM range is
    handled as [mark, point[, so it previously missed the section end
    node, which resulted in "unhiding" the last section, if it was the
    last node in the document.
    
    Change-Id: Ie094e2a0182647a49c9ba45d08a7dd2cabe667c6

diff --git a/sw/inc/IDocumentContentOperations.hxx b/sw/inc/IDocumentContentOperations.hxx
index 75b4f84..1572e21 100644
--- a/sw/inc/IDocumentContentOperations.hxx
+++ b/sw/inc/IDocumentContentOperations.hxx
@@ -80,7 +80,7 @@ public:
         be within the range!
 
         \warning The range has to include at least two nodes or has to be a
-        SwDoc::IsColumnSelection!
+        SwDoc::IsColumnSelection, because the rPam is treated [mark, point[.
 
         Normally this function should work only with content nodes. But there
         is a special case used by SwDoc::Paste, which starts the SwPaM at the
diff --git a/sw/qa/extras/mailmerge/data/sections_first_last.odt b/sw/qa/extras/mailmerge/data/sections_first_last.odt
new file mode 100644
index 0000000..5a92adb
Binary files /dev/null and b/sw/qa/extras/mailmerge/data/sections_first_last.odt differ
diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx
index 4b2e8ef..84331cc8 100644
--- a/sw/qa/extras/mailmerge/mailmerge.cxx
+++ b/sw/qa/extras/mailmerge/mailmerge.cxx
@@ -32,6 +32,7 @@
 #include <edtwin.hxx>
 #include <olmenu.hxx>
 #include <cmdid.h>
+#include <pagefrm.hxx>
 
 /**
  * Maps database URIs to the registered database names for quick lookups
@@ -531,5 +532,42 @@ DECLARE_SHELL_MAILMERGE_TEST_SELECTION(testTdf95292, "linked-labels.odt", "10-te
     CPPUNIT_ASSERT_EQUAL( sal_uInt16( 5 ), pWrtShell->GetPhyPageNum() );
 }
 
+DECLARE_SHELL_MAILMERGE_TEST(test_sections_first_last, "sections_first_last.odt", "10-testing-addresses.ods", "testing-addresses")
+{
+    // A document with a leading, middle and trailing section
+    // Originally we were losing the trailing section during merge
+    executeMailMerge();
+
+    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+    CPPUNIT_ASSERT(pTextDoc);
+
+    // Get the size of the document in nodes
+    SwDoc *pDoc = pTextDoc->GetDocShell()->GetDoc();
+    sal_uLong nSize = pDoc->GetNodes().GetEndOfContent().GetIndex() - pDoc->GetNodes().GetEndOfExtras().GetIndex();
+    nSize -= 2; // The common start and end node
+    CPPUNIT_ASSERT_EQUAL( sal_uLong(13), nSize );
+
+    SwXTextDocument* pTextDocMM = dynamic_cast<SwXTextDocument *>(mxMMComponent.get());
+    CPPUNIT_ASSERT(pTextDocMM);
+
+    SwDoc *pDocMM = pTextDocMM->GetDocShell()->GetDoc();
+    sal_uLong nSizeMM = pDocMM->GetNodes().GetEndOfContent().GetIndex() - pDocMM->GetNodes().GetEndOfExtras().GetIndex();
+    nSizeMM -= 2;
+    CPPUNIT_ASSERT_EQUAL( sal_uLong(10 * nSize), nSizeMM );
+
+    CPPUNIT_ASSERT_EQUAL( sal_uInt16(19), pDocMM->GetDocShell()->GetWrtShell()->GetPhyPageNum() );
+
+    // All even pages should be empty, all sub-documents have two pages
+    const SwRootFrame* pLayout = pDocMM->getIDocumentLayoutAccess().GetCurrentLayout();
+    const SwPageFrame* pPageFrm = static_cast<const SwPageFrame*>( pLayout->Lower() );
+    while ( pPageFrm )
+    {
+        bool bOdd = (1 == (pPageFrm->GetPhyPageNum() % 2));
+        CPPUNIT_ASSERT_EQUAL( !bOdd, pPageFrm->IsEmptyPage() );
+        CPPUNIT_ASSERT_EQUAL( sal_uInt16( bOdd ? 1 : 2 ), pPageFrm->GetVirtPageNum() );
+        pPageFrm = static_cast<const SwPageFrame*>( pPageFrm->GetNext() );
+    }
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index 3b13238..0dada40 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -965,20 +965,13 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu
     SAL_INFO( "sw.pagefrm", "(SwDoc::AppendDoc in " << bDeletePrevious );
 
     // GetEndOfExtras + 1 = StartOfContent == no content node!
-    // this ensures, that we have at least two nodes in the SwPaM.
-    // @see IDocumentContentOperations::CopyRange
+    // This ensures it won't be merged in the SwTextNode at the position.
     SwNodeIndex aSourceIdx( rSource.GetNodes().GetEndOfExtras(), 1 );
-    SwNodeIndex aSourceEndIdx( rSource.GetNodes().GetEndOfContent(), -1 );
-    SwPaM aCpyPam( aSourceIdx );
-
-    if ( aSourceEndIdx.GetNode().IsTextNode() ) {
-        aCpyPam.SetMark();
-        // moves to the last content node before EOC; for single paragraph
-        // documents this would result in [n, n], which is considered empty
-        aCpyPam.Move( fnMoveForward, fnGoDoc );
-    }
-    else
-        aCpyPam = SwPaM( aSourceIdx, aSourceEndIdx );
+    // CopyRange works on the range a [mark, point[ and considers an
+    // index < point outside the selection.
+    // @see IDocumentContentOperations::CopyRange
+    SwNodeIndex aSourceEndIdx( rSource.GetNodes().GetEndOfContent(), 0 );
+    SwPaM aCpyPam( aSourceIdx, aSourceEndIdx );
 
 #ifdef DBG_UTIL
     SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceIdx.GetNode().GetNodeType()
@@ -995,10 +988,8 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu
     SAL_INFO( "sw.docappend", ".." );
     SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceEndIdx.GetNode().GetNodeType()
                               << std::dec << " " << aSourceEndIdx.GetNode().GetIndex() );
-    aSourceEndIdx++;
     SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceEndIdx.GetNode().GetNodeType()
                               << std::dec << " " << aSourceEndIdx.GetNode().GetIndex() );
-    aSourceEndIdx--;
     SAL_INFO( "sw.docappend", "Src-Nd: " << CNTNT_DOC( &rSource ) );
     SAL_INFO( "sw.docappend", "Nd: " << CNTNT_DOC( this ) );
 #endif
@@ -1042,9 +1033,23 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu
         }
 
         // Otherwise we have to handle SwPlaceholderNodes as first node
-        if ( pTargetPageDesc ) {
+        if ( pTargetPageDesc )
+        {
+            SwNodeIndex aBreakIdx( GetNodes().GetEndOfContent(), -1 );
+            SwPosition aBreakPos( aBreakIdx );
+            // InsertPageBreak just works on SwTextNode nodes, so make
+            // sure the last node is one!
+            bool bIsTextNode = aBreakIdx.GetNode().IsTextNode();
+            if ( !bIsTextNode )
+                getIDocumentContentOperations().AppendTextNode( aBreakPos );
             OUString name = pTargetPageDesc->GetName();
             pTargetShell->InsertPageBreak( &name, nStartPageNumber );
+            if ( !bIsTextNode )
+            {
+                pTargetShell->SttEndDoc( false );
+                --aBreakIdx;
+                GetNodes().Delete( aBreakIdx, 1 );
+            }
 
             // There is now a new empty text node on the new page. If it has
             // any marks, those are from the previous page: move them back
@@ -1104,7 +1109,8 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu
     this->GetIDocumentUndoRedo().StartUndo( UNDO_INSGLOSSARY, nullptr );
     this->getIDocumentFieldsAccess().LockExpFields();
 
-    // Position where the appended doc starts. Will be filled in later (uses GetEndOfContent() because SwNodeIndex has no default ctor).
+    // Position where the appended doc starts. Will be filled in later.
+    // Initially uses GetEndOfContent() because SwNodeIndex has no default ctor.
     SwNodeIndex aStartAppendIndex( GetNodes().GetEndOfContent() );
 
     {
diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx
index 7927af3..4b04d07 100644
--- a/sw/source/core/docnode/nodes.cxx
+++ b/sw/source/core/docnode/nodes.cxx
@@ -1695,24 +1695,30 @@ void SwNodes::CopyNodes( const SwNodeRange& rRange,
                 !pAktNode->m_pStartOfSection->IsSectionNode() ) )
         ++aRg.aStart;
 
-    // if aEnd-1 points to no ContentNode, search previous one
-    --aRg.aEnd;
-    // #i107142#: if aEnd is start node of a special section, do nothing.
-    // Otherwise this could lead to crash: going through all previous
-    // special section nodes and then one before the first.
-    if (aRg.aEnd.GetNode().StartOfSectionIndex() != 0)
+    const SwNode *aEndNode = &aRg.aEnd.GetNode();
+    int nIsEndOfContent = (aEndNode == &aEndNode->GetNodes().GetEndOfContent()) ? 1 : 0;
+
+    if (0 == nIsEndOfContent)
     {
-        while( ((pAktNode = & aRg.aEnd.GetNode())->GetStartNode() &&
-                !pAktNode->IsSectionNode() ) ||
-                ( pAktNode->IsEndNode() &&
-                ND_STARTNODE == pAktNode->m_pStartOfSection->GetNodeType()) )
+        // if aEnd-1 points to no ContentNode, search previous one
+        --aRg.aEnd;
+        // #i107142#: if aEnd is start node of a special section, do nothing.
+        // Otherwise this could lead to crash: going through all previous
+        // special section nodes and then one before the first.
+        if (aRg.aEnd.GetNode().StartOfSectionIndex() != 0)
         {
-            --aRg.aEnd;
+            while( ((pAktNode = & aRg.aEnd.GetNode())->GetStartNode() &&
+                    !pAktNode->IsSectionNode() ) ||
+                    ( pAktNode->IsEndNode() &&
+                    ND_STARTNODE == pAktNode->m_pStartOfSection->GetNodeType()) )
+            {
+                --aRg.aEnd;
+            }
         }
+        ++aRg.aEnd;
     }
-    ++aRg.aEnd;
 
-    // if in same array, check insertion position
+    // is there anything left to copy?
     if( aRg.aStart >= aRg.aEnd )
         return;
 
@@ -1787,7 +1793,7 @@ void SwNodes::CopyNodes( const SwNodeRange& rRange,
                 if (nDistance < nNodeCnt)
                     nNodeCnt -= nDistance;
                 else
-                    nNodeCnt = 1;
+                    nNodeCnt = 1 - nIsEndOfContent;
 
                 aRg.aStart = pAktNode->EndOfSectionIndex();
 
@@ -1815,7 +1821,7 @@ void SwNodes::CopyNodes( const SwNodeRange& rRange,
                 if (nDistance < nNodeCnt)
                     nNodeCnt -= nDistance;
                 else
-                    nNodeCnt = 1;
+                    nNodeCnt = 1 - nIsEndOfContent;
                 aRg.aStart = pAktNode->EndOfSectionIndex();
 
                 if( bNewFrames && pSectNd &&
@@ -1840,6 +1846,9 @@ void SwNodes::CopyNodes( const SwNodeRange& rRange,
                 --nLevel;
                 ++aInsPos; // EndNode already exists
             }
+            else if( 1 == nNodeCnt && 1 == nIsEndOfContent )
+                // we have reached the EndOfContent node - nothing to do!
+                continue;
             else if( !pAktNode->m_pStartOfSection->IsSectionNode() )
             {
                 // create a section at the original InsertPosition
commit d6b789b762d272a6c42cf6fd21f6bc5b1e962c53
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Aug 10 12:42:29 2016 +0200

    MM block idle-handling of generated documents
    
    We don't need any background idle jobs for the generated documents,
    like spell checking, statistics etc.
    
    This can be done when (or even if) the document is presented to the
    user as a background task.
    
    Change-Id: I4c72ed6e0d2f90d43e7f04cd0ea4418cbffe1206

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 76b6707..b21c6d8 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -987,6 +987,7 @@ static SfxObjectShell* lcl_CreateWorkingDocument(
 
     SwView* pWorkView = static_cast< SwView* >( pWorkFrame->GetViewShell() );
     SwWrtShell* pWorkWrtShell = pWorkView->GetWrtShellPtr();
+    pWorkWrtShell->GetViewOptions()->SetIdle( false );
     pWorkView->AttrChangedNotify( pWorkWrtShell );// in order for SelectShell to be called
     SwDoc* pWorkDoc = pWorkWrtShell->GetDoc();
     pWorkDoc->ReplaceDocumentProperties( *pSourceDoc );
@@ -1528,6 +1529,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
         SAL_INFO( "sw.pageframe", "(MergeMailFiles pTargetShell->CalcLayout in" );
         pTargetShell->CalcLayout();
         SAL_INFO( "sw.pageframe", "MergeMailFiles pTargetShell->CalcLayout out)" );
+        pTargetShell->GetViewOptions()->SetIdle( true );
         for ( auto aLayout : pTargetShell->GetDoc()->GetAllLayouts() )
         {
             aLayout->FreezeLayout(false);
commit 471091d6728f4e7aa780852b1168ae625bc57339
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Aug 10 11:37:15 2016 +0200

    Add SAL_INFOs to dump the SwPageFrame lifecycle
    
    Debug area name is "sw.pageframe".
    
    Change-Id: I136cc8192137a8c682900a6ce2c557f6b6b3a6cd

diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox
index ac824a8..29f5227 100644
--- a/include/sal/log-areas.dox
+++ b/include/sal/log-areas.dox
@@ -471,6 +471,7 @@ certain functionality.
 @li @c sw.idle
 @li @c sw.level2
 @li @c sw.mailmerge - Writer mail merge
+ at li @c sw.pageframe - debug lifecycle of SwPageFrame
 @li @c sw.rtf - .rtf export filter
 @li @c sw.tiled
 @li @c sw.ui
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index d140486..3b13238 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -879,6 +879,7 @@ void SwDoc::ReplaceCompatibilityOptions(const SwDoc& rSource)
 
 SfxObjectShell* SwDoc::CreateCopy( bool bCallInitNew, bool bEmpty ) const
 {
+    SAL_INFO( "sw.pagefrm", "(SwDoc::CreateCopy in" );
     SwDoc* pRet = new SwDoc;
 
     // we have to use pointer here, since the callee has to decide whether
@@ -917,6 +918,7 @@ SfxObjectShell* SwDoc::CreateCopy( bool bCallInitNew, bool bEmpty ) const
 
     (void)pRet->release();
 
+    SAL_INFO( "sw.pagefrm", "SwDoc::CreateCopy out)" );
     return pRetShell;
 }
 
@@ -960,6 +962,8 @@ static void lcl_CopyFollowPageDesc(
 SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNumber,
                              bool const bDeletePrevious, int pageOffset, const sal_uLong nDocNo)
 {
+    SAL_INFO( "sw.pagefrm", "(SwDoc::AppendDoc in " << bDeletePrevious );
+
     // GetEndOfExtras + 1 = StartOfContent == no content node!
     // this ensures, that we have at least two nodes in the SwPaM.
     // @see IDocumentContentOperations::CopyRange
@@ -1071,7 +1075,9 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu
             // Flush the page break, if we want to keep it
             if ( !bDeletePrevious )
             {
+                SAL_INFO( "sw.pagefrm", "(Flush pagebreak AKA EndAllAction" );
                 pTargetShell->EndAllAction();
+                SAL_INFO( "sw.pagefrm",  "Flush changes AKA EndAllAction)" );
                 pTargetShell->StartAllAction();
             }
         }
@@ -1247,6 +1253,7 @@ else
     if ( pTargetShell )
         pTargetShell->EndAllAction();
 
+    SAL_INFO( "sw.pagefrm", "SwDoc::AppendDoc out)" );
     return aStartAppendIndex;
 }
 
diff --git a/sw/source/core/layout/flowfrm.cxx b/sw/source/core/layout/flowfrm.cxx
index a28f36a..3b3cfcd 100644
--- a/sw/source/core/layout/flowfrm.cxx
+++ b/sw/source/core/layout/flowfrm.cxx
@@ -856,6 +856,13 @@ bool SwFrame::WrongPageDesc( SwPageFrame* pNew )
     const SwPageDesc *pNewDesc= ( pNewFlow && !pNewFlow->IsFollow() )
             ? pNewFlow->GetFrame().GetAttrSet()->GetPageDesc().GetPageDesc() : nullptr;
 
+    SAL_INFO( "sw.pagefrm", "WrongPageDesc p: " << pNew << " phys: " << pNew->GetPhyPageNum() );
+    SAL_INFO( "sw.pagefrm", "WrongPageDesc " << pNew->GetPageDesc() << " " << pDesc );
+    SAL_INFO( "sw.pagefrm", "WrongPageDesc odd: " << bOdd
+              << " first: " << bFirst << " " << pNew->GetFormat() << " == "
+              << (bOdd ? pDesc->GetRightFormat(bFirst) : pDesc->GetLeftFormat(bFirst)) << " "
+              << (bOdd ? pDesc->GetLeftFormat(bFirst) : pDesc->GetRightFormat(bFirst)) );
+
     return (pNew->GetPageDesc() != pDesc)   //  own desc ?
         || (pNew->GetFormat() !=
               (bOdd ? pDesc->GetRightFormat(bFirst) : pDesc->GetLeftFormat(bFirst)))
diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx
index 3e36f3f..b69d987 100644
--- a/sw/source/core/layout/frmtool.cxx
+++ b/sw/source/core/layout/frmtool.cxx
@@ -2663,10 +2663,12 @@ SwPageFrame * InsertNewPage( SwPageDesc &rDesc, SwFrame *pUpper,
         SwPageDesc *pTmpDesc = pSibling && pSibling->GetPrev() ?
                 static_cast<SwPageFrame*>(pSibling->GetPrev())->GetPageDesc() : &rDesc;
         pRet = new SwPageFrame( pDoc->GetEmptyPageFormat(), pUpper, pTmpDesc );
+        SAL_INFO( "sw.pageframe", "InsertNewPage - insert empty p: " << pRet << " d: " << pTmpDesc );
         pRet->Paste( pUpper, pSibling );
         pRet->PreparePage( bFootnote );
     }
     pRet = new SwPageFrame( pFormat, pUpper, &rDesc );
+    SAL_INFO( "sw.pageframe", "InsertNewPage p: " << pRet << " d: " << &rDesc << " f: " << pFormat );
     pRet->Paste( pUpper, pSibling );
     pRet->PreparePage( bFootnote );
     if ( pRet->GetNext() )
diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx
index 28477e9..493c0ec 100644
--- a/sw/source/core/layout/pagechg.cxx
+++ b/sw/source/core/layout/pagechg.cxx
@@ -966,6 +966,7 @@ void SwPageFrame::PrepareRegisterChg()
  */
 void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFrame** ppPrev )
 {
+    SAL_INFO( "sw.pageframe", "(CheckPageDescs in phy: " << pStart->GetPhyPageNum() );
     assert(pStart && "no starting page.");
 
     SwViewShell *pSh   = pStart->getRootFrame()->GetCurrShell();
@@ -974,6 +975,8 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra
     if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() )
     {
         pImp->GetLayAction().SetCheckPageNum( pStart->GetPhyPageNum() );
+        SAL_INFO( "sw.pageframe", "CheckPageDescs out fast - via SetCheckPageNum: "
+                  << pStart->GetPhyPageNum() << ")" );
         return;
     }
 
@@ -1045,7 +1048,7 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra
                         pNextFormatWish = bNextWantOdd ? pNextDesc->GetLeftFormat() : pNextDesc->GetRightFormat();
                     if ( pNextFormatWish && pNextPage->GetFormat() == pNextFormatWish )
                     {
-                        SAL_INFO( "sw.swpagefrm", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
+                        SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
                                   << " c: 1+3 - skip next page of p: " << pPage );
                         if (pPage->GetPageDesc() != pPrevPage->GetPageDesc())
                             pPage->SetPageDesc( pPrevPage->GetPageDesc(), 0 );
@@ -1059,6 +1062,8 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra
                 bool bUpdatePrev = false;
                 if (ppPrev && *ppPrev == pPage)
                     bUpdatePrev = true;
+                SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
+                          << " c: 1 - destroy p: " << pPage );
                 SwFrame::DestroyFrame(pPage);
                 if ( pStart == pPage )
                     pStart = pNextPage;
@@ -1070,6 +1075,8 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra
             else if ( bIsEmpty && !pFormatWish &&  //2.
                       pDesc != pPage->GetPageDesc() )
             {
+                SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
+                          << " c: 2 - set desc p: " << pPage << " d: " << pDesc );
                 pPage->SetPageDesc( pDesc, nullptr );
             }
             else if ( !bIsEmpty &&      //3.
@@ -1082,6 +1089,8 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra
                 if ( pPrevPage )
                     pDesc = pPrevPage->GetPageDesc();
                 SwPageFrame *pTmp = new SwPageFrame( pDoc->GetEmptyPageFormat(), pRoot, pDesc );
+                SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
+                          << " c: 3 - insert empty p: " << pTmp << " d: " << pDesc );
                 pTmp->Paste( pRoot, pPage );
                 pTmp->PreparePage( false );
                 pPage = pTmp;
@@ -1090,6 +1099,9 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra
             {
                 SwPageDesc *pOld = pPage->GetPageDesc();
                 pPage->SetPageDesc( pDesc, pFormatWish );
+                SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
+                          << " c: 4 - set desc + format p: " << pPage
+                          << " d: " << pDesc << " f: " << pFormatWish );
                 if ( bFootnotes )
                 {
                     // If specific values of the FootnoteInfo are changed, something has to happen.
@@ -1104,13 +1116,19 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra
             else if ( pFormatWish && pPage->GetFormat() != pFormatWish )         //5.
             {
                 pPage->SetFrameFormat( pFormatWish );
+                SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
+                          << " c: 5 - set format p: " << pPage << " f: " << pFormatWish );
             }
             else if ( !pFormatWish )                                       //6.
             {
                 // get format with inverted logic
                 pFormatWish = bWantOdd ? pDesc->GetLeftFormat() : pDesc->GetRightFormat();
                 if ( pFormatWish && pPage->GetFormat() != pFormatWish )
+                {
                     pPage->SetFrameFormat( pFormatWish );
+                    SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
+                              << " c: 6 - set format p: " << pPage << " f: " << pFormatWish );
+                }
             }
 #if OSL_DEBUG_LEVEL > 0
             else
@@ -1134,6 +1152,7 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra
                 if (ppPrev && *ppPrev == pPage)
                     bUpdatePrev = true;
                 SwFrame::DestroyFrame(pPage);
+                SAL_INFO( "sw.pageframe", "CheckPageDescs - handle bIsEmpty - destroy p: " << pPage );
                 if ( pStart == pPage )
                     pStart = pTmp;
                 pPage = pTmp;
@@ -1175,6 +1194,7 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra
         pPg = static_cast<SwPageFrame*>(pPg->GetNext());
     }
 #endif
+    SAL_INFO( "sw.pageframe", "CheckPageDescs out)" );
 }
 
 namespace
@@ -1193,7 +1213,14 @@ namespace
         SwPageFrame *pPage = new SwPageFrame(pFormat, pRoot, pDesc);
         SwPageFrame *pSibling = *pRefSibling;
         if ( pRefPage )
+        {
             *pRefPage = pPage;
+            SAL_INFO( "sw.pageframe", "doInsertPage p: " << pPage
+                                      << " d: " << pDesc << " f: " << pFormat );
+        }
+        else
+            SAL_INFO( "sw.pageframe", "doInsertPage - insert empty p: "
+                                      << pPage << " d: " << pDesc );
         pPage->Paste( pRoot, pSibling );
         pPage->PreparePage( bFootnote );
         // If the sibling has no body text, destroy it as long as it is no footnote page.
@@ -1268,8 +1295,12 @@ SwPageFrame *SwFrame::InsertPage( SwPageFrame *pPrevPage, bool bFootnote )
             {
                 const sal_uInt16 nNum = pImp->GetLayAction().GetCheckPageNum();
                 if ( nNum == pPrevPage->GetPhyPageNum() + 1 )
+                {
                     pImp->GetLayAction().SetCheckPageNumDirect(
                                                     pSibling->GetPhyPageNum() );
+                    SAL_INFO( "sw.pageframe", "InsertPage - SetCheckPageNumDirect: "
+                              << pSibling->GetPhyPageNum() );
+                }
                 return pPage;
             }
         }
@@ -1406,6 +1437,7 @@ void SwRootFrame::RemoveSuperfluous()
 
         if ( pPage )
         {
+            SAL_INFO( "sw.pageframe", "RemoveSuperfluous - DestroyFrm p: " << pPage );
             RemovePage( &pPage, SwRemoveResult::Prev );
             nDocPos = pPage ? pPage->Frame().Top() : 0;
         }
@@ -1469,11 +1501,27 @@ void SwRootFrame::AssertFlyPages()
             }
         }
     }
+
+#if OSL_DEBUG_LEVEL > 0
+    pPage = static_cast<SwPageFrame*>(Lower());
+    while ( pPage && pPage->GetNext() &&
+            !static_cast<SwPageFrame*>(pPage->GetNext())->IsFootnotePage() )
+    {
+        SAL_INFO( "sw.pageframe",  "AssertFlyPages p: " << pPage << " d: " << pPage->GetPageDesc()
+                   << " f: " << pPage->GetFormat() << " virt: " << pPage->GetVirtPageNum()
+                   << " phys: " << pPage->GetPhyPageNum() << " empty: " << pPage->IsEmptyPage() );
+        pPage = static_cast<SwPageFrame*>(pPage->GetNext());
+    }
+    SAL_INFO( "sw.pageframe", "AssertFlyPages p: " << pPage << " d: " << pPage->GetPageDesc()
+              << " f: " << pPage->GetFormat() << " virt: " << pPage->GetVirtPageNum()
+              << " phys: " << pPage->GetPhyPageNum() << " empty: " << pPage->IsEmptyPage() );
+#endif
 }
 
 /// Ensure that after the given page all page-bound objects are located on the correct page
 void SwRootFrame::AssertPageFlys( SwPageFrame *pPage )
 {
+    SAL_INFO( "sw.pageframe", "(AssertPageFlys in" );
     while ( pPage )
     {
         if (pPage->GetSortedObjs())
@@ -1488,6 +1536,7 @@ void SwRootFrame::AssertPageFlys( SwPageFrame *pPage )
                 if ((rAnch.GetAnchorId() == FLY_AT_PAGE) &&
                      nPg != pPage->GetPhyPageNum() )
                 {
+                    SAL_INFO( "sw.pageframe", nPg << " " << pPage->GetPhyPageNum() );
                     // If on the wrong page, check if previous page is empty
                     if( nPg && !(pPage->GetPhyPageNum()-1 == nPg &&
                         static_cast<SwPageFrame*>(pPage->GetPrev())->IsEmptyPage()) )
@@ -1511,6 +1560,7 @@ void SwRootFrame::AssertPageFlys( SwPageFrame *pPage )
         }
         pPage = static_cast<SwPageFrame*>(pPage->GetNext());
     }
+    SAL_INFO( "sw.pageframe", "AssertPageFlys out)" );
 }
 
 Size SwRootFrame::ChgSize( const Size& aNewSize )
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 6ac018b..76b6707 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1525,7 +1525,9 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
         pTargetDoc->SetAllUniqueFlyNames();
 
         // Unfreeze target document layouts and correct all PageDescs.
+        SAL_INFO( "sw.pageframe", "(MergeMailFiles pTargetShell->CalcLayout in" );
         pTargetShell->CalcLayout();
+        SAL_INFO( "sw.pageframe", "MergeMailFiles pTargetShell->CalcLayout out)" );
         for ( auto aLayout : pTargetShell->GetDoc()->GetAllLayouts() )
         {
             aLayout->FreezeLayout(false);
commit c364307df74d0746405f26c9bf286cf7910fe25c
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Aug 10 11:29:16 2016 +0200

    Don't oscillate empty pages in CheckPageDescs
    
    For the first case of dropping "wrong" empty pages,look ahead and
    pre-validate the next page, if it needs this empty page, to
    prevent case three for the next page.
    
    This prevents destruction and re-insert of the empty page.
    
    Change-Id: I475aa98a2693f814afcc41bd4bc73f04e742c105

diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx
index 3142e33..28477e9 100644
--- a/sw/source/core/layout/pagechg.cxx
+++ b/sw/source/core/layout/pagechg.cxx
@@ -1028,6 +1028,33 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra
             if ( bIsEmpty && ( pFormatWish ||          //1.
                  ( !bWantOdd && !pPrevPage ) ) )
             {
+                // Check all cases for the next page, so we don't oscillate empty pages
+                // Skip case 1 and 2, as we require a non-empty next page to save the empty page
+                // Case 3 is the one we actually want to predict and skip
+                // We can skip the empty check of case 3, as we just work on an existing next page
+                bool bNextWantOdd;
+                SwPageDesc *pNextDesc;
+                if ( pNextPage && !pNextPage->IsEmptyPage() &&    //3.
+                     pNextPage->OnRightPage() == (bNextWantOdd = pNextPage->WannaRightPage()) &&
+                     pNextPage->GetPageDesc() == (pNextDesc = pNextPage->FindPageDesc()) )   //4.
+                {
+                    bool bNextFirst = pNextPage->OnFirstPage();
+                    SwFrameFormat *pNextFormatWish = (bNextWantOdd) ?   //5.
+                        pNextDesc->GetRightFormat(bNextFirst) : pNextDesc->GetLeftFormat(bNextFirst);
+                    if ( !pNextFormatWish )    // 6.
+                        pNextFormatWish = bNextWantOdd ? pNextDesc->GetLeftFormat() : pNextDesc->GetRightFormat();
+                    if ( pNextFormatWish && pNextPage->GetFormat() == pNextFormatWish )
+                    {
+                        SAL_INFO( "sw.swpagefrm", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
+                                  << " c: 1+3 - skip next page of p: " << pPage );
+                        if (pPage->GetPageDesc() != pPrevPage->GetPageDesc())
+                            pPage->SetPageDesc( pPrevPage->GetPageDesc(), 0 );
+                        // We can skip the next page, as all checks were already done!
+                        pPage = static_cast<SwPageFrame*>(pNextPage->GetNext());
+                        continue;
+                    }
+                }
+
                 pPage->Cut();
                 bool bUpdatePrev = false;
                 if (ppPrev && *ppPrev == pPage)
commit 030d0ce8aa75f4f1a06fa0e88c6aadfaf6c9fd39
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Aug 10 11:23:23 2016 +0200

    Flush the page break for correct layouting
    
    This is a workaround to create correct SwPageFrm objects for
    layouting, so the page break is actually visible when
    copying nodes, so we create the correct SwPageFrm.
    
    This is especially problematic for mail merge after the fix in
    commit 60d34e1c840d2c317bb7d0a5b14f4602c22b3fcc, which -
    correctly - checks all later SwPageDesc for every fix done by
    CheckPageDescs().
    
    Change-Id: Ie6ea2e9a0587199be4dbaf3ed63a94c29b318ce2

diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index 94d4fcc..d140486 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -1067,6 +1067,13 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu
                 for (sw::mark::IMark* pMark : aSeenMarks)
                     pMarkAccess->repositionMark(pMark, aPaM);
             }
+
+            // Flush the page break, if we want to keep it
+            if ( !bDeletePrevious )
+            {
+                pTargetShell->EndAllAction();
+                pTargetShell->StartAllAction();
+            }
         }
     }
 #ifdef DBG_UTIL
commit 69155740812b4d4129df26f398ae59d659f1e1b1
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Aug 10 11:06:33 2016 +0200

    Use InsertPage in AssertFlyPages
    
    AssertFlyPages used its own code to insert pages. It had two
    flaws:
    
      1. It used the SwPageDesc of the previous page, unaware of
         changed page description of a new page, which would later
         be fixed by CheckPageDescs, eventually requiring re-layout.
    
      2. The Code has an of-by-one error when setting the initial
         bOdd, which would also insert wrong / inverse left and
         right pages.
    
    So this changes AssertFlyPages to use InsertPage, which has a
    little more overhead for inserts, but prevents later expensive
    corrections, especially when CheckPageDescs() inserts or removes
    "early" pages, which need to evaluate and move all page bound
    flys.
    
    Change-Id: I8806cebb26db60602d8438f117e0416e07228b3b

diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx
index b679cc6..3142e33 100644
--- a/sw/source/core/layout/pagechg.cxx
+++ b/sw/source/core/layout/pagechg.cxx
@@ -1422,29 +1422,9 @@ void SwRootFrame::AssertFlyPages()
 
     if ( nMaxPg > pPage->GetPhyPageNum() )
     {
-        // Continue pages based on the rules of the PageDesc after the last page.
-        bool bOdd = (pPage->GetPhyPageNum() % 2) != 0;
-        SwPageDesc *pDesc = pPage->GetPageDesc();
-        SwFrame *pSibling = pPage->GetNext();
-        for ( sal_uInt16 i = pPage->GetPhyPageNum(); i < nMaxPg; ++i  )
-        {
-            if ( !(bOdd ? pDesc->GetRightFormat() : pDesc->GetLeftFormat()) )
-            {
-                // Insert empty page (but Flys will be stored in the next page)
-                pPage = new SwPageFrame( pDoc->GetEmptyPageFormat(), this, pDesc );
-                pPage->Paste( this, pSibling );
-                pPage->PreparePage( false );
-                bOdd = !bOdd;
-                ++i;
-            }
-            pPage = new
-                    SwPageFrame( (bOdd ? pDesc->GetRightFormat() :
-                                       pDesc->GetLeftFormat()), this, pDesc );
-            pPage->Paste( this, pSibling );
-            pPage->PreparePage( false );
-            bOdd = !bOdd;
-            pDesc = pDesc->GetFollow();
-        }
+        for ( sal_uInt16 i = pPage->GetPhyPageNum(); i < nMaxPg; ++i )
+            pPage = InsertPage( pPage, false );
+
         // If the endnote pages are now corrupt, destroy them.
         if ( !pDoc->GetFootnoteIdxs().empty() )
         {
@@ -1455,7 +1435,7 @@ void SwRootFrame::AssertFlyPages()
             if ( pPage )
             {
                 SwPageDesc *pTmpDesc = pPage->FindPageDesc();
-                bOdd = pPage->OnRightPage();
+                bool bOdd = pPage->OnRightPage();
                 if ( pPage->GetFormat() !=
                      (bOdd ? pTmpDesc->GetRightFormat() : pTmpDesc->GetLeftFormat()) )
                     RemoveFootnotes( pPage, false, true );
commit 27a854d2a4055b0a9c13ce7c34c404b29423436b
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Aug 10 10:15:33 2016 +0200

    Refactor duplicated code in SwFrame::InsertPage
    
    Change-Id: Iff9a78cf2f5e6ded4d1b03a8303529aa324ddad9

diff --git a/sw/source/core/inc/rootfrm.hxx b/sw/source/core/inc/rootfrm.hxx
index 66dc0ec..078a838 100644
--- a/sw/source/core/inc/rootfrm.hxx
+++ b/sw/source/core/inc/rootfrm.hxx
@@ -58,6 +58,12 @@ namespace o3tl
     template<> struct typed_flags<SwInvalidateFlags> : is_typed_flags<SwInvalidateFlags, 0x7f> {};
 };
 
+enum class SwRemoveResult
+{
+    Next,
+    Prev
+};
+
 /// The root element of a Writer document layout.
 class SwRootFrame: public SwLayoutFrame
 {
@@ -385,6 +391,8 @@ public:
 
     bool IsLayoutFreezed() const { return mbLayoutFreezed; }
     void FreezeLayout( bool freeze ) { mbLayoutFreezed = freeze; }
+
+    void RemovePage( SwPageFrame **pDel, SwRemoveResult eResult );
 };
 
 inline long SwRootFrame::GetBrowseWidth() const
diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx
index 6375f8c..b679cc6 100644
--- a/sw/source/core/layout/pagechg.cxx
+++ b/sw/source/core/layout/pagechg.cxx
@@ -1158,6 +1158,27 @@ namespace
         const SwFrame* pBodyContent = pBody ? pBody->Lower() : nullptr;
         return pBodyContent && pBodyContent->IsDeleteForbidden();
     }
+
+    bool doInsertPage( SwRootFrame *pRoot, SwPageFrame **pRefSibling,
+                       SwFrameFormat *pFormat, SwPageDesc *pDesc,
+                       bool bFootnote, SwPageFrame **pRefPage )
+    {
+        SwPageFrame *pPage = new SwPageFrame(pFormat, pRoot, pDesc);
+        SwPageFrame *pSibling = *pRefSibling;
+        if ( pRefPage )
+            *pRefPage = pPage;
+        pPage->Paste( pRoot, pSibling );
+        pPage->PreparePage( bFootnote );
+        // If the sibling has no body text, destroy it as long as it is no footnote page.
+        if ( pSibling && !pSibling->IsFootnotePage() &&
+             !pSibling->FindFirstBodyContent() &&
+             (!pRefPage || !isDeleteForbidden(pSibling)) )
+        {
+            pRoot->RemovePage( pRefSibling, SwRemoveResult::Next ) ;
+            return false;
+        }
+        return true;
+    }
 }
 
 SwPageFrame *SwFrame::InsertPage( SwPageFrame *pPrevPage, bool bFootnote )
@@ -1197,44 +1218,16 @@ SwPageFrame *SwFrame::InsertPage( SwPageFrame *pPrevPage, bool bFootnote )
     // If there is no FrameFormat for this page, create an empty page.
     if( bWishedOdd != bNextOdd )
     {
-        SwFrameFormat *const pEmptyFormat = pDoc->GetEmptyPageFormat();
-        SwPageDesc *pTmpDesc = pPrevPage->GetPageDesc();
-        SwPageFrame *pPage = new SwPageFrame(pEmptyFormat, pRoot, pTmpDesc);
-        pPage->Paste( pRoot, pSibling );
-        pPage->PreparePage( bFootnote );
-        // If the sibling has no body text, destroy it as long as it is no footnote page.
-        if ( pSibling && !pSibling->IsFootnotePage() &&
-             !pSibling->FindFirstBodyContent() )
-        {
-            SwPageFrame *pDel = pSibling;
-            pSibling = static_cast<SwPageFrame*>(pSibling->GetNext());
-            if ( !pDoc->GetFootnoteIdxs().empty() )
-                pRoot->RemoveFootnotes( pDel, true );
-            pDel->Cut();
-            SwFrame::DestroyFrame(pDel);
-        }
-        else
+        if( doInsertPage( pRoot, &pSibling, pDoc->GetEmptyPageFormat(),
+                          pPrevPage->GetPageDesc(), bFootnote, nullptr ) )
             bCheckPages = true;
     }
     SwFrameFormat *const pFormat( (bWishedOdd)
             ? pDesc->GetRightFormat(bWishedFirst)
             : pDesc->GetLeftFormat(bWishedFirst) );
     assert(pFormat);
-    SwPageFrame *pPage = new SwPageFrame( pFormat, pRoot, pDesc );
-    pPage->Paste( pRoot, pSibling );
-    pPage->PreparePage( bFootnote );
-    // If the sibling has no body text, destroy it as long as it is no footnote page.
-    if ( pSibling && !pSibling->IsFootnotePage() &&
-         !pSibling->FindFirstBodyContent() && !isDeleteForbidden(pSibling) )
-    {
-        SwPageFrame *pDel = pSibling;
-        pSibling = static_cast<SwPageFrame*>(pSibling->GetNext());
-        if ( !pDoc->GetFootnoteIdxs().empty() )
-            pRoot->RemoveFootnotes( pDel, true );
-        pDel->Cut();
-        SwFrame::DestroyFrame(pDel);
-    }
-    else
+    SwPageFrame *pPage = nullptr;
+    if( doInsertPage( pRoot, &pSibling, pFormat, pDesc, bFootnote, &pPage ) )
         bCheckPages = true;
 
     if ( pSibling )
@@ -1304,6 +1297,17 @@ SwTwips SwRootFrame::ShrinkFrame( SwTwips nDist, bool bTst, bool )
     return nDist;
 }
 
+void SwRootFrame::RemovePage( SwPageFrame **pDelRef, SwRemoveResult eResult )
+{
+    SwPageFrame *pDel = *pDelRef;
+    (*pDelRef) = static_cast<SwPageFrame*>(
+        eResult == SwRemoveResult::Next ? pDel->GetNext() : pDel->GetPrev() );
+    if ( !GetFormat()->GetDoc()->GetFootnoteIdxs().empty() )
+        RemoveFootnotes( pDel, true );
+    pDel->Cut();
+    SwFrame::DestroyFrame( pDel );
+}
+
 /// remove pages that are not needed at all
 void SwRootFrame::RemoveSuperfluous()
 {
@@ -1375,12 +1379,7 @@ void SwRootFrame::RemoveSuperfluous()
 
         if ( pPage )
         {
-            SwPageFrame *pEmpty = pPage;
-            pPage = static_cast<SwPageFrame*>(pPage->GetPrev());
-            if ( !GetFormat()->GetDoc()->GetFootnoteIdxs().empty() )
-                RemoveFootnotes( pEmpty, true );
-            pEmpty->Cut();
-            SwFrame::DestroyFrame(pEmpty);
+            RemovePage( &pPage, SwRemoveResult::Prev );
             nDocPos = pPage ? pPage->Frame().Top() : 0;
         }
     } while ( pPage );
commit 5c6b303032331aef3beacd0659e2450d8fac85ad
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Aug 10 10:05:08 2016 +0200

    Fix some variable scopes and clarify names
    
    Helps understanding the code, especially CheckPageDescs().
    
    Change-Id: I53e7d0ea65d6c6ae3da98acba4d366a47d2c4210

diff --git a/sw/source/core/layout/flowfrm.cxx b/sw/source/core/layout/flowfrm.cxx
index f207a89..a28f36a 100644
--- a/sw/source/core/layout/flowfrm.cxx
+++ b/sw/source/core/layout/flowfrm.cxx
@@ -818,15 +818,15 @@ bool SwFrame::WrongPageDesc( SwPageFrame* pNew )
     // Way out of the situation: Try to preliminarily insert a
     // new page once (empty pages are already inserted by InsertPage()
     // if required)
-    const SwFormatPageDesc &rFormatDesc = GetAttrSet()->GetPageDesc();
 
     //My Pagedesc doesn't count if I'm a follow!
-    SwPageDesc *pDesc = nullptr;
+    const SwPageDesc *pDesc = nullptr;
     int nTmp = 0;
     SwFlowFrame *pFlow = SwFlowFrame::CastFlowFrame( this );
     if ( !pFlow || !pFlow->IsFollow() )
     {
-        pDesc = const_cast<SwPageDesc*>(rFormatDesc.GetPageDesc());
+        const SwFormatPageDesc &rFormatDesc = GetAttrSet()->GetPageDesc();
+        pDesc = rFormatDesc.GetPageDesc();
         if( pDesc )
         {
             if( !pDesc->GetRightFormat() )
diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx
index 7ea39752..6375f8c 100644
--- a/sw/source/core/layout/pagechg.cxx
+++ b/sw/source/core/layout/pagechg.cxx
@@ -990,19 +990,21 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra
         pPage = static_cast<SwPageFrame*>(pPage->GetPrev());
     while ( pPage )
     {
-        // obtain PageDesc and FrameFormat
+        SwPageFrame *pPrevPage = static_cast<SwPageFrame*>(pPage->GetPrev());
+        SwPageFrame *pNextPage = static_cast<SwPageFrame*>(pPage->GetNext());
+
         SwPageDesc *pDesc = pPage->FindPageDesc();
-        bool bCheckEmpty = pPage->IsEmptyPage();
-        bool bActOdd = pPage->OnRightPage();
-        bool bOdd = pPage->WannaRightPage();
+        bool bIsEmpty = pPage->IsEmptyPage();
+        bool bIsOdd = pPage->OnRightPage();
+        bool bWantOdd = pPage->WannaRightPage();
         bool bFirst = pPage->OnFirstPage();
-        SwFrameFormat *pFormatWish = (bOdd)
+        SwFrameFormat *pFormatWish = (bWantOdd)
             ? pDesc->GetRightFormat(bFirst) : pDesc->GetLeftFormat(bFirst);
 
-        if ( bActOdd != bOdd ||
+        if ( bIsOdd != bWantOdd ||
              pDesc != pPage->GetPageDesc() ||        // wrong Desc
-             ( pFormatWish != pPage->GetFormat()  &&       // wrong format and
-               ( !pPage->IsEmptyPage() || pFormatWish ) // not blank /empty
+             ( pFormatWish != pPage->GetFormat() &&       // wrong format and
+               ( !bIsEmpty || pFormatWish ) // not blank /empty
              )
            )
         {
@@ -1012,8 +1014,7 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra
 
             // invalidate the field, starting from here
             if ( nDocPos == LONG_MAX )
-                nDocPos = pPage->GetPrev() ?
-                            pPage->GetPrev()->Frame().Top() : pPage->Frame().Top();
+                nDocPos = pPrevPage ? pPrevPage->Frame().Top() : pPage->Frame().Top();
 
             // Cases:
             //  1. Empty page should be "normal" page -> remove empty page and take next one
@@ -1024,38 +1025,36 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra
             //  5. Normal page should have different format -> change
             //  6. No "wish" format provided -> take the "other" format (left/right) of the PageDesc
 
-            if ( pPage->IsEmptyPage() && ( pFormatWish ||          //1.
-                 ( !bOdd && !pPage->GetPrev() ) ) )
+            if ( bIsEmpty && ( pFormatWish ||          //1.
+                 ( !bWantOdd && !pPrevPage ) ) )
             {
-                SwPageFrame *pTmp = static_cast<SwPageFrame*>(pPage->GetNext());
                 pPage->Cut();
                 bool bUpdatePrev = false;
                 if (ppPrev && *ppPrev == pPage)
                     bUpdatePrev = true;
                 SwFrame::DestroyFrame(pPage);
                 if ( pStart == pPage )
-                    pStart = pTmp;
-                pPage = pTmp;
+                    pStart = pNextPage;
+                pPage = pNextPage;
                 if (bUpdatePrev)
-                    *ppPrev = pTmp;
+                    *ppPrev = pNextPage;
                 continue;
             }
-            else if ( pPage->IsEmptyPage() && !pFormatWish &&  //2.
+            else if ( bIsEmpty && !pFormatWish &&  //2.
                       pDesc != pPage->GetPageDesc() )
             {
                 pPage->SetPageDesc( pDesc, nullptr );
             }
-            else if ( !pPage->IsEmptyPage() &&      //3.
-                      bActOdd != bOdd &&
-                      ( ( !pPage->GetPrev() && !bOdd ) ||
-                        ( pPage->GetPrev() &&
-                          !static_cast<SwPageFrame*>(pPage->GetPrev())->IsEmptyPage() )
+            else if ( !bIsEmpty &&      //3.
+                      bIsOdd != bWantOdd &&
+                      ( ( !pPrevPage && !bWantOdd ) ||
+                        ( pPrevPage && !pPrevPage->IsEmptyPage() )
                       )
                     )
             {
-                if ( pPage->GetPrev() )
-                    pDesc = static_cast<SwPageFrame*>(pPage->GetPrev())->GetPageDesc();
-                SwPageFrame *pTmp = new SwPageFrame( pDoc->GetEmptyPageFormat(),pRoot,pDesc);
+                if ( pPrevPage )
+                    pDesc = pPrevPage->GetPageDesc();
+                SwPageFrame *pTmp = new SwPageFrame( pDoc->GetEmptyPageFormat(), pRoot, pDesc );
                 pTmp->Paste( pRoot, pPage );
                 pTmp->PreparePage( false );
                 pPage = pTmp;
@@ -1082,8 +1081,8 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra
             else if ( !pFormatWish )                                       //6.
             {
                 // get format with inverted logic
-                pFormatWish = bOdd ? pDesc->GetLeftFormat() : pDesc->GetRightFormat();
-                if ( pPage->GetFormat() != pFormatWish )
+                pFormatWish = bWantOdd ? pDesc->GetLeftFormat() : pDesc->GetRightFormat();
+                if ( pFormatWish && pPage->GetFormat() != pFormatWish )
                     pPage->SetFrameFormat( pFormatWish );
             }
 #if OSL_DEBUG_LEVEL > 0
@@ -1093,7 +1092,7 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra
             }
 #endif
         }
-        if ( bCheckEmpty )
+        if ( bIsEmpty )
         {
             // It also might be that an empty page is not needed at all.
             // However, the algorithm above cannot determine that. It is not needed if the following
commit ae6f4a18c6859228b7f6a08616b7b3a0c1bb0278
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Aug 10 09:47:40 2016 +0200

    Don't re-check valid SwPageDescs when layouting
    
    nCheckPageNum is set to USHRT_MAX, if all SwPageDesc were checked.
    Code manipulating SwPageFrm objects checks the pages via
    CheckPageDescs(). If this is currently forbidden, CheckPageDescs()
    sets nCheckPageNum to the first page to check.
    
    I guess the !pPage check is there to check the pages - at the end,
    if someone has missed the CheckPageDescs call. And we have to run
    the check, if the current page is unchecked AKA
      pPage->GetPhyPageNum() >= nCheckPageNum
    to do correct layouting.
    
    Change-Id: Ib67878115cde04b7161c919a67131a1e1dc67d8d

diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx
index a8d04af..f416426 100644
--- a/sw/source/core/layout/layact.cxx
+++ b/sw/source/core/layout/layact.cxx
@@ -454,7 +454,10 @@ void SwLayAction::InternalAction(OutputDevice* pRenderContext)
     sal_uInt16 nPercentPageNum = 0;
     while ( (pPage && !IsInterrupt()) || m_nCheckPageNum != USHRT_MAX )
     {
-        if (!pPage || (m_nCheckPageNum != USHRT_MAX && pPage->GetPhyPageNum() >= m_nCheckPageNum))
+        // nCheckPageNum is set to USHRT_MAX in this code path after we have
+        // checked the SwPageDescs and set tos the minimal changed SwPageDesc.
+        // We don't need to check the SwPageDescs without changes.
+        if ( (m_nCheckPageNum != USHRT_MAX) && (!pPage || pPage->GetPhyPageNum() >= m_nCheckPageNum) )
         {
             if ( !pPage || pPage->GetPhyPageNum() > m_nCheckPageNum )
             {
commit b1800c9c94a124ec0a88912928f6ed6ccfa94239
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Sat Jul 30 19:18:00 2016 +0200

    Use mpSchedulerData for delete and active handling
    
    We define an active task to have a Scheduler::mpSchedulerData
    pointer. And if the ImplSchedulerData::mpScheduler pointer is
    empty, we can delete the task when scheduling.
    
    This simplifies the scheduling handling.
    
    Change-Id: I7aaddea7f5171b66b7fa309363fc546f97dcb981

diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx
index 3abd37d..b65687f 100644
--- a/include/vcl/scheduler.hxx
+++ b/include/vcl/scheduler.hxx
@@ -43,7 +43,6 @@ protected:
     ImplSchedulerData*  mpSchedulerData;    /// Pointer to element in scheduler list
     const sal_Char     *mpDebugName;        /// Useful for debugging
     SchedulerPriority   mePriority;         /// Scheduler priority
-    bool                mbActive;           /// Currently in the scheduler
 
     // These should be constexpr static, when supported.
     static const sal_uInt64 ImmediateTimeoutMs = 1;
@@ -80,7 +79,7 @@ public:
     virtual void    Start();
     void            Stop();
 
-    bool            IsActive() const { return mbActive; }
+    inline bool     IsActive() const;
 
     Scheduler&      operator=( const Scheduler& rScheduler );
     static void ImplDeInitScheduler();
@@ -101,6 +100,11 @@ public:
     static bool GetDeterministicMode();
 };
 
+inline bool Scheduler::IsActive() const
+{
+    return nullptr != mpSchedulerData;
+}
+
 #endif // INCLUDED_VCL_SCHEDULER_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/solenv/gdb/libreoffice/vcl.py b/solenv/gdb/libreoffice/vcl.py
index 3f3dcf2..a9b3821 100644
--- a/solenv/gdb/libreoffice/vcl.py
+++ b/solenv/gdb/libreoffice/vcl.py
@@ -29,16 +29,15 @@ class ImplSchedulerDataPrinter(object):
                 sched_type = "Idle"
             else:
                 assert sched_type, "Scheduler object neither Timer nor Idle"
-            res = "{:7s}{:10s} active: {:6s}".format( sched_type, str(sched['mePriority']), str(sched['mbActive']) ) 
+            res = "{:7s}{:10s}".format( sched_type, str(sched['mePriority']) )
             name = sched['mpDebugName']
             if not name:
-                res = res + "   (scheduler debug name not set)"
+                res = "{}   (scheduler debug name not set) ({})".format(res, str(sched.dynamic_type))
             else:
                 res = "{} '{}' ({})".format(res, str(name.string()), str(sched.dynamic_type))
             return res
         else:
-            assert gdbobj['mbDelete'], "No scheduler set and not marked for deletion!"
-            return "(no scheduler)"
+            return "(no scheduler - to be deleted)"
 
     def to_string(self):
         return self.typename
@@ -60,7 +59,7 @@ class ImplSchedulerDataPrinter(object):
             return self
 
         def __next__(self):
-            if not self.value['mpNext']:
+            if not self.value:
                 raise StopIteration()
 
             pos = str(self.pos)
diff --git a/vcl/inc/saltimer.hxx b/vcl/inc/saltimer.hxx
index 9a71eac..fbd7ac3 100644
--- a/vcl/inc/saltimer.hxx
+++ b/vcl/inc/saltimer.hxx
@@ -63,7 +63,6 @@ struct ImplSchedulerData
 {
     ImplSchedulerData*  mpNext;        // Pointer to the next element in list
     Scheduler*          mpScheduler;   // Pointer to VCL Scheduler instance
-    bool                mbDelete;      // Destroy this scheduler?
     bool                mbInScheduler; // Scheduler currently processed?
     sal_uInt64          mnUpdateTime;  // Last Update Time
 
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 4dcbc4d..4273f79 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -31,18 +31,21 @@ void InitSystemTimer(ImplSVData* pSVData);
 
 void ImplSchedulerData::Invoke()
 {
-    if (mbDelete || mbInScheduler )
+    assert( mpScheduler && !mbInScheduler );
+    if ( !mpScheduler || mbInScheduler )
         return;
 
-    // prepare Scheduler Object for deletion after handling
-    mpScheduler->SetDeletionFlags();
-
     // tdf#92036 Reset the period to avoid re-firing immediately.
     mpScheduler->mpSchedulerData->mnUpdateTime = tools::Time::GetSystemTicks();
 
+    Scheduler *sched = mpScheduler;
+
+    // prepare Scheduler Object for deletion after handling
+    mpScheduler->SetDeletionFlags();
+
     // invoke it
     mbInScheduler = true;
-    mpScheduler->Invoke();
+    sched->Invoke();
     mbInScheduler = false;
 }
 
@@ -54,9 +57,7 @@ ImplSchedulerData *ImplSchedulerData::GetMostImportantTask( bool bTimerOnly )
     sal_uInt64 nTimeNow = tools::Time::GetSystemTicks();
     for ( ImplSchedulerData *pSchedulerData = pSVData->mpFirstSchedulerData; pSchedulerData; pSchedulerData = pSchedulerData->mpNext )
     {
-        if ( !pSchedulerData->mpScheduler || pSchedulerData->mbDelete ||
-             !pSchedulerData->mpScheduler->ReadyForSchedule( bTimerOnly, nTimeNow ) ||
-             !pSchedulerData->mpScheduler->IsActive())
+        if ( !pSchedulerData->mpScheduler || !pSchedulerData->mpScheduler->ReadyForSchedule( bTimerOnly, nTimeNow ) )
             continue;
         if (!pMostUrgent)
             pMostUrgent = pSchedulerData;
@@ -75,38 +76,32 @@ ImplSchedulerData *ImplSchedulerData::GetMostImportantTask( bool bTimerOnly )
 
 void Scheduler::SetDeletionFlags()
 {
-    mpSchedulerData->mbDelete = true;
-    mbActive = false;
+    assert( mpSchedulerData );
+    mpSchedulerData->mpScheduler = nullptr;
+    mpSchedulerData = nullptr;
 }
 
 void Scheduler::ImplDeInitScheduler()
 {
     ImplSVData*     pSVData = ImplGetSVData();
-    ImplSchedulerData*  pSchedulerData = pSVData->mpFirstSchedulerData;
     if (pSVData->mpSalTimer)
     {
         pSVData->mpSalTimer->Stop();
     }
 
-    if ( pSchedulerData )
+    ImplSchedulerData *pSchedulerData = pSVData->mpFirstSchedulerData;
+    while ( pSchedulerData )
     {
-        do
-        {
-            ImplSchedulerData* pTempSchedulerData = pSchedulerData;
-            if ( pSchedulerData->mpScheduler )
-            {
-                pSchedulerData->mpScheduler->mbActive = false;
-                pSchedulerData->mpScheduler->mpSchedulerData = nullptr;
-            }
-            pSchedulerData = pSchedulerData->mpNext;
-            delete pTempSchedulerData;
-        }
-        while ( pSchedulerData );
-
-        pSVData->mpFirstSchedulerData = nullptr;
-        pSVData->mnTimerPeriod = 0;
+        if ( pSchedulerData->mpScheduler )
+            pSchedulerData->mpScheduler->mpSchedulerData = nullptr;
+        ImplSchedulerData* pNextSchedulerData = pSchedulerData->mpNext;
+        delete pSchedulerData;
+        pSchedulerData = pNextSchedulerData;
     }
 
+    pSVData->mpFirstSchedulerData = nullptr;
+    pSVData->mnTimerPeriod        = 0;
+
     delete pSVData->mpSalTimer;
     pSVData->mpSalTimer = nullptr;
 }
@@ -211,7 +206,7 @@ sal_uInt64 Scheduler::CalculateMinimumTimeout( bool &bHasActiveIdles )
 
         // Should Task be released from scheduling?
         if ( !pSchedulerData->mbInScheduler &&
-              pSchedulerData->mbDelete )
+             !pSchedulerData->mpScheduler )
         {
             if ( pPrevSchedulerData )
                 pPrevSchedulerData->mpNext = pSchedulerData->mpNext;
@@ -275,9 +270,6 @@ void Scheduler::Start()
         return;
     }
 
-    // Mark timer active
-    mbActive = true;
-
     if ( !mpSchedulerData )
     {
         // insert Scheduler
@@ -299,16 +291,15 @@ void Scheduler::Start()
         else
             pSVData->mpFirstSchedulerData = mpSchedulerData;
     }
-    mpSchedulerData->mbDelete      = false;
     mpSchedulerData->mnUpdateTime  = tools::Time::GetSystemTicks();
 }
 
 void Scheduler::Stop()
 {
-    mbActive = false;
-
-    if ( mpSchedulerData )
-        mpSchedulerData->mbDelete = true;
+    if ( !mpSchedulerData )
+        return;
+    Scheduler::SetDeletionFlags();
+    assert( !mpSchedulerData );
 }
 
 Scheduler& Scheduler::operator=( const Scheduler& rScheduler )
@@ -316,7 +307,6 @@ Scheduler& Scheduler::operator=( const Scheduler& rScheduler )
     if ( IsActive() )
         Stop();
 
-    mbActive = false;
     mePriority = rScheduler.mePriority;
 
     if ( rScheduler.IsActive() )
@@ -328,16 +318,14 @@ Scheduler& Scheduler::operator=( const Scheduler& rScheduler )
 Scheduler::Scheduler(const sal_Char *pDebugName):
     mpSchedulerData(nullptr),
     mpDebugName(pDebugName),
-    mePriority(SchedulerPriority::HIGH),
-    mbActive(false)
+    mePriority(SchedulerPriority::HIGH)
 {
 }
 
 Scheduler::Scheduler( const Scheduler& rScheduler ):
     mpSchedulerData(nullptr),
     mpDebugName(rScheduler.mpDebugName),
-    mePriority(rScheduler.mePriority),
-    mbActive(false)
+    mePriority(rScheduler.mePriority)
 {
     if ( rScheduler.IsActive() )
         Start();
@@ -346,10 +334,7 @@ Scheduler::Scheduler( const Scheduler& rScheduler ):
 Scheduler::~Scheduler()
 {
     if ( mpSchedulerData )
-    {
-        mpSchedulerData->mbDelete = true;
         mpSchedulerData->mpScheduler = nullptr;
-    }
 }
 
 const char *ImplSchedulerData::GetDebugName() const
@@ -358,5 +343,4 @@ const char *ImplSchedulerData::GetDebugName() const
         mpScheduler->GetDebugName() : "unknown";
 }
 
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx
index 1766d7f..a435b33 100644
--- a/vcl/source/app/timer.cxx
+++ b/vcl/source/app/timer.cxx
@@ -25,10 +25,7 @@ void Timer::SetDeletionFlags()
 {
     // If no AutoTimer, then stop.
     if ( !mbAuto )
-    {
-        mpSchedulerData->mbDelete = true;
-        mbActive = false;
-    }
+        Scheduler::SetDeletionFlags();
 }
 
 bool Timer::ReadyForSchedule( bool /* bTimerOnly */, sal_uInt64 nTimeNow ) const
@@ -98,7 +95,7 @@ void Timer::SetTimeout( sal_uInt64 nNewTimeout )
 {
     mnTimeout = nNewTimeout;
     // If timer is active, then renew clock.
-    if ( mbActive )
+    if ( IsActive() )
     {
         Scheduler::ImplStartTimer(mnTimeout);
     }
commit f20a447dc30442bca9ac24acb6d2a4834114cebe
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Jul 20 10:54:30 2016 +0200

    tdf#97087 GDB pretty print the Scheduler task list
    
    In addition to the GDB pretty printer, this annotates a lot more
    Timers and Idles.
    
    Change-Id: I5b93fab02161b23bb753e65ef92643a04fb0789c

diff --git a/chart2/source/view/charttypes/GL3DBarChart.cxx b/chart2/source/view/charttypes/GL3DBarChart.cxx
index a10a06e..032bbd8 100644
--- a/chart2/source/view/charttypes/GL3DBarChart.cxx
+++ b/chart2/source/view/charttypes/GL3DBarChart.cxx
@@ -560,6 +560,7 @@ GL3DBarChart::GL3DBarChart(
         }
         maIdle.SetPriority(SchedulerPriority::REPAINT);
         maIdle.SetIdleHdl(LINK(this, GL3DBarChart, UpdateTimerHdl));
+        maIdle.SetDebugName( "charttypes::GL3DBarChart maIdle" );
         maIdle.Start();
         osl_getSystemTime(&maFPSRenderStartTime);
         osl_getSystemTime(&maFPSRenderEndTime);
diff --git a/cui/source/tabpages/macroass.cxx b/cui/source/tabpages/macroass.cxx
index 7972967..f230f54 100644
--- a/cui/source/tabpages/macroass.cxx
+++ b/cui/source/tabpages/macroass.cxx
@@ -136,6 +136,11 @@ SfxMacroTabPage::SfxMacroTabPage(vcl::Window* pParent, const Reference< XFrame >
     : SfxTabPage(pParent, "EventAssignPage", "cui/ui/eventassignpage.ui", &rAttrSet)
 {
     mpImpl.reset(new SfxMacroTabPage_Impl);
+
+    mpImpl->maFillGroupIdle.SetIdleHdl( LINK( this, SfxMacroTabPage, TimeOut_Impl ) );
+    mpImpl->maFillGroupIdle.SetPriority( SchedulerPriority::HIGHEST );
+    mpImpl->maFillGroupIdle.SetDebugName( "SfxMacroTabPage maFillGroupIdle" );
+
     mpImpl->sStrEvent = get<FixedText>("eventft")->GetText();
     mpImpl->sAssignedMacro = get<FixedText>("assignft")->GetText();
     get(mpImpl->pEventLB , "assignments");
@@ -154,7 +159,6 @@ SfxMacroTabPage::SfxMacroTabPage(vcl::Window* pParent, const Reference< XFrame >
     ScriptChanged();
 }
 
-
 SfxMacroTabPage::~SfxMacroTabPage()
 {
     disposeOnce();
@@ -208,12 +212,8 @@ bool SfxMacroTabPage::FillItemSet( SfxItemSet* rSet )
 
 void SfxMacroTabPage::LaunchFillGroup()
 {
-    if (!mpImpl->maFillGroupIdle.GetIdleHdl().IsSet())
-    {
-        mpImpl->maFillGroupIdle.SetIdleHdl( LINK( this, SfxMacroTabPage, TimeOut_Impl ) );
-        mpImpl->maFillGroupIdle.SetPriority( SchedulerPriority::HIGHEST );
+    if (! mpImpl->maFillGroupIdle.IsActive() )
         mpImpl->maFillGroupIdle.Start();
-    }
 }
 
 void SfxMacroTabPage::ActivatePage( const SfxItemSet& )
diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index 7628c7a..55426fe 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -523,6 +523,9 @@ Desktop::Desktop()
     , m_aBootstrapError(BE_OK)
     , m_aBootstrapStatus(BS_OK)
 {
+    m_firstRunTimer.SetTimeout(3000); // 3 sec.
+    m_firstRunTimer.SetTimeoutHdl(LINK(this, Desktop, AsyncInitFirstRun));
+    m_firstRunTimer.SetDebugName( "desktop::Desktop m_firstRunTimer" );
 }
 
 Desktop::~Desktop()
@@ -2577,8 +2580,6 @@ void Desktop::CheckFirstRun( )
     {
         // use VCL timer, which won't trigger during shutdown if the
         // application exits before timeout
-        m_firstRunTimer.SetTimeout(3000); // 3 sec.
-        m_firstRunTimer.SetTimeoutHdl(LINK(this, Desktop, AsyncInitFirstRun));
         m_firstRunTimer.Start();
 
 #ifdef _WIN32
diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
index dacc58b..8ffb4ba 100644
--- a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
+++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
@@ -71,6 +71,7 @@ namespace
         maUsedBuffers()
     {
         SetTimeout(10L * 1000L); // ten seconds
+        SetDebugName("drawinglayer::VDevBuffer via Invoke()");
     }
 
     VDevBuffer::~VDevBuffer()
diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx
index b54ce8f..a9e3c4f 100644
--- a/editeng/source/editeng/impedit2.cxx
+++ b/editeng/source/editeng/impedit2.cxx
@@ -146,12 +146,15 @@ ImpEditEngine::ImpEditEngine( EditEngine* pEE, SfxItemPool* pItemPool ) :
 
     aStatusTimer.SetTimeout( 200 );
     aStatusTimer.SetTimeoutHdl( LINK( this, ImpEditEngine, StatusTimerHdl ) );
+    aStatusTimer.SetDebugName( "editeng::ImpEditEngine aStatusTimer" );
 
     aIdleFormatter.SetPriority( SchedulerPriority::REPAINT );
     aIdleFormatter.SetIdleHdl( LINK( this, ImpEditEngine, IdleFormatHdl ) );
+    aIdleFormatter.SetDebugName( "editeng::ImpEditEngine aIdleFormatter" );
 
     aOnlineSpellTimer.SetTimeout( 100 );
     aOnlineSpellTimer.SetTimeoutHdl( LINK( this, ImpEditEngine, OnlineSpellHdl ) );
+    aOnlineSpellTimer.SetDebugName( "editeng::ImpEditEngine aOnlineSpellTimer" );
 
     // Access data already from here on!
     SetRefDevice( nullptr );
diff --git a/framework/source/layoutmanager/layoutmanager.cxx b/framework/source/layoutmanager/layoutmanager.cxx
index ead5fc8..17c106f 100644
--- a/framework/source/layoutmanager/layoutmanager.cxx
+++ b/framework/source/layoutmanager/layoutmanager.cxx
@@ -145,6 +145,7 @@ LayoutManager::LayoutManager( const Reference< XComponentContext >& xContext ) :
 
     m_aAsyncLayoutTimer.SetTimeout( 50 );
     m_aAsyncLayoutTimer.SetTimeoutHdl( LINK( this, LayoutManager, AsyncLayoutHdl ) );
+    m_aAsyncLayoutTimer.SetDebugName( "framework::LayoutManager m_aAsyncLayoutTimer" );
 
     registerProperty( LAYOUTMANAGER_PROPNAME_ASCII_AUTOMATICTOOLBARS, LAYOUTMANAGER_PROPHANDLE_AUTOMATICTOOLBARS, css::beans::PropertyAttribute::TRANSIENT, &m_bAutomaticToolbars, cppu::UnoType<decltype(m_bAutomaticToolbars)>::get() );
     registerProperty( LAYOUTMANAGER_PROPNAME_ASCII_HIDECURRENTUI, LAYOUTMANAGER_PROPHANDLE_HIDECURRENTUI, beans::PropertyAttribute::TRANSIENT, &m_bHideCurrentUI, cppu::UnoType<decltype(m_bHideCurrentUI)>::get() );
diff --git a/framework/source/services/autorecovery.cxx b/framework/source/services/autorecovery.cxx
index 40238c6..4002d74 100644
--- a/framework/source/services/autorecovery.cxx
+++ b/framework/source/services/autorecovery.cxx
@@ -1256,6 +1256,7 @@ AutoRecovery::AutoRecovery(const css::uno::Reference< css::uno::XComponentContex
     , m_nMinSpaceDocSave        (MIN_DISCSPACE_DOCSAVE                              )
     , m_nMinSpaceConfigSave     (MIN_DISCSPACE_CONFIGSAVE                           )
 {
+    m_aTimer.SetDebugName( "framework::AutoRecovery m_aTimer" );
 }
 
 void AutoRecovery::initListeners()
diff --git a/framework/source/uielement/menubarmanager.cxx b/framework/source/uielement/menubarmanager.cxx
index 560db80..1a547b91 100644
--- a/framework/source/uielement/menubarmanager.cxx
+++ b/framework/source/uielement/menubarmanager.cxx
@@ -135,6 +135,7 @@ MenuBarManager::MenuBarManager(
     , m_xURLTransformer(_xURLTransformer)
     , m_sIconTheme( SvtMiscOptions().GetIconTheme() )
 {
+    m_aAsyncSettingsTimer.SetDebugName( "framework::MenuBarManager::Deactivate m_aAsyncSettingsTimer" );
     m_xPopupMenuControllerFactory = frame::thePopupMenuControllerFactory::get(m_xContext);
     FillMenuManager( pMenu, rFrame, rDispatchProvider, rModuleIdentifier, bDelete, bDeleteChildren );
 }
@@ -158,6 +159,7 @@ MenuBarManager::MenuBarManager(
     , m_xURLTransformer(_xURLTransformer)
     , m_sIconTheme( SvtMiscOptions().GetIconTheme() )
 {
+    m_aAsyncSettingsTimer.SetDebugName( "framework::MenuBarManager::Deactivate m_aAsyncSettingsTimer" );
     Init(rFrame,pAddonMenu,bDelete,bDeleteChildren, popup);
 }
 
diff --git a/framework/source/uielement/toolbarmanager.cxx b/framework/source/uielement/toolbarmanager.cxx
index 68a3e00..1db2d56 100644
--- a/framework/source/uielement/toolbarmanager.cxx
+++ b/framework/source/uielement/toolbarmanager.cxx
@@ -185,6 +185,7 @@ ToolBarManager::ToolBarManager( const Reference< XComponentContext >& rxContext,
 
     m_aAsyncUpdateControllersTimer.SetTimeout( 50 );
     m_aAsyncUpdateControllersTimer.SetTimeoutHdl( LINK( this, ToolBarManager, AsyncUpdateControllersHdl ) );
+    m_aAsyncUpdateControllersTimer.SetDebugName( "framework::ToolBarManager m_aAsyncUpdateControllersTimer" );
 
     SvtMiscOptions().AddListenerLink( LINK( this, ToolBarManager, MiscOptionsChanged ) );
 }
diff --git a/include/vcl/dockwin.hxx b/include/vcl/dockwin.hxx
index c5e9d32..6ab145f 100644
--- a/include/vcl/dockwin.hxx
+++ b/include/vcl/dockwin.hxx
@@ -251,6 +251,8 @@ private:
                            DockingWindow & operator= (const DockingWindow &) = delete;
 
 protected:
+    SAL_DLLPRIVATE void    SetIdleDebugName( const sal_Char *pDebugName );
+
     using Window::ImplInit;
     SAL_DLLPRIVATE void    ImplInit( vcl::Window* pParent, WinBits nStyle );
     SAL_DLLPRIVATE void    ImplInitSettings();
@@ -368,6 +370,11 @@ inline void DockingWindow::SetFloatingPos( const Point& rNewPos )
         maFloatPos = rNewPos;
 }
 
+inline void DockingWindow::SetIdleDebugName( const sal_Char *pDebugName )
+{
+    maLayoutIdle.SetDebugName( pDebugName );
+}
+
 
 #endif // INCLUDED_VCL_DOCKWIN_HXX
 
diff --git a/include/vcl/syswin.hxx b/include/vcl/syswin.hxx
index 837a079..d9b355e 100644
--- a/include/vcl/syswin.hxx
+++ b/include/vcl/syswin.hxx
@@ -191,6 +191,8 @@ protected:
     virtual void settingOptimalLayoutSize(Window *pBox);
 
     SAL_DLLPRIVATE void DoInitialLayout();
+
+    SAL_DLLPRIVATE void SetIdleDebugName( const sal_Char *pDebugName );
 public:
     virtual         ~SystemWindow();
     virtual void    dispose() override;
@@ -293,6 +295,11 @@ public:
     virtual        void    doDeferredInit(WinBits nBits);
 };
 
+inline void SystemWindow::SetIdleDebugName( const sal_Char *pDebugName )
+{
+    maLayoutIdle.SetDebugName( pDebugName );
+}
+
 #endif // INCLUDED_VCL_SYSWIN_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/chartlis.hxx b/sc/inc/chartlis.hxx
index d66fb33..b1640c4 100644
--- a/sc/inc/chartlis.hxx
+++ b/sc/inc/chartlis.hxx
@@ -149,6 +149,9 @@ private:
 
     ScChartListenerCollection& operator=( const ScChartListenerCollection& ) = delete;
 
+protected:
+    void Init();
+
 public:
     ScChartListenerCollection( ScDocument* pDoc );
     ScChartListenerCollection( const ScChartListenerCollection& );
diff --git a/sc/source/core/tool/chartlis.cxx b/sc/source/core/tool/chartlis.cxx
index 52e761f..e170bd9 100644
--- a/sc/source/core/tool/chartlis.cxx
+++ b/sc/source/core/tool/chartlis.cxx
@@ -402,21 +402,26 @@ ScChartHiddenRangeListener::~ScChartHiddenRangeListener()
     // empty d'tor
 }
 
+void ScChartListenerCollection::Init()
+{
+    aIdle.SetIdleHdl( LINK( this, ScChartListenerCollection, TimerHdl ) );
+    aIdle.SetPriority( SchedulerPriority::REPAINT );
+    aIdle.SetDebugName( "sc::ScChartListenerCollection aIdle" );
+}
+
 ScChartListenerCollection::ScChartListenerCollection( ScDocument* pDocP ) :
     meModifiedDuringUpdate( SC_CLCUPDATE_NONE ),
-    aIdle( "sc ScChartListenerCollection" ),
     pDoc( pDocP )
 {
-    aIdle.SetIdleHdl( LINK( this, ScChartListenerCollection, TimerHdl ) );
+    Init();
 }
 
 ScChartListenerCollection::ScChartListenerCollection(
         const ScChartListenerCollection& rColl ) :
     meModifiedDuringUpdate( SC_CLCUPDATE_NONE ),
-    aIdle( "sc ScChartListenerCollection" ),
     pDoc( rColl.pDoc )
 {
-    aIdle.SetIdleHdl( LINK( this, ScChartListenerCollection, TimerHdl ) );
+    Init();
 }
 
 ScChartListenerCollection::~ScChartListenerCollection()
@@ -591,7 +596,6 @@ void ScChartListenerCollection::FreeUno( const uno::Reference< chart::XChartData
 
 void ScChartListenerCollection::StartTimer()
 {
-    aIdle.SetPriority( SchedulerPriority::REPAINT );
     aIdle.Start();
 }
 
diff --git a/sc/source/ui/app/scmod.cxx b/sc/source/ui/app/scmod.cxx
index ac5ddec..d06ed71 100644
--- a/sc/source/ui/app/scmod.cxx
+++ b/sc/source/ui/app/scmod.cxx
@@ -178,8 +178,11 @@ ScModule::ScModule( SfxObjectFactory* pFact ) :
 
     aSpellIdle.SetPriority(SchedulerPriority::LOWER);
     aSpellIdle.SetIdleHdl( LINK( this, ScModule, SpellTimerHdl ) );
+    aSpellIdle.SetDebugName( "sc::ScModule aSpellIdle" );
+
     aIdleTimer.SetTimeout(SC_IDLE_MIN);
     aIdleTimer.SetTimeoutHdl( LINK( this, ScModule, IdleHandler ) );
+    aIdleTimer.SetDebugName( "sc::ScModule aIdleTimer" );
     aIdleTimer.Start();
 
     pMessagePool = new ScMessagePool;
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index e2f100e..c0a5a06 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -1684,6 +1684,7 @@ ScExternalRefManager::ScExternalRefManager(ScDocument* pDoc) :
 {
     maSrcDocTimer.SetTimeoutHdl( LINK(this, ScExternalRefManager, TimeOutHdl) );
     maSrcDocTimer.SetTimeout(SRCDOC_SCAN_INTERVAL);
+    maSrcDocTimer.SetDebugName( "sc::ScExternalRefManager maSrcDocTimer" );
 }
 
 ScExternalRefManager::~ScExternalRefManager()
diff --git a/sc/source/ui/miscdlgs/acredlin.cxx b/sc/source/ui/miscdlgs/acredlin.cxx
index b5f5b79..55739df 100644
--- a/sc/source/ui/miscdlgs/acredlin.cxx
+++ b/sc/source/ui/miscdlgs/acredlin.cxx
@@ -116,6 +116,7 @@ ScAcceptChgDlg::ScAcceptChgDlg(SfxBindings* pB, SfxChildWindow* pCW, vcl::Window
     pTheView=pTPView->GetTableControl();
     aSelectionIdle.SetPriority(SchedulerPriority::LOW);
     aSelectionIdle.SetIdleHdl(LINK( this, ScAcceptChgDlg, UpdateSelectionHdl ));
+    aSelectionIdle.SetDebugName( "ScAcceptChgDlg  aSelectionIdle" );
 
     pTPFilter->SetReadyHdl(LINK( this, ScAcceptChgDlg, FilterHandle ));
     pTPFilter->SetRefHdl(LINK( this, ScAcceptChgDlg, RefHandle ));
diff --git a/sc/source/ui/miscdlgs/conflictsdlg.cxx b/sc/source/ui/miscdlgs/conflictsdlg.cxx
index 2d4e8cf..99abeb3 100644
--- a/sc/source/ui/miscdlgs/conflictsdlg.cxx
+++ b/sc/source/ui/miscdlgs/conflictsdlg.cxx
@@ -423,6 +423,7 @@ ScConflictsDlg::ScConflictsDlg( vcl::Window* pParent, ScViewData* pViewData, ScD
 
     maSelectionIdle.SetPriority( SchedulerPriority::LOW );
     maSelectionIdle.SetIdleHdl( LINK( this, ScConflictsDlg, UpdateSelectionHdl ) );
+    maSelectionIdle.SetDebugName( "ScConflictsDlg maSelectionIdle" );
 
     m_pLbConflicts->SetSelectHdl( LINK( this, ScConflictsDlg, SelectHandle ) );
     m_pLbConflicts->SetDeselectHdl( LINK( this, ScConflictsDlg, DeselectHandle ) );
diff --git a/sd/source/ui/dlg/brkdlg.cxx b/sd/source/ui/dlg/brkdlg.cxx
index bf87099..09631a2 100644
--- a/sd/source/ui/dlg/brkdlg.cxx
+++ b/sd/source/ui/dlg/brkdlg.cxx
@@ -45,9 +45,12 @@ BreakDlg::BreakDlg(
     sal_uLong nSumActionCount,
     sal_uLong nObjCount )
     : SfxModalDialog(pWindow, "BreakDialog", "modules/sdraw/ui/breakdialog.ui")
-    , aIdle("sd BreakDlg Idle")
     , mpProgress( nullptr )
 {
+    m_aUpdateIdle.SetPriority( SchedulerPriority::REPAINT );
+    m_aUpdateIdle.SetIdleHdl( LINK( this, BreakDlg, InitialUpdate ) );
+    m_aUpdateIdle.SetDebugName( "sd::BreakDlg m_aUpdateIdle" );
+
     get(m_pFiObjInfo, "metafiles");
     get(m_pFiActInfo, "metaobjects");
     get(m_pFiInsInfo, "drawingobjects");
@@ -155,9 +158,7 @@ IMPL_LINK_TYPED( BreakDlg, UpDate, void*, nInit, bool )
  */
 short BreakDlg::Execute()
 {
-  aIdle.SetPriority( SchedulerPriority::REPAINT );
-  aIdle.SetIdleHdl( LINK( this, BreakDlg, InitialUpdate ) );
-  aIdle.Start();
+  m_aUpdateIdle.Start();
 
   return SfxModalDialog::Execute();
 }
diff --git a/sd/source/ui/dlg/filedlg.cxx b/sd/source/ui/dlg/filedlg.cxx
index 94922ca..9ddb303 100644
--- a/sd/source/ui/dlg/filedlg.cxx
+++ b/sd/source/ui/dlg/filedlg.cxx
@@ -214,6 +214,7 @@ SdFileDialog_Imp::SdFileDialog_Imp( const short nDialogType ) :
     mbLabelPlaying(false)
 {
     maUpdateIdle.SetIdleHdl(LINK(this, SdFileDialog_Imp, IsMusicStoppedHdl));
+    maUpdateIdle.SetDebugName( "SdFileDialog_Imp maUpdateIdle" );
 
     css::uno::Reference < css::ui::dialogs::XFilePicker2 > xFileDlg = GetFilePicker();
 
diff --git a/sd/source/ui/inc/BreakDlg.hxx b/sd/source/ui/inc/BreakDlg.hxx
index 635abc7..137f523 100644
--- a/sd/source/ui/inc/BreakDlg.hxx
+++ b/sd/source/ui/inc/BreakDlg.hxx
@@ -67,7 +67,7 @@ private:
 
     bool            bCancel;
 
-    Idle            aIdle;
+    Idle            m_aUpdateIdle;
     SvdProgressInfo *pProgrInfo;
     SfxProgress     *mpProgress;
 
diff --git a/sfx2/source/appl/appcfg.cxx b/sfx2/source/appl/appcfg.cxx
index 65cabfe..65fb04c 100644
--- a/sfx2/source/appl/appcfg.cxx
+++ b/sfx2/source/appl/appcfg.cxx
@@ -112,6 +112,7 @@ SfxEventAsyncer_Impl::SfxEventAsyncer_Impl( const SfxEventHint& rHint )
     pIdle = new Idle("SfxEventASyncer");
     pIdle->SetIdleHdl( LINK(this, SfxEventAsyncer_Impl, IdleHdl) );
     pIdle->SetPriority( SchedulerPriority::HIGHEST );
+    pIdle->SetDebugName( "sfx::SfxEventAsyncer_Impl pIdle" );
     pIdle->Start();
 }
 
diff --git a/sfx2/source/control/bindings.cxx b/sfx2/source/control/bindings.cxx
index a068ab3..d3ad4d5 100644
--- a/sfx2/source/control/bindings.cxx
+++ b/sfx2/source/control/bindings.cxx
@@ -180,6 +180,7 @@ SfxBindings::SfxBindings()
     // create the list of caches
     pImpl->pCaches = new SfxStateCacheArr_Impl;
     pImpl->aTimer.SetTimeoutHdl( LINK(this, SfxBindings, NextJob) );
+    pImpl->aTimer.SetDebugName( "sfx::SfxBindings aTimer" );
 }
 
 
diff --git a/sfx2/source/control/dispatch.cxx b/sfx2/source/control/dispatch.cxx
index c959816..44e4b1e 100644
--- a/sfx2/source/control/dispatch.cxx
+++ b/sfx2/source/control/dispatch.cxx
@@ -455,6 +455,7 @@ void SfxDispatcher::Construct_Impl( SfxDispatcher* pParent )
 
     xImp->aIdle.SetPriority(SchedulerPriority::MEDIUM);
     xImp->aIdle.SetIdleHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
+    xImp->aIdle.SetDebugName( "sfx::SfxDispatcher_Impl aIdle" );
 }
 
 SfxDispatcher::SfxDispatcher( SfxDispatcher* pParent )
diff --git a/sfx2/source/dialog/dockwin.cxx b/sfx2/source/dialog/dockwin.cxx
index b9fb2c2..170e09c 100644
--- a/sfx2/source/dialog/dockwin.cxx
+++ b/sfx2/source/dialog/dockwin.cxx
@@ -828,8 +828,10 @@ SfxDockingWindow::SfxDockingWindow( SfxBindings *pBindinx, SfxChildWindow *pCW,
     pImpl->bNewLine = false;
     pImpl->SetDockAlignment(SfxChildAlignment::NOALIGNMENT);
     pImpl->SetLastAlignment(SfxChildAlignment::NOALIGNMENT);
+
     pImpl->aMoveIdle.SetPriority(SchedulerPriority::RESIZE);
     pImpl->aMoveIdle.SetIdleHdl(LINK(this,SfxDockingWindow,TimerHdl));
+    pImpl->aMoveIdle.SetDebugName( "sfx::SfxDockingWindow_Impl aMoveIdle" );
 }
 
 /** Constructor for the SfxDockingWindow class. A SfxChildWindow will be
diff --git a/solenv/bin/install-gdb-printers b/solenv/bin/install-gdb-printers
index 0362a5c..4d5be92 100755
--- a/solenv/bin/install-gdb-printers
+++ b/solenv/bin/install-gdb-printers
@@ -123,7 +123,7 @@ if [[ ${DESTDIR}${pythondir} != ${GDBDIR} ]]; then
 fi
 
 if [[ -n "${MERGELIBS}" ]]; then
-    make_autoload merged program libmergedlo."$DYLIB" merge svl tl basegfx
+    make_autoload merged program libmergedlo."$DYLIB" merge svl tl basegfx vcl
     make_autoload cppu program libuno_cppu."$DYLIB".3
     make_autoload sal program libuno_sal."$DYLIB".3
     make_autoload sw program libswlo."$DYLIB"
@@ -134,6 +134,7 @@ else
     make_autoload svl program libsvllo."$DYLIB"
     make_autoload sw program libswlo."$DYLIB"
     make_autoload tl program libtllo."$DYLIB"
+    make_autoload vcl program libvcllo."$DYLIB"
 fi
 make_autoload writerfilter program libwriterfilterlo."$DYLIB"
 
diff --git a/solenv/gdb/libreoffice/vcl.py b/solenv/gdb/libreoffice/vcl.py
new file mode 100644
index 0000000..3f3dcf2
--- /dev/null
+++ b/solenv/gdb/libreoffice/vcl.py
@@ -0,0 +1,90 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import six
+import gdb
+from libreoffice.util import printing
+
+class ImplSchedulerDataPrinter(object):
+    '''Prints ImplSchedulerData.'''
+
+    def __init__(self, typename, value):
+        self.typename = typename
+        self.value = value
+        self.timer_type_ptr = gdb.lookup_type("Timer").pointer()
+        self.idle_type_ptr = gdb.lookup_type("Idle").pointer()
+
+    def as_string(self, gdbobj):
+        if gdbobj['mpScheduler']:
+            sched = gdbobj['mpScheduler'].dereference()
+            if gdbobj['mpScheduler'].dynamic_cast( self.timer_type_ptr ):
+                sched_type = "Timer"
+            elif gdbobj['mpScheduler'].dynamic_cast( self.idle_type_ptr ):
+                sched_type = "Idle"
+            else:
+                assert sched_type, "Scheduler object neither Timer nor Idle"
+            res = "{:7s}{:10s} active: {:6s}".format( sched_type, str(sched['mePriority']), str(sched['mbActive']) ) 
+            name = sched['mpDebugName']
+            if not name:
+                res = res + "   (scheduler debug name not set)"
+            else:
+                res = "{} '{}' ({})".format(res, str(name.string()), str(sched.dynamic_type))
+            return res
+        else:
+            assert gdbobj['mbDelete'], "No scheduler set and not marked for deletion!"
+            return "(no scheduler)"
+
+    def to_string(self):
+        return self.typename
+
+    def children(self):
+        return self._iterator(self)
+
+    def display_hint(self):
+        return 'array'
+
+    class _iterator(six.Iterator):
+
+        def __init__(self, printer):
+            self.pos = 0
+            self.printer = printer
+            self.value = printer.value
+
+        def __iter__(self):
+            return self
+
+        def __next__(self):
+            if not self.value['mpNext']:
+                raise StopIteration()
+
+            pos = str(self.pos)
+            name = "\n  " + self.printer.as_string(self.value)
+            self.value = self.value['mpNext']
+            self.pos += 1
+
+            return (pos, name)
+
+printer = None
+
+def build_pretty_printers():
+    global printer
+
+    printer = printing.Printer("libreoffice/vcl")
+    printer.add('ImplSchedulerData', ImplSchedulerDataPrinter)
+
+def register_pretty_printers(obj):
+    printing.register_pretty_printer(printer, obj)
+
+build_pretty_printers()
+
+#for obj in gdb.objfiles():
+#    if obj.filename == '/home/glg/Development/libreoffice/branch-5-0/instdir/program/libvcllo.so':
+#        gdb.printing.register_pretty_printer( obj, printer, True )
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/svtools/source/contnr/imivctl1.cxx b/svtools/source/contnr/imivctl1.cxx
index 5050907..a3dca6b 100644
--- a/svtools/source/contnr/imivctl1.cxx
+++ b/svtools/source/contnr/imivctl1.cxx
@@ -58,7 +58,7 @@ class IcnViewEdit_Impl : public MultiLineEdit
     Link<LinkParamNone*,void> aCallBackHdl;
     Accelerator     aAccReturn;
     Accelerator     aAccEscape;
-    Idle            aIdle;
+    Idle            maLoseFocusIdle;
     bool            bCanceled;
     bool            bAlreadyInCallback;
     bool            bGrabFocus;
@@ -141,15 +141,23 @@ SvxIconChoiceCtrl_Impl::SvxIconChoiceCtrl_Impl(
 
     aEditIdle.SetPriority( SchedulerPriority::LOWEST );
     aEditIdle.SetIdleHdl(LINK(this,SvxIconChoiceCtrl_Impl,EditTimeoutHdl));
+    aEditIdle.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aEditIdle" );
+
     aAutoArrangeIdle.SetPriority( SchedulerPriority::LOW );
     aAutoArrangeIdle.SetIdleHdl(LINK(this,SvxIconChoiceCtrl_Impl,AutoArrangeHdl));
+    aAutoArrangeIdle.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aAutoArrangeIdle" );
+
     aCallSelectHdlIdle.SetPriority( SchedulerPriority::LOWEST );
     aCallSelectHdlIdle.SetIdleHdl( LINK(this,SvxIconChoiceCtrl_Impl,CallSelectHdlHdl));
+    aCallSelectHdlIdle.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aCallSelectHdlIdle" );
 
     aDocRectChangedIdle.SetPriority( SchedulerPriority::MEDIUM );
     aDocRectChangedIdle.SetIdleHdl(LINK(this,SvxIconChoiceCtrl_Impl,DocRectChangedHdl));
+    aDocRectChangedIdle.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aDocRectChangedIdle" );
+
     aVisRectChangedIdle.SetPriority( SchedulerPriority::MEDIUM );
     aVisRectChangedIdle.SetIdleHdl(LINK(this,SvxIconChoiceCtrl_Impl,VisRectChangedHdl));
+    aVisRectChangedIdle.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aVisRectChangedIdle" );
 
     Clear( true );
     Size gridSize(100,70);
@@ -3029,6 +3037,10 @@ IcnViewEdit_Impl::IcnViewEdit_Impl( SvtIconChoiceCtrl* pParent, const Point& rPo
     bAlreadyInCallback( false ),
     bGrabFocus( false )
 {
+    maLoseFocusIdle.SetPriority(SchedulerPriority::REPAINT);
+    maLoseFocusIdle.SetIdleHdl(LINK(this,IcnViewEdit_Impl,Timeout_Impl));
+    maLoseFocusIdle.SetDebugName( "svx::IcnViewEdit_Impl maLoseFocusIdle" );
+
     // FIXME: Outside of Paint Hierarchy
     vcl::Font aFont(pParent->GetPointFont(*this));
     aFont.SetTransparent( false );
@@ -3068,7 +3080,7 @@ void IcnViewEdit_Impl::dispose()
 
 void IcnViewEdit_Impl::CallCallBackHdl_Impl()
 {
-    aIdle.Stop();
+    maLoseFocusIdle.Stop();
     if ( !bAlreadyInCallback )
     {
         bAlreadyInCallback = true;
@@ -3130,9 +3142,7 @@ bool IcnViewEdit_Impl::PreNotify( NotifyEvent& rNEvt )
             ((!Application::GetFocusWindow()) || !IsChild(Application::GetFocusWindow())))
         {
             bCanceled = false;
-            aIdle.SetPriority(SchedulerPriority::REPAINT);
-            aIdle.SetIdleHdl(LINK(this,IcnViewEdit_Impl,Timeout_Impl));
-            aIdle.Start();
+            maLoseFocusIdle.Start();
         }
     }
     return false;
diff --git a/svtools/source/contnr/treelistbox.cxx b/svtools/source/contnr/treelistbox.cxx
index 14d1efc..8b5f235 100644
--- a/svtools/source/contnr/treelistbox.cxx
+++ b/svtools/source/contnr/treelistbox.cxx
@@ -201,6 +201,7 @@ void SvInplaceEdit2::LoseFocus()
         bCanceled = false;
         aIdle.SetPriority(SchedulerPriority::REPAINT);
         aIdle.SetIdleHdl(LINK(this,SvInplaceEdit2,Timeout_Impl));
+        aIdle.SetDebugName( "svtools::SvInplaceEdit2 aIdle" );
         aIdle.Start();
     }
 }
diff --git a/svtools/source/control/tabbar.cxx b/svtools/source/control/tabbar.cxx
index 5d6c352..47eef83 100644
--- a/svtools/source/control/tabbar.cxx
+++ b/svtools/source/control/tabbar.cxx
@@ -407,6 +407,9 @@ TabBarEdit::TabBarEdit( TabBar* pParent, WinBits nWinStyle ) :
     Edit( pParent, nWinStyle )
 {
     mbPostEvt = false;
+    maLoseFocusIdle.SetPriority( SchedulerPriority::REPAINT );
+    maLoseFocusIdle.SetIdleHdl( LINK( this, TabBarEdit, ImplEndTimerHdl ) );
+    maLoseFocusIdle.SetDebugName( "svtools::TabBarEdit maLoseFocusIdle" );
 }
 
 bool TabBarEdit::PreNotify( NotifyEvent& rNEvt )
@@ -460,8 +463,6 @@ IMPL_LINK_TYPED( TabBarEdit, ImplEndEditHdl, void*, pCancel, void )
     // when it shows the context menu or the insert symbol dialog
     if ( !HasFocus() && HasChildPathFocus( true ) )
     {
-        maLoseFocusIdle.SetPriority( SchedulerPriority::REPAINT );
-        maLoseFocusIdle.SetIdleHdl( LINK( this, TabBarEdit, ImplEndTimerHdl ) );
         maLoseFocusIdle.Start();
     }
     else
diff --git a/svtools/source/graphic/grfcache.cxx b/svtools/source/graphic/grfcache.cxx
index 43f4d07..5b64e32 100644
--- a/svtools/source/graphic/grfcache.cxx
+++ b/svtools/source/graphic/grfcache.cxx
@@ -826,7 +826,7 @@ void GraphicDisplayCacheEntry::Draw( OutputDevice* pOut, const Point& rPt, const
 }
 
 GraphicCache::GraphicCache( sal_uLong nDisplayCacheSize, sal_uLong nMaxObjDisplayCacheSize ) :
-    maReleaseTimer          ( "GraphicCache maReleaseTimer" ),
+    maReleaseTimer          ( "svtools::GraphicCache maReleaseTimer" ),
     mnReleaseTimeoutSeconds ( 0UL ),
     mnMaxDisplaySize        ( nDisplayCacheSize ),
     mnMaxObjDisplaySize     ( nMaxObjDisplayCacheSize ),
diff --git a/svtools/source/graphic/grfmgr.cxx b/svtools/source/graphic/grfmgr.cxx
index 42b2799..202185e 100644
--- a/svtools/source/graphic/grfmgr.cxx
+++ b/svtools/source/graphic/grfmgr.cxx
@@ -458,6 +458,7 @@ void GraphicObject::SetSwapStreamHdl(const Link<const GraphicObject*, SvStream*>
         {
             mpSwapOutTimer = new Timer("SwapOutTimer");
             mpSwapOutTimer->SetTimeoutHdl( LINK( this, GraphicObject, ImplAutoSwapOutHdl ) );
+            mpSwapOutTimer->SetDebugName( "svtools::GraphicObject mpSwapOutTimer" );
         }
 
         mpSwapOutTimer->SetTimeout( nSwapOutTimeout );
diff --git a/svx/source/form/fmshimp.cxx b/svx/source/form/fmshimp.cxx
index 16a8c76..8219719 100644
--- a/svx/source/form/fmshimp.cxx
+++ b/svx/source/form/fmshimp.cxx
@@ -639,6 +639,7 @@ FmXFormShell::FmXFormShell( FmFormShell& _rShell, SfxViewFrame* _pViewFrame )
 {
     m_aMarkTimer.SetTimeout(100);
     m_aMarkTimer.SetTimeoutHdl(LINK(this,FmXFormShell,OnTimeOut));
+    m_aMarkTimer.SetDebugName("svx::FmXFormShell m_aMarkTimer");
 
     m_xAttachedFrame = _pViewFrame->GetFrame().GetFrameInterface();
 
diff --git a/svx/source/sdr/overlay/overlaymanagerbuffered.cxx b/svx/source/sdr/overlay/overlaymanagerbuffered.cxx
index d5bb135..449130c 100644
--- a/svx/source/sdr/overlay/overlaymanagerbuffered.cxx
+++ b/svx/source/sdr/overlay/overlaymanagerbuffered.cxx
@@ -385,6 +385,7 @@ namespace sdr
             // Init timer
             maBufferIdle.SetPriority( SchedulerPriority::POST_PAINT );
             maBufferIdle.SetIdleHdl(LINK(this, OverlayManagerBuffered, ImpBufferTimerHandler));
+            maBufferIdle.SetDebugName( "sdr::overlay::OverlayManagerBuffered maBufferIdle" );
         }
 
         rtl::Reference<OverlayManager> OverlayManagerBuffered::create(
diff --git a/svx/source/sidebar/PanelLayout.cxx b/svx/source/sidebar/PanelLayout.cxx
index 9e04f33..5dfe290 100644
--- a/svx/source/sidebar/PanelLayout.cxx
+++ b/svx/source/sidebar/PanelLayout.cxx
@@ -25,8 +25,10 @@ PanelLayout::PanelLayout(vcl::Window* pParent, const OString& rID, const OUStrin
 {
     SetStyle(GetStyle() | WB_DIALOGCONTROL);
     m_pUIBuilder = new VclBuilder(this, getUIRootDir(), rUIXMLDescription, rID, rFrame);
+
     m_aPanelLayoutIdle.SetPriority(SchedulerPriority::RESIZE);
     m_aPanelLayoutIdle.SetIdleHdl( LINK( this, PanelLayout, ImplHandlePanelLayoutTimerHdl ) );
+    m_aPanelLayoutIdle.SetDebugName( "svx::PanelLayout  m_aPanelLayoutIdle" );
     if (GetSettings().GetStyleSettings().GetAutoMnemonic())
        Accelerator::GenerateAutoMnemonicsOnHierarchy(this);
 }
diff --git a/svx/source/svdraw/svdetc.cxx b/svx/source/svdraw/svdetc.cxx
index 3ee78e9..812021d 100644
--- a/svx/source/svdraw/svdetc.cxx
+++ b/svx/source/svdraw/svdetc.cxx
@@ -116,7 +116,7 @@ OLEObjCache::OLEObjCache()
     pTimer->SetTimeoutHdl(aLink);
     pTimer->SetTimeout(20000);
     pTimer->Start();
-    pTimer->SetDebugName("OLEObjCache pTimer UnloadCheck");
+    pTimer->SetDebugName("svx::OLEObjCache pTimer UnloadCheck");
 
     aLink.Call(pTimer);
 }
diff --git a/svx/source/svdraw/svdpntv.cxx b/svx/source/svdraw/svdpntv.cxx
index f9b2b19..2924573 100644
--- a/svx/source/svdraw/svdpntv.cxx
+++ b/svx/source/svdraw/svdpntv.cxx
@@ -180,6 +180,7 @@ void SdrPaintView::ImpClearVars()
     mnGraphicManagerDrawMode = GraphicManagerDrawFlags::STANDARD;
     maComeBackIdle.SetPriority(SchedulerPriority::REPAINT);
     maComeBackIdle.SetIdleHdl(LINK(this,SdrPaintView,ImpComeBackHdl));
+    maComeBackIdle.SetDebugName( "svx::SdrPaintView aComeBackIdle" );
 
     if (mpModel)
         SetDefaultStyleSheet(mpModel->GetDefaultStyleSheet(), true);
diff --git a/sw/source/core/doc/DocumentStatisticsManager.cxx b/sw/source/core/doc/DocumentStatisticsManager.cxx
index 51d398e..4e6f357 100644
--- a/sw/source/core/doc/DocumentStatisticsManager.cxx
+++ b/sw/source/core/doc/DocumentStatisticsManager.cxx
@@ -76,6 +76,7 @@ DocumentStatisticsManager::DocumentStatisticsManager( SwDoc& i_rSwdoc ) : m_rDoc
     maStatsUpdateTimer.SetTimeout( 1 );
     maStatsUpdateTimer.SetPriority( SchedulerPriority::LOWEST );
     maStatsUpdateTimer.SetTimeoutHdl( LINK( this, DocumentStatisticsManager, DoIdleStatsUpdate ) );
+    maStatsUpdateTimer.SetDebugName( "sw::DocumentStatisticsManager maStatsUpdateTimer" );
 }
 
 void DocumentStatisticsManager::DocInfoChgd(bool const isEnableSetModified)
diff --git a/sw/source/core/doc/DocumentTimerManager.cxx b/sw/source/core/doc/DocumentTimerManager.cxx
index 1a0fa08..5f0fceb 100644
--- a/sw/source/core/doc/DocumentTimerManager.cxx
+++ b/sw/source/core/doc/DocumentTimerManager.cxx
@@ -44,6 +44,7 @@ DocumentTimerManager::DocumentTimerManager( SwDoc& i_rSwdoc ) : m_rDoc( i_rSwdoc
 {
     maIdle.SetPriority( SchedulerPriority::LOWEST );
     maIdle.SetIdleHdl( LINK( this, DocumentTimerManager, DoIdleJobs) );
+    maIdle.SetDebugName( "sw::DocumentTimerManager maIdle" );
 }
 
 void DocumentTimerManager::StartIdling()
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index 3e162fd..94d4fcc 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -341,6 +341,7 @@ SwDoc::SwDoc()
 
     maOLEModifiedIdle.SetPriority( SchedulerPriority::LOWEST );
     maOLEModifiedIdle.SetIdleHdl( LINK( this, SwDoc, DoUpdateModifiedOLE ));
+    maOLEModifiedIdle.SetDebugName( "sw::SwDoc maOLEModifiedIdle" );
 
 #if HAVE_FEATURE_DBCONNECTIVITY
     // Create DBManager
diff --git a/sw/source/core/txtnode/SwGrammarContact.cxx b/sw/source/core/txtnode/SwGrammarContact.cxx
index 0f900d4..af8c460 100644
--- a/sw/source/core/txtnode/SwGrammarContact.cxx
+++ b/sw/source/core/txtnode/SwGrammarContact.cxx
@@ -63,6 +63,7 @@ SwGrammarContact::SwGrammarContact() : mpProxyList(nullptr), mbFinished( false )
 {
     aTimer.SetTimeout( 2000 );  // Repaint of grammar check after 'setChecked'
     aTimer.SetTimeoutHdl( LINK(this, SwGrammarContact, TimerRepaint) );
+    aTimer.SetDebugName( "sw::SwGrammarContact TimerRepaint" );
 }
 
 IMPL_LINK_TYPED( SwGrammarContact, TimerRepaint, Timer *, pTimer, void )
diff --git a/sw/source/core/unocore/unochart.cxx b/sw/source/core/unocore/unochart.cxx
index c180ebb..272aac9 100644
--- a/sw/source/core/unocore/unochart.cxx
+++ b/sw/source/core/unocore/unochart.cxx
@@ -91,6 +91,7 @@ SwChartLockController_Helper::SwChartLockController_Helper( SwDoc *pDocument ) :
 {
     aUnlockTimer.SetTimeout( 1500 );
     aUnlockTimer.SetTimeoutHdl( LINK( this, SwChartLockController_Helper, DoUnlockAllCharts ));
+    aUnlockTimer.SetDebugName( "sw::SwChartLockController_Helper aUnlockTimer" );
 }
 
 SwChartLockController_Helper::~SwChartLockController_Helper()
diff --git a/sw/source/uibase/misc/swruler.cxx b/sw/source/uibase/misc/swruler.cxx
index 5eabc7c..c04e94c 100644
--- a/sw/source/uibase/misc/swruler.cxx
+++ b/sw/source/uibase/misc/swruler.cxx
@@ -77,6 +77,7 @@ SwCommentRuler::SwCommentRuler( SwViewShell* pViewSh, vcl::Window* pParent, SwEd
     // Set fading timeout: 5 x 40ms = 200ms
     maFadeTimer.SetTimeout(40);
     maFadeTimer.SetTimeoutHdl( LINK( this, SwCommentRuler, FadeHandler ) );
+    maFadeTimer.SetDebugName( "sw::SwCommentRuler maFadeTimer" );
 }
 
 // Destructor
diff --git a/sw/source/uibase/uiview/view.cxx b/sw/source/uibase/uiview/view.cxx
index 2674f3e..9f8c37a 100644
--- a/sw/source/uibase/uiview/view.cxx
+++ b/sw/source/uibase/uiview/view.cxx
@@ -1004,6 +1004,7 @@ SwView::SwView( SfxViewFrame *_pFrame, SfxViewShell* pOldSh )
     }
 
     m_aTimer.SetTimeoutHdl(LINK(this, SwView, TimeoutHdl));
+    m_aTimer.SetDebugName( "sw::SwView m_aTimer" );
     m_bAttrChgNotified = m_bAttrChgNotifiedWithRegistrations = false;
     if (bOldModifyFlag)
         rDocSh.EnableSetModified();
diff --git a/vcl/source/app/help.cxx b/vcl/source/app/help.cxx
index 7a8bbc8..8f2109e 100644
--- a/vcl/source/app/help.cxx
+++ b/vcl/source/app/help.cxx
@@ -271,10 +271,14 @@ HelpTextWindow::HelpTextWindow( vcl::Window* pParent, const OUString& rText, sal
     if ( pSVData->maHelpData.mbSetKeyboardHelp )
         pSVData->maHelpData.mbKeyboardHelp = true;
 
-    const HelpSettings& rHelpSettings = pParent->GetSettings().GetHelpSettings();
+
     maShowTimer.SetTimeoutHdl( LINK( this, HelpTextWindow, TimerHdl ) );
-    maHideTimer.SetTimeoutHdl( LINK( this, HelpTextWindow, TimerHdl ) );
+    maShowTimer.SetDebugName( "vcl::HelpTextWindow maShowTimer" );
+
+    const HelpSettings& rHelpSettings = pParent->GetSettings().GetHelpSettings();
     maHideTimer.SetTimeout( rHelpSettings.GetTipTimeout() );
+    maHideTimer.SetTimeoutHdl( LINK( this, HelpTextWindow, TimerHdl ) );
+    maHideTimer.SetDebugName( "vcl::HelpTextWindow maHideTimer" );
 }
 
 void HelpTextWindow::StateChanged(StateChangedType nType)
diff --git a/vcl/source/control/edit.cxx b/vcl/source/control/edit.cxx
index d4d9936..28eab25 100644
--- a/vcl/source/control/edit.cxx
+++ b/vcl/source/control/edit.cxx
@@ -2404,6 +2404,7 @@ void Edit::EnableUpdateData( sal_uLong nTimeout )
         {
             mpUpdateDataTimer = new Timer("UpdateDataTimer");
             mpUpdateDataTimer->SetTimeoutHdl( LINK( this, Edit, ImplUpdateDataHdl ) );
+            mpUpdateDataTimer->SetDebugName( "vcl::Edit mpUpdateDataTimer" );
         }
 
         mpUpdateDataTimer->SetTimeout( nTimeout );
diff --git a/vcl/source/control/quickselectionengine.cxx b/vcl/source/control/quickselectionengine.cxx
index 146b48e..c394158 100644
--- a/vcl/source/control/quickselectionengine.cxx
+++ b/vcl/source/control/quickselectionengine.cxx
@@ -44,6 +44,7 @@ namespace vcl
         {
             aSearchTimeout.SetTimeout( 2500 );
             aSearchTimeout.SetTimeoutHdl( LINK( this, QuickSelectionEngine_Data, SearchStringTimeout ) );
+            aSearchTimeout.SetDebugName( "vcl::QuickSelectionEngine_Data aSearchTimeout" );
         }
 
         ~QuickSelectionEngine_Data()
diff --git a/vcl/source/control/scrbar.cxx b/vcl/source/control/scrbar.cxx
index b4abe08..aa82429 100644
--- a/vcl/source/control/scrbar.cxx
+++ b/vcl/source/control/scrbar.cxx
@@ -97,6 +97,7 @@ void ScrollBar::ImplInit( vcl::Window* pParent, WinBits nStyle )
     {
         mpData = new ImplScrollBarData;
         mpData->maTimer.SetTimeoutHdl( LINK( this, ScrollBar, ImplAutoTimerHdl ) );
+        mpData->maTimer.SetDebugName( "vcl::ScrollBar mpData->maTimer" );
         mpData->mbHide = false;
     }
 
diff --git a/vcl/source/edit/texteng.cxx b/vcl/source/edit/texteng.cxx
index c713557..13b78f9 100644
--- a/vcl/source/edit/texteng.cxx
+++ b/vcl/source/edit/texteng.cxx
@@ -93,6 +93,7 @@ TextEngine::TextEngine()
 
     mpIdleFormatter = new IdleFormatter;
     mpIdleFormatter->SetIdleHdl( LINK( this, TextEngine, IdleFormatHdl ) );
+    mpIdleFormatter->SetDebugName( "vcl::TextEngine mpIdleFormatter" );
 

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list