summaryrefslogtreecommitdiff
path: root/vcl/win/source/app/salinst.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/win/source/app/salinst.cxx')
-rw-r--r--vcl/win/source/app/salinst.cxx1173
1 files changed, 1173 insertions, 0 deletions
diff --git a/vcl/win/source/app/salinst.cxx b/vcl/win/source/app/salinst.cxx
new file mode 100644
index 000000000000..97dbb5285cca
--- /dev/null
+++ b/vcl/win/source/app/salinst.cxx
@@ -0,0 +1,1173 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include <string.h>
+#include <tools/svwin.h>
+#ifdef WNT
+#include <process.h>
+#endif
+#ifdef __MINGW32__
+#include <excpt.h>
+#endif
+#include <osl/file.hxx>
+#include <vos/mutex.hxx>
+#include <tools/debug.hxx>
+#include <wincomp.hxx>
+#include <salids.hrc>
+#include <saldata.hxx>
+#include <salinst.h>
+#include <salframe.h>
+#include <salobj.h>
+#include <vcl/salsys.hxx>
+#include <saltimer.h>
+#include <vcl/salatype.hxx>
+#include <salbmp.h>
+#include <vcl/salimestatus.hxx>
+#include <vcl/timer.hxx>
+#include <wincomp.hxx> // CS_DROPSHADOW
+#include <tools/solarmutex.hxx>
+
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#if defined _MSC_VER
+#pragma warning(push, 1)
+#pragma warning( disable: 4917 )
+#endif
+
+#include <GdiPlus.h>
+#include <GdiPlusEnums.h>
+#include <GdiPlusColor.h>
+#include <Shlobj.h>
+
+#if defined _MSC_VER
+#pragma warning(pop)
+#endif
+
+// =======================================================================
+
+void SalAbort( const XubString& rErrorText )
+{
+ ImplFreeSalGDI();
+
+ if ( !rErrorText.Len() )
+ {
+ // #112255# make sure crash reporter is triggered
+ RaiseException( 0, EXCEPTION_NONCONTINUABLE, 0, NULL );
+ FatalAppExit( 0, "Application Error" );
+ }
+ else
+ {
+ // #112255# make sure crash reporter is triggered
+ RaiseException( 0, EXCEPTION_NONCONTINUABLE, 0, NULL );
+ ByteString aErrorText( ImplSalGetWinAnsiString( rErrorText ) );
+ FatalAppExit( 0, aErrorText.GetBuffer() );
+ }
+}
+
+// =======================================================================
+
+LRESULT CALLBACK SalComWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam );
+LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam );
+
+// =======================================================================
+
+class SalYieldMutex : public vos::OMutex
+{
+public: // for ImplSalYield()
+ WinSalInstance* mpInstData;
+ ULONG mnCount;
+ DWORD mnThreadId;
+
+public:
+ SalYieldMutex( WinSalInstance* pInstData );
+
+ virtual void SAL_CALL acquire();
+ virtual void SAL_CALL release();
+ virtual sal_Bool SAL_CALL tryToAcquire();
+
+ ULONG GetAcquireCount( ULONG nThreadId );
+};
+
+// -----------------------------------------------------------------------
+
+SalYieldMutex::SalYieldMutex( WinSalInstance* pInstData )
+{
+ mpInstData = pInstData;
+ mnCount = 0;
+ mnThreadId = 0;
+}
+
+// -----------------------------------------------------------------------
+
+void SAL_CALL SalYieldMutex::acquire()
+{
+ OMutex::acquire();
+ mnCount++;
+ mnThreadId = GetCurrentThreadId();
+}
+
+// -----------------------------------------------------------------------
+
+void SAL_CALL SalYieldMutex::release()
+{
+ DWORD nThreadId = GetCurrentThreadId();
+ if ( mnThreadId != nThreadId )
+ OMutex::release();
+ else
+ {
+ SalData* pSalData = GetSalData();
+ if ( pSalData->mnAppThreadId != nThreadId )
+ {
+ if ( mnCount == 1 )
+ {
+ // If we don't call these message, the Output from the
+ // Java clients doesn't come in the right order
+ GdiFlush();
+
+ mpInstData->mpSalWaitMutex->acquire();
+ if ( mpInstData->mnYieldWaitCount )
+ ImplPostMessage( mpInstData->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
+ mnThreadId = 0;
+ mnCount--;
+ OMutex::release();
+ mpInstData->mpSalWaitMutex->release();
+ }
+ else
+ {
+ mnCount--;
+ OMutex::release();
+ }
+ }
+ else
+ {
+ if ( mnCount == 1 )
+ mnThreadId = 0;
+ mnCount--;
+ OMutex::release();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool SAL_CALL SalYieldMutex::tryToAcquire()
+{
+ if( OMutex::tryToAcquire() )
+ {
+ mnCount++;
+ mnThreadId = GetCurrentThreadId();
+ return sal_True;
+ }
+ else
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG SalYieldMutex::GetAcquireCount( ULONG nThreadId )
+{
+ if ( nThreadId == mnThreadId )
+ return mnCount;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSalYieldMutexAcquireWithWait()
+{
+ WinSalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( !pInst )
+ return;
+
+ // If we are the main thread, then we must wait with wait, because
+ // in if we don't reschedule, then we create deadlocks if a Windows
+ // Function is called from another thread. If we arn't the main thread,
+ // than we call qcquire directly.
+ DWORD nThreadId = GetCurrentThreadId();
+ SalData* pSalData = GetSalData();
+ if ( pSalData->mnAppThreadId == nThreadId )
+ {
+ // Wenn wir den Mutex nicht bekommen, muessen wir solange
+ // warten, bis wir Ihn bekommen
+ BOOL bAcquire = FALSE;
+ do
+ {
+ if ( pInst->mpSalYieldMutex->tryToAcquire() )
+ bAcquire = TRUE;
+ else
+ {
+ pInst->mpSalWaitMutex->acquire();
+ if ( pInst->mpSalYieldMutex->tryToAcquire() )
+ {
+ bAcquire = TRUE;
+ pInst->mpSalWaitMutex->release();
+ }
+ else
+ {
+ pInst->mnYieldWaitCount++;
+ pInst->mpSalWaitMutex->release();
+ MSG aTmpMsg;
+ ImplGetMessage( &aTmpMsg, pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, SAL_MSG_RELEASEWAITYIELD );
+ pInst->mnYieldWaitCount--;
+ if ( pInst->mnYieldWaitCount )
+ ImplPostMessage( pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
+ }
+ }
+ }
+ while ( !bAcquire );
+ }
+ else
+ pInst->mpSalYieldMutex->acquire();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplSalYieldMutexTryToAcquire()
+{
+ WinSalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( pInst )
+ return pInst->mpSalYieldMutex->tryToAcquire();
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSalYieldMutexAcquire()
+{
+ WinSalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( pInst )
+ pInst->mpSalYieldMutex->acquire();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSalYieldMutexRelease()
+{
+ WinSalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( pInst )
+ {
+ GdiFlush();
+ pInst->mpSalYieldMutex->release();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ULONG ImplSalReleaseYieldMutex()
+{
+ WinSalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( !pInst )
+ return 0;
+
+ SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex;
+ ULONG nCount = pYieldMutex->GetAcquireCount( GetCurrentThreadId() );
+ ULONG n = nCount;
+ while ( n )
+ {
+ pYieldMutex->release();
+ n--;
+ }
+
+ return nCount;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSalAcquireYieldMutex( ULONG nCount )
+{
+ WinSalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( !pInst )
+ return;
+
+ SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex;
+ while ( nCount )
+ {
+ pYieldMutex->acquire();
+ nCount--;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef DBG_UTIL
+
+void ImplDbgTestSolarMutex()
+{
+ SalData* pSalData = GetSalData();
+ DWORD nCurThreadId = GetCurrentThreadId();
+ if ( pSalData->mnAppThreadId != nCurThreadId )
+ {
+ if ( pSalData->mpFirstInstance )
+ {
+ SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
+ if ( pYieldMutex->mnThreadId != nCurThreadId )
+ {
+ DBG_ERROR( "SolarMutex not locked, and not thread save code in VCL is called from outside of the main thread" );
+ }
+ }
+ }
+ else
+ {
+ if ( pSalData->mpFirstInstance )
+ {
+ SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
+ if ( pYieldMutex->mnThreadId != nCurThreadId )
+ {
+ DBG_ERROR( "SolarMutex not locked in the main thread" );
+ }
+ }
+ }
+}
+
+#endif
+
+// =======================================================================
+
+void SalData::initKeyCodeMap()
+{
+ UINT nKey = 0xffffffff;
+ #define initKey( a, b )\
+ nKey = LOWORD( VkKeyScan( a ) );\
+ if( nKey < 0xffff )\
+ maVKMap[ nKey ] = b;
+
+ initKey( '+', KEY_ADD );
+ initKey( '-', KEY_SUBTRACT );
+ initKey( '*', KEY_MULTIPLY );
+ initKey( '/', KEY_DIVIDE );
+ initKey( '.', KEY_POINT );
+ initKey( ',', KEY_COMMA );
+ initKey( '<', KEY_LESS );
+ initKey( '>', KEY_GREATER );
+ initKey( '=', KEY_EQUAL );
+ initKey( '~', KEY_TILDE );
+ initKey( '`', KEY_QUOTELEFT );
+}
+
+// =======================================================================
+// -------
+// SalData
+// -------
+
+SalData::SalData()
+{
+ mhInst = 0; // default instance handle
+ mhPrevInst = 0; // previous instance handle
+ mnCmdShow = 0; // default frame show style
+ mhDitherPal = 0; // dither palette
+ mhDitherDIB = 0; // dither memory handle
+ mpDitherDIB = 0; // dither memory
+ mpDitherDIBData = 0; // beginning of DIB data
+ mpDitherDiff = 0; // Dither mapping table
+ mpDitherLow = 0; // Dither mapping table
+ mpDitherHigh = 0; // Dither mapping table
+ mnTimerMS = 0; // Current Time (in MS) of the Timer
+ mnTimerOrgMS = 0; // Current Original Time (in MS)
+ mnNextTimerTime = 0;
+ mnLastEventTime = 0;
+ mnTimerId = 0; // windows timer id
+ mbInTimerProc = FALSE; // timer event is currently being dispatched
+ mhSalObjMsgHook = 0; // hook to get interesting msg for SalObject
+ mhWantLeaveMsg = 0; // window handle, that want a MOUSELEAVE message
+ mpMouseLeaveTimer = 0; // Timer for MouseLeave Test
+ mpFirstInstance = 0; // pointer of first instance
+ mpFirstFrame = 0; // pointer of first frame
+ mpFirstObject = 0; // pointer of first object window
+ mpFirstVD = 0; // first VirDev
+ mpFirstPrinter = 0; // first printing printer
+ mpHDCCache = 0; // Cache for three DC's
+ mh50Bmp = 0; // 50% Bitmap
+ mh50Brush = 0; // 50% Brush
+ int i;
+ for(i=0; i<MAX_STOCKPEN; i++)
+ {
+ maStockPenColorAry[i] = 0;
+ mhStockPenAry[i] = 0;
+ }
+ for(i=0; i<MAX_STOCKBRUSH; i++)
+ {
+ maStockBrushColorAry[i] = 0;
+ mhStockBrushAry[i] = 0;
+ }
+ mnStockPenCount = 0; // count of static pens
+ mnStockBrushCount = 0; // count of static brushes
+ mnSalObjWantKeyEvt = 0; // KeyEvent, welcher vom SalObj-Hook verarbeitet werden soll
+ mnCacheDCInUse = 0; // count of CacheDC in use
+ mbObjClassInit = FALSE; // is SALOBJECTCLASS initialised
+ mbInPalChange = FALSE; // is in WM_QUERYNEWPALETTE
+ mnAppThreadId = 0; // Id from Applikation-Thread
+ mbScrSvrEnabled = FALSE; // ScreenSaver enabled
+ mnSageStatus = 0; // status of Sage-DLL (DISABLE_AGENT == nicht vorhanden)
+ mpSageEnableProc = 0; // funktion to deactivate the system agent
+ mpFirstIcon = 0; // icon cache, points to first icon, NULL if none
+ mpTempFontItem = 0;
+ mbThemeChanged = FALSE; // true if visual theme was changed: throw away theme handles
+
+ // init with NULL
+ gdiplusToken = 0;
+
+ initKeyCodeMap();
+
+ SetSalData( this );
+ initNWF();
+}
+
+SalData::~SalData()
+{
+ deInitNWF();
+ SetSalData( NULL );
+}
+
+void InitSalData()
+{
+ SalData* pSalData = new SalData;
+ CoInitialize(0);
+
+ // init GDIPlus
+ static Gdiplus::GdiplusStartupInput gdiplusStartupInput;
+ Gdiplus::GdiplusStartup(&pSalData->gdiplusToken, &gdiplusStartupInput, NULL);
+}
+
+
+void DeInitSalData()
+{
+ CoUninitialize();
+ SalData* pSalData = GetSalData();
+
+ // deinit GDIPlus
+ if(pSalData)
+ {
+ Gdiplus::GdiplusShutdown(pSalData->gdiplusToken);
+ }
+
+ delete pSalData;
+}
+
+// -----------------------------------------------------------------------
+
+void InitSalMain()
+{
+ // remember data, copied from WinMain
+ SalData* pData = GetAppSalData();
+ if ( pData ) // Im AppServer NULL
+ {
+ STARTUPINFO aSI;
+ aSI.cb = sizeof( aSI );
+ GetStartupInfo( &aSI );
+ pData->mhInst = GetModuleHandle( NULL );
+ pData->mhPrevInst = NULL;
+ pData->mnCmdShow = aSI.wShowWindow;
+ }
+}
+
+void DeInitSalMain()
+{
+}
+
+// -----------------------------------------------------------------------
+
+SalInstance* CreateSalInstance()
+{
+ SalData* pSalData = GetSalData();
+
+ // determine the windows version
+ aSalShlData.mbWNT = 0;
+ aSalShlData.mbWXP = 0;
+ aSalShlData.mbWPrinter = 0;
+ WORD nVer = (WORD)GetVersion();
+ aSalShlData.mnVersion = (((WORD)LOBYTE(nVer)) * 100) + HIBYTE(nVer);
+ if ( aSalShlData.mnVersion >= 400 )
+ aSalShlData.mbW40 = 1;
+ rtl_zeroMemory( &aSalShlData.maVersionInfo, sizeof(aSalShlData.maVersionInfo) );
+ aSalShlData.maVersionInfo.dwOSVersionInfoSize = sizeof( aSalShlData.maVersionInfo );
+ if ( GetVersionEx( &aSalShlData.maVersionInfo ) )
+ {
+ if ( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
+ {
+ aSalShlData.mbWNT = 1;
+ // Windows XP ?
+ if ( aSalShlData.maVersionInfo.dwMajorVersion > 5 ||
+ ( aSalShlData.maVersionInfo.dwMajorVersion == 5 && aSalShlData.maVersionInfo.dwMinorVersion >= 1 ) )
+ aSalShlData.mbWXP = 1;
+ if( aSalShlData.maVersionInfo.dwMajorVersion >= 5 )
+ aSalShlData.mbWPrinter = 1;
+ }
+ }
+
+ pSalData->mnAppThreadId = GetCurrentThreadId();
+
+ // register frame class
+ if ( !pSalData->mhPrevInst )
+ {
+ if ( aSalShlData.mbWNT )
+ {
+ WNDCLASSEXW aWndClassEx;
+ aWndClassEx.cbSize = sizeof( aWndClassEx );
+ aWndClassEx.style = CS_OWNDC;
+ aWndClassEx.lpfnWndProc = SalFrameWndProcW;
+ aWndClassEx.cbClsExtra = 0;
+ aWndClassEx.cbWndExtra = SAL_FRAME_WNDEXTRA;
+ aWndClassEx.hInstance = pSalData->mhInst;
+ aWndClassEx.hCursor = 0;
+ aWndClassEx.hbrBackground = 0;
+ aWndClassEx.lpszMenuName = 0;
+ aWndClassEx.lpszClassName = SAL_FRAME_CLASSNAMEW;
+ ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT, aWndClassEx.hIcon, aWndClassEx.hIconSm );
+ if ( !RegisterClassExW( &aWndClassEx ) )
+ return NULL;
+
+ aWndClassEx.hIcon = 0;
+ aWndClassEx.hIconSm = 0;
+ aWndClassEx.style |= CS_SAVEBITS;
+ aWndClassEx.lpszClassName = SAL_SUBFRAME_CLASSNAMEW;
+ if ( !RegisterClassExW( &aWndClassEx ) )
+ return NULL;
+
+ // shadow effect for popups on XP
+ if( aSalShlData.mbWXP )
+ aWndClassEx.style |= CS_DROPSHADOW;
+ aWndClassEx.lpszClassName = SAL_TMPSUBFRAME_CLASSNAMEW;
+ if ( !RegisterClassExW( &aWndClassEx ) )
+ return NULL;
+
+ aWndClassEx.style = 0;
+ aWndClassEx.lpfnWndProc = SalComWndProcW;
+ aWndClassEx.cbWndExtra = 0;
+ aWndClassEx.lpszClassName = SAL_COM_CLASSNAMEW;
+ if ( !RegisterClassExW( &aWndClassEx ) )
+ return NULL;
+ }
+ else
+ {
+ WNDCLASSEXA aWndClassEx;
+ aWndClassEx.cbSize = sizeof( aWndClassEx );
+ aWndClassEx.style = CS_OWNDC;
+ aWndClassEx.lpfnWndProc = SalFrameWndProcA;
+ aWndClassEx.cbClsExtra = 0;
+ aWndClassEx.cbWndExtra = SAL_FRAME_WNDEXTRA;
+ aWndClassEx.hInstance = pSalData->mhInst;
+ aWndClassEx.hCursor = 0;
+ aWndClassEx.hbrBackground = 0;
+ aWndClassEx.lpszMenuName = 0;
+ aWndClassEx.lpszClassName = SAL_FRAME_CLASSNAMEA;
+ ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT, aWndClassEx.hIcon, aWndClassEx.hIconSm );
+ if ( !RegisterClassExA( &aWndClassEx ) )
+ return NULL;
+
+ aWndClassEx.hIcon = 0;
+ aWndClassEx.hIconSm = 0;
+ aWndClassEx.style |= CS_SAVEBITS;
+ aWndClassEx.lpszClassName = SAL_SUBFRAME_CLASSNAMEA;
+ if ( !RegisterClassExA( &aWndClassEx ) )
+ return NULL;
+
+ aWndClassEx.style = 0;
+ aWndClassEx.lpfnWndProc = SalComWndProcA;
+ aWndClassEx.cbWndExtra = 0;
+ aWndClassEx.lpszClassName = SAL_COM_CLASSNAMEA;
+ if ( !RegisterClassExA( &aWndClassEx ) )
+ return NULL;
+ }
+ }
+
+ HWND hComWnd;
+ if ( aSalShlData.mbWNT )
+ {
+ hComWnd = CreateWindowExW( WS_EX_TOOLWINDOW, SAL_COM_CLASSNAMEW,
+ L"", WS_POPUP, 0, 0, 0, 0, 0, 0,
+ pSalData->mhInst, NULL );
+ }
+ else
+ {
+ hComWnd = CreateWindowExA( WS_EX_TOOLWINDOW, SAL_COM_CLASSNAMEA,
+ "", WS_POPUP, 0, 0, 0, 0, 0, 0,
+ pSalData->mhInst, NULL );
+ }
+ if ( !hComWnd )
+ return NULL;
+
+ WinSalInstance* pInst = new WinSalInstance;
+
+ // init instance (only one instance in this version !!!)
+ pSalData->mpFirstInstance = pInst;
+ pInst->mhInst = pSalData->mhInst;
+ pInst->mhComWnd = hComWnd;
+
+ // init static GDI Data
+ ImplInitSalGDI();
+
+ return pInst;
+}
+
+// -----------------------------------------------------------------------
+
+void DestroySalInstance( SalInstance* pInst )
+{
+ SalData* pSalData = GetSalData();
+
+ // (only one instance in this version !!!)
+
+ ImplFreeSalGDI();
+
+ // reset instance
+ if ( pSalData->mpFirstInstance == pInst )
+ pSalData->mpFirstInstance = NULL;
+
+ delete pInst;
+}
+
+// -----------------------------------------------------------------------
+
+WinSalInstance::WinSalInstance()
+{
+ mhComWnd = 0;
+ mpSalYieldMutex = new SalYieldMutex( this );
+ mpSalWaitMutex = new vos::OMutex;
+ mnYieldWaitCount = 0;
+ mpSalYieldMutex->acquire();
+ ::tools::SolarMutex::SetSolarMutex( mpSalYieldMutex );
+}
+
+// -----------------------------------------------------------------------
+
+WinSalInstance::~WinSalInstance()
+{
+ ::tools::SolarMutex::SetSolarMutex( 0 );
+ mpSalYieldMutex->release();
+ delete mpSalYieldMutex;
+ delete mpSalWaitMutex;
+ DestroyWindow( mhComWnd );
+}
+
+// -----------------------------------------------------------------------
+
+vos::IMutex* WinSalInstance::GetYieldMutex()
+{
+ return mpSalYieldMutex;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG WinSalInstance::ReleaseYieldMutex()
+{
+ return ImplSalReleaseYieldMutex();
+}
+
+// -----------------------------------------------------------------------
+
+void WinSalInstance::AcquireYieldMutex( ULONG nCount )
+{
+ ImplSalAcquireYieldMutex( nCount );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplSalDispatchMessage( MSG* pMsg )
+{
+ SalData* pSalData = GetSalData();
+ if ( pSalData->mpFirstObject )
+ {
+ if ( ImplSalPreDispatchMsg( pMsg ) )
+ return;
+ }
+ LRESULT lResult = ImplDispatchMessage( pMsg );
+ if ( pSalData->mpFirstObject )
+ ImplSalPostDispatchMsg( pMsg, lResult );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSalYield( BOOL bWait, BOOL bHandleAllCurrentEvents )
+{
+ MSG aMsg;
+ bool bWasMsg = false, bOneEvent = false;
+
+ int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
+ do
+ {
+ if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
+ {
+ TranslateMessage( &aMsg );
+ ImplSalDispatchMessage( &aMsg );
+ bOneEvent = bWasMsg = true;
+ }
+ else
+ bOneEvent = false;
+ } while( --nMaxEvents && bOneEvent );
+
+ if ( bWait && ! bWasMsg )
+ {
+ if ( ImplGetMessage( &aMsg, 0, 0, 0 ) )
+ {
+ TranslateMessage( &aMsg );
+ ImplSalDispatchMessage( &aMsg );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void WinSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
+{
+ SalYieldMutex* pYieldMutex = mpSalYieldMutex;
+ SalData* pSalData = GetSalData();
+ DWORD nCurThreadId = GetCurrentThreadId();
+ ULONG nCount = pYieldMutex->GetAcquireCount( nCurThreadId );
+ ULONG n = nCount;
+ while ( n )
+ {
+ pYieldMutex->release();
+ n--;
+ }
+ if ( pSalData->mnAppThreadId != nCurThreadId )
+ {
+ // #97739# A SendMessage call blocks until the called thread (here: the main thread)
+ // returns. During a yield however, messages are processed in the main thread that might
+ // result in a new message loop due to opening a dialog. Thus, SendMessage would not
+ // return which will block this thread!
+ // Solution: just give up the time slice and hope that messages are processed
+ // by the main thread anyway (where all windows are created)
+ // If the mainthread is not currently handling messages, then our SendMessage would
+ // also do nothing, so this seems to be reasonable.
+
+ // #i18883# only sleep if potential deadlock scenario, ie, when a dialog is open
+ if( ImplGetSVData()->maAppData.mnModalMode )
+ Sleep(1);
+ else
+ ImplSendMessage( mhComWnd, SAL_MSG_THREADYIELD, (WPARAM)bWait, (LPARAM)bHandleAllCurrentEvents );
+
+ n = nCount;
+ while ( n )
+ {
+ pYieldMutex->acquire();
+ n--;
+ }
+ }
+ else
+ {
+ ImplSalYield( bWait, bHandleAllCurrentEvents );
+
+ n = nCount;
+ while ( n )
+ {
+ ImplSalYieldMutexAcquireWithWait();
+ n--;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+LRESULT CALLBACK SalComWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
+{
+ LRESULT nRet = 0;
+
+
+ switch ( nMsg )
+ {
+ case SAL_MSG_PRINTABORTJOB:
+ ImplSalPrinterAbortJobAsync( (HDC)wParam );
+ rDef = FALSE;
+ break;
+ case SAL_MSG_THREADYIELD:
+ ImplSalYield( (BOOL)wParam, (BOOL)lParam );
+ rDef = FALSE;
+ break;
+ // If we get this message, because another GetMessage() call
+ // has recieved this message, we must post this message to
+ // us again, because in the other case we wait forever.
+ case SAL_MSG_RELEASEWAITYIELD:
+ {
+ WinSalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( pInst && pInst->mnYieldWaitCount )
+ ImplPostMessage( hWnd, SAL_MSG_RELEASEWAITYIELD, wParam, lParam );
+ }
+ rDef = FALSE;
+ break;
+ case SAL_MSG_STARTTIMER:
+ ImplSalStartTimer( (ULONG) lParam, FALSE );
+ rDef = FALSE;
+ break;
+ case SAL_MSG_CREATEFRAME:
+ nRet = (LRESULT)ImplSalCreateFrame( GetSalData()->mpFirstInstance, (HWND)lParam, (ULONG)wParam );
+ rDef = FALSE;
+ break;
+ case SAL_MSG_RECREATEHWND:
+ nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, FALSE );
+ rDef = FALSE;
+ break;
+ case SAL_MSG_RECREATECHILDHWND:
+ nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, TRUE );
+ rDef = FALSE;
+ break;
+ case SAL_MSG_DESTROYFRAME:
+ delete (SalFrame*)lParam;
+ rDef = FALSE;
+ break;
+ case SAL_MSG_DESTROYHWND:
+ //We only destroy the native window here. We do NOT destroy the SalFrame contained
+ //in the structure (GetWindowPtr()).
+ if (DestroyWindow((HWND)lParam) == 0)
+ {
+ OSL_ENSURE(0, "DestroyWindow failed!");
+ //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((HWND)lParam, 0);
+ }
+ rDef = FALSE;
+ break;
+ case SAL_MSG_CREATEOBJECT:
+ nRet = (LRESULT)ImplSalCreateObject( GetSalData()->mpFirstInstance, (WinSalFrame*)lParam );
+ rDef = FALSE;
+ break;
+ case SAL_MSG_DESTROYOBJECT:
+ delete (SalObject*)lParam;
+ rDef = FALSE;
+ break;
+ case SAL_MSG_GETDC:
+ nRet = (LRESULT)GetDCEx( (HWND)wParam, 0, DCX_CACHE );
+ rDef = FALSE;
+ break;
+ case SAL_MSG_RELEASEDC:
+ ReleaseDC( (HWND)wParam, (HDC)lParam );
+ rDef = FALSE;
+ break;
+ case SAL_MSG_POSTTIMER:
+ SalTimerProc( 0, 0, SALTIMERPROC_RECURSIVE, lParam );
+ break;
+ }
+
+ return nRet;
+}
+
+LRESULT CALLBACK SalComWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
+{
+ int bDef = TRUE;
+ LRESULT nRet = 0;
+#ifdef __MINGW32__
+ jmp_buf jmpbuf;
+ __SEHandler han;
+ if (__builtin_setjmp(jmpbuf) == 0)
+ {
+ han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
+#else
+ __try
+ {
+#endif
+ nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef );
+ }
+#ifdef __MINGW32__
+ han.Reset();
+#else
+ __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
+ {
+ }
+#endif
+ if ( bDef )
+ {
+ if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) )
+ nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
+ }
+ return nRet;
+}
+
+LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
+{
+ int bDef = TRUE;
+ LRESULT nRet = 0;
+#ifdef __MINGW32__
+ jmp_buf jmpbuf;
+ __SEHandler han;
+ if (__builtin_setjmp(jmpbuf) == 0)
+ {
+ han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
+#else
+ __try
+ {
+#endif
+ nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef );
+ }
+#ifdef __MINGW32__
+ han.Reset();
+#else
+ __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
+ {
+ }
+#endif
+ if ( bDef )
+ {
+ if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) )
+ nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
+ }
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+bool WinSalInstance::AnyInput( USHORT nType )
+{
+ MSG aMsg;
+
+ if ( (nType & (INPUT_ANY)) == (INPUT_ANY) )
+ {
+ // revert bugfix for #108919# which never reported timeouts when called from the timer handler
+ // which made the application completely unresponsive during background formatting
+ if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) )
+ return true;
+ }
+ else
+ {
+ if ( nType & INPUT_MOUSE )
+ {
+ // Test for mouse input
+ if ( ImplPeekMessage( &aMsg, 0, WM_MOUSEFIRST, WM_MOUSELAST,
+ PM_NOREMOVE | PM_NOYIELD ) )
+ return true;
+ }
+
+ if ( nType & INPUT_KEYBOARD )
+ {
+ // Test for key input
+ if ( ImplPeekMessage( &aMsg, 0, WM_KEYDOWN, WM_KEYDOWN,
+ PM_NOREMOVE | PM_NOYIELD ) )
+ {
+ if ( (aMsg.wParam == VK_SHIFT) ||
+ (aMsg.wParam == VK_CONTROL) ||
+ (aMsg.wParam == VK_MENU) )
+ return false;
+ else
+ return true;
+ }
+ }
+
+ if ( nType & INPUT_PAINT )
+ {
+ // Test for paint input
+ if ( ImplPeekMessage( &aMsg, 0, WM_PAINT, WM_PAINT,
+ PM_NOREMOVE | PM_NOYIELD ) )
+ return true;
+
+ if ( ImplPeekMessage( &aMsg, 0, WM_SIZE, WM_SIZE,
+ PM_NOREMOVE | PM_NOYIELD ) )
+ return true;
+
+ if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTCALLSIZE, SAL_MSG_POSTCALLSIZE,
+ PM_NOREMOVE | PM_NOYIELD ) )
+ return true;
+
+ if ( ImplPeekMessage( &aMsg, 0, WM_MOVE, WM_MOVE,
+ PM_NOREMOVE | PM_NOYIELD ) )
+ return true;
+
+ if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTMOVE, SAL_MSG_POSTMOVE,
+ PM_NOREMOVE | PM_NOYIELD ) )
+ return true;
+ }
+
+ if ( nType & INPUT_TIMER )
+ {
+ // Test for timer input
+ if ( ImplPeekMessage( &aMsg, 0, WM_TIMER, WM_TIMER,
+ PM_NOREMOVE | PM_NOYIELD ) )
+ return true;
+
+ }
+
+ if ( nType & INPUT_OTHER )
+ {
+ // Test for any input
+ if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) )
+ return true;
+ }
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void SalTimer::Start( ULONG nMS )
+{
+ // Um auf Main-Thread umzuschalten
+ SalData* pSalData = GetSalData();
+ if ( pSalData->mpFirstInstance )
+ {
+ if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
+ ImplPostMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
+ else
+ ImplSendMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
+ }
+ else
+ ImplSalStartTimer( nMS, FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+SalFrame* WinSalInstance::CreateChildFrame( SystemParentData* pSystemParentData, ULONG nSalFrameStyle )
+{
+ // Um auf Main-Thread umzuschalten
+ return (SalFrame*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEFRAME, nSalFrameStyle, (LPARAM)pSystemParentData->hWnd );
+}
+
+// -----------------------------------------------------------------------
+
+SalFrame* WinSalInstance::CreateFrame( SalFrame* pParent, ULONG nSalFrameStyle )
+{
+ // Um auf Main-Thread umzuschalten
+ HWND hWndParent;
+ if ( pParent )
+ hWndParent = static_cast<WinSalFrame*>(pParent)->mhWnd;
+ else
+ hWndParent = 0;
+ return (SalFrame*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEFRAME, nSalFrameStyle, (LPARAM)hWndParent );
+}
+
+// -----------------------------------------------------------------------
+
+void WinSalInstance::DestroyFrame( SalFrame* pFrame )
+{
+ ImplSendMessage( mhComWnd, SAL_MSG_DESTROYFRAME, 0, (LPARAM)pFrame );
+}
+
+// -----------------------------------------------------------------------
+
+SalObject* WinSalInstance::CreateObject( SalFrame* pParent,
+ SystemWindowData* /*pWindowData*/, // SystemWindowData meaningless on Windows
+ BOOL /*bShow*/ )
+{
+ // Um auf Main-Thread umzuschalten
+ return (SalObject*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEOBJECT, 0, (LPARAM)static_cast<WinSalFrame*>(pParent) );
+}
+
+// -----------------------------------------------------------------------
+
+void WinSalInstance::DestroyObject( SalObject* pObject )
+{
+ ImplSendMessage( mhComWnd, SAL_MSG_DESTROYOBJECT, 0, (LPARAM)pObject );
+}
+
+// -----------------------------------------------------------------------
+
+void* WinSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes )
+{
+ rReturnedBytes = 1;
+ rReturnedType = AsciiCString;
+ return const_cast<char *>("");
+}
+
+// -----------------------------------------------------------------------
+
+/** Add a file to the system shells recent document list if there is any.
+ This function may have no effect under Unix because there is no
+ standard API among the different desktop managers.
+
+ @param aFileUrl
+ The file url of the document.
+*/
+void WinSalInstance::AddToRecentDocumentList(const rtl::OUString& rFileUrl, const rtl::OUString& /*rMimeType*/)
+{
+ rtl::OUString system_path;
+ osl::FileBase::RC rc = osl::FileBase::getSystemPathFromFileURL(rFileUrl, system_path);
+
+ OSL_ENSURE(osl::FileBase::E_None == rc, "Invalid file url");
+
+ if (osl::FileBase::E_None == rc)
+ SHAddToRecentDocs(SHARD_PATHW, system_path.getStr());
+}
+
+// -----------------------------------------------------------------------
+
+SalTimer* WinSalInstance::CreateSalTimer()
+{
+ return new WinSalTimer();
+}
+
+// -----------------------------------------------------------------------
+
+SalBitmap* WinSalInstance::CreateSalBitmap()
+{
+ return new WinSalBitmap();
+}
+
+class WinImeStatus : public SalI18NImeStatus
+{
+ public:
+ WinImeStatus() {}
+ virtual ~WinImeStatus() {}
+
+ // asks whether there is a status window available
+ // to toggle into menubar
+ virtual bool canToggle() { return false; }
+ virtual void toggle() {}
+};
+
+SalI18NImeStatus* WinSalInstance::CreateI18NImeStatus()
+{
+ return new WinImeStatus();
+}
+
+// -----------------------------------------------------------------------
+
+const ::rtl::OUString& SalGetDesktopEnvironment()
+{
+ static ::rtl::OUString aDesktopEnvironment( RTL_CONSTASCII_USTRINGPARAM( "Windows" ) );
+ return aDesktopEnvironment;
+}
+
+SalSession* WinSalInstance::CreateSalSession()
+{
+ return NULL;
+}
+
+#ifndef __MINGW32__
+// -----------------------------------------------------------------------
+int WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(int, LPEXCEPTION_POINTERS pExceptionInfo)
+{
+ // Decide if an exception is a c++ (mostly UNO) exception or a process violation.
+ // Depending on this information we pass process violations directly to our signal handler ...
+ // and c++ (UNO) exceptions are sended to the following code on the current stack.
+ // Problem behind: user32.dll sometime consumes exceptions/process violations .-)
+ // see also #112221#
+
+ static DWORD EXCEPTION_MSC_CPP_EXCEPTION = 0xE06D7363;
+
+ if (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_MSC_CPP_EXCEPTION)
+ return EXCEPTION_CONTINUE_SEARCH;
+
+ return UnhandledExceptionFilter( pExceptionInfo );
+}
+#endif