xref: /trunk/main/vcl/win/source/window/salframe.cxx (revision 79aad27f)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 // i72022: ad-hoc to forcibly enable reconversion
28 #if WINVER < 0x0500
29 #undef WINVER
30 #define WINVER 0x0500
31 #endif
32 
33 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34 #include <com/sun/star/container/XIndexAccess.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/awt/Rectangle.hpp>
37 #include <comphelper/processfactory.hxx>
38 #include <unotools/misccfg.hxx>
39 
40 #include <string.h>
41 #include <limits.h>
42 
43 #include <stdio.h>
44 
45 #include <tools/svwin.h>
46 #ifdef __MINGW32__
47 #include <excpt.h>
48 #endif
49 
50 #include <rtl/string.h>
51 #include <rtl/ustring.h>
52 
53 #include <osl/module.h>
54 
55 #include <tools/debug.hxx>
56 
57 #include <vcl/sysdata.hxx>
58 #include <vcl/timer.hxx>
59 #include <vcl/settings.hxx>
60 #include <vcl/keycodes.hxx>
61 #include <vcl/window.hxx>
62 #include <vcl/wrkwin.hxx>
63 #include <vcl/svapp.hxx>
64 #include <vcl/impdel.hxx>
65 
66 // Warning in SDK header
67 #if defined(_MSC_VER) && (_MSC_VER > 1400)
68 #pragma warning( disable: 4242 4244 )
69 #endif
70 #include <win/wincomp.hxx>
71 #include <win/salids.hrc>
72 #include <win/saldata.hxx>
73 #include <win/salinst.h>
74 #include <win/salbmp.h>
75 #include <win/salgdi.h>
76 #include <win/salsys.h>
77 #include <win/salframe.h>
78 #include <win/salvd.h>
79 #include <win/salmenu.h>
80 #include <win/salobj.h>
81 #include <win/saltimer.h>
82 
83 #include <impbmp.hxx>
84 #include <window.h>
85 #include <sallayout.hxx>
86 
87 #define COMPILE_MULTIMON_STUBS
88 #include <multimon.h>
89 #include <vector>
90 #ifdef __MINGW32__
91 #include <algorithm>
92 using ::std::max;
93 #endif
94 
95 #include <com/sun/star/uno/Exception.hdl>
96 
97 #include <time.h>
98 
99 using ::rtl::OUString;
100 using namespace ::com::sun::star;
101 using namespace ::com::sun::star::uno;
102 using namespace ::com::sun::star::lang;
103 using namespace ::com::sun::star::container;
104 using namespace ::com::sun::star::beans;
105 
106 // The following defines are newly added in Longhorn
107 #ifndef WM_MOUSEHWHEEL
108 # define WM_MOUSEHWHEEL            0x020E
109 #endif
110 #ifndef SPI_GETWHEELSCROLLCHARS
111 # define SPI_GETWHEELSCROLLCHARS   0x006C
112 #endif
113 #ifndef SPI_SETWHEELSCROLLCHARS
114 # define SPI_SETWHEELSCROLLCHARS   0x006D
115 #endif
116 
117 
118 
119 #if OSL_DEBUG_LEVEL > 1
120 void MyOutputDebugString( char *s) { OutputDebugString( s ); }
121 #endif
122 
123 // misssing prototypes and constants for LayeredWindows
124 extern "C" {
125     //WINUSERAPI sal_Bool WINAPI SetLayeredWindowAttributes(HWND,COLORREF,BYTE,DWORD);
126     typedef sal_Bool ( WINAPI * SetLayeredWindowAttributes_Proc_T ) (HWND,COLORREF,BYTE,DWORD);
127     static SetLayeredWindowAttributes_Proc_T lpfnSetLayeredWindowAttributes;
128 };
129 
130 // =======================================================================
131 
132 const unsigned int WM_USER_SYSTEM_WINDOW_ACTIVATED = RegisterWindowMessageA("SYSTEM_WINDOW_ACTIVATED");
133 
134 sal_Bool WinSalFrame::mbInReparent = FALSE;
135 
136 // =======================================================================
137 
138 // Wegen Fehler in Windows-Headerfiles
139 #ifndef IMN_OPENCANDIDATE
140 #define IMN_OPENCANDIDATE               0x0005
141 #endif
142 #ifndef IMN_CLOSECANDIDATE
143 #define IMN_CLOSECANDIDATE              0x0004
144 #endif
145 
146 #ifndef WM_THEMECHANGED
147 #define WM_THEMECHANGED                 0x031A
148 #endif
149 
150 // Macros for support of WM_UNICHAR & Keyman 6.0
151 #define Uni_UTF32ToSurrogate1(ch)   (((unsigned long) (ch) - 0x10000) / 0x400 + 0xD800)
152 #define Uni_UTF32ToSurrogate2(ch)   (((unsigned long) (ch) - 0x10000) % 0x400 + 0xDC00)
153 #define Uni_SupplementaryPlanesStart    0x10000
154 
155 // =======================================================================
156 
157 static void UpdateFrameGeometry( HWND hWnd, WinSalFrame* pFrame );
158 static void SetMaximizedFrameGeometry( HWND hWnd, WinSalFrame* pFrame, RECT* pParentRect = NULL );
159 
160 static void ImplSaveFrameState( WinSalFrame* pFrame )
161 {
162     // Position, Groesse und Status fuer GetWindowState() merken
163     if ( !pFrame->mbFullScreen )
164     {
165         sal_Bool bVisible = (GetWindowStyle( pFrame->mhWnd ) & WS_VISIBLE) != 0;
166         if ( IsIconic( pFrame->mhWnd ) )
167         {
168             pFrame->maState.mnState |= SAL_FRAMESTATE_MINIMIZED;
169             if ( bVisible )
170                 pFrame->mnShowState = SW_SHOWMAXIMIZED;
171         }
172         else if ( IsZoomed( pFrame->mhWnd ) )
173         {
174             pFrame->maState.mnState &= ~SAL_FRAMESTATE_MINIMIZED;
175             pFrame->maState.mnState |= SAL_FRAMESTATE_MAXIMIZED;
176             if ( bVisible )
177                 pFrame->mnShowState = SW_SHOWMAXIMIZED;
178             pFrame->mbRestoreMaximize = TRUE;
179 
180             WINDOWPLACEMENT aPlacement;
181             aPlacement.length = sizeof(aPlacement);
182             if( GetWindowPlacement( pFrame->mhWnd, &aPlacement ) )
183             {
184                 RECT aRect = aPlacement.rcNormalPosition;
185                 RECT aRect2 = aRect;
186                 AdjustWindowRectEx( &aRect2, GetWindowStyle( pFrame->mhWnd ),
187                                     FALSE,  GetWindowExStyle( pFrame->mhWnd ) );
188                 long nTopDeco = abs( aRect.top - aRect2.top );
189                 long nLeftDeco = abs( aRect.left - aRect2.left );
190                 long nBottomDeco = abs( aRect.bottom - aRect2.bottom );
191                 long nRightDeco = abs( aRect.right - aRect2.right );
192 
193                 pFrame->maState.mnX      = aRect.left + nLeftDeco;
194                 pFrame->maState.mnY      = aRect.top + nTopDeco;
195                 pFrame->maState.mnWidth  = aRect.right - aRect.left - nLeftDeco - nRightDeco;
196                 pFrame->maState.mnHeight = aRect.bottom - aRect.top - nTopDeco - nBottomDeco;
197             }
198         }
199         else
200         {
201             RECT aRect;
202             GetWindowRect( pFrame->mhWnd, &aRect );
203 
204             // to be consistent with Unix, the frame state is without(!) decoration
205             RECT aRect2 = aRect;
206 		    AdjustWindowRectEx( &aRect2, GetWindowStyle( pFrame->mhWnd ),
207 							FALSE,     GetWindowExStyle( pFrame->mhWnd ) );
208             long nTopDeco = abs( aRect.top - aRect2.top );
209             long nLeftDeco = abs( aRect.left - aRect2.left );
210             long nBottomDeco = abs( aRect.bottom - aRect2.bottom );
211             long nRightDeco = abs( aRect.right - aRect2.right );
212 
213             pFrame->maState.mnState &= ~(SAL_FRAMESTATE_MINIMIZED | SAL_FRAMESTATE_MAXIMIZED);
214             // subtract decoration
215             pFrame->maState.mnX      = aRect.left+nLeftDeco;
216             pFrame->maState.mnY      = aRect.top+nTopDeco;
217             pFrame->maState.mnWidth  = aRect.right-aRect.left-nLeftDeco-nRightDeco;
218             pFrame->maState.mnHeight = aRect.bottom-aRect.top-nTopDeco-nBottomDeco;
219             if ( bVisible )
220                 pFrame->mnShowState = SW_SHOWNORMAL;
221             pFrame->mbRestoreMaximize = FALSE;
222         }
223     }
224 }
225 
226 // -----------------------------------------------------------------------
227 
228 // if pParentRect is set, the workarea of the monitor that contains pParentRect is returned
229 void ImplSalGetWorkArea( HWND hWnd, RECT *pRect, const RECT *pParentRect )
230 {
231 	static int winVerChecked = 0;
232 	static int winVerOk = 0;
233 
234     // check if we or our parent is fullscreen, then the taskbar should be ignored
235     bool bIgnoreTaskbar = false;
236     WinSalFrame* pFrame = GetWindowPtr( hWnd );
237 	if( pFrame )
238     {
239 	    Window *pWin = pFrame->GetWindow();
240         while( pWin )
241         {
242             WorkWindow *pWorkWin = (pWin->GetType() == WINDOW_WORKWINDOW) ? (WorkWindow *) pWin : NULL;
243             if( pWorkWin && pWorkWin->ImplGetWindowImpl()->mbReallyVisible && pWorkWin->IsFullScreenMode() )
244             {
245                 bIgnoreTaskbar = true;
246                 break;
247             }
248             else
249                 pWin = pWin->ImplGetWindowImpl()->mpParent;
250         }
251     }
252 
253     if( !winVerChecked )
254 	{
255 		winVerChecked = 1;
256 		winVerOk = 1;
257 
258 		// multi monitor calls not available on Win95/NT
259         if ( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
260         {
261             if ( aSalShlData.maVersionInfo.dwMajorVersion <= 4 )
262                 winVerOk = 0;	// NT
263         }
264         else if( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
265         {
266             if ( aSalShlData.maVersionInfo.dwMajorVersion == 4 && aSalShlData.maVersionInfo.dwMinorVersion == 0 )
267                 winVerOk = 0;	// Win95
268         }
269 	}
270 
271     // calculates the work area taking multiple monitors into account
272     if( winVerOk )
273     {
274         static int nMonitors = GetSystemMetrics( SM_CMONITORS );
275         if( nMonitors == 1 )
276         {
277             if( bIgnoreTaskbar )
278             {
279                 pRect->left = pRect->top = 0;
280                 pRect->right   = GetSystemMetrics( SM_CXSCREEN );
281                 pRect->bottom  = GetSystemMetrics( SM_CYSCREEN );
282             }
283             else
284 	            SystemParametersInfo( SPI_GETWORKAREA, 0, pRect, 0 );
285         }
286         else
287         {
288             if( pParentRect != NULL )
289             {
290                 // return the size of the monitor where pParentRect lives
291                 HMONITOR hMonitor;
292                 MONITORINFO mi;
293 
294                 // get the nearest monitor to the passed rect.
295                 hMonitor = MonitorFromRect(pParentRect, MONITOR_DEFAULTTONEAREST);
296 
297                 // get the work area or entire monitor rect.
298                 mi.cbSize = sizeof(mi);
299                 GetMonitorInfo(hMonitor, &mi);
300                 if( !bIgnoreTaskbar )
301                     *pRect = mi.rcWork;
302                 else
303                     *pRect = mi.rcMonitor;
304             }
305             else
306             {
307                 // return the union of all monitors
308                 pRect->left = GetSystemMetrics( SM_XVIRTUALSCREEN );
309                 pRect->top = GetSystemMetrics( SM_YVIRTUALSCREEN );
310                 pRect->right = pRect->left + GetSystemMetrics( SM_CXVIRTUALSCREEN );
311                 pRect->bottom = pRect->top + GetSystemMetrics( SM_CYVIRTUALSCREEN );
312 
313                 // virtualscreen does not take taskbar into account, so use the corresponding
314                 // diffs between screen and workarea from the default screen
315                 // however, this is still not perfect: the taskbar might not be on the primary screen
316                 if( !bIgnoreTaskbar )
317                 {
318                     RECT wRect, scrRect;
319                     SystemParametersInfo( SPI_GETWORKAREA, 0, &wRect, 0 );
320                     scrRect.left = 0;
321                     scrRect.top = 0;
322                     scrRect.right = GetSystemMetrics( SM_CXSCREEN );
323                     scrRect.bottom = GetSystemMetrics( SM_CYSCREEN );
324 
325                     pRect->left += wRect.left;
326                     pRect->top += wRect.top;
327                     pRect->right -= scrRect.right - wRect.right;
328                     pRect->bottom -= scrRect.bottom - wRect.bottom;
329                 }
330             }
331         }
332     }
333     else
334     {
335         if( bIgnoreTaskbar )
336         {
337             pRect->left = pRect->top = 0;
338             pRect->right   = GetSystemMetrics( SM_CXSCREEN );
339             pRect->bottom  = GetSystemMetrics( SM_CYSCREEN );
340         }
341         else
342 	        SystemParametersInfo( SPI_GETWORKAREA, 0, pRect, 0 );
343     }
344 }
345 
346 // =======================================================================
347 
348 SalFrame* ImplSalCreateFrame( WinSalInstance* pInst,
349                               HWND hWndParent, sal_uLong nSalFrameStyle )
350 {
351     WinSalFrame*   pFrame = new WinSalFrame;
352     HWND        hWnd;
353     DWORD       nSysStyle = 0;
354     DWORD       nExSysStyle = 0;
355     sal_Bool        bSubFrame = FALSE;
356 
357     if( getenv( "SAL_SYNCHRONIZE" ) )   // no buffering of drawing commands
358         GdiSetBatchLimit( 1 );
359 
360     static int bLayeredAPI = -1;
361     if( bLayeredAPI == -1 )
362     {
363         bLayeredAPI = 0;
364         // check for W2k and XP
365         if ( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && aSalShlData.maVersionInfo.dwMajorVersion >= 5 )
366         {
367             OUString aLibraryName( RTL_CONSTASCII_USTRINGPARAM( "user32" ) );
368             oslModule pLib = osl_loadModule( aLibraryName.pData, SAL_LOADMODULE_DEFAULT );
369             oslGenericFunction pFunc = NULL;
370             if( pLib )
371                 pFunc = osl_getAsciiFunctionSymbol( pLib, "SetLayeredWindowAttributes" );
372 
373             lpfnSetLayeredWindowAttributes = ( SetLayeredWindowAttributes_Proc_T ) pFunc;
374 
375             bLayeredAPI = pFunc ? 1 : 0;
376         }
377     }
378     static const char* pEnvTransparentFloats = getenv("SAL_TRANSPARENT_FLOATS" );
379 
380     // determine creation data
381     if ( nSalFrameStyle & (SAL_FRAME_STYLE_PLUG | SAL_FRAME_STYLE_SYSTEMCHILD) )
382     {
383         nSysStyle |= WS_CHILD;
384         if( nSalFrameStyle & SAL_FRAME_STYLE_SYSTEMCHILD )
385             nSysStyle |= WS_CLIPSIBLINGS;
386     }
387     else
388     {
389         // #i87402# commenting out WS_CLIPCHILDREN
390         // this breaks SAL_FRAME_STYLE_SYSTEMCHILD handling, which is not
391         // used currently. Probably SAL_FRAME_STYLE_SYSTEMCHILD should be
392         // removed again.
393 
394         // nSysStyle  |= WS_CLIPCHILDREN;
395         if ( hWndParent )
396         {
397             nSysStyle |= WS_POPUP;
398             bSubFrame = TRUE;
399             pFrame->mbNoIcon = TRUE;
400         }
401         else
402         {
403             // Only with WS_OVRLAPPED we get a useful default position/size
404             if ( (nSalFrameStyle & (SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_MOVEABLE)) ==
405                  (SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_MOVEABLE) )
406                 nSysStyle |= WS_OVERLAPPED;
407             else
408             {
409                 nSysStyle |= WS_POPUP;
410                 if ( !(nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE) )
411                     nExSysStyle |= WS_EX_TOOLWINDOW;    // avoid taskbar appearance, for eg splash screen
412             }
413         }
414 
415         if ( nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE )
416         {
417             pFrame->mbCaption = TRUE;
418             nSysStyle |= WS_SYSMENU | WS_CAPTION;
419             if ( !hWndParent )
420                 nSysStyle |= WS_SYSMENU | WS_MINIMIZEBOX;
421             else
422                 nExSysStyle |= WS_EX_DLGMODALFRAME;
423 
424             if ( nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE )
425             {
426                 pFrame->mbSizeBorder = TRUE;
427                 nSysStyle |= WS_THICKFRAME;
428                 if ( !hWndParent )
429                     nSysStyle |= WS_MAXIMIZEBOX;
430             }
431             else
432                 pFrame->mbFixBorder = TRUE;
433 
434             if ( nSalFrameStyle & SAL_FRAME_STYLE_DEFAULT )
435                 nExSysStyle |= WS_EX_APPWINDOW;
436         }
437         if( nSalFrameStyle & SAL_FRAME_STYLE_TOOLWINDOW
438             // #100656# toolwindows lead to bad alt-tab behaviour, if they have the focus
439             // you must press it twice to leave the application
440             // so toolwindows are only used for non sizeable windows
441             // which are typically small, so a small caption makes sense
442 
443             // #103578# looked too bad - above changes reverted
444             /* && !(nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE) */ )
445         {
446             pFrame->mbNoIcon = TRUE;
447             nExSysStyle |= WS_EX_TOOLWINDOW;
448             if ( pEnvTransparentFloats && bLayeredAPI == 1 /*&& !(nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE) */)
449                 nExSysStyle |= WS_EX_LAYERED;
450         }
451     }
452     if ( nSalFrameStyle & SAL_FRAME_STYLE_FLOAT )
453     {
454         nExSysStyle |= WS_EX_TOOLWINDOW;
455         pFrame->mbFloatWin = TRUE;
456 
457         if ( (bLayeredAPI == 1) && (pEnvTransparentFloats /* does not work remote! || (nSalFrameStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) */ )  )
458             nExSysStyle |= WS_EX_LAYERED;
459 
460     }
461     if( (nSalFrameStyle & SAL_FRAME_STYLE_TOOLTIP) || (nSalFrameStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) )
462         nExSysStyle |= WS_EX_TOPMOST;
463 
464     // init frame data
465     pFrame->mnStyle = nSalFrameStyle;
466 
467     // determine show style
468     pFrame->mnShowState = SW_SHOWNORMAL;
469     if ( (nSysStyle & (WS_POPUP | WS_MAXIMIZEBOX | WS_THICKFRAME)) == (WS_MAXIMIZEBOX | WS_THICKFRAME) )
470     {
471         if ( GetSystemMetrics( SM_CXSCREEN ) <= 1024 )
472             pFrame->mnShowState = SW_SHOWMAXIMIZED;
473         else
474         {
475             if ( nSalFrameStyle & SAL_FRAME_STYLE_DEFAULT )
476             {
477                 SalData* pSalData = GetSalData();
478                 pFrame->mnShowState = pSalData->mnCmdShow;
479                 if ( (pFrame->mnShowState != SW_SHOWMINIMIZED) &&
480                      (pFrame->mnShowState != SW_MINIMIZE) &&
481                      (pFrame->mnShowState != SW_SHOWMINNOACTIVE) )
482                 {
483                     if ( (pFrame->mnShowState == SW_SHOWMAXIMIZED) ||
484                          (pFrame->mnShowState == SW_MAXIMIZE) )
485                         pFrame->mbOverwriteState = FALSE;
486                     pFrame->mnShowState = SW_SHOWMAXIMIZED;
487                 }
488                 else
489                     pFrame->mbOverwriteState = FALSE;
490             }
491             else
492             {
493                 // Document Windows are also maximized, if the current Document Window
494                 // is also maximized
495                 HWND hWnd = GetForegroundWindow();
496                 if ( hWnd && IsMaximized( hWnd ) &&
497                      (GetWindowInstance( hWnd ) == pInst->mhInst) &&
498                      ((GetWindowStyle( hWnd ) & (WS_POPUP | WS_MAXIMIZEBOX | WS_THICKFRAME)) == (WS_MAXIMIZEBOX | WS_THICKFRAME)) )
499                     pFrame->mnShowState = SW_SHOWMAXIMIZED;
500             }
501         }
502     }
503 
504     // create frame
505     if( true/*aSalShlData.mbWNT*/ )
506     {
507         LPCWSTR pClassName;
508         if ( bSubFrame )
509         {
510             if ( nSalFrameStyle & (SAL_FRAME_STYLE_MOVEABLE|SAL_FRAME_STYLE_NOSHADOW) ) // check if shadow not wanted
511                 pClassName = SAL_SUBFRAME_CLASSNAMEW;
512             else
513                 pClassName = SAL_TMPSUBFRAME_CLASSNAMEW;    // undecorated floaters will get shadow on XP
514         }
515         else
516         {
517             if ( nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE )
518                 pClassName = SAL_FRAME_CLASSNAMEW;
519             else
520                 pClassName = SAL_TMPSUBFRAME_CLASSNAMEW;
521         }
522         hWnd = CreateWindowExW( nExSysStyle, pClassName, L"", nSysStyle,
523                                 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
524                                 hWndParent, 0, pInst->mhInst, (void*)pFrame );
525         if( !hWnd )
526             ImplWriteLastError( GetLastError(), "CreateWindowEx" );
527 #if OSL_DEBUG_LEVEL > 1
528         // set transparency value
529         if( bLayeredAPI == 1 && GetWindowExStyle( hWnd ) & WS_EX_LAYERED )
530             lpfnSetLayeredWindowAttributes( hWnd, 0, 230, 0x00000002 /*LWA_ALPHA*/ );
531 #endif
532     }
533     if ( !hWnd )
534     {
535         delete pFrame;
536         return NULL;
537     }
538 
539     // If we have an Window with an Caption Bar and without
540     // an MaximizeBox, we change the SystemMenu
541     if ( (nSysStyle & (WS_CAPTION | WS_MAXIMIZEBOX)) == (WS_CAPTION) )
542     {
543         HMENU hSysMenu = GetSystemMenu( hWnd, FALSE );
544         if ( hSysMenu )
545         {
546             if ( !(nSysStyle & (WS_MINIMIZEBOX | WS_MAXIMIZEBOX)) )
547                 DeleteMenu( hSysMenu, SC_RESTORE, MF_BYCOMMAND );
548             else
549                 EnableMenuItem( hSysMenu, SC_RESTORE, MF_BYCOMMAND | MF_GRAYED | MF_DISABLED );
550             if ( !(nSysStyle & WS_MINIMIZEBOX) )
551                 DeleteMenu( hSysMenu, SC_MINIMIZE, MF_BYCOMMAND );
552             if ( !(nSysStyle & WS_MAXIMIZEBOX) )
553                 DeleteMenu( hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND );
554             if ( !(nSysStyle & WS_THICKFRAME) )
555                 DeleteMenu( hSysMenu, SC_SIZE, MF_BYCOMMAND );
556         }
557     }
558     if ( (nSysStyle & WS_SYSMENU) && !(nSalFrameStyle & SAL_FRAME_STYLE_CLOSEABLE) )
559     {
560         HMENU hSysMenu = GetSystemMenu( hWnd, FALSE );
561         if ( hSysMenu )
562             EnableMenuItem( hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED | MF_DISABLED );
563     }
564 
565     // reset input context
566     pFrame->mhDefIMEContext = ImmAssociateContext( hWnd, 0 );
567 
568     // determine output size and state
569     RECT aRect;
570     GetClientRect( hWnd, &aRect );
571     pFrame->mnWidth  = aRect.right;
572     pFrame->mnHeight = aRect.bottom;
573     ImplSaveFrameState( pFrame );
574     pFrame->mbDefPos = TRUE;
575 
576 	UpdateFrameGeometry( hWnd, pFrame );
577 
578     if( pFrame->mnShowState == SW_SHOWMAXIMIZED )
579 	{
580 		// #96084 set a useful internal window size because
581 		// the window will not be maximized (and the size updated) before show()
582 
583         SetMaximizedFrameGeometry( hWnd, pFrame );
584 	}
585 
586     return pFrame;
587 }
588 
589 // helper that only creates the HWND
590 // to allow for easy reparenting of system windows, (i.e. destroy and create new)
591 HWND ImplSalReCreateHWND( HWND hWndParent, HWND oldhWnd, sal_Bool bAsChild )
592 {
593     HINSTANCE hInstance = GetSalData()->mhInst;
594     ULONG nSysStyle     = GetWindowLong( oldhWnd, GWL_STYLE );
595     ULONG nExSysStyle   = GetWindowLong( oldhWnd, GWL_EXSTYLE );
596 
597     if( bAsChild )
598     {
599         nSysStyle = WS_CHILD;
600         nExSysStyle = 0;
601     }
602 
603     LPCWSTR pClassName = SAL_SUBFRAME_CLASSNAMEW;
604     HWND hWnd = CreateWindowExW( nExSysStyle, pClassName, L"", nSysStyle,
605                                 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
606                                 hWndParent, 0, hInstance, (void*)GetWindowPtr( oldhWnd ) );
607     return hWnd;
608 }
609 
610 // =======================================================================
611 
612 // Uebersetzungstabelle von System-Keycodes in StarView-Keycodes
613 #define KEY_TAB_SIZE     146
614 
615 static sal_uInt16 aImplTranslateKeyTab[KEY_TAB_SIZE] =
616 {
617     // StarView-Code      System-Code                         Index
618     0,                    //                                  0
619     0,                    // VK_LBUTTON                       1
620     0,                    // VK_RBUTTON                       2
621     0,                    // VK_CANCEL                        3
622     0,                    // VK_MBUTTON                       4
623     0,                    //                                  5
624     0,                    //                                  6
625     0,                    //                                  7
626     KEY_BACKSPACE,        // VK_BACK                          8
627     KEY_TAB,              // VK_TAB                           9
628     0,                    //                                  10
629     0,                    //                                  11
630     0,                    // VK_CLEAR                         12
631     KEY_RETURN,           // VK_RETURN                        13
632     0,                    //                                  14
633     0,                    //                                  15
634     0,                    // VK_SHIFT                         16
635     0,                    // VK_CONTROL                       17
636     0,                    // VK_MENU                          18
637     0,                    // VK_PAUSE                         19
638     0,                    // VK_CAPITAL                       20
639     0,                    // VK_HANGUL                        21
640     0,                    //                                  22
641     0,                    //                                  23
642     0,                    //                                  24
643     KEY_HANGUL_HANJA,     // VK_HANJA                         25
644     0,                    //                                  26
645     KEY_ESCAPE,           // VK_ESCAPE                        27
646     0,                    //                                  28
647     0,                    //                                  29
648     0,                    //                                  30
649     0,                    //                                  31
650     KEY_SPACE,            // VK_SPACE                         32
651     KEY_PAGEUP,           // VK_PRIOR                         33
652     KEY_PAGEDOWN,         // VK_NEXT                          34
653     KEY_END,              // VK_END                           35
654     KEY_HOME,             // VK_HOME                          36
655     KEY_LEFT,             // VK_LEFT                          37
656     KEY_UP,               // VK_UP                            38
657     KEY_RIGHT,            // VK_RIGHT                         39
658     KEY_DOWN,             // VK_DOWN                          40
659     0,                    // VK_SELECT                        41
660     0,                    // VK_PRINT                         42
661     0,                    // VK_EXECUTE                       43
662     0,                    // VK_SNAPSHOT                      44
663     KEY_INSERT,           // VK_INSERT                        45
664     KEY_DELETE,           // VK_DELETE                        46
665     KEY_HELP,             // VK_HELP                          47
666     KEY_0,                //                                  48
667     KEY_1,                //                                  49
668     KEY_2,                //                                  50
669     KEY_3,                //                                  51
670     KEY_4,                //                                  52
671     KEY_5,                //                                  53
672     KEY_6,                //                                  54
673     KEY_7,                //                                  55
674     KEY_8,                //                                  56
675     KEY_9,                //                                  57
676     0,                    //                                  58
677     0,                    //                                  59
678     0,                    //                                  60
679     0,                    //                                  61
680     0,                    //                                  62
681     0,                    //                                  63
682     0,                    //                                  64
683     KEY_A,                //                                  65
684     KEY_B,                //                                  66
685     KEY_C,                //                                  67
686     KEY_D,                //                                  68
687     KEY_E,                //                                  69
688     KEY_F,                //                                  70
689     KEY_G,                //                                  71
690     KEY_H,                //                                  72
691     KEY_I,                //                                  73
692     KEY_J,                //                                  74
693     KEY_K,                //                                  75
694     KEY_L,                //                                  76
695     KEY_M,                //                                  77
696     KEY_N,                //                                  78
697     KEY_O,                //                                  79
698     KEY_P,                //                                  80
699     KEY_Q,                //                                  81
700     KEY_R,                //                                  82
701     KEY_S,                //                                  83
702     KEY_T,                //                                  84
703     KEY_U,                //                                  85
704     KEY_V,                //                                  86
705     KEY_W,                //                                  87
706     KEY_X,                //                                  88
707     KEY_Y,                //                                  89
708     KEY_Z,                //                                  90
709     0,                    // VK_LWIN                          91
710     0,                    // VK_RWIN                          92
711     KEY_CONTEXTMENU,      // VK_APPS                          93
712     0,                    //                                  94
713     0,                    //                                  95
714     KEY_0,                // VK_NUMPAD0                       96
715     KEY_1,                // VK_NUMPAD1                       97
716     KEY_2,                // VK_NUMPAD2                       98
717     KEY_3,                // VK_NUMPAD3                       99
718     KEY_4,                // VK_NUMPAD4                      100
719     KEY_5,                // VK_NUMPAD5                      101
720     KEY_6,                // VK_NUMPAD6                      102
721     KEY_7,                // VK_NUMPAD7                      103
722     KEY_8,                // VK_NUMPAD8                      104
723     KEY_9,                // VK_NUMPAD9                      105
724     KEY_MULTIPLY,         // VK_MULTIPLY                     106
725     KEY_ADD,              // VK_ADD                          107
726     KEY_DECIMAL,          // VK_SEPARATOR                    108
727     KEY_SUBTRACT,         // VK_SUBTRACT                     109
728     KEY_DECIMAL,          // VK_DECIMAL                      110
729     KEY_DIVIDE,           // VK_DIVIDE                       111
730     KEY_F1,               // VK_F1                           112
731     KEY_F2,               // VK_F2                           113
732     KEY_F3,               // VK_F3                           114
733     KEY_F4,               // VK_F4                           115
734     KEY_F5,               // VK_F5                           116
735     KEY_F6,               // VK_F6                           117
736     KEY_F7,               // VK_F7                           118
737     KEY_F8,               // VK_F8                           119
738     KEY_F9,               // VK_F9                           120
739     KEY_F10,              // VK_F10                          121
740     KEY_F11,              // VK_F11                          122
741     KEY_F12,              // VK_F12                          123
742     KEY_F13,              // VK_F13                          124
743     KEY_F14,              // VK_F14                          125
744     KEY_F15,              // VK_F15                          126
745     KEY_F16,              // VK_F16                          127
746     KEY_F17,              // VK_F17                          128
747     KEY_F18,              // VK_F18                          129
748     KEY_F19,              // VK_F19                          130
749     KEY_F20,              // VK_F20                          131
750     KEY_F21,              // VK_F21                          132
751     KEY_F22,              // VK_F22                          133
752     KEY_F23,              // VK_F23                          134
753     KEY_F24,              // VK_F24                          135
754     0,                    //                                 136
755     0,                    //                                 137
756     0,                    //                                 138
757     0,                    //                                 139
758     0,                    //                                 140
759     0,                    //                                 141
760     0,                    //                                 142
761     0,                    //                                 143
762     0,                    // NUMLOCK                         144
763     0                     // SCROLLLOCK                      145
764 };
765 
766 // =======================================================================
767 
768 static UINT ImplSalGetWheelScrollLines()
769 {
770     UINT nScrLines = 0;
771     HWND hWndMsWheel = WIN_FindWindow( MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE );
772     if ( hWndMsWheel )
773     {
774         UINT nGetScrollLinesMsgId = RegisterWindowMessage( MSH_SCROLL_LINES );
775         nScrLines = (UINT)ImplSendMessage( hWndMsWheel, nGetScrollLinesMsgId, 0, 0 );
776     }
777 
778     if ( !nScrLines )
779         if( !SystemParametersInfo( SPI_GETWHEELSCROLLLINES, 0, &nScrLines, 0 ) )
780             nScrLines = 0 ;
781 
782     if ( !nScrLines )
783         nScrLines = 3;
784 
785     return nScrLines;
786 }
787 
788 // -----------------------------------------------------------------------
789 
790 static UINT ImplSalGetWheelScrollChars()
791 {
792     UINT nScrChars = 0;
793     if( !SystemParametersInfo( SPI_GETWHEELSCROLLCHARS, 0, &nScrChars, 0 ) )
794     {
795         // Depending on Windows version, use proper default or 1 (when
796         // driver emulates hscroll)
797         if( VER_PLATFORM_WIN32_NT == aSalShlData.maVersionInfo.dwPlatformId &&
798             aSalShlData.maVersionInfo.dwMajorVersion < 6 )
799         {
800             // Windows 2000 & WinXP : emulating driver, use step size
801             // of 1
802             return 1;
803         }
804         else
805         {
806             // Longhorn or above: use proper default value of 3
807             return 3;
808         }
809     }
810 
811     // system settings successfully read
812     return nScrChars;
813 }
814 
815 // -----------------------------------------------------------------------
816 
817 static void ImplSalAddBorder( const WinSalFrame* pFrame, int& width, int& height )
818 {
819     // transform client size into window size
820     RECT    aWinRect;
821     aWinRect.left   = 0;
822     aWinRect.right  = width-1;
823     aWinRect.top    = 0;
824     aWinRect.bottom = height-1;
825     AdjustWindowRectEx( &aWinRect, GetWindowStyle( pFrame->mhWnd ),
826                         FALSE,     GetWindowExStyle( pFrame->mhWnd ) );
827     width  = aWinRect.right - aWinRect.left + 1;
828     height = aWinRect.bottom - aWinRect.top + 1;
829 }
830 
831 // -----------------------------------------------------------------------
832 
833 static void ImplSalCalcFullScreenSize( const WinSalFrame* pFrame,
834                                        int& rX, int& rY, int& rDX, int& rDY )
835 {
836     // set window to screen size
837     int nFrameX;
838     int nFrameY;
839     int nCaptionY;
840 	int nScreenX = 0;
841 	int nScreenY = 0;
842     int nScreenDX = 0;
843     int nScreenDY = 0;
844 
845     if ( pFrame->mbSizeBorder )
846     {
847         nFrameX = GetSystemMetrics( SM_CXSIZEFRAME );
848         nFrameY = GetSystemMetrics( SM_CYSIZEFRAME );
849     }
850     else if ( pFrame->mbFixBorder )
851     {
852         nFrameX = GetSystemMetrics( SM_CXFIXEDFRAME );
853         nFrameY = GetSystemMetrics( SM_CYFIXEDFRAME );
854     }
855     else if ( pFrame->mbBorder )
856     {
857         nFrameX = GetSystemMetrics( SM_CXBORDER );
858         nFrameY = GetSystemMetrics( SM_CYBORDER );
859     }
860     else
861     {
862         nFrameX = 0;
863         nFrameY = 0;
864     }
865     if ( pFrame->mbCaption )
866         nCaptionY = GetSystemMetrics( SM_CYCAPTION );
867     else
868         nCaptionY = 0;
869 
870 	try
871 	{
872 	    uno::Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW );
873 	    uno::Reference< XIndexAccess > xMultiMon( xFactory->createInstance(OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.DisplayAccess" ) ) ), UNO_QUERY_THROW );
874         sal_Int32 nMonitors = xMultiMon->getCount();
875 		if( (pFrame->mnDisplay >= 0) && (pFrame->mnDisplay < nMonitors) )
876 		{
877 		    uno::Reference< XPropertySet > xMonitor( xMultiMon->getByIndex( pFrame->mnDisplay ), UNO_QUERY_THROW );
878 			com::sun::star::awt::Rectangle aRect;
879 			if( xMonitor->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ScreenArea" ) ) ) >>= aRect )
880 			{
881 				nScreenX = aRect.X;
882 				nScreenY = aRect.Y;
883 				nScreenDX = aRect.Width+1;  // difference between java/awt convention and vcl
884 				nScreenDY = aRect.Height+1; // difference between java/awt convention and vcl
885 			}
886 		}
887 		else
888 		{
889             Rectangle aCombined;
890             uno::Reference< XPropertySet > xMonitor( xMultiMon->getByIndex( 0 ), UNO_QUERY_THROW );
891 			com::sun::star::awt::Rectangle aRect;
892 			if( xMonitor->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ScreenArea" ) ) ) >>= aRect )
893 			{
894                 aCombined.Left()   = aRect.X;
895                 aCombined.Top()    = aRect.Y;
896                 aCombined.Right()  = aRect.X + aRect.Width;
897                 aCombined.Bottom() = aRect.Y + aRect.Height;
898                 for( sal_Int32 i = 1 ; i < nMonitors ; i++ )
899                 {
900                     xMonitor = uno::Reference< XPropertySet >( xMultiMon->getByIndex(i), UNO_QUERY_THROW );
901                     if( xMonitor->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ScreenArea" ) ) ) >>= aRect )
902                     {
903                         aCombined.Union( Rectangle( aRect.X, aRect.Y, aRect.X+aRect.Width, aRect.Y+aRect.Height ) );
904                     }
905                 }
906             }
907             nScreenX  = aCombined.Left();
908             nScreenY  = aCombined.Top();
909             nScreenDX = aCombined.GetWidth();
910             nScreenDY = aCombined.GetHeight();
911 		}
912 	}
913 	catch( Exception& )
914 	{
915 	}
916 
917 	if( !nScreenDX || !nScreenDY )
918 	{
919 	    nScreenDX   = GetSystemMetrics( SM_CXSCREEN );
920 		nScreenDY   = GetSystemMetrics( SM_CYSCREEN );
921 	}
922 
923     rX  = nScreenX -nFrameX;
924     rY  = nScreenY -(nFrameY+nCaptionY);
925     rDX = nScreenDX+(nFrameX*2);
926     rDY = nScreenDY+(nFrameY*2)+nCaptionY;
927 }
928 
929 // -----------------------------------------------------------------------
930 
931 static void ImplSalFrameFullScreenPos( WinSalFrame* pFrame, sal_Bool bAlways = FALSE )
932 {
933     if ( bAlways || !IsIconic( pFrame->mhWnd ) )
934     {
935         // set window to screen size
936         int nX;
937         int nY;
938         int nWidth;
939         int nHeight;
940         ImplSalCalcFullScreenSize( pFrame, nX, nY, nWidth, nHeight );
941         SetWindowPos( pFrame->mhWnd, 0,
942                       nX, nY, nWidth, nHeight,
943                       SWP_NOZORDER | SWP_NOACTIVATE );
944     }
945 }
946 
947 // -----------------------------------------------------------------------
948 
949 WinSalFrame::WinSalFrame()
950 {
951     SalData* pSalData = GetSalData();
952 
953     mhWnd               = 0;
954     mhCursor            = LoadCursor( 0, IDC_ARROW );
955     mhDefIMEContext     = 0;
956     mpGraphics          = NULL;
957     mpGraphics2         = NULL;
958     mnShowState         = SW_SHOWNORMAL;
959     mnWidth             = 0;
960     mnHeight            = 0;
961     mnMinWidth          = 0;
962     mnMinHeight         = 0;
963     mnMaxWidth          = SHRT_MAX;
964     mnMaxHeight         = SHRT_MAX;
965     mnInputLang         = 0;
966     mnInputCodePage     = 0;
967     mbGraphics          = FALSE;
968     mbCaption           = FALSE;
969     mbBorder            = FALSE;
970     mbFixBorder         = FALSE;
971     mbSizeBorder        = FALSE;
972     mbFullScreen        = FALSE;
973     mbPresentation      = FALSE;
974     mbInShow            = FALSE;
975     mbRestoreMaximize   = FALSE;
976     mbInMoveMsg         = FALSE;
977     mbInSizeMsg         = FALSE;
978     mbFullScreenToolWin = FALSE;
979     mbDefPos            = TRUE;
980     mbOverwriteState    = TRUE;
981     mbIME               = FALSE;
982     mbHandleIME         = FALSE;
983     mbSpezIME           = FALSE;
984     mbAtCursorIME       = FALSE;
985     mbCandidateMode     = FALSE;
986     mbFloatWin          = FALSE;
987     mbNoIcon            = FALSE;
988     mSelectedhMenu      = 0;
989     mLastActivatedhMenu = 0;
990     mpClipRgnData       = NULL;
991     mbFirstClipRect     = TRUE;
992     mpNextClipRect      = NULL;
993 	mnDisplay			= 0;
994 
995     memset( &maState, 0, sizeof( SalFrameState ) );
996     maSysData.nSize     = sizeof( SystemEnvData );
997 
998     memset( &maGeometry, 0, sizeof( maGeometry ) );
999 
1000     // Daten ermitteln, wenn erster Frame angelegt wird
1001     if ( !pSalData->mpFirstFrame )
1002     {
1003         if ( !aSalShlData.mnWheelMsgId )
1004             aSalShlData.mnWheelMsgId = RegisterWindowMessage( MSH_MOUSEWHEEL );
1005         if ( !aSalShlData.mnWheelScrollLines )
1006             aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines();
1007         if ( !aSalShlData.mnWheelScrollChars )
1008             aSalShlData.mnWheelScrollChars = ImplSalGetWheelScrollChars();
1009     }
1010 
1011     // insert frame in framelist
1012     mpNextFrame = pSalData->mpFirstFrame;
1013     pSalData->mpFirstFrame = this;
1014 }
1015 
1016 // -----------------------------------------------------------------------
1017 void WinSalFrame::updateScreenNumber()
1018 {
1019     if( mnDisplay == -1 ) // spans all monitors
1020         return;
1021     WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem());
1022     if( pSys )
1023     {
1024         const std::vector<WinSalSystem::DisplayMonitor>& rMonitors =
1025             pSys->getMonitors();
1026         Point aPoint( maGeometry.nX, maGeometry.nY );
1027         size_t nMon = rMonitors.size();
1028         for( size_t i = 0; i < nMon; i++ )
1029         {
1030             if( rMonitors[i].m_aArea.IsInside( aPoint ) )
1031             {
1032                 mnDisplay = static_cast<sal_Int32>(i);
1033                 maGeometry.nScreenNumber = static_cast<unsigned int>(i);
1034             }
1035         }
1036     }
1037 }
1038 
1039 // -----------------------------------------------------------------------
1040 
1041 WinSalFrame::~WinSalFrame()
1042 {
1043     SalData* pSalData = GetSalData();
1044 
1045     if( mpClipRgnData )
1046         delete [] (BYTE*)mpClipRgnData;
1047 
1048     // remove frame from framelist
1049     WinSalFrame** ppFrame = &pSalData->mpFirstFrame;
1050     for(; (*ppFrame != this) && *ppFrame; ppFrame = &(*ppFrame)->mpNextFrame );
1051     if( *ppFrame )
1052         *ppFrame = mpNextFrame;
1053     mpNextFrame = NULL;
1054 
1055     // Release Cache DC
1056     if ( mpGraphics2 &&
1057          mpGraphics2->mhDC )
1058         ReleaseGraphics( mpGraphics2 );
1059 
1060     // destroy saved DC
1061     if ( mpGraphics )
1062     {
1063         if ( mpGraphics->mhDefPal )
1064             SelectPalette( mpGraphics->mhDC, mpGraphics->mhDefPal, TRUE );
1065         ImplSalDeInitGraphics( mpGraphics );
1066         ReleaseDC( mhWnd, mpGraphics->mhDC );
1067         delete mpGraphics;
1068         mpGraphics = NULL;
1069     }
1070 
1071     if ( mhWnd )
1072     {
1073         // reset mouse leave data
1074         if ( pSalData->mhWantLeaveMsg == mhWnd )
1075         {
1076             pSalData->mhWantLeaveMsg = 0;
1077             if ( pSalData->mpMouseLeaveTimer )
1078             {
1079                 delete pSalData->mpMouseLeaveTimer;
1080                 pSalData->mpMouseLeaveTimer = NULL;
1081             }
1082         }
1083 
1084         // destroy system frame
1085         if ( !DestroyWindow( mhWnd ) )
1086             SetWindowPtr( mhWnd, 0 );
1087 
1088         mhWnd = 0;
1089     }
1090 }
1091 
1092 // -----------------------------------------------------------------------
1093 
1094 SalGraphics* WinSalFrame::GetGraphics()
1095 {
1096     if ( mbGraphics )
1097         return NULL;
1098 
1099     // Other threads get an own DC, because Windows modify in the
1100     // other case our DC (changing clip region), when they send a
1101     // WM_ERASEBACKGROUND message
1102     SalData* pSalData = GetSalData();
1103     if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
1104     {
1105         // We use only three CacheDC's for all threads, because W9x is limited
1106         // to max. 5 Cache DC's per thread
1107         if ( pSalData->mnCacheDCInUse >= 3 )
1108             return NULL;
1109 
1110         if ( !mpGraphics2 )
1111         {
1112             mpGraphics2 = new WinSalGraphics;
1113             mpGraphics2->mhDC        = 0;
1114             mpGraphics2->mhWnd       = mhWnd;
1115             mpGraphics2->mbPrinter   = FALSE;
1116             mpGraphics2->mbVirDev    = FALSE;
1117             mpGraphics2->mbWindow    = TRUE;
1118             mpGraphics2->mbScreen    = TRUE;
1119         }
1120 
1121         HDC hDC = (HDC)ImplSendMessage( pSalData->mpFirstInstance->mhComWnd,
1122                                         SAL_MSG_GETDC,
1123                                         (WPARAM)mhWnd, 0 );
1124         if ( hDC )
1125         {
1126             mpGraphics2->mhDC = hDC;
1127             if ( pSalData->mhDitherPal )
1128             {
1129                 mpGraphics2->mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE );
1130                 RealizePalette( hDC );
1131             }
1132             ImplSalInitGraphics( mpGraphics2 );
1133             mbGraphics = TRUE;
1134 
1135             pSalData->mnCacheDCInUse++;
1136             return mpGraphics2;
1137         }
1138         else
1139             return NULL;
1140     }
1141     else
1142     {
1143         if ( !mpGraphics )
1144         {
1145             HDC hDC = GetDC( mhWnd );
1146             if ( hDC )
1147             {
1148                 mpGraphics = new WinSalGraphics;
1149                 mpGraphics->mhDC      = hDC;
1150                 mpGraphics->mhWnd     = mhWnd;
1151                 mpGraphics->mbPrinter = FALSE;
1152                 mpGraphics->mbVirDev  = FALSE;
1153                 mpGraphics->mbWindow  = TRUE;
1154                 mpGraphics->mbScreen  = TRUE;
1155                 if ( pSalData->mhDitherPal )
1156                 {
1157                     mpGraphics->mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE );
1158                     RealizePalette( hDC );
1159                 }
1160                 ImplSalInitGraphics( mpGraphics );
1161                 mbGraphics = TRUE;
1162             }
1163         }
1164         else
1165             mbGraphics = TRUE;
1166 
1167         return mpGraphics;
1168     }
1169 }
1170 
1171 // -----------------------------------------------------------------------
1172 
1173 void WinSalFrame::ReleaseGraphics( SalGraphics* pGraphics )
1174 {
1175     if ( mpGraphics2 == pGraphics )
1176     {
1177         if ( mpGraphics2->mhDC )
1178         {
1179             SalData* pSalData = GetSalData();
1180             if ( mpGraphics2->mhDefPal )
1181                 SelectPalette( mpGraphics2->mhDC, mpGraphics2->mhDefPal, TRUE );
1182             ImplSalDeInitGraphics( mpGraphics2 );
1183             ImplSendMessage( pSalData->mpFirstInstance->mhComWnd,
1184                              SAL_MSG_RELEASEDC,
1185                              (WPARAM)mhWnd,
1186                              (LPARAM)mpGraphics2->mhDC );
1187             mpGraphics2->mhDC = 0;
1188             pSalData->mnCacheDCInUse--;
1189         }
1190     }
1191 
1192     mbGraphics = FALSE;
1193 }
1194 
1195 // -----------------------------------------------------------------------
1196 
1197 sal_Bool WinSalFrame::PostEvent( void* pData )
1198 {
1199     return (sal_Bool)ImplPostMessage( mhWnd, SAL_MSG_USEREVENT, 0, (LPARAM)pData );
1200 }
1201 
1202 // -----------------------------------------------------------------------
1203 
1204 void WinSalFrame::SetTitle( const XubString& rTitle )
1205 {
1206     DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "WinSalFrame::SetTitle(): WCHAR != sal_Unicode" );
1207 
1208     if ( !SetWindowTextW( mhWnd, reinterpret_cast<LPCWSTR>(rTitle.GetBuffer()) ) )
1209     {
1210         ByteString aAnsiTitle = ImplSalGetWinAnsiString( rTitle );
1211         SetWindowTextA( mhWnd, aAnsiTitle.GetBuffer() );
1212     }
1213 }
1214 
1215 // -----------------------------------------------------------------------
1216 
1217 void WinSalFrame::SetIcon( sal_uInt16 nIcon )
1218 {
1219     // If we have a window without an Icon (for example a dialog), ignore this call
1220     if ( mbNoIcon )
1221         return;
1222 
1223     // 0 means default (class) icon
1224     HICON hIcon = NULL, hSmIcon = NULL;
1225     if ( !nIcon )
1226         nIcon = 1;
1227 
1228     ImplLoadSalIcon( nIcon, hIcon, hSmIcon );
1229 
1230     DBG_ASSERT( hIcon ,   "WinSalFrame::SetIcon(): Could not load large icon !" );
1231     DBG_ASSERT( hSmIcon , "WinSalFrame::SetIcon(): Could not load small icon !" );
1232 
1233     ImplSendMessage( mhWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon );
1234     ImplSendMessage( mhWnd, WM_SETICON, ICON_SMALL, (LPARAM)hSmIcon );
1235 }
1236 
1237 // -----------------------------------------------------------------------
1238 
1239 void WinSalFrame::SetMenu( SalMenu* pSalMenu )
1240 {
1241     WinSalMenu* pWMenu = static_cast<WinSalMenu*>(pSalMenu);
1242     if( pSalMenu && pWMenu->mbMenuBar )
1243         ::SetMenu( mhWnd, pWMenu->mhMenu );
1244 }
1245 
1246 void WinSalFrame::DrawMenuBar()
1247 {
1248     ::DrawMenuBar( mhWnd );
1249 }
1250 
1251 // -----------------------------------------------------------------------
1252 HWND ImplGetParentHwnd( HWND hWnd )
1253 {
1254     WinSalFrame* pFrame = GetWindowPtr( hWnd );
1255 	if( !pFrame || !pFrame->GetWindow())
1256 		return ::GetParent( hWnd );
1257 	Window *pRealParent = pFrame->GetWindow()->ImplGetWindowImpl()->mpRealParent;
1258 	if( pRealParent )
1259 		return static_cast<WinSalFrame*>(pRealParent->ImplGetWindowImpl()->mpFrame)->mhWnd;
1260 	else
1261 		return ::GetParent( hWnd );
1262 
1263 }
1264 
1265 // -----------------------------------------------------------------------
1266 
1267 SalFrame* WinSalFrame::GetParent() const
1268 {
1269     return GetWindowPtr( ImplGetParentHwnd( mhWnd ) );
1270 }
1271 
1272 // -----------------------------------------------------------------------
1273 
1274 static void ImplSalShow( HWND hWnd, sal_Bool bVisible, sal_Bool bNoActivate )
1275 {
1276     WinSalFrame* pFrame = GetWindowPtr( hWnd );
1277     if ( !pFrame )
1278         return;
1279 
1280     if ( bVisible )
1281     {
1282         pFrame->mbDefPos = FALSE;
1283         pFrame->mbOverwriteState = TRUE;
1284         pFrame->mbInShow = TRUE;
1285 
1286         // #i4715, save position
1287         RECT aRectPreMatrox, aRectPostMatrox;
1288         GetWindowRect( hWnd, &aRectPreMatrox );
1289 
1290         vcl::DeletionListener aDogTag( pFrame );
1291         if( bNoActivate )
1292             ShowWindow( hWnd, SW_SHOWNOACTIVATE );
1293         else
1294             ShowWindow( hWnd, pFrame->mnShowState );
1295         if( aDogTag.isDeleted() )
1296             return;
1297 
1298         if ( aSalShlData.mbWXP && pFrame->mbFloatWin && !(pFrame->mnStyle & SAL_FRAME_STYLE_NOSHADOW))
1299         {
1300             // erase the window immediately to improve XP shadow effect
1301             // otherwise the shadow may appears long time before the rest of the window
1302             // especially when accessibility is on
1303             HDC dc = GetDC( hWnd );
1304             RECT aRect;
1305             GetClientRect( hWnd, &aRect );
1306             FillRect( dc, &aRect, (HBRUSH) (COLOR_MENU+1) ); // choose the menucolor, because its mostly noticeable for menues
1307             ReleaseDC( hWnd, dc );
1308         }
1309 
1310         // #i4715, matrox centerpopup might have changed our position
1311         // reposition popups without caption (menues, dropdowns, tooltips)
1312         GetWindowRect( hWnd, &aRectPostMatrox );
1313         if( (GetWindowStyle( hWnd ) & WS_POPUP) &&
1314             !pFrame->mbCaption &&
1315             (aRectPreMatrox.left != aRectPostMatrox.left || aRectPreMatrox.top != aRectPostMatrox.top) )
1316             SetWindowPos( hWnd, 0, aRectPreMatrox.left, aRectPreMatrox.top, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE  );
1317 
1318         if( aDogTag.isDeleted() )
1319             return;
1320 		Window *pClientWin = pFrame->GetWindow()->ImplGetClientWindow();
1321         if ( pFrame->mbFloatWin || ( pClientWin && (pClientWin->GetStyle() & WB_SYSTEMFLOATWIN) ) )
1322             pFrame->mnShowState = SW_SHOWNOACTIVATE;
1323         else
1324             pFrame->mnShowState = SW_SHOW;
1325         // Damit Taskleiste unter W98 auch gleich ausgeblendet wird
1326         if ( pFrame->mbPresentation )
1327         {
1328             HWND hWndParent = ::GetParent( hWnd );
1329             if ( hWndParent )
1330                 SetForegroundWindow( hWndParent );
1331             SetForegroundWindow( hWnd );
1332         }
1333 
1334         pFrame->mbInShow = FALSE;
1335         pFrame->updateScreenNumber();
1336 
1337         // Direct Paint only, if we get the SolarMutx
1338         if ( ImplSalYieldMutexTryToAcquire() )
1339         {
1340             UpdateWindow( hWnd );
1341             ImplSalYieldMutexRelease();
1342         }
1343     }
1344     else
1345     {
1346         // See also Bug #91813# and #68467#
1347         if ( pFrame->mbFullScreen &&
1348              pFrame->mbPresentation &&
1349              (aSalShlData.mnVersion < 500) &&
1350              !::GetParent( hWnd ) )
1351         {
1352             // Damit im Impress-Player in der Taskleiste nicht durch
1353             // einen Windows-Fehler hin- und wieder mal ein leerer
1354             // Button stehen bleibt, muessen wir hier die Taskleiste
1355             // etwas austricksen. Denn wenn wir im FullScreenMode sind
1356             // und das Fenster hiden kommt Windows anscheinend etwas aus
1357             // dem tritt und somit minimieren wir das Fenster damit es
1358             // nicht flackert
1359             ANIMATIONINFO aInfo;
1360             aInfo.cbSize = sizeof( aInfo );
1361             SystemParametersInfo( SPI_GETANIMATION, 0, &aInfo, 0 );
1362             if ( aInfo.iMinAnimate )
1363             {
1364                 int nOldAni = aInfo.iMinAnimate;
1365                 aInfo.iMinAnimate = 0;
1366                 SystemParametersInfo( SPI_SETANIMATION, 0, &aInfo, 0 );
1367                 ShowWindow( pFrame->mhWnd, SW_SHOWMINNOACTIVE );
1368                 aInfo.iMinAnimate = nOldAni;
1369                 SystemParametersInfo( SPI_SETANIMATION, 0, &aInfo, 0 );
1370             }
1371             else
1372                 ShowWindow( hWnd, SW_SHOWMINNOACTIVE );
1373             ShowWindow( hWnd, SW_HIDE );
1374         }
1375         else
1376             ShowWindow( hWnd, SW_HIDE );
1377     }
1378 }
1379 
1380 // -----------------------------------------------------------------------
1381 
1382 
1383 void WinSalFrame::SetExtendedFrameStyle( SalExtStyle )
1384 {
1385 }
1386 
1387 // -----------------------------------------------------------------------
1388 
1389 void WinSalFrame::Show( sal_Bool bVisible, sal_Bool bNoActivate )
1390 {
1391     // Post this Message to the window, because this only works
1392     // in the thread of the window, which has create this window.
1393     // We post this message to avoid deadlocks
1394     if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() )
1395         ImplPostMessage( mhWnd, SAL_MSG_SHOW, bVisible, bNoActivate );
1396     else
1397         ImplSalShow( mhWnd, bVisible, bNoActivate );
1398 }
1399 
1400 // -----------------------------------------------------------------------
1401 
1402 void WinSalFrame::Enable( sal_Bool bEnable )
1403 {
1404     EnableWindow( mhWnd, bEnable );
1405 }
1406 
1407 // -----------------------------------------------------------------------
1408 
1409 void WinSalFrame::SetMinClientSize( long nWidth, long nHeight )
1410 {
1411     mnMinWidth  = nWidth;
1412     mnMinHeight = nHeight;
1413 }
1414 
1415 void WinSalFrame::SetMaxClientSize( long nWidth, long nHeight )
1416 {
1417     mnMaxWidth  = nWidth;
1418     mnMaxHeight = nHeight;
1419 }
1420 
1421 // -----------------------------------------------------------------------
1422 
1423 void WinSalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight,
1424                                                    sal_uInt16 nFlags )
1425 {
1426     sal_Bool bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0;
1427     if ( !bVisible )
1428     {
1429 		Window *pClientWin = GetWindow()->ImplGetClientWindow();
1430         if ( mbFloatWin || ( pClientWin && (pClientWin->GetStyle() & WB_SYSTEMFLOATWIN) ) )
1431                 mnShowState = SW_SHOWNOACTIVATE;
1432         else
1433                 mnShowState = SW_SHOWNORMAL;
1434     }
1435     else
1436     {
1437         if ( IsIconic( mhWnd ) || IsZoomed( mhWnd ) )
1438                 ShowWindow( mhWnd, SW_RESTORE );
1439     }
1440 
1441     sal_uInt16 nEvent = 0;
1442     UINT    nPosSize = 0;
1443     RECT    aClientRect, aWindowRect;
1444     GetClientRect( mhWnd, &aClientRect );   // x,y always 0,0, but width and height without border
1445     GetWindowRect( mhWnd, &aWindowRect );   // x,y in screen coordinates, width and height with border
1446 
1447     if ( !(nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y)) )
1448         nPosSize |= SWP_NOMOVE;
1449     else
1450     {
1451         //DBG_ASSERT( nX && nY, " Windowposition of (0,0) requested!" );
1452         nEvent = SALEVENT_MOVE;
1453     }
1454     if ( !(nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) )
1455         nPosSize |= SWP_NOSIZE;
1456     else
1457         nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE;
1458 
1459     if ( !(nFlags & SAL_FRAME_POSSIZE_X) )
1460         nX = aWindowRect.left;
1461     if ( !(nFlags & SAL_FRAME_POSSIZE_Y) )
1462         nY = aWindowRect.top;
1463     if ( !(nFlags & SAL_FRAME_POSSIZE_WIDTH) )
1464         nWidth = aClientRect.right-aClientRect.left;
1465     if ( !(nFlags & SAL_FRAME_POSSIZE_HEIGHT) )
1466         nHeight = aClientRect.bottom-aClientRect.top;
1467 
1468     // Calculate window size including the border
1469     RECT    aWinRect;
1470     aWinRect.left   = 0;
1471     aWinRect.right  = (int)nWidth-1;
1472     aWinRect.top    = 0;
1473     aWinRect.bottom = (int)nHeight-1;
1474     AdjustWindowRectEx( &aWinRect, GetWindowStyle( mhWnd ),
1475                         FALSE,     GetWindowExStyle( mhWnd ) );
1476     nWidth  = aWinRect.right - aWinRect.left + 1;
1477     nHeight = aWinRect.bottom - aWinRect.top + 1;
1478 
1479     if ( !(nPosSize & SWP_NOMOVE) && ::GetParent( mhWnd ) )
1480     {
1481             // --- RTL --- (mirror window pos)
1482             RECT aParentRect;
1483             GetClientRect( ImplGetParentHwnd( mhWnd ), &aParentRect );
1484             if( Application::GetSettings().GetLayoutRTL() )
1485                 nX = (aParentRect.right - aParentRect.left) - nWidth-1 - nX;
1486 
1487             //#110386#, do not transform coordinates for system child windows
1488             if( !(GetWindowStyle( mhWnd ) & WS_CHILD) )
1489             {
1490                 POINT aPt;
1491                 aPt.x = nX;
1492                 aPt.y = nY;
1493 
1494                 HWND parentHwnd = ImplGetParentHwnd( mhWnd );
1495                 WinSalFrame* pParentFrame = GetWindowPtr( parentHwnd );
1496                 if ( pParentFrame && pParentFrame->mnShowState == SW_SHOWMAXIMIZED )
1497                 {
1498                     // #i42485#: parent will be shown maximized in which case
1499                     // a ClientToScreen uses the wrong coordinates (i.e. those from the restore pos)
1500                     // so use the (already updated) frame geometry for the transformation
1501                     aPt.x +=  pParentFrame->maGeometry.nX;
1502                     aPt.y +=  pParentFrame->maGeometry.nY;
1503                 }
1504                 else
1505                     ClientToScreen( parentHwnd, &aPt );
1506 
1507                 nX = aPt.x;
1508                 nY = aPt.y;
1509             }
1510     }
1511 
1512     // #i3338# to be conformant to UNIX we must position the client window, ie without the decoration
1513     // #i43250# if the position was read from the system (GetWindowRect(), see above), it must not be modified
1514     if ( nFlags & SAL_FRAME_POSSIZE_X )
1515         nX += aWinRect.left;
1516     if ( nFlags & SAL_FRAME_POSSIZE_Y )
1517         nY += aWinRect.top;
1518 
1519     int     nScreenX;
1520     int     nScreenY;
1521     int     nScreenWidth;
1522     int     nScreenHeight;
1523 
1524 
1525     RECT aRect;
1526     ImplSalGetWorkArea( mhWnd, &aRect, NULL );
1527     nScreenX        = aRect.left;
1528     nScreenY        = aRect.top;
1529     nScreenWidth    = aRect.right-aRect.left;
1530     nScreenHeight   = aRect.bottom-aRect.top;
1531 
1532     if ( mbDefPos && (nPosSize & SWP_NOMOVE)) // we got no positioning request, so choose default position
1533     {
1534         // center window
1535 
1536         HWND hWndParent = ::GetParent( mhWnd );
1537         // Search for TopLevel Frame
1538         while ( hWndParent && (GetWindowStyle( hWndParent ) & WS_CHILD) )
1539             hWndParent = ::GetParent( hWndParent );
1540         // if the Window has a Parent, than center the window to
1541         // the parent, in the other case to the screen
1542         if ( hWndParent && !IsIconic( hWndParent ) &&
1543              (GetWindowStyle( hWndParent ) & WS_VISIBLE) )
1544         {
1545             RECT aParentRect;
1546             GetWindowRect( hWndParent, &aParentRect );
1547             int nParentWidth    = aParentRect.right-aParentRect.left;
1548             int nParentHeight   = aParentRect.bottom-aParentRect.top;
1549 
1550             // We don't center, when Parent is smaller than our window
1551             if ( (nParentWidth-GetSystemMetrics( SM_CXFIXEDFRAME ) <= nWidth) &&
1552                  (nParentHeight-GetSystemMetrics( SM_CYFIXEDFRAME ) <= nHeight) )
1553             {
1554                 int nOff = GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION );
1555                 nX = aParentRect.left+nOff;
1556                 nY = aParentRect.top+nOff;
1557             }
1558             else
1559             {
1560                 nX = (nParentWidth-nWidth)/2 + aParentRect.left;
1561                 nY = (nParentHeight-nHeight)/2 + aParentRect.top;
1562             }
1563         }
1564         else
1565         {
1566             POINT pt;
1567             GetCursorPos( &pt );
1568             RECT aRect;
1569             aRect.left = pt.x;
1570             aRect.top = pt.y;
1571             aRect.right = pt.x+2;
1572             aRect.bottom = pt.y+2;
1573 
1574             // dualmonitor support:
1575             // Get screensize of the monitor whith the mouse pointer
1576             ImplSalGetWorkArea( mhWnd, &aRect, &aRect );
1577 
1578             nX = ((aRect.right-aRect.left)-nWidth)/2 + aRect.left;
1579             nY = ((aRect.bottom-aRect.top)-nHeight)/2 + aRect.top;
1580         }
1581 
1582 
1583         //if ( bVisible )
1584         //    mbDefPos = FALSE;
1585 
1586         mbDefPos = FALSE;   // center only once
1587         nPosSize &= ~SWP_NOMOVE;        // activate positioning
1588         nEvent = SALEVENT_MOVERESIZE;
1589     }
1590 
1591 
1592     // Adjust Window in the screen
1593     sal_Bool bCheckOffScreen = TRUE;
1594 
1595     // but don't do this for floaters or ownerdraw windows that are currently moved interactively
1596     if( (mnStyle & SAL_FRAME_STYLE_FLOAT) && !(mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
1597         bCheckOffScreen = FALSE;
1598 
1599     if( mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION )
1600     {
1601         // may be the window is currently being moved (mouse is captured), then no check is required
1602         if( mhWnd == ::GetCapture() )
1603             bCheckOffScreen = FALSE;
1604         else
1605             bCheckOffScreen = TRUE;
1606     }
1607 
1608     if( bCheckOffScreen )
1609     {
1610         if ( nX+nWidth > nScreenX+nScreenWidth )
1611             nX = (nScreenX+nScreenWidth) - nWidth;
1612         if ( nY+nHeight > nScreenY+nScreenHeight )
1613             nY = (nScreenY+nScreenHeight) - nHeight;
1614         if ( nX < nScreenX )
1615             nX = nScreenX;
1616         if ( nY < nScreenY )
1617             nY = nScreenY;
1618     }
1619 
1620     UINT nPosFlags = SWP_NOACTIVATE | SWP_NOOWNERZORDER | nPosSize;
1621     // bring floating windows always to top
1622     if( !(mnStyle & SAL_FRAME_STYLE_FLOAT) )
1623         nPosFlags |= SWP_NOZORDER; // do not change z-order
1624 
1625     SetWindowPos( mhWnd, HWND_TOP, nX, nY, (int)nWidth, (int)nHeight, nPosFlags  );
1626 
1627 	UpdateFrameGeometry( mhWnd, this );
1628 
1629     // Notification -- really ???
1630     if( nEvent )
1631         CallCallback( nEvent, NULL );
1632 }
1633 
1634 // -----------------------------------------------------------------------
1635 
1636 static void ImplSetParentFrame( WinSalFrame* pThis, HWND hNewParentWnd, sal_Bool bAsChild )
1637 {
1638     // save hwnd, will be overwritten in WM_CREATE during createwindow
1639     HWND hWndOld = pThis->mhWnd;
1640     HWND hWndOldParent = ::GetParent( hWndOld );
1641     SalData* pSalData = GetSalData();
1642 
1643     if( hNewParentWnd == hWndOldParent )
1644         return;
1645 
1646     ::std::vector< WinSalFrame* > children;
1647     ::std::vector< WinSalObject* > systemChildren;
1648 
1649     // search child windows
1650     WinSalFrame *pFrame = pSalData->mpFirstFrame;
1651     while( pFrame )
1652     {
1653         HWND hWndParent = ::GetParent( pFrame->mhWnd );
1654         if( pThis->mhWnd == hWndParent )
1655             children.push_back( pFrame );
1656         pFrame = pFrame->mpNextFrame;
1657     }
1658 
1659     // search system child windows (plugins etc.)
1660     WinSalObject *pObject = pSalData->mpFirstObject;
1661     while( pObject )
1662     {
1663         HWND hWndParent = ::GetParent( pObject->mhWnd );
1664         if( pThis->mhWnd == hWndParent )
1665             systemChildren.push_back( pObject );
1666         pObject = pObject->mpNextObject;
1667     }
1668 
1669     sal_Bool bNeedGraphics = pThis->mbGraphics;
1670     sal_Bool bNeedCacheDC  = FALSE;
1671 
1672     HFONT   hFont   = NULL;
1673     HPEN    hPen    = NULL;
1674     HBRUSH  hBrush  = NULL;
1675 
1676     #if OSL_DEBUG_LEVEL > 0
1677     int oldCount = pSalData->mnCacheDCInUse;
1678 	(void)oldCount;
1679     #endif
1680 
1681     // Release Cache DC
1682     if ( pThis->mpGraphics2 &&
1683          pThis->mpGraphics2->mhDC )
1684     {
1685         // save current gdi objects before hdc is gone
1686         hFont   = (HFONT)   GetCurrentObject( pThis->mpGraphics2->mhDC, OBJ_FONT);
1687         hPen    = (HPEN)    GetCurrentObject( pThis->mpGraphics2->mhDC, OBJ_PEN);
1688         hBrush  = (HBRUSH)  GetCurrentObject( pThis->mpGraphics2->mhDC, OBJ_BRUSH);
1689         pThis->ReleaseGraphics( pThis->mpGraphics2 );
1690 
1691         // recreate cache dc only if it was destroyed
1692         bNeedCacheDC  = TRUE;
1693     }
1694 
1695     // destroy saved DC
1696     if ( pThis->mpGraphics )
1697     {
1698         if ( pThis->mpGraphics->mhDefPal )
1699             SelectPalette( pThis->mpGraphics->mhDC, pThis->mpGraphics->mhDefPal, TRUE );
1700         ImplSalDeInitGraphics( pThis->mpGraphics );
1701         ReleaseDC( pThis->mhWnd, pThis->mpGraphics->mhDC );
1702     }
1703 
1704     // create a new hwnd with the same styles
1705     HWND hWndParent = hNewParentWnd;
1706     // forward to main thread
1707     HWND hWnd = (HWND) ImplSendMessage( pSalData->mpFirstInstance->mhComWnd,
1708                                         bAsChild ? SAL_MSG_RECREATECHILDHWND : SAL_MSG_RECREATEHWND,
1709                                         (WPARAM) hWndParent, (LPARAM)pThis->mhWnd );
1710 
1711     // succeeded ?
1712     DBG_ASSERT( IsWindow( hWnd ), "WinSalFrame::SetParent not successful");
1713 
1714     // recreate DCs
1715     if( bNeedGraphics )
1716     {
1717         if( pThis->mpGraphics2 )
1718         {
1719             pThis->mpGraphics2->mhWnd = hWnd;
1720 
1721             if( bNeedCacheDC )
1722             {
1723                 // re-create cached DC
1724                 HDC hDC = (HDC)ImplSendMessage( pSalData->mpFirstInstance->mhComWnd,
1725                                                 SAL_MSG_GETDC,
1726                                                 (WPARAM) hWnd, 0 );
1727                 if ( hDC )
1728                 {
1729                     pThis->mpGraphics2->mhDC = hDC;
1730                     if ( pSalData->mhDitherPal )
1731                     {
1732                         pThis->mpGraphics2->mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE );
1733                         RealizePalette( hDC );
1734                     }
1735                     ImplSalInitGraphics( pThis->mpGraphics2 );
1736 
1737                     // re-select saved gdi objects
1738                     if( hFont )
1739                         SelectObject( hDC, hFont );
1740                     if( hPen )
1741                         SelectObject( hDC, hPen );
1742                     if( hBrush )
1743                         SelectObject( hDC, hBrush );
1744 
1745                     pThis->mbGraphics = TRUE;
1746 
1747                     pSalData->mnCacheDCInUse++;
1748 
1749                     DBG_ASSERT( oldCount == pSalData->mnCacheDCInUse, "WinSalFrame::SetParent() hDC count corrupted");
1750                 }
1751             }
1752         }
1753 
1754         if( pThis->mpGraphics )
1755         {
1756             // re-create DC
1757             pThis->mpGraphics->mhWnd = hWnd;
1758             pThis->mpGraphics->mhDC = GetDC( hWnd );
1759             if ( GetSalData()->mhDitherPal )
1760             {
1761                 pThis->mpGraphics->mhDefPal = SelectPalette( pThis->mpGraphics->mhDC, GetSalData()->mhDitherPal, TRUE );
1762                 RealizePalette( pThis->mpGraphics->mhDC );
1763             }
1764             ImplSalInitGraphics( pThis->mpGraphics );
1765             pThis->mbGraphics = TRUE;
1766         }
1767     }
1768 
1769 
1770     // TODO: add SetParent() call for SalObjects
1771     DBG_ASSERT( systemChildren.empty(), "WinSalFrame::SetParent() parent of living system child window will be destroyed!");
1772 
1773     // reparent children before old parent is destroyed
1774     for( ::std::vector< WinSalFrame* >::iterator iChild = children.begin(); iChild != children.end(); iChild++ )
1775         ImplSetParentFrame( *iChild, hWnd, FALSE );
1776 
1777     children.clear();
1778     systemChildren.clear();
1779 
1780     // Now destroy original HWND in the thread where it was created.
1781     ImplSendMessage( GetSalData()->mpFirstInstance->mhComWnd,
1782                      SAL_MSG_DESTROYHWND, (WPARAM) 0, (LPARAM)hWndOld);
1783 }
1784 
1785 // -----------------------------------------------------------------------
1786 
1787 void WinSalFrame::SetParent( SalFrame* pNewParent )
1788 {
1789     WinSalFrame::mbInReparent = TRUE;
1790     ImplSetParentFrame( this, static_cast<WinSalFrame*>(pNewParent)->mhWnd, FALSE );
1791     WinSalFrame::mbInReparent = FALSE;
1792 }
1793 
1794 bool WinSalFrame::SetPluginParent( SystemParentData* pNewParent )
1795 {
1796     if ( pNewParent->hWnd == 0 )
1797     {
1798         pNewParent->hWnd = GetDesktopWindow();
1799     }
1800 
1801     WinSalFrame::mbInReparent = TRUE;
1802     ImplSetParentFrame( this, pNewParent->hWnd, TRUE );
1803     WinSalFrame::mbInReparent = FALSE;
1804     return true;
1805 }
1806 
1807 
1808 // -----------------------------------------------------------------------
1809 
1810 void WinSalFrame::GetWorkArea( Rectangle &rRect )
1811 {
1812     RECT aRect;
1813 	ImplSalGetWorkArea( mhWnd, &aRect, NULL );
1814     rRect.nLeft     = aRect.left;
1815     rRect.nRight    = aRect.right-1;
1816     rRect.nTop      = aRect.top;
1817     rRect.nBottom   = aRect.bottom-1;
1818 }
1819 
1820 // -----------------------------------------------------------------------
1821 
1822 void WinSalFrame::GetClientSize( long& rWidth, long& rHeight )
1823 {
1824     rWidth  = maGeometry.nWidth;
1825     rHeight = maGeometry.nHeight;
1826 }
1827 
1828 // -----------------------------------------------------------------------
1829 
1830 void WinSalFrame::SetWindowState( const SalFrameState* pState )
1831 {
1832     // Wir testen, ob das Fenster ueberhaupt auf den Bildschirm passt, damit
1833     // nicht wenn die Bildschirm-Aufloesung geaendert wurde, das Fenster aus
1834     // diesem herausragt
1835     int     nX;
1836     int     nY;
1837     int     nWidth;
1838     int     nHeight;
1839     int     nScreenX;
1840     int     nScreenY;
1841     int     nScreenWidth;
1842     int     nScreenHeight;
1843 
1844     RECT aRect;
1845 	ImplSalGetWorkArea( mhWnd, &aRect, NULL );
1846     // #102500# allow some overlap, the window could have been made a little larger than the physical screen
1847     nScreenX        = aRect.left-10;
1848     nScreenY        = aRect.top-10;
1849     nScreenWidth    = aRect.right-aRect.left+20;
1850     nScreenHeight   = aRect.bottom-aRect.top+20;
1851 
1852     UINT    nPosSize    = 0;
1853     RECT    aWinRect;
1854     GetWindowRect( mhWnd, &aWinRect );
1855 
1856     // to be consistent with Unix, the frame state is without(!) decoration
1857     // ->add the decoration
1858     RECT aRect2 = aWinRect;
1859 	AdjustWindowRectEx( &aRect2, GetWindowStyle( mhWnd ),
1860 					FALSE,     GetWindowExStyle( mhWnd ) );
1861     long nTopDeco = abs( aWinRect.top - aRect2.top );
1862     long nLeftDeco = abs( aWinRect.left - aRect2.left );
1863     long nBottomDeco = abs( aWinRect.bottom - aRect2.bottom );
1864     long nRightDeco = abs( aWinRect.right - aRect2.right );
1865 
1866     // Fenster-Position/Groesse in den Bildschirm einpassen
1867     if ( !(pState->mnMask & (SAL_FRAMESTATE_MASK_X | SAL_FRAMESTATE_MASK_Y)) )
1868         nPosSize |= SWP_NOMOVE;
1869     if ( !(pState->mnMask & (SAL_FRAMESTATE_MASK_WIDTH | SAL_FRAMESTATE_MASK_HEIGHT)) )
1870         nPosSize |= SWP_NOSIZE;
1871     if ( pState->mnMask & SAL_FRAMESTATE_MASK_X )
1872         nX = (int)pState->mnX - nLeftDeco;
1873     else
1874         nX = aWinRect.left;
1875     if ( pState->mnMask & SAL_FRAMESTATE_MASK_Y )
1876         nY = (int)pState->mnY - nTopDeco;
1877     else
1878         nY = aWinRect.top;
1879     if ( pState->mnMask & SAL_FRAMESTATE_MASK_WIDTH )
1880         nWidth = (int)pState->mnWidth + nLeftDeco + nRightDeco;
1881     else
1882         nWidth = aWinRect.right-aWinRect.left;
1883     if ( pState->mnMask & SAL_FRAMESTATE_MASK_HEIGHT )
1884         nHeight = (int)pState->mnHeight + nTopDeco + nBottomDeco;
1885     else
1886         nHeight = aWinRect.bottom-aWinRect.top;
1887 
1888     // Adjust Window in the screen:
1889     // if it does not fit into the screen do nothing, ie default pos/size will be used
1890     // if there is an overlap with the screen border move the window while keeping its size
1891 
1892     if( nWidth > nScreenWidth || nHeight > nScreenHeight )
1893         nPosSize |= (SWP_NOMOVE | SWP_NOSIZE);
1894 
1895     if ( nX+nWidth > nScreenX+nScreenWidth )
1896         nX = (nScreenX+nScreenWidth) - nWidth;
1897     if ( nY+nHeight > nScreenY+nScreenHeight )
1898         nY = (nScreenY+nScreenHeight) - nHeight;
1899     if ( nX < nScreenX )
1900         nX = nScreenX;
1901     if ( nY < nScreenY )
1902         nY = nScreenY;
1903 
1904     // Restore-Position setzen
1905     WINDOWPLACEMENT aPlacement;
1906     aPlacement.length = sizeof( aPlacement );
1907     GetWindowPlacement( mhWnd, &aPlacement );
1908 
1909     // Status setzen
1910     sal_Bool bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0;
1911 	sal_Bool bUpdateHiddenFramePos = FALSE;
1912     if ( !bVisible )
1913     {
1914         aPlacement.showCmd = SW_HIDE;
1915 
1916         if ( mbOverwriteState )
1917         {
1918             if ( pState->mnMask & SAL_FRAMESTATE_MASK_STATE )
1919             {
1920                 if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED )
1921                     mnShowState = SW_SHOWMINIMIZED;
1922                 else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
1923 				{
1924                     mnShowState = SW_SHOWMAXIMIZED;
1925 					bUpdateHiddenFramePos = TRUE;
1926 				}
1927                 else if ( pState->mnState & SAL_FRAMESTATE_NORMAL )
1928                     mnShowState = SW_SHOWNORMAL;
1929             }
1930         }
1931     }
1932     else
1933     {
1934         if ( pState->mnMask & SAL_FRAMESTATE_MASK_STATE )
1935         {
1936             if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED )
1937             {
1938                 if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
1939                     aPlacement.flags |= WPF_RESTORETOMAXIMIZED;
1940                 aPlacement.showCmd = SW_SHOWMINIMIZED;
1941             }
1942             else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
1943                 aPlacement.showCmd = SW_SHOWMAXIMIZED;
1944             else if ( pState->mnState & SAL_FRAMESTATE_NORMAL )
1945                 aPlacement.showCmd = SW_RESTORE;
1946         }
1947     }
1948 
1949     // if a window is neither minimized nor maximized or need not be
1950     // positioned visibly (that is in visible state), do not use
1951     // SetWindowPlacement since it calculates including the TaskBar
1952     if ( !IsIconic( mhWnd ) && !IsZoomed( mhWnd ) &&
1953          (!bVisible || (aPlacement.showCmd == SW_RESTORE)) )
1954     {
1955 		if( bUpdateHiddenFramePos )
1956 		{
1957 		    RECT aStateRect;
1958 		    aStateRect.left   = nX;
1959 		    aStateRect.top    = nY;
1960 		    aStateRect.right  = nX+nWidth;
1961 		    aStateRect.bottom = nY+nHeight;
1962 			// #96084 set a useful internal window size because
1963 			// the window will not be maximized (and the size updated) before show()
1964             SetMaximizedFrameGeometry( mhWnd, this, &aStateRect );
1965 			SetWindowPos( mhWnd, 0,
1966                           maGeometry.nX, maGeometry.nY, maGeometry.nWidth, maGeometry.nHeight,
1967                           SWP_NOZORDER | SWP_NOACTIVATE | nPosSize );
1968 		}
1969 		else
1970 			SetWindowPos( mhWnd, 0,
1971                       nX, nY, nWidth, nHeight,
1972                       SWP_NOZORDER | SWP_NOACTIVATE | nPosSize );
1973     }
1974     else
1975     {
1976         if( !(nPosSize & (SWP_NOMOVE|SWP_NOSIZE)) )
1977         {
1978             aPlacement.rcNormalPosition.left    = nX-nScreenX;
1979             aPlacement.rcNormalPosition.top     = nY-nScreenY;
1980             aPlacement.rcNormalPosition.right   = nX+nWidth-nScreenX;
1981             aPlacement.rcNormalPosition.bottom  = nY+nHeight-nScreenY;
1982         }
1983         SetWindowPlacement( mhWnd, &aPlacement );
1984     }
1985 
1986     if( !(nPosSize & SWP_NOMOVE) )
1987         mbDefPos = FALSE; // window was positioned
1988 }
1989 
1990 // -----------------------------------------------------------------------
1991 
1992 sal_Bool WinSalFrame::GetWindowState( SalFrameState* pState )
1993 {
1994     if ( maState.mnWidth && maState.mnHeight )
1995     {
1996         *pState = maState;
1997         // #94144# allow Minimize again, should be masked out when read from configuration
1998         // 91625 - Don't save minimize
1999         //if ( !(pState->mnState & SAL_FRAMESTATE_MAXIMIZED) )
2000         if ( !(pState->mnState & (SAL_FRAMESTATE_MINIMIZED | SAL_FRAMESTATE_MAXIMIZED)) )
2001             pState->mnState |= SAL_FRAMESTATE_NORMAL;
2002         return TRUE;
2003     }
2004 
2005     return FALSE;
2006 }
2007 
2008 // -----------------------------------------------------------------------
2009 
2010 void WinSalFrame::SetScreenNumber( unsigned int nNewScreen )
2011 {
2012     WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem());
2013     if( pSys )
2014     {
2015         const std::vector<WinSalSystem::DisplayMonitor>& rMonitors =
2016             pSys->getMonitors();
2017         size_t nMon = rMonitors.size();
2018         if( nNewScreen < nMon )
2019         {
2020             Point aOldMonPos, aNewMonPos( rMonitors[nNewScreen].m_aArea.TopLeft() );
2021             Point aCurPos( maGeometry.nX, maGeometry.nY );
2022             for( size_t i = 0; i < nMon; i++ )
2023             {
2024                 if( rMonitors[i].m_aArea.IsInside( aCurPos ) )
2025                 {
2026                     aOldMonPos = rMonitors[i].m_aArea.TopLeft();
2027                     break;
2028                 }
2029             }
2030             mnDisplay = nNewScreen;
2031             maGeometry.nScreenNumber = nNewScreen;
2032             SetPosSize( aNewMonPos.X() + (maGeometry.nX - aOldMonPos.X()),
2033                         aNewMonPos.Y() + (maGeometry.nY - aOldMonPos.Y()),
2034                         0, 0,
2035                         SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
2036         }
2037     }
2038 }
2039 
2040 // -----------------------------------------------------------------------
2041 
2042 void WinSalFrame::ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nDisplay )
2043 {
2044     if ( (mbFullScreen == bFullScreen) && (!bFullScreen || (mnDisplay == nDisplay)) )
2045         return;
2046 
2047     mbFullScreen = bFullScreen;
2048 	mnDisplay = nDisplay;
2049 
2050 	if ( bFullScreen )
2051     {
2052         // Damit Taskleiste von Windows ausgeblendet wird
2053         DWORD nExStyle = GetWindowExStyle( mhWnd );
2054         if ( nExStyle & WS_EX_TOOLWINDOW )
2055         {
2056             mbFullScreenToolWin = TRUE;
2057             nExStyle &= ~WS_EX_TOOLWINDOW;
2058             SetWindowExStyle( mhWnd, nExStyle );
2059         }
2060         // save old position
2061         GetWindowRect( mhWnd, &maFullScreenRect );
2062 
2063         // save show state
2064         mnFullScreenShowState = mnShowState;
2065         if ( !(GetWindowStyle( mhWnd ) & WS_VISIBLE) )
2066             mnShowState = SW_SHOW;
2067 
2068         // set window to screen size
2069         ImplSalFrameFullScreenPos( this, TRUE );
2070     }
2071     else
2072     {
2073         // wenn ShowState wieder hergestellt werden muss, hiden wir zuerst
2074         // das Fenster, damit es nicht so sehr flackert
2075         sal_Bool bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0;
2076         if ( bVisible && (mnShowState != mnFullScreenShowState) )
2077             ShowWindow( mhWnd, SW_HIDE );
2078 
2079         if ( mbFullScreenToolWin )
2080             SetWindowExStyle( mhWnd, GetWindowExStyle( mhWnd ) | WS_EX_TOOLWINDOW );
2081         mbFullScreenToolWin = FALSE;
2082 
2083         SetWindowPos( mhWnd, 0,
2084                       maFullScreenRect.left,
2085                       maFullScreenRect.top,
2086                       maFullScreenRect.right-maFullScreenRect.left,
2087                       maFullScreenRect.bottom-maFullScreenRect.top,
2088                       SWP_NOZORDER | SWP_NOACTIVATE );
2089 
2090         // restore show state
2091         if ( mnShowState != mnFullScreenShowState )
2092         {
2093             mnShowState = mnFullScreenShowState;
2094             if ( bVisible )
2095             {
2096                 mbInShow = TRUE;
2097                 ShowWindow( mhWnd, mnShowState );
2098                 mbInShow = FALSE;
2099                 UpdateWindow( mhWnd );
2100             }
2101         }
2102     }
2103 }
2104 
2105 // -----------------------------------------------------------------------
2106 
2107 void WinSalFrame::StartPresentation( sal_Bool bStart )
2108 {
2109     if ( mbPresentation == bStart )
2110         return;
2111 
2112     mbPresentation = bStart;
2113 
2114     SalData* pSalData = GetSalData();
2115     if ( bStart )
2116     {
2117         if ( !pSalData->mpSageEnableProc )
2118         {
2119             if ( pSalData->mnSageStatus != DISABLE_AGENT )
2120             {
2121                 OFSTRUCT aOS;
2122                 OpenFile( "SAGE.DLL", &aOS, OF_EXIST );
2123 
2124                 if ( !aOS.nErrCode )
2125                 {
2126                     OUString aLibraryName( OUString::createFromAscii( aOS.szPathName ) );
2127                     oslModule mhSageInst = osl_loadModule( aLibraryName.pData, SAL_LOADMODULE_DEFAULT );
2128                     pSalData->mpSageEnableProc = (SysAgt_Enable_PROC)osl_getAsciiFunctionSymbol( mhSageInst, "System_Agent_Enable" );
2129                 }
2130                 else
2131                     pSalData->mnSageStatus = DISABLE_AGENT;
2132             }
2133         }
2134 
2135         if ( pSalData->mpSageEnableProc )
2136         {
2137             pSalData->mnSageStatus = pSalData->mpSageEnableProc( GET_AGENT_STATUS );
2138             if ( pSalData->mnSageStatus == ENABLE_AGENT )
2139                 pSalData->mpSageEnableProc( DISABLE_AGENT );
2140         }
2141 
2142         // Bildschirmschoner ausschalten, wenn Praesentation laueft
2143         SystemParametersInfo( SPI_GETSCREENSAVEACTIVE, 0,
2144                               &(pSalData->mbScrSvrEnabled), 0 );
2145         if ( pSalData->mbScrSvrEnabled )
2146             SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, FALSE, 0, 0 );
2147     }
2148     else
2149     {
2150         // Bildschirmschoner wieder einschalten
2151         if ( pSalData->mbScrSvrEnabled )
2152             SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, pSalData->mbScrSvrEnabled, 0, 0 );
2153 
2154         // Systemagenten wieder aktivieren
2155         if ( pSalData->mnSageStatus == ENABLE_AGENT )
2156             pSalData->mpSageEnableProc( pSalData->mnSageStatus );
2157     }
2158 }
2159 
2160 // -----------------------------------------------------------------------
2161 
2162 void WinSalFrame::SetAlwaysOnTop( sal_Bool bOnTop )
2163 {
2164     HWND hWnd;
2165     if ( bOnTop )
2166         hWnd = HWND_TOPMOST;
2167     else
2168         hWnd = HWND_NOTOPMOST;
2169     SetWindowPos( mhWnd, hWnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
2170 }
2171 
2172 // -----------------------------------------------------------------------
2173 
2174 static void ImplSalToTop( HWND hWnd, sal_uInt16 nFlags )
2175 {
2176     WinSalFrame* pToTopFrame = GetWindowPtr( hWnd );
2177     if( pToTopFrame && (pToTopFrame->mnStyle & SAL_FRAME_STYLE_SYSTEMCHILD) != 0 )
2178         BringWindowToTop( hWnd );
2179 
2180     if ( nFlags & SAL_FRAME_TOTOP_FOREGROUNDTASK )
2181     {
2182         // This magic code is necessary to connect the input focus of the
2183         // current window thread and the thread which owns the window that
2184         // should be the new foreground window.
2185         HWND   hCurrWnd     = GetForegroundWindow();
2186         DWORD  myThreadID   = GetCurrentThreadId();
2187         DWORD  currThreadID = GetWindowThreadProcessId(hCurrWnd,NULL);
2188         AttachThreadInput(myThreadID, currThreadID,TRUE);
2189         SetForegroundWindow(hWnd);
2190         AttachThreadInput(myThreadID,currThreadID,FALSE);
2191     }
2192 
2193     if ( nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN )
2194     {
2195         HWND hIconicWnd = hWnd;
2196         while ( hIconicWnd )
2197         {
2198             if ( IsIconic( hIconicWnd ) )
2199             {
2200                 WinSalFrame* pFrame = GetWindowPtr( hIconicWnd );
2201                 if ( pFrame )
2202                 {
2203                     if ( GetWindowPtr( hWnd )->mbRestoreMaximize )
2204                         ShowWindow( hIconicWnd, SW_MAXIMIZE );
2205                     else
2206                         ShowWindow( hIconicWnd, SW_RESTORE );
2207                 }
2208                 else
2209                     ShowWindow( hIconicWnd, SW_RESTORE );
2210             }
2211 
2212             hIconicWnd = ::GetParent( hIconicWnd );
2213         }
2214     }
2215 
2216     if ( !IsIconic( hWnd ) && IsWindowVisible( hWnd ) )
2217     {
2218         SetFocus( hWnd );
2219 
2220         // Windows behauptet oefters mal, das man den Focus hat, obwohl
2221         // man diesen nicht hat. Wenn dies der Fall ist, dann versuchen
2222         // wir diesen auch ganz richtig zu bekommen.
2223         if ( ::GetFocus() == hWnd )
2224             SetForegroundWindow( hWnd );
2225     }
2226 }
2227 
2228 // -----------------------------------------------------------------------
2229 
2230 void WinSalFrame::ToTop( sal_uInt16 nFlags )
2231 {
2232 	nFlags &= ~SAL_FRAME_TOTOP_GRABFOCUS;	// this flag is not needed on win32
2233     // Post this Message to the window, because this only works
2234     // in the thread of the window, which has create this window.
2235     // We post this message to avoid deadlocks
2236     if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() )
2237         ImplPostMessage( mhWnd, SAL_MSG_TOTOP, nFlags, 0 );
2238     else
2239         ImplSalToTop( mhWnd, nFlags );
2240 }
2241 
2242 // -----------------------------------------------------------------------
2243 
2244 void WinSalFrame::SetPointer( PointerStyle ePointerStyle )
2245 {
2246     struct ImplPtrData
2247     {
2248         HCURSOR         mhCursor;
2249         LPCSTR          mnSysId;
2250         UINT            mnOwnId;
2251     };
2252 
2253     static ImplPtrData aImplPtrTab[POINTER_COUNT] =
2254     {
2255     { 0, IDC_ARROW, 0 },                            // POINTER_ARROW
2256     { 0, 0, SAL_RESID_POINTER_NULL },               // POINTER_NULL
2257     { 0, IDC_WAIT, 0 },                             // POINTER_WAIT
2258     { 0, IDC_IBEAM, 0 },                            // POINTER_TEXT
2259     { 0, IDC_HELP, 0 },                             // POINTER_HELP
2260     { 0, 0, SAL_RESID_POINTER_CROSS },              // POINTER_CROSS
2261     { 0, 0, SAL_RESID_POINTER_MOVE },               // POINTER_MOVE
2262     { 0, IDC_SIZENS, 0 },                           // POINTER_NSIZE
2263     { 0, IDC_SIZENS, 0 },                           // POINTER_SSIZE
2264     { 0, IDC_SIZEWE, 0 },                           // POINTER_WSIZE
2265     { 0, IDC_SIZEWE, 0 },                           // POINTER_ESIZE
2266     { 0, IDC_SIZENWSE, 0 },                         // POINTER_NWSIZE
2267     { 0, IDC_SIZENESW, 0 },                         // POINTER_NESIZE
2268     { 0, IDC_SIZENESW, 0 },                         // POINTER_SWSIZE
2269     { 0, IDC_SIZENWSE, 0 },                         // POINTER_SESIZE
2270     { 0, IDC_SIZENS, 0 },                           // POINTER_WINDOW_NSIZE
2271     { 0, IDC_SIZENS, 0 },                           // POINTER_WINDOW_SSIZE
2272     { 0, IDC_SIZEWE, 0 },                           // POINTER_WINDOW_WSIZE
2273     { 0, IDC_SIZEWE, 0 },                           // POINTER_WINDOW_ESIZE
2274     { 0, IDC_SIZENWSE, 0 },                         // POINTER_WINDOW_NWSIZE
2275     { 0, IDC_SIZENESW, 0 },                         // POINTER_WINDOW_NESIZE
2276     { 0, IDC_SIZENESW, 0 },                         // POINTER_WINDOW_SWSIZE
2277     { 0, IDC_SIZENWSE, 0 },                         // POINTER_WINDOW_SESIZE
2278     { 0, 0, SAL_RESID_POINTER_HSPLIT },             // POINTER_HSPLIT
2279     { 0, 0, SAL_RESID_POINTER_VSPLIT },             // POINTER_VSPLIT
2280     { 0, 0, SAL_RESID_POINTER_HSIZEBAR },           // POINTER_HSIZEBAR
2281     { 0, 0, SAL_RESID_POINTER_VSIZEBAR },           // POINTER_VSIZEBAR
2282     { 0, 0, SAL_RESID_POINTER_HAND },               // POINTER_HAND
2283     { 0, 0, SAL_RESID_POINTER_REFHAND },            // POINTER_REFHAND
2284     { 0, 0, SAL_RESID_POINTER_PEN },                // POINTER_PEN
2285     { 0, 0, SAL_RESID_POINTER_MAGNIFY },            // POINTER_MAGNIFY
2286     { 0, 0, SAL_RESID_POINTER_FILL },               // POINTER_FILL
2287     { 0, 0, SAL_RESID_POINTER_ROTATE },             // POINTER_ROTATE
2288     { 0, 0, SAL_RESID_POINTER_HSHEAR },             // POINTER_HSHEAR
2289     { 0, 0, SAL_RESID_POINTER_VSHEAR },             // POINTER_VSHEAR
2290     { 0, 0, SAL_RESID_POINTER_MIRROR },             // POINTER_MIRROR
2291     { 0, 0, SAL_RESID_POINTER_CROOK },              // POINTER_CROOK
2292     { 0, 0, SAL_RESID_POINTER_CROP },               // POINTER_CROP
2293     { 0, 0, SAL_RESID_POINTER_MOVEPOINT },          // POINTER_MOVEPOINT
2294     { 0, 0, SAL_RESID_POINTER_MOVEBEZIERWEIGHT },   // POINTER_MOVEBEZIERWEIGHT
2295     { 0, 0, SAL_RESID_POINTER_MOVEDATA },           // POINTER_MOVEDATA
2296     { 0, 0, SAL_RESID_POINTER_COPYDATA },           // POINTER_COPYDATA
2297     { 0, 0, SAL_RESID_POINTER_LINKDATA },           // POINTER_LINKDATA
2298     { 0, 0, SAL_RESID_POINTER_MOVEDATALINK },       // POINTER_MOVEDATALINK
2299     { 0, 0, SAL_RESID_POINTER_COPYDATALINK },       // POINTER_COPYDATALINK
2300     { 0, 0, SAL_RESID_POINTER_MOVEFILE },           // POINTER_MOVEFILE
2301     { 0, 0, SAL_RESID_POINTER_COPYFILE },           // POINTER_COPYFILE
2302     { 0, 0, SAL_RESID_POINTER_LINKFILE },           // POINTER_LINKFILE
2303     { 0, 0, SAL_RESID_POINTER_MOVEFILELINK },       // POINTER_MOVEFILELINK
2304     { 0, 0, SAL_RESID_POINTER_COPYFILELINK },       // POINTER_COPYFILELINK
2305     { 0, 0, SAL_RESID_POINTER_MOVEFILES },          // POINTER_MOVEFILES
2306     { 0, 0, SAL_RESID_POINTER_COPYFILES },          // POINTER_COPYFILES
2307     { 0, 0, SAL_RESID_POINTER_NOTALLOWED },         // POINTER_NOTALLOWED
2308     { 0, 0, SAL_RESID_POINTER_DRAW_LINE },          // POINTER_DRAW_LINE
2309     { 0, 0, SAL_RESID_POINTER_DRAW_RECT },          // POINTER_DRAW_RECT
2310     { 0, 0, SAL_RESID_POINTER_DRAW_POLYGON },       // POINTER_DRAW_POLYGON
2311     { 0, 0, SAL_RESID_POINTER_DRAW_BEZIER },        // POINTER_DRAW_BEZIER
2312     { 0, 0, SAL_RESID_POINTER_DRAW_ARC },           // POINTER_DRAW_ARC
2313     { 0, 0, SAL_RESID_POINTER_DRAW_PIE },           // POINTER_DRAW_PIE
2314     { 0, 0, SAL_RESID_POINTER_DRAW_CIRCLECUT },     // POINTER_DRAW_CIRCLECUT
2315     { 0, 0, SAL_RESID_POINTER_DRAW_ELLIPSE },       // POINTER_DRAW_ELLIPSE
2316     { 0, 0, SAL_RESID_POINTER_DRAW_FREEHAND },      // POINTER_DRAW_FREEHAND
2317     { 0, 0, SAL_RESID_POINTER_DRAW_CONNECT },       // POINTER_DRAW_CONNECT
2318     { 0, 0, SAL_RESID_POINTER_DRAW_TEXT },          // POINTER_DRAW_TEXT
2319     { 0, 0, SAL_RESID_POINTER_DRAW_CAPTION },       // POINTER_DRAW_CAPTION
2320     { 0, 0, SAL_RESID_POINTER_CHART },              // POINTER_CHART
2321     { 0, 0, SAL_RESID_POINTER_DETECTIVE },          // POINTER_DETECTIVE
2322     { 0, 0, SAL_RESID_POINTER_PIVOT_COL },          // POINTER_PIVOT_COL
2323     { 0, 0, SAL_RESID_POINTER_PIVOT_ROW },          // POINTER_PIVOT_ROW
2324     { 0, 0, SAL_RESID_POINTER_PIVOT_FIELD },        // POINTER_PIVOT_FIELD
2325     { 0, 0, SAL_RESID_POINTER_CHAIN },              // POINTER_CHAIN
2326     { 0, 0, SAL_RESID_POINTER_CHAIN_NOTALLOWED },   // POINTER_CHAIN_NOTALLOWED
2327     { 0, 0, SAL_RESID_POINTER_TIMEEVENT_MOVE },     // POINTER_TIMEEVENT_MOVE
2328     { 0, 0, SAL_RESID_POINTER_TIMEEVENT_SIZE },     // POINTER_TIMEEVENT_SIZE
2329     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_N },       // POINTER_AUTOSCROLL_N
2330     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_S },       // POINTER_AUTOSCROLL_S
2331     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_W },       // POINTER_AUTOSCROLL_W
2332     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_E },       // POINTER_AUTOSCROLL_E
2333     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NW },      // POINTER_AUTOSCROLL_NW
2334     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NE },      // POINTER_AUTOSCROLL_NE
2335     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SW },      // POINTER_AUTOSCROLL_SW
2336     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SE },      // POINTER_AUTOSCROLL_SE
2337     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NS },      // POINTER_AUTOSCROLL_NS
2338     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_WE },      // POINTER_AUTOSCROLL_WE
2339     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NSWE },    // POINTER_AUTOSCROLL_NSWE
2340     { 0, 0, SAL_RESID_POINTER_AIRBRUSH },           // POINTER_AIRBRUSH
2341     { 0, 0, SAL_RESID_POINTER_TEXT_VERTICAL },      // POINTER_TEXT_VERTICAL
2342     { 0, 0, SAL_RESID_POINTER_PIVOT_DELETE },       // POINTER_PIVOT_DELETE
2343 
2344     // --> FME 2004-07-30 #i32329# Enhanced table selection
2345     { 0, 0, SAL_RESID_POINTER_TAB_SELECT_S },       // POINTER_TAB_SELECT_S
2346     { 0, 0, SAL_RESID_POINTER_TAB_SELECT_E },       // POINTER_TAB_SELECT_E
2347     { 0, 0, SAL_RESID_POINTER_TAB_SELECT_SE },      // POINTER_TAB_SELECT_SE
2348     { 0, 0, SAL_RESID_POINTER_TAB_SELECT_W },       // POINTER_TAB_SELECT_W
2349     { 0, 0, SAL_RESID_POINTER_TAB_SELECT_SW },      // POINTER_TAB_SELECT_SW
2350     // <--
2351 
2352     // --> FME 2004-08-16 #i20119# Paintbrush tool
2353     { 0, 0, SAL_RESID_POINTER_PAINTBRUSH }          // POINTER_PAINTBRUSH
2354     // <--
2355 
2356     };
2357 
2358 #if POINTER_COUNT != 94
2359 #error New Pointer must be defined!
2360 #endif
2361 
2362     // Mousepointer loaded ?
2363     if ( !aImplPtrTab[ePointerStyle].mhCursor )
2364     {
2365         if ( aImplPtrTab[ePointerStyle].mnOwnId )
2366             aImplPtrTab[ePointerStyle].mhCursor = ImplLoadSalCursor( aImplPtrTab[ePointerStyle].mnOwnId );
2367         else
2368             aImplPtrTab[ePointerStyle].mhCursor = LoadCursor( 0, aImplPtrTab[ePointerStyle].mnSysId );
2369     }
2370 
2371     // Unterscheidet sich der Mauspointer, dann den neuen setzen
2372     if ( mhCursor != aImplPtrTab[ePointerStyle].mhCursor )
2373     {
2374         mhCursor = aImplPtrTab[ePointerStyle].mhCursor;
2375         SetCursor( mhCursor );
2376     }
2377 }
2378 
2379 // -----------------------------------------------------------------------
2380 
2381 void WinSalFrame::CaptureMouse( sal_Bool bCapture )
2382 {
2383     // Send this Message to the window, because CaptureMouse() only work
2384     // in the thread of the window, which has create this window
2385     int nMsg;
2386     if ( bCapture )
2387         nMsg = SAL_MSG_CAPTUREMOUSE;
2388     else
2389         nMsg = SAL_MSG_RELEASEMOUSE;
2390     ImplSendMessage( mhWnd, nMsg, 0, 0 );
2391 }
2392 
2393 // -----------------------------------------------------------------------
2394 
2395 void WinSalFrame::SetPointerPos( long nX, long nY )
2396 {
2397     POINT aPt;
2398     aPt.x = (int)nX;
2399     aPt.y = (int)nY;
2400     ClientToScreen( mhWnd, &aPt );
2401     SetCursorPos( aPt.x, aPt.y );
2402 }
2403 
2404 // -----------------------------------------------------------------------
2405 
2406 void WinSalFrame::Flush()
2407 {
2408     GdiFlush();
2409 }
2410 
2411 // -----------------------------------------------------------------------
2412 
2413 void WinSalFrame::Sync()
2414 {
2415     GdiFlush();
2416 }
2417 
2418 // -----------------------------------------------------------------------
2419 
2420 static void ImplSalFrameSetInputContext( HWND hWnd, const SalInputContext* pContext )
2421 {
2422     WinSalFrame*   pFrame = GetWindowPtr( hWnd );
2423     sal_Bool        bIME = (pContext->mnOptions & SAL_INPUTCONTEXT_TEXT) != 0;
2424     if ( bIME )
2425     {
2426         if ( !pFrame->mbIME )
2427         {
2428             pFrame->mbIME = TRUE;
2429 
2430             if ( pFrame->mhDefIMEContext )
2431             {
2432                 ImmAssociateContext( pFrame->mhWnd, pFrame->mhDefIMEContext );
2433                 UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_PROPERTY );
2434                 pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
2435                 pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
2436                 pFrame->mbHandleIME = !pFrame->mbSpezIME;
2437             }
2438         }
2439 
2440         // When the application can't handle IME messages, then the
2441         // System should handle the IME handling
2442         if ( !(pContext->mnOptions & SAL_INPUTCONTEXT_EXTTEXTINPUT) )
2443             pFrame->mbHandleIME = FALSE;
2444 
2445         // Set the Font for IME Handling
2446         if ( pContext->mpFont )
2447         {
2448             HIMC hIMC = ImmGetContext( pFrame->mhWnd );
2449             if ( hIMC )
2450             {
2451                 LOGFONTW aLogFont;
2452                 HDC hDC = GetDC( pFrame->mhWnd );
2453                 // In case of vertical writing, always append a '@' to the
2454                 // Windows font name, not only if such a Windows font really is
2455                 // available (bTestVerticalAvail == false in the below call):
2456                 // The Windows IME's candidates window seems to always use a
2457                 // font that has all necessary glyphs, not necessarily the one
2458                 // specified by this font name; but it seems to decide whether
2459                 // to use that font's horizontal or vertical variant based on a
2460                 // '@' in front of this font name.
2461                 ImplGetLogFontFromFontSelect( hDC, pContext->mpFont, aLogFont,
2462                                               false );
2463                 ReleaseDC( pFrame->mhWnd, hDC );
2464                 ImmSetCompositionFontW( hIMC, &aLogFont );
2465                 ImmReleaseContext( pFrame->mhWnd, hIMC );
2466             }
2467         }
2468     }
2469     else
2470     {
2471         if ( pFrame->mbIME )
2472         {
2473             pFrame->mbIME = FALSE;
2474             pFrame->mbHandleIME = FALSE;
2475             ImmAssociateContext( pFrame->mhWnd, 0 );
2476         }
2477     }
2478 }
2479 
2480 // -----------------------------------------------------------------------
2481 
2482 void WinSalFrame::SetInputContext( SalInputContext* pContext )
2483 {
2484     // Must be called in the main thread!
2485     ImplSendMessage( mhWnd, SAL_MSG_SETINPUTCONTEXT, 0, (LPARAM)(void*)pContext );
2486 }
2487 
2488 // -----------------------------------------------------------------------
2489 
2490 static void ImplSalFrameEndExtTextInput( HWND hWnd, sal_uInt16 nFlags )
2491 {
2492     HIMC hIMC = ImmGetContext( hWnd );
2493     if ( hIMC )
2494     {
2495         DWORD nIndex;
2496         if ( nFlags & SAL_FRAME_ENDEXTTEXTINPUT_COMPLETE )
2497             nIndex = CPS_COMPLETE;
2498         else
2499             nIndex = CPS_CANCEL;
2500 
2501         ImmNotifyIME( hIMC, NI_COMPOSITIONSTR, nIndex, 0 );
2502         ImmReleaseContext( hWnd, hIMC );
2503     }
2504 }
2505 
2506 // -----------------------------------------------------------------------
2507 
2508 void WinSalFrame::EndExtTextInput( sal_uInt16 nFlags )
2509 {
2510     // Must be called in the main thread!
2511     ImplSendMessage( mhWnd, SAL_MSG_ENDEXTTEXTINPUT, (WPARAM)nFlags, 0 );
2512 }
2513 
2514 // -----------------------------------------------------------------------
2515 
2516 static void ImplGetKeyNameText( LONG lParam, sal_Unicode* pBuf,
2517                                 UINT& rCount, UINT nMaxSize,
2518                                 const sal_Char* pReplace )
2519 {
2520     DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "WinSalFrame::ImplGetKeyNameTextW(): WCHAR != sal_Unicode" );
2521 
2522     static const int nMaxKeyLen = 350;
2523     WCHAR aKeyBuf[ nMaxKeyLen ];
2524     int nKeyLen = 0;
2525     if ( lParam )
2526     {
2527         if ( true/*aSalShlData.mbWNT*/ )
2528         {
2529             nKeyLen = GetKeyNameTextW( lParam, aKeyBuf, nMaxKeyLen );
2530             DBG_ASSERT( nKeyLen <= nMaxKeyLen, "Invalid key name length!" );
2531             if( nKeyLen > nMaxKeyLen )
2532                 nKeyLen = 0;
2533             else if( nKeyLen > 0 )
2534             {
2535                 // Capitalize just the first letter of key names
2536                 CharLowerBuffW( aKeyBuf, nKeyLen );
2537 
2538                 bool bUpper = true;
2539                 for( WCHAR *pW=aKeyBuf, *pE=pW+nKeyLen; pW < pE; ++pW )
2540                 {
2541                     if( bUpper )
2542                         CharUpperBuffW( pW, 1 );
2543                     bUpper = (*pW=='+') || (*pW=='-') || (*pW==' ') || (*pW=='.');
2544                 }
2545             }
2546         }
2547     }
2548 
2549     if ( (nKeyLen > 0) || pReplace )
2550     {
2551         if( (rCount > 0) && (rCount < nMaxSize) )
2552         {
2553             pBuf[rCount] = '+';
2554             rCount++;
2555         }
2556 
2557         if( nKeyLen > 0 )
2558         {
2559             if( nKeyLen + rCount > nMaxSize )
2560                 nKeyLen = nMaxSize - rCount;
2561             memcpy( pBuf+rCount, aKeyBuf, nKeyLen*sizeof( sal_Unicode ) );
2562             rCount += nKeyLen;
2563         }
2564         else // fall back to provided default name
2565         {
2566             while( *pReplace && (rCount < nMaxSize) )
2567             {
2568                 pBuf[rCount] = *pReplace;
2569                 rCount++;
2570                 pReplace++;
2571             }
2572         }
2573     }
2574     else
2575         rCount = 0;
2576 }
2577 
2578 // -----------------------------------------------------------------------
2579 
2580 XubString WinSalFrame::GetKeyName( sal_uInt16 nKeyCode )
2581 {
2582     static const int nMaxKeyLen = 350;
2583     sal_Unicode aKeyBuf[ nMaxKeyLen ];
2584     UINT        nKeyBufLen = 0;
2585     UINT        nSysCode = 0;
2586 
2587     if ( nKeyCode & KEY_MOD1 )
2588     {
2589         nSysCode = MapVirtualKey( VK_CONTROL, 0 );
2590         nSysCode = (nSysCode << 16) | (((sal_uLong)1) << 25);
2591         ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Ctrl" );
2592     }
2593 
2594     if ( nKeyCode & KEY_MOD2 )
2595     {
2596         nSysCode = MapVirtualKey( VK_MENU, 0 );
2597         nSysCode = (nSysCode << 16) | (((sal_uLong)1) << 25);
2598         ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Alt" );
2599     }
2600 
2601     if ( nKeyCode & KEY_SHIFT )
2602     {
2603         nSysCode = MapVirtualKey( VK_SHIFT, 0 );
2604         nSysCode = (nSysCode << 16) | (((sal_uLong)1) << 25);
2605         ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Shift" );
2606     }
2607 
2608     sal_uInt16      nCode = nKeyCode & 0x0FFF;
2609     sal_uLong       nSysCode2 = 0;
2610     sal_Char*   pReplace = NULL;
2611     sal_Unicode cSVCode = 0;
2612     sal_Char    aFBuf[4];
2613     nSysCode = 0;
2614 
2615     if ( (nCode >= KEY_0) && (nCode <= KEY_9) )
2616         cSVCode = '0' + (nCode - KEY_0);
2617     else if ( (nCode >= KEY_A) && (nCode <= KEY_Z) )
2618         cSVCode = 'A' + (nCode - KEY_A);
2619     else if ( (nCode >= KEY_F1) && (nCode <= KEY_F26) )
2620     {
2621         nSysCode = VK_F1 + (nCode - KEY_F1);
2622         aFBuf[0] = 'F';
2623         if ( (nCode >= KEY_F1) && (nCode <= KEY_F9) )
2624         {
2625             aFBuf[1] = sal::static_int_cast<sal_Char>('1' + (nCode - KEY_F1));
2626             aFBuf[2] = 0;
2627         }
2628         else if ( (nCode >= KEY_F10) && (nCode <= KEY_F19) )
2629         {
2630             aFBuf[1] = '1';
2631             aFBuf[2] = sal::static_int_cast<sal_Char>('0' + (nCode - KEY_F10));
2632             aFBuf[3] = 0;
2633         }
2634         else
2635         {
2636             aFBuf[1] = '2';
2637             aFBuf[2] = sal::static_int_cast<sal_Char>('0' + (nCode - KEY_F20));
2638             aFBuf[3] = 0;
2639         }
2640         pReplace = aFBuf;
2641     }
2642     else
2643     {
2644         switch ( nCode )
2645         {
2646             case KEY_DOWN:
2647                 nSysCode = VK_DOWN;
2648                 nSysCode2 = (((sal_uLong)1) << 24);
2649                 pReplace = "Down";
2650                 break;
2651             case KEY_UP:
2652                 nSysCode = VK_UP;
2653                 nSysCode2 = (((sal_uLong)1) << 24);
2654                 pReplace = "Up";
2655                 break;
2656             case KEY_LEFT:
2657                 nSysCode = VK_LEFT;
2658                 nSysCode2 = (((sal_uLong)1) << 24);
2659                 pReplace = "Left";
2660                 break;
2661             case KEY_RIGHT:
2662                 nSysCode = VK_RIGHT;
2663                 nSysCode2 = (((sal_uLong)1) << 24);
2664                 pReplace = "Right";
2665                 break;
2666             case KEY_HOME:
2667                 nSysCode = VK_HOME;
2668                 nSysCode2 = (((sal_uLong)1) << 24);
2669                 pReplace = "Home";
2670                 break;
2671             case KEY_END:
2672                 nSysCode = VK_END;
2673                 nSysCode2 = (((sal_uLong)1) << 24);
2674                 pReplace = "End";
2675                 break;
2676             case KEY_PAGEUP:
2677                 nSysCode = VK_PRIOR;
2678                 nSysCode2 = (((sal_uLong)1) << 24);
2679                 pReplace = "Page Up";
2680                 break;
2681             case KEY_PAGEDOWN:
2682                 nSysCode = VK_NEXT;
2683                 nSysCode2 = (((sal_uLong)1) << 24);
2684                 pReplace = "Page Down";
2685                 break;
2686             case KEY_RETURN:
2687                 nSysCode = VK_RETURN;
2688                 pReplace = "Enter";
2689                 break;
2690             case KEY_ESCAPE:
2691                 nSysCode = VK_ESCAPE;
2692                 pReplace = "Escape";
2693                 break;
2694             case KEY_TAB:
2695                 nSysCode = VK_TAB;
2696                 pReplace = "Tab";
2697                 break;
2698             case KEY_BACKSPACE:
2699                 nSysCode = VK_BACK;
2700                 pReplace = "Backspace";
2701                 break;
2702             case KEY_SPACE:
2703                 nSysCode = VK_SPACE;
2704                 pReplace = "Space";
2705                 break;
2706             case KEY_INSERT:
2707                 nSysCode = VK_INSERT;
2708                 nSysCode2 = (((sal_uLong)1) << 24);
2709                 pReplace = "Insert";
2710                 break;
2711             case KEY_DELETE:
2712                 nSysCode = VK_DELETE;
2713                 nSysCode2 = (((sal_uLong)1) << 24);
2714                 pReplace = "Delete";
2715                 break;
2716 
2717             case KEY_ADD:
2718                 cSVCode  = '+';
2719                 break;
2720             case KEY_SUBTRACT:
2721                 cSVCode  = '-';
2722                 break;
2723             case KEY_MULTIPLY:
2724                 cSVCode  = '*';
2725                 break;
2726             case KEY_DIVIDE:
2727                 cSVCode  = '/';
2728                 break;
2729             case KEY_POINT:
2730                 cSVCode  = '.';
2731                 break;
2732             case KEY_COMMA:
2733                 cSVCode  = ',';
2734                 break;
2735             case KEY_LESS:
2736                 cSVCode  = '<';
2737                 break;
2738             case KEY_GREATER:
2739                 cSVCode  = '>';
2740                 break;
2741             case KEY_EQUAL:
2742                 cSVCode  = '=';
2743                 break;
2744         }
2745     }
2746 
2747     if ( nSysCode )
2748     {
2749         nSysCode = MapVirtualKey( (UINT)nSysCode, 0 );
2750         if ( nSysCode )
2751             nSysCode = (nSysCode << 16) | nSysCode2;
2752         ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, pReplace );
2753     }
2754     else
2755     {
2756         if ( cSVCode )
2757         {
2758             if ( nKeyBufLen > 0 )
2759                 aKeyBuf[ nKeyBufLen++ ] = '+';
2760             if( nKeyBufLen < nMaxKeyLen )
2761                 aKeyBuf[ nKeyBufLen++ ] = cSVCode;
2762         }
2763     }
2764 
2765     if( !nKeyBufLen )
2766         return XubString();
2767 
2768     return XubString( aKeyBuf, sal::static_int_cast< sal_uInt16 >(nKeyBufLen) );
2769 }
2770 
2771 // -----------------------------------------------------------------------
2772 
2773 XubString WinSalFrame::GetSymbolKeyName( const XubString&, sal_uInt16 nKeyCode )
2774 {
2775     return GetKeyName( nKeyCode );
2776 }
2777 
2778 // -----------------------------------------------------------------------
2779 
2780 inline Color ImplWinColorToSal( COLORREF nColor )
2781 {
2782     return Color( GetRValue( nColor ), GetGValue( nColor ), GetBValue( nColor ) );
2783 }
2784 
2785 // -----------------------------------------------------------------------
2786 
2787 static void ImplSalUpdateStyleFontA( HDC hDC, const LOGFONTA& rLogFont, Font& rFont )
2788 {
2789     ImplSalLogFontToFontA( hDC, rLogFont, rFont );
2790 
2791     // On Windows 9x, Windows NT we get sometimes very small sizes
2792     // (for example for the small Caption height).
2793     // So if it is MS Sans Serif, a none scalable font we use
2794     // 8 Point as the minimum control height, in all other cases
2795     // 6 Point is the smallest one
2796     if ( rFont.GetHeight() < 8 )
2797     {
2798         if ( rtl_str_compareIgnoreAsciiCase( rLogFont.lfFaceName, "MS Sans Serif" ) == 0 )
2799             rFont.SetHeight( 8 );
2800         else if ( rFont.GetHeight() < 6 )
2801             rFont.SetHeight( 6 );
2802     }
2803 }
2804 
2805 // -----------------------------------------------------------------------
2806 
2807 static void ImplSalUpdateStyleFontW( HDC hDC, const LOGFONTW& rLogFont, Font& rFont )
2808 {
2809     ImplSalLogFontToFontW( hDC, rLogFont, rFont );
2810 
2811     // On Windows 9x, Windows NT we get sometimes very small sizes
2812     // (for example for the small Caption height).
2813     // So if it is MS Sans Serif, a none scalable font we use
2814     // 8 Point as the minimum control height, in all other cases
2815     // 6 Point is the smallest one
2816     if ( rFont.GetHeight() < 8 )
2817     {
2818         if ( rtl_ustr_compareIgnoreAsciiCase( reinterpret_cast<const sal_Unicode*>(rLogFont.lfFaceName), reinterpret_cast<const sal_Unicode*>(L"MS Sans Serif") ) == 0 )
2819             rFont.SetHeight( 8 );
2820         else if ( rFont.GetHeight() < 6 )
2821             rFont.SetHeight( 6 );
2822     }
2823 }
2824 
2825 // -----------------------------------------------------------------------
2826 
2827 static long ImplA2I( const BYTE* pStr )
2828 {
2829     long    n = 0;
2830     int     nSign = 1;
2831 
2832     if ( *pStr == '-' )
2833     {
2834         nSign = -1;
2835         pStr++;
2836     }
2837 
2838     while( (*pStr >= 48) && (*pStr <= 57) )
2839     {
2840         n *= 10;
2841         n += ((*pStr) - 48);
2842         pStr++;
2843     }
2844 
2845     n *= nSign;
2846 
2847     return n;
2848 }
2849 
2850 // -----------------------------------------------------------------------
2851 static HRESULT WINAPI backwardCompatibleDwmIsCompositionEnabled( BOOL* pOut )
2852 {
2853     *pOut = FALSE;
2854     return S_OK;
2855 }
2856 
2857 static BOOL ImplDwmIsCompositionEnabled()
2858 {
2859     SalData* pSalData = GetSalData();
2860     if( ! pSalData->mpDwmIsCompositionEnabled )
2861     {
2862         rtl::OUString aLibraryName( RTL_CONSTASCII_USTRINGPARAM( "Dwmapi.dll" ) );
2863         pSalData->maDwmLib = osl_loadModule( aLibraryName.pData, SAL_LOADMODULE_DEFAULT );
2864         if( pSalData->maDwmLib )
2865             pSalData->mpDwmIsCompositionEnabled = (DwmIsCompositionEnabled_ptr)osl_getAsciiFunctionSymbol( pSalData->maDwmLib, "DwmIsCompositionEnabled" );
2866         if( ! pSalData->mpDwmIsCompositionEnabled ) // something failed
2867             pSalData->mpDwmIsCompositionEnabled = backwardCompatibleDwmIsCompositionEnabled;
2868     }
2869     BOOL aResult = FALSE;
2870     HRESULT nError = pSalData->mpDwmIsCompositionEnabled( &aResult );
2871     return nError == S_OK && aResult;
2872 }
2873 
2874 
2875 void WinSalFrame::UpdateSettings( AllSettings& rSettings )
2876 {
2877     MouseSettings aMouseSettings = rSettings.GetMouseSettings();
2878     aMouseSettings.SetDoubleClickTime( GetDoubleClickTime() );
2879     aMouseSettings.SetDoubleClickWidth( GetSystemMetrics( SM_CXDOUBLECLK ) );
2880     aMouseSettings.SetDoubleClickHeight( GetSystemMetrics( SM_CYDOUBLECLK ) );
2881     long nDragWidth = GetSystemMetrics( SM_CXDRAG );
2882     long nDragHeight = GetSystemMetrics( SM_CYDRAG );
2883     if ( nDragWidth )
2884         aMouseSettings.SetStartDragWidth( nDragWidth );
2885     if ( nDragHeight )
2886         aMouseSettings.SetStartDragHeight( nDragHeight );
2887     HKEY hRegKey;
2888     if ( RegOpenKey( HKEY_CURRENT_USER,
2889                      "Control Panel\\Desktop",
2890                      &hRegKey ) == ERROR_SUCCESS )
2891     {
2892         BYTE    aValueBuf[10];
2893         DWORD   nValueSize = sizeof( aValueBuf );
2894         DWORD   nType;
2895         if ( RegQueryValueEx( hRegKey, "MenuShowDelay", 0,
2896                               &nType, aValueBuf, &nValueSize ) == ERROR_SUCCESS )
2897         {
2898             if ( nType == REG_SZ )
2899                 aMouseSettings.SetMenuDelay( (sal_uLong)ImplA2I( aValueBuf ) );
2900         }
2901 
2902         RegCloseKey( hRegKey );
2903     }
2904 
2905     StyleSettings aStyleSettings = rSettings.GetStyleSettings();
2906     // TODO: once those options vanish: just set bCompBorder to TRUE
2907     // to have the system colors read
2908     aStyleSettings.SetScrollBarSize( GetSystemMetrics( SM_CXVSCROLL ) );
2909     aStyleSettings.SetSpinSize( GetSystemMetrics( SM_CXVSCROLL ) );
2910     aStyleSettings.SetCursorBlinkTime( GetCaretBlinkTime() );
2911     aStyleSettings.SetFloatTitleHeight( GetSystemMetrics( SM_CYSMCAPTION ) );
2912     aStyleSettings.SetTitleHeight( GetSystemMetrics( SM_CYCAPTION ) );
2913     aStyleSettings.SetActiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVEBORDER ) ) );
2914     aStyleSettings.SetDeactiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVEBORDER ) ) );
2915     if ( aSalShlData.mnVersion >= 410 )
2916     {
2917         aStyleSettings.SetActiveColor2( ImplWinColorToSal( GetSysColor( COLOR_GRADIENTACTIVECAPTION ) ) );
2918         aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_GRADIENTINACTIVECAPTION ) ) );
2919     }
2920     aStyleSettings.SetFaceColor( ImplWinColorToSal( GetSysColor( COLOR_3DFACE ) ) );
2921     aStyleSettings.SetInactiveTabColor( aStyleSettings.GetFaceColor() );
2922     aStyleSettings.SetLightColor( ImplWinColorToSal( GetSysColor( COLOR_3DHILIGHT ) ) );
2923     aStyleSettings.SetLightBorderColor( ImplWinColorToSal( GetSysColor( COLOR_3DLIGHT ) ) );
2924     aStyleSettings.SetShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DSHADOW ) ) );
2925     aStyleSettings.SetDarkShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DDKSHADOW ) ) );
2926     aStyleSettings.SetWorkspaceColor( ImplWinColorToSal( GetSysColor( COLOR_APPWORKSPACE ) ) );
2927     aStyleSettings.SetHelpColor( ImplWinColorToSal( GetSysColor( COLOR_INFOBK ) ) );
2928     aStyleSettings.SetHelpTextColor( ImplWinColorToSal( GetSysColor( COLOR_INFOTEXT ) ) );
2929     aStyleSettings.SetDialogColor( aStyleSettings.GetFaceColor() );
2930     aStyleSettings.SetDialogTextColor( aStyleSettings.GetButtonTextColor() );
2931     aStyleSettings.SetButtonTextColor( ImplWinColorToSal( GetSysColor( COLOR_BTNTEXT ) ) );
2932     aStyleSettings.SetButtonRolloverTextColor( aStyleSettings.GetButtonTextColor() );
2933     aStyleSettings.SetRadioCheckTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) );
2934     aStyleSettings.SetGroupTextColor( aStyleSettings.GetRadioCheckTextColor() );
2935     aStyleSettings.SetLabelTextColor( aStyleSettings.GetRadioCheckTextColor() );
2936     aStyleSettings.SetInfoTextColor( aStyleSettings.GetRadioCheckTextColor() );
2937     aStyleSettings.SetWindowColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOW ) ) );
2938     aStyleSettings.SetActiveTabColor( aStyleSettings.GetWindowColor() );
2939     aStyleSettings.SetWindowTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) );
2940     aStyleSettings.SetFieldColor( aStyleSettings.GetWindowColor() );
2941     aStyleSettings.SetFieldTextColor( aStyleSettings.GetWindowTextColor() );
2942     aStyleSettings.SetFieldRolloverTextColor( aStyleSettings.GetFieldTextColor() );
2943     aStyleSettings.SetHighlightColor( ImplWinColorToSal( GetSysColor( COLOR_HIGHLIGHT ) ) );
2944     aStyleSettings.SetHighlightTextColor( ImplWinColorToSal( GetSysColor( COLOR_HIGHLIGHTTEXT ) ) );
2945     aStyleSettings.SetMenuHighlightColor( aStyleSettings.GetHighlightColor() );
2946     aStyleSettings.SetMenuHighlightTextColor( aStyleSettings.GetHighlightTextColor() );
2947 
2948     ImplSVData* pSVData = ImplGetSVData();
2949     pSVData->maNWFData.mnMenuFormatExtraBorder = 0;
2950     pSVData->maNWFData.maMenuBarHighlightTextColor = Color( COL_TRANSPARENT );
2951     GetSalData()->mbThemeMenuSupport = FALSE;
2952     aStyleSettings.SetMenuColor( ImplWinColorToSal( GetSysColor( COLOR_MENU ) ) );
2953     aStyleSettings.SetMenuBarColor( aStyleSettings.GetMenuColor() );
2954     aStyleSettings.SetMenuBorderColor( aStyleSettings.GetLightBorderColor() ); // overriden below for flat menus
2955     aStyleSettings.SetUseFlatBorders( FALSE );
2956     aStyleSettings.SetUseFlatMenues( FALSE );
2957     aStyleSettings.SetMenuTextColor( ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ) );
2958     aStyleSettings.SetMenuBarTextColor( ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ) );
2959     aStyleSettings.SetActiveColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVECAPTION ) ) );
2960     aStyleSettings.SetActiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_CAPTIONTEXT ) ) );
2961     aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTION ) ) );
2962     aStyleSettings.SetDeactiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTIONTEXT ) ) );
2963     if ( aSalShlData.mbWXP )
2964     {
2965         // only xp supports a different menu bar color
2966         long bFlatMenues = 0;
2967         SystemParametersInfo( SPI_GETFLATMENU, 0, &bFlatMenues, 0);
2968         if( bFlatMenues )
2969         {
2970             aStyleSettings.SetUseFlatMenues( TRUE );
2971             aStyleSettings.SetMenuBarColor( ImplWinColorToSal( GetSysColor( COLOR_MENUBAR ) ) );
2972             aStyleSettings.SetMenuHighlightColor( ImplWinColorToSal( GetSysColor( COLOR_MENUHILIGHT ) ) );
2973             aStyleSettings.SetMenuBorderColor( ImplWinColorToSal( GetSysColor( COLOR_3DSHADOW ) ) );
2974 
2975             // flat borders for our controls etc. as well in this mode (ie, no 3d borders)
2976             // this is not active in the classic style appearance
2977             aStyleSettings.SetUseFlatBorders( TRUE );
2978         }
2979     }
2980     // check if vista or newer runs
2981     // in Aero theme (and similar ?) the menu text color does not change
2982     // for selected items; also on WinXP and earlier menus are not themed
2983     if( aSalShlData.maVersionInfo.dwMajorVersion >= 6 &&
2984        ImplDwmIsCompositionEnabled()
2985        )
2986     {
2987         // in aero menuitem highlight text is drawn in the same color as normal
2988         aStyleSettings.SetMenuHighlightTextColor( aStyleSettings.GetMenuTextColor() );
2989         pSVData->maNWFData.mnMenuFormatExtraBorder = 2;
2990         pSVData->maNWFData.maMenuBarHighlightTextColor = aStyleSettings.GetMenuTextColor();
2991         GetSalData()->mbThemeMenuSupport = TRUE;
2992     }
2993     // Bei hellgrau geben wir die Farbe vor, damit es besser aussieht
2994     if ( aStyleSettings.GetFaceColor() == COL_LIGHTGRAY )
2995         aStyleSettings.SetCheckedColor( Color( 0xCC, 0xCC, 0xCC ) );
2996     else
2997     {
2998         // Checked-Color berechnen
2999         Color   aColor1 = aStyleSettings.GetFaceColor();
3000         Color   aColor2 = aStyleSettings.GetLightColor();
3001         BYTE    nRed    = (BYTE)(((sal_uInt16)aColor1.GetRed()   + (sal_uInt16)aColor2.GetRed())/2);
3002         BYTE    nGreen  = (BYTE)(((sal_uInt16)aColor1.GetGreen() + (sal_uInt16)aColor2.GetGreen())/2);
3003         BYTE    nBlue   = (BYTE)(((sal_uInt16)aColor1.GetBlue()  + (sal_uInt16)aColor2.GetBlue())/2);
3004         aStyleSettings.SetCheckedColor( Color( nRed, nGreen, nBlue ) );
3005     }
3006 
3007     // caret width
3008     DWORD nCaretWidth = 2;
3009     if( SystemParametersInfo( SPI_GETCARETWIDTH, 0, &nCaretWidth, 0 ) )
3010         aStyleSettings.SetCursorSize( nCaretWidth );
3011 
3012 	// High contrast
3013 	HIGHCONTRAST hc;
3014 	hc.cbSize = sizeof( HIGHCONTRAST );
3015 	if( SystemParametersInfo( SPI_GETHIGHCONTRAST, hc.cbSize, &hc, 0) && (hc.dwFlags & HCF_HIGHCONTRASTON) )
3016 		aStyleSettings.SetHighContrastMode( 1 );
3017 	else
3018 		aStyleSettings.SetHighContrastMode( 0 );
3019 
3020 
3021     // Query Fonts
3022     Font    aMenuFont = aStyleSettings.GetMenuFont();
3023     Font    aTitleFont = aStyleSettings.GetTitleFont();
3024     Font    aFloatTitleFont = aStyleSettings.GetFloatTitleFont();
3025     Font    aHelpFont = aStyleSettings.GetHelpFont();
3026     Font    aAppFont = aStyleSettings.GetAppFont();
3027     Font    aIconFont = aStyleSettings.GetIconFont();
3028     HDC     hDC = GetDC( 0 );
3029     if( true/*aSalShlData.mbWNT*/ )
3030     {
3031         NONCLIENTMETRICSW aNonClientMetrics;
3032         aNonClientMetrics.cbSize = sizeof( aNonClientMetrics );
3033         if ( SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) )
3034         {
3035             ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfMenuFont, aMenuFont );
3036             ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfCaptionFont, aTitleFont );
3037             ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfSmCaptionFont, aFloatTitleFont );
3038             ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfStatusFont, aHelpFont );
3039             ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfMessageFont, aAppFont );
3040 
3041             LOGFONTW aLogFont;
3042             if ( SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &aLogFont, 0 ) )
3043                 ImplSalUpdateStyleFontW( hDC, aLogFont, aIconFont );
3044         }
3045     }
3046 
3047     // get screen font resolution to calculate toolbox item size
3048 	long nDPIY = GetDeviceCaps( hDC, LOGPIXELSY );
3049 
3050     ReleaseDC( 0, hDC );
3051 
3052     long nHeightPx = aMenuFont.GetHeight() * nDPIY / 72;
3053     aStyleSettings.SetToolbarIconSize( (((nHeightPx-1)*2) >= 28) ? STYLE_TOOLBAR_ICONSIZE_LARGE : STYLE_TOOLBAR_ICONSIZE_SMALL );
3054 
3055     aStyleSettings.SetMenuFont( aMenuFont );
3056     aStyleSettings.SetTitleFont( aTitleFont );
3057     aStyleSettings.SetFloatTitleFont( aFloatTitleFont );
3058     aStyleSettings.SetHelpFont( aHelpFont );
3059     aStyleSettings.SetIconFont( aIconFont );
3060     // We prefer Arial in the russian version, because MS Sans Serif
3061     // is to wide for the dialogs
3062     if ( rSettings.GetLanguage() == LANGUAGE_RUSSIAN )
3063     {
3064         XubString aFontName = aAppFont.GetName();
3065         XubString aFirstName = aFontName.GetToken( 0, ';' );
3066         if ( aFirstName.EqualsIgnoreCaseAscii( "MS Sans Serif" ) )
3067         {
3068             aFontName.InsertAscii( "Arial;", 0 );
3069             aAppFont.SetName( aFontName );
3070         }
3071     }
3072     aStyleSettings.SetAppFont( aAppFont );
3073     aStyleSettings.SetGroupFont( aAppFont );
3074     aStyleSettings.SetLabelFont( aAppFont );
3075     aStyleSettings.SetRadioCheckFont( aAppFont );
3076     aStyleSettings.SetPushButtonFont( aAppFont );
3077     aStyleSettings.SetFieldFont( aAppFont );
3078     if ( aAppFont.GetWeight() > WEIGHT_NORMAL )
3079         aAppFont.SetWeight( WEIGHT_NORMAL );
3080     aStyleSettings.SetInfoFont( aAppFont );
3081     aStyleSettings.SetToolFont( aAppFont );
3082 
3083     BOOL bDragFull;
3084     if ( SystemParametersInfo( SPI_GETDRAGFULLWINDOWS, 0, &bDragFull, 0 ) )
3085     {
3086         sal_uLong nDragFullOptions = aStyleSettings.GetDragFullOptions();
3087         if ( bDragFull )
3088             nDragFullOptions |=  DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT;
3089         else
3090             nDragFullOptions &= ~(DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT);
3091         aStyleSettings.SetDragFullOptions( nDragFullOptions );
3092     }
3093 
3094     aStyleSettings.SetIconHorzSpace( GetSystemMetrics( SM_CXICONSPACING ) );
3095     aStyleSettings.SetIconVertSpace( GetSystemMetrics( SM_CYICONSPACING ) );
3096     if ( RegOpenKey( HKEY_CURRENT_USER,
3097                      "Control Panel\\International\\Calendars\\TwoDigitYearMax",
3098                      &hRegKey ) == ERROR_SUCCESS )
3099     {
3100         BYTE    aValueBuf[10];
3101         DWORD   nValue;
3102         DWORD   nValueSize = sizeof( aValueBuf );
3103         DWORD   nType;
3104         if ( RegQueryValueEx( hRegKey, "1", 0,
3105                               &nType, aValueBuf, &nValueSize ) == ERROR_SUCCESS )
3106         {
3107             if ( nType == REG_SZ )
3108             {
3109                 nValue = (sal_uLong)ImplA2I( aValueBuf );
3110                 if ( (nValue > 1000) && (nValue < 10000) )
3111                 {
3112                     MiscSettings aMiscSettings = rSettings.GetMiscSettings();
3113 					utl::MiscCfg().SetYear2000( (sal_Int32)(nValue-99) );
3114                     rSettings.SetMiscSettings( aMiscSettings );
3115                 }
3116             }
3117         }
3118 
3119         RegCloseKey( hRegKey );
3120     }
3121 
3122     rSettings.SetMouseSettings( aMouseSettings );
3123     rSettings.SetStyleSettings( aStyleSettings );
3124 }
3125 
3126 // -----------------------------------------------------------------------
3127 
3128 SalBitmap* WinSalFrame::SnapShot()
3129 {
3130     WinSalBitmap* pSalBitmap = NULL;
3131 
3132     RECT aRect;
3133     GetWindowRect( mhWnd, &aRect );
3134 
3135     int     nDX = aRect.right-aRect.left;
3136     int     nDY = aRect.bottom-aRect.top;
3137     HDC     hDC = GetWindowDC( mhWnd );
3138     HBITMAP hBmpBitmap = CreateCompatibleBitmap( hDC, nDX, nDY );
3139     HDC     hBmpDC = ImplGetCachedDC( CACHED_HDC_1, hBmpBitmap );
3140     sal_Bool    bRet;
3141 
3142     bRet = BitBlt( hBmpDC, 0, 0, nDX, nDY, hDC, 0, 0, SRCCOPY ) ? TRUE : FALSE;
3143     ImplReleaseCachedDC( CACHED_HDC_1 );
3144 
3145     if ( bRet )
3146     {
3147         pSalBitmap = new WinSalBitmap;
3148 
3149         if ( !pSalBitmap->Create( hBmpBitmap, FALSE, FALSE ) )
3150         {
3151             delete pSalBitmap;
3152             pSalBitmap = NULL;
3153         }
3154     }
3155 
3156     return pSalBitmap;
3157 }
3158 
3159 // -----------------------------------------------------------------------
3160 
3161 const SystemEnvData* WinSalFrame::GetSystemData() const
3162 {
3163     return &maSysData;
3164 }
3165 
3166 // -----------------------------------------------------------------------
3167 
3168 void WinSalFrame::Beep( SoundType eSoundType )
3169 {
3170     static UINT aImplSoundTab[5] =
3171     {
3172         0,                              // SOUND_DEFAULT
3173         MB_ICONASTERISK,                // SOUND_INFO
3174         MB_ICONEXCLAMATION,             // SOUND_WARNING
3175         MB_ICONHAND,                    // SOUND_ERROR
3176         MB_ICONQUESTION                 // SOUND_QUERY
3177     };
3178 
3179     if( eSoundType != SOUND_DISABLE ) // don't beep on disable
3180         MessageBeep( aImplSoundTab[eSoundType] );
3181 }
3182 
3183 // -----------------------------------------------------------------------
3184 
3185 SalFrame::SalPointerState WinSalFrame::GetPointerState()
3186 {
3187     SalPointerState aState;
3188     aState.mnState = 0;
3189 
3190     if ( GetKeyState( VK_LBUTTON ) & 0x8000 )
3191         aState.mnState |= MOUSE_LEFT;
3192     if ( GetKeyState( VK_MBUTTON ) & 0x8000 )
3193         aState.mnState |= MOUSE_MIDDLE;
3194     if ( GetKeyState( VK_RBUTTON ) & 0x8000 )
3195         aState.mnState |= MOUSE_RIGHT;
3196     if ( GetKeyState( VK_SHIFT ) & 0x8000 )
3197         aState.mnState |= KEY_SHIFT;
3198     if ( GetKeyState( VK_CONTROL ) & 0x8000 )
3199         aState.mnState |= KEY_MOD1;
3200     if ( GetKeyState( VK_MENU ) & 0x8000 )
3201         aState.mnState |= KEY_MOD2;
3202 
3203     POINT pt;
3204     GetCursorPos( &pt );
3205 
3206     aState.maPos = Point( pt.x - maGeometry.nX, pt.y - maGeometry.nY );
3207     return aState;
3208 }
3209 
3210 // -----------------------------------------------------------------------
3211 
3212 void WinSalFrame::SetBackgroundBitmap( SalBitmap* )
3213 {
3214 }
3215 
3216 // -----------------------------------------------------------------------
3217 
3218 void WinSalFrame::ResetClipRegion()
3219 {
3220 	SetWindowRgn( mhWnd, 0, TRUE );
3221 }
3222 
3223 // -----------------------------------------------------------------------
3224 
3225 void WinSalFrame::BeginSetClipRegion( sal_uLong nRects )
3226 {
3227     if( mpClipRgnData )
3228         delete [] (BYTE*)mpClipRgnData;
3229 	sal_uLong nRectBufSize = sizeof(RECT)*nRects;
3230     mpClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+nRectBufSize];
3231 	mpClipRgnData->rdh.dwSize	  = sizeof( RGNDATAHEADER );
3232 	mpClipRgnData->rdh.iType	  = RDH_RECTANGLES;
3233 	mpClipRgnData->rdh.nCount	  = nRects;
3234 	mpClipRgnData->rdh.nRgnSize  = nRectBufSize;
3235 	SetRectEmpty( &(mpClipRgnData->rdh.rcBound) );
3236 	mpNextClipRect 		  = (RECT*)(&(mpClipRgnData->Buffer));
3237 	mbFirstClipRect		  = TRUE;
3238 }
3239 
3240 // -----------------------------------------------------------------------
3241 
3242 void WinSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
3243 {
3244     if( ! mpClipRgnData )
3245         return;
3246 
3247 	RECT*		pRect = mpNextClipRect;
3248 	RECT*		pBoundRect = &(mpClipRgnData->rdh.rcBound);
3249 	long		nRight = nX + nWidth;
3250 	long		nBottom = nY + nHeight;
3251 
3252 	if ( mbFirstClipRect )
3253 	{
3254 		pBoundRect->left	= nX;
3255 		pBoundRect->top 	= nY;
3256 		pBoundRect->right	= nRight;
3257 		pBoundRect->bottom	= nBottom;
3258 		mbFirstClipRect = FALSE;
3259 	}
3260 	else
3261 	{
3262 		if ( nX < pBoundRect->left )
3263 			pBoundRect->left = (int)nX;
3264 
3265 		if ( nY < pBoundRect->top )
3266 			pBoundRect->top = (int)nY;
3267 
3268 		if ( nRight > pBoundRect->right )
3269 			pBoundRect->right = (int)nRight;
3270 
3271 		if ( nBottom > pBoundRect->bottom )
3272 			pBoundRect->bottom = (int)nBottom;
3273 	}
3274 
3275 	pRect->left 	= (int)nX;
3276 	pRect->top		= (int)nY;
3277 	pRect->right	= (int)nRight;
3278 	pRect->bottom	= (int)nBottom;
3279     if( (mpNextClipRect  - (RECT*)(&mpClipRgnData->Buffer)) < (int)mpClipRgnData->rdh.nCount )
3280         mpNextClipRect++;
3281 }
3282 
3283 // -----------------------------------------------------------------------
3284 
3285 void WinSalFrame::EndSetClipRegion()
3286 {
3287     if( ! mpClipRgnData )
3288         return;
3289 
3290 	HRGN hRegion;
3291 
3292 	// create region from accumulated rectangles
3293 	if ( mpClipRgnData->rdh.nCount == 1 )
3294 	{
3295 		RECT* pRect = &(mpClipRgnData->rdh.rcBound);
3296 		hRegion = CreateRectRgn( pRect->left, pRect->top,
3297 								 pRect->right, pRect->bottom );
3298 	}
3299 	else
3300 	{
3301 		sal_uLong nSize = mpClipRgnData->rdh.nRgnSize+sizeof(RGNDATAHEADER);
3302 		hRegion = ExtCreateRegion( NULL, nSize, mpClipRgnData );
3303 	}
3304     delete [] (BYTE*)mpClipRgnData;
3305     mpClipRgnData = NULL;
3306 
3307 	DBG_ASSERT( hRegion, "WinSalFrame::EndSetClipRegion() - Can't create ClipRegion" );
3308     if( hRegion )
3309     {
3310         RECT aWindowRect;
3311         GetWindowRect( mhWnd, &aWindowRect );
3312         POINT aPt;
3313         aPt.x=0;
3314         aPt.y=0;
3315         ClientToScreen( mhWnd, &aPt );
3316         OffsetRgn( hRegion, aPt.x - aWindowRect.left, aPt.y - aWindowRect.top );
3317 
3318         if( SetWindowRgn( mhWnd, hRegion, TRUE ) == 0 )
3319             DeleteObject( hRegion );
3320     }
3321 }
3322 
3323 // -----------------------------------------------------------------------
3324 
3325 static long ImplHandleMouseMsg( HWND hWnd, UINT nMsg,
3326                                 WPARAM wParam, LPARAM lParam )
3327 {
3328     WinSalFrame* pFrame = GetWindowPtr( hWnd );
3329     if ( !pFrame )
3330         return 0;
3331 
3332     if( nMsg == WM_LBUTTONDOWN || nMsg == WM_MBUTTONDOWN || nMsg == WM_RBUTTONDOWN )
3333     {
3334         // #103168# post again if async focus has not arrived yet
3335         // hopefully we will not receive the corresponding button up before this
3336         // button down arrives again
3337         Window *pWin = pFrame->GetWindow();
3338         if( pWin && pWin->ImplGetWindowImpl()->mpFrameData->mnFocusId )
3339         {
3340             ImplPostMessage( hWnd, nMsg, wParam, lParam );
3341             return 1;
3342         }
3343     }
3344     SalMouseEvent   aMouseEvt;
3345     long            nRet;
3346     sal_uInt16          nEvent = 0;
3347     sal_Bool            bCall = TRUE;
3348 
3349     aMouseEvt.mnX       = (short)LOWORD( lParam );
3350     aMouseEvt.mnY       = (short)HIWORD( lParam );
3351     aMouseEvt.mnCode    = 0;
3352     aMouseEvt.mnTime    = GetMessageTime();
3353 
3354     // Wegen (Logitech-)MouseTreiber ueber GetKeyState() gehen, die auf
3355     // mittlerer Maustaste Doppelklick simulieren und den KeyStatus nicht
3356     // beruecksichtigen
3357 
3358     if ( GetKeyState( VK_LBUTTON ) & 0x8000 )
3359         aMouseEvt.mnCode |= MOUSE_LEFT;
3360     if ( GetKeyState( VK_MBUTTON ) & 0x8000 )
3361         aMouseEvt.mnCode |= MOUSE_MIDDLE;
3362     if ( GetKeyState( VK_RBUTTON ) & 0x8000 )
3363         aMouseEvt.mnCode |= MOUSE_RIGHT;
3364     if ( GetKeyState( VK_SHIFT ) & 0x8000 )
3365         aMouseEvt.mnCode |= KEY_SHIFT;
3366     if ( GetKeyState( VK_CONTROL ) & 0x8000 )
3367         aMouseEvt.mnCode |= KEY_MOD1;
3368     if ( GetKeyState( VK_MENU ) & 0x8000 )
3369         aMouseEvt.mnCode |= KEY_MOD2;
3370 
3371     switch ( nMsg )
3372     {
3373         case WM_MOUSEMOVE:
3374             {
3375             // Da bei Druecken von Modifier-Tasten die MouseEvents
3376             // nicht zusammengefast werden (da diese durch KeyEvents
3377             // unterbrochen werden), machen wir dieses hier selber
3378             if ( aMouseEvt.mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2) )
3379             {
3380                 MSG aTempMsg;
3381                 if ( ImplPeekMessage( &aTempMsg, hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE | PM_NOYIELD ) )
3382                 {
3383                     if ( (aTempMsg.message == WM_MOUSEMOVE) &&
3384                          (aTempMsg.wParam == wParam) )
3385                         return 1;
3386                 }
3387             }
3388 
3389             SalData* pSalData = GetSalData();
3390             // Test for MouseLeave
3391             if ( pSalData->mhWantLeaveMsg && (pSalData->mhWantLeaveMsg != hWnd) )
3392 				ImplSendMessage( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, GetMessagePos() );
3393 
3394             pSalData->mhWantLeaveMsg = hWnd;
3395             // Start MouseLeave-Timer
3396             if ( !pSalData->mpMouseLeaveTimer )
3397             {
3398                 pSalData->mpMouseLeaveTimer = new AutoTimer;
3399                 pSalData->mpMouseLeaveTimer->SetTimeout( SAL_MOUSELEAVE_TIMEOUT );
3400                 pSalData->mpMouseLeaveTimer->Start();
3401                 // We dont need to set a timeout handler, because we test
3402                 // for mouseleave in the timeout callback
3403             }
3404             aMouseEvt.mnButton = 0;
3405             nEvent = SALEVENT_MOUSEMOVE;
3406             }
3407             break;
3408 
3409         case WM_NCMOUSEMOVE:
3410         case SAL_MSG_MOUSELEAVE:
3411             {
3412             SalData* pSalData = GetSalData();
3413             if ( pSalData->mhWantLeaveMsg == hWnd )
3414             {
3415                 pSalData->mhWantLeaveMsg = 0;
3416                 if ( pSalData->mpMouseLeaveTimer )
3417                 {
3418                     delete pSalData->mpMouseLeaveTimer;
3419                     pSalData->mpMouseLeaveTimer = NULL;
3420                 }
3421                 // Mouse-Coordinaates are relativ to the screen
3422                 POINT aPt;
3423                 aPt.x = (short)LOWORD( lParam );
3424                 aPt.y = (short)HIWORD( lParam );
3425                 ScreenToClient( hWnd, &aPt );
3426                 aMouseEvt.mnX = aPt.x;
3427                 aMouseEvt.mnY = aPt.y;
3428                 aMouseEvt.mnButton = 0;
3429                 nEvent = SALEVENT_MOUSELEAVE;
3430             }
3431             else
3432                 bCall = FALSE;
3433             }
3434             break;
3435 
3436         case WM_LBUTTONDOWN:
3437             aMouseEvt.mnButton = MOUSE_LEFT;
3438             nEvent = SALEVENT_MOUSEBUTTONDOWN;
3439             break;
3440 
3441         case WM_MBUTTONDOWN:
3442             aMouseEvt.mnButton = MOUSE_MIDDLE;
3443             nEvent = SALEVENT_MOUSEBUTTONDOWN;
3444             break;
3445 
3446         case WM_RBUTTONDOWN:
3447             aMouseEvt.mnButton = MOUSE_RIGHT;
3448             nEvent = SALEVENT_MOUSEBUTTONDOWN;
3449             break;
3450 
3451         case WM_LBUTTONUP:
3452             aMouseEvt.mnButton = MOUSE_LEFT;
3453             nEvent = SALEVENT_MOUSEBUTTONUP;
3454             break;
3455 
3456         case WM_MBUTTONUP:
3457             aMouseEvt.mnButton = MOUSE_MIDDLE;
3458             nEvent = SALEVENT_MOUSEBUTTONUP;
3459             break;
3460 
3461         case WM_RBUTTONUP:
3462             aMouseEvt.mnButton = MOUSE_RIGHT;
3463             nEvent = SALEVENT_MOUSEBUTTONUP;
3464             break;
3465     }
3466 
3467 	// check if this window was destroyed - this might happen if we are the help window
3468 	// and sent a mouse leave message to the application which killed the help window, ie ourself
3469 	if( !IsWindow( hWnd ) )
3470 		return 0;
3471 
3472     if ( bCall )
3473     {
3474         if ( nEvent == SALEVENT_MOUSEBUTTONDOWN )
3475             UpdateWindow( hWnd );
3476 
3477         // --- RTL --- (mirror mouse pos)
3478         if( Application::GetSettings().GetLayoutRTL() )
3479             aMouseEvt.mnX = pFrame->maGeometry.nWidth-1-aMouseEvt.mnX;
3480 
3481         nRet = pFrame->CallCallback( nEvent, &aMouseEvt );
3482         if ( nMsg == WM_MOUSEMOVE )
3483             SetCursor( pFrame->mhCursor );
3484     }
3485     else
3486         nRet = 0;
3487 
3488     return nRet;
3489 }
3490 
3491 // -----------------------------------------------------------------------
3492 
3493 static long ImplHandleMouseActivateMsg( HWND hWnd )
3494 {
3495     WinSalFrame* pFrame = GetWindowPtr( hWnd );
3496     if ( !pFrame )
3497         return 0;
3498 
3499     if ( pFrame->mbFloatWin )
3500         return TRUE;
3501 
3502     SalMouseActivateEvent   aMouseActivateEvt;
3503     POINT                   aPt;
3504     GetCursorPos( &aPt );
3505     ScreenToClient( hWnd, &aPt );
3506     aMouseActivateEvt.mnX = aPt.x;
3507     aMouseActivateEvt.mnY = aPt.y;
3508     return pFrame->CallCallback( SALEVENT_MOUSEACTIVATE, &aMouseActivateEvt );
3509 }
3510 
3511 // -----------------------------------------------------------------------
3512 
3513 static long ImplHandleWheelMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
3514 {
3515     DBG_ASSERT( nMsg == WM_MOUSEWHEEL ||
3516                 nMsg == WM_MOUSEHWHEEL,
3517                 "ImplHandleWheelMsg() called with no wheel mouse event" );
3518 
3519     ImplSalYieldMutexAcquireWithWait();
3520 
3521     long        nRet = 0;
3522     WinSalFrame*   pFrame = GetWindowPtr( hWnd );
3523     if ( pFrame )
3524     {
3525         WORD    nWinModCode = LOWORD( wParam );
3526         POINT   aWinPt;
3527         aWinPt.x    = (short)LOWORD( lParam );
3528         aWinPt.y    = (short)HIWORD( lParam );
3529         ScreenToClient( hWnd, &aWinPt );
3530 
3531         SalWheelMouseEvent aWheelEvt;
3532         aWheelEvt.mnTime        = GetMessageTime();
3533         aWheelEvt.mnX           = aWinPt.x;
3534         aWheelEvt.mnY           = aWinPt.y;
3535         aWheelEvt.mnCode        = 0;
3536         aWheelEvt.mnDelta       = (short)HIWORD( wParam );
3537         aWheelEvt.mnNotchDelta  = aWheelEvt.mnDelta/WHEEL_DELTA;
3538         if( aWheelEvt.mnNotchDelta == 0 )
3539         {
3540             if( aWheelEvt.mnDelta > 0 )
3541                 aWheelEvt.mnNotchDelta = 1;
3542             else if( aWheelEvt.mnDelta < 0 )
3543                 aWheelEvt.mnNotchDelta = -1;
3544         }
3545 
3546         if( nMsg == WM_MOUSEWHEEL )
3547         {
3548             if ( aSalShlData.mnWheelScrollLines == WHEEL_PAGESCROLL )
3549                 aWheelEvt.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
3550             else
3551                 aWheelEvt.mnScrollLines = aSalShlData.mnWheelScrollLines;
3552             aWheelEvt.mbHorz        = FALSE;
3553         }
3554         else
3555         {
3556             aWheelEvt.mnScrollLines = aSalShlData.mnWheelScrollChars;
3557             aWheelEvt.mbHorz        = TRUE;
3558         }
3559 
3560         if ( nWinModCode & MK_SHIFT )
3561             aWheelEvt.mnCode |= KEY_SHIFT;
3562         if ( nWinModCode & MK_CONTROL )
3563             aWheelEvt.mnCode |= KEY_MOD1;
3564         if ( GetKeyState( VK_MENU ) & 0x8000 )
3565             aWheelEvt.mnCode |= KEY_MOD2;
3566 
3567         // --- RTL --- (mirror mouse pos)
3568         if( Application::GetSettings().GetLayoutRTL() )
3569             aWheelEvt.mnX = pFrame->maGeometry.nWidth-1-aWheelEvt.mnX;
3570 
3571         nRet = pFrame->CallCallback( SALEVENT_WHEELMOUSE, &aWheelEvt );
3572     }
3573 
3574     ImplSalYieldMutexRelease();
3575 
3576     return nRet;
3577 }
3578 
3579 // -----------------------------------------------------------------------
3580 
3581 static sal_uInt16 ImplSalGetKeyCode( WPARAM wParam )
3582 {
3583     sal_uInt16 nKeyCode;
3584 
3585     // convert KeyCode
3586     if ( wParam < KEY_TAB_SIZE )
3587         nKeyCode = aImplTranslateKeyTab[wParam];
3588 	else
3589 	{
3590 		SalData* pSalData = GetSalData();
3591 		std::map< UINT, sal_uInt16 >::const_iterator it = pSalData->maVKMap.find( (UINT)wParam );
3592 		if( it != pSalData->maVKMap.end() )
3593 			nKeyCode = it->second;
3594 		else
3595 			nKeyCode = 0;
3596 	}
3597 
3598     return nKeyCode;
3599 }
3600 
3601 // -----------------------------------------------------------------------
3602 
3603 static UINT ImplStrToNum( const sal_Char* pStr )
3604 {
3605     sal_uInt16 n = 0;
3606 
3607     // Solange es sich um eine Ziffer handelt, String umwandeln
3608     while( (*pStr >= 48) && (*pStr <= 57) )
3609     {
3610         n *= 10;
3611         n += ((*pStr) - 48);
3612         pStr++;
3613     }
3614 
3615     return n;
3616 }
3617 
3618 // -----------------------------------------------------------------------
3619 
3620 static void ImplUpdateInputLang( WinSalFrame* pFrame )
3621 {
3622     sal_Bool bLanguageChange = FALSE;
3623     UINT nLang = LOWORD( GetKeyboardLayout( 0 ) );
3624     if ( nLang && nLang != pFrame->mnInputLang )
3625     {
3626         // keep input lang up-to-date
3627         pFrame->mnInputLang = nLang;
3628         bLanguageChange = TRUE;
3629     }
3630 
3631     // If we are on Windows NT we use Unicode FrameProcs and so we
3632     // get Unicode charcodes directly from Windows
3633     // no need to set up a code page
3634     return;
3635 }
3636 
3637 
3638 static sal_Unicode ImplGetCharCode( WinSalFrame* pFrame, WPARAM nCharCode )
3639 {
3640     ImplUpdateInputLang( pFrame );
3641 
3642     // If we are on Windows NT we use Unicode FrameProcs and so we
3643     // get Unicode charcodes directly from Windows
3644     return (sal_Unicode)nCharCode;
3645 }
3646 
3647 // -----------------------------------------------------------------------
3648 
3649 LanguageType WinSalFrame::GetInputLanguage()
3650 {
3651     if( !mnInputLang )
3652         ImplUpdateInputLang( this );
3653 
3654     if( !mnInputLang )
3655         return LANGUAGE_DONTKNOW;
3656     else
3657         return (LanguageType) mnInputLang;
3658 }
3659 
3660 // -----------------------------------------------------------------------
3661 
3662 sal_Bool WinSalFrame::MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, KeyCode& rKeyCode )
3663 {
3664     sal_Bool bRet = FALSE;
3665     HKL hkl = 0;
3666 
3667     // just use the passed language identifier, do not try to load additional keyboard support
3668     hkl = (HKL) aLangType;
3669 
3670     if( hkl )
3671     {
3672         SHORT scan = VkKeyScanExW( aUnicode, hkl );
3673         if( LOWORD(scan) == 0xFFFF )
3674             // keyboard not loaded or key cannot be mapped
3675             bRet = FALSE;
3676         else
3677         {
3678             BYTE vkeycode   = LOBYTE(scan);
3679             BYTE shiftstate = HIBYTE(scan);
3680 
3681             // Last argument is set to FALSE, because there's no decission made
3682             // yet which key should be assigned to MOD3 modifier on Windows.
3683             // Windows key - user's can be confused, because it should display
3684             //               Windows menu (applies to both left/right key)
3685             // Menu key    - this key is used to display context menu
3686             // AltGr key   - probably it has no sense
3687             rKeyCode = KeyCode( ImplSalGetKeyCode( vkeycode ),
3688                 (shiftstate & 0x01) ? TRUE : FALSE,     // shift
3689                 (shiftstate & 0x02) ? TRUE : FALSE,     // ctrl
3690                 (shiftstate & 0x04) ? TRUE : FALSE,     // alt
3691                 FALSE );
3692             bRet = TRUE;
3693         }
3694     }
3695 
3696     return bRet;
3697 }
3698 
3699 // -----------------------------------------------------------------------
3700 
3701 static long ImplHandleKeyMsg( HWND hWnd, UINT nMsg,
3702                               WPARAM wParam, LPARAM lParam, LRESULT& rResult )
3703 {
3704     static sal_Bool     bIgnoreCharMsg  = FALSE;
3705     static WPARAM   nDeadChar       = 0;
3706     static WPARAM   nLastVKChar     = 0;
3707     static sal_uInt16   nLastChar       = 0;
3708     static sal_uInt16   nLastModKeyCode = 0;
3709     static bool     bWaitForModKeyRelease = false;
3710     sal_uInt16          nRepeat         = LOWORD( lParam )-1;
3711     sal_uInt16          nModCode        = 0;
3712 
3713     // Key wurde evtl. durch SysChild an uns weitergeleitet und
3714     // darf somit dann nicht doppelt verarbeitet werden
3715     GetSalData()->mnSalObjWantKeyEvt = 0;
3716 
3717     if ( nMsg == WM_DEADCHAR )
3718     {
3719         nDeadChar = wParam;
3720         return 0;
3721     }
3722 
3723     WinSalFrame* pFrame = GetWindowPtr( hWnd );
3724     if ( !pFrame )
3725         return 0;
3726 
3727     // Wir restaurieren den Background-Modus bei jeder Texteingabe,
3728     // da einige Tools wie RichWin uns diesen hin- und wieder umsetzen
3729     if ( pFrame->mpGraphics &&
3730          pFrame->mpGraphics->mhDC )
3731         SetBkMode( pFrame->mpGraphics->mhDC, TRANSPARENT );
3732 
3733     // determine modifiers
3734     if ( GetKeyState( VK_SHIFT ) & 0x8000 )
3735         nModCode |= KEY_SHIFT;
3736     if ( GetKeyState( VK_CONTROL ) & 0x8000 )
3737         nModCode |= KEY_MOD1;
3738     if ( GetKeyState( VK_MENU ) & 0x8000 )
3739         nModCode |= KEY_MOD2;
3740 
3741     if ( (nMsg == WM_CHAR) || (nMsg == WM_SYSCHAR) )
3742     {
3743         nDeadChar = 0;
3744 
3745         if ( bIgnoreCharMsg )
3746         {
3747             bIgnoreCharMsg = FALSE;
3748             // #101635# if zero is returned here for WM_SYSCHAR (ALT+<key>) Windows will beep
3749             // becaus this 'hotkey' was not processed -> better return 1
3750             // except for Alt-SPACE which should always open the sysmenu (#104616#)
3751 
3752             // also return zero if a system menubar is available that might process this hotkey
3753             // this also applies to the OLE inplace embedding where we are a child window
3754             if( (GetWindowStyle( hWnd ) & WS_CHILD) || GetMenu( hWnd ) || (wParam == 0x20) )
3755                 return 0;
3756             else
3757                 return 1;
3758         }
3759 
3760         // Backspace ignorieren wir als eigenstaendige Taste,
3761         // damit wir keine Probleme in Kombination mit einem
3762         // DeadKey bekommen
3763         if ( wParam == 0x08 )    // BACKSPACE
3764             return 0;
3765 
3766         // Hier kommen nur "freifliegende" WM_CHAR Message an, die durch
3767         // eintippen einer ALT-NUMPAD Kombination erzeugt wurden
3768         SalKeyEvent aKeyEvt;
3769 
3770         if ( (wParam >= '0') && (wParam <= '9') )
3771             aKeyEvt.mnCode = sal::static_int_cast<sal_uInt16>(KEYGROUP_NUM + wParam - '0');
3772         else if ( (wParam >= 'A') && (wParam <= 'Z') )
3773             aKeyEvt.mnCode = sal::static_int_cast<sal_uInt16>(KEYGROUP_ALPHA + wParam - 'A');
3774         else if ( (wParam >= 'a') && (wParam <= 'z') )
3775             aKeyEvt.mnCode = sal::static_int_cast<sal_uInt16>(KEYGROUP_ALPHA + wParam - 'a');
3776         else if ( wParam == 0x0D )    // RETURN
3777             aKeyEvt.mnCode = KEY_RETURN;
3778         else if ( wParam == 0x1B )    // ESCAPE
3779             aKeyEvt.mnCode = KEY_ESCAPE;
3780         else if ( wParam == 0x09 )    // TAB
3781             aKeyEvt.mnCode = KEY_TAB;
3782         else if ( wParam == 0x20 )    // SPACE
3783             aKeyEvt.mnCode = KEY_SPACE;
3784         else
3785             aKeyEvt.mnCode = 0;
3786 
3787         aKeyEvt.mnTime      = GetMessageTime();
3788         aKeyEvt.mnCode     |= nModCode;
3789         aKeyEvt.mnCharCode  = ImplGetCharCode( pFrame, wParam );
3790         aKeyEvt.mnRepeat    = nRepeat;
3791         nLastChar = 0;
3792         nLastVKChar = 0;
3793         long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
3794         pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3795         return nRet;
3796     }
3797  	// #i11583#, MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0; addition begins
3798 	else if( nMsg == WM_UNICHAR )
3799  	{
3800  		// If Windows is asking if we accept WM_UNICHAR, return TRUE
3801  		if(wParam == UNICODE_NOCHAR)
3802         {
3803             rResult = TRUE; // ssa: this will actually return TRUE to windows
3804             return 1;       // ...but this will only avoid calling the defwindowproc
3805         }
3806 
3807  		SalKeyEvent aKeyEvt;
3808  		aKeyEvt.mnCode		= nModCode;	// Or should it be 0? - as this is always a character returned
3809  		aKeyEvt.mnTime		= GetMessageTime();
3810  		aKeyEvt.mnRepeat	= 0;
3811 
3812 		if( wParam >= Uni_SupplementaryPlanesStart )
3813 		{
3814 			// character is supplementary char in UTF-32 format - must be converted to UTF-16 supplementary pair
3815 			// sal_Unicode ch = (sal_Unicode) Uni_UTF32ToSurrogate1(wParam);
3816 	 		nLastChar = 0;
3817  			nLastVKChar = 0;
3818 	 		pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
3819  			pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3820 			wParam = (sal_Unicode) Uni_UTF32ToSurrogate2( wParam );
3821  		}
3822 
3823  		aKeyEvt.mnCharCode	= (sal_Unicode) wParam;
3824 
3825  		nLastChar = 0;
3826  		nLastVKChar = 0;
3827  		long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
3828  		pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3829 
3830  		return nRet;
3831  	}
3832  	// MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0; addition ends
3833     else
3834     {
3835         // Bei Shift, Control und Menu schicken wir einen KeyModChange-Event
3836         if ( (wParam == VK_SHIFT) || (wParam == VK_CONTROL) || (wParam == VK_MENU) )
3837         {
3838             SalKeyModEvent aModEvt;
3839             aModEvt.mnTime = GetMessageTime();
3840             aModEvt.mnCode = nModCode;
3841             aModEvt.mnModKeyCode = 0;   // no command events will be sent if this member is 0
3842 
3843             sal_uInt16 tmpCode = 0;
3844             if( GetKeyState( VK_LSHIFT )  & 0x8000 )
3845                 tmpCode |= MODKEY_LSHIFT;
3846             if( GetKeyState( VK_RSHIFT )  & 0x8000 )
3847                 tmpCode |= MODKEY_RSHIFT;
3848             if( GetKeyState( VK_LCONTROL ) & 0x8000 )
3849                 tmpCode |= MODKEY_LMOD1;
3850             if( GetKeyState( VK_RCONTROL ) & 0x8000 )
3851                 tmpCode |= MODKEY_RMOD1;
3852             if( GetKeyState( VK_LMENU )  & 0x8000 )
3853                 tmpCode |= MODKEY_LMOD2;
3854             if( GetKeyState( VK_RMENU )  & 0x8000 )
3855                 tmpCode |= MODKEY_RMOD2;
3856 
3857             if( tmpCode < nLastModKeyCode )
3858             {
3859                 aModEvt.mnModKeyCode = nLastModKeyCode;
3860                 nLastModKeyCode = 0;
3861                 bWaitForModKeyRelease = true;
3862             }
3863             else
3864             {
3865                 if( !bWaitForModKeyRelease )
3866                     nLastModKeyCode = tmpCode;
3867             }
3868 
3869             if( !tmpCode )
3870                 bWaitForModKeyRelease = false;
3871 
3872             return pFrame->CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt );
3873         }
3874         else
3875         {
3876             SalKeyEvent     aKeyEvt;
3877             sal_uInt16          nEvent;
3878             MSG             aCharMsg;
3879             BOOL        bCharPeek = FALSE;
3880             UINT            nCharMsg = WM_CHAR;
3881             sal_Bool            bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP);
3882 
3883             nLastModKeyCode = 0; // make sure no modkey messages are sent if they belong to a hotkey (see above)
3884             aKeyEvt.mnCharCode = 0;
3885             aKeyEvt.mnCode = 0;
3886 
3887             aKeyEvt.mnCode = ImplSalGetKeyCode( wParam );
3888             if ( !bKeyUp )
3889             {
3890                 // check for charcode
3891                 // Mit Hilfe von PeekMessage holen wir uns jetzt die
3892                 // zugehoerige WM_CHAR Message, wenn vorhanden.
3893                 // Diese WM_CHAR Message steht immer am Anfang der
3894                 // Messagequeue. Ausserdem ist sichergestellt, dass immer
3895                 // nur eine WM_CHAR Message in der Queue steht.
3896                 bCharPeek = ImplPeekMessage( &aCharMsg, hWnd,
3897                                              WM_CHAR, WM_CHAR, PM_NOREMOVE | PM_NOYIELD );
3898                 if ( bCharPeek && (nDeadChar == aCharMsg.wParam) )
3899                 {
3900                     bCharPeek = FALSE;
3901                     nDeadChar = 0;
3902 
3903                     if ( wParam == VK_BACK )
3904                     {
3905                         ImplPeekMessage( &aCharMsg, hWnd,
3906                                          nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD );
3907                         return 0;
3908                     }
3909                 }
3910                 else
3911                 {
3912                     if ( !bCharPeek )
3913                     {
3914                         bCharPeek = ImplPeekMessage( &aCharMsg, hWnd,
3915                                                     WM_SYSCHAR, WM_SYSCHAR, PM_NOREMOVE | PM_NOYIELD );
3916                         nCharMsg = WM_SYSCHAR;
3917                     }
3918                 }
3919                 if ( bCharPeek )
3920                     aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, aCharMsg.wParam );
3921                 else
3922                     aKeyEvt.mnCharCode = 0;
3923 
3924                 nLastChar = aKeyEvt.mnCharCode;
3925                 nLastVKChar = wParam;
3926             }
3927             else
3928             {
3929                 if ( wParam == nLastVKChar )
3930                 {
3931                     aKeyEvt.mnCharCode = nLastChar;
3932                     nLastChar = 0;
3933                     nLastVKChar = 0;
3934                 }
3935             }
3936 
3937             if ( aKeyEvt.mnCode || aKeyEvt.mnCharCode )
3938             {
3939                 if ( bKeyUp )
3940                     nEvent = SALEVENT_KEYUP;
3941                 else
3942                     nEvent = SALEVENT_KEYINPUT;
3943 
3944                 aKeyEvt.mnTime      = GetMessageTime();
3945                 aKeyEvt.mnCode     |= nModCode;
3946                 aKeyEvt.mnRepeat    = nRepeat;
3947 
3948                 if( (nModCode & (KEY_MOD1|KEY_MOD2)) == (KEY_MOD1|KEY_MOD2) &&
3949                     aKeyEvt.mnCharCode )
3950                 {
3951                      // this is actually AltGr and should not be handled as Alt
3952                      aKeyEvt.mnCode &= ~(KEY_MOD1|KEY_MOD2);
3953                 }
3954 
3955                 bIgnoreCharMsg = bCharPeek ? TRUE : FALSE;
3956                 long nRet = pFrame->CallCallback( nEvent, &aKeyEvt );
3957                 // independent part only reacts on keyup but Windows does not send
3958                 // keyup for VK_HANJA
3959                 if( aKeyEvt.mnCode == KEY_HANGUL_HANJA )
3960                     nRet = pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3961 
3962                 bIgnoreCharMsg = FALSE;
3963 
3964                 // char-message, than remove or ignore
3965                 if ( bCharPeek )
3966                 {
3967                     nDeadChar = 0;
3968                     if ( nRet )
3969                     {
3970                         ImplPeekMessage( &aCharMsg, hWnd,
3971                                          nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD );
3972                     }
3973                     else
3974                         bIgnoreCharMsg = TRUE;
3975                 }
3976 
3977                 return nRet;
3978             }
3979             else
3980                 return 0;
3981         }
3982     }
3983 }
3984 
3985 // -----------------------------------------------------------------------
3986 
3987 long ImplHandleSalObjKeyMsg( HWND hWnd, UINT nMsg,
3988                              WPARAM wParam, LPARAM lParam )
3989 {
3990     if ( (nMsg == WM_KEYDOWN) || (nMsg == WM_KEYUP) )
3991     {
3992         WinSalFrame* pFrame = GetWindowPtr( hWnd );
3993         if ( !pFrame )
3994             return 0;
3995 
3996         sal_uInt16  nRepeat     = LOWORD( lParam )-1;
3997         sal_uInt16  nModCode    = 0;
3998 
3999         // determine modifiers
4000         if ( GetKeyState( VK_SHIFT ) & 0x8000 )
4001             nModCode |= KEY_SHIFT;
4002         if ( GetKeyState( VK_CONTROL ) & 0x8000 )
4003             nModCode |= KEY_MOD1;
4004         if ( GetKeyState( VK_MENU ) & 0x8000 )
4005             nModCode |= KEY_MOD2;
4006 
4007         if ( (wParam != VK_SHIFT) && (wParam != VK_CONTROL) && (wParam != VK_MENU) )
4008         {
4009             SalKeyEvent     aKeyEvt;
4010             sal_uInt16          nEvent;
4011             sal_Bool            bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP);
4012 
4013             // convert KeyCode
4014             aKeyEvt.mnCode      = ImplSalGetKeyCode( wParam );
4015             aKeyEvt.mnCharCode  = 0;
4016 
4017             if ( aKeyEvt.mnCode )
4018             {
4019                 if ( bKeyUp )
4020                     nEvent = SALEVENT_KEYUP;
4021                 else
4022                     nEvent = SALEVENT_KEYINPUT;
4023 
4024                 aKeyEvt.mnTime      = GetMessageTime();
4025                 aKeyEvt.mnCode     |= nModCode;
4026                 aKeyEvt.mnRepeat    = nRepeat;
4027                 long nRet = pFrame->CallCallback( nEvent, &aKeyEvt );
4028                 return nRet;
4029             }
4030             else
4031                 return 0;
4032         }
4033     }
4034 
4035     return 0;
4036 }
4037 
4038 // -----------------------------------------------------------------------
4039 
4040 long ImplHandleSalObjSysCharMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
4041 {
4042     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4043     if ( !pFrame )
4044         return 0;
4045 
4046     sal_uInt16  nRepeat     = LOWORD( lParam )-1;
4047     sal_uInt16  nModCode    = 0;
4048     sal_uInt16  cKeyCode    = (sal_uInt16)wParam;
4049 
4050     // determine modifiers
4051     if ( GetKeyState( VK_SHIFT ) & 0x8000 )
4052         nModCode |= KEY_SHIFT;
4053     if ( GetKeyState( VK_CONTROL ) & 0x8000 )
4054         nModCode |= KEY_MOD1;
4055     nModCode |= KEY_MOD2;
4056 
4057     // KeyEvent zusammenbauen
4058     SalKeyEvent aKeyEvt;
4059     aKeyEvt.mnTime      = GetMessageTime();
4060     if ( (cKeyCode >= 48) && (cKeyCode <= 57) )
4061         aKeyEvt.mnCode = KEY_0+(cKeyCode-48);
4062     else if ( (cKeyCode >= 65) && (cKeyCode <= 90) )
4063         aKeyEvt.mnCode = KEY_A+(cKeyCode-65);
4064     else  if ( (cKeyCode >= 97) && (cKeyCode <= 122) )
4065         aKeyEvt.mnCode = KEY_A+(cKeyCode-97);
4066     else
4067         aKeyEvt.mnCode = 0;
4068     aKeyEvt.mnCode     |= nModCode;
4069     aKeyEvt.mnCharCode  = ImplGetCharCode( pFrame, cKeyCode );
4070     aKeyEvt.mnRepeat    = nRepeat;
4071     long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
4072     pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
4073     return nRet;
4074 }
4075 
4076 // -----------------------------------------------------------------------
4077 
4078 static bool ImplHandlePaintMsg( HWND hWnd )
4079 {
4080     sal_Bool bMutex = FALSE;
4081     if ( ImplSalYieldMutexTryToAcquire() )
4082         bMutex = TRUE;
4083 
4084     // if we don't get the mutex, we can also change the clip region,
4085     // because other threads doesn't use the mutex from the main
4086     // thread --> see GetGraphics()
4087 
4088     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4089     if ( pFrame )
4090     {
4091         // Clip-Region muss zurueckgesetzt werden, da wir sonst kein
4092         // ordentliches Bounding-Rectangle bekommen
4093         if ( pFrame->mpGraphics && pFrame->mpGraphics->mhRegion )
4094             SelectClipRgn( pFrame->mpGraphics->mhDC, 0 );
4095 
4096         // Laut Window-Doku soll man erst abfragen, ob ueberhaupt eine
4097         // Paint-Region anliegt
4098         if ( GetUpdateRect( hWnd, NULL, FALSE ) )
4099         {
4100             // Call BeginPaint/EndPaint to query the rect and send
4101             // this Notofication to rect
4102             RECT aUpdateRect;
4103             PAINTSTRUCT aPs;
4104             BeginPaint( hWnd, &aPs );
4105             CopyRect( &aUpdateRect, &aPs.rcPaint );
4106 
4107             // Paint
4108             // ClipRegion wieder herstellen
4109             if ( pFrame->mpGraphics && pFrame->mpGraphics->mhRegion )
4110             {
4111                 SelectClipRgn( pFrame->mpGraphics->mhDC,
4112                                pFrame->mpGraphics->mhRegion );
4113             }
4114 
4115             if ( bMutex )
4116             {
4117                 SalPaintEvent aPEvt( aUpdateRect.left, aUpdateRect.top, aUpdateRect.right-aUpdateRect.left, aUpdateRect.bottom-aUpdateRect.top, pFrame->mbPresentation );
4118                 pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
4119             }
4120             else
4121             {
4122                 RECT* pRect = new RECT;
4123                 CopyRect( pRect, &aUpdateRect );
4124                 ImplPostMessage( hWnd, SAL_MSG_POSTPAINT, (WPARAM)pRect, 0 );
4125             }
4126             EndPaint( hWnd, &aPs );
4127         }
4128         else
4129         {
4130             // ClipRegion wieder herstellen
4131             if ( pFrame->mpGraphics && pFrame->mpGraphics->mhRegion )
4132             {
4133                 SelectClipRgn( pFrame->mpGraphics->mhDC,
4134                                pFrame->mpGraphics->mhRegion );
4135             }
4136         }
4137     }
4138 
4139     if ( bMutex )
4140         ImplSalYieldMutexRelease();
4141 
4142 	return bMutex ? true : false;
4143 }
4144 
4145 // -----------------------------------------------------------------------
4146 
4147 static void ImplHandlePaintMsg2( HWND hWnd, RECT* pRect )
4148 {
4149     // Paint
4150     if ( ImplSalYieldMutexTryToAcquire() )
4151     {
4152         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4153         if ( pFrame )
4154         {
4155             SalPaintEvent aPEvt( pRect->left, pRect->top, pRect->right-pRect->left, pRect->bottom-pRect->top );
4156             pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
4157         }
4158         ImplSalYieldMutexRelease();
4159         delete pRect;
4160     }
4161     else
4162         ImplPostMessage( hWnd, SAL_MSG_POSTPAINT, (WPARAM)pRect, 0 );
4163 }
4164 
4165 // -----------------------------------------------------------------------
4166 
4167 static void SetMaximizedFrameGeometry( HWND hWnd, WinSalFrame* pFrame, RECT* pParentRect )
4168 {
4169     // calculate and set frame geometry of a maximized window - useful if the window is still hidden
4170 
4171     // dualmonitor support:
4172     // Get screensize of the monitor whith the mouse pointer
4173 
4174     RECT aRectMouse;
4175     if( ! pParentRect )
4176     {
4177         POINT pt;
4178         GetCursorPos( &pt );
4179         aRectMouse.left = pt.x;
4180         aRectMouse.top = pt.y;
4181         aRectMouse.right = pt.x+2;
4182         aRectMouse.bottom = pt.y+2;
4183         pParentRect = &aRectMouse;
4184     }
4185 
4186     RECT aRect;
4187     ImplSalGetWorkArea( hWnd, &aRect, pParentRect );
4188 
4189     // a maximized window has no other borders than the caption
4190     pFrame->maGeometry.nLeftDecoration = pFrame->maGeometry.nRightDecoration = pFrame->maGeometry.nBottomDecoration = 0;
4191     pFrame->maGeometry.nTopDecoration = pFrame->mbCaption ? GetSystemMetrics( SM_CYCAPTION ) : 0;
4192 
4193     aRect.top += pFrame->maGeometry.nTopDecoration;
4194     pFrame->maGeometry.nX = aRect.left;
4195     pFrame->maGeometry.nY = aRect.top;
4196     pFrame->maGeometry.nWidth = aRect.right - aRect.left;
4197     pFrame->maGeometry.nHeight = aRect.bottom - aRect.top;
4198 }
4199 
4200 static void UpdateFrameGeometry( HWND hWnd, WinSalFrame* pFrame )
4201 {
4202     if( !pFrame )
4203         return;
4204 
4205     RECT aRect;
4206     GetWindowRect( hWnd, &aRect );
4207     memset(&pFrame->maGeometry, 0, sizeof(SalFrameGeometry) );
4208 
4209     if ( IsIconic( hWnd ) )
4210         return;
4211 
4212     POINT aPt;
4213     aPt.x=0;
4214     aPt.y=0;
4215     ClientToScreen(hWnd, &aPt);
4216     int cx = aPt.x - aRect.left;
4217     pFrame->maGeometry.nTopDecoration = aPt.y - aRect.top;
4218 
4219     pFrame->maGeometry.nLeftDecoration = cx;
4220     pFrame->maGeometry.nRightDecoration = cx;
4221 
4222     pFrame->maGeometry.nX = aPt.x;
4223     pFrame->maGeometry.nY = aPt.y;
4224 
4225     RECT aInnerRect;
4226     GetClientRect( hWnd, &aInnerRect );
4227     if( aInnerRect.right )
4228     {
4229         // improve right decoration
4230         aPt.x=aInnerRect.right;
4231         aPt.y=aInnerRect.top;
4232         ClientToScreen(hWnd, &aPt);
4233         pFrame->maGeometry.nRightDecoration = aRect.right - aPt.x;
4234     }
4235     if( aInnerRect.bottom ) // may be zero if window was not shown yet
4236         pFrame->maGeometry.nBottomDecoration += aRect.bottom - aPt.y - aInnerRect.bottom;
4237     else
4238         // bottom border is typically the same as left/right
4239         pFrame->maGeometry.nBottomDecoration = pFrame->maGeometry.nLeftDecoration;
4240 
4241     int nWidth  = aRect.right - aRect.left
4242         - pFrame->maGeometry.nRightDecoration - pFrame->maGeometry.nLeftDecoration;
4243     int nHeight = aRect.bottom - aRect.top
4244         - pFrame->maGeometry.nBottomDecoration - pFrame->maGeometry.nTopDecoration;
4245     // clamp to zero
4246     pFrame->maGeometry.nHeight = nHeight < 0 ? 0 : nHeight;
4247     pFrame->maGeometry.nWidth = nWidth < 0 ? 0 : nWidth;
4248     pFrame->updateScreenNumber();
4249 }
4250 
4251 // -----------------------------------------------------------------------
4252 
4253 static void ImplCallMoveHdl( HWND hWnd )
4254 {
4255     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4256     if ( pFrame )
4257     {
4258         pFrame->CallCallback( SALEVENT_MOVE, 0 );
4259         // Um doppelte Paints von VCL und SAL zu vermeiden
4260         //if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow )
4261         //    UpdateWindow( hWnd );
4262     }
4263 }
4264 
4265 // -----------------------------------------------------------------------
4266 
4267 static void ImplCallClosePopupsHdl( HWND hWnd )
4268 {
4269     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4270     if ( pFrame )
4271     {
4272         pFrame->CallCallback( SALEVENT_CLOSEPOPUPS, 0 );
4273     }
4274 }
4275 
4276 // -----------------------------------------------------------------------
4277 
4278 static void ImplHandleMoveMsg( HWND hWnd )
4279 {
4280     if ( ImplSalYieldMutexTryToAcquire() )
4281     {
4282         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4283         if ( pFrame )
4284         {
4285             UpdateFrameGeometry( hWnd, pFrame );
4286 
4287             if ( GetWindowStyle( hWnd ) & WS_VISIBLE )
4288                 pFrame->mbDefPos = FALSE;
4289 
4290             // Gegen moegliche Rekursionen sichern
4291             if ( !pFrame->mbInMoveMsg )
4292             {
4293                 // Fenster im FullScreenModus wieder einpassen
4294                 pFrame->mbInMoveMsg = TRUE;
4295                 if ( pFrame->mbFullScreen )
4296                     ImplSalFrameFullScreenPos( pFrame );
4297                 pFrame->mbInMoveMsg = FALSE;
4298             }
4299 
4300             // Status merken
4301             ImplSaveFrameState( pFrame );
4302 
4303             // Call Hdl
4304             //#93851 if we call this handler, VCL floating windows are not updated correctly
4305             ImplCallMoveHdl( hWnd );
4306 
4307         }
4308 
4309         ImplSalYieldMutexRelease();
4310     }
4311     else
4312         ImplPostMessage( hWnd, SAL_MSG_POSTMOVE, 0, 0 );
4313 }
4314 
4315 // -----------------------------------------------------------------------
4316 
4317 static void ImplCallSizeHdl( HWND hWnd )
4318 {
4319     // Da Windows diese Messages auch senden kann, muss hier auch die
4320     // Solar-Semaphore beruecksichtigt werden
4321     if ( ImplSalYieldMutexTryToAcquire() )
4322     {
4323         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4324         if ( pFrame )
4325         {
4326             pFrame->CallCallback( SALEVENT_RESIZE, 0 );
4327             // Um doppelte Paints von VCL und SAL zu vermeiden
4328             if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow )
4329                 UpdateWindow( hWnd );
4330         }
4331 
4332         ImplSalYieldMutexRelease();
4333     }
4334     else
4335         ImplPostMessage( hWnd, SAL_MSG_POSTCALLSIZE, 0, 0 );
4336 }
4337 
4338 // -----------------------------------------------------------------------
4339 
4340 static void ImplHandleSizeMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
4341 {
4342     if ( (wParam != SIZE_MAXSHOW) && (wParam != SIZE_MAXHIDE) )
4343     {
4344         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4345         if ( pFrame )
4346         {
4347             UpdateFrameGeometry( hWnd, pFrame );
4348 
4349             pFrame->mnWidth  = (int)LOWORD(lParam);
4350             pFrame->mnHeight = (int)HIWORD(lParam);
4351             // Status merken
4352             ImplSaveFrameState( pFrame );
4353             // Call Hdl
4354             ImplCallSizeHdl( hWnd );
4355         }
4356     }
4357 }
4358 
4359 // -----------------------------------------------------------------------
4360 
4361 static void ImplHandleFocusMsg( HWND hWnd )
4362 {
4363     if ( ImplSalYieldMutexTryToAcquire() )
4364     {
4365         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4366         if ( pFrame && !WinSalFrame::mbInReparent )
4367         {
4368             // Query the actual status
4369             if ( ::GetFocus() == hWnd )
4370             {
4371                 if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow )
4372                     UpdateWindow( hWnd );
4373 
4374                 // Feststellen, ob wir IME unterstuetzen
4375                 if ( pFrame->mbIME && pFrame->mhDefIMEContext )
4376                 {
4377                     UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_PROPERTY );
4378 
4379                     pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
4380                     pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
4381                     pFrame->mbHandleIME = !pFrame->mbSpezIME;
4382                 }
4383 
4384                 pFrame->CallCallback( SALEVENT_GETFOCUS, 0 );
4385             }
4386             else
4387             {
4388                 pFrame->CallCallback( SALEVENT_LOSEFOCUS, 0 );
4389             }
4390         }
4391 
4392         ImplSalYieldMutexRelease();
4393     }
4394     else
4395         ImplPostMessage( hWnd, SAL_MSG_POSTFOCUS, 0, 0 );
4396 }
4397 
4398 // -----------------------------------------------------------------------
4399 
4400 static void ImplHandleCloseMsg( HWND hWnd )
4401 {
4402     if ( ImplSalYieldMutexTryToAcquire() )
4403     {
4404         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4405         if ( pFrame )
4406         {
4407             pFrame->CallCallback( SALEVENT_CLOSE, 0 );
4408         }
4409 
4410         ImplSalYieldMutexRelease();
4411     }
4412     else
4413         ImplPostMessage( hWnd, WM_CLOSE, 0, 0 );
4414 }
4415 
4416 // -----------------------------------------------------------------------
4417 
4418 static long ImplHandleShutDownMsg( HWND hWnd )
4419 {
4420     ImplSalYieldMutexAcquireWithWait();
4421     long        nRet = 0;
4422     WinSalFrame*   pFrame = GetWindowPtr( hWnd );
4423     if ( pFrame )
4424     {
4425         nRet = pFrame->CallCallback( SALEVENT_SHUTDOWN, 0 );
4426     }
4427     ImplSalYieldMutexRelease();
4428     return nRet;
4429 }
4430 
4431 // -----------------------------------------------------------------------
4432 
4433 static void ImplHandleSettingsChangeMsg( HWND hWnd, UINT nMsg,
4434                                          WPARAM wParam, LPARAM lParam )
4435 {
4436     sal_uInt16 nSalEvent = SALEVENT_SETTINGSCHANGED;
4437 
4438     if ( nMsg == WM_DEVMODECHANGE )
4439         nSalEvent = SALEVENT_PRINTERCHANGED;
4440     else if ( nMsg == WM_DISPLAYCHANGE )
4441         nSalEvent = SALEVENT_DISPLAYCHANGED;
4442     else if ( nMsg == WM_FONTCHANGE )
4443         nSalEvent = SALEVENT_FONTCHANGED;
4444     else if ( nMsg == WM_TIMECHANGE )
4445         nSalEvent = SALEVENT_DATETIMECHANGED;
4446     else if ( nMsg == WM_WININICHANGE )
4447     {
4448         if ( lParam )
4449         {
4450                 if ( ImplSalWICompareAscii( (const wchar_t*)lParam, "devices" ) == 0 )
4451                     nSalEvent = SALEVENT_PRINTERCHANGED;
4452         }
4453     }
4454 
4455     if ( nMsg == WM_SETTINGCHANGE )
4456     {
4457         if ( wParam == SPI_SETWHEELSCROLLLINES )
4458             aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines();
4459         else if( wParam == SPI_SETWHEELSCROLLCHARS )
4460             aSalShlData.mnWheelScrollChars = ImplSalGetWheelScrollChars();
4461     }
4462 
4463     if ( WM_SYSCOLORCHANGE == nMsg && GetSalData()->mhDitherPal )
4464         ImplUpdateSysColorEntries();
4465 
4466     ImplSalYieldMutexAcquireWithWait();
4467 
4468     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4469     if ( pFrame )
4470     {
4471         if ( (nMsg == WM_DISPLAYCHANGE) || (nMsg == WM_WININICHANGE) )
4472         {
4473             if ( pFrame->mbFullScreen )
4474                 ImplSalFrameFullScreenPos( pFrame );
4475         }
4476 
4477         pFrame->CallCallback( nSalEvent, 0 );
4478     }
4479 
4480     ImplSalYieldMutexRelease();
4481 }
4482 
4483 // -----------------------------------------------------------------------
4484 
4485 static void ImplHandleUserEvent( HWND hWnd, LPARAM lParam )
4486 {
4487     ImplSalYieldMutexAcquireWithWait();
4488     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4489     if ( pFrame )
4490     {
4491         pFrame->CallCallback( SALEVENT_USEREVENT, (void*)lParam );
4492     }
4493     ImplSalYieldMutexRelease();
4494 }
4495 
4496 // -----------------------------------------------------------------------
4497 
4498 static void ImplHandleForcePalette( HWND hWnd )
4499 {
4500     SalData*    pSalData = GetSalData();
4501     HPALETTE    hPal = pSalData->mhDitherPal;
4502     if ( hPal )
4503     {
4504         if ( !ImplSalYieldMutexTryToAcquire() )
4505         {
4506             ImplPostMessage( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 );
4507             return;
4508         }
4509 
4510         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4511         if ( pFrame && pFrame->mpGraphics )
4512         {
4513             WinSalGraphics* pGraphics = pFrame->mpGraphics;
4514             if ( pGraphics && pGraphics->mhDefPal )
4515             {
4516                 SelectPalette( pGraphics->mhDC, hPal, FALSE );
4517                 if ( RealizePalette( pGraphics->mhDC ) )
4518                 {
4519                     InvalidateRect( hWnd, NULL, FALSE );
4520                     UpdateWindow( hWnd );
4521                     pFrame->CallCallback( SALEVENT_DISPLAYCHANGED, 0 );
4522                 }
4523             }
4524         }
4525 
4526         ImplSalYieldMutexRelease();
4527     }
4528 }
4529 
4530 // -----------------------------------------------------------------------
4531 
4532 static LRESULT ImplHandlePalette( sal_Bool bFrame, HWND hWnd, UINT nMsg,
4533                                   WPARAM wParam, LPARAM lParam, int& rDef )
4534 {
4535     SalData*    pSalData = GetSalData();
4536     HPALETTE    hPal = pSalData->mhDitherPal;
4537     if ( !hPal )
4538         return 0;
4539 
4540     rDef = FALSE;
4541     if ( pSalData->mbInPalChange )
4542         return 0;
4543 
4544     if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) )
4545     {
4546         if ( (HWND)wParam == hWnd )
4547             return 0;
4548     }
4549 
4550     sal_Bool bReleaseMutex = FALSE;
4551     if ( (nMsg == WM_QUERYNEWPALETTE) || (nMsg == WM_PALETTECHANGED) )
4552     {
4553         // Da Windows diese Messages auch sendet, muss hier auch die
4554         // Solar-Semaphore beruecksichtigt werden
4555         if ( ImplSalYieldMutexTryToAcquire() )
4556             bReleaseMutex = TRUE;
4557         else if ( nMsg == WM_QUERYNEWPALETTE )
4558             ImplPostMessage( hWnd, SAL_MSG_POSTQUERYNEWPAL, wParam, lParam );
4559         else /* ( nMsg == WM_PALETTECHANGED ) */
4560             ImplPostMessage( hWnd, SAL_MSG_POSTPALCHANGED, wParam, lParam );
4561     }
4562 
4563     WinSalVirtualDevice*pTempVD;
4564     WinSalFrame*        pTempFrame;
4565     WinSalGraphics*     pGraphics;
4566     HDC                 hDC;
4567     HPALETTE            hOldPal;
4568     UINT                nCols;
4569     sal_Bool                bStdDC;
4570     sal_Bool                bUpdate;
4571 
4572     pSalData->mbInPalChange = TRUE;
4573 
4574     // Alle Paletten in VirDevs und Frames zuruecksetzen
4575     pTempVD = pSalData->mpFirstVD;
4576     while ( pTempVD )
4577     {
4578         pGraphics = pTempVD->mpGraphics;
4579         if ( pGraphics->mhDefPal )
4580         {
4581             SelectPalette( pGraphics->mhDC,
4582                            pGraphics->mhDefPal,
4583                            TRUE );
4584         }
4585         pTempVD = pTempVD->mpNext;
4586     }
4587     pTempFrame = pSalData->mpFirstFrame;
4588     while ( pTempFrame )
4589     {
4590         pGraphics = pTempFrame->mpGraphics;
4591         if ( pGraphics && pGraphics->mhDefPal )
4592         {
4593             SelectPalette( pGraphics->mhDC,
4594                            pGraphics->mhDefPal,
4595                            TRUE );
4596         }
4597         pTempFrame = pTempFrame->mpNextFrame;
4598     }
4599 
4600     // Palette neu realizen
4601     WinSalFrame* pFrame = NULL;
4602     if ( bFrame )
4603         pFrame = GetWindowPtr( hWnd );
4604     if ( pFrame && pFrame->mpGraphics )
4605     {
4606         hDC = pFrame->mpGraphics->mhDC;
4607         bStdDC = TRUE;
4608     }
4609     else
4610     {
4611         hDC = GetDC( hWnd );
4612         bStdDC = FALSE;
4613     }
4614     UnrealizeObject( hPal );
4615     hOldPal = SelectPalette( hDC, hPal, TRUE );
4616     nCols = RealizePalette( hDC );
4617     bUpdate = nCols != 0;
4618     if ( !bStdDC )
4619     {
4620         SelectPalette( hDC, hOldPal, TRUE );
4621         ReleaseDC( hWnd, hDC );
4622     }
4623 
4624     // Alle Paletten in VirDevs und Frames neu setzen
4625     pTempVD = pSalData->mpFirstVD;
4626     while ( pTempVD )
4627     {
4628         pGraphics = pTempVD->mpGraphics;
4629         if ( pGraphics->mhDefPal )
4630         {
4631             SelectPalette( pGraphics->mhDC, hPal, TRUE );
4632             RealizePalette( pGraphics->mhDC );
4633         }
4634         pTempVD = pTempVD->mpNext;
4635     }
4636     pTempFrame = pSalData->mpFirstFrame;
4637     while ( pTempFrame )
4638     {
4639         if ( pTempFrame != pFrame )
4640         {
4641             pGraphics = pTempFrame->mpGraphics;
4642             if ( pGraphics && pGraphics->mhDefPal )
4643             {
4644                 SelectPalette( pGraphics->mhDC, hPal, TRUE );
4645                 if ( RealizePalette( pGraphics->mhDC ) )
4646                     bUpdate = TRUE;
4647             }
4648         }
4649         pTempFrame = pTempFrame->mpNextFrame;
4650     }
4651 
4652     // Wenn sich Farben geaendert haben, dann die Fenster updaten
4653     if ( bUpdate )
4654     {
4655         pTempFrame = pSalData->mpFirstFrame;
4656         while ( pTempFrame )
4657         {
4658             pGraphics = pTempFrame->mpGraphics;
4659             if ( pGraphics && pGraphics->mhDefPal )
4660             {
4661                 InvalidateRect( pTempFrame->mhWnd, NULL, FALSE );
4662                 UpdateWindow( pTempFrame->mhWnd );
4663                 pTempFrame->CallCallback( SALEVENT_DISPLAYCHANGED, 0 );
4664             }
4665             pTempFrame = pTempFrame->mpNextFrame;
4666         }
4667     }
4668 
4669     pSalData->mbInPalChange = FALSE;
4670 
4671     if ( bReleaseMutex )
4672         ImplSalYieldMutexRelease();
4673 
4674     if ( nMsg == WM_PALETTECHANGED )
4675         return 0;
4676     else
4677         return nCols;
4678 }
4679 
4680 // -----------------------------------------------------------------------
4681 
4682 static int ImplHandleMinMax( HWND hWnd, LPARAM lParam )
4683 {
4684     int bRet = FALSE;
4685 
4686     if ( ImplSalYieldMutexTryToAcquire() )
4687     {
4688         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4689         if ( pFrame )
4690         {
4691             MINMAXINFO* pMinMax = (MINMAXINFO*)lParam;
4692 
4693             if ( pFrame->mbFullScreen )
4694             {
4695                 int         nX;
4696                 int         nY;
4697                 int         nDX;
4698                 int         nDY;
4699                 ImplSalCalcFullScreenSize( pFrame, nX, nY, nDX, nDY );
4700 
4701                 if ( pMinMax->ptMaxPosition.x > nX )
4702                     pMinMax->ptMaxPosition.x = nX;
4703                 if ( pMinMax->ptMaxPosition.y > nY )
4704                     pMinMax->ptMaxPosition.y = nY;
4705 
4706                 if ( pMinMax->ptMaxSize.x < nDX )
4707                     pMinMax->ptMaxSize.x = nDX;
4708                 if ( pMinMax->ptMaxSize.y < nDY )
4709                     pMinMax->ptMaxSize.y = nDY;
4710                 if ( pMinMax->ptMaxTrackSize.x < nDX )
4711                     pMinMax->ptMaxTrackSize.x = nDX;
4712                 if ( pMinMax->ptMaxTrackSize.y < nDY )
4713                     pMinMax->ptMaxTrackSize.y = nDY;
4714 
4715                 pMinMax->ptMinTrackSize.x = nDX;
4716                 pMinMax->ptMinTrackSize.y = nDY;
4717 
4718                 bRet = TRUE;
4719             }
4720 
4721             if ( pFrame->mnMinWidth || pFrame->mnMinHeight )
4722             {
4723                 int nWidth   = pFrame->mnMinWidth;
4724                 int nHeight  = pFrame->mnMinHeight;
4725 
4726                 ImplSalAddBorder( pFrame, nWidth, nHeight );
4727 
4728                 if ( pMinMax->ptMinTrackSize.x < nWidth )
4729                      pMinMax->ptMinTrackSize.x = nWidth;
4730                 if ( pMinMax->ptMinTrackSize.y < nHeight )
4731                      pMinMax->ptMinTrackSize.y = nHeight;
4732             }
4733 
4734             if ( pFrame->mnMaxWidth || pFrame->mnMaxHeight )
4735             {
4736                 int nWidth   = pFrame->mnMaxWidth;
4737                 int nHeight  = pFrame->mnMaxHeight;
4738 
4739                 ImplSalAddBorder( pFrame, nWidth, nHeight );
4740 
4741                 if( nWidth > 0 && nHeight > 0 ) // protect against int overflow due to INT_MAX initialisation
4742                 {
4743                     if ( pMinMax->ptMaxTrackSize.x > nWidth )
4744                         pMinMax->ptMaxTrackSize.x = nWidth;
4745                     if ( pMinMax->ptMaxTrackSize.y > nHeight )
4746                         pMinMax->ptMaxTrackSize.y = nHeight;
4747                 }
4748             }
4749         }
4750 
4751         ImplSalYieldMutexRelease();
4752     }
4753 
4754     return bRet;
4755 }
4756 
4757 // -----------------------------------------------------------------------
4758 
4759 // retrieves the SalMenuItem pointer from a hMenu
4760 // the pointer is stored in every item, so if no position
4761 // is specified we just use the first item (ie, pos=0)
4762 // if bByPosition is FALSE then nPos denotes a menu id instead of a position
4763 static WinSalMenuItem* ImplGetSalMenuItem( HMENU hMenu, UINT nPos, sal_Bool bByPosition=TRUE )
4764 {
4765     DWORD err=0;
4766 
4767     MENUITEMINFOW mi;
4768     memset(&mi, 0, sizeof(mi));
4769     mi.cbSize = sizeof( mi );
4770     mi.fMask = MIIM_DATA;
4771     if( !GetMenuItemInfoW( hMenu, nPos, bByPosition, &mi) )
4772         err = GetLastError();
4773 
4774     return (WinSalMenuItem *) mi.dwItemData;
4775 }
4776 
4777 // returns the index of the currently selected item if any or -1
4778 static int ImplGetSelectedIndex( HMENU hMenu )
4779 {
4780     DWORD err=0;
4781 
4782     MENUITEMINFOW mi;
4783     memset(&mi, 0, sizeof(mi));
4784     mi.cbSize = sizeof( mi );
4785     mi.fMask = MIIM_STATE;
4786     int n = GetMenuItemCount( hMenu );
4787     if( n != -1 )
4788     {
4789         for(int i=0; i<n; i++ )
4790         {
4791             if( !GetMenuItemInfoW( hMenu, i, TRUE, &mi) )
4792                 err = GetLastError();
4793             else
4794             {
4795                 if( mi.fState & MFS_HILITE )
4796                     return i;
4797             }
4798         }
4799     }
4800     return -1;
4801 }
4802 
4803 static int ImplMenuChar( HWND, WPARAM wParam, LPARAM lParam )
4804 {
4805     int nRet = MNC_IGNORE;
4806     HMENU hMenu = (HMENU) lParam;
4807     String aMnemonic;
4808     aMnemonic.AssignAscii("&");
4809     aMnemonic.Append( (sal_Unicode) LOWORD(wParam) );
4810     aMnemonic.ToLowerAscii();   // we only have ascii mnemonics
4811 
4812     // search the mnemonic in the current menu
4813     int nItemCount = GetMenuItemCount( hMenu );
4814     int nFound = 0;
4815     int idxFound = -1;
4816     int idxSelected = ImplGetSelectedIndex( hMenu );
4817     int idx = idxSelected != -1 ? idxSelected+1 : 0;    // if duplicate mnemonics cycle through menu
4818     for( int i=0; i< nItemCount; i++, idx++ )
4819     {
4820         WinSalMenuItem* pSalMenuItem = ImplGetSalMenuItem( hMenu, idx % nItemCount );
4821         if( !pSalMenuItem )
4822             continue;
4823         String aStr = pSalMenuItem->mText;
4824         aStr.ToLowerAscii();
4825         if( aStr.Search( aMnemonic ) != STRING_NOTFOUND)
4826         {
4827             if( idxFound == -1 )
4828                 idxFound = idx % nItemCount;
4829             if( nFound++ )
4830                 break;  // duplicate found
4831         }
4832     }
4833     if( nFound == 1 )
4834         nRet = MAKELRESULT( idxFound, MNC_EXECUTE );
4835     else
4836         // duplicate mnemonics, just select the next occurence
4837         nRet = MAKELRESULT( idxFound, MNC_SELECT );
4838 
4839     return nRet;
4840 }
4841 
4842 static int ImplMeasureItem( HWND hWnd, WPARAM wParam, LPARAM lParam )
4843 {
4844     int nRet = 0;
4845     if( !wParam )
4846     {
4847         // request was sent by a menu
4848         nRet = 1;
4849         MEASUREITEMSTRUCT *pMI = (LPMEASUREITEMSTRUCT) lParam;
4850         if( pMI->CtlType != ODT_MENU )
4851             return 0;
4852 
4853         WinSalMenuItem *pSalMenuItem = (WinSalMenuItem *) pMI->itemData;
4854         if( !pSalMenuItem )
4855             return 0;
4856 
4857         HDC hdc = GetDC( hWnd );
4858         SIZE strSize;
4859 
4860         NONCLIENTMETRICS ncm;
4861         memset( &ncm, 0, sizeof(ncm) );
4862         ncm.cbSize = sizeof( ncm );
4863         SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0 );
4864 
4865         // Assume every menu item can be default and printed bold
4866         //ncm.lfMenuFont.lfWeight = FW_BOLD;
4867 
4868         HFONT hfntOld = (HFONT) SelectObject(hdc, (HFONT) CreateFontIndirect( &ncm.lfMenuFont ));
4869 
4870         // menu text and accelerator
4871         String aStr(pSalMenuItem->mText.GetBuffer() );
4872         if( pSalMenuItem->mAccelText.Len() )
4873         {
4874             aStr.AppendAscii(" ");
4875             aStr.Append( pSalMenuItem->mAccelText );
4876         }
4877         GetTextExtentPoint32W( hdc, (LPWSTR) aStr.GetBuffer(),
4878                                 aStr.Len(), &strSize );
4879 
4880         // image
4881         Size bmpSize( 16, 16 );
4882         //if( !!pSalMenuItem->maBitmap )
4883         //    bmpSize = pSalMenuItem->maBitmap.GetSizePixel();
4884 
4885         // checkmark
4886         Size checkSize( GetSystemMetrics( SM_CXMENUCHECK ), GetSystemMetrics( SM_CYMENUCHECK ) );
4887 
4888         pMI->itemWidth = checkSize.Width() + 3 + bmpSize.Width() + 3 + strSize.cx;
4889         pMI->itemHeight = Max( Max( checkSize.Height(), bmpSize.Height() ), strSize.cy );
4890         pMI->itemHeight += 4;
4891 
4892         DeleteObject( SelectObject(hdc, hfntOld) );
4893         ReleaseDC( hWnd, hdc );
4894     }
4895 
4896     return nRet;
4897 }
4898 
4899 static int ImplDrawItem(HWND, WPARAM wParam, LPARAM lParam )
4900 {
4901     int nRet = 0;
4902     DWORD err = 0;
4903     if( !wParam )
4904     {
4905         // request was sent by a menu
4906         nRet = 1;
4907         DRAWITEMSTRUCT *pDI = (LPDRAWITEMSTRUCT) lParam;
4908         if( pDI->CtlType != ODT_MENU )
4909             return 0;
4910 
4911         WinSalMenuItem *pSalMenuItem = (WinSalMenuItem *) pDI->itemData;
4912         if( !pSalMenuItem )
4913             return 0;
4914 
4915         COLORREF clrPrevText, clrPrevBkgnd;
4916         HFONT hfntOld;
4917         HBRUSH hbrOld;
4918         sal_Bool	fChecked = (pDI->itemState & ODS_CHECKED) ? TRUE : FALSE;
4919         sal_Bool	fSelected = (pDI->itemState & ODS_SELECTED) ? TRUE : FALSE;
4920         sal_Bool	fDisabled = (pDI->itemState & (ODS_DISABLED | ODS_GRAYED)) ? TRUE : FALSE;
4921 
4922         // Set the appropriate foreground and background colors.
4923         RECT aRect = pDI->rcItem;
4924 
4925         clrPrevBkgnd = SetBkColor( pDI->hDC, GetSysColor( COLOR_MENU ) );
4926 
4927         if ( fDisabled )
4928             clrPrevText = SetTextColor( pDI->hDC, GetSysColor( COLOR_GRAYTEXT ) );
4929         else
4930             clrPrevText = SetTextColor( pDI->hDC, GetSysColor( fSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT ) );
4931 
4932         DWORD colBackground = GetSysColor( fSelected ? COLOR_HIGHLIGHT : COLOR_MENU );
4933         if ( fSelected )
4934 	        clrPrevBkgnd = SetBkColor( pDI->hDC, colBackground );
4935         else
4936 	        clrPrevBkgnd = SetBkColor( pDI->hDC, colBackground );
4937 
4938         hbrOld = (HBRUSH)SelectObject( pDI->hDC, CreateSolidBrush( GetBkColor( pDI->hDC ) ) );
4939 
4940         // Fill background
4941         if(!PatBlt( pDI->hDC, aRect.left, aRect.top, aRect.right-aRect.left, aRect.bottom-aRect.top, PATCOPY ))
4942             err = GetLastError();
4943 
4944         int lineHeight = aRect.bottom-aRect.top;
4945 
4946         int x = aRect.left;
4947         int y = aRect.top;
4948 
4949         int checkWidth  = GetSystemMetrics( SM_CXMENUCHECK );
4950         int checkHeight = GetSystemMetrics( SM_CYMENUCHECK );
4951         if( fChecked )
4952         {
4953             RECT r;
4954             r.left = 0;
4955             r.top = 0;
4956             r.right = checkWidth;
4957             r.bottom = checkWidth;
4958             HDC memDC = CreateCompatibleDC( pDI->hDC );
4959             HBITMAP memBmp = CreateCompatibleBitmap( pDI->hDC, checkWidth, checkHeight );
4960             HBITMAP hOldBmp = (HBITMAP) SelectObject( memDC, memBmp );
4961             DrawFrameControl( memDC, &r, DFC_MENU, DFCS_MENUCHECK );
4962             BitBlt( pDI->hDC, x, y+(lineHeight-checkHeight)/2, checkWidth, checkHeight, memDC, 0, 0, SRCAND );
4963             DeleteObject( SelectObject( memDC, hOldBmp ) );
4964             DeleteDC( memDC );
4965         }
4966         x += checkWidth+3;
4967 
4968         //Size bmpSize = aBitmap.GetSizePixel();
4969         Size bmpSize(16, 16);
4970         if( !!pSalMenuItem->maBitmap )
4971         {
4972             Bitmap aBitmap( pSalMenuItem->maBitmap );
4973 
4974             // set transparent pixels to background color
4975             if( fDisabled )
4976                 colBackground = RGB(255,255,255);
4977             aBitmap.Replace( Color( COL_LIGHTMAGENTA ),
4978                 Color( GetRValue(colBackground),GetGValue(colBackground),GetBValue(colBackground) ), 0);
4979 
4980             WinSalBitmap* pSalBmp = static_cast<WinSalBitmap*>(aBitmap.ImplGetImpBitmap()->ImplGetSalBitmap());
4981 			HGLOBAL hDrawDIB = pSalBmp->ImplGethDIB();
4982 
4983             if( hDrawDIB )
4984             {
4985                 PBITMAPINFO 		pBI = (PBITMAPINFO) GlobalLock( hDrawDIB );
4986 			    PBITMAPINFOHEADER	pBIH = (PBITMAPINFOHEADER) pBI;
4987 			    PBYTE				pBits = (PBYTE) pBI + *(DWORD*) pBI +
4988 										    pSalBmp->ImplGetDIBColorCount( hDrawDIB ) * sizeof( RGBQUAD );
4989 
4990                 HBITMAP hBmp = CreateDIBitmap( pDI->hDC, pBIH, CBM_INIT, pBits, pBI, DIB_RGB_COLORS );
4991 			    GlobalUnlock( hDrawDIB );
4992 
4993                 HBRUSH hbrIcon = CreateSolidBrush( GetSysColor( COLOR_GRAYTEXT ) );
4994                 DrawStateW( pDI->hDC, (HBRUSH)hbrIcon, (DRAWSTATEPROC)NULL, (LPARAM)hBmp, (WPARAM)0,
4995                     x, y+(lineHeight-bmpSize.Height())/2, bmpSize.Width(), bmpSize.Height(),
4996                      DST_BITMAP | (fDisabled ? (fSelected ? DSS_MONO : DSS_DISABLED) : DSS_NORMAL) );
4997 
4998                 DeleteObject( hbrIcon );
4999                 DeleteObject( hBmp );
5000             }
5001 
5002         }
5003         x += bmpSize.Width() + 3;
5004         aRect.left = x;
5005 
5006         NONCLIENTMETRICS ncm;
5007         memset( &ncm, 0, sizeof(ncm) );
5008         ncm.cbSize = sizeof( ncm );
5009         SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0 );
5010 
5011         // Print default menu entry with bold font
5012         //if ( pDI->itemState & ODS_DEFAULT )
5013 	    //    ncm.lfMenuFont.lfWeight = FW_BOLD;
5014 
5015         hfntOld = (HFONT) SelectObject(pDI->hDC, (HFONT) CreateFontIndirect( &ncm.lfMenuFont ));
5016 
5017         SIZE strSize;
5018         String aStr( pSalMenuItem->mText.GetBuffer() );
5019         GetTextExtentPoint32W( pDI->hDC, (LPWSTR) aStr.GetBuffer(),
5020                                 aStr.Len(), &strSize );
5021 
5022         if(!DrawStateW( pDI->hDC, (HBRUSH)NULL, (DRAWSTATEPROC)NULL,
5023             (LPARAM)(LPWSTR) aStr.GetBuffer(),
5024             (WPARAM)0, aRect.left, aRect.top + (lineHeight - strSize.cy)/2, 0, 0,
5025             DST_PREFIXTEXT | (fDisabled && !fSelected ? DSS_DISABLED : DSS_NORMAL) ) )
5026             err = GetLastError();
5027 
5028         if( pSalMenuItem->mAccelText.Len() )
5029         {
5030             SIZE strSizeA;
5031             aStr = pSalMenuItem->mAccelText;
5032             GetTextExtentPoint32W( pDI->hDC, (LPWSTR) aStr.GetBuffer(),
5033                                     aStr.Len(), &strSizeA );
5034             TEXTMETRIC tm;
5035             GetTextMetrics( pDI->hDC, &tm );
5036 
5037             // position the accelerator string to the right but leave space for the
5038             // (potential) submenu arrow (tm.tmMaxCharWidth)
5039             if(!DrawStateW( pDI->hDC, (HBRUSH)NULL, (DRAWSTATEPROC)NULL,
5040                 (LPARAM)(LPWSTR) aStr.GetBuffer(),
5041                 (WPARAM)0, aRect.right-strSizeA.cx-tm.tmMaxCharWidth, aRect.top + (lineHeight - strSizeA.cy)/2, 0, 0,
5042                 DST_TEXT | (fDisabled && !fSelected ? DSS_DISABLED : DSS_NORMAL) ) )
5043                 err = GetLastError();
5044         }
5045 
5046         // Restore the original font and colors.
5047         DeleteObject( SelectObject( pDI->hDC, hbrOld ) );
5048         DeleteObject( SelectObject( pDI->hDC, hfntOld) );
5049         SetTextColor(pDI->hDC, clrPrevText);
5050         SetBkColor(pDI->hDC, clrPrevBkgnd);
5051     }
5052     return nRet;
5053 }
5054 
5055 static int ImplHandleMenuActivate( HWND hWnd, WPARAM wParam, LPARAM )
5056 {
5057     // Menu activation
5058     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5059     if ( !pFrame )
5060         return 0;
5061 
5062     HMENU hMenu = (HMENU) wParam;
5063     // WORD nPos = LOWORD (lParam);
5064     // sal_Bool bWindowMenu = (sal_Bool) HIWORD(lParam);
5065 
5066     // Send activate and deactivate together, so we have not keep track of opened menues
5067     // this will be enough to have the menues updated correctly
5068     SalMenuEvent aMenuEvt;
5069     WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, 0 );
5070     if( pSalMenuItem )
5071         aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5072     else
5073         aMenuEvt.mpMenu = NULL;
5074 
5075     long nRet = pFrame->CallCallback( SALEVENT_MENUACTIVATE, &aMenuEvt );
5076     if( nRet )
5077         nRet = pFrame->CallCallback( SALEVENT_MENUDEACTIVATE, &aMenuEvt );
5078     if( nRet )
5079         pFrame->mLastActivatedhMenu = hMenu;
5080 
5081     return (nRet!=0);
5082 }
5083 
5084 static int ImplHandleMenuSelect( HWND hWnd, WPARAM wParam, LPARAM lParam )
5085 {
5086     // Menu selection
5087     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5088     if ( !pFrame )
5089         return 0;
5090 
5091     WORD nId = LOWORD(wParam);      // menu item or submenu index
5092     WORD nFlags = HIWORD(wParam);
5093     HMENU hMenu = (HMENU) lParam;
5094 
5095     // check if we have to process the message
5096     if( !GetSalData()->IsKnownMenuHandle( hMenu ) )
5097         return 0;
5098 
5099     sal_Bool bByPosition = FALSE;
5100     if( nFlags & MF_POPUP )
5101         bByPosition = TRUE;
5102 
5103     long nRet = 0;
5104     if ( hMenu && !pFrame->mLastActivatedhMenu )
5105     {
5106         // we never activated a menu (ie, no WM_INITMENUPOPUP has occured yet)
5107         // which means this must be the menubar -> send activation/deactivation
5108         SalMenuEvent aMenuEvt;
5109         WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, nId, bByPosition );
5110         if( pSalMenuItem )
5111             aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5112         else
5113             aMenuEvt.mpMenu = NULL;
5114 
5115         nRet = pFrame->CallCallback( SALEVENT_MENUACTIVATE, &aMenuEvt );
5116         if( nRet )
5117             nRet = pFrame->CallCallback( SALEVENT_MENUDEACTIVATE, &aMenuEvt );
5118         if( nRet )
5119             pFrame->mLastActivatedhMenu = hMenu;
5120     }
5121 
5122     if( !hMenu && nFlags == 0xFFFF )
5123     {
5124         // all menus are closed, reset activation logic
5125         pFrame->mLastActivatedhMenu = NULL;
5126     }
5127 
5128     if( hMenu )
5129     {
5130         // hMenu must be saved, as it is not passed in WM_COMMAND which always occurs after a selection
5131         // if a menu is closed due to a command selection then hMenu is NULL, but WM_COMMAND comes later
5132         // so we must not overwrite it in this case
5133         pFrame->mSelectedhMenu = hMenu;
5134 
5135         // send highlight event
5136         if( nFlags & MF_POPUP )
5137         {
5138             // submenu selected
5139             // wParam now carries an index instead of an id -> retrieve id
5140             MENUITEMINFOW mi;
5141             memset(&mi, 0, sizeof(mi));
5142             mi.cbSize = sizeof( mi );
5143             mi.fMask = MIIM_ID;
5144             if( GetMenuItemInfoW( hMenu, LOWORD(wParam), TRUE, &mi) )
5145                 nId = sal::static_int_cast<WORD>(mi.wID);
5146         }
5147 
5148         SalMenuEvent aMenuEvt;
5149         aMenuEvt.mnId   = nId;
5150         WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, nId, FALSE );
5151         if( pSalMenuItem )
5152             aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5153         else
5154             aMenuEvt.mpMenu = NULL;
5155 
5156         nRet = pFrame->CallCallback( SALEVENT_MENUHIGHLIGHT, &aMenuEvt );
5157     }
5158 
5159     return (nRet != 0);
5160 }
5161 
5162 static int ImplHandleCommand( HWND hWnd, WPARAM wParam, LPARAM )
5163 {
5164     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5165     if ( !pFrame )
5166         return 0;
5167 
5168     long nRet = 0;
5169     if( !HIWORD(wParam) )
5170     {
5171         // Menu command
5172         WORD nId = LOWORD(wParam);
5173         if( nId )   // zero for separators
5174         {
5175             SalMenuEvent aMenuEvt;
5176             aMenuEvt.mnId   = nId;
5177             WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( pFrame->mSelectedhMenu, nId, FALSE );
5178             if( pSalMenuItem )
5179                 aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5180             else
5181                 aMenuEvt.mpMenu = NULL;
5182 
5183             nRet = pFrame->CallCallback( SALEVENT_MENUCOMMAND, &aMenuEvt );
5184         }
5185     }
5186     return (nRet != 0);
5187 }
5188 
5189 static int ImplHandleSysCommand( HWND hWnd, WPARAM wParam, LPARAM lParam )
5190 {
5191     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5192     if ( !pFrame )
5193         return 0;
5194 
5195     WPARAM nCommand = wParam & 0xFFF0;
5196 
5197     if ( pFrame->mbFullScreen )
5198     {
5199         BOOL    bMaximize = IsZoomed( pFrame->mhWnd );
5200         BOOL    bMinimize = IsIconic( pFrame->mhWnd );
5201         if ( (nCommand == SC_SIZE) ||
5202              (!bMinimize && (nCommand == SC_MOVE)) ||
5203              (!bMaximize && (nCommand == SC_MAXIMIZE)) ||
5204              (bMaximize && (nCommand == SC_RESTORE)) )
5205         {
5206             MessageBeep( 0 );
5207             return TRUE;
5208         }
5209     }
5210 
5211     if ( nCommand == SC_KEYMENU )
5212     {
5213         // do not process SC_KEYMENU if we have a native menu
5214         // Windows should handle this
5215         if( GetMenu( hWnd ) )
5216             return FALSE;
5217 
5218         // Hier verarbeiten wir nur KeyMenu-Events fuer Alt um
5219         // den MenuBar zu aktivieren, oder wenn ein SysChild-Fenster
5220         // den Focus hat, da diese Alt+Tasten-Kombinationen nur
5221         // ueber diesen Event verarbeitet werden
5222         if ( !LOWORD( lParam ) )
5223         {
5224             // Nur ausloesen, wenn keine weitere Taste gedrueckt ist. Im
5225             // Gegensatz zur Doku wird in der X-Koordinaate der CharCode
5226             // geliefert, der zusaetzlich gedrueckt ist
5227             // Also 32 fuer Space, 99 fuer c, 100 fuer d, ...
5228             // Da dies nicht dokumentiert ist, fragen wir vorsichtshalber
5229             // auch den Status der Space-Taste ab
5230             if ( GetKeyState( VK_SPACE ) & 0x8000 )
5231                 return 0;
5232 
5233             // Damit nicht bei Alt+Maustaste auch der MenuBar aktiviert wird
5234             if ( (GetKeyState( VK_LBUTTON ) & 0x8000) ||
5235                  (GetKeyState( VK_RBUTTON ) & 0x8000) ||
5236                  (GetKeyState( VK_MBUTTON ) & 0x8000) ||
5237 				 (GetKeyState( VK_SHIFT )   & 0x8000) )
5238                 return 1;
5239 
5240             SalKeyEvent aKeyEvt;
5241             aKeyEvt.mnTime      = GetMessageTime();
5242             aKeyEvt.mnCode      = KEY_MENU;
5243             aKeyEvt.mnCharCode  = 0;
5244             aKeyEvt.mnRepeat    = 0;
5245             long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
5246             pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
5247             return (nRet != 0);
5248         }
5249         else
5250         {
5251             // Testen, ob ein SysChild den Focus hat
5252             HWND hFocusWnd = ::GetFocus();
5253             if ( hFocusWnd && ImplFindSalObject( hFocusWnd ) )
5254             {
5255                 char cKeyCode = (char)(unsigned char)LOWORD( lParam );
5256                 // LowerCase
5257                 if ( (cKeyCode >= 65) && (cKeyCode <= 90) )
5258                     cKeyCode += 32;
5259                 // Wir nehmen nur 0-9 und A-Z, alle anderen Tasten muessen durch
5260                 // den Hook vom SalObj verarbeitet werden
5261                 if ( ((cKeyCode >= 48) && (cKeyCode <= 57)) ||
5262                      ((cKeyCode >= 97) && (cKeyCode <= 122)) )
5263                 {
5264                     sal_uInt16 nModCode = 0;
5265                     if ( GetKeyState( VK_SHIFT ) & 0x8000 )
5266                         nModCode |= KEY_SHIFT;
5267                     if ( GetKeyState( VK_CONTROL ) & 0x8000 )
5268                         nModCode |= KEY_MOD1;
5269                     nModCode |= KEY_MOD2;
5270 
5271                     SalKeyEvent aKeyEvt;
5272                     aKeyEvt.mnTime      = GetMessageTime();
5273                     if ( (cKeyCode >= 48) && (cKeyCode <= 57) )
5274                         aKeyEvt.mnCode = KEY_0+(cKeyCode-48);
5275                     else
5276                         aKeyEvt.mnCode = KEY_A+(cKeyCode-97);
5277                     aKeyEvt.mnCode     |= nModCode;
5278                     aKeyEvt.mnCharCode  = cKeyCode;
5279                     aKeyEvt.mnRepeat    = 0;
5280                     long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
5281                     pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
5282                     return (nRet != 0);
5283                 }
5284             }
5285         }
5286     }
5287 
5288     return FALSE;
5289 }
5290 
5291 // -----------------------------------------------------------------------
5292 
5293 static void ImplHandleInputLangChange( HWND hWnd, WPARAM, LPARAM lParam )
5294 {
5295     ImplSalYieldMutexAcquireWithWait();
5296 
5297     // Feststellen, ob wir IME unterstuetzen
5298     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5299     if ( pFrame && pFrame->mbIME && pFrame->mhDefIMEContext )
5300     {
5301         HKL     hKL = (HKL)lParam;
5302         UINT    nImeProps = ImmGetProperty( hKL, IGP_PROPERTY );
5303 
5304         pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
5305         pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
5306         pFrame->mbHandleIME = !pFrame->mbSpezIME;
5307     }
5308 
5309     // trigger input language and codepage update
5310     UINT nLang = pFrame->mnInputLang;
5311     ImplUpdateInputLang( pFrame );
5312 
5313     // notify change
5314     if( nLang != pFrame->mnInputLang )
5315         pFrame->CallCallback( SALEVENT_INPUTLANGUAGECHANGE, 0 );
5316 
5317     ImplSalYieldMutexRelease();
5318 }
5319 
5320 // -----------------------------------------------------------------------
5321 
5322 static void ImplUpdateIMECursorPos( WinSalFrame* pFrame, HIMC hIMC )
5323 {
5324     COMPOSITIONFORM aForm;
5325     memset( &aForm, 0, sizeof( aForm ) );
5326 
5327     // Cursor-Position ermitteln und aus der die Default-Position fuer
5328     // das Composition-Fenster berechnen
5329     SalExtTextInputPosEvent aPosEvt;
5330     pFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvt );
5331     if ( (aPosEvt.mnX == -1) && (aPosEvt.mnY == -1) )
5332         aForm.dwStyle |= CFS_DEFAULT;
5333     else
5334     {
5335         aForm.dwStyle          |= CFS_POINT;
5336         aForm.ptCurrentPos.x    = aPosEvt.mnX;
5337         aForm.ptCurrentPos.y    = aPosEvt.mnY;
5338     }
5339     ImmSetCompositionWindow( hIMC, &aForm );
5340 
5341     // Because not all IME's use this values, we create
5342     // a Windows caret to force the Position from the IME
5343     if ( GetFocus() == pFrame->mhWnd )
5344     {
5345         CreateCaret( pFrame->mhWnd, 0,
5346                      aPosEvt.mnWidth, aPosEvt.mnHeight );
5347         SetCaretPos( aPosEvt.mnX, aPosEvt.mnY );
5348     }
5349 }
5350 
5351 // -----------------------------------------------------------------------
5352 
5353 static sal_Bool ImplHandleIMEStartComposition( HWND hWnd )
5354 {
5355     sal_Bool bDef = TRUE;
5356 
5357     ImplSalYieldMutexAcquireWithWait();
5358 
5359     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5360     if ( pFrame )
5361     {
5362         HIMC hIMC = ImmGetContext( hWnd );
5363         if ( hIMC )
5364         {
5365             ImplUpdateIMECursorPos( pFrame, hIMC );
5366             ImmReleaseContext( hWnd, hIMC );
5367         }
5368 
5369         if ( pFrame->mbHandleIME )
5370         {
5371             if ( pFrame->mbAtCursorIME )
5372                 bDef = FALSE;
5373         }
5374     }
5375 
5376     ImplSalYieldMutexRelease();
5377 
5378     return bDef;
5379 }
5380 
5381 // -----------------------------------------------------------------------
5382 
5383 static sal_Bool ImplHandleIMECompositionInput( WinSalFrame* pFrame,
5384                                            HIMC hIMC, LPARAM lParam )
5385 {
5386     sal_Bool bDef = TRUE;
5387 
5388     // Init Event
5389     SalExtTextInputEvent    aEvt;
5390     aEvt.mnTime             = GetMessageTime();
5391     aEvt.mpTextAttr         = NULL;
5392     aEvt.mnCursorPos        = 0;
5393     aEvt.mnDeltaStart       = 0;
5394     aEvt.mbOnlyCursor       = FALSE;
5395     aEvt.mnCursorFlags      = 0;
5396 
5397     // If we get a result string, then we handle this input
5398     if ( lParam & GCS_RESULTSTR )
5399     {
5400         bDef = FALSE;
5401 
5402         LONG nTextLen = ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, 0, 0 ) / sizeof( WCHAR );
5403         if ( nTextLen >= 0 )
5404         {
5405             WCHAR* pTextBuf = new WCHAR[nTextLen];
5406             ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, pTextBuf, nTextLen*sizeof( WCHAR ) );
5407             aEvt.maText = XubString( reinterpret_cast<const xub_Unicode*>(pTextBuf), (xub_StrLen)nTextLen );
5408             delete [] pTextBuf;
5409         }
5410 
5411         aEvt.mnCursorPos = aEvt.maText.Len();
5412         pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5413         pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
5414         ImplUpdateIMECursorPos( pFrame, hIMC );
5415     }
5416 
5417     // If the IME doesn't support OnSpot input, then there is nothing to do
5418     if ( !pFrame->mbAtCursorIME )
5419         return !bDef;
5420 
5421     // If we get new Composition data, then we handle this new input
5422     if ( (lParam & (GCS_COMPSTR | GCS_COMPATTR)) ||
5423          ((lParam & GCS_CURSORPOS) && !(lParam & GCS_RESULTSTR)) )
5424     {
5425         bDef = FALSE;
5426 
5427         sal_uInt16* pSalAttrAry = NULL;
5428         LONG    nTextLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, 0, 0 ) / sizeof( WCHAR );
5429         if ( nTextLen > 0 )
5430         {
5431             WCHAR* pTextBuf = new WCHAR[nTextLen];
5432             ImmGetCompositionStringW( hIMC, GCS_COMPSTR, pTextBuf, nTextLen*sizeof( WCHAR ) );
5433             aEvt.maText = XubString( reinterpret_cast<const xub_Unicode*>(pTextBuf), (xub_StrLen)nTextLen );
5434             delete [] pTextBuf;
5435 
5436             BYTE*   pAttrBuf = NULL;
5437             LONG        nAttrLen = ImmGetCompositionStringW( hIMC, GCS_COMPATTR, 0, 0 );
5438             if ( nAttrLen > 0 )
5439             {
5440                 pAttrBuf = new BYTE[nAttrLen];
5441                 ImmGetCompositionStringW( hIMC, GCS_COMPATTR, pAttrBuf, nAttrLen );
5442             }
5443 
5444             if ( pAttrBuf )
5445             {
5446                 xub_StrLen nTextLen = aEvt.maText.Len();
5447                 pSalAttrAry = new sal_uInt16[nTextLen];
5448                 memset( pSalAttrAry, 0, nTextLen*sizeof( sal_uInt16 ) );
5449                 for ( xub_StrLen i = 0; (i < nTextLen) && (i < nAttrLen); i++ )
5450                 {
5451                     BYTE nWinAttr = pAttrBuf[i];
5452                     sal_uInt16   nSalAttr;
5453                     if ( nWinAttr == ATTR_TARGET_CONVERTED )
5454                     {
5455                         nSalAttr = SAL_EXTTEXTINPUT_ATTR_BOLDUNDERLINE;
5456                         aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_INVISIBLE;
5457                     }
5458                     else if ( nWinAttr == ATTR_CONVERTED )
5459                         nSalAttr = SAL_EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE;
5460                     else if ( nWinAttr == ATTR_TARGET_NOTCONVERTED )
5461                         nSalAttr = SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
5462                     else if ( nWinAttr == ATTR_INPUT_ERROR )
5463                         nSalAttr = SAL_EXTTEXTINPUT_ATTR_REDTEXT | SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
5464                     else /* ( nWinAttr == ATTR_INPUT ) */
5465                         nSalAttr = SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
5466                     pSalAttrAry[i] = nSalAttr;
5467                 }
5468 
5469                 aEvt.mpTextAttr = pSalAttrAry;
5470                 delete [] pAttrBuf;
5471             }
5472         }
5473 
5474         // Only when we get new composition data, we must send this event
5475         if ( (nTextLen > 0) || !(lParam & GCS_RESULTSTR) )
5476         {
5477             // End the mode, if the last character is deleted
5478             if ( !nTextLen && !pFrame->mbCandidateMode )
5479             {
5480                 pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5481                 pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
5482             }
5483             else
5484             {
5485                 // Because Cursor-Position and DeltaStart never updated
5486                 // from the korean input engine, we must handle this here
5487                 if ( lParam & CS_INSERTCHAR )
5488                 {
5489                     aEvt.mnCursorPos = nTextLen;
5490                     if ( aEvt.mnCursorPos && (lParam & CS_NOMOVECARET) )
5491                         aEvt.mnCursorPos--;
5492                 }
5493                 else
5494                     aEvt.mnCursorPos = LOWORD( ImmGetCompositionStringW( hIMC, GCS_CURSORPOS, 0, 0 ) );
5495 
5496                 if ( pFrame->mbCandidateMode )
5497                     aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_INVISIBLE;
5498                 if ( lParam & CS_NOMOVECARET )
5499                     aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_OVERWRITE;
5500 
5501                 pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5502             }
5503             ImplUpdateIMECursorPos( pFrame, hIMC );
5504         }
5505 
5506         if ( pSalAttrAry )
5507             delete [] pSalAttrAry;
5508     }
5509 
5510     return !bDef;
5511 }
5512 
5513 // -----------------------------------------------------------------------
5514 
5515 static sal_Bool ImplHandleIMEComposition( HWND hWnd, LPARAM lParam )
5516 {
5517     sal_Bool bDef = TRUE;
5518     ImplSalYieldMutexAcquireWithWait();
5519 
5520     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5521     if ( pFrame && (!lParam || (lParam & GCS_RESULTSTR)) )
5522     {
5523         // Wir restaurieren den Background-Modus bei jeder Texteingabe,
5524         // da einige Tools wie RichWin uns diesen hin- und wieder umsetzen
5525         if ( pFrame->mpGraphics &&
5526              pFrame->mpGraphics->mhDC )
5527             SetBkMode( pFrame->mpGraphics->mhDC, TRANSPARENT );
5528     }
5529 
5530     if ( pFrame && pFrame->mbHandleIME )
5531     {
5532         if ( !lParam )
5533         {
5534             SalExtTextInputEvent aEvt;
5535             aEvt.mnTime             = GetMessageTime();
5536             aEvt.mpTextAttr         = NULL;
5537             aEvt.mnCursorPos        = 0;
5538             aEvt.mnDeltaStart       = 0;
5539             aEvt.mbOnlyCursor       = FALSE;
5540             aEvt.mnCursorFlags      = 0;
5541             pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5542             pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
5543         }
5544         else if ( lParam & (GCS_RESULTSTR | GCS_COMPSTR | GCS_COMPATTR | GCS_CURSORPOS) )
5545         {
5546             HIMC hIMC = ImmGetContext( hWnd );
5547             if ( hIMC )
5548             {
5549                 if ( ImplHandleIMECompositionInput( pFrame, hIMC, lParam ) )
5550                     bDef = FALSE;
5551 
5552                 ImmReleaseContext( hWnd, hIMC );
5553             }
5554         }
5555     }
5556 
5557     ImplSalYieldMutexRelease();
5558     return bDef;
5559 }
5560 
5561 // -----------------------------------------------------------------------
5562 
5563 static sal_Bool ImplHandleIMEEndComposition( HWND hWnd )
5564 {
5565     sal_Bool bDef = TRUE;
5566 
5567     ImplSalYieldMutexAcquireWithWait();
5568 
5569     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5570     if ( pFrame && pFrame->mbHandleIME )
5571     {
5572         if ( pFrame->mbAtCursorIME )
5573             bDef = FALSE;
5574     }
5575 
5576     ImplSalYieldMutexRelease();
5577 
5578     return bDef;
5579 }
5580 
5581 // -----------------------------------------------------------------------
5582 
5583 static boolean ImplHandleAppCommand( HWND hWnd, LPARAM lParam )
5584 {
5585 	sal_Int16 nCommand = 0;
5586 	switch( GET_APPCOMMAND_LPARAM(lParam) )
5587 	{
5588 	case APPCOMMAND_MEDIA_CHANNEL_DOWN:			nCommand = MEDIA_COMMAND_CHANNEL_DOWN; break;
5589 	case APPCOMMAND_MEDIA_CHANNEL_UP:			nCommand = MEDIA_COMMAND_CHANNEL_UP; break;
5590 	case APPCOMMAND_MEDIA_NEXTTRACK:			nCommand = MEDIA_COMMAND_NEXTTRACK; break;
5591 	case APPCOMMAND_MEDIA_PAUSE:				nCommand = MEDIA_COMMAND_PAUSE; break;
5592 	case APPCOMMAND_MEDIA_PLAY:					nCommand = MEDIA_COMMAND_PLAY; break;
5593 	case APPCOMMAND_MEDIA_PLAY_PAUSE:			nCommand = MEDIA_COMMAND_PLAY_PAUSE; break;
5594 	case APPCOMMAND_MEDIA_PREVIOUSTRACK:		nCommand = MEDIA_COMMAND_PREVIOUSTRACK; break;
5595 	case APPCOMMAND_MEDIA_RECORD:				nCommand = MEDIA_COMMAND_RECORD; break;
5596 	case APPCOMMAND_MEDIA_REWIND:				nCommand = MEDIA_COMMAND_REWIND; break;
5597 	case APPCOMMAND_MEDIA_STOP:					nCommand = MEDIA_COMMAND_STOP; break;
5598 	case APPCOMMAND_MIC_ON_OFF_TOGGLE:			nCommand = MEDIA_COMMAND_MIC_ON_OFF_TOGGLE; break;
5599 	case APPCOMMAND_MICROPHONE_VOLUME_DOWN:		nCommand = MEDIA_COMMAND_MICROPHONE_VOLUME_DOWN; break;
5600 	case APPCOMMAND_MICROPHONE_VOLUME_MUTE:		nCommand = MEDIA_COMMAND_MICROPHONE_VOLUME_MUTE; break;
5601 	case APPCOMMAND_MICROPHONE_VOLUME_UP:		nCommand = MEDIA_COMMAND_MICROPHONE_VOLUME_UP; break;
5602 	case APPCOMMAND_VOLUME_DOWN:				nCommand = MEDIA_COMMAND_VOLUME_DOWN; break;
5603 	case APPCOMMAND_VOLUME_MUTE:				nCommand = MEDIA_COMMAND_VOLUME_MUTE; break;
5604 	case APPCOMMAND_VOLUME_UP:					nCommand = MEDIA_COMMAND_VOLUME_UP; break;
5605 		break;
5606 	default:
5607 		return false;
5608 	}
5609 
5610     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5611 	Window *pWindow = pFrame ? pFrame->GetWindow() : NULL;
5612 
5613 	if( pWindow )
5614 	{
5615 		const Point aPoint;
5616 		CommandEvent aCEvt( aPoint, COMMAND_MEDIA, FALSE, &nCommand );
5617 		NotifyEvent aNCmdEvt( EVENT_COMMAND, pWindow, &aCEvt );
5618 
5619 		if ( !ImplCallPreNotify( aNCmdEvt ) )
5620         {
5621 			pWindow->Command( aCEvt );
5622             return true;
5623         }
5624 	}
5625 
5626     return false;
5627 }
5628 
5629 
5630 static void ImplHandleIMENotify( HWND hWnd, WPARAM wParam )
5631 {
5632     if ( wParam == (WPARAM)IMN_OPENCANDIDATE )
5633     {
5634         ImplSalYieldMutexAcquireWithWait();
5635 
5636         WinSalFrame* pFrame = GetWindowPtr( hWnd );
5637         if ( pFrame && pFrame->mbHandleIME &&
5638              pFrame->mbAtCursorIME )
5639         {
5640             // Wir wollen den Cursor hiden
5641             pFrame->mbCandidateMode = TRUE;
5642             ImplHandleIMEComposition( hWnd, GCS_CURSORPOS );
5643 
5644             HWND hWnd = pFrame->mhWnd;
5645             HIMC hIMC = ImmGetContext( hWnd );
5646             if ( hIMC )
5647             {
5648                 LONG nBufLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, 0, 0 );
5649                 if ( nBufLen >= 1 )
5650                 {
5651                     SalExtTextInputPosEvent aPosEvt;
5652                     pFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvt );
5653 
5654                     // Vertical !!!
5655                     CANDIDATEFORM aForm;
5656                     aForm.dwIndex           = 0;
5657                     aForm.dwStyle           = CFS_EXCLUDE;
5658                     aForm.ptCurrentPos.x    = aPosEvt.mnX;
5659                     aForm.ptCurrentPos.y    = aPosEvt.mnY+1;
5660                     aForm.rcArea.left       = aPosEvt.mnX;
5661                     aForm.rcArea.top        = aPosEvt.mnY;
5662                     aForm.rcArea.right      = aForm.rcArea.left+aPosEvt.mnExtWidth+1;
5663                     aForm.rcArea.bottom     = aForm.rcArea.top+aPosEvt.mnHeight+1;
5664                     ImmSetCandidateWindow( hIMC, &aForm );
5665                 }
5666 
5667                 ImmReleaseContext( hWnd, hIMC );
5668             }
5669         }
5670 
5671         ImplSalYieldMutexRelease();
5672     }
5673     else if ( wParam == (WPARAM)IMN_CLOSECANDIDATE )
5674     {
5675         ImplSalYieldMutexAcquireWithWait();
5676         WinSalFrame* pFrame = GetWindowPtr( hWnd );
5677         if ( pFrame )
5678             pFrame->mbCandidateMode = FALSE;
5679         ImplSalYieldMutexRelease();
5680     }
5681 }
5682 
5683 // -----------------------------------------------------------------------
5684 #if WINVER >= 0x0500
5685 
5686 static LRESULT ImplHandleIMEReconvertString( HWND hWnd, LPARAM lParam )
5687 {
5688     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5689     LPRECONVERTSTRING pReconvertString = (LPRECONVERTSTRING) lParam;
5690     LRESULT nRet = 0;
5691     SalSurroundingTextRequestEvent aEvt;
5692     aEvt.maText = UniString();
5693     aEvt.mnStart = aEvt.mnEnd = 0;
5694 
5695     UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_SETCOMPSTR );
5696     if( (nImeProps & SCS_CAP_SETRECONVERTSTRING) == 0 )
5697     {
5698 	// This IME does not support reconversion.
5699 	return 0;
5700     }
5701 
5702     if( !pReconvertString )
5703     {
5704 	// The first call for reconversion.
5705 	pFrame->CallCallback( SALEVENT_STARTRECONVERSION, (void*)NULL );
5706 
5707 	// Retrieve the surrounding text from the focused control.
5708 	pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTREQUEST, (void*)&aEvt );
5709 
5710 	if( aEvt.maText.Len() == 0 )
5711 	{
5712 	    return 0;
5713 	}
5714 
5715 	nRet = sizeof(RECONVERTSTRING) + (aEvt.maText.Len() + 1) * sizeof(WCHAR);
5716     }
5717     else
5718     {
5719 	// The second call for reconversion.
5720 
5721 	// Retrieve the surrounding text from the focused control.
5722 	pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTREQUEST, (void*)&aEvt );
5723 	nRet = sizeof(RECONVERTSTRING) + (aEvt.maText.Len() + 1) * sizeof(WCHAR);
5724 
5725 	pReconvertString->dwStrOffset = sizeof(RECONVERTSTRING);
5726 	pReconvertString->dwStrLen = aEvt.maText.Len();
5727 	pReconvertString->dwCompStrOffset = aEvt.mnStart * sizeof(WCHAR);
5728 	pReconvertString->dwCompStrLen = aEvt.mnEnd - aEvt.mnStart;
5729 	pReconvertString->dwTargetStrOffset = pReconvertString->dwCompStrOffset;
5730 	pReconvertString->dwTargetStrLen = pReconvertString->dwCompStrLen;
5731 
5732 	memcpy( (LPWSTR)(pReconvertString + 1), aEvt.maText.GetBuffer(), (aEvt.maText.Len() + 1) * sizeof(WCHAR) );
5733     }
5734 
5735     // just return the required size of buffer to reconvert.
5736     return nRet;
5737 }
5738 
5739 // -----------------------------------------------------------------------
5740 
5741 static LRESULT ImplHandleIMEConfirmReconvertString( HWND hWnd, LPARAM lParam )
5742 {
5743     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5744     LPRECONVERTSTRING pReconvertString = (LPRECONVERTSTRING) lParam;
5745     SalSurroundingTextRequestEvent aEvt;
5746     aEvt.maText = UniString();
5747     aEvt.mnStart = aEvt.mnEnd = 0;
5748 
5749     pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTREQUEST, (void*)&aEvt );
5750 
5751     sal_uLong nTmpStart = pReconvertString->dwCompStrOffset / sizeof(WCHAR);
5752     sal_uLong nTmpEnd = nTmpStart + pReconvertString->dwCompStrLen;
5753 
5754     if( nTmpStart != aEvt.mnStart || nTmpEnd != aEvt.mnEnd )
5755     {
5756 	SalSurroundingTextSelectionChangeEvent aSelEvt;
5757 	aSelEvt.mnStart = nTmpStart;
5758 	aSelEvt.mnEnd = nTmpEnd;
5759 
5760 	pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTSELECTIONCHANGE, (void*)&aSelEvt );
5761     }
5762 
5763     return TRUE;
5764 }
5765 
5766 #endif // WINVER >= 0x0500
5767 
5768 // -----------------------------------------------------------------------
5769 
5770 void SalTestMouseLeave()
5771 {
5772     SalData* pSalData = GetSalData();
5773 
5774     if ( pSalData->mhWantLeaveMsg && !::GetCapture() )
5775     {
5776         POINT aPt;
5777         GetCursorPos( &aPt );
5778         if ( pSalData->mhWantLeaveMsg != WindowFromPoint( aPt ) )
5779             ImplSendMessage( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, MAKELPARAM( aPt.x, aPt.y ) );
5780     }
5781 }
5782 
5783 // -----------------------------------------------------------------------
5784 
5785 static int ImplSalWheelMousePos( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ,
5786                                  LRESULT& rResult )
5787 {
5788     POINT aPt;
5789     POINT aScreenPt;
5790     aScreenPt.x = (short)LOWORD( lParam );
5791     aScreenPt.y = (short)HIWORD( lParam );
5792     // Child-Fenster suchen, welches an der entsprechenden
5793     // Position liegt
5794     HWND hChildWnd;
5795     HWND hWheelWnd = hWnd;
5796     do
5797     {
5798         hChildWnd = hWheelWnd;
5799         aPt = aScreenPt;
5800         ScreenToClient( hChildWnd, &aPt );
5801         hWheelWnd = ChildWindowFromPointEx( hChildWnd, aPt, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT );
5802     }
5803     while ( hWheelWnd && (hWheelWnd != hChildWnd) );
5804     if ( hWheelWnd && (hWheelWnd != hWnd) &&
5805          (hWheelWnd != ::GetFocus()) && IsWindowEnabled( hWheelWnd ) )
5806     {
5807         rResult = ImplSendMessage( hWheelWnd, nMsg, wParam, lParam );
5808         return FALSE;
5809     }
5810 
5811     return TRUE;
5812 }
5813 
5814 // -----------------------------------------------------------------------
5815 
5816 LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
5817 {
5818     LRESULT     nRet = 0;
5819     static int  bInWheelMsg = FALSE;
5820 	static int	bInQueryEnd = FALSE;
5821 
5822     // By WM_CRETAE we connect the frame with the window handle
5823     if ( nMsg == WM_CREATE )
5824     {
5825         // Window-Instanz am Windowhandle speichern
5826         // Can also be used for the W-Version, because the struct
5827         // to access lpCreateParams is the same structure
5828         CREATESTRUCTA* pStruct = (CREATESTRUCTA*)lParam;
5829         WinSalFrame* pFrame = (WinSalFrame*)pStruct->lpCreateParams;
5830 		if ( pFrame != 0 )
5831 		{
5832 			SetWindowPtr( hWnd, pFrame );
5833 			// HWND schon hier setzen, da schon auf den Instanzdaten
5834 			// gearbeitet werden kann, wenn Messages waehrend
5835 			// CreateWindow() gesendet werden
5836 			pFrame->mhWnd = hWnd;
5837 			pFrame->maSysData.hWnd = hWnd;
5838 		}
5839         return 0;
5840     }
5841 
5842     ImplSVData* pSVData = ImplGetSVData();
5843     // #i72707# TODO: the mbDeInit check will not be needed
5844     // once all windows that are not properly closed on exit got fixed
5845     if( pSVData->mbDeInit )
5846         return 0;
5847 
5848     if ( WM_USER_SYSTEM_WINDOW_ACTIVATED == nMsg )
5849     {
5850         if (pSVData->mpIntroWindow)
5851             pSVData->mpIntroWindow->Hide();
5852 
5853         return 0;
5854     }
5855 
5856 	bool bCheckTimers = false;
5857 
5858     switch( nMsg )
5859     {
5860         case WM_MOUSEMOVE:
5861         case WM_LBUTTONDOWN:
5862         case WM_MBUTTONDOWN:
5863         case WM_RBUTTONDOWN:
5864         case WM_LBUTTONUP:
5865         case WM_MBUTTONUP:
5866         case WM_RBUTTONUP:
5867         case WM_NCMOUSEMOVE:
5868         case SAL_MSG_MOUSELEAVE:
5869             ImplSalYieldMutexAcquireWithWait();
5870             rDef = !ImplHandleMouseMsg( hWnd, nMsg, wParam, lParam );
5871             ImplSalYieldMutexRelease();
5872             break;
5873 
5874         case WM_NCLBUTTONDOWN:
5875         case WM_NCMBUTTONDOWN:
5876         case WM_NCRBUTTONDOWN:
5877             ImplSalYieldMutexAcquireWithWait();
5878             ImplCallClosePopupsHdl( hWnd );   // close popups...
5879             ImplSalYieldMutexRelease();
5880             break;
5881 
5882         case WM_MOUSEACTIVATE:
5883             if ( LOWORD( lParam ) == HTCLIENT )
5884             {
5885                 ImplSalYieldMutexAcquireWithWait();
5886                 nRet = ImplHandleMouseActivateMsg( hWnd );
5887                 ImplSalYieldMutexRelease();
5888                 if ( nRet )
5889                 {
5890                     nRet = MA_NOACTIVATE;
5891                     rDef = FALSE;
5892                 }
5893             }
5894             break;
5895 
5896         case WM_KEYDOWN:
5897         case WM_KEYUP:
5898         case WM_DEADCHAR:
5899         case WM_CHAR:
5900         case WM_UNICHAR:    // MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0
5901         case WM_SYSKEYDOWN:
5902         case WM_SYSKEYUP:
5903         case WM_SYSCHAR:
5904             ImplSalYieldMutexAcquireWithWait();
5905             rDef = !ImplHandleKeyMsg( hWnd, nMsg, wParam, lParam, nRet );
5906             ImplSalYieldMutexRelease();
5907             break;
5908 
5909         case WM_MOUSEWHEEL:
5910             // FALLTHROUGH intended
5911         case WM_MOUSEHWHEEL:
5912             // Gegen Rekursion absichern, falls wir vom IE oder dem externen
5913             // Fenster die Message wieder zurueckbekommen
5914             if ( !bInWheelMsg )
5915             {
5916                 bInWheelMsg++;
5917                 rDef = !ImplHandleWheelMsg( hWnd, nMsg, wParam, lParam );
5918                 // Wenn wir die Message nicht ausgewertet haben, schauen wir
5919                 // noch einmal nach, ob dort ein geplugtes Fenster steht,
5920                 // welches wir dann benachrichtigen
5921                 if ( rDef )
5922                     rDef = ImplSalWheelMousePos( hWnd, nMsg, wParam, lParam, nRet );
5923                 bInWheelMsg--;
5924             }
5925             break;
5926 
5927         case WM_COMMAND:
5928             ImplSalYieldMutexAcquireWithWait();
5929             rDef = !ImplHandleCommand( hWnd, wParam, lParam );
5930             ImplSalYieldMutexRelease();
5931             break;
5932 
5933         case WM_INITMENUPOPUP:
5934             ImplSalYieldMutexAcquireWithWait();
5935             rDef = !ImplHandleMenuActivate( hWnd, wParam, lParam );
5936             ImplSalYieldMutexRelease();
5937             break;
5938 
5939         case WM_MENUSELECT:
5940             ImplSalYieldMutexAcquireWithWait();
5941             rDef = !ImplHandleMenuSelect( hWnd, wParam, lParam );
5942             ImplSalYieldMutexRelease();
5943             break;
5944 
5945         case WM_SYSCOMMAND:
5946             ImplSalYieldMutexAcquireWithWait();
5947             nRet = ImplHandleSysCommand( hWnd, wParam, lParam );
5948             ImplSalYieldMutexRelease();
5949             if ( nRet )
5950                 rDef = FALSE;
5951             break;
5952 
5953         case WM_MENUCHAR:
5954             nRet = ImplMenuChar( hWnd, wParam, lParam );
5955             if( nRet )
5956                 rDef = FALSE;
5957             break;
5958 
5959         case WM_MEASUREITEM:
5960             nRet = ImplMeasureItem(hWnd, wParam, lParam);
5961             if( nRet )
5962                 rDef = FALSE;
5963             break;
5964 
5965         case WM_DRAWITEM:
5966             nRet = ImplDrawItem(hWnd, wParam, lParam);
5967             if( nRet )
5968                 rDef = FALSE;
5969             break;
5970 
5971         case WM_MOVE:
5972         case SAL_MSG_POSTMOVE:
5973             ImplHandleMoveMsg( hWnd );
5974             rDef = FALSE;
5975             break;
5976         case WM_SIZE:
5977             ImplHandleSizeMsg( hWnd, wParam, lParam );
5978             rDef = FALSE;
5979             break;
5980         case SAL_MSG_POSTCALLSIZE:
5981             ImplCallSizeHdl( hWnd );
5982             rDef = FALSE;
5983             break;
5984 
5985         case WM_GETMINMAXINFO:
5986             if ( ImplHandleMinMax( hWnd, lParam ) )
5987                 rDef = FALSE;
5988             break;
5989 
5990         case WM_ERASEBKGND:
5991             nRet = 1;
5992             rDef = FALSE;
5993             break;
5994         case WM_PAINT:
5995             bCheckTimers = ImplHandlePaintMsg( hWnd );
5996             rDef = FALSE;
5997             break;
5998         case SAL_MSG_POSTPAINT:
5999             ImplHandlePaintMsg2( hWnd, (RECT*)wParam );
6000 			bCheckTimers = true;
6001             rDef = FALSE;
6002             break;
6003 
6004         case SAL_MSG_FORCEPALETTE:
6005             ImplHandleForcePalette( hWnd );
6006             rDef = FALSE;
6007             break;
6008 
6009         case WM_QUERYNEWPALETTE:
6010         case SAL_MSG_POSTQUERYNEWPAL:
6011             nRet = ImplHandlePalette( TRUE, hWnd, nMsg, wParam, lParam, rDef );
6012             break;
6013 
6014         case WM_ACTIVATE:
6015             // Wenn wir aktiviert werden, dann wollen wir auch unsere
6016             // Palette setzen. Wir machen dieses in Activate,
6017             // damit andere externe Child-Fenster auch unsere Palette
6018             // ueberschreiben koennen. So wird unsere jedenfalls nur einmal
6019             // gesetzt und nicht immer rekursiv, da an allen anderen Stellen
6020             // diese nur als Background-Palette gesetzt wird
6021             if ( LOWORD( wParam ) != WA_INACTIVE )
6022                 ImplSendMessage( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 );
6023             break;
6024 
6025         case WM_ENABLE:
6026             // #95133# a system dialog is opened/closed, using our app window as parent
6027             {
6028                 WinSalFrame* pFrame = GetWindowPtr( hWnd );
6029                 Window *pWin = NULL;
6030 	            if( pFrame )
6031 	                pWin = pFrame->GetWindow();
6032 
6033                 if( !wParam )
6034                 {
6035                     ImplSVData* pSVData = ImplGetSVData();
6036                     pSVData->maAppData.mnModalMode++;
6037 
6038                     // #106431#, hide SplashScreen
6039                     if( pSVData->mpIntroWindow )
6040                         pSVData->mpIntroWindow->Hide();
6041 
6042                     if( pWin )
6043                     {
6044                         pWin->EnableInput( FALSE, TRUE, TRUE, NULL );
6045                         pWin->ImplIncModalCount();  // #106303# support frame based modal count
6046                     }
6047                 }
6048                 else
6049                 {
6050                     ImplGetSVData()->maAppData.mnModalMode--;
6051                     if( pWin )
6052                     {
6053                         pWin->EnableInput( TRUE, TRUE, TRUE, NULL );
6054                         pWin->ImplDecModalCount();  // #106303# support frame based modal count
6055                     }
6056                 }
6057             }
6058             break;
6059 
6060         case WM_KILLFOCUS:
6061             DestroyCaret();
6062         case WM_SETFOCUS:
6063         case SAL_MSG_POSTFOCUS:
6064             ImplHandleFocusMsg( hWnd );
6065             rDef = FALSE;
6066             break;
6067 
6068         case WM_CLOSE:
6069             ImplHandleCloseMsg( hWnd );
6070             rDef = FALSE;
6071             break;
6072 
6073         case WM_QUERYENDSESSION:
6074 			if( !bInQueryEnd )
6075 			{
6076 				// handle queryendsession only once
6077 				bInQueryEnd = TRUE;
6078 				nRet = !ImplHandleShutDownMsg( hWnd );
6079 				rDef = FALSE;
6080 
6081 				// Issue #16314#: ImplHandleShutDownMsg causes a PostMessage in case of allowing shutdown.
6082 				// This posted message was never processed and cause Windows XP to hang after log off
6083 				// if there are multiple sessions and the current session wasn't the first one started.
6084 				// So if shutdown is allowed we assume that a post message was done and retrieve all
6085 				// messages in the message queue and dispatch them before we return control to the system.
6086 
6087 				if ( nRet )
6088 				{
6089 					MSG	msg;
6090 
6091 					while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
6092 					{
6093 						DispatchMessage( &msg );
6094 					}
6095 				}
6096 			}
6097 			else
6098 			{
6099 				ImplSalYieldMutexAcquireWithWait();
6100 				ImplSalYieldMutexRelease();
6101 				rDef = TRUE;
6102 			}
6103             break;
6104 
6105 		case WM_ENDSESSION:
6106 			if( !wParam )
6107 				bInQueryEnd = FALSE; // no shutdown: allow query again
6108 			nRet = FALSE;
6109 			rDef = FALSE;
6110 			break;
6111 
6112         case WM_DISPLAYCHANGE:
6113         case WM_SETTINGCHANGE:
6114         case WM_DEVMODECHANGE:
6115         case WM_FONTCHANGE:
6116         case WM_SYSCOLORCHANGE:
6117         case WM_TIMECHANGE:
6118             ImplHandleSettingsChangeMsg( hWnd, nMsg, wParam, lParam );
6119             break;
6120 
6121         case WM_THEMECHANGED:
6122             GetSalData()->mbThemeChanged = TRUE;
6123             break;
6124 
6125         case SAL_MSG_USEREVENT:
6126             ImplHandleUserEvent( hWnd, lParam );
6127             rDef = FALSE;
6128             break;
6129 
6130         case SAL_MSG_CAPTUREMOUSE:
6131             SetCapture( hWnd );
6132             rDef = FALSE;
6133             break;
6134         case SAL_MSG_RELEASEMOUSE:
6135             if ( ::GetCapture() == hWnd )
6136                 ReleaseCapture();
6137             rDef = FALSE;
6138             break;
6139         case SAL_MSG_TOTOP:
6140             ImplSalToTop( hWnd, (sal_uInt16)wParam );
6141             rDef = FALSE;
6142             break;
6143         case SAL_MSG_SHOW:
6144             ImplSalShow( hWnd, (sal_Bool)wParam, (sal_Bool)lParam );
6145             rDef = FALSE;
6146             break;
6147         case SAL_MSG_SETINPUTCONTEXT:
6148             ImplSalFrameSetInputContext( hWnd, (const SalInputContext*)(void*)lParam );
6149             rDef = FALSE;
6150             break;
6151         case SAL_MSG_ENDEXTTEXTINPUT:
6152             ImplSalFrameEndExtTextInput( hWnd, (sal_uInt16)(sal_uLong)(void*)wParam );
6153             rDef = FALSE;
6154             break;
6155 
6156         case WM_INPUTLANGCHANGE:
6157             ImplHandleInputLangChange( hWnd, wParam, lParam );
6158             break;
6159 
6160         case WM_IME_CHAR:
6161             // #103487#, some IMEs (eg, those that do not work onspot)
6162             //           may send WM_IME_CHAR instead of WM_IME_COMPOSITION
6163             // we just handle it like a WM_CHAR message - seems to work fine
6164             ImplSalYieldMutexAcquireWithWait();
6165             rDef = !ImplHandleKeyMsg( hWnd, WM_CHAR, wParam, lParam, nRet );
6166             ImplSalYieldMutexRelease();
6167             break;
6168 
6169          case WM_IME_STARTCOMPOSITION:
6170             rDef = ImplHandleIMEStartComposition( hWnd );
6171             break;
6172 
6173         case WM_IME_COMPOSITION:
6174             rDef = ImplHandleIMEComposition( hWnd, lParam );
6175             break;
6176 
6177         case WM_IME_ENDCOMPOSITION:
6178             rDef = ImplHandleIMEEndComposition( hWnd );
6179             break;
6180 
6181         case WM_IME_NOTIFY:
6182             ImplHandleIMENotify( hWnd, wParam );
6183             break;
6184         case WM_APPCOMMAND:
6185             if( ImplHandleAppCommand( hWnd, lParam ) )
6186             {
6187                 rDef = false;
6188                 nRet = 1;
6189             }
6190             break;
6191 #if WINVER >= 0x0500
6192         case WM_IME_REQUEST:
6193             if ( PtrToInt( wParam ) == IMR_RECONVERTSTRING )
6194             {
6195                 nRet = ImplHandleIMEReconvertString( hWnd, lParam );
6196                 rDef = FALSE;
6197             }
6198 	    else if( PtrToInt( wParam ) == IMR_CONFIRMRECONVERTSTRING )
6199 	    {
6200 		nRet = ImplHandleIMEConfirmReconvertString( hWnd, lParam );
6201 		rDef = FALSE;
6202 	    }
6203             break;
6204 #endif // WINVER >= 0x0500
6205     }
6206 
6207     // WheelMouse-Message abfangen
6208     if ( rDef && (nMsg == aSalShlData.mnWheelMsgId) && aSalShlData.mnWheelMsgId )
6209     {
6210         // Gegen Rekursion absichern, falls wir vom IE oder dem externen
6211         // Fenster die Message wieder zurueckbekommen
6212         if ( !bInWheelMsg )
6213         {
6214             bInWheelMsg++;
6215             // Zuerst wollen wir die Message dispatchen und dann darf auch
6216             // das SystemWindow drankommen
6217             WORD nKeyState = 0;
6218             if ( GetKeyState( VK_SHIFT ) & 0x8000 )
6219                 nKeyState |= MK_SHIFT;
6220             if ( GetKeyState( VK_CONTROL ) & 0x8000 )
6221                 nKeyState |= MK_CONTROL;
6222             // Mutex handling is inside from this call
6223             rDef = !ImplHandleWheelMsg( hWnd,
6224                                         WM_MOUSEWHEEL,
6225                                         MAKEWPARAM( nKeyState, (WORD)wParam ),
6226                                         lParam );
6227             if ( rDef )
6228             {
6229                 HWND hWheelWnd = ::GetFocus();
6230                 if ( hWheelWnd && (hWheelWnd != hWnd) )
6231                 {
6232                     nRet = ImplSendMessage( hWheelWnd, nMsg, wParam, lParam );
6233                     rDef = FALSE;
6234                 }
6235                 else
6236                     rDef = ImplSalWheelMousePos( hWnd, nMsg, wParam, lParam, nRet );
6237             }
6238             bInWheelMsg--;
6239         }
6240     }
6241 
6242 	if( bCheckTimers )
6243 	{
6244 		SalData* pSalData = GetSalData();
6245 		if( pSalData->mnNextTimerTime )
6246 		{
6247 			DWORD nCurTime = GetTickCount();
6248 			if( pSalData->mnNextTimerTime < nCurTime )
6249 			{
6250 				MSG aMsg;
6251 				if( ! ImplPeekMessage( &aMsg, 0, WM_PAINT, WM_PAINT, PM_NOREMOVE | PM_NOYIELD ) )
6252 					ImplPostMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_POSTTIMER, 0, nCurTime );
6253 			}
6254 		}
6255 	}
6256 
6257     return nRet;
6258 }
6259 
6260 LRESULT CALLBACK SalFrameWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
6261 {
6262     int bDef = TRUE;
6263     LRESULT nRet = 0;
6264 #ifdef __MINGW32__
6265     jmp_buf jmpbuf;
6266     __SEHandler han;
6267     if (__builtin_setjmp(jmpbuf) == 0)
6268     {
6269         han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
6270 #else
6271     __try
6272     {
6273 #endif
6274         nRet = SalFrameWndProc( hWnd, nMsg, wParam, lParam, bDef );
6275     }
6276 #ifdef __MINGW32__
6277     han.Reset();
6278 #else
6279     __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
6280     {
6281     }
6282 #endif
6283     if ( bDef )
6284         nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
6285     return nRet;
6286 }
6287 
6288 LRESULT CALLBACK SalFrameWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
6289 {
6290     int bDef = TRUE;
6291     LRESULT nRet = 0;
6292 #ifdef __MINGW32__
6293     jmp_buf jmpbuf;
6294     __SEHandler han;
6295     if (__builtin_setjmp(jmpbuf) == 0)
6296     {
6297         han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
6298 #else
6299     __try
6300     {
6301 #endif
6302         nRet = SalFrameWndProc( hWnd, nMsg, wParam, lParam, bDef );
6303     }
6304 #ifdef __MINGW32__
6305     han.Reset();
6306 #else
6307     __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
6308     {
6309     }
6310 #endif
6311 
6312     if ( bDef )
6313         nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
6314     return nRet;
6315 }
6316 
6317 // -----------------------------------------------------------------------
6318 
6319 sal_Bool ImplHandleGlobalMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT& rlResult )
6320 {
6321 	// handle all messages concerning all frames so they get processed only once
6322     // Must work for Unicode and none Unicode
6323 	sal_Bool bResult = FALSE;
6324     if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) )
6325     {
6326         int bDef = TRUE;
6327         rlResult = ImplHandlePalette( FALSE, hWnd, nMsg, wParam, lParam, bDef );
6328         bResult = (bDef != 0);
6329     }
6330 	else if( nMsg == WM_DISPLAYCHANGE )
6331 	{
6332 		WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem());
6333 		if( pSys )
6334 			pSys->clearMonitors();
6335 		bResult = (pSys != NULL);
6336 	}
6337 	return bResult;
6338 }
6339 
6340 // -----------------------------------------------------------------------
6341 
6342 sal_Bool ImplWriteLastError( DWORD lastError, const char *szApiCall )
6343 {
6344     static int first=1;
6345     // if VCL_LOGFILE_ENABLED is set, Win32 API error messages can be written
6346     // to %TMP%/vcl.log or %TEMP%/vcl.log
6347     static char *logEnabled = getenv("VCL_LOGFILE_ENABLED");
6348     if( logEnabled )
6349     {
6350         sal_Bool bSuccess = FALSE;
6351         static char *szTmp = getenv("TMP");
6352         if( !szTmp || !*szTmp )
6353             szTmp = getenv("TEMP");
6354         if( szTmp && *szTmp )
6355         {
6356             char fname[5000];
6357             strcpy( fname, szTmp );
6358             if( fname[strlen(fname) - 1] != '\\' )
6359                 strcat( fname, "\\");
6360             strcat( fname, "vcl.log" );
6361             FILE *fp = fopen( fname, "a" ); // always append
6362             if( fp )
6363             {
6364                 if( first )
6365                 {
6366                     first = 0;
6367                     fprintf( fp, "Process ID: %d (0x%x)\n", GetCurrentProcessId(), GetCurrentProcessId() );
6368                 }
6369                 time_t aclock;
6370                 time( &aclock );                           // Get time in seconds
6371                 struct tm *newtime = localtime( &aclock ); // Convert time to struct tm form
6372                 fprintf( fp, asctime( newtime ) );         // print time stamp
6373 
6374                 fprintf( fp, "%s returned %u (0x%x)\n", szApiCall, lastError, lastError );
6375                 bSuccess = TRUE;    // may be FormatMessage fails but we wrote at least the error code
6376 
6377                 LPVOID lpMsgBuf;
6378                 if (FormatMessageA(
6379                     FORMAT_MESSAGE_ALLOCATE_BUFFER |
6380                     FORMAT_MESSAGE_FROM_SYSTEM |
6381                     FORMAT_MESSAGE_IGNORE_INSERTS,
6382                     NULL,
6383                     lastError,
6384                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
6385                     (LPSTR) &lpMsgBuf,
6386                     0,
6387                     NULL ))
6388                 {
6389                     fprintf( fp, " %s\n", (LPSTR)lpMsgBuf );
6390                     LocalFree( lpMsgBuf );
6391                 }
6392 
6393                 fclose( fp );
6394             }
6395         }
6396         return bSuccess;
6397     }
6398     else
6399         return TRUE;
6400 }
6401 
6402 // -----------------------------------------------------------------------
6403 
6404