[Libreoffice-commits] core.git: Branch 'private/jmux/scheduler-fixes' - 62 commits - basic/qa chart2/uiconfig compilerplugins/clang cui/source dbaccess/source drawinglayer/inc drawinglayer/source editeng/source extensions/source external/gpgme external/libepubgen filter/source forms/source framework/source hwpfilter/source icon-themes/sifr icon-themes/sifr_dark icon-themes/sifr_svg include/comphelper include/LibreOfficeKit include/oox include/rtl include/svtools include/svx include/vcl include/xmloff ios/LibreOfficeKit lingucomponent/Library_hyphen.mk lingucomponent/Library_lnth.mk lingucomponent/Library_MacOSXSpell.mk lingucomponent/Library_spell.mk lingucomponent/source lotuswordpro/inc lotuswordpro/Library_lwpft.mk lotuswordpro/source offapi/com officecfg/registry oox/inc oox/source scaddins/source sc/inc sc/qa sc/source sd/qa sd/source sfx2/source svl/source svtools/source svx/source sw/qa sw/source translations vcl/android vcl/headless vcl/inc vcl/osx vcl/qa vcl/README.scheduler vcl/source v cl/unx vcl/win writerfilter/source writerperfect/qa writerperfect/source xmloff/source xmlscript/source xmlsecurity/inc xmlsecurity/source

Jan-Marek Glogowski glogow at fbihome.de
Wed Oct 18 15:18:08 UTC 2017


Rebased ref, commits from common ancestor:
commit 5146a9bbbe394851a2fc1f56196a76df540ff03c
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Oct 17 13:13:23 2017 +0200

    Implement processing of (all) current LO tasks
    
    Processing all current events is currently just implemented for
    LO user events and system events, which is inconsistent. This
    implements the same functionality in the scheduler to process all
    current LO tasks.
    
    Currently used by DoYield in the Mac and Windows backends.
    
    This also fixes the testTriggerIdleFromIdle test, as this now
    correctly wait-yields until the watchdog kicks in.
    
    Change-Id: Icab8671ceae724a96959fa092ad00bff20c919e1

diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx
index ac429ed33b09..77396b90ae9c 100644
--- a/include/vcl/scheduler.hxx
+++ b/include/vcl/scheduler.hxx
@@ -43,16 +43,22 @@ class VCL_DLLPUBLIC Scheduler final
     static void Lock( sal_uInt32 nLockCount = 1 );
     static sal_uInt32 Unlock( bool bUnlockAll = false );
 
+    static bool ProcessSingleTask( sal_uInt64 nTime,
+                                   ImplSchedulerData ** const pLastDataPtr );
+
 public:
     static constexpr sal_uInt64 ImmediateTimeoutMs = 0;
     static constexpr sal_uInt64 InfiniteTimeoutMs  = SAL_MAX_UINT64;
 
     static void       ImplDeInitScheduler();
 
