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