merge the formfield patch from ooo-build
[ooovba.git] / vcl / win / source / app / salinst.cxx
blob1e085b8872f874eb12e3cd8e891617e9495b47d6
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salinst.cxx,v $
10 * $Revision: 1.42.154.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <string.h>
35 #include <tools/svwin.h>
36 #ifdef WNT
37 #include <process.h>
38 #endif
39 #ifdef __MINGW32__
40 #include <excpt.h>
41 #endif
42 #include <osl/file.hxx>
43 #include <vos/mutex.hxx>
44 #include <tools/debug.hxx>
45 #include <wincomp.hxx>
46 #include <salids.hrc>
47 #include <saldata.hxx>
48 #include <salinst.h>
49 #include <salframe.h>
50 #include <salobj.h>
51 #include <vcl/salsys.hxx>
52 #include <saltimer.h>
53 #include <vcl/salatype.hxx>
54 #include <salbmp.h>
55 #include <vcl/salimestatus.hxx>
56 #include <vcl/timer.hxx>
57 #include <wincomp.hxx> // CS_DROPSHADOW
59 #ifndef min
60 #define min(a,b) (((a) < (b)) ? (a) : (b))
61 #endif
62 #ifndef max
63 #define max(a,b) (((a) > (b)) ? (a) : (b))
64 #endif
66 #if defined _MSC_VER
67 #pragma warning(push, 1)
68 #pragma warning( disable: 4917 )
69 #endif
71 #include <GdiPlus.h>
72 #include <GdiPlusEnums.h>
73 #include <GdiPlusColor.h>
74 #include <Shlobj.h>
76 #if defined _MSC_VER
77 #pragma warning(pop)
78 #endif
80 // =======================================================================
82 void SalAbort( const XubString& rErrorText )
84 ImplFreeSalGDI();
86 if ( !rErrorText.Len() )
88 // #112255# make sure crash reporter is triggered
89 RaiseException( 0, EXCEPTION_NONCONTINUABLE, 0, NULL );
90 FatalAppExit( 0, "Application Error" );
92 else
94 // #112255# make sure crash reporter is triggered
95 RaiseException( 0, EXCEPTION_NONCONTINUABLE, 0, NULL );
96 ByteString aErrorText( ImplSalGetWinAnsiString( rErrorText ) );
97 FatalAppExit( 0, aErrorText.GetBuffer() );
101 // =======================================================================
103 LRESULT CALLBACK SalComWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam );
104 LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam );
106 // =======================================================================
108 class SalYieldMutex : public vos::OMutex
110 public: // for ImplSalYield()
111 WinSalInstance* mpInstData;
112 ULONG mnCount;
113 DWORD mnThreadId;
115 public:
116 SalYieldMutex( WinSalInstance* pInstData );
118 virtual void SAL_CALL acquire();
119 virtual void SAL_CALL release();
120 virtual sal_Bool SAL_CALL tryToAcquire();
122 ULONG GetAcquireCount( ULONG nThreadId );
125 // -----------------------------------------------------------------------
127 SalYieldMutex::SalYieldMutex( WinSalInstance* pInstData )
129 mpInstData = pInstData;
130 mnCount = 0;
131 mnThreadId = 0;
134 // -----------------------------------------------------------------------
136 void SAL_CALL SalYieldMutex::acquire()
138 OMutex::acquire();
139 mnCount++;
140 mnThreadId = GetCurrentThreadId();
143 // -----------------------------------------------------------------------
145 void SAL_CALL SalYieldMutex::release()
147 DWORD nThreadId = GetCurrentThreadId();
148 if ( mnThreadId != nThreadId )
149 OMutex::release();
150 else
152 SalData* pSalData = GetSalData();
153 if ( pSalData->mnAppThreadId != nThreadId )
155 if ( mnCount == 1 )
157 // If we don't call these message, the Output from the
158 // Java clients doesn't come in the right order
159 GdiFlush();
161 mpInstData->mpSalWaitMutex->acquire();
162 if ( mpInstData->mnYieldWaitCount )
163 ImplPostMessage( mpInstData->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
164 mnThreadId = 0;
165 mnCount--;
166 OMutex::release();
167 mpInstData->mpSalWaitMutex->release();
169 else
171 mnCount--;
172 OMutex::release();
175 else
177 if ( mnCount == 1 )
178 mnThreadId = 0;
179 mnCount--;
180 OMutex::release();
185 // -----------------------------------------------------------------------
187 sal_Bool SAL_CALL SalYieldMutex::tryToAcquire()
189 if( OMutex::tryToAcquire() )
191 mnCount++;
192 mnThreadId = GetCurrentThreadId();
193 return sal_True;
195 else
196 return sal_False;
199 // -----------------------------------------------------------------------
201 ULONG SalYieldMutex::GetAcquireCount( ULONG nThreadId )
203 if ( nThreadId == mnThreadId )
204 return mnCount;
205 else
206 return 0;
209 // -----------------------------------------------------------------------
211 void ImplSalYieldMutexAcquireWithWait()
213 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
214 if ( !pInst )
215 return;
217 // If we are the main thread, then we must wait with wait, because
218 // in if we don't reschedule, then we create deadlocks if a Windows
219 // Function is called from another thread. If we arn't the main thread,
220 // than we call qcquire directly.
221 DWORD nThreadId = GetCurrentThreadId();
222 SalData* pSalData = GetSalData();
223 if ( pSalData->mnAppThreadId == nThreadId )
225 // Wenn wir den Mutex nicht bekommen, muessen wir solange
226 // warten, bis wir Ihn bekommen
227 BOOL bAcquire = FALSE;
230 if ( pInst->mpSalYieldMutex->tryToAcquire() )
231 bAcquire = TRUE;
232 else
234 pInst->mpSalWaitMutex->acquire();
235 if ( pInst->mpSalYieldMutex->tryToAcquire() )
237 bAcquire = TRUE;
238 pInst->mpSalWaitMutex->release();
240 else
242 pInst->mnYieldWaitCount++;
243 pInst->mpSalWaitMutex->release();
244 MSG aTmpMsg;
245 ImplGetMessage( &aTmpMsg, pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, SAL_MSG_RELEASEWAITYIELD );
246 pInst->mnYieldWaitCount--;
247 if ( pInst->mnYieldWaitCount )
248 ImplPostMessage( pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
252 while ( !bAcquire );
254 else
255 pInst->mpSalYieldMutex->acquire();
258 // -----------------------------------------------------------------------
260 BOOL ImplSalYieldMutexTryToAcquire()
262 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
263 if ( pInst )
264 return pInst->mpSalYieldMutex->tryToAcquire();
265 else
266 return FALSE;
269 // -----------------------------------------------------------------------
271 void ImplSalYieldMutexAcquire()
273 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
274 if ( pInst )
275 pInst->mpSalYieldMutex->acquire();
278 // -----------------------------------------------------------------------
280 void ImplSalYieldMutexRelease()
282 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
283 if ( pInst )
285 GdiFlush();
286 pInst->mpSalYieldMutex->release();
290 // -----------------------------------------------------------------------
292 ULONG ImplSalReleaseYieldMutex()
294 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
295 if ( !pInst )
296 return 0;
298 SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex;
299 ULONG nCount = pYieldMutex->GetAcquireCount( GetCurrentThreadId() );
300 ULONG n = nCount;
301 while ( n )
303 pYieldMutex->release();
304 n--;
307 return nCount;
310 // -----------------------------------------------------------------------
312 void ImplSalAcquireYieldMutex( ULONG nCount )
314 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
315 if ( !pInst )
316 return;
318 SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex;
319 while ( nCount )
321 pYieldMutex->acquire();
322 nCount--;
326 // -----------------------------------------------------------------------
328 #ifdef DBG_UTIL
330 void ImplDbgTestSolarMutex()
332 SalData* pSalData = GetSalData();
333 DWORD nCurThreadId = GetCurrentThreadId();
334 if ( pSalData->mnAppThreadId != nCurThreadId )
336 if ( pSalData->mpFirstInstance )
338 SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
339 if ( pYieldMutex->mnThreadId != nCurThreadId )
341 DBG_ERROR( "SolarMutex not locked, and not thread save code in VCL is called from outside of the main thread" );
345 else
347 if ( pSalData->mpFirstInstance )
349 SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
350 if ( pYieldMutex->mnThreadId != nCurThreadId )
352 DBG_ERROR( "SolarMutex not locked in the main thread" );
358 #endif
360 // =======================================================================
362 void SalData::initKeyCodeMap()
364 UINT nKey = 0xffffffff;
365 #define initKey( a, b )\
366 nKey = LOWORD( VkKeyScan( a ) );\
367 if( nKey < 0xffff )\
368 maVKMap[ nKey ] = b;
370 initKey( '+', KEY_ADD );
371 initKey( '-', KEY_SUBTRACT );
372 initKey( '*', KEY_MULTIPLY );
373 initKey( '/', KEY_DIVIDE );
374 initKey( '.', KEY_POINT );
375 initKey( ',', KEY_COMMA );
376 initKey( '<', KEY_LESS );
377 initKey( '>', KEY_GREATER );
378 initKey( '=', KEY_EQUAL );
379 initKey( '~', KEY_TILDE );
380 initKey( '`', KEY_QUOTELEFT );
381 initKey( '[', KEY_BRACKETLEFT );
382 initKey( ']', KEY_BRACKETRIGHT );
385 // =======================================================================
386 // -------
387 // SalData
388 // -------
390 SalData::SalData()
392 mhInst = 0; // default instance handle
393 mhPrevInst = 0; // previous instance handle
394 mnCmdShow = 0; // default frame show style
395 mhDitherPal = 0; // dither palette
396 mhDitherDIB = 0; // dither memory handle
397 mpDitherDIB = 0; // dither memory
398 mpDitherDIBData = 0; // beginning of DIB data
399 mpDitherDiff = 0; // Dither mapping table
400 mpDitherLow = 0; // Dither mapping table
401 mpDitherHigh = 0; // Dither mapping table
402 mnTimerMS = 0; // Current Time (in MS) of the Timer
403 mnTimerOrgMS = 0; // Current Original Time (in MS)
404 mnNextTimerTime = 0;
405 mnLastEventTime = 0;
406 mnTimerId = 0; // windows timer id
407 mbInTimerProc = FALSE; // timer event is currently being dispatched
408 mhSalObjMsgHook = 0; // hook to get interesting msg for SalObject
409 mhWantLeaveMsg = 0; // window handle, that want a MOUSELEAVE message
410 mpMouseLeaveTimer = 0; // Timer for MouseLeave Test
411 mpFirstInstance = 0; // pointer of first instance
412 mpFirstFrame = 0; // pointer of first frame
413 mpFirstObject = 0; // pointer of first object window
414 mpFirstVD = 0; // first VirDev
415 mpFirstPrinter = 0; // first printing printer
416 mpHDCCache = 0; // Cache for three DC's
417 mh50Bmp = 0; // 50% Bitmap
418 mh50Brush = 0; // 50% Brush
419 int i;
420 for(i=0; i<MAX_STOCKPEN; i++)
422 maStockPenColorAry[i] = 0;
423 mhStockPenAry[i] = 0;
425 for(i=0; i<MAX_STOCKBRUSH; i++)
427 maStockBrushColorAry[i] = 0;
428 mhStockBrushAry[i] = 0;
430 mnStockPenCount = 0; // count of static pens
431 mnStockBrushCount = 0; // count of static brushes
432 mnSalObjWantKeyEvt = 0; // KeyEvent, welcher vom SalObj-Hook verarbeitet werden soll
433 mnCacheDCInUse = 0; // count of CacheDC in use
434 mbObjClassInit = FALSE; // is SALOBJECTCLASS initialised
435 mbInPalChange = FALSE; // is in WM_QUERYNEWPALETTE
436 mnAppThreadId = 0; // Id from Applikation-Thread
437 mbScrSvrEnabled = FALSE; // ScreenSaver enabled
438 mnSageStatus = 0; // status of Sage-DLL (DISABLE_AGENT == nicht vorhanden)
439 mpSageEnableProc = 0; // funktion to deactivate the system agent
440 mpFirstIcon = 0; // icon cache, points to first icon, NULL if none
441 mpTempFontItem = 0;
442 mbThemeChanged = FALSE; // true if visual theme was changed: throw away theme handles
444 // init with NULL
445 gdiplusToken = 0;
447 initKeyCodeMap();
449 SetSalData( this );
450 initNWF();
453 SalData::~SalData()
455 deInitNWF();
456 SetSalData( NULL );
459 void InitSalData()
461 SalData* pSalData = new SalData;
462 CoInitialize(0);
464 // init GDIPlus
465 static Gdiplus::GdiplusStartupInput gdiplusStartupInput;
466 Gdiplus::GdiplusStartup(&pSalData->gdiplusToken, &gdiplusStartupInput, NULL);
470 void DeInitSalData()
472 CoUninitialize();
473 SalData* pSalData = GetSalData();
475 // deinit GDIPlus
476 if(pSalData)
478 Gdiplus::GdiplusShutdown(pSalData->gdiplusToken);
481 delete pSalData;
484 // -----------------------------------------------------------------------
486 void InitSalMain()
488 // remember data, copied from WinMain
489 SalData* pData = GetAppSalData();
490 if ( pData ) // Im AppServer NULL
492 STARTUPINFO aSI;
493 aSI.cb = sizeof( aSI );
494 GetStartupInfo( &aSI );
495 pData->mhInst = GetModuleHandle( NULL );
496 pData->mhPrevInst = NULL;
497 pData->mnCmdShow = aSI.wShowWindow;
501 void DeInitSalMain()
505 // -----------------------------------------------------------------------
507 SalInstance* CreateSalInstance()
509 SalData* pSalData = GetSalData();
511 // determine the windows version
512 aSalShlData.mbWNT = 0;
513 aSalShlData.mbWXP = 0;
514 aSalShlData.mbWPrinter = 0;
515 WORD nVer = (WORD)GetVersion();
516 aSalShlData.mnVersion = (((WORD)LOBYTE(nVer)) * 100) + HIBYTE(nVer);
517 if ( aSalShlData.mnVersion >= 400 )
518 aSalShlData.mbW40 = 1;
519 rtl_zeroMemory( &aSalShlData.maVersionInfo, sizeof(aSalShlData.maVersionInfo) );
520 aSalShlData.maVersionInfo.dwOSVersionInfoSize = sizeof( aSalShlData.maVersionInfo );
521 if ( GetVersionEx( &aSalShlData.maVersionInfo ) )
523 if ( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
525 aSalShlData.mbWNT = 1;
526 // Windows XP ?
527 if ( aSalShlData.maVersionInfo.dwMajorVersion > 5 ||
528 ( aSalShlData.maVersionInfo.dwMajorVersion == 5 && aSalShlData.maVersionInfo.dwMinorVersion >= 1 ) )
529 aSalShlData.mbWXP = 1;
530 if( aSalShlData.maVersionInfo.dwMajorVersion >= 5 )
531 aSalShlData.mbWPrinter = 1;
535 pSalData->mnAppThreadId = GetCurrentThreadId();
537 // register frame class
538 if ( !pSalData->mhPrevInst )
540 if ( aSalShlData.mbWNT )
542 WNDCLASSEXW aWndClassEx;
543 aWndClassEx.cbSize = sizeof( aWndClassEx );
544 aWndClassEx.style = CS_OWNDC;
545 aWndClassEx.lpfnWndProc = SalFrameWndProcW;
546 aWndClassEx.cbClsExtra = 0;
547 aWndClassEx.cbWndExtra = SAL_FRAME_WNDEXTRA;
548 aWndClassEx.hInstance = pSalData->mhInst;
549 aWndClassEx.hCursor = 0;
550 aWndClassEx.hbrBackground = 0;
551 aWndClassEx.lpszMenuName = 0;
552 aWndClassEx.lpszClassName = SAL_FRAME_CLASSNAMEW;
553 ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT, aWndClassEx.hIcon, aWndClassEx.hIconSm );
554 if ( !RegisterClassExW( &aWndClassEx ) )
555 return NULL;
557 aWndClassEx.hIcon = 0;
558 aWndClassEx.hIconSm = 0;
559 aWndClassEx.style |= CS_SAVEBITS;
560 aWndClassEx.lpszClassName = SAL_SUBFRAME_CLASSNAMEW;
561 if ( !RegisterClassExW( &aWndClassEx ) )
562 return NULL;
564 // shadow effect for popups on XP
565 if( aSalShlData.mbWXP )
566 aWndClassEx.style |= CS_DROPSHADOW;
567 aWndClassEx.lpszClassName = SAL_TMPSUBFRAME_CLASSNAMEW;
568 if ( !RegisterClassExW( &aWndClassEx ) )
569 return NULL;
571 aWndClassEx.style = 0;
572 aWndClassEx.lpfnWndProc = SalComWndProcW;
573 aWndClassEx.cbWndExtra = 0;
574 aWndClassEx.lpszClassName = SAL_COM_CLASSNAMEW;
575 if ( !RegisterClassExW( &aWndClassEx ) )
576 return NULL;
578 else
580 WNDCLASSEXA aWndClassEx;
581 aWndClassEx.cbSize = sizeof( aWndClassEx );
582 aWndClassEx.style = CS_OWNDC;
583 aWndClassEx.lpfnWndProc = SalFrameWndProcA;
584 aWndClassEx.cbClsExtra = 0;
585 aWndClassEx.cbWndExtra = SAL_FRAME_WNDEXTRA;
586 aWndClassEx.hInstance = pSalData->mhInst;
587 aWndClassEx.hCursor = 0;
588 aWndClassEx.hbrBackground = 0;
589 aWndClassEx.lpszMenuName = 0;
590 aWndClassEx.lpszClassName = SAL_FRAME_CLASSNAMEA;
591 ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT, aWndClassEx.hIcon, aWndClassEx.hIconSm );
592 if ( !RegisterClassExA( &aWndClassEx ) )
593 return NULL;
595 aWndClassEx.hIcon = 0;
596 aWndClassEx.hIconSm = 0;
597 aWndClassEx.style |= CS_SAVEBITS;
598 aWndClassEx.lpszClassName = SAL_SUBFRAME_CLASSNAMEA;
599 if ( !RegisterClassExA( &aWndClassEx ) )
600 return NULL;
602 aWndClassEx.style = 0;
603 aWndClassEx.lpfnWndProc = SalComWndProcA;
604 aWndClassEx.cbWndExtra = 0;
605 aWndClassEx.lpszClassName = SAL_COM_CLASSNAMEA;
606 if ( !RegisterClassExA( &aWndClassEx ) )
607 return NULL;
611 HWND hComWnd;
612 if ( aSalShlData.mbWNT )
614 hComWnd = CreateWindowExW( WS_EX_TOOLWINDOW, SAL_COM_CLASSNAMEW,
615 L"", WS_POPUP, 0, 0, 0, 0, 0, 0,
616 pSalData->mhInst, NULL );
618 else
620 hComWnd = CreateWindowExA( WS_EX_TOOLWINDOW, SAL_COM_CLASSNAMEA,
621 "", WS_POPUP, 0, 0, 0, 0, 0, 0,
622 pSalData->mhInst, NULL );
624 if ( !hComWnd )
625 return NULL;
627 WinSalInstance* pInst = new WinSalInstance;
629 // init instance (only one instance in this version !!!)
630 pSalData->mpFirstInstance = pInst;
631 pInst->mhInst = pSalData->mhInst;
632 pInst->mhComWnd = hComWnd;
634 // init static GDI Data
635 ImplInitSalGDI();
637 return pInst;
640 // -----------------------------------------------------------------------
642 void DestroySalInstance( SalInstance* pInst )
644 SalData* pSalData = GetSalData();
646 // (only one instance in this version !!!)
648 ImplFreeSalGDI();
650 // reset instance
651 if ( pSalData->mpFirstInstance == pInst )
652 pSalData->mpFirstInstance = NULL;
654 delete pInst;
657 // -----------------------------------------------------------------------
659 WinSalInstance::WinSalInstance()
661 mhComWnd = 0;
662 mpSalYieldMutex = new SalYieldMutex( this );
663 mpSalWaitMutex = new vos::OMutex;
664 mnYieldWaitCount = 0;
665 mpSalYieldMutex->acquire();
668 // -----------------------------------------------------------------------
670 WinSalInstance::~WinSalInstance()
672 mpSalYieldMutex->release();
673 delete mpSalYieldMutex;
674 delete mpSalWaitMutex;
675 DestroyWindow( mhComWnd );
678 // -----------------------------------------------------------------------
680 vos::IMutex* WinSalInstance::GetYieldMutex()
682 return mpSalYieldMutex;
685 // -----------------------------------------------------------------------
687 ULONG WinSalInstance::ReleaseYieldMutex()
689 return ImplSalReleaseYieldMutex();
692 // -----------------------------------------------------------------------
694 void WinSalInstance::AcquireYieldMutex( ULONG nCount )
696 ImplSalAcquireYieldMutex( nCount );
699 // -----------------------------------------------------------------------
701 static void ImplSalDispatchMessage( MSG* pMsg )
703 SalData* pSalData = GetSalData();
704 if ( pSalData->mpFirstObject )
706 if ( ImplSalPreDispatchMsg( pMsg ) )
707 return;
709 LRESULT lResult = ImplDispatchMessage( pMsg );
710 if ( pSalData->mpFirstObject )
711 ImplSalPostDispatchMsg( pMsg, lResult );
714 // -----------------------------------------------------------------------
716 void ImplSalYield( BOOL bWait, BOOL bHandleAllCurrentEvents )
718 MSG aMsg;
719 bool bWasMsg = false, bOneEvent = false;
721 int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
724 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
726 TranslateMessage( &aMsg );
727 ImplSalDispatchMessage( &aMsg );
728 bOneEvent = bWasMsg = true;
730 else
731 bOneEvent = false;
732 } while( --nMaxEvents && bOneEvent );
734 if ( bWait && ! bWasMsg )
736 if ( ImplGetMessage( &aMsg, 0, 0, 0 ) )
738 TranslateMessage( &aMsg );
739 ImplSalDispatchMessage( &aMsg );
744 // -----------------------------------------------------------------------
746 void WinSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
748 SalYieldMutex* pYieldMutex = mpSalYieldMutex;
749 SalData* pSalData = GetSalData();
750 DWORD nCurThreadId = GetCurrentThreadId();
751 ULONG nCount = pYieldMutex->GetAcquireCount( nCurThreadId );
752 ULONG n = nCount;
753 while ( n )
755 pYieldMutex->release();
756 n--;
758 if ( pSalData->mnAppThreadId != nCurThreadId )
760 // #97739# A SendMessage call blocks until the called thread (here: the main thread)
761 // returns. During a yield however, messages are processed in the main thread that might
762 // result in a new message loop due to opening a dialog. Thus, SendMessage would not
763 // return which will block this thread!
764 // Solution: just give up the time slice and hope that messages are processed
765 // by the main thread anyway (where all windows are created)
766 // If the mainthread is not currently handling messages, then our SendMessage would
767 // also do nothing, so this seems to be reasonable.
769 // #i18883# only sleep if potential deadlock scenario, ie, when a dialog is open
770 if( ImplGetSVData()->maAppData.mnModalMode )
771 Sleep(1);
772 else
773 ImplSendMessage( mhComWnd, SAL_MSG_THREADYIELD, (WPARAM)bWait, (LPARAM)bHandleAllCurrentEvents );
775 n = nCount;
776 while ( n )
778 pYieldMutex->acquire();
779 n--;
782 else
784 ImplSalYield( bWait, bHandleAllCurrentEvents );
786 n = nCount;
787 while ( n )
789 ImplSalYieldMutexAcquireWithWait();
790 n--;
795 // -----------------------------------------------------------------------
797 LRESULT CALLBACK SalComWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
799 LRESULT nRet = 0;
802 switch ( nMsg )
804 case SAL_MSG_PRINTABORTJOB:
805 ImplSalPrinterAbortJobAsync( (HDC)wParam );
806 rDef = FALSE;
807 break;
808 case SAL_MSG_THREADYIELD:
809 ImplSalYield( (BOOL)wParam, (BOOL)lParam );
810 rDef = FALSE;
811 break;
812 // If we get this message, because another GetMessage() call
813 // has recieved this message, we must post this message to
814 // us again, because in the other case we wait forever.
815 case SAL_MSG_RELEASEWAITYIELD:
817 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
818 if ( pInst && pInst->mnYieldWaitCount )
819 ImplPostMessage( hWnd, SAL_MSG_RELEASEWAITYIELD, wParam, lParam );
821 rDef = FALSE;
822 break;
823 case SAL_MSG_STARTTIMER:
824 ImplSalStartTimer( (ULONG) lParam, FALSE );
825 rDef = FALSE;
826 break;
827 case SAL_MSG_CREATEFRAME:
828 nRet = (LRESULT)ImplSalCreateFrame( GetSalData()->mpFirstInstance, (HWND)lParam, (ULONG)wParam );
829 rDef = FALSE;
830 break;
831 case SAL_MSG_RECREATEHWND:
832 nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, FALSE );
833 rDef = FALSE;
834 break;
835 case SAL_MSG_RECREATECHILDHWND:
836 nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, TRUE );
837 rDef = FALSE;
838 break;
839 case SAL_MSG_DESTROYFRAME:
840 delete (SalFrame*)lParam;
841 rDef = FALSE;
842 break;
843 case SAL_MSG_DESTROYHWND:
844 //We only destroy the native window here. We do NOT destroy the SalFrame contained
845 //in the structure (GetWindowPtr()).
846 if (DestroyWindow((HWND)lParam) == 0)
848 OSL_ENSURE(0, "DestroyWindow failed!");
849 //Failure: We remove the SalFrame from the window structure. So we avoid that
850 // the window structure may contain an invalid pointer, once the SalFrame is deleted.
851 SetWindowPtr((HWND)lParam, 0);
853 rDef = FALSE;
854 break;
855 case SAL_MSG_CREATEOBJECT:
856 nRet = (LRESULT)ImplSalCreateObject( GetSalData()->mpFirstInstance, (WinSalFrame*)lParam );
857 rDef = FALSE;
858 break;
859 case SAL_MSG_DESTROYOBJECT:
860 delete (SalObject*)lParam;
861 rDef = FALSE;
862 break;
863 case SAL_MSG_GETDC:
864 nRet = (LRESULT)GetDCEx( (HWND)wParam, 0, DCX_CACHE );
865 rDef = FALSE;
866 break;
867 case SAL_MSG_RELEASEDC:
868 ReleaseDC( (HWND)wParam, (HDC)lParam );
869 rDef = FALSE;
870 break;
871 case SAL_MSG_POSTTIMER:
872 SalTimerProc( 0, 0, SALTIMERPROC_RECURSIVE, lParam );
873 break;
876 return nRet;
879 LRESULT CALLBACK SalComWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
881 int bDef = TRUE;
882 LRESULT nRet = 0;
883 #ifdef __MINGW32__
884 jmp_buf jmpbuf;
885 __SEHandler han;
886 if (__builtin_setjmp(jmpbuf) == 0)
888 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
889 #else
890 __try
892 #endif
893 nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef );
895 #ifdef __MINGW32__
896 han.Reset();
897 #else
898 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
901 #endif
902 if ( bDef )
904 if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) )
905 nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
907 return nRet;
910 LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
912 int bDef = TRUE;
913 LRESULT nRet = 0;
914 #ifdef __MINGW32__
915 jmp_buf jmpbuf;
916 __SEHandler han;
917 if (__builtin_setjmp(jmpbuf) == 0)
919 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
920 #else
921 __try
923 #endif
924 nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef );
926 #ifdef __MINGW32__
927 han.Reset();
928 #else
929 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
932 #endif
933 if ( bDef )
935 if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) )
936 nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
938 return nRet;
941 // -----------------------------------------------------------------------
943 bool WinSalInstance::AnyInput( USHORT nType )
945 MSG aMsg;
947 if ( (nType & (INPUT_ANY)) == (INPUT_ANY) )
949 // revert bugfix for #108919# which never reported timeouts when called from the timer handler
950 // which made the application completely unresponsive during background formatting
951 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) )
952 return true;
954 else
956 if ( nType & INPUT_MOUSE )
958 // Test for mouse input
959 if ( ImplPeekMessage( &aMsg, 0, WM_MOUSEFIRST, WM_MOUSELAST,
960 PM_NOREMOVE | PM_NOYIELD ) )
961 return true;
964 if ( nType & INPUT_KEYBOARD )
966 // Test for key input
967 if ( ImplPeekMessage( &aMsg, 0, WM_KEYDOWN, WM_KEYDOWN,
968 PM_NOREMOVE | PM_NOYIELD ) )
970 if ( (aMsg.wParam == VK_SHIFT) ||
971 (aMsg.wParam == VK_CONTROL) ||
972 (aMsg.wParam == VK_MENU) )
973 return false;
974 else
975 return true;
979 if ( nType & INPUT_PAINT )
981 // Test for paint input
982 if ( ImplPeekMessage( &aMsg, 0, WM_PAINT, WM_PAINT,
983 PM_NOREMOVE | PM_NOYIELD ) )
984 return true;
986 if ( ImplPeekMessage( &aMsg, 0, WM_SIZE, WM_SIZE,
987 PM_NOREMOVE | PM_NOYIELD ) )
988 return true;
990 if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTCALLSIZE, SAL_MSG_POSTCALLSIZE,
991 PM_NOREMOVE | PM_NOYIELD ) )
992 return true;
994 if ( ImplPeekMessage( &aMsg, 0, WM_MOVE, WM_MOVE,
995 PM_NOREMOVE | PM_NOYIELD ) )
996 return true;
998 if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTMOVE, SAL_MSG_POSTMOVE,
999 PM_NOREMOVE | PM_NOYIELD ) )
1000 return true;
1003 if ( nType & INPUT_TIMER )
1005 // Test for timer input
1006 if ( ImplPeekMessage( &aMsg, 0, WM_TIMER, WM_TIMER,
1007 PM_NOREMOVE | PM_NOYIELD ) )
1008 return true;
1012 if ( nType & INPUT_OTHER )
1014 // Test for any input
1015 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) )
1016 return true;
1020 return FALSE;
1023 // -----------------------------------------------------------------------
1025 void SalTimer::Start( ULONG nMS )
1027 // Um auf Main-Thread umzuschalten
1028 SalData* pSalData = GetSalData();
1029 if ( pSalData->mpFirstInstance )
1031 if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
1032 ImplPostMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
1033 else
1034 ImplSendMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
1036 else
1037 ImplSalStartTimer( nMS, FALSE );
1040 // -----------------------------------------------------------------------
1042 SalFrame* WinSalInstance::CreateChildFrame( SystemParentData* pSystemParentData, ULONG nSalFrameStyle )
1044 // Um auf Main-Thread umzuschalten
1045 return (SalFrame*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEFRAME, nSalFrameStyle, (LPARAM)pSystemParentData->hWnd );
1048 // -----------------------------------------------------------------------
1050 SalFrame* WinSalInstance::CreateFrame( SalFrame* pParent, ULONG nSalFrameStyle )
1052 // Um auf Main-Thread umzuschalten
1053 HWND hWndParent;
1054 if ( pParent )
1055 hWndParent = static_cast<WinSalFrame*>(pParent)->mhWnd;
1056 else
1057 hWndParent = 0;
1058 return (SalFrame*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEFRAME, nSalFrameStyle, (LPARAM)hWndParent );
1061 // -----------------------------------------------------------------------
1063 void WinSalInstance::DestroyFrame( SalFrame* pFrame )
1065 ImplSendMessage( mhComWnd, SAL_MSG_DESTROYFRAME, 0, (LPARAM)pFrame );
1068 // -----------------------------------------------------------------------
1070 SalObject* WinSalInstance::CreateObject( SalFrame* pParent,
1071 SystemWindowData* /*pWindowData*/, // SystemWindowData meaningless on Windows
1072 BOOL /*bShow*/ )
1074 // Um auf Main-Thread umzuschalten
1075 return (SalObject*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEOBJECT, 0, (LPARAM)static_cast<WinSalFrame*>(pParent) );
1078 // -----------------------------------------------------------------------
1080 void WinSalInstance::DestroyObject( SalObject* pObject )
1082 ImplSendMessage( mhComWnd, SAL_MSG_DESTROYOBJECT, 0, (LPARAM)pObject );
1085 // -----------------------------------------------------------------------
1087 void* WinSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes )
1089 rReturnedBytes = 1;
1090 rReturnedType = AsciiCString;
1091 return const_cast<char *>("");
1094 // -----------------------------------------------------------------------
1096 /** Add a file to the system shells recent document list if there is any.
1097 This function may have no effect under Unix because there is no
1098 standard API among the different desktop managers.
1100 @param aFileUrl
1101 The file url of the document.
1103 void WinSalInstance::AddToRecentDocumentList(const rtl::OUString& rFileUrl, const rtl::OUString& /*rMimeType*/)
1105 rtl::OUString system_path;
1106 osl::FileBase::RC rc = osl::FileBase::getSystemPathFromFileURL(rFileUrl, system_path);
1108 OSL_ENSURE(osl::FileBase::E_None == rc, "Invalid file url");
1110 if (osl::FileBase::E_None == rc)
1111 SHAddToRecentDocs(SHARD_PATHW, system_path.getStr());
1114 // -----------------------------------------------------------------------
1116 SalTimer* WinSalInstance::CreateSalTimer()
1118 return new WinSalTimer();
1121 // -----------------------------------------------------------------------
1123 SalBitmap* WinSalInstance::CreateSalBitmap()
1125 return new WinSalBitmap();
1128 class WinImeStatus : public SalI18NImeStatus
1130 public:
1131 WinImeStatus() {}
1132 virtual ~WinImeStatus() {}
1134 // asks whether there is a status window available
1135 // to toggle into menubar
1136 virtual bool canToggle() { return false; }
1137 virtual void toggle() {}
1140 SalI18NImeStatus* WinSalInstance::CreateI18NImeStatus()
1142 return new WinImeStatus();
1145 // -----------------------------------------------------------------------
1147 const ::rtl::OUString& SalGetDesktopEnvironment()
1149 static ::rtl::OUString aDesktopEnvironment( RTL_CONSTASCII_USTRINGPARAM( "Windows" ) );
1150 return aDesktopEnvironment;
1153 SalSession* WinSalInstance::CreateSalSession()
1155 return NULL;
1158 #ifndef __MINGW32__
1159 // -----------------------------------------------------------------------
1160 int WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(int, LPEXCEPTION_POINTERS pExceptionInfo)
1162 // Decide if an exception is a c++ (mostly UNO) exception or a process violation.
1163 // Depending on this information we pass process violations directly to our signal handler ...
1164 // and c++ (UNO) exceptions are sended to the following code on the current stack.
1165 // Problem behind: user32.dll sometime consumes exceptions/process violations .-)
1166 // see also #112221#
1168 static DWORD EXCEPTION_MSC_CPP_EXCEPTION = 0xE06D7363;
1170 if (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_MSC_CPP_EXCEPTION)
1171 return EXCEPTION_CONTINUE_SEARCH;
1173 return UnhandledExceptionFilter( pExceptionInfo );
1175 #endif