-    /// Process one pending Timer with highhest priority
-    static void       CallbackTaskScheduling();
-    /// Process one pending task ahead of time with highest priority.
-    static bool       ProcessTaskScheduling();
+    /**
+     * Process one or all current pending tasks, ranked by priority
+     *
+     * @param bHandleAllCurrentEvents process one or all pending tasks
+     * @return true, if any task was processed
+     */
+    static bool       ProcessTaskScheduling( bool bHandleAllCurrentEvents );
     /**
      * Process all events until none is pending
      *
diff --git a/sd/qa/unit/misc-tests.cxx b/sd/qa/unit/misc-tests.cxx
index 60be08f83c09..64890b02129f 100644
--- a/sd/qa/unit/misc-tests.cxx
+++ b/sd/qa/unit/misc-tests.cxx
@@ -105,7 +105,7 @@ sd::DrawDocShellRef SdMiscTest::Load(const OUString& rURL, sal_Int32 nFormat)
     for (int i = 0; i < 1000; i++)
     {
         // Process all Tasks - slide sorter is created here
-        while (Scheduler::ProcessTaskScheduling());
+        Scheduler::ProcessEventsToIdle();
         if ((pSSVS = sd::slidesorter::SlideSorterViewShell::GetSlideSorter(pViewShell->GetViewShellBase())) != nullptr)
             break;
         osl::Thread::wait(std::chrono::milliseconds(100));
@@ -149,7 +149,7 @@ void SdMiscTest::testTdf96708()
 
     // Now wait for timers to trigger creation of auto-layout
     osl::Thread::wait(std::chrono::milliseconds(100));
-    Scheduler::ProcessTaskScheduling();
+    Scheduler::ProcessEventsToIdle();
 
     rSSController.GetClipboard().DoPaste();
     const sal_uInt16 nMasterPageCnt2 = xDocSh->GetDoc()->GetMasterSdPageCount(PageKind::Standard);
diff --git a/vcl/README.scheduler b/vcl/README.scheduler
index 80c14b032c54..ed44b66f5753 100644
--- a/vcl/README.scheduler
+++ b/vcl/README.scheduler
@@ -105,11 +105,8 @@ bool DoYield( bool bWait, bool bAllCurrent )
     if ( !bAllCurrent && bWasEvent )
         return true;
     bWasEvent = ProcessSystemEvents( bAllCurrent, &bWasSchedulerEvent ) || bWasEvent;
-    if ( !bWasSchedulerEvent && IsSchedulerEvent() )
-    {
-        ProcessSchedulerEvent()
-        bWasEvent = true;
-    }
+    if ( (!bWasSchedulerEvent || bAllCurrent) && IsSchedulerEvent() )
+        bWasEvent = ProcessSchedulerEvent( bAllCurrent ) || bWasEvent;
     if ( !bWasEvent && bWait )
     {
         WaitForSystemEvents();
@@ -118,6 +115,11 @@ bool DoYield( bool bWait, bool bAllCurrent )
     return bWasEvent;
 }
 
+Since the Scheduler works priority based, processing all current events
+might return before all current tasks are processed, if the next task
+has a higher priority then a current task, but was started after the
+current time!
+
 == General: main thread deferral ==
 
 Currently for Mac and Windows, we run main thread deferrals by disabling the
diff --git a/vcl/android/androidinst.cxx b/vcl/android/androidinst.cxx
index 3c181ace2ff6..13ce4f83061f 100644
--- a/vcl/android/androidinst.cxx
+++ b/vcl/android/androidinst.cxx
@@ -69,7 +69,7 @@ AndroidSalInstance::~AndroidSalInstance()
 bool AndroidSalInstance::AnyInput( VclInputFlags nType )
 {
     if( nType & VclInputFlags::TIMER )
-        return CheckTimeout( false );
+        return HandleTimeout( HandleTimeoutMode::CheckOnly );
 
     // Unfortunately there is no way to check for a specific type of
     // input being queued. That information is too hidden, sigh.
diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx
index 44df78a7df60..478fcfd85c5e 100644
--- a/vcl/headless/svpinst.cxx
+++ b/vcl/headless/svpinst.cxx
@@ -164,7 +164,7 @@ void SvpSalInstance::Wakeup()
 #endif
 }
 
-bool SvpSalInstance::CheckTimeout( bool bExecuteTimers )
+bool SvpSalInstance::HandleTimeout( const HandleTimeoutMode eMode )
 {
     bool bRet = false;
     if( m_aTimeout.tv_sec ) // timer is started
@@ -174,7 +174,7 @@ bool SvpSalInstance::CheckTimeout( bool bExecuteTimers )
         if( aTimeOfDay >= m_aTimeout )
         {
             bRet = true;
-            if( bExecuteTimers )
+            if( eMode != HandleTimeoutMode::CheckOnly )
             {
                 // timed out, update timeout
                 m_aTimeout = aTimeOfDay;
@@ -183,9 +183,8 @@ bool SvpSalInstance::CheckTimeout( bool bExecuteTimers )
                 osl::Guard< comphelper::SolarMutex > aGuard( mpSalYieldMutex.get() );
 
                 // notify
-                ImplSVData* pSVData = ImplGetSVData();
-                if( pSVData->maSchedCtx.mpSalTimer )
-                    pSVData->maSchedCtx.mpSalTimer->CallCallback();
+                bRet = SalTimer::CallCallback(
+                    eMode == HandleTimeoutMode::ProcessAllCurrentTasks );
             }
         }
     }
@@ -269,7 +268,9 @@ bool SvpSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
     if ( !bHandleAllCurrentEvents &&bEvent )
         return true;
 
-    bEvent = CheckTimeout() || bEvent;
+    bEvent = HandleTimeout( bHandleAllCurrentEvents
+         ? HandleTimeoutMode::ProcessAllCurrentTasks
+         : HandleTimeoutMode::ProcessSingleTask ) || bEvent;
 
     if (bWait && ! bEvent )
     {
@@ -330,7 +331,7 @@ void SvpSalInstance::DoReleaseYield( int nTimeoutMS )
 bool SvpSalInstance::AnyInput( VclInputFlags nType )
 {
     if( nType & VclInputFlags::TIMER )
-        return CheckTimeout( false );
+        return HandleTimeout( HandleTimeoutMode::CheckOnly );
     return false;
 }
 
diff --git a/vcl/inc/headless/svpinst.hxx b/vcl/inc/headless/svpinst.hxx
index ba80960326dc..17ee24cd8107 100644
--- a/vcl/inc/headless/svpinst.hxx
+++ b/vcl/inc/headless/svpinst.hxx
@@ -85,7 +85,7 @@ public:
     inline void             registerFrame( SalFrame* pFrame );
     inline void             deregisterFrame( SalFrame* pFrame );
 
-    bool                    CheckTimeout( bool bExecuteTimers = true );
+    bool                    HandleTimeout( HandleTimeoutMode eMode );
 
     // Frame
     virtual SalFrame*       CreateChildFrame( SystemParentData* pParent, SalFrameStyleFlags nStyle ) override;
diff --git a/vcl/inc/osx/saldata.hxx b/vcl/inc/osx/saldata.hxx
index 357a2df6a74b..fea6d4908ea2 100644
--- a/vcl/inc/osx/saldata.hxx
+++ b/vcl/inc/osx/saldata.hxx
@@ -62,7 +62,6 @@ class SystemFontList;
 class SalData
 {
 public:
-    SALTIMERPROC                                  mpTimerProc;      // timer callback proc
     AquaSalInstance                              *mpInstance;
     std::list<AquaSalFrame*>                      maPresentationFrames;  // list of frames in presentation mode
     SalObject                                    *mpFirstObject;    // pointer of first object window
diff --git a/vcl/inc/osx/saltimer.h b/vcl/inc/osx/saltimer.h
index a9934f280636..97c8db397e9c 100644
--- a/vcl/inc/osx/saltimer.h
+++ b/vcl/inc/osx/saltimer.h
@@ -47,7 +47,7 @@ class AquaSalTimer final : public SalTimer, protected VersionedEvent
     bool        m_bDirectTimeout;    ///< timeout can be processed directly
 
     void queueDispatchTimerEvent( bool bAtStart );
-    void callTimerCallback();
+    bool callTimerCallback( bool bHandleAllCurrentEvents );
 
 public:
     AquaSalTimer();
@@ -58,7 +58,7 @@ public:
 
     void handleStartTimerEvent( NSEvent* pEvent );
     bool handleDispatchTimerEvent( NSEvent* pEvent );
-    void handleTimerElapsed();
+    bool handleTimerElapsed( bool bHandleAllCurrentEvents );
     void handleWindowShouldClose();
 
     bool IsTimerElapsed() const;
diff --git a/vcl/inc/saltimer.hxx b/vcl/inc/saltimer.hxx
index 983e0771ee9b..9fde8de82071 100644
--- a/vcl/inc/saltimer.hxx
+++ b/vcl/inc/saltimer.hxx
@@ -22,8 +22,9 @@
 
 #include <sal/config.h>
 #include <vcl/dllapi.h>
-#include <salwtype.hxx>
-#include <iostream>
+#include <svdata.hxx>
+
+typedef bool (*SALTIMERPROC)( bool bHandleAllCurrentEvents );
 
 /*
  * note: there will be only a single instance of SalTimer
@@ -40,19 +41,32 @@ public:
     virtual ~SalTimer() COVERITY_NOEXCEPT_FALSE;
 
     // AutoRepeat and Restart
-    virtual void            Start( sal_uLong nMS ) = 0;
-    virtual void            Stop() = 0;
+    virtual void Start( sal_uLong nMS ) = 0;
+    virtual void Stop() = 0;
 
     // Callbacks (indepen in \sv\source\app\timer.cxx)
-    void            SetCallback( SALTIMERPROC pProc )
+    void SetCallback( SALTIMERPROC pProc )
     {
         m_pProc = pProc;
     }
 
-    void            CallCallback()
+    bool Timeout( bool bHandleAllCurrentEvents )
     {
+        bool bRet = false;
         if( m_pProc )
-            m_pProc();
+            bRet = m_pProc( bHandleAllCurrentEvents );
+        return bRet;
+    }
+
+    static bool CallCallback( bool bHandleAllCurrentEvents )
+    {
+        ImplSVData* pSVData = ImplGetSVData();
+        bool bRet = false;
+        assert( pSVData );
+        SalTimer *pTimer = pSVData->maSchedCtx.mpSalTimer;
+        if( pTimer )
+            bRet = pTimer->Timeout( bHandleAllCurrentEvents );
+        return bRet;
     }
 };
 
diff --git a/vcl/inc/salwtype.hxx b/vcl/inc/salwtype.hxx
index 1538c8e78a25..e4eca95dcfe8 100644
--- a/vcl/inc/salwtype.hxx
+++ b/vcl/inc/salwtype.hxx
@@ -215,7 +215,8 @@ struct SalQueryCharPositionEvent
 
 typedef bool (*SALFRAMEPROC)( vcl::Window* pInst, SalEvent nEvent, const void* pEvent );
 
-enum class SalObjEvent {
+enum class SalObjEvent
+{
     GetFocus           = 1,
     LoseFocus          = 2,
     ToTop              = 3
@@ -258,7 +259,12 @@ struct SalLongPressEvent
     long mnY;
 };
 
-typedef void (*SALTIMERPROC)();
+enum class HandleTimeoutMode
+{
+    CheckOnly,
+    ProcessSingleTask,
+    ProcessAllCurrentTasks
+};
 
 #endif // INCLUDED_VCL_INC_SALWTYPE_HXX
 
diff --git a/vcl/inc/unx/saldata.hxx b/vcl/inc/unx/saldata.hxx
index 6a7902dbf444..753f6ce8973b 100644
--- a/vcl/inc/unx/saldata.hxx
+++ b/vcl/inc/unx/saldata.hxx
@@ -72,8 +72,6 @@ public:
 
     SalXLib*        GetLib() const { return pXLib_; }
 
-    static void             Timeout();
-
     // X errors
     virtual void            ErrorTrapPush() override;
     virtual bool            ErrorTrapPop( bool bIgnoreError = true ) override;
diff --git a/vcl/inc/unx/saldisp.hxx b/vcl/inc/unx/saldisp.hxx
index 54799149e25c..e8d0f7b67bb9 100644
--- a/vcl/inc/unx/saldisp.hxx
+++ b/vcl/inc/unx/saldisp.hxx
@@ -179,7 +179,7 @@ public:
     virtual void    StartTimer( sal_uLong nMS );
     virtual void    StopTimer();
 
-    virtual bool    CheckTimeout( bool bExecuteTimers = true );
+    virtual bool    HandleTimeout( HandleTimeoutMode eMode );
 
     SalI18N_InputMethod* GetInputMethod() const { return m_pInputMethod; }
     Display*             GetDisplay() const { return m_pDisplay; }
diff --git a/vcl/inc/win/saltimer.h b/vcl/inc/win/saltimer.h
index 61d284d82ddb..ec6b8faebd7a 100644
--- a/vcl/inc/win/saltimer.h
+++ b/vcl/inc/win/saltimer.h
@@ -43,7 +43,7 @@ class WinSalTimer final : public SalTimer, protected VersionedEvent
     void ImplStart( sal_uIntPtr nMS );
     void ImplStop();
     bool ImplHandleTimerEvent( WPARAM aWPARAM );
-    void ImplHandleElapsedTimer();
+    bool ImplHandleElapsedTimer( bool bHandleAllCurrentEvents );
     bool ImplHandle_WM_TIMER( WPARAM aWPARAM );
 
 public:
diff --git a/vcl/osx/saldata.cxx b/vcl/osx/saldata.cxx
index a445e5cfb7ad..b35210bc6754 100644
--- a/vcl/osx/saldata.cxx
+++ b/vcl/osx/saldata.cxx
@@ -36,7 +36,6 @@ static void SAL_CALL releasePool( void* pPool )
 
 SalData::SalData()
 :
-    mpTimerProc( nullptr ),
     mpInstance( nullptr ),
     mpFirstObject( nullptr ),
     mpFirstVD( nullptr ),
diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm
index c0d28fe4bc3f..5798f5b3e7a1 100644
--- a/vcl/osx/salframeview.mm
+++ b/vcl/osx/salframeview.mm
@@ -538,7 +538,7 @@ private:
         if ( bWasLiveResize != bIsLiveResize )
         {
             GetSalData()->mpInstance->mbIsLiveResize = bIsLiveResize;
-            Scheduler::ProcessTaskScheduling();
+            Scheduler::ProcessTaskScheduling( false );
         }
     }
 
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index 922046bcbfe8..8add64168bb3 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -603,11 +603,8 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
         while( true );
 
         AquaSalTimer *pTimer = static_cast<AquaSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
-        if ( !mbTimerProcessed && pTimer && pTimer->IsDirectTimeout() )
-        {
-            pTimer->handleTimerElapsed();
-            bHadEvent = true;
-        }
+        if ( (!mbTimerProcessed || bHandleAllCurrentEvents) && pTimer && pTimer->IsDirectTimeout() )
+            bHadEvent = pTimer->handleTimerElapsed( bHandleAllCurrentEvents ) || bHadEvent;
 
         // if we had no event yet, wait for one if requested
         if( bWait && ! bHadEvent )
diff --git a/vcl/osx/salnstimer.mm b/vcl/osx/salnstimer.mm
index 9647bb6b87c1..b21e6a7e9695 100644
--- a/vcl/osx/salnstimer.mm
+++ b/vcl/osx/salnstimer.mm
@@ -32,7 +32,7 @@
     (void) pNSTimer;
     AquaSalTimer *pTimer = static_cast<AquaSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
     if (pTimer)
-        pTimer->handleTimerElapsed();
+        pTimer->handleTimerElapsed( false );
 }
 
 @end
diff --git a/vcl/osx/saltimer.cxx b/vcl/osx/saltimer.cxx
index af18ae7ea740..60bf9a67e5e1 100644
--- a/vcl/osx/saltimer.cxx
+++ b/vcl/osx/saltimer.cxx
@@ -90,7 +90,10 @@ void AquaSalTimer::Start( sal_uLong nMS )
     }
 
     if ( 0 == nMS && !pSalData->mpInstance->mbIsLiveResize )
-        queueDispatchTimerEvent( NO );
+    {
+        Stop();
+        m_bDirectTimeout = true;
+    }
     else
     {
         NSTimeInterval aTI = double(nMS) / 1000.0;
@@ -136,32 +139,33 @@ void AquaSalTimer::Stop()
     InvalidateEvent();
 }
 
-void AquaSalTimer::callTimerCallback()
+bool AquaSalTimer::callTimerCallback( bool bHandleAllCurrentEvents )
 {
-    ImplSVData* pSVData = ImplGetSVData();
     SolarMutexGuard aGuard;
     m_bDirectTimeout = false;
-    if( pSVData->maSchedCtx.mpSalTimer )
-        pSVData->maSchedCtx.mpSalTimer->CallCallback();
+    return SalTimer::CallCallback( bHandleAllCurrentEvents );
 }
 
-void AquaSalTimer::handleTimerElapsed()
+bool AquaSalTimer::handleTimerElapsed( bool bHandleAllCurrentEvent )
 {
+    bool bRet = false;
+
     if ( m_bDirectTimeout || GetSalData()->mpInstance->mbIsLiveResize )
     {
-        // Stop the timer, as it is just invalidated after the firing function
-        Stop();
-        callTimerCallback();
-    }
-    else
-        queueDispatchTimerEvent( YES );
+         // Stop the timer, as it is just invalidated after the firing function
+         Stop();
+         bRet = callTimerCallback( bHandleAllCurrentEvent );
+     }
+     else
+         queueDispatchTimerEvent( YES );
+    return bRet;
 }
 
 bool AquaSalTimer::handleDispatchTimerEvent( NSEvent *pEvent )
 {
     bool bIsValidEvent = IsValidEventVersion( [pEvent data1] );
     if ( bIsValidEvent )
-        callTimerCallback();
+        callTimerCallback( false );
     return bIsValidEvent;
 }
 
diff --git a/vcl/qa/cppunit/lifecycle.cxx b/vcl/qa/cppunit/lifecycle.cxx
index 26f8796a57ea..18160ccdb056 100644
--- a/vcl/qa/cppunit/lifecycle.cxx
+++ b/vcl/qa/cppunit/lifecycle.cxx
@@ -212,7 +212,7 @@ void LifecycleTest::testFocus()
     xWin->Show();
     xChild->GrabFocus();
     // process asynchronous ToTop
-    Scheduler::ProcessTaskScheduling();
+    Scheduler::ProcessTaskScheduling( false );
     // FIXME: really awful to test focus issues without showing windows.
     // CPPUNIT_ASSERT(xChild->HasFocus());
 }
diff --git a/vcl/qa/cppunit/timer.cxx b/vcl/qa/cppunit/timer.cxx
index 7b712bd76c04..a94d44cb7a15 100644
--- a/vcl/qa/cppunit/timer.cxx
+++ b/vcl/qa/cppunit/timer.cxx
@@ -402,8 +402,10 @@ public:
     {
         Start();
         if (mpOther)
+        {
             mpOther->Start();
-        Application::Yield();
+            Application::Yield();
+        }
         if (mpTriggered)
             *mpTriggered = true;
     }
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 8fd26ec79a55..6c3059cedec1 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -236,7 +236,7 @@ void Scheduler::ImplStartTimer(sal_uInt64 nMS, bool bForce, sal_uInt64 nTime)
         rSchedCtx.mnTimerStart = 0;
         rSchedCtx.mnTimerPeriod = InfiniteTimeoutMs;
         rSchedCtx.mpSalTimer = pSVData->mpDefInst->CreateSalTimer();
-        rSchedCtx.mpSalTimer->SetCallback(Scheduler::CallbackTaskScheduling);
+        rSchedCtx.mpSalTimer->SetCallback( Scheduler::ProcessTaskScheduling );
     }
 
     assert(SAL_MAX_UINT64 - nMS >= nTime);
@@ -256,12 +256,6 @@ void Scheduler::ImplStartTimer(sal_uInt64 nMS, bool bForce, sal_uInt64 nTime)
     }
 }
 
-void Scheduler::CallbackTaskScheduling()
-{
-    // this function is for the saltimer callback
-    Scheduler::ProcessTaskScheduling();
-}
-
 static bool g_bDeterministicMode = false;
 
 void Scheduler::SetDeterministicMode(bool bDeterministic)
@@ -325,7 +319,8 @@ static inline ImplSchedulerData* DropSchedulerData(
     return pSchedulerDataNext;
 }
 
-bool Scheduler::ProcessTaskScheduling()
+bool Scheduler::ProcessSingleTask( const sal_uInt64 nTime,
+                                   ImplSchedulerData ** const pLastDataPtr )
 {
     ImplSVData *pSVData = ImplGetSVData();
     ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx;
@@ -336,25 +331,26 @@ bool Scheduler::ProcessTaskScheduling()
     if ( !rSchedCtx.mbActive || InfiniteTimeoutMs == rSchedCtx.mnTimerPeriod )
         return false;
 
-    sal_uInt64 nTime = tools::Time::GetSystemTicks();
     if ( nTime < rSchedCtx.mnTimerStart + rSchedCtx.mnTimerPeriod )
     {
-        SAL_WARN( "vcl.schedule", "we're too early - restart the timer!" );
+        SAL_WARN_IF( !pLastDataPtr,
+                     "vcl.schedule", "we're too early - restart the timer!" );
         UpdateSystemTimer( rSchedCtx,
                            rSchedCtx.mnTimerStart + rSchedCtx.mnTimerPeriod - nTime,
                            true, nTime );
         return false;
     }
 
-    ImplSchedulerData* pSchedulerData = nullptr;
+    ImplSchedulerData* pSchedulerData = rSchedCtx.mpFirstSchedulerData;
     ImplSchedulerData* pPrevSchedulerData = nullptr;
     ImplSchedulerData *pMostUrgent = nullptr;
     ImplSchedulerData *pPrevMostUrgent = nullptr;
     sal_uInt64         nMinPeriod = InfiniteTimeoutMs;
     sal_uInt64         nMostUrgentPeriod = InfiniteTimeoutMs;
     sal_uInt64         nReadyPeriod = InfiniteTimeoutMs;
+    bool               bAfterLastData = false;
+    bool               bInvokeMostUrgent = ( !pLastDataPtr || *pLastDataPtr );
 
-    pSchedulerData = rSchedCtx.mpFirstSchedulerData;
     while ( pSchedulerData )
     {
         const Timer *timer = dynamic_cast<Timer*>( pSchedulerData->mpTask );
@@ -386,6 +382,8 @@ bool Scheduler::ProcessTaskScheduling()
                     pSchedulerData->mpTask->mpSchedulerData = nullptr;
                 delete pSchedulerData;
             }
+            if ( pLastDataPtr && *pLastDataPtr == pSchedulerData )
+                bAfterLastData = true;
             pSchedulerData = pSchedulerDataNext;
             continue;
         }
@@ -404,11 +402,15 @@ bool Scheduler::ProcessTaskScheduling()
             pPrevMostUrgent = pPrevSchedulerData;
             pMostUrgent = pSchedulerData;
             nMostUrgentPeriod = nReadyPeriod;
+            if ( bAfterLastData || pMostUrgent->mnUpdateTime > nTime )
+                bInvokeMostUrgent = false;
         }
         else if ( nMinPeriod > nReadyPeriod )
             nMinPeriod = nReadyPeriod;
 
 next_entry:
+        if ( pLastDataPtr && *pLastDataPtr == pSchedulerData )
+            bAfterLastData = true;
         pPrevSchedulerData = pSchedulerData;
         pSchedulerData = pSchedulerData->mpNext;
     }
@@ -417,8 +419,19 @@ next_entry:
         SAL_INFO("vcl.schedule", "Calculated minimum timeout as " << nMinPeriod );
     UpdateSystemTimer( rSchedCtx, nMinPeriod, true, nTime );
 
-    if ( pMostUrgent )
+    if ( pMostUrgent && !bInvokeMostUrgent )
+    {
+        nReadyPeriod = pMostUrgent->mpTask->UpdateMinPeriod( nMinPeriod, nTime );
+        if ( nMinPeriod > nReadyPeriod )
+            nMinPeriod = nReadyPeriod;
+        UpdateSystemTimer( rSchedCtx, nMinPeriod, false, nTime );
+        pMostUrgent = nullptr;
+    }
+    else if ( pMostUrgent )
     {
+        if ( pLastDataPtr && *pLastDataPtr == pMostUrgent )
+            *pLastDataPtr = nullptr;
+
         SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
                   << pMostUrgent << "  invoke-in  " << *pMostUrgent->mpTask );
 
@@ -460,6 +473,8 @@ next_entry:
             AppendSchedulerData( rSchedCtx, pSchedulerData );
             UpdateSystemTimer( rSchedCtx, ImmediateTimeoutMs, true,
                                tools::Time::GetSystemTicks() );
+            if ( pLastDataPtr && *pLastDataPtr && rSchedCtx.mpLastSchedulerData != *pLastDataPtr )
+                *pLastDataPtr = rSchedCtx.mpLastSchedulerData;
         }
         else
         {
@@ -484,6 +499,26 @@ next_entry:
     return !!pMostUrgent;
 }
 
+bool Scheduler::ProcessTaskScheduling( bool bHandleAllCurrentEvents )
+{
+    sal_uInt64 nTime = tools::Time::GetSystemTicks();
+    bool bWasEvent = false, bAnyEvent = false;
+    ImplSchedulerData *pLastData = ImplGetSVData()->maSchedCtx.mpLastSchedulerData;
+    ImplSchedulerData ** const pLastDataPtr = bHandleAllCurrentEvents ? &pLastData : nullptr;
+    SAL_INFO_IF( bHandleAllCurrentEvents, "vcl.schedule", tools::Time::GetSystemTicks()
+        << " process all current events - start" );
+    do
+    {
+        bWasEvent = ProcessSingleTask( nTime, pLastDataPtr );
+        if ( !bAnyEvent && bWasEvent )
+            bAnyEvent = bWasEvent;
+    }
+    while ( bWasEvent && bHandleAllCurrentEvents );
+    SAL_INFO_IF( bHandleAllCurrentEvents, "vcl.schedule", tools::Time::GetSystemTicks()
+        << " process all current events - done" );
+    return bAnyEvent;
+}
+
 void Task::StartTimer( sal_uInt64 nMS )
 {
     Scheduler::ImplStartTimer( nMS, false, tools::Time::GetSystemTicks() );
diff --git a/vcl/unx/generic/app/saldata.cxx b/vcl/unx/generic/app/saldata.cxx
index 4ad2c02db54f..39bab4f7368f 100644
--- a/vcl/unx/generic/app/saldata.cxx
+++ b/vcl/unx/generic/app/saldata.cxx
@@ -560,13 +560,6 @@ void X11SalData::XError( Display *pDisplay, XErrorEvent *pEvent )
     m_aXErrorHandlerStack.back().m_bWas = true;
 }
 
-void X11SalData::Timeout()
-{
-    ImplSVData* pSVData = ImplGetSVData();
-    if( pSVData->maSchedCtx.mpSalTimer )
-        pSVData->maSchedCtx.mpSalTimer->CallCallback();
-}
-
 struct YieldEntry
 {
     int         fd;         // file descriptor for reading
@@ -622,7 +615,7 @@ void SalXLib::Remove( int nFD )
     }
 }
 
-bool SalXLib::CheckTimeout( bool bExecuteTimers )
+bool SalXLib::HandleTimeout( HandleTimeoutMode eMode )
 {
     bool bRet = false;
     if( m_aTimeout.tv_sec ) // timer is started
@@ -632,7 +625,7 @@ bool SalXLib::CheckTimeout( bool bExecuteTimers )
         if( aTimeOfDay >= m_aTimeout )
         {
             bRet = true;
-            if( bExecuteTimers )
+            if( eMode != HandleTimeoutMode::CheckOnly )
             {
                 // timed out, update timeout
                 m_aTimeout = aTimeOfDay;
@@ -644,7 +637,7 @@ bool SalXLib::CheckTimeout( bool bExecuteTimers )
                 */
                 m_aTimeout += m_nTimeoutMS;
                 // notify
