fdo#38837: Timers must end eventually [Writer idle timer]

Change-Id: I36c6c56d7277b9b3853b846c86c1f4dd47ebdb08
Signed-off-by: Luboš Luňák <l.lunak@suse.cz>
diff --git a/sw/inc/IDocumentTimerAccess.hxx b/sw/inc/IDocumentTimerAccess.hxx
index 84e3cd4..b2229f9 100644
--- a/sw/inc/IDocumentTimerAccess.hxx
+++ b/sw/inc/IDocumentTimerAccess.hxx
@@ -20,31 +20,41 @@
 #ifndef IDOCUMENTTIMERACCESS_HXX_INCLUDED
 #define IDOCUMENTTIMERACCESS_HXX_INCLUDED

 /** Get information about the current document state
 /** Manipulate background jobs of the document. It starts with a mode of
 'started' and a block count of 0.
 */
 class IDocumentTimerAccess
 {
 public:
    /**
    Set modus to start, i.e. start timer if block count == 0
    Set modus to 'start'.
    */
    virtual void StartIdling() = 0;

    /**
    Set modus to stopped, i.e. stop timer if running
    Set mode to 'stopped'.
    */
    virtual void StopIdling() = 0;

    /**
    Increment block count, stop timer if running
    Increment block count.
    */
    virtual void BlockIdling() = 0;

    /**
    Decrement block count, start timer if block count == 0 AND modus == start
    Decrement block count.
    */
    virtual void UnblockIdling() = 0;

    /**
    Do these jobs asynchronously: do grammar checking,
    do layout, and update fields.
    They will be delayed until mode is start AND block count == 0.
    The implementation might delay them further, for example
    it might wait until the application is idle.
    */
    virtual void StartBackgroundJobs() = 0;

 protected:
    virtual ~IDocumentTimerAccess() {};
 };
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index bfe2826..ef40d44 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -965,6 +965,7 @@ public:
    virtual void StopIdling();
    virtual void BlockIdling();
    virtual void UnblockIdling();
    virtual void StartBackgroundJobs();

    /** IDocumentChartDataProviderAccess
    */
diff --git a/sw/source/core/doc/docfld.cxx b/sw/source/core/doc/docfld.cxx
index 0fc9f44..3fe8a0b 100644
--- a/sw/source/core/doc/docfld.cxx
+++ b/sw/source/core/doc/docfld.cxx
@@ -2555,8 +2555,8 @@ void SwDocUpdtFld::RemoveFldType( const SwFieldType& rType )
    }
}

SwDocUpdtFld::SwDocUpdtFld()
    : pFldSortLst(0), nFldLstGetMode(0)
SwDocUpdtFld::SwDocUpdtFld(SwDoc* pDoc)
    : pFldSortLst(0), nFldLstGetMode(0), pDocument(pDoc)
{
    bInUpdateFlds = bFldsDirty = sal_False;
    memset( aFldTypeTable, 0, sizeof( aFldTypeTable ) );
diff --git a/sw/source/core/doc/doclay.cxx b/sw/source/core/doc/doclay.cxx
index f31c998..f73cc72 100644
--- a/sw/source/core/doc/doclay.cxx
+++ b/sw/source/core/doc/doclay.cxx
@@ -1817,6 +1817,11 @@ void SwDoc::UnblockIdling()
        aIdleTimer.Start();
}

void SwDoc::StartBackgroundJobs() {
    // Trigger DoIdleJobs(), asynchronously.
    aIdleTimer.Start();
}

/*************************************************************************
|*
|*  SwDoc::DoIdleJobs()
@@ -1839,8 +1844,7 @@ IMPL_LINK( SwDoc, DoIdleJobs, Timer *, pTimer )
        do {
            if( pSh->ActionPend() )
            {
                if( pTimer )
                    pTimer->Start();
                pTimer->Start();
                return 0;
            }
            pSh = (ViewShell*)pSh->GetNext();
@@ -1856,7 +1860,6 @@ IMPL_LINK( SwDoc, DoIdleJobs, Timer *, pTimer )
            if (bIsOnlineSpell && bIsAutoGrammar)
                StartGrammarChecking( *this );
        }
        SwFldUpdateFlags nFldUpdFlag;
        std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();//swmod 080320
        std::set<SwRootFrm*>::iterator pLayIter = aAllLayouts.begin();
        for ( ;pLayIter != aAllLayouts.end();++pLayIter )
@@ -1864,20 +1867,28 @@ IMPL_LINK( SwDoc, DoIdleJobs, Timer *, pTimer )
            if ((*pLayIter)->IsIdleFormat())
            {
                (*pLayIter)->GetCurrShell()->LayoutIdle();
                break;

                // Defer the remaining work.
                pTimer->Start();
                return 0;
            }
        }
        bool bAllValid = pLayIter == aAllLayouts.end() ? 1 : 0;
        if( bAllValid && ( AUTOUPD_FIELD_ONLY ==
                 ( nFldUpdFlag = getFieldUpdateFlags(true) )

        SwFldUpdateFlags nFldUpdFlag = getFieldUpdateFlags(true);
        if( ( AUTOUPD_FIELD_ONLY == nFldUpdFlag
                    || AUTOUPD_FIELD_AND_CHARTS == nFldUpdFlag ) &&
                GetUpdtFlds().IsFieldsDirty() &&
                !GetUpdtFlds().IsInUpdateFlds() &&
                !IsExpFldsLocked()
                GetUpdtFlds().IsFieldsDirty()
                // If we switch the field name the Fields are not updated.
                // So the "backgorund update" should always be carried out
                /* && !pStartSh->GetViewOptions()->IsFldName()*/ )
        {
            if ( GetUpdtFlds().IsInUpdateFlds() ||
                 IsExpFldsLocked() )
            {
                pTimer->Start();
                return 0;
            }

            //  Action brackets!
            GetUpdtFlds().SetInUpdateFlds( true );

@@ -1904,8 +1915,6 @@ IMPL_LINK( SwDoc, DoIdleJobs, Timer *, pTimer )
    if( pModLogFile && 1 != (long)pModLogFile )
        delete pModLogFile, ((long&)pModLogFile) = 1;
#endif
    if( pTimer )
        pTimer->Start();
    return 0;
}

diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index 730fe56..cb3bc9c 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -211,7 +211,7 @@ SwDoc::SwDoc()
    pDefTOXBases( new SwDefTOXBase_Impl() ),
    pCurrentView( 0 ),  //swmod 071225
    pDrawModel( 0 ),
    pUpdtFlds( new SwDocUpdtFld() ),
    pUpdtFlds( new SwDocUpdtFld( this ) ),
    pFldTypes( new SwFldTypes() ),
    pVirDev( 0 ),
    pPrt( 0 ),
diff --git a/sw/source/core/inc/docfld.hxx b/sw/source/core/inc/docfld.hxx
index 7e60b209..f30a366 100644
--- a/sw/source/core/inc/docfld.hxx
+++ b/sw/source/core/inc/docfld.hxx
@@ -21,6 +21,7 @@
#define _DOCFLD_HXX

#include <calc.hxx>
#include <doc.hxx>
#include <o3tl/sorted_vector.hxx>

class SwTxtFld;
@@ -146,6 +147,7 @@ class SwDocUpdtFld

    sal_uLong nNodes;               // if the node count is different
    sal_uInt8 nFldLstGetMode;
    SwDoc* pDocument;

    bool bInUpdateFlds : 1;     // currently there is an UpdateFlds
    bool bFldsDirty : 1;        // some fields are invalid
@@ -155,7 +157,7 @@ class SwDocUpdtFld
    void GetBodyNode( const SwSectionNode&);

public:
    SwDocUpdtFld();
    SwDocUpdtFld(SwDoc* pDocument);
    ~SwDocUpdtFld();

    const _SetGetExpFlds* GetSortLst() const { return pFldSortLst; }
@@ -171,7 +173,15 @@ public:
    void SetInUpdateFlds( bool b )      { bInUpdateFlds = b; }

    bool IsFieldsDirty() const          { return bFldsDirty; }
    void SetFieldsDirty( bool b )       { bFldsDirty = b; }
    void SetFieldsDirty( bool b )
    {
        bFldsDirty = b;

        if (b)
        {
            pDocument->StartBackgroundJobs();
        }
    }

    SwHash** GetFldTypeTable() const { return (SwHash**)aFldTypeTable; }
};
diff --git a/sw/source/core/inc/rootfrm.hxx b/sw/source/core/inc/rootfrm.hxx
index 7bc09d1..ad31308 100644
--- a/sw/source/core/inc/rootfrm.hxx
+++ b/sw/source/core/inc/rootfrm.hxx
@@ -20,6 +20,8 @@
#define SW_ROOTFRM_HXX

#include "layfrm.hxx"
#include <viewsh.hxx>
#include <doc.hxx>

class SwCntntFrm;
class ViewShell;
@@ -203,12 +205,33 @@ public:

    virtual Size ChgSize( const Size& aNewSize );

    void SetIdleFlags() { bIdleFormat = sal_True; }
    void SetIdleFlags()
    {
        bIdleFormat = sal_True;

        ViewShell* lcl_pCurrShell = GetCurrShell();
        // May be NULL if called from SfxBaseModel::dispose
        // (this happens in the build test 'rtfexport').
        if (lcl_pCurrShell != NULL)
            lcl_pCurrShell->GetDoc()->StartBackgroundJobs();
    }
    sal_Bool IsIdleFormat()  const { return bIdleFormat; }
    void ResetIdleFormat()     { bIdleFormat = sal_False; }

    bool IsNeedGrammarCheck() const         { return mbNeedGrammarCheck; }
    void SetNeedGrammarCheck( bool bVal )   { mbNeedGrammarCheck = bVal; }
    void SetNeedGrammarCheck( bool bVal )
    {
        mbNeedGrammarCheck = bVal;

        if ( bVal )
        {
            ViewShell* lcl_pCurrShell = GetCurrShell();
            // May be NULL if called from SfxBaseModel::dispose
            // (this happens in the build test 'rtfexport').
            if (lcl_pCurrShell != NULL)
                lcl_pCurrShell->GetDoc()->StartBackgroundJobs();
        }
    }

    //Sorgt dafuer, dass alle gewuenschten Seitengebunden Flys eine Seite finden
    void SetAssertFlyPages() { bAssertFlyPages = sal_True; }