-                X11SalData::Timeout();
+                bRet = SalTimer::CallCallback( eMode == HandleTimeoutMode::ProcessAllCurrentTasks );
             }
         }
     }
@@ -655,10 +648,7 @@ bool
 SalXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
 {
     // check for timeouts here if you want to make screenshots
-    static char* p_prioritize_timer = getenv ("SAL_HIGHPRIORITY_REPAINT");
     bool bHandledEvent = false;
-    if (p_prioritize_timer != nullptr)
-        bHandledEvent = CheckTimeout();
 
     const int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
 
@@ -724,8 +714,9 @@ SalXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
     }
 
     // usually handle timeouts here (as in 5.2)
-    if (p_prioritize_timer == nullptr)
-        bHandledEvent = CheckTimeout() || bHandledEvent;
+    bHandledEvent = HandleTimeout( bHandleAllCurrentEvents
+                  ? HandleTimeoutMode::ProcessAllCurrentTasks
+                  : HandleTimeoutMode::ProcessSingleTask ) || bHandledEvent;
 
     // handle wakeup events.
     if ((nFound > 0) && FD_ISSET(m_pTimeoutFDS[0], &ReadFDS))
diff --git a/vcl/unx/generic/app/salinst.cxx b/vcl/unx/generic/app/salinst.cxx
index 0d30e1d17a99..b1615b052e94 100644
--- a/vcl/unx/generic/app/salinst.cxx
+++ b/vcl/unx/generic/app/salinst.cxx
@@ -145,7 +145,8 @@ bool X11SalInstance::AnyInput(VclInputFlags nType)
     Display *pDisplay  = vcl_sal::getSalDisplay(pData)->GetDisplay();
     bool bRet = false;
 
-    if( (nType & VclInputFlags::TIMER) && (mpXLib && mpXLib->CheckTimeout(false)) )
+    if( (nType & VclInputFlags::TIMER)
+            && mpXLib && mpXLib->HandleTimeout( HandleTimeoutMode::CheckOnly ) )
         bRet = true;
 
     if( !bRet && XPending(pDisplay) )
diff --git a/vcl/unx/gtk/gtkdata.cxx b/vcl/unx/gtk/gtkdata.cxx
index 97541eed22c1..6f849f212eaa 100644
--- a/vcl/unx/gtk/gtkdata.cxx
+++ b/vcl/unx/gtk/gtkdata.cxx
@@ -728,9 +728,7 @@ extern "C" {
 
         sal_gtk_timeout_defer( pTSource );
 
-        ImplSVData* pSVData = ImplGetSVData();
-        if( pSVData->maSchedCtx.mpSalTimer )
-            pSVData->maSchedCtx.mpSalTimer->CallCallback();
+        SalTimer::CallCallback( false );
 
         return G_SOURCE_REMOVE;
     }
diff --git a/vcl/unx/gtk3/gtk3gtkdata.cxx b/vcl/unx/gtk3/gtk3gtkdata.cxx
index f4d41a53d2c0..bf69882d181f 100644
--- a/vcl/unx/gtk3/gtk3gtkdata.cxx
+++ b/vcl/unx/gtk3/gtk3gtkdata.cxx
@@ -693,9 +693,7 @@ extern "C" {
 
         sal_gtk_timeout_defer( pTSource );
 
-        ImplSVData* pSVData = ImplGetSVData();
-        if( pSVData->maSchedCtx.mpSalTimer )
-            pSVData->maSchedCtx.mpSalTimer->CallCallback();
+        SalTimer::CallCallback( false );
 
         return G_SOURCE_REMOVE;
     }
diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx
index 43e055a2c0bb..8be84f99a925 100644
--- a/vcl/unx/kde4/KDEXLib.cxx
+++ b/vcl/unx/kde4/KDEXLib.cxx
@@ -42,6 +42,8 @@
 
 #include "KDESalDisplay.hxx"
 
+#include <saltimer.hxx>
+
 #if KDE4_HAVE_GLIB
 #include "KDE4FilePicker.hxx"
 #include "tst_exclude_socket_notifiers.moc"
@@ -356,11 +358,11 @@ void KDEXLib::StopTimer()
     timeoutTimer.stop();
 }
 
-bool KDEXLib::CheckTimeout( bool bExecuteTimers )
+bool KDEXLib::HandleTimeout( HandleTimeoutMode eMode )
 {
     if( !m_isGlibEventLoopType )
-        return SalXLib::CheckTimeout( bExecuteTimers );
-    assert( !bExecuteTimers );
+        return SalXLib::HandleTimeout( eMode );
+    assert( eMode == HandleTimeoutMode::CheckOnly );
     return m_bTimedOut;
 }
 
@@ -376,7 +378,7 @@ void KDEXLib::customEvent(QEvent* e)
     if( e->type() == m_timerEventId )
     {
         m_bTimedOut = false;
-        X11SalData::Timeout();
+        SalTimer::CallCallback( false );
     }
 }
 
diff --git a/vcl/unx/kde4/KDEXLib.hxx b/vcl/unx/kde4/KDEXLib.hxx
index 452aae8b3286..e2d6d6b024fb 100644
--- a/vcl/unx/kde4/KDEXLib.hxx
+++ b/vcl/unx/kde4/KDEXLib.hxx
@@ -84,7 +84,7 @@ public:
         virtual void Remove( int fd ) override;
         virtual void StartTimer( sal_uLong nMS ) override;
         virtual void StopTimer() override;
-        virtual bool CheckTimeout( bool bExecuteTimers = true ) override;
+        virtual bool HandleTimeout( HandleTimeoutMode eMode ) override;
         virtual void Wakeup() override;
         void TriggerUserEventProcessing();
 
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index f2a998ee78e7..ceb3651b4353 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -512,11 +512,8 @@ bool ImplSalYield( bool bWait, bool bHandleAllCurrentEvents )
     // event loop with timeout messages.
     // We ensure we never handle more then one timeout per call.
     // This way we'll always process a normal system message.
-    if ( !bWasTimeoutMsg && pTimer && pTimer->IsDirectTimeout() )
-    {
-        pTimer->ImplHandleElapsedTimer();
-        bWasMsg = true;
-    }
+    if ( (!bWasTimeoutMsg || bHandleAllCurrentEvents) && pTimer && pTimer->IsDirectTimeout() )
+        bWasMsg = pTimer->ImplHandleElapsedTimer( bHandleAllCurrentEvents ) || bWasMsg;
 
     if ( bHandleAllCurrentEvents )
         nLastTicks = nCurTicks;
diff --git a/vcl/win/app/saltimer.cxx b/vcl/win/app/saltimer.cxx
index 9c67e841956e..2098e757d953 100644
--- a/vcl/win/app/saltimer.cxx
+++ b/vcl/win/app/saltimer.cxx
@@ -147,15 +147,16 @@ void CALLBACK SalTimerProc(PVOID data, BOOLEAN)
     }
 }
 
-void WinSalTimer::ImplHandleElapsedTimer()
+bool WinSalTimer::ImplHandleElapsedTimer( bool bHandleAllCurrentEvents )
 {
     // Test for MouseLeave
     SalTestMouseLeave();
 
     m_bDirectTimeout = false;
     ImplSalYieldMutexAcquireWithWait();
-    CallCallback();
+    bool bRet = Timeout( bHandleAllCurrentEvents );
     ImplSalYieldMutexRelease();
+    return bRet;
 }
 
 bool WinSalTimer::ImplHandleTimerEvent( const WPARAM aWPARAM )
@@ -163,9 +164,7 @@ bool WinSalTimer::ImplHandleTimerEvent( const WPARAM aWPARAM )
     assert( aWPARAM <= SAL_MAX_INT32 );
     if ( !IsValidEventVersion( static_cast<sal_Int32>( aWPARAM ) ) )
         return false;
-
-    ImplHandleElapsedTimer();
-    return true;
+    return ImplHandleElapsedTimer( false );
 }
 
 void WinSalTimer::SetForceRealTimer( const bool bVal )
@@ -185,9 +184,7 @@ bool WinSalTimer::ImplHandle_WM_TIMER( const WPARAM aWPARAM )
     assert( m_aWmTimerId == aWPARAM );
     if ( !(m_aWmTimerId == aWPARAM && m_bDirectTimeout && m_bForceRealTimer) )
         return false;
-
-    ImplHandleElapsedTimer();
-    return true;
+    return ImplHandleElapsedTimer( false );
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 5bb4ef1e062ab7b90f8550ebe93ca9730513c772
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 16 17:04:24 2017 +0200

    WIN scheduler cleanup and refactoring
    
    Replace a lot of duplicated case code with macros.
    Some minor constifications of function parameters.
    
    I restrained from shorten the SAL_MSG_* via preprocessor concat,
    so a grep will still find the whole names.
    
    Change-Id: If1f2477fc8817b4ae7816e807154e35004bb4da9

diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index 01e50af77b99..a80af4fb5ee7 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -63,6 +63,8 @@ public:
 
 class AquaSalInstance : public SalInstance, public SalUserEventList
 {
+    friend class AquaSalFrame;
+
     bool RunInMainYield( bool bHandleAllCurrentEvents );
 
     virtual void TriggerUserEventProcessing() override;
@@ -81,7 +83,6 @@ public:
 
     static std::list<const ApplicationEvent*> aAppEventList;
 
-public:
     AquaSalInstance();
     virtual ~AquaSalInstance() override;
 
@@ -136,9 +137,6 @@ public:
     // this is needed to avoid duplicate open events through a) command line and b) NSApp's openFile
     static bool isOnCommandLine( const OUString& );
 
-public:
-    friend class AquaSalFrame;
-
     void delayedSettingsChanged( bool bInvalidate );
 
     // Is this the NSAppThread?
diff --git a/vcl/inc/win/saldata.hxx b/vcl/inc/win/saldata.hxx
index 0f3e05b8f31a..659fd68f7dda 100644
--- a/vcl/inc/win/saldata.hxx
+++ b/vcl/inc/win/saldata.hxx
@@ -180,8 +180,8 @@ bool ImplHandleSalObjSysCharMsg( HWND hWnd, WPARAM wParam, LPARAM lParam );
 bool ImplHandleGlobalMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT& rlResult );
 
 WinSalObject* ImplFindSalObject( HWND hWndChild );
-bool ImplSalPreDispatchMsg( MSG* pMsg );
-void ImplSalPostDispatchMsg( MSG* pMsg, LRESULT nDispatchResult );
+bool ImplSalPreDispatchMsg( const MSG* pMsg );
+void ImplSalPostDispatchMsg( const MSG* pMsg );
 
 void ImplSalLogFontToFontW( HDC hDC, const LOGFONTW& rLogFont, vcl::Font& rFont );
 
diff --git a/vcl/inc/win/saltimer.h b/vcl/inc/win/saltimer.h
index b7d1a1e0d0f1..61d284d82ddb 100644
--- a/vcl/inc/win/saltimer.h
+++ b/vcl/inc/win/saltimer.h
@@ -25,7 +25,7 @@
 class WinSalTimer final : public SalTimer, protected VersionedEvent
 {
     // for access to Impl* functions
-    friend LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef );
+    friend LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, bool& rDef );
     // for access to GetNextVersionedEvent
     friend void CALLBACK SalTimerProc( PVOID data, BOOLEAN );
     // for access to ImplHandleElapsedTimer
diff --git a/vcl/osx/vclnsapp.mm b/vcl/osx/vclnsapp.mm
index 4dd8ceac8169..23b22c360eeb 100644
--- a/vcl/osx/vclnsapp.mm
+++ b/vcl/osx/vclnsapp.mm
@@ -66,7 +66,7 @@ SAL_WNODEPRECATED_DECLARATIONS_PUSH
     NSEvent* pEvent = [NSEvent otherEventWithType: NSApplicationDefined
                                location: NSZeroPoint
                                modifierFlags: 0
-                               timestamp: 0
+                               timestamp: [[NSProcessInfo processInfo] systemUptime]
                                windowNumber: 0
                                context: nil
                                subtype: AquaSalInstance::AppExecuteSVMain
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index 5fcca5cde5b4..f2a998ee78e7 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -569,124 +569,108 @@ bool WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
     return bDidWork;
 }
 
-LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
+#define CASE_NOYIELDLOCK( salmsg, function ) \
+    case salmsg: \
+        assert( !pInst->mbNoYieldLock ); \
+        pInst->mbNoYieldLock = true; \
+        function; \
+        pInst->mbNoYieldLock = false; \
+        break;
+
+#define CASE_NOYIELDLOCK_RESULT( salmsg, function ) \
+    case salmsg: \
+        assert( !pInst->mbNoYieldLock ); \
+        pInst->mbNoYieldLock = true; \
+        nRet = reinterpret_cast<LRESULT>( function ); \
+        pInst->mbNoYieldLock = false; \
+        break;
+
+LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, bool& rDef )
 {
     LRESULT nRet = 0;
     WinSalInstance *pInst = GetSalData()->mpInstance;
+    WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
 
     switch ( nMsg )
     {
         case SAL_MSG_THREADYIELD:
             assert( !(bool)wParam );
-            nRet = static_cast<LRESULT>(ImplSalYield( false, (bool)lParam ));
-            rDef = FALSE;
+            nRet = static_cast<LRESULT>(ImplSalYield(
+                false, static_cast<bool>( lParam ) ));
             break;
+
         case SAL_MSG_STARTTIMER:
         {
             sal_uInt64 nTime = tools::Time::GetSystemTicks();
-            if ( nTime < (sal_uInt64) lParam )
-                nTime = (sal_uInt64) lParam - nTime;
+            if ( nTime < static_cast<sal_uInt64>( lParam ) )
+                nTime = static_cast<sal_uInt64>( lParam ) - nTime;
             else
                 nTime = 0;
-            static_cast<WinSalTimer*>(ImplGetSVData()->maSchedCtx.mpSalTimer)->ImplStart( nTime );
-            rDef = FALSE;
+            assert( pTimer != nullptr );
+            pTimer->ImplStart( nTime );
             break;
         }
+
         case SAL_MSG_STOPTIMER:
-            static_cast<WinSalTimer*>(ImplGetSVData()->maSchedCtx.mpSalTimer)->ImplStop();
-            break;
-        case SAL_MSG_CREATEFRAME:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            nRet = reinterpret_cast<LRESULT>(ImplSalCreateFrame( GetSalData()->mpInstance, reinterpret_cast<HWND>(lParam), (SalFrameStyleFlags)wParam ));
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
-            break;
-        case SAL_MSG_RECREATEHWND:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            nRet = reinterpret_cast<LRESULT>(ImplSalReCreateHWND( reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), false ));
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
-            break;
-        case SAL_MSG_RECREATECHILDHWND:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            nRet = reinterpret_cast<LRESULT>(ImplSalReCreateHWND( reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), true ));
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
-            break;
-        case SAL_MSG_DESTROYFRAME:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            delete reinterpret_cast<SalFrame*>(lParam);
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
+            assert( pTimer != nullptr );
+            pTimer->ImplStop();
             break;
+
+        CASE_NOYIELDLOCK_RESULT( SAL_MSG_CREATEFRAME, ImplSalCreateFrame( GetSalData()->mpInstance,
+            reinterpret_cast<HWND>(lParam), static_cast<SalFrameStyleFlags>(wParam)) )
+        CASE_NOYIELDLOCK_RESULT( SAL_MSG_RECREATEHWND, ImplSalReCreateHWND(
+            reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), false) )
+        CASE_NOYIELDLOCK_RESULT( SAL_MSG_RECREATECHILDHWND, ImplSalReCreateHWND(
+            reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), true) )
+        CASE_NOYIELDLOCK( SAL_MSG_DESTROYFRAME, delete reinterpret_cast<SalFrame*>(lParam) )
+
         case SAL_MSG_DESTROYHWND:
-            //We only destroy the native window here. We do NOT destroy the SalFrame contained
-            //in the structure (GetWindowPtr()).
+            // We only destroy the native window here. We do NOT destroy the SalFrame contained
+            // in the structure (GetWindowPtr()).
             if (DestroyWindow(reinterpret_cast<HWND>(lParam)) == 0)
             {
                 OSL_FAIL("DestroyWindow failed!");
-                //Failure: We remove the SalFrame from the window structure. So we avoid that
+                // Failure: We remove the SalFrame from the window structure. So we avoid that
                 // the window structure may contain an invalid pointer, once the SalFrame is deleted.
-               SetWindowPtr(reinterpret_cast<HWND>(lParam), nullptr);
+                SetWindowPtr(reinterpret_cast<HWND>(lParam), nullptr);
             }
-            rDef = FALSE;
-            break;
-        case SAL_MSG_CREATEOBJECT:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            nRet = reinterpret_cast<LRESULT>(ImplSalCreateObject( GetSalData()->mpInstance, reinterpret_cast<WinSalFrame*>(lParam) ));
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
-            break;
-        case SAL_MSG_DESTROYOBJECT:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            delete reinterpret_cast<SalObject*>(lParam);
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
-            break;
-        case SAL_MSG_GETDC:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            nRet = reinterpret_cast<LRESULT>(GetDCEx( reinterpret_cast<HWND>(wParam), nullptr, DCX_CACHE ));
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
-            break;
-        case SAL_MSG_RELEASEDC:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            ReleaseDC( reinterpret_cast<HWND>(wParam), reinterpret_cast<HDC>(lParam) );
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
             break;
+
+        CASE_NOYIELDLOCK_RESULT( SAL_MSG_CREATEOBJECT, ImplSalCreateObject(
+            GetSalData()->mpInstance, reinterpret_cast<WinSalFrame*>(lParam)) )
+        CASE_NOYIELDLOCK( SAL_MSG_DESTROYOBJECT, delete reinterpret_cast<SalObject*>(lParam) )
+        CASE_NOYIELDLOCK_RESULT( SAL_MSG_GETDC, GetDCEx(
+            reinterpret_cast<HWND>(wParam), nullptr, DCX_CACHE) )
+        CASE_NOYIELDLOCK( SAL_MSG_RELEASEDC, ReleaseDC(
+            reinterpret_cast<HWND>(wParam), reinterpret_cast<HDC>(lParam)) )
+
         case SAL_MSG_TIMER_CALLBACK:
-        {
-            WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
             assert( pTimer != nullptr );
             nRet = static_cast<LRESULT>( pTimer->ImplHandleTimerEvent( wParam ) );
-            nDef = FALSE;
             break;
-        }
+
         case WM_TIMER:
-        {
-            WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
             assert( pTimer != nullptr );
             nRet = static_cast<LRESULT>( pTimer->ImplHandle_WM_TIMER( wParam ) );
-            nDef = FALSE;
             break;
-        }
+
+        case SAL_MSG_DUMMY:
+            break;
+
+        default:
+            rDef = TRUE;
+            break;
     }
 
     return nRet;
 }
 
+#undef CASE_NOYIELDLOCK
+#undef CASE_NOYIELDLOCK_RESULT
+
 LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
 {
-    int bDef = TRUE;
+    bool bDef = FALSE;
     LRESULT nRet = 0;
     __try
     {
diff --git a/vcl/win/window/salobj.cxx b/vcl/win/window/salobj.cxx
index 172f61e923d3..75e406c33f61 100644
--- a/vcl/win/window/salobj.cxx
+++ b/vcl/win/window/salobj.cxx
@@ -145,7 +145,7 @@ LRESULT CALLBACK SalSysMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
     return CallNextHookEx( pSalData->mhSalObjMsgHook, nCode, wParam, lParam );
 }
 
-bool ImplSalPreDispatchMsg( MSG* pMsg )
+bool ImplSalPreDispatchMsg( const MSG* pMsg )
 {
     // Used for Unicode and none Unicode
     SalData*        pSalData = GetSalData();
@@ -231,10 +231,10 @@ bool ImplSalPreDispatchMsg( MSG* pMsg )
     return FALSE;
 }
 
-void ImplSalPostDispatchMsg( MSG* pMsg, LRESULT /* nDispatchResult */ )
+void ImplSalPostDispatchMsg( const MSG* pMsg )
 {
     // Used for Unicode and none Unicode
-    SalData*        pSalData = GetSalData();
+    SalData *pSalData = GetSalData();
 
     if ( (pMsg->message == WM_KEYDOWN) || (pMsg->message == WM_KEYUP) )
     {
commit b2da514bd88342a92d5aa0e6bb98c347909b0601
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Oct 18 17:00:53 2017 +0200

    OSX implement direct timeout processing
    
    Basically works in the same way then in the Windows backend.
    
    Change-Id: If48e2b55f037563839a5e716830ce75ed78381e4

diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index 272cfc722d64..01e50af77b99 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -77,6 +77,7 @@ public:
     osl::Condition                          maWaitingYieldCond;
     bool                                    mbIsLiveResize;
     bool                                    mbNoYieldLock;
+    bool                                    mbTimerProcessed;
 
     static std::list<const ApplicationEvent*> aAppEventList;
 
diff --git a/vcl/inc/osx/saltimer.h b/vcl/inc/osx/saltimer.h
index c860ad5cbdda..a9934f280636 100644
--- a/vcl/inc/osx/saltimer.h
+++ b/vcl/inc/osx/saltimer.h
@@ -44,6 +44,7 @@ public:
 class AquaSalTimer final : public SalTimer, protected VersionedEvent
 {
     NSTimer    *m_pRunningTimer;
+    bool        m_bDirectTimeout;    ///< timeout can be processed directly
 
     void queueDispatchTimerEvent( bool bAtStart );
     void callTimerCallback();
@@ -56,13 +57,19 @@ public:
     void Stop() override;
 
     void handleStartTimerEvent( NSEvent* pEvent );
-    void handleDispatchTimerEvent( NSEvent* pEvent );
+    bool handleDispatchTimerEvent( NSEvent* pEvent );
     void handleTimerElapsed();
     void handleWindowShouldClose();
 
     bool IsTimerElapsed() const;
+    inline bool IsDirectTimeout() const;
 };
 
+inline bool AquaSalTimer::IsDirectTimeout() const
+{
+    return m_bDirectTimeout;
+}
+
 #endif // INCLUDED_VCL_INC_OSX_SALTIMER_H
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index d475f30275b0..922046bcbfe8 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -379,6 +379,7 @@ AquaSalInstance::AquaSalInstance()
     : mnActivePrintJobs( 0 )
     , mbIsLiveResize( false )
     , mbNoYieldLock( false )
+    , mbTimerProcessed( false )
 {
     mpSalYieldMutex = new SalYieldMutex;
     mpSalYieldMutex->acquire();
@@ -452,9 +453,12 @@ void AquaSalInstance::handleAppDefinedEvent( NSEvent* pEvent )
         break;
     }
     case DispatchTimerEvent:
-        if ( pTimer )
-            pTimer->handleDispatchTimerEvent( pEvent );
+    {
+        AquaSalInstance *pInst = GetSalData()->mpInstance;
+        if ( pTimer && pInst )
+            pInst->mbTimerProcessed = pTimer->handleDispatchTimerEvent( pEvent );
         break;
+    }
 #if !HAVE_FEATURE_MACOSX_SANDBOX
     case AppleRemoteControlEvent: // Defined in <apple_remote/RemoteMainController.h>
     {
@@ -570,6 +574,8 @@ bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
         // handle available events
         NSEvent* pEvent = nil;
         NSTimeInterval now = [[NSProcessInfo processInfo] systemUptime];
+        mbTimerProcessed = false;
+
         do
         {
             SolarMutexReleaser aReleaser;
@@ -596,6 +602,13 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
         }
         while( true );
 
+        AquaSalTimer *pTimer = static_cast<AquaSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
+        if ( !mbTimerProcessed && pTimer && pTimer->IsDirectTimeout() )
+        {
+            pTimer->handleTimerElapsed();
+            bHadEvent = true;
+        }
+
         // if we had no event yet, wait for one if requested
         if( bWait && ! bHadEvent )
         {
diff --git a/vcl/osx/saltimer.cxx b/vcl/osx/saltimer.cxx
index 34d46f08728a..af18ae7ea740 100644
--- a/vcl/osx/saltimer.cxx
+++ b/vcl/osx/saltimer.cxx
@@ -74,6 +74,7 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
 void AquaSalTimer::queueDispatchTimerEvent( bool bAtStart )
 {
     Stop();
+    m_bDirectTimeout = true;
     ImplNSAppPostEvent( AquaSalInstance::DispatchTimerEvent,
                         bAtStart, GetNextEventVersion() );
 }
@@ -139,13 +140,14 @@ void AquaSalTimer::callTimerCallback()
 {
     ImplSVData* pSVData = ImplGetSVData();
     SolarMutexGuard aGuard;
+    m_bDirectTimeout = false;
     if( pSVData->maSchedCtx.mpSalTimer )
         pSVData->maSchedCtx.mpSalTimer->CallCallback();
 }
 
 void AquaSalTimer::handleTimerElapsed()
 {
-    if ( GetSalData()->mpInstance->mbIsLiveResize )
+    if ( m_bDirectTimeout || GetSalData()->mpInstance->mbIsLiveResize )
     {
         // Stop the timer, as it is just invalidated after the firing function
         Stop();
@@ -155,10 +157,12 @@ void AquaSalTimer::handleTimerElapsed()
         queueDispatchTimerEvent( YES );
 }
 
-void AquaSalTimer::handleDispatchTimerEvent( NSEvent *pEvent )
+bool AquaSalTimer::handleDispatchTimerEvent( NSEvent *pEvent )
 {
-    if ( IsValidEventVersion( [pEvent data1] ) )
+    bool bIsValidEvent = IsValidEventVersion( [pEvent data1] );
+    if ( bIsValidEvent )
         callTimerCallback();
+    return bIsValidEvent;
 }
 
 void AquaSalTimer::handleStartTimerEvent( NSEvent* pEvent )
@@ -177,8 +181,8 @@ void AquaSalTimer::handleStartTimerEvent( NSEvent* pEvent )
 
 bool AquaSalTimer::IsTimerElapsed() const
 {
-    assert( !(ExistsValidEvent() && m_pRunningTimer) );
-    if ( ExistsValidEvent() )
+    assert( !((ExistsValidEvent() || m_bDirectTimeout) && m_pRunningTimer) );
+    if ( ExistsValidEvent() || m_bDirectTimeout )
         return true;
     if ( !m_pRunningTimer )
         return false;
commit 806ed4e81e2f11135cd6d8c056035d8a56bcf754
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 16 16:59:45 2017 +0200

    WIN guarantee direct timeout handling
    
    The code did acccount processing of an invaild timeout system
    message as a valid timeout event.
    
    Change-Id: I3c31f8b9cec592631b4089411163dadecffde816

diff --git a/vcl/README.scheduler b/vcl/README.scheduler
index 17648ae3b439..80c14b032c54 100644
--- a/vcl/README.scheduler
+++ b/vcl/README.scheduler
@@ -89,6 +89,35 @@ can be added to the scheduler reasonably.
 
 = Implementation details =
 
+== General: event priority for DoYield ==
+
+There are three types of events, with different priority:
+
+1. LO user events
+2. System events
+3. LO Scheduler event
+
+They should be processed according to the following code:
+
+bool DoYield( bool bWait, bool bAllCurrent )
+{
+    bool bWasEvent = ProcessUserEvents( bAllCurrent );
+    if ( !bAllCurrent && bWasEvent )
+        return true;
+    bWasEvent = ProcessSystemEvents( bAllCurrent, &bWasSchedulerEvent ) || bWasEvent;
+    if ( !bWasSchedulerEvent && IsSchedulerEvent() )
+    {
+        ProcessSchedulerEvent()
+        bWasEvent = true;
+    }
+    if ( !bWasEvent && bWait )
+    {
+        WaitForSystemEvents();
+        bWasEvent = true;
+    }
+    return bWasEvent;
+}
+
 == General: main thread deferral ==
 
 Currently for Mac and Windows, we run main thread deferrals by disabling the
diff --git a/vcl/inc/win/saltimer.h b/vcl/inc/win/saltimer.h
index d762b51b6716..b7d1a1e0d0f1 100644
--- a/vcl/inc/win/saltimer.h
+++ b/vcl/inc/win/saltimer.h
@@ -42,9 +42,9 @@ class WinSalTimer final : public SalTimer, protected VersionedEvent
 
     void ImplStart( sal_uIntPtr nMS );
     void ImplStop();
-    void ImplHandleTimerEvent( WPARAM aWPARAM );
+    bool ImplHandleTimerEvent( WPARAM aWPARAM );
     void ImplHandleElapsedTimer();
-    void ImplHandle_WM_TIMER( WPARAM aWPARAM );
+    bool ImplHandle_WM_TIMER( WPARAM aWPARAM );
 
 public:
     WinSalTimer();
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index d1fc8adb6272..5fcca5cde5b4 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -459,17 +459,15 @@ void WinSalInstance::AcquireYieldMutex( sal_uInt32 nCount )
     mpSalYieldMutex->acquire( nCount );
 }
 
-static void ImplSalDispatchMessage( MSG* pMsg )
+static LRESULT ImplSalDispatchMessage( const MSG* pMsg )
 {
     SalData* pSalData = GetSalData();
-    if ( pSalData->mpFirstObject )
-    {
-        if ( ImplSalPreDispatchMsg( pMsg ) )
-            return;
-    }
+    if ( pSalData->mpFirstObject && ImplSalPreDispatchMsg( pMsg ) )
+        return 0;
     LRESULT lResult = DispatchMessageW( pMsg );
     if ( pSalData->mpFirstObject )
-        ImplSalPostDispatchMsg( pMsg, lResult );
+        ImplSalPostDispatchMsg( pMsg );
+    return lResult;
 }
 
 bool ImplSalYield( bool bWait, bool bHandleAllCurrentEvents )
@@ -491,10 +489,13 @@ bool ImplSalYield( bool bWait, bool bHandleAllCurrentEvents )
         if ( bOneEvent )
         {
             bWasMsg = true;
-            if ( !bWasTimeoutMsg )
-                bWasTimeoutMsg = (SAL_MSG_TIMER_CALLBACK == aMsg.message);
             TranslateMessage( &aMsg );
-            ImplSalDispatchMessage( &aMsg );
+            LRESULT nRet = ImplSalDispatchMessage( &aMsg );
+
+            if ( !bWasTimeoutMsg )
+                bWasTimeoutMsg = (SAL_MSG_TIMER_CALLBACK == aMsg.message)
+                    && static_cast<bool>( nRet );
+
             if ( bHandleAllCurrentEvents
                     && !bHadNewerEvent && aMsg.time > nCurTicks
                     && (nLastTicks <= nCurTicks || aMsg.time < nLastTicks) )
@@ -666,14 +667,16 @@ LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, i
         {
             WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
             assert( pTimer != nullptr );
-            pTimer->ImplHandleTimerEvent( wParam );
+            nRet = static_cast<LRESULT>( pTimer->ImplHandleTimerEvent( wParam ) );
+            nDef = FALSE;
             break;
         }
         case WM_TIMER:
         {
             WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
             assert( pTimer != nullptr );
-            pTimer->ImplHandle_WM_TIMER( wParam );
+            nRet = static_cast<LRESULT>( pTimer->ImplHandle_WM_TIMER( wParam ) );
+            nDef = FALSE;
             break;
         }
     }
diff --git a/vcl/win/app/saltimer.cxx b/vcl/win/app/saltimer.cxx
index 9d20c70bdb5a..9c67e841956e 100644
--- a/vcl/win/app/saltimer.cxx
+++ b/vcl/win/app/saltimer.cxx
@@ -158,13 +158,14 @@ void WinSalTimer::ImplHandleElapsedTimer()
     ImplSalYieldMutexRelease();
 }
 
-void WinSalTimer::ImplHandleTimerEvent( const WPARAM aWPARAM )
+bool WinSalTimer::ImplHandleTimerEvent( const WPARAM aWPARAM )
 {
     assert( aWPARAM <= SAL_MAX_INT32 );
     if ( !IsValidEventVersion( static_cast<sal_Int32>( aWPARAM ) ) )
-        return;
+        return false;
 
     ImplHandleElapsedTimer();
+    return true;
 }
 
 void WinSalTimer::SetForceRealTimer( const bool bVal )
@@ -179,11 +180,14 @@ void WinSalTimer::SetForceRealTimer( const bool bVal )
         Start( 0 );
 }
 
-void WinSalTimer::ImplHandle_WM_TIMER( const WPARAM aWPARAM )
+bool WinSalTimer::ImplHandle_WM_TIMER( const WPARAM aWPARAM )
 {
     assert( m_aWmTimerId == aWPARAM );
-    if ( m_aWmTimerId == aWPARAM && m_bDirectTimeout && m_bForceRealTimer )
-        ImplHandleElapsedTimer();
+    if ( !(m_aWmTimerId == aWPARAM && m_bDirectTimeout && m_bForceRealTimer) )
+        return false;
+
+    ImplHandleElapsedTimer();
+    return true;
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 327abc3433c220bf549ad305a17a1cc4e1dbc44f
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 16 19:03:59 2017 +0200

    tdf#105062 prevent AutoRecovery DB deadlock
    
    AutoRecovery document event notification - at least for Firebird
    DB files - needs the SolarMutex for getLocation().
    
    If I place the SolarMutex inside the CacheLockGuard I get a the
    css::uno::RuntimeException from CacheLockGuard::lock.
    
    Change-Id: I3341a80ecf144d29e0a68de6695d1ca6a7241c60

diff --git a/framework/source/services/autorecovery.cxx b/framework/source/services/autorecovery.cxx
index d1b106592d4e..53f02f4e3d5f 100644
--- a/framework/source/services/autorecovery.cxx
+++ b/framework/source/services/autorecovery.cxx
@@ -2606,6 +2606,7 @@ void AutoRecovery::implts_updateDocumentUsedForSavingState(const css::uno::Refer
 
 void AutoRecovery::implts_markDocumentAsSaved(const css::uno::Reference< css::frame::XModel >& xDocument)
 {
+    SolarMutexGuard aSolarGuard;
     CacheLockGuard aCacheLock(this, cppu::WeakComponentImplHelperBase::rBHelper.rMutex, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
 
     AutoRecovery::TDocumentInfo aInfo;
commit 5db82a6cb4d0cde2577ac6ebb12052cb7750f551
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Oct 18 14:54:20 2017 +0200

    Prefer ACE over Jet ODBC Excel drivers in VB tests
    
    The Jet drivers are deprectated and unsupported.
    
    From commit 66b3970c946bd25647484ea1ac2c2e62bd9fb7b4 I guess a
    Windows 10 64bit doesn't provide any, but don't know.
    
    Essentially commit 66b3970c946bd25647484ea1ac2c2e62bd9fb7b4,
    is reverted, as it also removed the ole_dfltObjDflMethod.vb test.
    
    Change-Id: I2dfc525c7cdf7ceb7f46521905933f9ce67aa2e6

diff --git a/basic/qa/cppunit/test_vba.cxx b/basic/qa/cppunit/test_vba.cxx
index d153a1d62f82..6baa98e8ff8d 100644
--- a/basic/qa/cppunit/test_vba.cxx
+++ b/basic/qa/cppunit/test_vba.cxx
@@ -36,7 +36,9 @@ namespace
 
         // Declares the method as a test to call
         CPPUNIT_TEST(testMiscVBAFunctions);
+#ifdef _WIN32
         CPPUNIT_TEST(testMiscOLEStuff);
+#endif
 
         // End of test suite definition
         CPPUNIT_TEST_SUITE_END();
@@ -175,16 +177,11 @@ void VBATest::testMiscVBAFunctions()
     }
 }
 
-void VBATest::testMiscOLEStuff()
-{
 // Not much point even trying to run except on Windows.
 // (Without Excel doesn't really do anything anyway,
-// see "so skip test" below.)
-
-// Since some time, on a properly updated Windows 10, this works
-// only with a 64-bit LibreOffice
-
-#if defined(_WIN64)
+#ifdef _WIN32
+void VBATest::testMiscOLEStuff()
+{
     // test if we have the necessary runtime environment
     // to run the OLE tests.
     uno::Reference< lang::XMultiServiceFactory > xOLEFactory;
@@ -203,27 +200,45 @@ void VBATest::testMiscOLEStuff()
         bOk = xADODB.is();
     }
     if ( !bOk )
-        return; // can't do anything, skip test
+        return; // can't do anything without OLE, so skip test
 
+    // search for the ODBC Excel drivers
     const int nBufSize = 1024 * 4;
     wchar_t sBuf[nBufSize];
-    SQLGetInstalledDriversW( sBuf, nBufSize, nullptr );
+    if( !SQLGetInstalledDriversW( sBuf, nBufSize, nullptr ) )
+        return;
+
+    const wchar_t *aExcelDriverNameList[]
+    {
+        L"Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)",
+        L"Microsoft Excel Driver (*.xls)"
+    };
+    const unsigned MAX_DRV = SAL_N_ELEMENTS( aExcelDriverNameList );
+    bool bFoundDrivers[ MAX_DRV ] = { false, };
 
     const wchar_t *pODBCDriverName = sBuf;
-    bool bFound = false;
-    for (; wcslen( pODBCDriverName ) != 0; pODBCDriverName += wcslen( pODBCDriverName ) + 1 ) {
-        if( wcscmp( pODBCDriverName, L"Microsoft Excel Driver (*.xls)" ) == 0 ||
-            wcscmp( pODBCDriverName, L"Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)" ) == 0 ) {
-            bFound = true;
+    for (; wcslen( pODBCDriverName ) != 0; pODBCDriverName += wcslen( pODBCDriverName ) + 1 )
+    {
+        for ( unsigned i = 0; i < MAX_DRV; ++i )
+            if ( !bFoundDrivers[ i ] && wcscmp( pODBCDriverName, aExcelDriverNameList[ i ] ) == 0 )
+                bFoundDrivers[ i ] = true;
+    }
+
+    pODBCDriverName = nullptr;
+    for ( unsigned i = 0; i < MAX_DRV; ++i )
+        if ( bFoundDrivers[ i ] )
+        {
+            pODBCDriverName = aExcelDriverNameList[ i ];
             break;
         }
-    }
-    if ( !bFound )
-        return; // can't find ODBC driver needed test, so skip test
+
+    if ( !pODBCDriverName )
+        return; // can't find any ODBC driver needed for the test, so skip it
 
     const char* macroSource[] = {
         "ole_ObjAssignNoDflt.vb",
         "ole_ObjAssignToNothing.vb",
+        "ole_dfltObjDflMethod.vb",
     };
 
     OUString sMacroPathURL = m_directories.getURLFromSrc("/basic/qa/vba_tests/");
@@ -251,11 +266,8 @@ void VBATest::testMiscOLEStuff()
         CPPUNIT_ASSERT_MESSAGE("No return variable huh?", pReturn.get() != nullptr );
         CPPUNIT_ASSERT_EQUAL_MESSAGE("Result not as expected", OUString("OK"), pReturn->GetOUString() );
     }
-#else
-    // Avoid "this method is empty and should be removed" warning
-    (void) 42;
-#endif
 }
+#endif
 
   // Put the test suite in the registry
   CPPUNIT_TEST_SUITE_REGISTRATION(VBATest);
commit 331016f82a709d80c70143435db18753a78a23f6
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Wed Oct 18 11:15:00 2017 +0100

    return early on failure
    
    Change-Id: Id96ba954d3056cf982701090cf84ab4b1793b40b
    Reviewed-on: https://gerrit.libreoffice.org/43489
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/svx/source/accessibility/AccessibleShape.cxx b/svx/source/accessibility/AccessibleShape.cxx
index 86cc8ba732d1..ecf4c478774f 100644
--- a/svx/source/accessibility/AccessibleShape.cxx
+++ b/svx/source/accessibility/AccessibleShape.cxx
@@ -405,67 +405,66 @@ uno::Reference<XAccessibleStateSet> SAL_CALL
     AccessibleShape::getAccessibleStateSet()
 {
     ::osl::MutexGuard aGuard (maMutex);
-    Reference<XAccessibleStateSet> xStateSet;
 
-    bool bDisposed = IsDisposed();
-
-    if (bDisposed)
+    if (IsDisposed())
     {
         // Return a minimal state set that only contains the DEFUNC state.
-        xStateSet = AccessibleContextBase::getAccessibleStateSet ();
+        return AccessibleContextBase::getAccessibleStateSet ();
     }
-    else
-    {
-        ::utl::AccessibleStateSetHelper* pStateSet =
-              static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
 
-        if (pStateSet != nullptr)
+    ::utl::AccessibleStateSetHelper* pStateSet =
+          static_cast<::utl::AccessibleStateSetHelper*>(mxStateSet.get());
+
+    if (!pStateSet)
+        return Reference<XAccessibleStateSet>();
+
+    // Merge current FOCUSED state from edit engine.
+    if (mpText)
+    {
+        if (mpText->HaveFocus())
+            pStateSet->AddState (AccessibleStateType::FOCUSED);
+        else
+            pStateSet->RemoveState (AccessibleStateType::FOCUSED);
+    }
+    //Just when the document is not read-only,set states EDITABLE,RESIZABLE,MOVEABLE
+    css::uno::Reference<XAccessible> xTempAcc = getAccessibleParent();
+    if( xTempAcc.is() )
+    {
+        css::uno::Reference<XAccessibleContext>
+                                xTempAccContext = xTempAcc->getAccessibleContext();
+        if( xTempAccContext.is() )
         {
-            // Merge current FOCUSED state from edit engine.
-            if (mpText != nullptr)
+            css::uno::Reference<XAccessibleStateSet> rState =
+                xTempAccContext->getAccessibleStateSet();
+            if (rState.is())
             {
-                if (mpText->HaveFocus())
-                    pStateSet->AddState (AccessibleStateType::FOCUSED);
-                else
-                    pStateSet->RemoveState (AccessibleStateType::FOCUSED);
-            }
-            //Just when the document is not read-only,set states EDITABLE,RESIZABLE,MOVEABLE
-            css::uno::Reference<XAccessible> xTempAcc = getAccessibleParent();
-            if( xTempAcc.is() )
-            {
-                css::uno::Reference<XAccessibleContext>
-                                        xTempAccContext = xTempAcc->getAccessibleContext();
-                if( xTempAccContext.is() )
+                css::uno::Sequence<short> aStates = rState->getStates();
+                int count = aStates.getLength();
+                for( int iIndex = 0;iIndex < count;iIndex++ )
                 {
-                    css::uno::Reference<XAccessibleStateSet> rState =
-                        xTempAccContext->getAccessibleStateSet();
-                    if( rState.is() )           {
-                        css::uno::Sequence<short> aStates = rState->getStates();
-                        int count = aStates.getLength();
-                        for( int iIndex = 0;iIndex < count;iIndex++ )
-                        {
-                            if( aStates[iIndex] == AccessibleStateType::EDITABLE )
-                            {
-                                pStateSet->AddState (AccessibleStateType::EDITABLE);
-                                pStateSet->AddState (AccessibleStateType::RESIZABLE);
-                                pStateSet->AddState (AccessibleStateType::MOVEABLE);
-                                break;
-                            }
-                        }
+                    if( aStates[iIndex] == AccessibleStateType::EDITABLE )
+                    {
+                        pStateSet->AddState (AccessibleStateType::EDITABLE);
+                        pStateSet->AddState (AccessibleStateType::RESIZABLE);
+                        pStateSet->AddState (AccessibleStateType::MOVEABLE);
+                        break;
                     }
                 }
             }
-            // Create a copy of the state set that may be modified by the
-            // caller without affecting the current state set.
-            xStateSet.set( new ::utl::AccessibleStateSetHelper (*pStateSet));
         }
     }
-    if (!bDisposed && xStateSet.is() && mpParent && mpParent->IsDocumentSelAll())
+
+    // Create a copy of the state set that may be modified by the
+    // caller without affecting the current state set.
+    Reference<XAccessibleStateSet> xStateSet(new ::utl::AccessibleStateSetHelper(*pStateSet));
+
+    if (mpParent && mpParent->IsDocumentSelAll())
     {
-        ::utl::AccessibleStateSetHelper* pStateSet =
-            static_cast< ::utl::AccessibleStateSetHelper*>(xStateSet.get());
-        pStateSet->AddState (AccessibleStateType::SELECTED);
+        ::utl::AccessibleStateSetHelper* pCopyStateSet =
+            static_cast<::utl::AccessibleStateSetHelper*>(xStateSet.get());
+        pCopyStateSet->AddState (AccessibleStateType::SELECTED);
     }
+
     return xStateSet;
 }
 
commit e7cab93ebbccfc02e84c9385b8c53832784ef47c
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Wed Oct 18 15:51:14 2017 +0100

    ofz+ubsan: signed integer overflow in unused variable
    
    Change-Id: Ie95ddfdb002fdb5b6670bb155d2dd0089b719fca

diff --git a/sw/source/filter/ww8/ww8scan.cxx b/sw/source/filter/ww8/ww8scan.cxx
index d02cb762ed78..402319bce5cb 100644
--- a/sw/source/filter/ww8/ww8scan.cxx
+++ b/sw/source/filter/ww8/ww8scan.cxx
@@ -7159,9 +7159,6 @@ WW8PLCF_HdFt::WW8PLCF_HdFt( SvStream* pSt, WW8Fib& rFib, WW8Dop const & rDop )
     for( sal_uInt8 nI = 0x1; nI <= 0x20; nI <<= 1 )
         if( nI & rDop.grpfIhdt )                // bit set?
             nIdxOffset++;
-
-    nTextOfs = rFib.m_ccpText + rFib.m_ccpFootnote;  // size of the main text
-                                            // and from the footnotes
 }
 
 bool WW8PLCF_HdFt::GetTextPos(sal_uInt8 grpfIhdt, sal_uInt8 nWhich, WW8_CP& rStart,
diff --git a/sw/source/filter/ww8/ww8scan.hxx b/sw/source/filter/ww8/ww8scan.hxx
index d43335928fb7..ba0f1e9efecf 100644
--- a/sw/source/filter/ww8/ww8scan.hxx
+++ b/sw/source/filter/ww8/ww8scan.hxx
@@ -1844,7 +1844,6 @@ class WW8PLCF_HdFt
 {
 private:
     WW8PLCF aPLCF;
-    long nTextOfs;
     short nIdxOffset;
 
 public:
commit 93c34fea480275343896ef25289a2b41ce19b114
Author: Andrea Gelmini <andrea.gelmini at gelma.net>
Date:   Wed Oct 18 12:57:27 2017 +0200

    Fix typo
    
    Change-Id: Ie29a05fec90c0d81b4a0399505b0a6761dfdef69
    Reviewed-on: https://gerrit.libreoffice.org/43463
    Reviewed-by: Julien Nabet <serval2412 at yahoo.fr>
    Tested-by: Julien Nabet <serval2412 at yahoo.fr>

diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 545a003bb3e3..6870e5ff335c 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1186,7 +1186,7 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap )
                     {
                         // Workaround to make sure char props of the field are not lost.
                         // Not relevant for editeng-based comments.
-                        // Nor revelent for fields inside a TOC field.
+                        // Not relevant for fields inside a TOC field.
                         OUString const sMarker("X");
                         xCursor = xTextAppend->getText()->createTextCursor();
                         if (xCursor.is())
commit abaf2e3b856356d68b104c6aa0d17d6937d980b4
Author: Noel Grandin <noel.grandin at collabora.co.uk>
Date:   Wed Oct 18 16:26:14 2017 +0200

    rename some fields
    
    in preparation for const-method detection
    
    Change-Id: Iecf7102892d664ded799615ce1a848a538dcfcef

diff --git a/compilerplugins/clang/constparams.cxx b/compilerplugins/clang/constparams.cxx
index 87a00ec488c3..ca30048f9b1c 100644
--- a/compilerplugins/clang/constparams.cxx
+++ b/compilerplugins/clang/constparams.cxx
@@ -8,7 +8,6 @@
  */
 
 #include <algorithm>
-#include <set>
 #include <string>
 #include <unordered_set>
 #include <unordered_map>
@@ -60,8 +59,8 @@ public:
 
         TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
 
-        for (const ParmVarDecl *pParmVarDecl : interestingSet) {
-            if (cannotBeConstSet.find(pParmVarDecl) == cannotBeConstSet.end()) {
+        for (const ParmVarDecl *pParmVarDecl : interestingParamSet) {
+            if (paramCannotBeConstSet.find(pParmVarDecl) == paramCannotBeConstSet.end()) {
                 auto functionDecl = parmToFunction[pParmVarDecl];
                 auto canonicalDecl = functionDecl->getCanonicalDecl();
                 if (ignoredFunctions_.find(canonicalDecl)
@@ -174,10 +173,10 @@ private:
     bool checkIfCanBeConst(const Stmt*, const ParmVarDecl*);
     bool isPointerOrReferenceToConst(const QualType& qt);
 
-    std::unordered_set<const ParmVarDecl*> interestingSet;
+    std::unordered_set<const ParmVarDecl*> interestingParamSet;
     std::unordered_map<const ParmVarDecl*, const FunctionDecl*> parmToFunction;
-    std::unordered_set<const ParmVarDecl*> cannotBeConstSet;
-    std::set<FunctionDecl const *> ignoredFunctions_;
+    std::unordered_set<const ParmVarDecl*> paramCannotBeConstSet;
+    std::unordered_set<FunctionDecl const *> ignoredFunctions_;
     Expr const * callee_ = nullptr;
 };
 
@@ -257,7 +256,7 @@ bool ConstParams::VisitFunctionDecl(const FunctionDecl * functionDecl)
         // ignore things with template params
         if (pParmVarDecl->getType()->isInstantiationDependentType())
             continue;
-        interestingSet.insert(pParmVarDecl);
+        interestingParamSet.insert(pParmVarDecl);
         parmToFunction[pParmVarDecl] = functionDecl;
     }
 
@@ -278,10 +277,10 @@ bool ConstParams::VisitDeclRefExpr( const DeclRefExpr* declRefExpr )
         return true;
     }
     // no need to check again if we have already eliminated this one
-    if (cannotBeConstSet.find(parmVarDecl) != cannotBeConstSet.end())
+    if (paramCannotBeConstSet.find(parmVarDecl) != paramCannotBeConstSet.end())
         return true;
     if (!checkIfCanBeConst(declRefExpr, parmVarDecl))
-        cannotBeConstSet.insert(parmVarDecl);
+        paramCannotBeConstSet.insert(parmVarDecl);
 
     return true;
 }
commit d9575e72de6ad54e6680d00e795e380df2c82264
Author: Noel Grandin <noel.grandin at collabora.co.uk>
Date:   Wed Oct 18 16:21:45 2017 +0200

    loplugin:manualrefcount
    
    this is the code I used to find naked acquire/release stuff
    
    No need to run it all the time, so leave it in store
    
    Change-Id: I9ac4a6f5db7cd4cbb1b63698340425eed7cb8713

diff --git a/compilerplugins/clang/store/manualrefcount.cxx b/compilerplugins/clang/store/manualrefcount.cxx
new file mode 100644
index 000000000000..c8085904fede
--- /dev/null
+++ b/compilerplugins/clang/store/manualrefcount.cxx
@@ -0,0 +1,323 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-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/.
+ */
+
+#include <cassert>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <set>
+
+#include <clang/AST/CXXInheritance.h>
+#include "compat.hxx"
+#include "plugin.hxx"
+#include "check.hxx"
+
+/**
+ Look for calls to the ref-counting methods acquire()/release(), which should only be called by classes like rtl::Reference.
+*/
+
+namespace {
+
+class ManualRefCount:
+    public RecursiveASTVisitor<ManualRefCount>, public loplugin::Plugin
+{
+public:
+    explicit ManualRefCount(InstantiationData const & data): Plugin(data) {}
+
+    virtual void run() override
+    {
+        StringRef fn( compiler.getSourceManager().getFileEntryForID(
+                          compiler.getSourceManager().getMainFileID())->getName() );
+
+       // old code, no point in updating
+        if (loplugin::isSamePathname(fn, SRCDIR "/store/source/store.cxx"))
+             return;
+
+// TODO -----------------------------
+        if (loplugin::isSamePathname(fn, SRCDIR "/registry/source/registry.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/registry/source/regimpl.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/registry/source/reflread.cxx"))
+             return;
+        // TODO MenuAttributes::CreateAttribute
+        if (loplugin::isSamePathname(fn, SRCDIR "/framework/source/fwe/xml/menuconfiguration.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/uibase/app/apphdl.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/core/dataaccess/ModelImpl.cxx"))
+             return;
+        // need a better replacement for vcl::EventPoster
+        if (loplugin::isSamePathname(fn, SRCDIR "/svtools/source/misc/acceleratorexecute.cxx"))
+             return;
+        // PostUserEvent stuff
+        if (loplugin::isSamePathname(fn, SRCDIR "/toolkit/source/awt/vclxwindow.cxx"))
+             return;
+        // playing games with pointers passed into combobox entries
+        if (loplugin::isSamePathname(fn, SRCDIR "/cui/source/customize/cfgutil.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/cui/source/customize/cfg.cxx"))
+             return;
+// END TODO -----------------------------
+
+        // can't fix these without breaking stable ABI
+        if (fn.startswith(SRCDIR "/sal/"))
+             return;
+        if (fn.startswith(SRCDIR "/salhelper/"))
+             return;
+        if (fn.startswith(SRCDIR "/cppu/"))
+             return;
+        if (fn.startswith(SRCDIR "/cppuhelper/"))
+             return;
+        if (fn.startswith(SRCDIR "/bridges/"))
+             return;
+
+        // lots of magic here
+        if (fn.startswith(SRCDIR "/stoc/"))
+             return;
+        if (fn.startswith(SRCDIR "/testtools/"))
+             return;
+
+        // mutex games
+        if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/app/scheduler.cxx"))
+             return;
+        // opengl games
+        if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/app/svdata.cxx"))
+             return;
+
+        // passing the pointer through PostUserEvent
+        if (loplugin::isSamePathname(fn, SRCDIR "/avmedia/source/gstreamer/gstplayer.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/form/fmscriptingenv.cxx"))
+             return;
+
+        // thread games
+        if (loplugin::isSamePathname(fn, SRCDIR "/io/source/stm/opump.cxx"))
+             return;
+
+        // ??? no idea what this code is up to
+        if (loplugin::isSamePathname(fn, SRCDIR "/extensions/source/scanner/scanunx.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/stoc/source/invocation_adapterfactory/iafactory.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/fpicker/source/office/asyncfilepicker.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/component/FormComponent.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/ucb/source/ucp/file/bc.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/ucb/source/ucp/file/filprp.cxx"))
+             return;
+        // calling release() ?
+        if (loplugin::isSamePathname(fn, SRCDIR "/toolkit/source/helper/accessibilityclient.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/svtools/source/misc/svtaccessiblefactory.cxx"))
+             return;
+
+        // implementing css::uno::XInterface
+        if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/animations/motionpathtag.cxx"))
+             return;
+        // UNO factory methods
+        if (fn.startswith(SRCDIR "/comphelper/"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/convdiclist.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/dlistimp.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/gciterator.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/lngsvcmgr.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/lngopt.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/vcl/unx/generic/gdi/gcach_xpeer.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/ui/dlg/dbwizsetup.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/ui/dlg/dbwizsetup.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/lingucomponent/source/spellcheck/spell/sspellimp.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/lingucomponent/source/thesaurus/libnth/nthesimp.cxx"))
+             return;
+
+
+        // some kind of complicated listener nonsense
+        if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/framework/tools/FrameworkHelper.cxx"))
+             return;
+        // more listener nonsense
+        if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/uibase/uno/unomailmerge.cxx"))
+             return;
+        // playing games with it's listener list
+        if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/cellsuno.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/chart2uno.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/dapiuno.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/datauno.cxx"))
+             return;
+        if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/linkuno.cxx"))
+             return;
+        // PostUserEvent
+        if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/vba/vbaeventshelper.cxx"))
+             return;
+        // thread holding itself
+        if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/component/EventThread.cxx"))
+             return;
+
+
+        TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
+    }
+
+    bool shouldVisitTemplateInstantiations () const { return true; }
+
+    bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *);
+    bool TraverseCXXRecordDecl(CXXRecordDecl *);
+    bool TraverseCXXMethodDecl(CXXMethodDecl *);
+    bool TraverseFunctionDecl(FunctionDecl *);
+    bool TraverseCXXConstructorDecl(CXXConstructorDecl *);
+    bool TraverseCXXDestructorDecl(CXXDestructorDecl *);
+    bool TraverseCXXConversionDecl(CXXConversionDecl *);
+    bool TraverseClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *);
+    bool TraverseLinkageSpecDecl(LinkageSpecDecl *);
+private:
+    bool ignoreCallerClass(CXXRecordDecl*);
+};
+
+bool ManualRefCount::TraverseCXXMethodDecl(CXXMethodDecl* cxxMethodDecl)
+{
+    if (ignoreCallerClass(cxxMethodDecl->getParent()))
+        return true;
+    // disambiguating forwarding methods for XInterface subclasses
+    if (cxxMethodDecl->getIdentifier() && (cxxMethodDecl->getName() == "acquire" || cxxMethodDecl->getName() == "release"))
+        return true;
+    return RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl);
+}
+
+bool ManualRefCount::TraverseFunctionDecl(FunctionDecl* functionDecl)
+{
+    auto tc = loplugin::DeclCheck(functionDecl);
+    if (tc.Function("make_shared_from_UNO").Namespace("comphelper").GlobalNamespace())
+        return true;
+    return RecursiveASTVisitor::TraverseFunctionDecl(functionDecl);
+}
+
+bool ManualRefCount::TraverseCXXConstructorDecl(CXXConstructorDecl* cxxMethodDecl)
+{
+    if (ignoreCallerClass(cxxMethodDecl->getParent()))
+        return true;
+    return RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl);
+}
+
+bool ManualRefCount::TraverseCXXDestructorDecl(CXXDestructorDecl*)
+{
+    // just ignore destructors, tons of places like to call acquire() on themselves in their destructor
+    // supposedly to prevent recursively calling the destructor
+    return true;
+}
+bool ManualRefCount::TraverseCXXConversionDecl(CXXConversionDecl* cxxMethodDecl)
+{
+    if (ignoreCallerClass(cxxMethodDecl->getParent()))
+        return true;
+    return RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl);
+}
+bool ManualRefCount::TraverseCXXRecordDecl(CXXRecordDecl* cxxRecordDecl)
+{
+    if (ignoreCallerClass(cxxRecordDecl))
+        return true;
+    return RecursiveASTVisitor::TraverseCXXRecordDecl(cxxRecordDecl);
+}
+
+bool ManualRefCount::TraverseClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl* templateDecl)
+{
+    if (ignoreCallerClass(templateDecl))
+        return true;
+    return RecursiveASTVisitor::TraverseClassTemplateSpecializationDecl(templateDecl);
+}
+
+bool ManualRefCount::TraverseLinkageSpecDecl(LinkageSpecDecl *)
+{
+    // ignore methods inside "extern ""C""" blocks, these are normally UNO constructors, which
+    // are required to raise the reference count before returning
+    return true;
+}
+
+bool ManualRefCount::ignoreCallerClass(CXXRecordDecl* cxxRecordDecl)
+{
+    auto tc = loplugin::TypeCheck(cxxRecordDecl);
+    return
+           tc.Class("Reference").Namespace("rtl").GlobalNamespace()
+        || tc.Class("cow_wrapper").Namespace("o3tl").GlobalNamespace()
+        || tc.Class("Reference").Namespace("uno").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace()
+        || tc.Class("ShareGuard").Namespace("framework").GlobalNamespace()
+        || tc.Class("ControlModelLock").Namespace("frm").GlobalNamespace()
+        || tc.Struct("ReleaseFunc").Namespace("detail").Namespace("comphelper").GlobalNamespace()
+        // TODO no idea what this is up to
+        || tc.Class("SfxModelSubComponent").GlobalNamespace()
+        || tc.Class("OSubComponent").Namespace("mysqlc").Namespace("connectivity").GlobalNamespace()
+        || tc.Class("OSubComponent").Namespace("connectivity").GlobalNamespace()
+        // TODO do we really need this?
+        || tc.Class("ShareableMutex").Namespace("framework").GlobalNamespace()
+        || tc.Class("ObservableThread").GlobalNamespace()
+        ;
+}
+
+bool ManualRefCount::VisitCXXMemberCallExpr(const CXXMemberCallExpr* cxxMemberCallExpr)
+{
+    if (ignoreLocation(cxxMemberCallExpr))
+        return true;
+    if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(cxxMemberCallExpr->getLocStart())))
+        return true;
+
+    // first, use some heuristics to find the right kind of acquire()/release() calls
+    CXXMethodDecl const * calleeMethodDecl = cxxMemberCallExpr->getMethodDecl();
+    if (!calleeMethodDecl || !calleeMethodDecl->getIdentifier())
+        return true;
+    if (calleeMethodDecl->getName() != "acquire" && calleeMethodDecl->getName() != "release")
+        return true;
+    if (calleeMethodDecl->getNumParams() != 0)
+        return true;
+    // std::unique_ptr::release() and similar methods
+    if (calleeMethodDecl->getName() == "release" && loplugin::TypeCheck(calleeMethodDecl->getReturnType()).Pointer())
+        return true;
+
+    // these are OK
+    auto calleeRecordTC = loplugin::TypeCheck(calleeMethodDecl->getParent());
+    if (calleeRecordTC.Struct("ResourceHolder").Namespace("store").GlobalNamespace())
+        return true;
+    if (calleeRecordTC.Class("Module").Namespace("osl").GlobalNamespace())
+        return true;
+    if (calleeRecordTC.Class("Mutex").Namespace("osl").GlobalNamespace())
+        return true;
+    if (calleeRecordTC.Class("multi_type_vector").Namespace("mdds").GlobalNamespace())
+        return true;
+
+//    while (calleeMethodDecl->size_overridden_methods() > 0)
+//        calleeMethodDecl = *calleeMethodDecl->begin_overridden_methods();
+//    auto tc2 = loplugin::TypeCheck(calleeMethodDecl->getParent());
+//    if (tc2.Class("XInterface").Namespace("uno").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace())
+//        return true;
+
+std::cout << calleeMethodDecl->getParent()->getQualifiedNameAsString() << std::endl;
+    report(
+        DiagnosticsEngine::Warning, "call to acquire/release",
+        cxxMemberCallExpr->getLocStart())
+        << cxxMemberCallExpr->getSourceRange();
+    return true;
+}
+
+
+loplugin::Plugin::Registration< ManualRefCount > X("manualrefcount", true);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit d5b971f94245b32e8e1a884d0076ca4f1696d09a
Author: Noel Grandin <noel.grandin at collabora.co.uk>
Date:   Wed Oct 18 13:43:07 2017 +0200

    use rtl::Reference in forms
    
    instead of manual reference counting
    
    Change-Id: I5bad5b7b83049f5c018a1f2d5bbc37f03727c3ce
    Reviewed-on: https://gerrit.libreoffice.org/43497
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>

diff --git a/forms/source/richtext/richtextcontrol.cxx b/forms/source/richtext/richtextcontrol.cxx
index fcf1c7ee3d79..ab662fa1d078 100644
--- a/forms/source/richtext/richtextcontrol.cxx
+++ b/forms/source/richtext/richtextcontrol.cxx
@@ -180,15 +180,12 @@ namespace frm
 
             // create the peer
             Reference< XControlModel > xModel( getModel() );
-            ORichTextPeer* pPeer = ORichTextPeer::Create( xModel, pParentWin, getWinBits( xModel ) );
+            rtl::Reference<ORichTextPeer> pPeer = ORichTextPeer::Create( xModel, pParentWin, getWinBits( xModel ) );
             DBG_ASSERT( pPeer, "ORichTextControl::createPeer: invalid peer returned!" );
             if ( pPeer )
             {
-                // by definition, the returned component is acquired once
-                pPeer->release();
-
                 // announce the peer to the base class
-                setPeer( pPeer );
+                setPeer( pPeer.get() );
 
                 // initialize ourself (and thus the peer) with the model properties
                 updateFromModel();
@@ -254,7 +251,7 @@ namespace frm
     }
 
     // ORichTextPeer
-    ORichTextPeer* ORichTextPeer::Create( const Reference< XControlModel >& _rxModel, vcl::Window* _pParentWindow, WinBits _nStyle )
+    rtl::Reference<ORichTextPeer> ORichTextPeer::Create( const Reference< XControlModel >& _rxModel, vcl::Window* _pParentWindow, WinBits _nStyle )
     {
         DBG_TESTSOLARMUTEX();
 
@@ -265,14 +262,13 @@ namespace frm
             return nullptr;
 
         // the peer itself
-        ORichTextPeer* pPeer = new ORichTextPeer;
-        pPeer->acquire();   // by definition, the returned object is acquired once
+        rtl::Reference<ORichTextPeer> pPeer(new ORichTextPeer);
 
         // the VCL control for the peer
-        VclPtrInstance<RichTextControl> pRichTextControl( pEngine, _pParentWindow, _nStyle, nullptr, pPeer );
+        VclPtrInstance<RichTextControl> pRichTextControl( pEngine, _pParentWindow, _nStyle, nullptr, pPeer.get() );
 
         // some knittings
-        pRichTextControl->SetComponentInterface( pPeer );
+        pRichTextControl->SetComponentInterface( pPeer.get() );
 
         // outta here
         return pPeer;
diff --git a/forms/source/richtext/richtextcontrol.hxx b/forms/source/richtext/richtextcontrol.hxx
index e19d68b08d8e..c48fa618da62 100644
--- a/forms/source/richtext/richtextcontrol.hxx
+++ b/forms/source/richtext/richtextcontrol.hxx
@@ -86,10 +86,8 @@ namespace frm
 
     public:
         /** factory method
-            @return
-                a new ORichTextPeer instance, which has been acquired once!
         */
-        static ORichTextPeer* Create(
+        static rtl::Reference<ORichTextPeer> Create(
             const css::uno::Reference< css::awt::XControlModel >&         _rxModel,
             vcl::Window* _pParentWindow,
             WinBits _nStyle
diff --git a/forms/source/solar/component/navbarcontrol.cxx b/forms/source/solar/component/navbarcontrol.cxx
index e6aca3a50d95..01b798808720 100644
--- a/forms/source/solar/component/navbarcontrol.cxx
+++ b/forms/source/solar/component/navbarcontrol.cxx
@@ -131,13 +131,11 @@ namespace frm
             }
 
             // create the peer
-            ONavigationBarPeer* pPeer = ONavigationBarPeer::Create( m_xContext, pParentWin, getModel() );
+            rtl::Reference<ONavigationBarPeer> pPeer = ONavigationBarPeer::Create( m_xContext, pParentWin, getModel() );
             assert(pPeer && "ONavigationBarControl::createPeer: invalid peer returned!");
-            // by definition, the returned component is acquired once
-            pPeer->release();
 
             // announce the peer to the base class
-            setPeer( pPeer );
+            setPeer( pPeer.get() );
 
             // initialize ourself (and thus the peer) with the model properties
             updateFromModel();
@@ -198,14 +196,13 @@ namespace frm
     // ONavigationBarPeer
 
 
-    ONavigationBarPeer* ONavigationBarPeer::Create( const Reference< XComponentContext >& _rxORB,
+    rtl::Reference<ONavigationBarPeer> ONavigationBarPeer::Create( const Reference< XComponentContext >& _rxORB,
         vcl::Window* _pParentWindow, const Reference< XControlModel >& _rxModel )
     {
         DBG_TESTSOLARMUTEX();
 
         // the peer itself
-        ONavigationBarPeer* pPeer = new ONavigationBarPeer( _rxORB );
-        pPeer->acquire();   // by definition, the returned object is acquired once
+        rtl::Reference<ONavigationBarPeer> pPeer(new ONavigationBarPeer( _rxORB ));
 
         // the VCL control for the peer
         Reference< XModel > xContextDocument( getXModel( _rxModel ) );
@@ -220,8 +217,8 @@ namespace frm
         );
 
         // some knittings
-        pNavBar->setDispatcher( pPeer );
-        pNavBar->SetComponentInterface( pPeer );
+        pNavBar->setDispatcher( pPeer.get() );
+        pNavBar->SetComponentInterface( pPeer.get() );
 
         // we want a faster repeating rate for the slots in this
         // toolbox
diff --git a/forms/source/solar/component/navbarcontrol.hxx b/forms/source/solar/component/navbarcontrol.hxx
index 22ebb3046b2b..4f2463e652e5 100644
--- a/forms/source/solar/component/navbarcontrol.hxx
+++ b/forms/source/solar/component/navbarcontrol.hxx
@@ -78,10 +78,8 @@ namespace frm
     {
     public:
         /** factory method
-            @return
-                a new ONavigationBarPeer instance, which has been acquired once!
         */
-        static ONavigationBarPeer* Create(
+        static rtl::Reference<ONavigationBarPeer> Create(
             const css::uno::Reference< css::uno::XComponentContext >& _rxORB,
             vcl::Window* _pParentWindow,
             const css::uno::Reference< css::awt::XControlModel >& _rxModel
commit e149c4f3dcd08b9331dbbecf31c200d4d3bb02b5
Author: Gulsah Kose <gulsah.1004 at gmail.com>
Date:   Tue Oct 17 15:09:37 2017 +0300

    tdf#112808 Disable "Edit Region" command while cursor in an index.
    
    Change-Id: Icefa1e42831ad0ba7a9f5346545adac0033ce3e0
    Signed-off-by: Gulsah Kose <gulsah.1004 at gmail.com>
    Reviewed-on: https://gerrit.libreoffice.org/43456
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>

diff --git a/sw/source/uibase/shells/basesh.cxx b/sw/source/uibase/shells/basesh.cxx
index 8dbfd4e91cc8..c053715bd4ad 100644
--- a/sw/source/uibase/shells/basesh.cxx
+++ b/sw/source/uibase/shells/basesh.cxx
@@ -1398,8 +1398,12 @@ void SwBaseShell::GetState( SfxItemSet &rSet )
                 break;
 
             case FN_EDIT_CURRENT_REGION:
-                if( !rSh.GetCurrSection() )
+                //tdf#112808 if cursor is in an index, don't show the edit section.
+                if( !rSh.GetCurrSection() ||
+                    rSh.GetCurrSection()->GetType() != CONTENT_SECTION )
+                {
                     rSet.DisableItem(nWhich);
+                }
                 break;
 
             case FN_INSERT_REGION:
commit 087a90e27b7219e8c1aaa880b39376c94a0dcaae
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date:   Wed Oct 18 14:23:37 2017 +0200

    gpg4libre fix tdf#113190 don't show expired/invalid keys
    
    Change-Id: I30485bc97d3d287bd867b50398927eabe018914b
    Reviewed-on: https://gerrit.libreoffice.org/43502
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/xmlsecurity/source/gpg/SecurityEnvironment.cxx b/xmlsecurity/source/gpg/SecurityEnvironment.cxx
index c3cd90565fe2..2392bf0c8031 100644
--- a/xmlsecurity/source/gpg/SecurityEnvironment.cxx
+++ b/xmlsecurity/source/gpg/SecurityEnvironment.cxx
@@ -76,7 +76,7 @@ Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getCertificatesIm
         GpgME::Key k = m_ctx->nextKey(err);
         if (err)
             break;
-        if (!k.isInvalid()) {
+        if (!k.isRevoked() && !k.isExpired() && !k.isDisabled() && !k.isInvalid()) {
             // We can't create CertificateImpl here as CertificateImpl::setCertificate uses GpgME API
             // which interrupts our key listing here. So first get the keys from GpgME, then create the CertificateImpls
             keyList.push_back(k);
commit 7b00829e27b0a26e9fa8d06bb651134f03a466e9
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date:   Wed Oct 18 12:48:55 2017 +0200

    gpg4libre - tdf#113188 add option for minimal PGPKeyPacket
    
    Change-Id: I660e68074616f6953e6527e40ec22276ce8ef2fb
    Reviewed-on: https://gerrit.libreoffice.org/43492
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/external/gpgme/UnpackedTarball_gpgme.mk b/external/gpgme/UnpackedTarball_gpgme.mk
index ca9fd79feaab..15259971f798 100644
--- a/external/gpgme/UnpackedTarball_gpgme.mk
+++ b/external/gpgme/UnpackedTarball_gpgme.mk
@@ -16,5 +16,6 @@ $(eval $(call gb_UnpackedTarball_set_patchlevel,gpgme,0))
 $(eval $(call gb_UnpackedTarball_add_patches,gpgme, \
     external/gpgme/find-libgpg-error-libassuan.patch \
     external/gpgme/fix-autoconf-macros.patch \
+    external/gpgme/add-minimal-keyexport.patch \
 ))
 # vim: set noet sw=4 ts=4:
diff --git a/external/gpgme/add-minimal-keyexport.patch b/external/gpgme/add-minimal-keyexport.patch
new file mode 100644
index 000000000000..abaeb15897fc
--- /dev/null
+++ b/external/gpgme/add-minimal-keyexport.patch
@@ -0,0 +1,68 @@
+--- lang/cpp/src/context.h.bak	2017-10-18 12:28:00.898945587 +0200
++++ lang/cpp/src/context.h	2017-10-18 12:28:35.794832395 +0200
+@@ -178,10 +178,10 @@
+     // Key Export
+     //
+ 
+-    GpgME::Error exportPublicKeys(const char *pattern, Data &keyData);
+-    GpgME::Error exportPublicKeys(const char *pattern[], Data &keyData);
+-    GpgME::Error startPublicKeyExport(const char *pattern, Data &keyData);
+-    GpgME::Error startPublicKeyExport(const char *pattern[], Data &keyData);
++    GpgME::Error exportPublicKeys(const char *pattern, Data &keyData, bool minimal=false);
++    GpgME::Error exportPublicKeys(const char *pattern[], Data &keyData, bool minimal=false);
++    GpgME::Error startPublicKeyExport(const char *pattern, Data &keyData, bool minimal=false);
++    GpgME::Error startPublicKeyExport(const char *pattern[], Data &keyData, bool minimal=false);
+ 
+     //
+     // Key Import
+--- lang/cpp/src/context.cpp.bak	2017-10-18 12:27:50.830978224 +0200
++++ lang/cpp/src/context.cpp	2017-10-18 12:30:13.278515603 +0200
+@@ -557,14 +557,14 @@
+     }
+ }
+ 
+-Error Context::exportPublicKeys(const char *pattern, Data &keyData)
++Error Context::exportPublicKeys(const char *pattern, Data &keyData, bool minimal)
+ {
+     d->lastop = Private::Export;
+     Data::Private *const dp = keyData.impl();
+-    return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, 0, dp ? dp->data : 0));
++    return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, minimal ? GPGME_EXPORT_MODE_MINIMAL : 0, dp ? dp->data : 0));
+ }
+ 
+-Error Context::exportPublicKeys(const char *patterns[], Data &keyData)
++Error Context::exportPublicKeys(const char *patterns[], Data &keyData, bool minimal)
+ {
+     d->lastop = Private::Export;
+ #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
+@@ -574,17 +574,17 @@
+     }
+ #endif
+     Data::Private *const dp = keyData.impl();
+-    return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, 0, dp ? dp->data : 0));
++    return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, minimal ? GPGME_EXPORT_MODE_MINIMAL : 0, dp ? dp->data : 0));
+ }
+ 
+-Error Context::startPublicKeyExport(const char *pattern, Data &keyData)
++Error Context::startPublicKeyExport(const char *pattern, Data &keyData, bool minimal)
+ {
+     d->lastop = Private::Export;
+     Data::Private *const dp = keyData.impl();
+-    return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, 0, dp ? dp->data : 0));
++    return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, minimal ? GPGME_EXPORT_MODE_MINIMAL : 0, dp ? dp->data : 0));
+ }
+ 
+-Error Context::startPublicKeyExport(const char *patterns[], Data &keyData)
++Error Context::startPublicKeyExport(const char *patterns[], Data &keyData, bool minimal)
+ {
+     d->lastop = Private::Export;
+ #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
+@@ -594,7 +594,7 @@
+     }
+ #endif
+     Data::Private *const dp = keyData.impl();
+-    return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, 0, dp ? dp->data : 0));
++    return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, minimal ? GPGME_EXPORT_MODE_MINIMAL : 0, dp ? dp->data : 0));
+ }
+ 
+ ImportResult Context::importKeys(const Data &data)
diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
index 118700782343..01651dabe8f5 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
@@ -2460,6 +2460,19 @@
         </info>
         <value>true</value>
       </prop>
+      <group oor:name="OpenPGP">
+        <info>
+          <desc>Contains security settings regarding the GnuPG/OpenPGP backend.</desc>
+        </info>
+        <prop oor:name="MinimalKeyExport" oor:type="xs:boolean" oor:nillable="false">
+          <info>
+            <desc>Determines if the PGPKeyPacket element on signed

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list