xref: /trunk/main/vcl/win/source/window/salframe.cxx (revision 891d3b9af397d8ae32ed0c41f31c113b1aa7c5bc)
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_AUTOSCROLL_N },       // POINTER_AUTOSCROLL_N
2333     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_S },       // POINTER_AUTOSCROLL_S
2334     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_W },       // POINTER_AUTOSCROLL_W
2335     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_E },       // POINTER_AUTOSCROLL_E
2336     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NW },      // POINTER_AUTOSCROLL_NW
2337     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NE },      // POINTER_AUTOSCROLL_NE
2338     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SW },      // POINTER_AUTOSCROLL_SW
2339     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SE },      // POINTER_AUTOSCROLL_SE
2340     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NS },      // POINTER_AUTOSCROLL_NS
2341     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_WE },      // POINTER_AUTOSCROLL_WE
2342     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NSWE },    // POINTER_AUTOSCROLL_NSWE
2343     { 0, 0, SAL_RESID_POINTER_AIRBRUSH },           // POINTER_AIRBRUSH
2344     { 0, 0, SAL_RESID_POINTER_TEXT_VERTICAL },      // POINTER_TEXT_VERTICAL
2345     { 0, 0, SAL_RESID_POINTER_PIVOT_DELETE },       // POINTER_PIVOT_DELETE
2346 
2347     // --> FME 2004-07-30 #i32329# Enhanced table selection
2348     { 0, 0, SAL_RESID_POINTER_TAB_SELECT_S },       // POINTER_TAB_SELECT_S
2349     { 0, 0, SAL_RESID_POINTER_TAB_SELECT_E },       // POINTER_TAB_SELECT_E
2350     { 0, 0, SAL_RESID_POINTER_TAB_SELECT_SE },      // POINTER_TAB_SELECT_SE
2351     { 0, 0, SAL_RESID_POINTER_TAB_SELECT_W },       // POINTER_TAB_SELECT_W
2352     { 0, 0, SAL_RESID_POINTER_TAB_SELECT_SW },      // POINTER_TAB_SELECT_SW
2353     // <--
2354 
2355     // --> FME 2004-08-16 #i20119# Paintbrush tool
2356     { 0, 0, SAL_RESID_POINTER_PAINTBRUSH }          // POINTER_PAINTBRUSH
2357     // <--
2358 
2359     };
2360 
2361 #if POINTER_COUNT != 92
2362 #error New Pointer must be defined!
2363 #endif
2364 
2365     // Mousepointer loaded ?
2366     if ( !aImplPtrTab[ePointerStyle].mhCursor )
2367     {
2368         if ( aImplPtrTab[ePointerStyle].mnOwnId )
2369             aImplPtrTab[ePointerStyle].mhCursor = ImplLoadSalCursor( aImplPtrTab[ePointerStyle].mnOwnId );
2370         else
2371             aImplPtrTab[ePointerStyle].mhCursor = LoadCursor( 0, aImplPtrTab[ePointerStyle].mnSysId );
2372     }
2373 
2374     // Unterscheidet sich der Mauspointer, dann den neuen setzen
2375     if ( mhCursor != aImplPtrTab[ePointerStyle].mhCursor )
2376     {
2377         mhCursor = aImplPtrTab[ePointerStyle].mhCursor;
2378         SetCursor( mhCursor );
2379     }
2380 }
2381 
2382 // -----------------------------------------------------------------------
2383 
CaptureMouse(sal_Bool bCapture)2384 void WinSalFrame::CaptureMouse( sal_Bool bCapture )
2385 {
2386     // Send this Message to the window, because CaptureMouse() only work
2387     // in the thread of the window, which has create this window
2388     int nMsg;
2389     if ( bCapture )
2390         nMsg = SAL_MSG_CAPTUREMOUSE;
2391     else
2392         nMsg = SAL_MSG_RELEASEMOUSE;
2393     ImplSendMessage( mhWnd, nMsg, 0, 0 );
2394 }
2395 
2396 // -----------------------------------------------------------------------
2397 
SetPointerPos(long nX,long nY)2398 void WinSalFrame::SetPointerPos( long nX, long nY )
2399 {
2400     POINT aPt;
2401     aPt.x = (int)nX;
2402     aPt.y = (int)nY;
2403     ClientToScreen( mhWnd, &aPt );
2404     SetCursorPos( aPt.x, aPt.y );
2405 }
2406 
2407 // -----------------------------------------------------------------------
2408 
Flush()2409 void WinSalFrame::Flush()
2410 {
2411     GdiFlush();
2412 }
2413 
2414 // -----------------------------------------------------------------------
2415 
Sync()2416 void WinSalFrame::Sync()
2417 {
2418     GdiFlush();
2419 }
2420 
2421 // -----------------------------------------------------------------------
2422 
ImplSalFrameSetInputContext(HWND hWnd,const SalInputContext * pContext)2423 static void ImplSalFrameSetInputContext( HWND hWnd, const SalInputContext* pContext )
2424 {
2425     WinSalFrame*   pFrame = GetWindowPtr( hWnd );
2426     sal_Bool        bIME = (pContext->mnOptions & SAL_INPUTCONTEXT_TEXT) != 0;
2427     if ( bIME )
2428     {
2429         if ( !pFrame->mbIME )
2430         {
2431             pFrame->mbIME = TRUE;
2432 
2433             if ( pFrame->mhDefIMEContext )
2434             {
2435                 ImmAssociateContext( pFrame->mhWnd, pFrame->mhDefIMEContext );
2436                 UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_PROPERTY );
2437                 pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
2438                 pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
2439                 pFrame->mbHandleIME = !pFrame->mbSpezIME;
2440             }
2441         }
2442 
2443         // When the application can't handle IME messages, then the
2444         // System should handle the IME handling
2445         if ( !(pContext->mnOptions & SAL_INPUTCONTEXT_EXTTEXTINPUT) )
2446             pFrame->mbHandleIME = FALSE;
2447 
2448         // Set the Font for IME Handling
2449         if ( pContext->mpFont )
2450         {
2451             HIMC hIMC = ImmGetContext( pFrame->mhWnd );
2452             if ( hIMC )
2453             {
2454                 LOGFONTW aLogFont;
2455                 HDC hDC = GetDC( pFrame->mhWnd );
2456                 // In case of vertical writing, always append a '@' to the
2457                 // Windows font name, not only if such a Windows font really is
2458                 // available (bTestVerticalAvail == false in the below call):
2459                 // The Windows IME's candidates window seems to always use a
2460                 // font that has all necessary glyphs, not necessarily the one
2461                 // specified by this font name; but it seems to decide whether
2462                 // to use that font's horizontal or vertical variant based on a
2463                 // '@' in front of this font name.
2464                 ImplGetLogFontFromFontSelect( hDC, pContext->mpFont, aLogFont,
2465                                               false );
2466                 ReleaseDC( pFrame->mhWnd, hDC );
2467                 ImmSetCompositionFontW( hIMC, &aLogFont );
2468                 ImmReleaseContext( pFrame->mhWnd, hIMC );
2469             }
2470         }
2471     }
2472     else
2473     {
2474         if ( pFrame->mbIME )
2475         {
2476             pFrame->mbIME = FALSE;
2477             pFrame->mbHandleIME = FALSE;
2478             ImmAssociateContext( pFrame->mhWnd, 0 );
2479         }
2480     }
2481 }
2482 
2483 // -----------------------------------------------------------------------
2484 
SetInputContext(SalInputContext * pContext)2485 void WinSalFrame::SetInputContext( SalInputContext* pContext )
2486 {
2487     // Must be called in the main thread!
2488     ImplSendMessage( mhWnd, SAL_MSG_SETINPUTCONTEXT, 0, (LPARAM)(void*)pContext );
2489 }
2490 
2491 // -----------------------------------------------------------------------
2492 
ImplSalFrameEndExtTextInput(HWND hWnd,sal_uInt16 nFlags)2493 static void ImplSalFrameEndExtTextInput( HWND hWnd, sal_uInt16 nFlags )
2494 {
2495     HIMC hIMC = ImmGetContext( hWnd );
2496     if ( hIMC )
2497     {
2498         DWORD nIndex;
2499         if ( nFlags & SAL_FRAME_ENDEXTTEXTINPUT_COMPLETE )
2500             nIndex = CPS_COMPLETE;
2501         else
2502             nIndex = CPS_CANCEL;
2503 
2504         ImmNotifyIME( hIMC, NI_COMPOSITIONSTR, nIndex, 0 );
2505         ImmReleaseContext( hWnd, hIMC );
2506     }
2507 }
2508 
2509 // -----------------------------------------------------------------------
2510 
EndExtTextInput(sal_uInt16 nFlags)2511 void WinSalFrame::EndExtTextInput( sal_uInt16 nFlags )
2512 {
2513     // Must be called in the main thread!
2514     ImplSendMessage( mhWnd, SAL_MSG_ENDEXTTEXTINPUT, (WPARAM)nFlags, 0 );
2515 }
2516 
2517 // -----------------------------------------------------------------------
2518 
ImplGetKeyNameText(LONG lParam,sal_Unicode * pBuf,UINT & rCount,UINT nMaxSize,const sal_Char * pReplace)2519 static void ImplGetKeyNameText( LONG lParam, sal_Unicode* pBuf,
2520                                 UINT& rCount, UINT nMaxSize,
2521                                 const sal_Char* pReplace )
2522 {
2523     DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "WinSalFrame::ImplGetKeyNameTextW(): WCHAR != sal_Unicode" );
2524 
2525     static const int nMaxKeyLen = 350;
2526     WCHAR aKeyBuf[ nMaxKeyLen ];
2527     int nKeyLen = 0;
2528     if ( lParam )
2529     {
2530         if ( true/*aSalShlData.mbWNT*/ )
2531         {
2532             nKeyLen = GetKeyNameTextW( lParam, aKeyBuf, nMaxKeyLen );
2533             DBG_ASSERT( nKeyLen <= nMaxKeyLen, "Invalid key name length!" );
2534             if( nKeyLen > nMaxKeyLen )
2535                 nKeyLen = 0;
2536             else if( nKeyLen > 0 )
2537             {
2538                 // Capitalize just the first letter of key names
2539                 CharLowerBuffW( aKeyBuf, nKeyLen );
2540 
2541                 bool bUpper = true;
2542                 for( WCHAR *pW=aKeyBuf, *pE=pW+nKeyLen; pW < pE; ++pW )
2543                 {
2544                     if( bUpper )
2545                         CharUpperBuffW( pW, 1 );
2546                     bUpper = (*pW=='+') || (*pW=='-') || (*pW==' ') || (*pW=='.');
2547                 }
2548             }
2549         }
2550     }
2551 
2552     if ( (nKeyLen > 0) || pReplace )
2553     {
2554         if( (rCount > 0) && (rCount < nMaxSize) )
2555         {
2556             pBuf[rCount] = '+';
2557             rCount++;
2558         }
2559 
2560         if( nKeyLen > 0 )
2561         {
2562             if( nKeyLen + rCount > nMaxSize )
2563                 nKeyLen = nMaxSize - rCount;
2564             memcpy( pBuf+rCount, aKeyBuf, nKeyLen*sizeof( sal_Unicode ) );
2565             rCount += nKeyLen;
2566         }
2567         else // fall back to provided default name
2568         {
2569             while( *pReplace && (rCount < nMaxSize) )
2570             {
2571                 pBuf[rCount] = *pReplace;
2572                 rCount++;
2573                 pReplace++;
2574             }
2575         }
2576     }
2577     else
2578         rCount = 0;
2579 }
2580 
2581 // -----------------------------------------------------------------------
2582 
GetKeyName(sal_uInt16 nKeyCode)2583 XubString WinSalFrame::GetKeyName( sal_uInt16 nKeyCode )
2584 {
2585     static const int nMaxKeyLen = 350;
2586     sal_Unicode aKeyBuf[ nMaxKeyLen ];
2587     UINT        nKeyBufLen = 0;
2588     UINT        nSysCode = 0;
2589 
2590     if ( nKeyCode & KEY_MOD1 )
2591     {
2592         nSysCode = MapVirtualKey( VK_CONTROL, 0 );
2593         nSysCode = (nSysCode << 16) | (((sal_uLong)1) << 25);
2594         ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Ctrl" );
2595     }
2596 
2597     if ( nKeyCode & KEY_MOD2 )
2598     {
2599         nSysCode = MapVirtualKey( VK_MENU, 0 );
2600         nSysCode = (nSysCode << 16) | (((sal_uLong)1) << 25);
2601         ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Alt" );
2602     }
2603 
2604     if ( nKeyCode & KEY_SHIFT )
2605     {
2606         nSysCode = MapVirtualKey( VK_SHIFT, 0 );
2607         nSysCode = (nSysCode << 16) | (((sal_uLong)1) << 25);
2608         ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Shift" );
2609     }
2610 
2611     sal_uInt16      nCode = nKeyCode & 0x0FFF;
2612     sal_uLong       nSysCode2 = 0;
2613     sal_Char*   pReplace = NULL;
2614     sal_Unicode cSVCode = 0;
2615     sal_Char    aFBuf[4];
2616     nSysCode = 0;
2617 
2618     if ( (nCode >= KEY_0) && (nCode <= KEY_9) )
2619         cSVCode = '0' + (nCode - KEY_0);
2620     else if ( (nCode >= KEY_A) && (nCode <= KEY_Z) )
2621         cSVCode = 'A' + (nCode - KEY_A);
2622     else if ( (nCode >= KEY_F1) && (nCode <= KEY_F26) )
2623     {
2624         nSysCode = VK_F1 + (nCode - KEY_F1);
2625         aFBuf[0] = 'F';
2626         if ( (nCode >= KEY_F1) && (nCode <= KEY_F9) )
2627         {
2628             aFBuf[1] = sal::static_int_cast<sal_Char>('1' + (nCode - KEY_F1));
2629             aFBuf[2] = 0;
2630         }
2631         else if ( (nCode >= KEY_F10) && (nCode <= KEY_F19) )
2632         {
2633             aFBuf[1] = '1';
2634             aFBuf[2] = sal::static_int_cast<sal_Char>('0' + (nCode - KEY_F10));
2635             aFBuf[3] = 0;
2636         }
2637         else
2638         {
2639             aFBuf[1] = '2';
2640             aFBuf[2] = sal::static_int_cast<sal_Char>('0' + (nCode - KEY_F20));
2641             aFBuf[3] = 0;
2642         }
2643         pReplace = aFBuf;
2644     }
2645     else
2646     {
2647         switch ( nCode )
2648         {
2649             case KEY_DOWN:
2650                 nSysCode = VK_DOWN;
2651                 nSysCode2 = (((sal_uLong)1) << 24);
2652                 pReplace = "Down";
2653                 break;
2654             case KEY_UP:
2655                 nSysCode = VK_UP;
2656                 nSysCode2 = (((sal_uLong)1) << 24);
2657                 pReplace = "Up";
2658                 break;
2659             case KEY_LEFT:
2660                 nSysCode = VK_LEFT;
2661                 nSysCode2 = (((sal_uLong)1) << 24);
2662                 pReplace = "Left";
2663                 break;
2664             case KEY_RIGHT:
2665                 nSysCode = VK_RIGHT;
2666                 nSysCode2 = (((sal_uLong)1) << 24);
2667                 pReplace = "Right";
2668                 break;
2669             case KEY_HOME:
2670                 nSysCode = VK_HOME;
2671                 nSysCode2 = (((sal_uLong)1) << 24);
2672                 pReplace = "Home";
2673                 break;
2674             case KEY_END:
2675                 nSysCode = VK_END;
2676                 nSysCode2 = (((sal_uLong)1) << 24);
2677                 pReplace = "End";
2678                 break;
2679             case KEY_PAGEUP:
2680                 nSysCode = VK_PRIOR;
2681                 nSysCode2 = (((sal_uLong)1) << 24);
2682                 pReplace = "Page Up";
2683                 break;
2684             case KEY_PAGEDOWN:
2685                 nSysCode = VK_NEXT;
2686                 nSysCode2 = (((sal_uLong)1) << 24);
2687                 pReplace = "Page Down";
2688                 break;
2689             case KEY_RETURN:
2690                 nSysCode = VK_RETURN;
2691                 pReplace = "Enter";
2692                 break;
2693             case KEY_ESCAPE:
2694                 nSysCode = VK_ESCAPE;
2695                 pReplace = "Escape";
2696                 break;
2697             case KEY_TAB:
2698                 nSysCode = VK_TAB;
2699                 pReplace = "Tab";
2700                 break;
2701             case KEY_BACKSPACE:
2702                 nSysCode = VK_BACK;
2703                 pReplace = "Backspace";
2704                 break;
2705             case KEY_SPACE:
2706                 nSysCode = VK_SPACE;
2707                 pReplace = "Space";
2708                 break;
2709             case KEY_INSERT:
2710                 nSysCode = VK_INSERT;
2711                 nSysCode2 = (((sal_uLong)1) << 24);
2712                 pReplace = "Insert";
2713                 break;
2714             case KEY_DELETE:
2715                 nSysCode = VK_DELETE;
2716                 nSysCode2 = (((sal_uLong)1) << 24);
2717                 pReplace = "Delete";
2718                 break;
2719 
2720             case KEY_ADD:
2721                 cSVCode  = '+';
2722                 break;
2723             case KEY_SUBTRACT:
2724                 cSVCode  = '-';
2725                 break;
2726             case KEY_MULTIPLY:
2727                 cSVCode  = '*';
2728                 break;
2729             case KEY_DIVIDE:
2730                 cSVCode  = '/';
2731                 break;
2732             case KEY_POINT:
2733                 cSVCode  = '.';
2734                 break;
2735             case KEY_COMMA:
2736                 cSVCode  = ',';
2737                 break;
2738             case KEY_LESS:
2739                 cSVCode  = '<';
2740                 break;
2741             case KEY_GREATER:
2742                 cSVCode  = '>';
2743                 break;
2744             case KEY_EQUAL:
2745                 cSVCode  = '=';
2746                 break;
2747         }
2748     }
2749 
2750     if ( nSysCode )
2751     {
2752         nSysCode = MapVirtualKey( (UINT)nSysCode, 0 );
2753         if ( nSysCode )
2754             nSysCode = (nSysCode << 16) | nSysCode2;
2755         ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, pReplace );
2756     }
2757     else
2758     {
2759         if ( cSVCode )
2760         {
2761             if ( nKeyBufLen > 0 )
2762                 aKeyBuf[ nKeyBufLen++ ] = '+';
2763             if( nKeyBufLen < nMaxKeyLen )
2764                 aKeyBuf[ nKeyBufLen++ ] = cSVCode;
2765         }
2766     }
2767 
2768     if( !nKeyBufLen )
2769         return XubString();
2770 
2771     return XubString( aKeyBuf, sal::static_int_cast< sal_uInt16 >(nKeyBufLen) );
2772 }
2773 
2774 // -----------------------------------------------------------------------
2775 
GetSymbolKeyName(const XubString &,sal_uInt16 nKeyCode)2776 XubString WinSalFrame::GetSymbolKeyName( const XubString&, sal_uInt16 nKeyCode )
2777 {
2778     return GetKeyName( nKeyCode );
2779 }
2780 
2781 // -----------------------------------------------------------------------
2782 
ImplWinColorToSal(COLORREF nColor)2783 inline Color ImplWinColorToSal( COLORREF nColor )
2784 {
2785     return Color( GetRValue( nColor ), GetGValue( nColor ), GetBValue( nColor ) );
2786 }
2787 
2788 // -----------------------------------------------------------------------
2789 
ImplSalUpdateStyleFontA(HDC hDC,const LOGFONTA & rLogFont,Font & rFont)2790 static void ImplSalUpdateStyleFontA( HDC hDC, const LOGFONTA& rLogFont, Font& rFont )
2791 {
2792     ImplSalLogFontToFontA( hDC, rLogFont, rFont );
2793 
2794     // On Windows 9x, Windows NT we get sometimes very small sizes
2795     // (for example for the small Caption height).
2796     // So if it is MS Sans Serif, a none scalable font we use
2797     // 8 Point as the minimum control height, in all other cases
2798     // 6 Point is the smallest one
2799     if ( rFont.GetHeight() < 8 )
2800     {
2801         if ( rtl_str_compareIgnoreAsciiCase( rLogFont.lfFaceName, "MS Sans Serif" ) == 0 )
2802             rFont.SetHeight( 8 );
2803         else if ( rFont.GetHeight() < 6 )
2804             rFont.SetHeight( 6 );
2805     }
2806 }
2807 
2808 // -----------------------------------------------------------------------
2809 
ImplSalUpdateStyleFontW(HDC hDC,const LOGFONTW & rLogFont,Font & rFont)2810 static void ImplSalUpdateStyleFontW( HDC hDC, const LOGFONTW& rLogFont, Font& rFont )
2811 {
2812     ImplSalLogFontToFontW( hDC, rLogFont, rFont );
2813 
2814     // On Windows 9x, Windows NT we get sometimes very small sizes
2815     // (for example for the small Caption height).
2816     // So if it is MS Sans Serif, a none scalable font we use
2817     // 8 Point as the minimum control height, in all other cases
2818     // 6 Point is the smallest one
2819     if ( rFont.GetHeight() < 8 )
2820     {
2821         if ( rtl_ustr_compareIgnoreAsciiCase( reinterpret_cast<const sal_Unicode*>(rLogFont.lfFaceName), reinterpret_cast<const sal_Unicode*>(L"MS Sans Serif") ) == 0 )
2822             rFont.SetHeight( 8 );
2823         else if ( rFont.GetHeight() < 6 )
2824             rFont.SetHeight( 6 );
2825     }
2826 }
2827 
2828 // -----------------------------------------------------------------------
2829 
ImplA2I(const BYTE * pStr)2830 static long ImplA2I( const BYTE* pStr )
2831 {
2832     long    n = 0;
2833     int     nSign = 1;
2834 
2835     if ( *pStr == '-' )
2836     {
2837         nSign = -1;
2838         pStr++;
2839     }
2840 
2841     while( (*pStr >= 48) && (*pStr <= 57) )
2842     {
2843         n *= 10;
2844         n += ((*pStr) - 48);
2845         pStr++;
2846     }
2847 
2848     n *= nSign;
2849 
2850     return n;
2851 }
2852 
2853 // -----------------------------------------------------------------------
backwardCompatibleDwmIsCompositionEnabled(BOOL * pOut)2854 static HRESULT WINAPI backwardCompatibleDwmIsCompositionEnabled( BOOL* pOut )
2855 {
2856     *pOut = FALSE;
2857     return S_OK;
2858 }
2859 
ImplDwmIsCompositionEnabled()2860 static BOOL ImplDwmIsCompositionEnabled()
2861 {
2862     SalData* pSalData = GetSalData();
2863     if( ! pSalData->mpDwmIsCompositionEnabled )
2864     {
2865         pSalData->maDwmLib = osl_loadAsciiModule( "Dwmapi.dll", SAL_LOADMODULE_DEFAULT );
2866         if( pSalData->maDwmLib )
2867             pSalData->mpDwmIsCompositionEnabled = (DwmIsCompositionEnabled_ptr)osl_getAsciiFunctionSymbol( pSalData->maDwmLib, "DwmIsCompositionEnabled" );
2868         if( ! pSalData->mpDwmIsCompositionEnabled ) // something failed
2869             pSalData->mpDwmIsCompositionEnabled = backwardCompatibleDwmIsCompositionEnabled;
2870     }
2871     BOOL aResult = FALSE;
2872     HRESULT nError = pSalData->mpDwmIsCompositionEnabled( &aResult );
2873     return nError == S_OK && aResult;
2874 }
2875 
2876 
UpdateSettings(AllSettings & rSettings)2877 void WinSalFrame::UpdateSettings( AllSettings& rSettings )
2878 {
2879     MouseSettings aMouseSettings = rSettings.GetMouseSettings();
2880     aMouseSettings.SetDoubleClickTime( GetDoubleClickTime() );
2881     aMouseSettings.SetDoubleClickWidth( GetSystemMetrics( SM_CXDOUBLECLK ) );
2882     aMouseSettings.SetDoubleClickHeight( GetSystemMetrics( SM_CYDOUBLECLK ) );
2883     long nDragWidth = GetSystemMetrics( SM_CXDRAG );
2884     long nDragHeight = GetSystemMetrics( SM_CYDRAG );
2885     if ( nDragWidth )
2886         aMouseSettings.SetStartDragWidth( nDragWidth );
2887     if ( nDragHeight )
2888         aMouseSettings.SetStartDragHeight( nDragHeight );
2889     HKEY hRegKey;
2890     if ( RegOpenKey( HKEY_CURRENT_USER,
2891                      "Control Panel\\Desktop",
2892                      &hRegKey ) == ERROR_SUCCESS )
2893     {
2894         BYTE    aValueBuf[10];
2895         DWORD   nValueSize = sizeof( aValueBuf );
2896         DWORD   nType;
2897         if ( RegQueryValueEx( hRegKey, "MenuShowDelay", 0,
2898                               &nType, aValueBuf, &nValueSize ) == ERROR_SUCCESS )
2899         {
2900             if ( nType == REG_SZ )
2901                 aMouseSettings.SetMenuDelay( (sal_uLong)ImplA2I( aValueBuf ) );
2902         }
2903 
2904         RegCloseKey( hRegKey );
2905     }
2906 
2907     StyleSettings aStyleSettings = rSettings.GetStyleSettings();
2908     // TODO: once those options vanish: just set bCompBorder to TRUE
2909     // to have the system colors read
2910     aStyleSettings.SetScrollBarSize( GetSystemMetrics( SM_CXVSCROLL ) );
2911     aStyleSettings.SetSpinSize( GetSystemMetrics( SM_CXVSCROLL ) );
2912     aStyleSettings.SetCursorBlinkTime( GetCaretBlinkTime() );
2913     aStyleSettings.SetFloatTitleHeight( GetSystemMetrics( SM_CYSMCAPTION ) );
2914     aStyleSettings.SetTitleHeight( GetSystemMetrics( SM_CYCAPTION ) );
2915     aStyleSettings.SetActiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVEBORDER ) ) );
2916     aStyleSettings.SetDeactiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVEBORDER ) ) );
2917     if ( aSalShlData.mnVersion >= 410 )
2918     {
2919         aStyleSettings.SetActiveColor2( ImplWinColorToSal( GetSysColor( COLOR_GRADIENTACTIVECAPTION ) ) );
2920         aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_GRADIENTINACTIVECAPTION ) ) );
2921     }
2922     aStyleSettings.SetFaceColor( ImplWinColorToSal( GetSysColor( COLOR_3DFACE ) ) );
2923     aStyleSettings.SetInactiveTabColor( aStyleSettings.GetFaceColor() );
2924     aStyleSettings.SetLightColor( ImplWinColorToSal( GetSysColor( COLOR_3DHILIGHT ) ) );
2925     aStyleSettings.SetLightBorderColor( ImplWinColorToSal( GetSysColor( COLOR_3DLIGHT ) ) );
2926     aStyleSettings.SetShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DSHADOW ) ) );
2927     aStyleSettings.SetDarkShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DDKSHADOW ) ) );
2928     aStyleSettings.SetWorkspaceColor( ImplWinColorToSal( GetSysColor( COLOR_APPWORKSPACE ) ) );
2929     aStyleSettings.SetHelpColor( ImplWinColorToSal( GetSysColor( COLOR_INFOBK ) ) );
2930     aStyleSettings.SetHelpTextColor( ImplWinColorToSal( GetSysColor( COLOR_INFOTEXT ) ) );
2931     aStyleSettings.SetDialogColor( aStyleSettings.GetFaceColor() );
2932     aStyleSettings.SetDialogTextColor( aStyleSettings.GetButtonTextColor() );
2933     aStyleSettings.SetButtonTextColor( ImplWinColorToSal( GetSysColor( COLOR_BTNTEXT ) ) );
2934     aStyleSettings.SetButtonRolloverTextColor( aStyleSettings.GetButtonTextColor() );
2935     aStyleSettings.SetRadioCheckTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) );
2936     aStyleSettings.SetGroupTextColor( aStyleSettings.GetRadioCheckTextColor() );
2937     aStyleSettings.SetLabelTextColor( aStyleSettings.GetRadioCheckTextColor() );
2938     aStyleSettings.SetInfoTextColor( aStyleSettings.GetRadioCheckTextColor() );
2939     aStyleSettings.SetWindowColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOW ) ) );
2940     aStyleSettings.SetActiveTabColor( aStyleSettings.GetWindowColor() );
2941     aStyleSettings.SetWindowTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) );
2942     aStyleSettings.SetFieldColor( aStyleSettings.GetWindowColor() );
2943     aStyleSettings.SetFieldTextColor( aStyleSettings.GetWindowTextColor() );
2944     aStyleSettings.SetFieldRolloverTextColor( aStyleSettings.GetFieldTextColor() );
2945     aStyleSettings.SetHighlightColor( ImplWinColorToSal( GetSysColor( COLOR_HIGHLIGHT ) ) );
2946     aStyleSettings.SetHighlightTextColor( ImplWinColorToSal( GetSysColor( COLOR_HIGHLIGHTTEXT ) ) );
2947     aStyleSettings.SetMenuHighlightColor( aStyleSettings.GetHighlightColor() );
2948     aStyleSettings.SetMenuHighlightTextColor( aStyleSettings.GetHighlightTextColor() );
2949 
2950     ImplSVData* pSVData = ImplGetSVData();
2951     pSVData->maNWFData.mnMenuFormatExtraBorder = 0;
2952     pSVData->maNWFData.maMenuBarHighlightTextColor = Color( COL_TRANSPARENT );
2953     GetSalData()->mbThemeMenuSupport = FALSE;
2954     aStyleSettings.SetMenuColor( ImplWinColorToSal( GetSysColor( COLOR_MENU ) ) );
2955     aStyleSettings.SetMenuBarColor( aStyleSettings.GetMenuColor() );
2956     aStyleSettings.SetMenuBorderColor( aStyleSettings.GetLightBorderColor() ); // overridden below for flat menus
2957     aStyleSettings.SetUseFlatBorders( FALSE );
2958     aStyleSettings.SetUseFlatMenues( FALSE );
2959     aStyleSettings.SetMenuTextColor( ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ) );
2960     aStyleSettings.SetMenuBarTextColor( ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ) );
2961     aStyleSettings.SetActiveColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVECAPTION ) ) );
2962     aStyleSettings.SetActiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_CAPTIONTEXT ) ) );
2963     aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTION ) ) );
2964     aStyleSettings.SetDeactiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTIONTEXT ) ) );
2965     if ( aSalShlData.mbWXP )
2966     {
2967         // only xp supports a different menu bar color
2968         long bFlatMenues = 0;
2969         SystemParametersInfo( SPI_GETFLATMENU, 0, &bFlatMenues, 0);
2970         if( bFlatMenues )
2971         {
2972             aStyleSettings.SetUseFlatMenues( TRUE );
2973             aStyleSettings.SetMenuBarColor( ImplWinColorToSal( GetSysColor( COLOR_MENUBAR ) ) );
2974             aStyleSettings.SetMenuHighlightColor( ImplWinColorToSal( GetSysColor( COLOR_MENUHILIGHT ) ) );
2975             aStyleSettings.SetMenuBorderColor( ImplWinColorToSal( GetSysColor( COLOR_3DSHADOW ) ) );
2976 
2977             // flat borders for our controls etc. as well in this mode (i.e. no 3D borders)
2978             // this is not active in the classic style appearance
2979             aStyleSettings.SetUseFlatBorders( TRUE );
2980         }
2981     }
2982     // check if vista or newer runs
2983     // in Aero theme (and similar ?) the menu text color does not change
2984     // for selected items; also on WinXP and earlier menus are not themed
2985     if( aSalShlData.maVersionInfo.dwMajorVersion >= 6 &&
2986        ImplDwmIsCompositionEnabled()
2987        )
2988     {
2989         // in Aero menuitem highlight text is drawn in the same color as normal
2990         aStyleSettings.SetMenuHighlightTextColor( aStyleSettings.GetMenuTextColor() );
2991         pSVData->maNWFData.mnMenuFormatExtraBorder = 2;
2992         pSVData->maNWFData.maMenuBarHighlightTextColor = aStyleSettings.GetMenuTextColor();
2993         GetSalData()->mbThemeMenuSupport = TRUE;
2994     }
2995     // Bei hellgrau geben wir die Farbe vor, damit es besser aussieht
2996     if ( aStyleSettings.GetFaceColor() == COL_LIGHTGRAY )
2997         aStyleSettings.SetCheckedColor( Color( 0xCC, 0xCC, 0xCC ) );
2998     else
2999     {
3000         // Checked-Color berechnen
3001         Color   aColor1 = aStyleSettings.GetFaceColor();
3002         Color   aColor2 = aStyleSettings.GetLightColor();
3003         BYTE    nRed    = (BYTE)(((sal_uInt16)aColor1.GetRed()   + (sal_uInt16)aColor2.GetRed())/2);
3004         BYTE    nGreen  = (BYTE)(((sal_uInt16)aColor1.GetGreen() + (sal_uInt16)aColor2.GetGreen())/2);
3005         BYTE    nBlue   = (BYTE)(((sal_uInt16)aColor1.GetBlue()  + (sal_uInt16)aColor2.GetBlue())/2);
3006         aStyleSettings.SetCheckedColor( Color( nRed, nGreen, nBlue ) );
3007     }
3008 
3009     // caret width
3010     DWORD nCaretWidth = 2;
3011     if( SystemParametersInfo( SPI_GETCARETWIDTH, 0, &nCaretWidth, 0 ) )
3012         aStyleSettings.SetCursorSize( nCaretWidth );
3013 
3014     // High contrast
3015     HIGHCONTRAST hc;
3016     hc.cbSize = sizeof( HIGHCONTRAST );
3017     if( SystemParametersInfo( SPI_GETHIGHCONTRAST, hc.cbSize, &hc, 0) && (hc.dwFlags & HCF_HIGHCONTRASTON) )
3018         aStyleSettings.SetHighContrastMode( 1 );
3019     else
3020         aStyleSettings.SetHighContrastMode( 0 );
3021 
3022 
3023     // Query Fonts
3024     Font    aMenuFont = aStyleSettings.GetMenuFont();
3025     Font    aTitleFont = aStyleSettings.GetTitleFont();
3026     Font    aFloatTitleFont = aStyleSettings.GetFloatTitleFont();
3027     Font    aHelpFont = aStyleSettings.GetHelpFont();
3028     Font    aAppFont = aStyleSettings.GetAppFont();
3029     Font    aIconFont = aStyleSettings.GetIconFont();
3030     HDC     hDC = GetDC( 0 );
3031     if( true/*aSalShlData.mbWNT*/ )
3032     {
3033         NONCLIENTMETRICSW aNonClientMetrics;
3034         aNonClientMetrics.cbSize = sizeof( aNonClientMetrics );
3035         if ( SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) )
3036         {
3037             ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfMenuFont, aMenuFont );
3038             ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfCaptionFont, aTitleFont );
3039             ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfSmCaptionFont, aFloatTitleFont );
3040             ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfStatusFont, aHelpFont );
3041             ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfMessageFont, aAppFont );
3042 
3043             LOGFONTW aLogFont;
3044             if ( SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &aLogFont, 0 ) )
3045                 ImplSalUpdateStyleFontW( hDC, aLogFont, aIconFont );
3046         }
3047     }
3048 
3049     // get screen font resolution to calculate toolbox item size
3050     long nDPIY = GetDeviceCaps( hDC, LOGPIXELSY );
3051 
3052     ReleaseDC( 0, hDC );
3053 
3054     long nHeightPx = aMenuFont.GetHeight() * nDPIY / 72;
3055     aStyleSettings.SetToolbarIconSize( (((nHeightPx-1)*2) >= 28) ? STYLE_TOOLBAR_ICONSIZE_LARGE : STYLE_TOOLBAR_ICONSIZE_SMALL );
3056 
3057     aStyleSettings.SetMenuFont( aMenuFont );
3058     aStyleSettings.SetTitleFont( aTitleFont );
3059     aStyleSettings.SetFloatTitleFont( aFloatTitleFont );
3060     aStyleSettings.SetHelpFont( aHelpFont );
3061     aStyleSettings.SetIconFont( aIconFont );
3062     // We prefer Arial in the Russian version, because MS Sans Serif
3063     // is to wide for the dialogs
3064     if ( rSettings.GetLanguage() == LANGUAGE_RUSSIAN )
3065     {
3066         XubString aFontName = aAppFont.GetName();
3067         XubString aFirstName = aFontName.GetToken( 0, ';' );
3068         if ( aFirstName.EqualsIgnoreCaseAscii( "MS Sans Serif" ) )
3069         {
3070             aFontName.InsertAscii( "Arial;", 0 );
3071             aAppFont.SetName( aFontName );
3072         }
3073     }
3074     aStyleSettings.SetAppFont( aAppFont );
3075     aStyleSettings.SetGroupFont( aAppFont );
3076     aStyleSettings.SetLabelFont( aAppFont );
3077     aStyleSettings.SetRadioCheckFont( aAppFont );
3078     aStyleSettings.SetPushButtonFont( aAppFont );
3079     aStyleSettings.SetFieldFont( aAppFont );
3080     if ( aAppFont.GetWeight() > WEIGHT_NORMAL )
3081         aAppFont.SetWeight( WEIGHT_NORMAL );
3082     aStyleSettings.SetInfoFont( aAppFont );
3083     aStyleSettings.SetToolFont( aAppFont );
3084 
3085     BOOL bDragFull;
3086     if ( SystemParametersInfo( SPI_GETDRAGFULLWINDOWS, 0, &bDragFull, 0 ) )
3087     {
3088         sal_uLong nDragFullOptions = aStyleSettings.GetDragFullOptions();
3089         if ( bDragFull )
3090             nDragFullOptions |=  DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT;
3091         else
3092             nDragFullOptions &= ~(DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT);
3093         aStyleSettings.SetDragFullOptions( nDragFullOptions );
3094     }
3095 
3096     aStyleSettings.SetIconHorzSpace( GetSystemMetrics( SM_CXICONSPACING ) );
3097     aStyleSettings.SetIconVertSpace( GetSystemMetrics( SM_CYICONSPACING ) );
3098     if ( RegOpenKey( HKEY_CURRENT_USER,
3099                      "Control Panel\\International\\Calendars\\TwoDigitYearMax",
3100                      &hRegKey ) == ERROR_SUCCESS )
3101     {
3102         BYTE    aValueBuf[10];
3103         DWORD   nValue;
3104         DWORD   nValueSize = sizeof( aValueBuf );
3105         DWORD   nType;
3106         if ( RegQueryValueEx( hRegKey, "1", 0,
3107                               &nType, aValueBuf, &nValueSize ) == ERROR_SUCCESS )
3108         {
3109             if ( nType == REG_SZ )
3110             {
3111                 nValue = (sal_uLong)ImplA2I( aValueBuf );
3112                 if ( (nValue > 1000) && (nValue < 10000) )
3113                 {
3114                     MiscSettings aMiscSettings = rSettings.GetMiscSettings();
3115                     utl::MiscCfg().SetYear2000( (sal_Int32)(nValue-99) );
3116                     rSettings.SetMiscSettings( aMiscSettings );
3117                 }
3118             }
3119         }
3120 
3121         RegCloseKey( hRegKey );
3122     }
3123 
3124     rSettings.SetMouseSettings( aMouseSettings );
3125     rSettings.SetStyleSettings( aStyleSettings );
3126 }
3127 
3128 // -----------------------------------------------------------------------
3129 
SnapShot()3130 SalBitmap* WinSalFrame::SnapShot()
3131 {
3132     WinSalBitmap* pSalBitmap = NULL;
3133 
3134     RECT aRect;
3135     GetWindowRect( mhWnd, &aRect );
3136 
3137     int     nDX = aRect.right-aRect.left;
3138     int     nDY = aRect.bottom-aRect.top;
3139     HDC     hDC = GetWindowDC( mhWnd );
3140     HBITMAP hBmpBitmap = CreateCompatibleBitmap( hDC, nDX, nDY );
3141     HDC     hBmpDC = ImplGetCachedDC( CACHED_HDC_1, hBmpBitmap );
3142     sal_Bool    bRet;
3143 
3144     bRet = BitBlt( hBmpDC, 0, 0, nDX, nDY, hDC, 0, 0, SRCCOPY ) ? TRUE : FALSE;
3145     ImplReleaseCachedDC( CACHED_HDC_1 );
3146 
3147     if ( bRet )
3148     {
3149         pSalBitmap = new WinSalBitmap;
3150 
3151         if ( !pSalBitmap->Create( hBmpBitmap, FALSE, FALSE ) )
3152         {
3153             delete pSalBitmap;
3154             pSalBitmap = NULL;
3155         }
3156     }
3157 
3158     return pSalBitmap;
3159 }
3160 
3161 // -----------------------------------------------------------------------
3162 
GetSystemData() const3163 const SystemEnvData* WinSalFrame::GetSystemData() const
3164 {
3165     return &maSysData;
3166 }
3167 
3168 // -----------------------------------------------------------------------
3169 
Beep(SoundType eSoundType)3170 void WinSalFrame::Beep( SoundType eSoundType )
3171 {
3172     static UINT aImplSoundTab[5] =
3173     {
3174         0,                              // SOUND_DEFAULT
3175         MB_ICONASTERISK,                // SOUND_INFO
3176         MB_ICONEXCLAMATION,             // SOUND_WARNING
3177         MB_ICONHAND,                    // SOUND_ERROR
3178         MB_ICONQUESTION                 // SOUND_QUERY
3179     };
3180 
3181     if( eSoundType != SOUND_DISABLE ) // don't beep on disable
3182         MessageBeep( aImplSoundTab[eSoundType] );
3183 }
3184 
3185 // -----------------------------------------------------------------------
3186 
GetPointerState()3187 SalFrame::SalPointerState WinSalFrame::GetPointerState()
3188 {
3189     SalPointerState aState;
3190     aState.mnState = 0;
3191 
3192     if ( GetKeyState( VK_LBUTTON ) & 0x8000 )
3193         aState.mnState |= MOUSE_LEFT;
3194     if ( GetKeyState( VK_MBUTTON ) & 0x8000 )
3195         aState.mnState |= MOUSE_MIDDLE;
3196     if ( GetKeyState( VK_RBUTTON ) & 0x8000 )
3197         aState.mnState |= MOUSE_RIGHT;
3198     if ( GetKeyState( VK_SHIFT ) & 0x8000 )
3199         aState.mnState |= KEY_SHIFT;
3200     if ( GetKeyState( VK_CONTROL ) & 0x8000 )
3201         aState.mnState |= KEY_MOD1;
3202     if ( GetKeyState( VK_MENU ) & 0x8000 )
3203         aState.mnState |= KEY_MOD2;
3204 
3205     POINT pt;
3206     GetCursorPos( &pt );
3207 
3208     aState.maPos = Point( pt.x - maGeometry.nX, pt.y - maGeometry.nY );
3209     return aState;
3210 }
3211 
3212 // -----------------------------------------------------------------------
3213 
SetBackgroundBitmap(SalBitmap *)3214 void WinSalFrame::SetBackgroundBitmap( SalBitmap* )
3215 {
3216 }
3217 
3218 // -----------------------------------------------------------------------
3219 
ResetClipRegion()3220 void WinSalFrame::ResetClipRegion()
3221 {
3222     SetWindowRgn( mhWnd, 0, TRUE );
3223 }
3224 
3225 // -----------------------------------------------------------------------
3226 
BeginSetClipRegion(sal_uLong nRects)3227 void WinSalFrame::BeginSetClipRegion( sal_uLong nRects )
3228 {
3229     if( mpClipRgnData )
3230         delete [] (BYTE*)mpClipRgnData;
3231     sal_uLong nRectBufSize = sizeof(RECT)*nRects;
3232     mpClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+nRectBufSize];
3233     mpClipRgnData->rdh.dwSize     = sizeof( RGNDATAHEADER );
3234     mpClipRgnData->rdh.iType      = RDH_RECTANGLES;
3235     mpClipRgnData->rdh.nCount     = nRects;
3236     mpClipRgnData->rdh.nRgnSize  = nRectBufSize;
3237     SetRectEmpty( &(mpClipRgnData->rdh.rcBound) );
3238     mpNextClipRect        = (RECT*)(&(mpClipRgnData->Buffer));
3239     mbFirstClipRect       = TRUE;
3240 }
3241 
3242 // -----------------------------------------------------------------------
3243 
UnionClipRegion(long nX,long nY,long nWidth,long nHeight)3244 void WinSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
3245 {
3246     if( ! mpClipRgnData )
3247         return;
3248 
3249     RECT*       pRect = mpNextClipRect;
3250     RECT*       pBoundRect = &(mpClipRgnData->rdh.rcBound);
3251     long        nRight = nX + nWidth;
3252     long        nBottom = nY + nHeight;
3253 
3254     if ( mbFirstClipRect )
3255     {
3256         pBoundRect->left    = nX;
3257         pBoundRect->top     = nY;
3258         pBoundRect->right   = nRight;
3259         pBoundRect->bottom  = nBottom;
3260         mbFirstClipRect = FALSE;
3261     }
3262     else
3263     {
3264         if ( nX < pBoundRect->left )
3265             pBoundRect->left = (int)nX;
3266 
3267         if ( nY < pBoundRect->top )
3268             pBoundRect->top = (int)nY;
3269 
3270         if ( nRight > pBoundRect->right )
3271             pBoundRect->right = (int)nRight;
3272 
3273         if ( nBottom > pBoundRect->bottom )
3274             pBoundRect->bottom = (int)nBottom;
3275     }
3276 
3277     pRect->left     = (int)nX;
3278     pRect->top      = (int)nY;
3279     pRect->right    = (int)nRight;
3280     pRect->bottom   = (int)nBottom;
3281     if( (mpNextClipRect  - (RECT*)(&mpClipRgnData->Buffer)) < (int)mpClipRgnData->rdh.nCount )
3282         mpNextClipRect++;
3283 }
3284 
3285 // -----------------------------------------------------------------------
3286 
EndSetClipRegion()3287 void WinSalFrame::EndSetClipRegion()
3288 {
3289     if( ! mpClipRgnData )
3290         return;
3291 
3292     HRGN hRegion;
3293 
3294     // create region from accumulated rectangles
3295     if ( mpClipRgnData->rdh.nCount == 1 )
3296     {
3297         RECT* pRect = &(mpClipRgnData->rdh.rcBound);
3298         hRegion = CreateRectRgn( pRect->left, pRect->top,
3299                                  pRect->right, pRect->bottom );
3300     }
3301     else
3302     {
3303         sal_uLong nSize = mpClipRgnData->rdh.nRgnSize+sizeof(RGNDATAHEADER);
3304         hRegion = ExtCreateRegion( NULL, nSize, mpClipRgnData );
3305     }
3306     delete [] (BYTE*)mpClipRgnData;
3307     mpClipRgnData = NULL;
3308 
3309     DBG_ASSERT( hRegion, "WinSalFrame::EndSetClipRegion() - Can't create ClipRegion" );
3310     if( hRegion )
3311     {
3312         RECT aWindowRect;
3313         GetWindowRect( mhWnd, &aWindowRect );
3314         POINT aPt;
3315         aPt.x=0;
3316         aPt.y=0;
3317         ClientToScreen( mhWnd, &aPt );
3318         OffsetRgn( hRegion, aPt.x - aWindowRect.left, aPt.y - aWindowRect.top );
3319 
3320         if( SetWindowRgn( mhWnd, hRegion, TRUE ) == 0 )
3321             DeleteObject( hRegion );
3322     }
3323 }
3324 
3325 // -----------------------------------------------------------------------
3326 
ImplHandleMouseMsg(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)3327 static long ImplHandleMouseMsg( HWND hWnd, UINT nMsg,
3328                                 WPARAM wParam, LPARAM lParam )
3329 {
3330     WinSalFrame* pFrame = GetWindowPtr( hWnd );
3331     if ( !pFrame )
3332         return 0;
3333 
3334     if( nMsg == WM_LBUTTONDOWN || nMsg == WM_MBUTTONDOWN || nMsg == WM_RBUTTONDOWN )
3335     {
3336         // #103168# post again if async focus has not arrived yet
3337         // hopefully we will not receive the corresponding button up before this
3338         // button down arrives again
3339         Window *pWin = pFrame->GetWindow();
3340         if( pWin && pWin->ImplGetWindowImpl()->mpFrameData->mnFocusId )
3341         {
3342             ImplPostMessage( hWnd, nMsg, wParam, lParam );
3343             return 1;
3344         }
3345     }
3346     SalMouseEvent   aMouseEvt;
3347     long            nRet;
3348     sal_uInt16          nEvent = 0;
3349     sal_Bool            bCall = TRUE;
3350 
3351     aMouseEvt.mnX       = (short)LOWORD( lParam );
3352     aMouseEvt.mnY       = (short)HIWORD( lParam );
3353     aMouseEvt.mnCode    = 0;
3354     aMouseEvt.mnTime    = GetMessageTime();
3355 
3356     // Wegen (Logitech-)MouseTreiber über GetKeyState() gehen, die auf
3357     // mittlerer Maustaste Doppelklick simulieren und den KeyStatus nicht
3358     // berücksichtigen
3359 
3360     if ( GetKeyState( VK_LBUTTON ) & 0x8000 )
3361         aMouseEvt.mnCode |= MOUSE_LEFT;
3362     if ( GetKeyState( VK_MBUTTON ) & 0x8000 )
3363         aMouseEvt.mnCode |= MOUSE_MIDDLE;
3364     if ( GetKeyState( VK_RBUTTON ) & 0x8000 )
3365         aMouseEvt.mnCode |= MOUSE_RIGHT;
3366     if ( GetKeyState( VK_SHIFT ) & 0x8000 )
3367         aMouseEvt.mnCode |= KEY_SHIFT;
3368     if ( GetKeyState( VK_CONTROL ) & 0x8000 )
3369         aMouseEvt.mnCode |= KEY_MOD1;
3370     if ( GetKeyState( VK_MENU ) & 0x8000 )
3371         aMouseEvt.mnCode |= KEY_MOD2;
3372 
3373     switch ( nMsg )
3374     {
3375         case WM_MOUSEMOVE:
3376             {
3377             // Da bei Drücken von Modifier-Tasten die MouseEvents
3378             // nicht zusammengefast werden (da diese durch KeyEvents
3379             // unterbrochen werden), machen wir dieses hier selber
3380             if ( aMouseEvt.mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2) )
3381             {
3382                 MSG aTempMsg;
3383                 if ( ImplPeekMessage( &aTempMsg, hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE | PM_NOYIELD ) )
3384                 {
3385                     if ( (aTempMsg.message == WM_MOUSEMOVE) &&
3386                          (aTempMsg.wParam == wParam) )
3387                         return 1;
3388                 }
3389             }
3390 
3391             SalData* pSalData = GetSalData();
3392             // Test for MouseLeave
3393             if ( pSalData->mhWantLeaveMsg && (pSalData->mhWantLeaveMsg != hWnd) )
3394                 ImplSendMessage( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, GetMessagePos() );
3395 
3396             pSalData->mhWantLeaveMsg = hWnd;
3397             // Start MouseLeave-Timer
3398             if ( !pSalData->mpMouseLeaveTimer )
3399             {
3400                 pSalData->mpMouseLeaveTimer = new AutoTimer;
3401                 pSalData->mpMouseLeaveTimer->SetTimeout( SAL_MOUSELEAVE_TIMEOUT );
3402                 pSalData->mpMouseLeaveTimer->Start();
3403                 // We don't need to set a timeout handler, because we test
3404                 // for mouseleave in the timeout callback
3405             }
3406             aMouseEvt.mnButton = 0;
3407             nEvent = SALEVENT_MOUSEMOVE;
3408             }
3409             break;
3410 
3411         case WM_NCMOUSEMOVE:
3412         case SAL_MSG_MOUSELEAVE:
3413             {
3414             SalData* pSalData = GetSalData();
3415             if ( pSalData->mhWantLeaveMsg == hWnd )
3416             {
3417                 pSalData->mhWantLeaveMsg = 0;
3418                 if ( pSalData->mpMouseLeaveTimer )
3419                 {
3420                     delete pSalData->mpMouseLeaveTimer;
3421                     pSalData->mpMouseLeaveTimer = NULL;
3422                 }
3423                 // Mouse-Coordinates are relative to the screen
3424                 POINT aPt;
3425                 aPt.x = (short)LOWORD( lParam );
3426                 aPt.y = (short)HIWORD( lParam );
3427                 ScreenToClient( hWnd, &aPt );
3428                 aMouseEvt.mnX = aPt.x;
3429                 aMouseEvt.mnY = aPt.y;
3430                 aMouseEvt.mnButton = 0;
3431                 nEvent = SALEVENT_MOUSELEAVE;
3432             }
3433             else
3434                 bCall = FALSE;
3435             }
3436             break;
3437 
3438         case WM_LBUTTONDOWN:
3439             aMouseEvt.mnButton = MOUSE_LEFT;
3440             nEvent = SALEVENT_MOUSEBUTTONDOWN;
3441             break;
3442 
3443         case WM_MBUTTONDOWN:
3444             aMouseEvt.mnButton = MOUSE_MIDDLE;
3445             nEvent = SALEVENT_MOUSEBUTTONDOWN;
3446             break;
3447 
3448         case WM_RBUTTONDOWN:
3449             aMouseEvt.mnButton = MOUSE_RIGHT;
3450             nEvent = SALEVENT_MOUSEBUTTONDOWN;
3451             break;
3452 
3453         case WM_LBUTTONUP:
3454             aMouseEvt.mnButton = MOUSE_LEFT;
3455             nEvent = SALEVENT_MOUSEBUTTONUP;
3456             break;
3457 
3458         case WM_MBUTTONUP:
3459             aMouseEvt.mnButton = MOUSE_MIDDLE;
3460             nEvent = SALEVENT_MOUSEBUTTONUP;
3461             break;
3462 
3463         case WM_RBUTTONUP:
3464             aMouseEvt.mnButton = MOUSE_RIGHT;
3465             nEvent = SALEVENT_MOUSEBUTTONUP;
3466             break;
3467     }
3468 
3469     // check if this window was destroyed - this might happen if we are the help window
3470     // and sent a mouse leave message to the application which killed the help window, i.e. ourself
3471     if( !IsWindow( hWnd ) )
3472         return 0;
3473 
3474     if ( bCall )
3475     {
3476         if ( nEvent == SALEVENT_MOUSEBUTTONDOWN )
3477             UpdateWindow( hWnd );
3478 
3479         // --- RTL --- (mirror mouse pos)
3480         if( Application::GetSettings().GetLayoutRTL() )
3481             aMouseEvt.mnX = pFrame->maGeometry.nWidth-1-aMouseEvt.mnX;
3482 
3483         nRet = pFrame->CallCallback( nEvent, &aMouseEvt );
3484         if ( nMsg == WM_MOUSEMOVE )
3485             SetCursor( pFrame->mhCursor );
3486     }
3487     else
3488         nRet = 0;
3489 
3490     return nRet;
3491 }
3492 
3493 // -----------------------------------------------------------------------
3494 
ImplHandleMouseActivateMsg(HWND hWnd)3495 static long ImplHandleMouseActivateMsg( HWND hWnd )
3496 {
3497     WinSalFrame* pFrame = GetWindowPtr( hWnd );
3498     if ( !pFrame )
3499         return 0;
3500 
3501     if ( pFrame->mbFloatWin )
3502         return TRUE;
3503 
3504     SalMouseActivateEvent   aMouseActivateEvt;
3505     POINT                   aPt;
3506     GetCursorPos( &aPt );
3507     ScreenToClient( hWnd, &aPt );
3508     aMouseActivateEvt.mnX = aPt.x;
3509     aMouseActivateEvt.mnY = aPt.y;
3510     return pFrame->CallCallback( SALEVENT_MOUSEACTIVATE, &aMouseActivateEvt );
3511 }
3512 
3513 // -----------------------------------------------------------------------
3514 
ImplHandleWheelMsg(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)3515 static long ImplHandleWheelMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
3516 {
3517     DBG_ASSERT( nMsg == WM_MOUSEWHEEL ||
3518                 nMsg == WM_MOUSEHWHEEL,
3519                 "ImplHandleWheelMsg() called with no wheel mouse event" );
3520 
3521     ImplSalYieldMutexAcquireWithWait();
3522 
3523     long        nRet = 0;
3524     WinSalFrame*   pFrame = GetWindowPtr( hWnd );
3525     if ( pFrame )
3526     {
3527         WORD    nWinModCode = LOWORD( wParam );
3528         POINT   aWinPt;
3529         aWinPt.x    = (short)LOWORD( lParam );
3530         aWinPt.y    = (short)HIWORD( lParam );
3531         ScreenToClient( hWnd, &aWinPt );
3532 
3533         SalWheelMouseEvent aWheelEvt;
3534         aWheelEvt.mnTime        = GetMessageTime();
3535         aWheelEvt.mnX           = aWinPt.x;
3536         aWheelEvt.mnY           = aWinPt.y;
3537         aWheelEvt.mnCode        = 0;
3538         aWheelEvt.mnDelta       = (short)HIWORD( wParam );
3539         aWheelEvt.mnNotchDelta  = aWheelEvt.mnDelta/WHEEL_DELTA;
3540         if( aWheelEvt.mnNotchDelta == 0 )
3541         {
3542             if( aWheelEvt.mnDelta > 0 )
3543                 aWheelEvt.mnNotchDelta = 1;
3544             else if( aWheelEvt.mnDelta < 0 )
3545                 aWheelEvt.mnNotchDelta = -1;
3546         }
3547 
3548         if( nMsg == WM_MOUSEWHEEL )
3549         {
3550             if ( aSalShlData.mnWheelScrollLines == WHEEL_PAGESCROLL )
3551                 aWheelEvt.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
3552             else
3553                 aWheelEvt.mnScrollLines = aSalShlData.mnWheelScrollLines;
3554             aWheelEvt.mbHorz        = FALSE;
3555         }
3556         else
3557         {
3558             aWheelEvt.mnScrollLines = aSalShlData.mnWheelScrollChars;
3559             aWheelEvt.mbHorz        = TRUE;
3560             // BZ 95390 - seems horiz scrolling has swapped direction
3561             aWheelEvt.mnDelta *= -1;
3562             aWheelEvt.mnNotchDelta *= -1;
3563         }
3564 
3565         if ( nWinModCode & MK_SHIFT )
3566             aWheelEvt.mnCode |= KEY_SHIFT;
3567         if ( nWinModCode & MK_CONTROL )
3568             aWheelEvt.mnCode |= KEY_MOD1;
3569         if ( GetKeyState( VK_MENU ) & 0x8000 )
3570             aWheelEvt.mnCode |= KEY_MOD2;
3571 
3572         // --- RTL --- (mirror mouse pos)
3573         if( Application::GetSettings().GetLayoutRTL() )
3574             aWheelEvt.mnX = pFrame->maGeometry.nWidth-1-aWheelEvt.mnX;
3575 
3576         nRet = pFrame->CallCallback( SALEVENT_WHEELMOUSE, &aWheelEvt );
3577     }
3578 
3579     ImplSalYieldMutexRelease();
3580 
3581     return nRet;
3582 }
3583 
3584 // -----------------------------------------------------------------------
3585 
ImplSalGetKeyCode(WPARAM wParam)3586 static sal_uInt16 ImplSalGetKeyCode( WPARAM wParam )
3587 {
3588     sal_uInt16 nKeyCode;
3589 
3590     // convert KeyCode
3591     if ( wParam < KEY_TAB_SIZE )
3592         nKeyCode = aImplTranslateKeyTab[wParam];
3593     else
3594     {
3595         SalData* pSalData = GetSalData();
3596         std::map< UINT, sal_uInt16 >::const_iterator it = pSalData->maVKMap.find( (UINT)wParam );
3597         if( it != pSalData->maVKMap.end() )
3598             nKeyCode = it->second;
3599         else
3600             nKeyCode = 0;
3601     }
3602 
3603     return nKeyCode;
3604 }
3605 
3606 // -----------------------------------------------------------------------
3607 
ImplStrToNum(const sal_Char * pStr)3608 static UINT ImplStrToNum( const sal_Char* pStr )
3609 {
3610     sal_uInt16 n = 0;
3611 
3612     // Solange es sich um eine Ziffer handelt, String umwandeln
3613     while( (*pStr >= 48) && (*pStr <= 57) )
3614     {
3615         n *= 10;
3616         n += ((*pStr) - 48);
3617         pStr++;
3618     }
3619 
3620     return n;
3621 }
3622 
3623 // -----------------------------------------------------------------------
3624 
ImplUpdateInputLang(WinSalFrame * pFrame)3625 static void ImplUpdateInputLang( WinSalFrame* pFrame )
3626 {
3627     sal_Bool bLanguageChange = FALSE;
3628     UINT nLang = LOWORD( GetKeyboardLayout( 0 ) );
3629     if ( nLang && nLang != pFrame->mnInputLang )
3630     {
3631         // keep input lang up-to-date
3632         pFrame->mnInputLang = nLang;
3633         bLanguageChange = TRUE;
3634     }
3635 
3636     // If we are on Windows NT we use Unicode FrameProcs and so we
3637     // get Unicode charcodes directly from Windows
3638     // no need to set up a code page
3639     return;
3640 }
3641 
3642 
ImplGetCharCode(WinSalFrame * pFrame,WPARAM nCharCode)3643 static sal_Unicode ImplGetCharCode( WinSalFrame* pFrame, WPARAM nCharCode )
3644 {
3645     ImplUpdateInputLang( pFrame );
3646 
3647     // If we are on Windows NT we use Unicode FrameProcs and so we
3648     // get Unicode charcodes directly from Windows
3649     return (sal_Unicode)nCharCode;
3650 }
3651 
3652 // -----------------------------------------------------------------------
3653 
GetInputLanguage()3654 LanguageType WinSalFrame::GetInputLanguage()
3655 {
3656     if( !mnInputLang )
3657         ImplUpdateInputLang( this );
3658 
3659     if( !mnInputLang )
3660         return LANGUAGE_DONTKNOW;
3661     else
3662         return (LanguageType) mnInputLang;
3663 }
3664 
3665 // -----------------------------------------------------------------------
3666 
MapUnicodeToKeyCode(sal_Unicode aUnicode,LanguageType aLangType,KeyCode & rKeyCode)3667 sal_Bool WinSalFrame::MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, KeyCode& rKeyCode )
3668 {
3669     sal_Bool bRet = FALSE;
3670     HKL hkl = 0;
3671 
3672     // just use the passed language identifier, do not try to load additional keyboard support
3673     hkl = (HKL) aLangType;
3674 
3675     if( hkl )
3676     {
3677         SHORT scan = VkKeyScanExW( aUnicode, hkl );
3678         if( LOWORD(scan) == 0xFFFF )
3679             // keyboard not loaded or key cannot be mapped
3680             bRet = FALSE;
3681         else
3682         {
3683             BYTE vkeycode   = LOBYTE(scan);
3684             BYTE shiftstate = HIBYTE(scan);
3685 
3686             // Last argument is set to FALSE, because there's no decision made
3687             // yet which key should be assigned to MOD3 modifier on Windows.
3688             // Windows key - user's can be confused, because it should display
3689             //               Windows menu (applies to both left/right key)
3690             // Menu key    - this key is used to display context menu
3691             // AltGr key   - probably it has no sense
3692             rKeyCode = KeyCode( ImplSalGetKeyCode( vkeycode ),
3693                 (shiftstate & 0x01) ? TRUE : FALSE,     // shift
3694                 (shiftstate & 0x02) ? TRUE : FALSE,     // ctrl
3695                 (shiftstate & 0x04) ? TRUE : FALSE,     // alt
3696                 FALSE );
3697             bRet = TRUE;
3698         }
3699     }
3700 
3701     return bRet;
3702 }
3703 
3704 // -----------------------------------------------------------------------
3705 
ImplHandleKeyMsg(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam,LRESULT & rResult)3706 static long ImplHandleKeyMsg( HWND hWnd, UINT nMsg,
3707                               WPARAM wParam, LPARAM lParam, LRESULT& rResult )
3708 {
3709     static sal_Bool     bIgnoreCharMsg  = FALSE;
3710     static WPARAM   nDeadChar       = 0;
3711     static WPARAM   nLastVKChar     = 0;
3712     static sal_uInt16   nLastChar       = 0;
3713     static sal_uInt16   nLastModKeyCode = 0;
3714     static bool     bWaitForModKeyRelease = false;
3715     sal_uInt16          nRepeat         = LOWORD( lParam )-1;
3716     sal_uInt16          nModCode        = 0;
3717 
3718     // Key wurde evtl. durch SysChild an uns weitergeleitet und
3719     // darf somit dann nicht doppelt verarbeitet werden
3720     GetSalData()->mnSalObjWantKeyEvt = 0;
3721 
3722     if ( nMsg == WM_DEADCHAR )
3723     {
3724         nDeadChar = wParam;
3725         return 0;
3726     }
3727 
3728     WinSalFrame* pFrame = GetWindowPtr( hWnd );
3729     if ( !pFrame )
3730         return 0;
3731 
3732     // Wir restaurieren den Background-Modus bei jeder Texteingabe,
3733     // da einige Tools wie RichWin uns diesen hin- und wieder umsetzen
3734     if ( pFrame->mpGraphics &&
3735          pFrame->mpGraphics->getHDC() )
3736         SetBkMode( pFrame->mpGraphics->getHDC(), TRANSPARENT );
3737 
3738     // determine modifiers
3739     if ( GetKeyState( VK_SHIFT ) & 0x8000 )
3740         nModCode |= KEY_SHIFT;
3741     if ( GetKeyState( VK_CONTROL ) & 0x8000 )
3742         nModCode |= KEY_MOD1;
3743     if ( GetKeyState( VK_MENU ) & 0x8000 )
3744         nModCode |= KEY_MOD2;
3745 
3746     if ( (nMsg == WM_CHAR) || (nMsg == WM_SYSCHAR) )
3747     {
3748         nDeadChar = 0;
3749 
3750         if ( bIgnoreCharMsg )
3751         {
3752             bIgnoreCharMsg = FALSE;
3753             // #101635# if zero is returned here for WM_SYSCHAR (ALT+<key>) Windows will beep
3754             // becaus this 'hotkey' was not processed -> better return 1
3755             // except for Alt-SPACE which should always open the sysmenu (#104616#)
3756 
3757             // also return zero if a system menubar is available that might process this hotkey
3758             // this also applies to the OLE inplace embedding where we are a child window
3759             if( (GetWindowStyle( hWnd ) & WS_CHILD) || GetMenu( hWnd ) || (wParam == 0x20) )
3760                 return 0;
3761             else
3762                 return 1;
3763         }
3764 
3765         // Backspace ignorieren wir als eigenständige Taste,
3766         // damit wir keine Probleme in Kombination mit einem
3767         // DeadKey bekommen
3768         if ( wParam == 0x08 )    // BACKSPACE
3769             return 0;
3770 
3771         // Hier kommen nur "freifliegende" WM_CHAR Message an, die durch
3772         // eintippen einer ALT-NUMPAD Kombination erzeugt wurden
3773         SalKeyEvent aKeyEvt;
3774 
3775         if ( (wParam >= '0') && (wParam <= '9') )
3776             aKeyEvt.mnCode = sal::static_int_cast<sal_uInt16>(KEYGROUP_NUM + wParam - '0');
3777         else if ( (wParam >= 'A') && (wParam <= 'Z') )
3778             aKeyEvt.mnCode = sal::static_int_cast<sal_uInt16>(KEYGROUP_ALPHA + wParam - 'A');
3779         else if ( (wParam >= 'a') && (wParam <= 'z') )
3780             aKeyEvt.mnCode = sal::static_int_cast<sal_uInt16>(KEYGROUP_ALPHA + wParam - 'a');
3781         else if ( wParam == 0x0D )    // RETURN
3782             aKeyEvt.mnCode = KEY_RETURN;
3783         else if ( wParam == 0x1B )    // ESCAPE
3784             aKeyEvt.mnCode = KEY_ESCAPE;
3785         else if ( wParam == 0x09 )    // TAB
3786             aKeyEvt.mnCode = KEY_TAB;
3787         else if ( wParam == 0x20 )    // SPACE
3788             aKeyEvt.mnCode = KEY_SPACE;
3789         else
3790             aKeyEvt.mnCode = 0;
3791 
3792         aKeyEvt.mnTime      = GetMessageTime();
3793         aKeyEvt.mnCode     |= nModCode;
3794         aKeyEvt.mnCharCode  = ImplGetCharCode( pFrame, wParam );
3795         aKeyEvt.mnRepeat    = nRepeat;
3796         nLastChar = 0;
3797         nLastVKChar = 0;
3798         long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
3799         pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3800         return nRet;
3801     }
3802     // #i11583#, MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0; addition begins
3803     else if( nMsg == WM_UNICHAR )
3804     {
3805         // If Windows is asking if we accept WM_UNICHAR, return TRUE
3806         if(wParam == UNICODE_NOCHAR)
3807         {
3808             rResult = TRUE; // ssa: this will actually return TRUE to windows
3809             return 1;       // ...but this will only avoid calling the defwindowproc
3810         }
3811 
3812         SalKeyEvent aKeyEvt;
3813         aKeyEvt.mnCode      = nModCode; // Or should it be 0? - as this is always a character returned
3814         aKeyEvt.mnTime      = GetMessageTime();
3815         aKeyEvt.mnRepeat    = 0;
3816 
3817         if( wParam >= Uni_SupplementaryPlanesStart )
3818         {
3819             // character is supplementary char in UTF-32 format - must be converted to UTF-16 supplementary pair
3820             // sal_Unicode ch = (sal_Unicode) Uni_UTF32ToSurrogate1(wParam);
3821             nLastChar = 0;
3822             nLastVKChar = 0;
3823             pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
3824             pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3825             wParam = (sal_Unicode) Uni_UTF32ToSurrogate2( wParam );
3826         }
3827 
3828         aKeyEvt.mnCharCode  = (sal_Unicode) wParam;
3829 
3830         nLastChar = 0;
3831         nLastVKChar = 0;
3832         long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
3833         pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3834 
3835         return nRet;
3836     }
3837     // MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0; addition ends
3838     else
3839     {
3840         // Bei Shift, Control und Menu schicken wir einen KeyModChange-Event
3841         if ( (wParam == VK_SHIFT) || (wParam == VK_CONTROL) || (wParam == VK_MENU) )
3842         {
3843             SalKeyModEvent aModEvt;
3844             aModEvt.mnTime = GetMessageTime();
3845             aModEvt.mnCode = nModCode;
3846             aModEvt.mnModKeyCode = 0;   // no command events will be sent if this member is 0
3847 
3848             sal_uInt16 tmpCode = 0;
3849             if( GetKeyState( VK_LSHIFT )  & 0x8000 )
3850                 tmpCode |= MODKEY_LSHIFT;
3851             if( GetKeyState( VK_RSHIFT )  & 0x8000 )
3852                 tmpCode |= MODKEY_RSHIFT;
3853             if( GetKeyState( VK_LCONTROL ) & 0x8000 )
3854                 tmpCode |= MODKEY_LMOD1;
3855             if( GetKeyState( VK_RCONTROL ) & 0x8000 )
3856                 tmpCode |= MODKEY_RMOD1;
3857             if( GetKeyState( VK_LMENU )  & 0x8000 )
3858                 tmpCode |= MODKEY_LMOD2;
3859             if( GetKeyState( VK_RMENU )  & 0x8000 )
3860                 tmpCode |= MODKEY_RMOD2;
3861 
3862             if( tmpCode < nLastModKeyCode )
3863             {
3864                 aModEvt.mnModKeyCode = nLastModKeyCode;
3865                 nLastModKeyCode = 0;
3866                 bWaitForModKeyRelease = true;
3867             }
3868             else
3869             {
3870                 if( !bWaitForModKeyRelease )
3871                     nLastModKeyCode = tmpCode;
3872             }
3873 
3874             if( !tmpCode )
3875                 bWaitForModKeyRelease = false;
3876 
3877             return pFrame->CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt );
3878         }
3879         else
3880         {
3881             SalKeyEvent     aKeyEvt;
3882             sal_uInt16          nEvent;
3883             MSG             aCharMsg;
3884             BOOL        bCharPeek = FALSE;
3885             UINT            nCharMsg = WM_CHAR;
3886             sal_Bool            bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP);
3887 
3888             nLastModKeyCode = 0; // make sure no modkey messages are sent if they belong to a hotkey (see above)
3889             aKeyEvt.mnCharCode = 0;
3890             aKeyEvt.mnCode = 0;
3891 
3892             aKeyEvt.mnCode = ImplSalGetKeyCode( wParam );
3893             if ( !bKeyUp )
3894             {
3895                 // check for charcode
3896                 // Mit Hilfe von PeekMessage holen wir uns jetzt die
3897                 // zugehörige WM_CHAR Message, wenn vorhanden.
3898                 // Diese WM_CHAR Message steht immer am Anfang der
3899                 // Messagequeue. Ausserdem ist sichergestellt, dass immer
3900                 // nur eine WM_CHAR Message in der Queue steht.
3901                 bCharPeek = ImplPeekMessage( &aCharMsg, hWnd,
3902                                              WM_CHAR, WM_CHAR, PM_NOREMOVE | PM_NOYIELD );
3903                 if ( bCharPeek && (nDeadChar == aCharMsg.wParam) )
3904                 {
3905                     bCharPeek = FALSE;
3906                     nDeadChar = 0;
3907 
3908                     if ( wParam == VK_BACK )
3909                     {
3910                         ImplPeekMessage( &aCharMsg, hWnd,
3911                                          nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD );
3912                         return 0;
3913                     }
3914                 }
3915                 else
3916                 {
3917                     if ( !bCharPeek )
3918                     {
3919                         bCharPeek = ImplPeekMessage( &aCharMsg, hWnd,
3920                                                     WM_SYSCHAR, WM_SYSCHAR, PM_NOREMOVE | PM_NOYIELD );
3921                         nCharMsg = WM_SYSCHAR;
3922                     }
3923                 }
3924                 if ( bCharPeek )
3925                     aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, aCharMsg.wParam );
3926                 else
3927                     aKeyEvt.mnCharCode = 0;
3928 
3929                 nLastChar = aKeyEvt.mnCharCode;
3930                 nLastVKChar = wParam;
3931             }
3932             else
3933             {
3934                 if ( wParam == nLastVKChar )
3935                 {
3936                     aKeyEvt.mnCharCode = nLastChar;
3937                     nLastChar = 0;
3938                     nLastVKChar = 0;
3939                 }
3940             }
3941 
3942             if ( aKeyEvt.mnCode || aKeyEvt.mnCharCode )
3943             {
3944                 if ( bKeyUp )
3945                     nEvent = SALEVENT_KEYUP;
3946                 else
3947                     nEvent = SALEVENT_KEYINPUT;
3948 
3949                 aKeyEvt.mnTime      = GetMessageTime();
3950                 aKeyEvt.mnCode     |= nModCode;
3951                 aKeyEvt.mnRepeat    = nRepeat;
3952 
3953                 if( (nModCode & (KEY_MOD1|KEY_MOD2)) == (KEY_MOD1|KEY_MOD2) &&
3954                     aKeyEvt.mnCharCode )
3955                 {
3956                      // this is actually AltGr and should not be handled as Alt
3957                      aKeyEvt.mnCode &= ~(KEY_MOD1|KEY_MOD2);
3958                 }
3959 
3960                 bIgnoreCharMsg = bCharPeek ? TRUE : FALSE;
3961                 long nRet = pFrame->CallCallback( nEvent, &aKeyEvt );
3962                 // independent part only reacts on keyup but Windows does not send
3963                 // keyup for VK_HANJA
3964                 if( aKeyEvt.mnCode == KEY_HANGUL_HANJA )
3965                     nRet = pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3966 
3967                 bIgnoreCharMsg = FALSE;
3968 
3969                 // char-message, than remove or ignore
3970                 if ( bCharPeek )
3971                 {
3972                     nDeadChar = 0;
3973                     if ( nRet )
3974                     {
3975                         ImplPeekMessage( &aCharMsg, hWnd,
3976                                          nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD );
3977                     }
3978                     else
3979                         bIgnoreCharMsg = TRUE;
3980                 }
3981 
3982                 return nRet;
3983             }
3984             else
3985                 return 0;
3986         }
3987     }
3988 }
3989 
3990 // -----------------------------------------------------------------------
3991 
ImplHandleSalObjKeyMsg(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)3992 long ImplHandleSalObjKeyMsg( HWND hWnd, UINT nMsg,
3993                              WPARAM wParam, LPARAM lParam )
3994 {
3995     if ( (nMsg == WM_KEYDOWN) || (nMsg == WM_KEYUP) )
3996     {
3997         WinSalFrame* pFrame = GetWindowPtr( hWnd );
3998         if ( !pFrame )
3999             return 0;
4000 
4001         sal_uInt16  nRepeat     = LOWORD( lParam )-1;
4002         sal_uInt16  nModCode    = 0;
4003 
4004         // determine modifiers
4005         if ( GetKeyState( VK_SHIFT ) & 0x8000 )
4006             nModCode |= KEY_SHIFT;
4007         if ( GetKeyState( VK_CONTROL ) & 0x8000 )
4008             nModCode |= KEY_MOD1;
4009         if ( GetKeyState( VK_MENU ) & 0x8000 )
4010             nModCode |= KEY_MOD2;
4011 
4012         if ( (wParam != VK_SHIFT) && (wParam != VK_CONTROL) && (wParam != VK_MENU) )
4013         {
4014             SalKeyEvent     aKeyEvt;
4015             sal_uInt16          nEvent;
4016             sal_Bool            bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP);
4017 
4018             // convert KeyCode
4019             aKeyEvt.mnCode      = ImplSalGetKeyCode( wParam );
4020             aKeyEvt.mnCharCode  = 0;
4021 
4022             if ( aKeyEvt.mnCode )
4023             {
4024                 if ( bKeyUp )
4025                     nEvent = SALEVENT_KEYUP;
4026                 else
4027                     nEvent = SALEVENT_KEYINPUT;
4028 
4029                 aKeyEvt.mnTime      = GetMessageTime();
4030                 aKeyEvt.mnCode     |= nModCode;
4031                 aKeyEvt.mnRepeat    = nRepeat;
4032                 long nRet = pFrame->CallCallback( nEvent, &aKeyEvt );
4033                 return nRet;
4034             }
4035             else
4036                 return 0;
4037         }
4038     }
4039 
4040     return 0;
4041 }
4042 
4043 // -----------------------------------------------------------------------
4044 
ImplHandleSalObjSysCharMsg(HWND hWnd,WPARAM wParam,LPARAM lParam)4045 long ImplHandleSalObjSysCharMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
4046 {
4047     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4048     if ( !pFrame )
4049         return 0;
4050 
4051     sal_uInt16  nRepeat     = LOWORD( lParam )-1;
4052     sal_uInt16  nModCode    = 0;
4053     sal_uInt16  cKeyCode    = (sal_uInt16)wParam;
4054 
4055     // determine modifiers
4056     if ( GetKeyState( VK_SHIFT ) & 0x8000 )
4057         nModCode |= KEY_SHIFT;
4058     if ( GetKeyState( VK_CONTROL ) & 0x8000 )
4059         nModCode |= KEY_MOD1;
4060     nModCode |= KEY_MOD2;
4061 
4062     // KeyEvent zusammenbauen
4063     SalKeyEvent aKeyEvt;
4064     aKeyEvt.mnTime      = GetMessageTime();
4065     if ( (cKeyCode >= 48) && (cKeyCode <= 57) )
4066         aKeyEvt.mnCode = KEY_0+(cKeyCode-48);
4067     else if ( (cKeyCode >= 65) && (cKeyCode <= 90) )
4068         aKeyEvt.mnCode = KEY_A+(cKeyCode-65);
4069     else  if ( (cKeyCode >= 97) && (cKeyCode <= 122) )
4070         aKeyEvt.mnCode = KEY_A+(cKeyCode-97);
4071     else
4072         aKeyEvt.mnCode = 0;
4073     aKeyEvt.mnCode     |= nModCode;
4074     aKeyEvt.mnCharCode  = ImplGetCharCode( pFrame, cKeyCode );
4075     aKeyEvt.mnRepeat    = nRepeat;
4076     long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
4077     pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
4078     return nRet;
4079 }
4080 
4081 // -----------------------------------------------------------------------
4082 
ImplHandlePaintMsg(HWND hWnd)4083 static bool ImplHandlePaintMsg( HWND hWnd )
4084 {
4085     sal_Bool bMutex = FALSE;
4086     if ( ImplSalYieldMutexTryToAcquire() )
4087         bMutex = TRUE;
4088 
4089     // if we don't get the mutex, we can also change the clip region,
4090     // because other threads doesn't use the mutex from the main
4091     // thread --> see GetGraphics()
4092 
4093     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4094     if ( pFrame )
4095     {
4096         // Clip-Region muss zurückgesetzt werden, da wir sonst kein
4097         // ordentliches Bounding-Rectangle bekommen
4098         if ( pFrame->mpGraphics && pFrame->mpGraphics->mhRegion )
4099             SelectClipRgn( pFrame->mpGraphics->getHDC(), 0 );
4100 
4101         // Laut Window-Doku soll man erst abfragen, ob überhaupt eine
4102         // Paint-Region anliegt
4103         if ( GetUpdateRect( hWnd, NULL, FALSE ) )
4104         {
4105             // Call BeginPaint/EndPaint to query the rect and send
4106             // this Notofication to rect
4107             RECT aUpdateRect;
4108             PAINTSTRUCT aPs;
4109             BeginPaint( hWnd, &aPs );
4110             CopyRect( &aUpdateRect, &aPs.rcPaint );
4111 
4112             // Paint
4113             // ClipRegion wieder herstellen
4114             if ( pFrame->mpGraphics && pFrame->mpGraphics->mhRegion )
4115             {
4116                 SelectClipRgn( pFrame->mpGraphics->getHDC(),
4117                                pFrame->mpGraphics->mhRegion );
4118             }
4119 
4120             if ( bMutex )
4121             {
4122                 SalPaintEvent aPEvt( aUpdateRect.left, aUpdateRect.top, aUpdateRect.right-aUpdateRect.left, aUpdateRect.bottom-aUpdateRect.top, pFrame->mbPresentation );
4123                 pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
4124             }
4125             else
4126             {
4127                 RECT* pRect = new RECT;
4128                 CopyRect( pRect, &aUpdateRect );
4129                 ImplPostMessage( hWnd, SAL_MSG_POSTPAINT, (WPARAM)pRect, 0 );
4130             }
4131             EndPaint( hWnd, &aPs );
4132         }
4133         else
4134         {
4135             // ClipRegion wieder herstellen
4136             if ( pFrame->mpGraphics && pFrame->mpGraphics->mhRegion )
4137             {
4138                 SelectClipRgn( pFrame->mpGraphics->getHDC(),
4139                                pFrame->mpGraphics->mhRegion );
4140             }
4141         }
4142     }
4143 
4144     if ( bMutex )
4145         ImplSalYieldMutexRelease();
4146 
4147     return bMutex ? true : false;
4148 }
4149 
4150 // -----------------------------------------------------------------------
4151 
ImplHandlePaintMsg2(HWND hWnd,RECT * pRect)4152 static void ImplHandlePaintMsg2( HWND hWnd, RECT* pRect )
4153 {
4154     // Paint
4155     if ( ImplSalYieldMutexTryToAcquire() )
4156     {
4157         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4158         if ( pFrame )
4159         {
4160             SalPaintEvent aPEvt( pRect->left, pRect->top, pRect->right-pRect->left, pRect->bottom-pRect->top );
4161             pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
4162         }
4163         ImplSalYieldMutexRelease();
4164         delete pRect;
4165     }
4166     else
4167         ImplPostMessage( hWnd, SAL_MSG_POSTPAINT, (WPARAM)pRect, 0 );
4168 }
4169 
4170 // -----------------------------------------------------------------------
4171 
SetMaximizedFrameGeometry(HWND hWnd,WinSalFrame * pFrame,RECT * pParentRect)4172 static void SetMaximizedFrameGeometry( HWND hWnd, WinSalFrame* pFrame, RECT* pParentRect )
4173 {
4174     // calculate and set frame geometry of a maximized window - useful if the window is still hidden
4175 
4176     // dualmonitor support:
4177     // Get screensize of the monitor with the mouse pointer
4178 
4179     RECT aRectMouse;
4180     if( ! pParentRect )
4181     {
4182         POINT pt;
4183         GetCursorPos( &pt );
4184         aRectMouse.left = pt.x;
4185         aRectMouse.top = pt.y;
4186         aRectMouse.right = pt.x+2;
4187         aRectMouse.bottom = pt.y+2;
4188         pParentRect = &aRectMouse;
4189     }
4190 
4191     RECT aRect;
4192     ImplSalGetWorkArea( hWnd, &aRect, pParentRect );
4193 
4194     // a maximized window has no other borders than the caption
4195     pFrame->maGeometry.nLeftDecoration = pFrame->maGeometry.nRightDecoration = pFrame->maGeometry.nBottomDecoration = 0;
4196     pFrame->maGeometry.nTopDecoration = pFrame->mbCaption ? GetSystemMetrics( SM_CYCAPTION ) : 0;
4197 
4198     aRect.top += pFrame->maGeometry.nTopDecoration;
4199     pFrame->maGeometry.nX = aRect.left;
4200     pFrame->maGeometry.nY = aRect.top;
4201     pFrame->maGeometry.nWidth = aRect.right - aRect.left;
4202     pFrame->maGeometry.nHeight = aRect.bottom - aRect.top;
4203 }
4204 
UpdateFrameGeometry(HWND hWnd,WinSalFrame * pFrame)4205 static void UpdateFrameGeometry( HWND hWnd, WinSalFrame* pFrame )
4206 {
4207     if( !pFrame )
4208         return;
4209 
4210     RECT aRect;
4211     GetWindowRect( hWnd, &aRect );
4212     memset(&pFrame->maGeometry, 0, sizeof(SalFrameGeometry) );
4213 
4214     if ( IsIconic( hWnd ) )
4215         return;
4216 
4217     POINT aPt;
4218     aPt.x=0;
4219     aPt.y=0;
4220     ClientToScreen(hWnd, &aPt);
4221     int cx = aPt.x - aRect.left;
4222     pFrame->maGeometry.nTopDecoration = aPt.y - aRect.top;
4223 
4224     pFrame->maGeometry.nLeftDecoration = cx;
4225     pFrame->maGeometry.nRightDecoration = cx;
4226 
4227     pFrame->maGeometry.nX = aPt.x;
4228     pFrame->maGeometry.nY = aPt.y;
4229 
4230     RECT aInnerRect;
4231     GetClientRect( hWnd, &aInnerRect );
4232     if( aInnerRect.right )
4233     {
4234         // improve right decoration
4235         aPt.x=aInnerRect.right;
4236         aPt.y=aInnerRect.top;
4237         ClientToScreen(hWnd, &aPt);
4238         pFrame->maGeometry.nRightDecoration = aRect.right - aPt.x;
4239     }
4240     if( aInnerRect.bottom ) // may be zero if window was not shown yet
4241         pFrame->maGeometry.nBottomDecoration += aRect.bottom - aPt.y - aInnerRect.bottom;
4242     else
4243         // bottom border is typically the same as left/right
4244         pFrame->maGeometry.nBottomDecoration = pFrame->maGeometry.nLeftDecoration;
4245 
4246     int nWidth  = aRect.right - aRect.left
4247         - pFrame->maGeometry.nRightDecoration - pFrame->maGeometry.nLeftDecoration;
4248     int nHeight = aRect.bottom - aRect.top
4249         - pFrame->maGeometry.nBottomDecoration - pFrame->maGeometry.nTopDecoration;
4250     // clamp to zero
4251     pFrame->maGeometry.nHeight = nHeight < 0 ? 0 : nHeight;
4252     pFrame->maGeometry.nWidth = nWidth < 0 ? 0 : nWidth;
4253     pFrame->updateScreenNumber();
4254 }
4255 
4256 // -----------------------------------------------------------------------
4257 
ImplCallMoveHdl(HWND hWnd)4258 static void ImplCallMoveHdl( HWND hWnd )
4259 {
4260     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4261     if ( pFrame )
4262     {
4263         pFrame->CallCallback( SALEVENT_MOVE, 0 );
4264         // Um doppelte Paints von VCL und SAL zu vermeiden
4265         //if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow )
4266         //    UpdateWindow( hWnd );
4267     }
4268 }
4269 
4270 // -----------------------------------------------------------------------
4271 
ImplCallClosePopupsHdl(HWND hWnd)4272 static void ImplCallClosePopupsHdl( HWND hWnd )
4273 {
4274     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4275     if ( pFrame )
4276     {
4277         pFrame->CallCallback( SALEVENT_CLOSEPOPUPS, 0 );
4278     }
4279 }
4280 
4281 // -----------------------------------------------------------------------
4282 
ImplHandleMoveMsg(HWND hWnd)4283 static void ImplHandleMoveMsg( HWND hWnd )
4284 {
4285     if ( ImplSalYieldMutexTryToAcquire() )
4286     {
4287         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4288         if ( pFrame )
4289         {
4290             UpdateFrameGeometry( hWnd, pFrame );
4291 
4292             if ( GetWindowStyle( hWnd ) & WS_VISIBLE )
4293                 pFrame->mbDefPos = FALSE;
4294 
4295             // Gegen mögliche Rekursionen sichern
4296             if ( !pFrame->mbInMoveMsg )
4297             {
4298                 // Fenster im FullScreenModus wieder einpassen
4299                 pFrame->mbInMoveMsg = TRUE;
4300                 if ( pFrame->mbFullScreen )
4301                     ImplSalFrameFullScreenPos( pFrame );
4302                 pFrame->mbInMoveMsg = FALSE;
4303             }
4304 
4305             // Status merken
4306             ImplSaveFrameState( pFrame );
4307 
4308             // Call Hdl
4309             //#93851 if we call this handler, VCL floating windows are not updated correctly
4310             ImplCallMoveHdl( hWnd );
4311 
4312         }
4313 
4314         ImplSalYieldMutexRelease();
4315     }
4316     else
4317         ImplPostMessage( hWnd, SAL_MSG_POSTMOVE, 0, 0 );
4318 }
4319 
4320 // -----------------------------------------------------------------------
4321 
ImplCallSizeHdl(HWND hWnd)4322 static void ImplCallSizeHdl( HWND hWnd )
4323 {
4324     // Da Windows diese Messages auch senden kann, muss hier auch die
4325     // Solar-Semaphore berücksichtigt werden
4326     if ( ImplSalYieldMutexTryToAcquire() )
4327     {
4328         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4329         if ( pFrame )
4330         {
4331             pFrame->CallCallback( SALEVENT_RESIZE, 0 );
4332             // Um doppelte Paints von VCL und SAL zu vermeiden
4333             if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow )
4334                 UpdateWindow( hWnd );
4335         }
4336 
4337         ImplSalYieldMutexRelease();
4338     }
4339     else
4340         ImplPostMessage( hWnd, SAL_MSG_POSTCALLSIZE, 0, 0 );
4341 }
4342 
4343 // -----------------------------------------------------------------------
4344 
ImplHandleSizeMsg(HWND hWnd,WPARAM wParam,LPARAM lParam)4345 static void ImplHandleSizeMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
4346 {
4347     if ( (wParam != SIZE_MAXSHOW) && (wParam != SIZE_MAXHIDE) )
4348     {
4349         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4350         if ( pFrame )
4351         {
4352             UpdateFrameGeometry( hWnd, pFrame );
4353 
4354             pFrame->mnWidth  = (int)LOWORD(lParam);
4355             pFrame->mnHeight = (int)HIWORD(lParam);
4356             // Status merken
4357             ImplSaveFrameState( pFrame );
4358             // Call Hdl
4359             ImplCallSizeHdl( hWnd );
4360         }
4361     }
4362 }
4363 
4364 // -----------------------------------------------------------------------
4365 
ImplHandleFocusMsg(HWND hWnd)4366 static void ImplHandleFocusMsg( HWND hWnd )
4367 {
4368     if ( ImplSalYieldMutexTryToAcquire() )
4369     {
4370         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4371         if ( pFrame && !WinSalFrame::mbInReparent )
4372         {
4373             // Query the actual status
4374             if ( ::GetFocus() == hWnd )
4375             {
4376                 if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow )
4377                     UpdateWindow( hWnd );
4378 
4379                 // Feststellen, ob wir IME unterstützen
4380                 if ( pFrame->mbIME && pFrame->mhDefIMEContext )
4381                 {
4382                     UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_PROPERTY );
4383 
4384                     pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
4385                     pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
4386                     pFrame->mbHandleIME = !pFrame->mbSpezIME;
4387                 }
4388 
4389                 pFrame->CallCallback( SALEVENT_GETFOCUS, 0 );
4390             }
4391             else
4392             {
4393                 pFrame->CallCallback( SALEVENT_LOSEFOCUS, 0 );
4394             }
4395         }
4396 
4397         ImplSalYieldMutexRelease();
4398     }
4399     else
4400         ImplPostMessage( hWnd, SAL_MSG_POSTFOCUS, 0, 0 );
4401 }
4402 
4403 // -----------------------------------------------------------------------
4404 
ImplHandleCloseMsg(HWND hWnd)4405 static void ImplHandleCloseMsg( HWND hWnd )
4406 {
4407     if ( ImplSalYieldMutexTryToAcquire() )
4408     {
4409         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4410         if ( pFrame )
4411         {
4412             pFrame->CallCallback( SALEVENT_CLOSE, 0 );
4413         }
4414 
4415         ImplSalYieldMutexRelease();
4416     }
4417     else
4418         ImplPostMessage( hWnd, WM_CLOSE, 0, 0 );
4419 }
4420 
4421 // -----------------------------------------------------------------------
4422 
ImplHandleShutDownMsg(HWND hWnd)4423 static long ImplHandleShutDownMsg( HWND hWnd )
4424 {
4425     ImplSalYieldMutexAcquireWithWait();
4426     long        nRet = 0;
4427     WinSalFrame*   pFrame = GetWindowPtr( hWnd );
4428     if ( pFrame )
4429     {
4430         nRet = pFrame->CallCallback( SALEVENT_SHUTDOWN, 0 );
4431     }
4432     ImplSalYieldMutexRelease();
4433     return nRet;
4434 }
4435 
4436 // -----------------------------------------------------------------------
4437 
ImplHandleSettingsChangeMsg(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)4438 static void ImplHandleSettingsChangeMsg( HWND hWnd, UINT nMsg,
4439                                          WPARAM wParam, LPARAM lParam )
4440 {
4441     sal_uInt16 nSalEvent = SALEVENT_SETTINGSCHANGED;
4442 
4443     if ( nMsg == WM_DEVMODECHANGE )
4444         nSalEvent = SALEVENT_PRINTERCHANGED;
4445     else if ( nMsg == WM_DISPLAYCHANGE )
4446         nSalEvent = SALEVENT_DISPLAYCHANGED;
4447     else if ( nMsg == WM_FONTCHANGE )
4448         nSalEvent = SALEVENT_FONTCHANGED;
4449     else if ( nMsg == WM_TIMECHANGE )
4450         nSalEvent = SALEVENT_DATETIMECHANGED;
4451     else if ( nMsg == WM_WININICHANGE )
4452     {
4453         if ( lParam )
4454         {
4455                 if ( ImplSalWICompareAscii( (const wchar_t*)lParam, "devices" ) == 0 )
4456                     nSalEvent = SALEVENT_PRINTERCHANGED;
4457         }
4458     }
4459 
4460     if ( nMsg == WM_SETTINGCHANGE )
4461     {
4462         if ( wParam == SPI_SETWHEELSCROLLLINES )
4463             aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines();
4464         else if( wParam == SPI_SETWHEELSCROLLCHARS )
4465             aSalShlData.mnWheelScrollChars = ImplSalGetWheelScrollChars();
4466     }
4467 
4468     if ( WM_SYSCOLORCHANGE == nMsg && GetSalData()->mhDitherPal )
4469         ImplUpdateSysColorEntries();
4470 
4471     ImplSalYieldMutexAcquireWithWait();
4472 
4473     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4474     if ( pFrame )
4475     {
4476         if ( (nMsg == WM_DISPLAYCHANGE) || (nMsg == WM_WININICHANGE) )
4477         {
4478             if ( pFrame->mbFullScreen )
4479                 ImplSalFrameFullScreenPos( pFrame );
4480         }
4481 
4482         pFrame->CallCallback( nSalEvent, 0 );
4483     }
4484 
4485     ImplSalYieldMutexRelease();
4486 }
4487 
4488 // -----------------------------------------------------------------------
4489 
ImplHandleUserEvent(HWND hWnd,LPARAM lParam)4490 static void ImplHandleUserEvent( HWND hWnd, LPARAM lParam )
4491 {
4492     ImplSalYieldMutexAcquireWithWait();
4493     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4494     if ( pFrame )
4495     {
4496         pFrame->CallCallback( SALEVENT_USEREVENT, (void*)lParam );
4497     }
4498     ImplSalYieldMutexRelease();
4499 }
4500 
4501 // -----------------------------------------------------------------------
4502 
ImplHandleForcePalette(HWND hWnd)4503 static void ImplHandleForcePalette( HWND hWnd )
4504 {
4505     SalData*    pSalData = GetSalData();
4506     HPALETTE    hPal = pSalData->mhDitherPal;
4507     if ( hPal )
4508     {
4509         if ( !ImplSalYieldMutexTryToAcquire() )
4510         {
4511             ImplPostMessage( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 );
4512             return;
4513         }
4514 
4515         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4516         if ( pFrame && pFrame->mpGraphics )
4517         {
4518             WinSalGraphics* pGraphics = pFrame->mpGraphics;
4519             if ( pGraphics && pGraphics->mhDefPal )
4520             {
4521                 SelectPalette( pGraphics->getHDC(), hPal, FALSE );
4522                 if ( RealizePalette( pGraphics->getHDC() ) )
4523                 {
4524                     InvalidateRect( hWnd, NULL, FALSE );
4525                     UpdateWindow( hWnd );
4526                     pFrame->CallCallback( SALEVENT_DISPLAYCHANGED, 0 );
4527                 }
4528             }
4529         }
4530 
4531         ImplSalYieldMutexRelease();
4532     }
4533 }
4534 
4535 // -----------------------------------------------------------------------
4536 
ImplHandlePalette(sal_Bool bFrame,HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam,int & rDef)4537 static LRESULT ImplHandlePalette( sal_Bool bFrame, HWND hWnd, UINT nMsg,
4538                                   WPARAM wParam, LPARAM lParam, int& rDef )
4539 {
4540     SalData*    pSalData = GetSalData();
4541     HPALETTE    hPal = pSalData->mhDitherPal;
4542     if ( !hPal )
4543         return 0;
4544 
4545     rDef = FALSE;
4546     if ( pSalData->mbInPalChange )
4547         return 0;
4548 
4549     if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) )
4550     {
4551         if ( (HWND)wParam == hWnd )
4552             return 0;
4553     }
4554 
4555     sal_Bool bReleaseMutex = FALSE;
4556     if ( (nMsg == WM_QUERYNEWPALETTE) || (nMsg == WM_PALETTECHANGED) )
4557     {
4558         // Da Windows diese Messages auch sendet, muss hier auch die
4559         // Solar-Semaphore berücksichtigt werden
4560         if ( ImplSalYieldMutexTryToAcquire() )
4561             bReleaseMutex = TRUE;
4562         else if ( nMsg == WM_QUERYNEWPALETTE )
4563             ImplPostMessage( hWnd, SAL_MSG_POSTQUERYNEWPAL, wParam, lParam );
4564         else /* ( nMsg == WM_PALETTECHANGED ) */
4565             ImplPostMessage( hWnd, SAL_MSG_POSTPALCHANGED, wParam, lParam );
4566     }
4567 
4568     WinSalVirtualDevice*pTempVD;
4569     WinSalFrame*        pTempFrame;
4570     WinSalGraphics*     pGraphics;
4571     HDC                 hDC;
4572     HPALETTE            hOldPal;
4573     UINT                nCols;
4574     sal_Bool                bStdDC;
4575     sal_Bool                bUpdate;
4576 
4577     pSalData->mbInPalChange = TRUE;
4578 
4579     // Alle Paletten in VirDevs und Frames zurücksetzen
4580     pTempVD = pSalData->mpFirstVD;
4581     while ( pTempVD )
4582     {
4583         pGraphics = pTempVD->mpGraphics;
4584         if ( pGraphics->mhDefPal )
4585         {
4586             SelectPalette( pGraphics->getHDC(),
4587                            pGraphics->mhDefPal,
4588                            TRUE );
4589         }
4590         pTempVD = pTempVD->mpNext;
4591     }
4592     pTempFrame = pSalData->mpFirstFrame;
4593     while ( pTempFrame )
4594     {
4595         pGraphics = pTempFrame->mpGraphics;
4596         if ( pGraphics && pGraphics->mhDefPal )
4597         {
4598             SelectPalette( pGraphics->getHDC(),
4599                            pGraphics->mhDefPal,
4600                            TRUE );
4601         }
4602         pTempFrame = pTempFrame->mpNextFrame;
4603     }
4604 
4605     // Palette neu realizen
4606     WinSalFrame* pFrame = NULL;
4607     if ( bFrame )
4608         pFrame = GetWindowPtr( hWnd );
4609     if ( pFrame && pFrame->mpGraphics )
4610     {
4611         hDC = pFrame->mpGraphics->getHDC();
4612         bStdDC = TRUE;
4613     }
4614     else
4615     {
4616         hDC = GetDC( hWnd );
4617         bStdDC = FALSE;
4618     }
4619     UnrealizeObject( hPal );
4620     hOldPal = SelectPalette( hDC, hPal, TRUE );
4621     nCols = RealizePalette( hDC );
4622     bUpdate = nCols != 0;
4623     if ( !bStdDC )
4624     {
4625         SelectPalette( hDC, hOldPal, TRUE );
4626         ReleaseDC( hWnd, hDC );
4627     }
4628 
4629     // Alle Paletten in VirDevs und Frames neu setzen
4630     pTempVD = pSalData->mpFirstVD;
4631     while ( pTempVD )
4632     {
4633         pGraphics = pTempVD->mpGraphics;
4634         if ( pGraphics->mhDefPal )
4635         {
4636             SelectPalette( pGraphics->getHDC(), hPal, TRUE );
4637             RealizePalette( pGraphics->getHDC() );
4638         }
4639         pTempVD = pTempVD->mpNext;
4640     }
4641     pTempFrame = pSalData->mpFirstFrame;
4642     while ( pTempFrame )
4643     {
4644         if ( pTempFrame != pFrame )
4645         {
4646             pGraphics = pTempFrame->mpGraphics;
4647             if ( pGraphics && pGraphics->mhDefPal )
4648             {
4649                 SelectPalette( pGraphics->getHDC(), hPal, TRUE );
4650                 if ( RealizePalette( pGraphics->getHDC() ) )
4651                     bUpdate = TRUE;
4652             }
4653         }
4654         pTempFrame = pTempFrame->mpNextFrame;
4655     }
4656 
4657     // Wenn sich Farben geändert haben, dann die Fenster updaten
4658     if ( bUpdate )
4659     {
4660         pTempFrame = pSalData->mpFirstFrame;
4661         while ( pTempFrame )
4662         {
4663             pGraphics = pTempFrame->mpGraphics;
4664             if ( pGraphics && pGraphics->mhDefPal )
4665             {
4666                 InvalidateRect( pTempFrame->mhWnd, NULL, FALSE );
4667                 UpdateWindow( pTempFrame->mhWnd );
4668                 pTempFrame->CallCallback( SALEVENT_DISPLAYCHANGED, 0 );
4669             }
4670             pTempFrame = pTempFrame->mpNextFrame;
4671         }
4672     }
4673 
4674     pSalData->mbInPalChange = FALSE;
4675 
4676     if ( bReleaseMutex )
4677         ImplSalYieldMutexRelease();
4678 
4679     if ( nMsg == WM_PALETTECHANGED )
4680         return 0;
4681     else
4682         return nCols;
4683 }
4684 
4685 // -----------------------------------------------------------------------
4686 
ImplHandleMinMax(HWND hWnd,LPARAM lParam)4687 static int ImplHandleMinMax( HWND hWnd, LPARAM lParam )
4688 {
4689     int bRet = FALSE;
4690 
4691     if ( ImplSalYieldMutexTryToAcquire() )
4692     {
4693         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4694         if ( pFrame )
4695         {
4696             MINMAXINFO* pMinMax = (MINMAXINFO*)lParam;
4697 
4698             if ( pFrame->mbFullScreen )
4699             {
4700                 int         nX;
4701                 int         nY;
4702                 int         nDX;
4703                 int         nDY;
4704                 ImplSalCalcFullScreenSize( pFrame, nX, nY, nDX, nDY );
4705 
4706                 if ( pMinMax->ptMaxPosition.x > nX )
4707                     pMinMax->ptMaxPosition.x = nX;
4708                 if ( pMinMax->ptMaxPosition.y > nY )
4709                     pMinMax->ptMaxPosition.y = nY;
4710 
4711                 if ( pMinMax->ptMaxSize.x < nDX )
4712                     pMinMax->ptMaxSize.x = nDX;
4713                 if ( pMinMax->ptMaxSize.y < nDY )
4714                     pMinMax->ptMaxSize.y = nDY;
4715                 if ( pMinMax->ptMaxTrackSize.x < nDX )
4716                     pMinMax->ptMaxTrackSize.x = nDX;
4717                 if ( pMinMax->ptMaxTrackSize.y < nDY )
4718                     pMinMax->ptMaxTrackSize.y = nDY;
4719 
4720                 pMinMax->ptMinTrackSize.x = nDX;
4721                 pMinMax->ptMinTrackSize.y = nDY;
4722 
4723                 bRet = TRUE;
4724             }
4725 
4726             if ( pFrame->mnMinWidth || pFrame->mnMinHeight )
4727             {
4728                 int nWidth   = pFrame->mnMinWidth;
4729                 int nHeight  = pFrame->mnMinHeight;
4730 
4731                 ImplSalAddBorder( pFrame, nWidth, nHeight );
4732 
4733                 if ( pMinMax->ptMinTrackSize.x < nWidth )
4734                      pMinMax->ptMinTrackSize.x = nWidth;
4735                 if ( pMinMax->ptMinTrackSize.y < nHeight )
4736                      pMinMax->ptMinTrackSize.y = nHeight;
4737             }
4738 
4739             if ( pFrame->mnMaxWidth || pFrame->mnMaxHeight )
4740             {
4741                 int nWidth   = pFrame->mnMaxWidth;
4742                 int nHeight  = pFrame->mnMaxHeight;
4743 
4744                 ImplSalAddBorder( pFrame, nWidth, nHeight );
4745 
4746                 if( nWidth > 0 && nHeight > 0 ) // protect against int overflow due to INT_MAX initialization
4747                 {
4748                     if ( pMinMax->ptMaxTrackSize.x > nWidth )
4749                         pMinMax->ptMaxTrackSize.x = nWidth;
4750                     if ( pMinMax->ptMaxTrackSize.y > nHeight )
4751                         pMinMax->ptMaxTrackSize.y = nHeight;
4752                 }
4753             }
4754         }
4755 
4756         ImplSalYieldMutexRelease();
4757     }
4758 
4759     return bRet;
4760 }
4761 
4762 // -----------------------------------------------------------------------
4763 
4764 // retrieves the SalMenuItem pointer from a hMenu
4765 // the pointer is stored in every item, so if no position
4766 // is specified we just use the first item (i.e. pos=0)
4767 // if bByPosition is FALSE then nPos denotes a menu id instead of a position
ImplGetSalMenuItem(HMENU hMenu,UINT nPos,sal_Bool bByPosition=TRUE)4768 static WinSalMenuItem* ImplGetSalMenuItem( HMENU hMenu, UINT nPos, sal_Bool bByPosition=TRUE )
4769 {
4770     DWORD err=0;
4771 
4772     MENUITEMINFOW mi;
4773     memset(&mi, 0, sizeof(mi));
4774     mi.cbSize = sizeof( mi );
4775     mi.fMask = MIIM_DATA;
4776     if( !GetMenuItemInfoW( hMenu, nPos, bByPosition, &mi) )
4777         err = GetLastError();
4778 
4779     return (WinSalMenuItem *) mi.dwItemData;
4780 }
4781 
4782 // returns the index of the currently selected item if any or -1
ImplGetSelectedIndex(HMENU hMenu)4783 static int ImplGetSelectedIndex( HMENU hMenu )
4784 {
4785     DWORD err=0;
4786 
4787     MENUITEMINFOW mi;
4788     memset(&mi, 0, sizeof(mi));
4789     mi.cbSize = sizeof( mi );
4790     mi.fMask = MIIM_STATE;
4791     int n = GetMenuItemCount( hMenu );
4792     if( n != -1 )
4793     {
4794         for(int i=0; i<n; i++ )
4795         {
4796             if( !GetMenuItemInfoW( hMenu, i, TRUE, &mi) )
4797                 err = GetLastError();
4798             else
4799             {
4800                 if( mi.fState & MFS_HILITE )
4801                     return i;
4802             }
4803         }
4804     }
4805     return -1;
4806 }
4807 
ImplMenuChar(HWND,WPARAM wParam,LPARAM lParam)4808 static int ImplMenuChar( HWND, WPARAM wParam, LPARAM lParam )
4809 {
4810     int nRet = MNC_IGNORE;
4811     HMENU hMenu = (HMENU) lParam;
4812     String aMnemonic;
4813     aMnemonic.AssignAscii("&");
4814     aMnemonic.Append( (sal_Unicode) LOWORD(wParam) );
4815     aMnemonic.ToLowerAscii();   // we only have ascii mnemonics
4816 
4817     // search the mnemonic in the current menu
4818     int nItemCount = GetMenuItemCount( hMenu );
4819     int nFound = 0;
4820     int idxFound = -1;
4821     int idxSelected = ImplGetSelectedIndex( hMenu );
4822     int idx = idxSelected != -1 ? idxSelected+1 : 0;    // if duplicate mnemonics cycle through menu
4823     for( int i=0; i< nItemCount; i++, idx++ )
4824     {
4825         WinSalMenuItem* pSalMenuItem = ImplGetSalMenuItem( hMenu, idx % nItemCount );
4826         if( !pSalMenuItem )
4827             continue;
4828         String aStr = pSalMenuItem->mText;
4829         aStr.ToLowerAscii();
4830         if( aStr.Search( aMnemonic ) != STRING_NOTFOUND)
4831         {
4832             if( idxFound == -1 )
4833                 idxFound = idx % nItemCount;
4834             if( nFound++ )
4835                 break;  // duplicate found
4836         }
4837     }
4838     if( nFound == 1 )
4839         nRet = MAKELRESULT( idxFound, MNC_EXECUTE );
4840     else
4841         // duplicate mnemonics, just select the next occurrence
4842         nRet = MAKELRESULT( idxFound, MNC_SELECT );
4843 
4844     return nRet;
4845 }
4846 
ImplMeasureItem(HWND hWnd,WPARAM wParam,LPARAM lParam)4847 static int ImplMeasureItem( HWND hWnd, WPARAM wParam, LPARAM lParam )
4848 {
4849     int nRet = 0;
4850     if( !wParam )
4851     {
4852         // request was sent by a menu
4853         nRet = 1;
4854         MEASUREITEMSTRUCT *pMI = (LPMEASUREITEMSTRUCT) lParam;
4855         if( pMI->CtlType != ODT_MENU )
4856             return 0;
4857 
4858         WinSalMenuItem *pSalMenuItem = (WinSalMenuItem *) pMI->itemData;
4859         if( !pSalMenuItem )
4860             return 0;
4861 
4862         HDC hdc = GetDC( hWnd );
4863         SIZE strSize;
4864 
4865         NONCLIENTMETRICS ncm;
4866         memset( &ncm, 0, sizeof(ncm) );
4867         ncm.cbSize = sizeof( ncm );
4868         SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0 );
4869 
4870         // Assume every menu item can be default and printed bold
4871         //ncm.lfMenuFont.lfWeight = FW_BOLD;
4872 
4873         HFONT hfntOld = (HFONT) SelectObject(hdc, (HFONT) CreateFontIndirect( &ncm.lfMenuFont ));
4874 
4875         // menu text and accelerator
4876         String aStr(pSalMenuItem->mText.GetBuffer() );
4877         if( pSalMenuItem->mAccelText.Len() )
4878         {
4879             aStr.AppendAscii(" ");
4880             aStr.Append( pSalMenuItem->mAccelText );
4881         }
4882         GetTextExtentPoint32W( hdc, (LPWSTR) aStr.GetBuffer(),
4883                                 aStr.Len(), &strSize );
4884 
4885         // image
4886         Size bmpSize( 16, 16 );
4887         //if( !!pSalMenuItem->maBitmap )
4888         //    bmpSize = pSalMenuItem->maBitmap.GetSizePixel();
4889 
4890         // checkmark
4891         Size checkSize( GetSystemMetrics( SM_CXMENUCHECK ), GetSystemMetrics( SM_CYMENUCHECK ) );
4892 
4893         pMI->itemWidth = checkSize.Width() + 3 + bmpSize.Width() + 3 + strSize.cx;
4894         pMI->itemHeight = Max( Max( checkSize.Height(), bmpSize.Height() ), strSize.cy );
4895         pMI->itemHeight += 4;
4896 
4897         DeleteObject( SelectObject(hdc, hfntOld) );
4898         ReleaseDC( hWnd, hdc );
4899     }
4900 
4901     return nRet;
4902 }
4903 
ImplDrawItem(HWND,WPARAM wParam,LPARAM lParam)4904 static int ImplDrawItem(HWND, WPARAM wParam, LPARAM lParam )
4905 {
4906     int nRet = 0;
4907     DWORD err = 0;
4908     if( !wParam )
4909     {
4910         // request was sent by a menu
4911         nRet = 1;
4912         DRAWITEMSTRUCT *pDI = (LPDRAWITEMSTRUCT) lParam;
4913         if( pDI->CtlType != ODT_MENU )
4914             return 0;
4915 
4916         WinSalMenuItem *pSalMenuItem = (WinSalMenuItem *) pDI->itemData;
4917         if( !pSalMenuItem )
4918             return 0;
4919 
4920         COLORREF clrPrevText, clrPrevBkgnd;
4921         HFONT hfntOld;
4922         HBRUSH hbrOld;
4923         sal_Bool    fChecked = (pDI->itemState & ODS_CHECKED) ? TRUE : FALSE;
4924         sal_Bool    fSelected = (pDI->itemState & ODS_SELECTED) ? TRUE : FALSE;
4925         sal_Bool    fDisabled = (pDI->itemState & (ODS_DISABLED | ODS_GRAYED)) ? TRUE : FALSE;
4926 
4927         // Set the appropriate foreground and background colors.
4928         RECT aRect = pDI->rcItem;
4929 
4930         clrPrevBkgnd = SetBkColor( pDI->hDC, GetSysColor( COLOR_MENU ) );
4931 
4932         if ( fDisabled )
4933             clrPrevText = SetTextColor( pDI->hDC, GetSysColor( COLOR_GRAYTEXT ) );
4934         else
4935             clrPrevText = SetTextColor( pDI->hDC, GetSysColor( fSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT ) );
4936 
4937         DWORD colBackground = GetSysColor( fSelected ? COLOR_HIGHLIGHT : COLOR_MENU );
4938         if ( fSelected )
4939             clrPrevBkgnd = SetBkColor( pDI->hDC, colBackground );
4940         else
4941             clrPrevBkgnd = SetBkColor( pDI->hDC, colBackground );
4942 
4943         hbrOld = (HBRUSH)SelectObject( pDI->hDC, CreateSolidBrush( GetBkColor( pDI->hDC ) ) );
4944 
4945         // Fill background
4946         if(!PatBlt( pDI->hDC, aRect.left, aRect.top, aRect.right-aRect.left, aRect.bottom-aRect.top, PATCOPY ))
4947             err = GetLastError();
4948 
4949         int lineHeight = aRect.bottom-aRect.top;
4950 
4951         int x = aRect.left;
4952         int y = aRect.top;
4953 
4954         int checkWidth  = GetSystemMetrics( SM_CXMENUCHECK );
4955         int checkHeight = GetSystemMetrics( SM_CYMENUCHECK );
4956         if( fChecked )
4957         {
4958             RECT r;
4959             r.left = 0;
4960             r.top = 0;
4961             r.right = checkWidth;
4962             r.bottom = checkWidth;
4963             HDC memDC = CreateCompatibleDC( pDI->hDC );
4964             HBITMAP memBmp = CreateCompatibleBitmap( pDI->hDC, checkWidth, checkHeight );
4965             HBITMAP hOldBmp = (HBITMAP) SelectObject( memDC, memBmp );
4966             DrawFrameControl( memDC, &r, DFC_MENU, DFCS_MENUCHECK );
4967             BitBlt( pDI->hDC, x, y+(lineHeight-checkHeight)/2, checkWidth, checkHeight, memDC, 0, 0, SRCAND );
4968             DeleteObject( SelectObject( memDC, hOldBmp ) );
4969             DeleteDC( memDC );
4970         }
4971         x += checkWidth+3;
4972 
4973         //Size bmpSize = aBitmap.GetSizePixel();
4974         Size bmpSize(16, 16);
4975         if( !!pSalMenuItem->maBitmap )
4976         {
4977             Bitmap aBitmap( pSalMenuItem->maBitmap );
4978 
4979             // set transparent pixels to background color
4980             if( fDisabled )
4981                 colBackground = RGB(255,255,255);
4982             aBitmap.Replace( Color( COL_LIGHTMAGENTA ),
4983                 Color( GetRValue(colBackground),GetGValue(colBackground),GetBValue(colBackground) ), 0);
4984 
4985             WinSalBitmap* pSalBmp = static_cast<WinSalBitmap*>(aBitmap.ImplGetImpBitmap()->ImplGetSalBitmap());
4986             HGLOBAL hDrawDIB = pSalBmp->ImplGethDIB();
4987 
4988             if( hDrawDIB )
4989             {
4990                 PBITMAPINFO         pBI = (PBITMAPINFO) GlobalLock( hDrawDIB );
4991                 PBITMAPINFOHEADER   pBIH = (PBITMAPINFOHEADER) pBI;
4992                 PBYTE               pBits = (PBYTE) pBI + *(DWORD*) pBI +
4993                                             pSalBmp->ImplGetDIBColorCount( hDrawDIB ) * sizeof( RGBQUAD );
4994 
4995                 HBITMAP hBmp = CreateDIBitmap( pDI->hDC, pBIH, CBM_INIT, pBits, pBI, DIB_RGB_COLORS );
4996                 GlobalUnlock( hDrawDIB );
4997 
4998                 HBRUSH hbrIcon = CreateSolidBrush( GetSysColor( COLOR_GRAYTEXT ) );
4999                 DrawStateW( pDI->hDC, (HBRUSH)hbrIcon, (DRAWSTATEPROC)NULL, (LPARAM)hBmp, (WPARAM)0,
5000                     x, y+(lineHeight-bmpSize.Height())/2, bmpSize.Width(), bmpSize.Height(),
5001                      DST_BITMAP | (fDisabled ? (fSelected ? DSS_MONO : DSS_DISABLED) : DSS_NORMAL) );
5002 
5003                 DeleteObject( hbrIcon );
5004                 DeleteObject( hBmp );
5005             }
5006 
5007         }
5008         x += bmpSize.Width() + 3;
5009         aRect.left = x;
5010 
5011         NONCLIENTMETRICS ncm;
5012         memset( &ncm, 0, sizeof(ncm) );
5013         ncm.cbSize = sizeof( ncm );
5014         SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0 );
5015 
5016         // Print default menu entry with bold font
5017         //if ( pDI->itemState & ODS_DEFAULT )
5018         //    ncm.lfMenuFont.lfWeight = FW_BOLD;
5019 
5020         hfntOld = (HFONT) SelectObject(pDI->hDC, (HFONT) CreateFontIndirect( &ncm.lfMenuFont ));
5021 
5022         SIZE strSize;
5023         String aStr( pSalMenuItem->mText.GetBuffer() );
5024         GetTextExtentPoint32W( pDI->hDC, (LPWSTR) aStr.GetBuffer(),
5025                                 aStr.Len(), &strSize );
5026 
5027         if(!DrawStateW( pDI->hDC, (HBRUSH)NULL, (DRAWSTATEPROC)NULL,
5028             (LPARAM)(LPWSTR) aStr.GetBuffer(),
5029             (WPARAM)0, aRect.left, aRect.top + (lineHeight - strSize.cy)/2, 0, 0,
5030             DST_PREFIXTEXT | (fDisabled && !fSelected ? DSS_DISABLED : DSS_NORMAL) ) )
5031             err = GetLastError();
5032 
5033         if( pSalMenuItem->mAccelText.Len() )
5034         {
5035             SIZE strSizeA;
5036             aStr = pSalMenuItem->mAccelText;
5037             GetTextExtentPoint32W( pDI->hDC, (LPWSTR) aStr.GetBuffer(),
5038                                     aStr.Len(), &strSizeA );
5039             TEXTMETRIC tm;
5040             GetTextMetrics( pDI->hDC, &tm );
5041 
5042             // position the accelerator string to the right but leave space for the
5043             // (potential) submenu arrow (tm.tmMaxCharWidth)
5044             if(!DrawStateW( pDI->hDC, (HBRUSH)NULL, (DRAWSTATEPROC)NULL,
5045                 (LPARAM)(LPWSTR) aStr.GetBuffer(),
5046                 (WPARAM)0, aRect.right-strSizeA.cx-tm.tmMaxCharWidth, aRect.top + (lineHeight - strSizeA.cy)/2, 0, 0,
5047                 DST_TEXT | (fDisabled && !fSelected ? DSS_DISABLED : DSS_NORMAL) ) )
5048                 err = GetLastError();
5049         }
5050 
5051         // Restore the original font and colors.
5052         DeleteObject( SelectObject( pDI->hDC, hbrOld ) );
5053         DeleteObject( SelectObject( pDI->hDC, hfntOld) );
5054         SetTextColor(pDI->hDC, clrPrevText);
5055         SetBkColor(pDI->hDC, clrPrevBkgnd);
5056     }
5057     return nRet;
5058 }
5059 
ImplHandleMenuActivate(HWND hWnd,WPARAM wParam,LPARAM)5060 static int ImplHandleMenuActivate( HWND hWnd, WPARAM wParam, LPARAM )
5061 {
5062     // Menu activation
5063     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5064     if ( !pFrame )
5065         return 0;
5066 
5067     HMENU hMenu = (HMENU) wParam;
5068     // WORD nPos = LOWORD (lParam);
5069     // sal_Bool bWindowMenu = (sal_Bool) HIWORD(lParam);
5070 
5071     // Send activate and deactivate together, so we have not keep track of opened menus
5072     // this will be enough to have the menus updated correctly
5073     SalMenuEvent aMenuEvt;
5074     WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, 0 );
5075     if( pSalMenuItem )
5076         aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5077     else
5078         aMenuEvt.mpMenu = NULL;
5079 
5080     long nRet = pFrame->CallCallback( SALEVENT_MENUACTIVATE, &aMenuEvt );
5081     if( nRet )
5082         nRet = pFrame->CallCallback( SALEVENT_MENUDEACTIVATE, &aMenuEvt );
5083     if( nRet )
5084         pFrame->mLastActivatedhMenu = hMenu;
5085 
5086     return (nRet!=0);
5087 }
5088 
ImplHandleMenuSelect(HWND hWnd,WPARAM wParam,LPARAM lParam)5089 static int ImplHandleMenuSelect( HWND hWnd, WPARAM wParam, LPARAM lParam )
5090 {
5091     // Menu selection
5092     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5093     if ( !pFrame )
5094         return 0;
5095 
5096     WORD nId = LOWORD(wParam);      // menu item or submenu index
5097     WORD nFlags = HIWORD(wParam);
5098     HMENU hMenu = (HMENU) lParam;
5099 
5100     // check if we have to process the message
5101     if( !GetSalData()->IsKnownMenuHandle( hMenu ) )
5102         return 0;
5103 
5104     sal_Bool bByPosition = FALSE;
5105     if( nFlags & MF_POPUP )
5106         bByPosition = TRUE;
5107 
5108     long nRet = 0;
5109     if ( hMenu && !pFrame->mLastActivatedhMenu )
5110     {
5111         // we never activated a menu (i.e. no WM_INITMENUPOPUP has occurred yet)
5112         // which means this must be the menubar -> send activation/deactivation
5113         SalMenuEvent aMenuEvt;
5114         WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, nId, bByPosition );
5115         if( pSalMenuItem )
5116             aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5117         else
5118             aMenuEvt.mpMenu = NULL;
5119 
5120         nRet = pFrame->CallCallback( SALEVENT_MENUACTIVATE, &aMenuEvt );
5121         if( nRet )
5122             nRet = pFrame->CallCallback( SALEVENT_MENUDEACTIVATE, &aMenuEvt );
5123         if( nRet )
5124             pFrame->mLastActivatedhMenu = hMenu;
5125     }
5126 
5127     if( !hMenu && nFlags == 0xFFFF )
5128     {
5129         // all menus are closed, reset activation logic
5130         pFrame->mLastActivatedhMenu = NULL;
5131     }
5132 
5133     if( hMenu )
5134     {
5135         // hMenu must be saved, as it is not passed in WM_COMMAND which always occurs after a selection
5136         // if a menu is closed due to a command selection then hMenu is NULL, but WM_COMMAND comes later
5137         // so we must not overwrite it in this case
5138         pFrame->mSelectedhMenu = hMenu;
5139 
5140         // send highlight event
5141         if( nFlags & MF_POPUP )
5142         {
5143             // submenu selected
5144             // wParam now carries an index instead of an id -> retrieve id
5145             MENUITEMINFOW mi;
5146             memset(&mi, 0, sizeof(mi));
5147             mi.cbSize = sizeof( mi );
5148             mi.fMask = MIIM_ID;
5149             if( GetMenuItemInfoW( hMenu, LOWORD(wParam), TRUE, &mi) )
5150                 nId = sal::static_int_cast<WORD>(mi.wID);
5151         }
5152 
5153         SalMenuEvent aMenuEvt;
5154         aMenuEvt.mnId   = nId;
5155         WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, nId, FALSE );
5156         if( pSalMenuItem )
5157             aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5158         else
5159             aMenuEvt.mpMenu = NULL;
5160 
5161         nRet = pFrame->CallCallback( SALEVENT_MENUHIGHLIGHT, &aMenuEvt );
5162     }
5163 
5164     return (nRet != 0);
5165 }
5166 
ImplHandleCommand(HWND hWnd,WPARAM wParam,LPARAM)5167 static int ImplHandleCommand( HWND hWnd, WPARAM wParam, LPARAM )
5168 {
5169     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5170     if ( !pFrame )
5171         return 0;
5172 
5173     long nRet = 0;
5174     if( !HIWORD(wParam) )
5175     {
5176         // Menu command
5177         WORD nId = LOWORD(wParam);
5178         if( nId )   // zero for separators
5179         {
5180             SalMenuEvent aMenuEvt;
5181             aMenuEvt.mnId   = nId;
5182             WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( pFrame->mSelectedhMenu, nId, FALSE );
5183             if( pSalMenuItem )
5184                 aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5185             else
5186                 aMenuEvt.mpMenu = NULL;
5187 
5188             nRet = pFrame->CallCallback( SALEVENT_MENUCOMMAND, &aMenuEvt );
5189         }
5190     }
5191     return (nRet != 0);
5192 }
5193 
ImplHandleSysCommand(HWND hWnd,WPARAM wParam,LPARAM lParam)5194 static int ImplHandleSysCommand( HWND hWnd, WPARAM wParam, LPARAM lParam )
5195 {
5196     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5197     if ( !pFrame )
5198         return 0;
5199 
5200     WPARAM nCommand = wParam & 0xFFF0;
5201 
5202     if ( pFrame->mbFullScreen )
5203     {
5204         BOOL    bMaximize = IsZoomed( pFrame->mhWnd );
5205         BOOL    bMinimize = IsIconic( pFrame->mhWnd );
5206         if ( (nCommand == SC_SIZE) ||
5207              (!bMinimize && (nCommand == SC_MOVE)) ||
5208              (!bMaximize && (nCommand == SC_MAXIMIZE)) ||
5209              (bMaximize && (nCommand == SC_RESTORE)) )
5210         {
5211             MessageBeep( 0 );
5212             return TRUE;
5213         }
5214     }
5215 
5216     if ( nCommand == SC_KEYMENU )
5217     {
5218         // do not process SC_KEYMENU if we have a native menu
5219         // Windows should handle this
5220         if( GetMenu( hWnd ) )
5221             return FALSE;
5222 
5223         // Hier verarbeiten wir nur KeyMenu-Events für Alt um
5224         // den MenuBar zu aktivieren, oder wenn ein SysChild-Fenster
5225         // den Focus hat, da diese Alt+Tasten-Kombinationen nur
5226         // über diesen Event verarbeitet werden
5227         if ( !LOWORD( lParam ) )
5228         {
5229             // Nur auslösen, wenn keine weitere Taste gedrückt ist. Im
5230             // Gegensatz zur Doku wird in der X-Koordinaate der CharCode
5231             // geliefert, der zusätzlich gedrückt ist
5232             // Also 32 für Space, 99 für c, 100 für d, ...
5233             // Da dies nicht dokumentiert ist, fragen wir vorsichtshalber
5234             // auch den Status der Space-Taste ab
5235             if ( GetKeyState( VK_SPACE ) & 0x8000 )
5236                 return 0;
5237 
5238             // Damit nicht bei Alt+Maustaste auch der MenuBar aktiviert wird
5239             if ( (GetKeyState( VK_LBUTTON ) & 0x8000) ||
5240                  (GetKeyState( VK_RBUTTON ) & 0x8000) ||
5241                  (GetKeyState( VK_MBUTTON ) & 0x8000) ||
5242                  (GetKeyState( VK_SHIFT )   & 0x8000) )
5243                 return 1;
5244 
5245             SalKeyEvent aKeyEvt;
5246             aKeyEvt.mnTime      = GetMessageTime();
5247             aKeyEvt.mnCode      = KEY_MENU;
5248             aKeyEvt.mnCharCode  = 0;
5249             aKeyEvt.mnRepeat    = 0;
5250             long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
5251             pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
5252             return (nRet != 0);
5253         }
5254         else
5255         {
5256             // Testen, ob ein SysChild den Focus hat
5257             HWND hFocusWnd = ::GetFocus();
5258             if ( hFocusWnd && ImplFindSalObject( hFocusWnd ) )
5259             {
5260                 char cKeyCode = (char)(unsigned char)LOWORD( lParam );
5261                 // LowerCase
5262                 if ( (cKeyCode >= 65) && (cKeyCode <= 90) )
5263                     cKeyCode += 32;
5264                 // Wir nehmen nur 0-9 und A-Z, alle anderen Tasten müssen durch
5265                 // den Hook vom SalObj verarbeitet werden
5266                 if ( ((cKeyCode >= 48) && (cKeyCode <= 57)) ||
5267                      ((cKeyCode >= 97) && (cKeyCode <= 122)) )
5268                 {
5269                     sal_uInt16 nModCode = 0;
5270                     if ( GetKeyState( VK_SHIFT ) & 0x8000 )
5271                         nModCode |= KEY_SHIFT;
5272                     if ( GetKeyState( VK_CONTROL ) & 0x8000 )
5273                         nModCode |= KEY_MOD1;
5274                     nModCode |= KEY_MOD2;
5275 
5276                     SalKeyEvent aKeyEvt;
5277                     aKeyEvt.mnTime      = GetMessageTime();
5278                     if ( (cKeyCode >= 48) && (cKeyCode <= 57) )
5279                         aKeyEvt.mnCode = KEY_0+(cKeyCode-48);
5280                     else
5281                         aKeyEvt.mnCode = KEY_A+(cKeyCode-97);
5282                     aKeyEvt.mnCode     |= nModCode;
5283                     aKeyEvt.mnCharCode  = cKeyCode;
5284                     aKeyEvt.mnRepeat    = 0;
5285                     long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
5286                     pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
5287                     return (nRet != 0);
5288                 }
5289             }
5290         }
5291     }
5292 
5293     return FALSE;
5294 }
5295 
5296 // -----------------------------------------------------------------------
5297 
ImplHandleInputLangChange(HWND hWnd,WPARAM,LPARAM lParam)5298 static void ImplHandleInputLangChange( HWND hWnd, WPARAM, LPARAM lParam )
5299 {
5300     ImplSalYieldMutexAcquireWithWait();
5301 
5302     // Feststellen, ob wir IME unterstützen
5303     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5304     if ( pFrame && pFrame->mbIME && pFrame->mhDefIMEContext )
5305     {
5306         HKL     hKL = (HKL)lParam;
5307         UINT    nImeProps = ImmGetProperty( hKL, IGP_PROPERTY );
5308 
5309         pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
5310         pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
5311         pFrame->mbHandleIME = !pFrame->mbSpezIME;
5312     }
5313 
5314     // trigger input language and codepage update
5315     UINT nLang = pFrame->mnInputLang;
5316     ImplUpdateInputLang( pFrame );
5317 
5318     // notify change
5319     if( nLang != pFrame->mnInputLang )
5320         pFrame->CallCallback( SALEVENT_INPUTLANGUAGECHANGE, 0 );
5321 
5322     ImplSalYieldMutexRelease();
5323 }
5324 
5325 // -----------------------------------------------------------------------
5326 
ImplUpdateIMECursorPos(WinSalFrame * pFrame,HIMC hIMC)5327 static void ImplUpdateIMECursorPos( WinSalFrame* pFrame, HIMC hIMC )
5328 {
5329     COMPOSITIONFORM aForm;
5330     memset( &aForm, 0, sizeof( aForm ) );
5331 
5332     // Cursor-Position ermitteln und aus der die Default-Position für
5333     // das Composition-Fenster berechnen
5334     SalExtTextInputPosEvent aPosEvt;
5335     pFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvt );
5336     if ( (aPosEvt.mnX == -1) && (aPosEvt.mnY == -1) )
5337         aForm.dwStyle |= CFS_DEFAULT;
5338     else
5339     {
5340         aForm.dwStyle          |= CFS_POINT;
5341         aForm.ptCurrentPos.x    = aPosEvt.mnX;
5342         aForm.ptCurrentPos.y    = aPosEvt.mnY;
5343     }
5344     ImmSetCompositionWindow( hIMC, &aForm );
5345 
5346     // Because not all IME's use this values, we create
5347     // a Windows caret to force the Position from the IME
5348     if ( GetFocus() == pFrame->mhWnd )
5349     {
5350         CreateCaret( pFrame->mhWnd, 0,
5351                      aPosEvt.mnWidth, aPosEvt.mnHeight );
5352         SetCaretPos( aPosEvt.mnX, aPosEvt.mnY );
5353     }
5354 }
5355 
5356 // -----------------------------------------------------------------------
5357 
ImplHandleIMEStartComposition(HWND hWnd)5358 static sal_Bool ImplHandleIMEStartComposition( HWND hWnd )
5359 {
5360     sal_Bool bDef = TRUE;
5361 
5362     ImplSalYieldMutexAcquireWithWait();
5363 
5364     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5365     if ( pFrame )
5366     {
5367         HIMC hIMC = ImmGetContext( hWnd );
5368         if ( hIMC )
5369         {
5370             ImplUpdateIMECursorPos( pFrame, hIMC );
5371             ImmReleaseContext( hWnd, hIMC );
5372         }
5373 
5374         if ( pFrame->mbHandleIME )
5375         {
5376             if ( pFrame->mbAtCursorIME )
5377                 bDef = FALSE;
5378         }
5379     }
5380 
5381     ImplSalYieldMutexRelease();
5382 
5383     return bDef;
5384 }
5385 
5386 // -----------------------------------------------------------------------
5387 
ImplHandleIMECompositionInput(WinSalFrame * pFrame,HIMC hIMC,LPARAM lParam)5388 static sal_Bool ImplHandleIMECompositionInput( WinSalFrame* pFrame,
5389                                            HIMC hIMC, LPARAM lParam )
5390 {
5391     sal_Bool bDef = TRUE;
5392 
5393     // Init Event
5394     SalExtTextInputEvent    aEvt;
5395     aEvt.mnTime             = GetMessageTime();
5396     aEvt.mpTextAttr         = NULL;
5397     aEvt.mnCursorPos        = 0;
5398     aEvt.mnDeltaStart       = 0;
5399     aEvt.mbOnlyCursor       = FALSE;
5400     aEvt.mnCursorFlags      = 0;
5401 
5402     // If we get a result string, then we handle this input
5403     if ( lParam & GCS_RESULTSTR )
5404     {
5405         bDef = FALSE;
5406 
5407         LONG nTextLen = ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, 0, 0 ) / sizeof( WCHAR );
5408         if ( nTextLen >= 0 )
5409         {
5410             WCHAR* pTextBuf = new WCHAR[nTextLen];
5411             ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, pTextBuf, nTextLen*sizeof( WCHAR ) );
5412             aEvt.maText = XubString( reinterpret_cast<const xub_Unicode*>(pTextBuf), (xub_StrLen)nTextLen );
5413             delete [] pTextBuf;
5414         }
5415 
5416         aEvt.mnCursorPos = aEvt.maText.Len();
5417         pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5418         pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
5419         ImplUpdateIMECursorPos( pFrame, hIMC );
5420     }
5421 
5422     // If the IME doesn't support OnSpot input, then there is nothing to do
5423     if ( !pFrame->mbAtCursorIME )
5424         return !bDef;
5425 
5426     // If we get new Composition data, then we handle this new input
5427     if ( (lParam & (GCS_COMPSTR | GCS_COMPATTR)) ||
5428          ((lParam & GCS_CURSORPOS) && !(lParam & GCS_RESULTSTR)) )
5429     {
5430         bDef = FALSE;
5431 
5432         sal_uInt16* pSalAttrAry = NULL;
5433         LONG    nTextLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, 0, 0 ) / sizeof( WCHAR );
5434         if ( nTextLen > 0 )
5435         {
5436             WCHAR* pTextBuf = new WCHAR[nTextLen];
5437             ImmGetCompositionStringW( hIMC, GCS_COMPSTR, pTextBuf, nTextLen*sizeof( WCHAR ) );
5438             aEvt.maText = XubString( reinterpret_cast<const xub_Unicode*>(pTextBuf), (xub_StrLen)nTextLen );
5439             delete [] pTextBuf;
5440 
5441             BYTE*   pAttrBuf = NULL;
5442             LONG        nAttrLen = ImmGetCompositionStringW( hIMC, GCS_COMPATTR, 0, 0 );
5443             if ( nAttrLen > 0 )
5444             {
5445                 pAttrBuf = new BYTE[nAttrLen];
5446                 ImmGetCompositionStringW( hIMC, GCS_COMPATTR, pAttrBuf, nAttrLen );
5447             }
5448 
5449             if ( pAttrBuf )
5450             {
5451                 xub_StrLen nTextLen = aEvt.maText.Len();
5452                 pSalAttrAry = new sal_uInt16[nTextLen];
5453                 memset( pSalAttrAry, 0, nTextLen*sizeof( sal_uInt16 ) );
5454                 for ( xub_StrLen i = 0; (i < nTextLen) && (i < nAttrLen); i++ )
5455                 {
5456                     BYTE nWinAttr = pAttrBuf[i];
5457                     sal_uInt16   nSalAttr;
5458                     if ( nWinAttr == ATTR_TARGET_CONVERTED )
5459                     {
5460                         nSalAttr = SAL_EXTTEXTINPUT_ATTR_BOLDUNDERLINE;
5461                         aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_INVISIBLE;
5462                     }
5463                     else if ( nWinAttr == ATTR_CONVERTED )
5464                         nSalAttr = SAL_EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE;
5465                     else if ( nWinAttr == ATTR_TARGET_NOTCONVERTED )
5466                         nSalAttr = SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
5467                     else if ( nWinAttr == ATTR_INPUT_ERROR )
5468                         nSalAttr = SAL_EXTTEXTINPUT_ATTR_REDTEXT | SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
5469                     else /* ( nWinAttr == ATTR_INPUT ) */
5470                         nSalAttr = SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
5471                     pSalAttrAry[i] = nSalAttr;
5472                 }
5473 
5474                 aEvt.mpTextAttr = pSalAttrAry;
5475                 delete [] pAttrBuf;
5476             }
5477         }
5478 
5479         // Only when we get new composition data, we must send this event
5480         if ( (nTextLen > 0) || !(lParam & GCS_RESULTSTR) )
5481         {
5482             // End the mode, if the last character is deleted
5483             if ( !nTextLen && !pFrame->mbCandidateMode )
5484             {
5485                 pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5486                 pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
5487             }
5488             else
5489             {
5490                 // Because Cursor-Position and DeltaStart never updated
5491                 // from the Korean input engine, we must handle this here
5492                 if ( lParam & CS_INSERTCHAR )
5493                 {
5494                     aEvt.mnCursorPos = nTextLen;
5495                     if ( aEvt.mnCursorPos && (lParam & CS_NOMOVECARET) )
5496                         aEvt.mnCursorPos--;
5497                 }
5498                 else
5499                     aEvt.mnCursorPos = LOWORD( ImmGetCompositionStringW( hIMC, GCS_CURSORPOS, 0, 0 ) );
5500 
5501                 if ( pFrame->mbCandidateMode )
5502                     aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_INVISIBLE;
5503                 if ( lParam & CS_NOMOVECARET )
5504                     aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_OVERWRITE;
5505 
5506                 pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5507             }
5508             ImplUpdateIMECursorPos( pFrame, hIMC );
5509         }
5510 
5511         if ( pSalAttrAry )
5512             delete [] pSalAttrAry;
5513     }
5514 
5515     return !bDef;
5516 }
5517 
5518 // -----------------------------------------------------------------------
5519 
ImplHandleIMEComposition(HWND hWnd,LPARAM lParam)5520 static sal_Bool ImplHandleIMEComposition( HWND hWnd, LPARAM lParam )
5521 {
5522     sal_Bool bDef = TRUE;
5523     ImplSalYieldMutexAcquireWithWait();
5524 
5525     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5526     if ( pFrame && (!lParam || (lParam & GCS_RESULTSTR)) )
5527     {
5528         // Wir restaurieren den Background-Modus bei jeder Texteingabe,
5529         // da einige Tools wie RichWin uns diesen hin- und wieder umsetzen
5530         if ( pFrame->mpGraphics &&
5531              pFrame->mpGraphics->getHDC() )
5532             SetBkMode( pFrame->mpGraphics->getHDC(), TRANSPARENT );
5533     }
5534 
5535     if ( pFrame && pFrame->mbHandleIME )
5536     {
5537         if ( !lParam )
5538         {
5539             SalExtTextInputEvent aEvt;
5540             aEvt.mnTime             = GetMessageTime();
5541             aEvt.mpTextAttr         = NULL;
5542             aEvt.mnCursorPos        = 0;
5543             aEvt.mnDeltaStart       = 0;
5544             aEvt.mbOnlyCursor       = FALSE;
5545             aEvt.mnCursorFlags      = 0;
5546             pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5547             pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
5548         }
5549         else if ( lParam & (GCS_RESULTSTR | GCS_COMPSTR | GCS_COMPATTR | GCS_CURSORPOS) )
5550         {
5551             HIMC hIMC = ImmGetContext( hWnd );
5552             if ( hIMC )
5553             {
5554                 if ( ImplHandleIMECompositionInput( pFrame, hIMC, lParam ) )
5555                     bDef = FALSE;
5556 
5557                 ImmReleaseContext( hWnd, hIMC );
5558             }
5559         }
5560     }
5561 
5562     ImplSalYieldMutexRelease();
5563     return bDef;
5564 }
5565 
5566 // -----------------------------------------------------------------------
5567 
ImplHandleIMEEndComposition(HWND hWnd)5568 static sal_Bool ImplHandleIMEEndComposition( HWND hWnd )
5569 {
5570     sal_Bool bDef = TRUE;
5571 
5572     ImplSalYieldMutexAcquireWithWait();
5573 
5574     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5575     if ( pFrame && pFrame->mbHandleIME )
5576     {
5577         if ( pFrame->mbAtCursorIME )
5578             bDef = FALSE;
5579     }
5580 
5581     ImplSalYieldMutexRelease();
5582 
5583     return bDef;
5584 }
5585 
5586 // -----------------------------------------------------------------------
5587 
ImplHandleAppCommand(HWND hWnd,LPARAM lParam)5588 static boolean ImplHandleAppCommand( HWND hWnd, LPARAM lParam )
5589 {
5590     sal_Int16 nCommand = 0;
5591     switch( GET_APPCOMMAND_LPARAM(lParam) )
5592     {
5593     case APPCOMMAND_MEDIA_CHANNEL_DOWN:         nCommand = MEDIA_COMMAND_CHANNEL_DOWN; break;
5594     case APPCOMMAND_MEDIA_CHANNEL_UP:           nCommand = MEDIA_COMMAND_CHANNEL_UP; break;
5595     case APPCOMMAND_MEDIA_NEXTTRACK:            nCommand = MEDIA_COMMAND_NEXTTRACK; break;
5596     case APPCOMMAND_MEDIA_PAUSE:                nCommand = MEDIA_COMMAND_PAUSE; break;
5597     case APPCOMMAND_MEDIA_PLAY:                 nCommand = MEDIA_COMMAND_PLAY; break;
5598     case APPCOMMAND_MEDIA_PLAY_PAUSE:           nCommand = MEDIA_COMMAND_PLAY_PAUSE; break;
5599     case APPCOMMAND_MEDIA_PREVIOUSTRACK:        nCommand = MEDIA_COMMAND_PREVIOUSTRACK; break;
5600     case APPCOMMAND_MEDIA_RECORD:               nCommand = MEDIA_COMMAND_RECORD; break;
5601     case APPCOMMAND_MEDIA_REWIND:               nCommand = MEDIA_COMMAND_REWIND; break;
5602     case APPCOMMAND_MEDIA_STOP:                 nCommand = MEDIA_COMMAND_STOP; break;
5603     case APPCOMMAND_MIC_ON_OFF_TOGGLE:          nCommand = MEDIA_COMMAND_MIC_ON_OFF_TOGGLE; break;
5604     case APPCOMMAND_MICROPHONE_VOLUME_DOWN:     nCommand = MEDIA_COMMAND_MICROPHONE_VOLUME_DOWN; break;
5605     case APPCOMMAND_MICROPHONE_VOLUME_MUTE:     nCommand = MEDIA_COMMAND_MICROPHONE_VOLUME_MUTE; break;
5606     case APPCOMMAND_MICROPHONE_VOLUME_UP:       nCommand = MEDIA_COMMAND_MICROPHONE_VOLUME_UP; break;
5607     case APPCOMMAND_VOLUME_DOWN:                nCommand = MEDIA_COMMAND_VOLUME_DOWN; break;
5608     case APPCOMMAND_VOLUME_MUTE:                nCommand = MEDIA_COMMAND_VOLUME_MUTE; break;
5609     case APPCOMMAND_VOLUME_UP:                  nCommand = MEDIA_COMMAND_VOLUME_UP; break;
5610         break;
5611     default:
5612         return false;
5613     }
5614 
5615     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5616     Window *pWindow = pFrame ? pFrame->GetWindow() : NULL;
5617 
5618     if( pWindow )
5619     {
5620         const Point aPoint;
5621         CommandEvent aCEvt( aPoint, COMMAND_MEDIA, FALSE, &nCommand );
5622         NotifyEvent aNCmdEvt( EVENT_COMMAND, pWindow, &aCEvt );
5623 
5624         if ( !ImplCallPreNotify( aNCmdEvt ) )
5625         {
5626             pWindow->Command( aCEvt );
5627             return true;
5628         }
5629     }
5630 
5631     return false;
5632 }
5633 
5634 
ImplHandleIMENotify(HWND hWnd,WPARAM wParam)5635 static void ImplHandleIMENotify( HWND hWnd, WPARAM wParam )
5636 {
5637     if ( wParam == (WPARAM)IMN_OPENCANDIDATE )
5638     {
5639         ImplSalYieldMutexAcquireWithWait();
5640 
5641         WinSalFrame* pFrame = GetWindowPtr( hWnd );
5642         if ( pFrame && pFrame->mbHandleIME &&
5643              pFrame->mbAtCursorIME )
5644         {
5645             // Wir wollen den Cursor hiden
5646             pFrame->mbCandidateMode = TRUE;
5647             ImplHandleIMEComposition( hWnd, GCS_CURSORPOS );
5648 
5649             HWND hWnd = pFrame->mhWnd;
5650             HIMC hIMC = ImmGetContext( hWnd );
5651             if ( hIMC )
5652             {
5653                 LONG nBufLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, 0, 0 );
5654                 if ( nBufLen >= 1 )
5655                 {
5656                     SalExtTextInputPosEvent aPosEvt;
5657                     pFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvt );
5658 
5659                     // Vertical !!!
5660                     CANDIDATEFORM aForm;
5661                     aForm.dwIndex           = 0;
5662                     aForm.dwStyle           = CFS_EXCLUDE;
5663                     aForm.ptCurrentPos.x    = aPosEvt.mnX;
5664                     aForm.ptCurrentPos.y    = aPosEvt.mnY+1;
5665                     aForm.rcArea.left       = aPosEvt.mnX;
5666                     aForm.rcArea.top        = aPosEvt.mnY;
5667                     aForm.rcArea.right      = aForm.rcArea.left+aPosEvt.mnExtWidth+1;
5668                     aForm.rcArea.bottom     = aForm.rcArea.top+aPosEvt.mnHeight+1;
5669                     ImmSetCandidateWindow( hIMC, &aForm );
5670                 }
5671 
5672                 ImmReleaseContext( hWnd, hIMC );
5673             }
5674         }
5675 
5676         ImplSalYieldMutexRelease();
5677     }
5678     else if ( wParam == (WPARAM)IMN_CLOSECANDIDATE )
5679     {
5680         ImplSalYieldMutexAcquireWithWait();
5681         WinSalFrame* pFrame = GetWindowPtr( hWnd );
5682         if ( pFrame )
5683             pFrame->mbCandidateMode = FALSE;
5684         ImplSalYieldMutexRelease();
5685     }
5686 }
5687 
5688 // -----------------------------------------------------------------------
5689 #if WINVER >= 0x0500
5690 
ImplHandleIMEReconvertString(HWND hWnd,LPARAM lParam)5691 static LRESULT ImplHandleIMEReconvertString( HWND hWnd, LPARAM lParam )
5692 {
5693     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5694     LPRECONVERTSTRING pReconvertString = (LPRECONVERTSTRING) lParam;
5695     LRESULT nRet = 0;
5696     SalSurroundingTextRequestEvent aEvt;
5697     aEvt.maText = UniString();
5698     aEvt.mnStart = aEvt.mnEnd = 0;
5699 
5700     UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_SETCOMPSTR );
5701     if( (nImeProps & SCS_CAP_SETRECONVERTSTRING) == 0 )
5702     {
5703     // This IME does not support reconversion.
5704     return 0;
5705     }
5706 
5707     if( !pReconvertString )
5708     {
5709     // The first call for reconversion.
5710     pFrame->CallCallback( SALEVENT_STARTRECONVERSION, (void*)NULL );
5711 
5712     // Retrieve the surrounding text from the focused control.
5713     pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTREQUEST, (void*)&aEvt );
5714 
5715     if( aEvt.maText.Len() == 0 )
5716     {
5717         return 0;
5718     }
5719 
5720     nRet = sizeof(RECONVERTSTRING) + (aEvt.maText.Len() + 1) * sizeof(WCHAR);
5721     }
5722     else
5723     {
5724     // The second call for reconversion.
5725 
5726     // Retrieve the surrounding text from the focused control.
5727     pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTREQUEST, (void*)&aEvt );
5728     nRet = sizeof(RECONVERTSTRING) + (aEvt.maText.Len() + 1) * sizeof(WCHAR);
5729 
5730     pReconvertString->dwStrOffset = sizeof(RECONVERTSTRING);
5731     pReconvertString->dwStrLen = aEvt.maText.Len();
5732     pReconvertString->dwCompStrOffset = aEvt.mnStart * sizeof(WCHAR);
5733     pReconvertString->dwCompStrLen = aEvt.mnEnd - aEvt.mnStart;
5734     pReconvertString->dwTargetStrOffset = pReconvertString->dwCompStrOffset;
5735     pReconvertString->dwTargetStrLen = pReconvertString->dwCompStrLen;
5736 
5737     memcpy( (LPWSTR)(pReconvertString + 1), aEvt.maText.GetBuffer(), (aEvt.maText.Len() + 1) * sizeof(WCHAR) );
5738     }
5739 
5740     // just return the required size of buffer to reconvert.
5741     return nRet;
5742 }
5743 
5744 // -----------------------------------------------------------------------
5745 
ImplHandleIMEConfirmReconvertString(HWND hWnd,LPARAM lParam)5746 static LRESULT ImplHandleIMEConfirmReconvertString( HWND hWnd, LPARAM lParam )
5747 {
5748     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5749     LPRECONVERTSTRING pReconvertString = (LPRECONVERTSTRING) lParam;
5750     SalSurroundingTextRequestEvent aEvt;
5751     aEvt.maText = UniString();
5752     aEvt.mnStart = aEvt.mnEnd = 0;
5753 
5754     pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTREQUEST, (void*)&aEvt );
5755 
5756     sal_uLong nTmpStart = pReconvertString->dwCompStrOffset / sizeof(WCHAR);
5757     sal_uLong nTmpEnd = nTmpStart + pReconvertString->dwCompStrLen;
5758 
5759     if( nTmpStart != aEvt.mnStart || nTmpEnd != aEvt.mnEnd )
5760     {
5761     SalSurroundingTextSelectionChangeEvent aSelEvt;
5762     aSelEvt.mnStart = nTmpStart;
5763     aSelEvt.mnEnd = nTmpEnd;
5764 
5765     pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTSELECTIONCHANGE, (void*)&aSelEvt );
5766     }
5767 
5768     return TRUE;
5769 }
5770 
5771 #endif // WINVER >= 0x0500
5772 
5773 // -----------------------------------------------------------------------
5774 
SalTestMouseLeave()5775 void SalTestMouseLeave()
5776 {
5777     SalData* pSalData = GetSalData();
5778 
5779     if ( pSalData->mhWantLeaveMsg && !::GetCapture() )
5780     {
5781         POINT aPt;
5782         GetCursorPos( &aPt );
5783         if ( pSalData->mhWantLeaveMsg != WindowFromPoint( aPt ) )
5784             ImplSendMessage( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, MAKELPARAM( aPt.x, aPt.y ) );
5785     }
5786 }
5787 
5788 // -----------------------------------------------------------------------
5789 
ImplSalWheelMousePos(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam,LRESULT & rResult)5790 static int ImplSalWheelMousePos( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ,
5791                                  LRESULT& rResult )
5792 {
5793     POINT aPt;
5794     POINT aScreenPt;
5795     aScreenPt.x = (short)LOWORD( lParam );
5796     aScreenPt.y = (short)HIWORD( lParam );
5797     // Child-Fenster suchen, welches an der entsprechenden
5798     // Position liegt
5799     HWND hChildWnd;
5800     HWND hWheelWnd = hWnd;
5801     do
5802     {
5803         hChildWnd = hWheelWnd;
5804         aPt = aScreenPt;
5805         ScreenToClient( hChildWnd, &aPt );
5806         hWheelWnd = ChildWindowFromPointEx( hChildWnd, aPt, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT );
5807     }
5808     while ( hWheelWnd && (hWheelWnd != hChildWnd) );
5809     if ( hWheelWnd && (hWheelWnd != hWnd) &&
5810          (hWheelWnd != ::GetFocus()) && IsWindowEnabled( hWheelWnd ) )
5811     {
5812         rResult = ImplSendMessage( hWheelWnd, nMsg, wParam, lParam );
5813         return FALSE;
5814     }
5815 
5816     return TRUE;
5817 }
5818 
5819 // -----------------------------------------------------------------------
5820 
SalFrameWndProc(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam,int & rDef)5821 LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
5822 {
5823     LRESULT     nRet = 0;
5824     static int  bInWheelMsg = FALSE;
5825     static int  bInQueryEnd = FALSE;
5826 
5827     // By WM_CREATE we connect the frame with the window handle
5828     if ( nMsg == WM_CREATE )
5829     {
5830         // Window-Instanz am Windowhandle speichern
5831         // Can also be used for the W-Version, because the struct
5832         // to access lpCreateParams is the same structure
5833         CREATESTRUCTA* pStruct = (CREATESTRUCTA*)lParam;
5834         WinSalFrame* pFrame = (WinSalFrame*)pStruct->lpCreateParams;
5835         if ( pFrame != 0 )
5836         {
5837             SetWindowPtr( hWnd, pFrame );
5838             // HWND schon hier setzen, da schon auf den Instanzdaten
5839             // gearbeitet werden kann, wenn Messages während
5840             // CreateWindow() gesendet werden
5841             pFrame->mhWnd = hWnd;
5842             pFrame->maSysData.hWnd = hWnd;
5843         }
5844         return 0;
5845     }
5846 
5847     ImplSVData* pSVData = ImplGetSVData();
5848     // #i72707# TODO: the mbDeInit check will not be needed
5849     // once all windows that are not properly closed on exit got fixed
5850     if( pSVData->mbDeInit )
5851         return 0;
5852 
5853     if ( WM_USER_SYSTEM_WINDOW_ACTIVATED == nMsg )
5854     {
5855         if (pSVData->mpIntroWindow)
5856             pSVData->mpIntroWindow->Hide();
5857 
5858         return 0;
5859     }
5860 
5861     bool bCheckTimers = false;
5862 
5863     switch( nMsg )
5864     {
5865         case WM_MOUSEMOVE:
5866         case WM_LBUTTONDOWN:
5867         case WM_MBUTTONDOWN:
5868         case WM_RBUTTONDOWN:
5869         case WM_LBUTTONUP:
5870         case WM_MBUTTONUP:
5871         case WM_RBUTTONUP:
5872         case WM_NCMOUSEMOVE:
5873         case SAL_MSG_MOUSELEAVE:
5874             ImplSalYieldMutexAcquireWithWait();
5875             rDef = !ImplHandleMouseMsg( hWnd, nMsg, wParam, lParam );
5876             ImplSalYieldMutexRelease();
5877             break;
5878 
5879         case WM_NCLBUTTONDOWN:
5880         case WM_NCMBUTTONDOWN:
5881         case WM_NCRBUTTONDOWN:
5882             ImplSalYieldMutexAcquireWithWait();
5883             ImplCallClosePopupsHdl( hWnd );   // close popups...
5884             ImplSalYieldMutexRelease();
5885             break;
5886 
5887         case WM_MOUSEACTIVATE:
5888             if ( LOWORD( lParam ) == HTCLIENT )
5889             {
5890                 ImplSalYieldMutexAcquireWithWait();
5891                 nRet = ImplHandleMouseActivateMsg( hWnd );
5892                 ImplSalYieldMutexRelease();
5893                 if ( nRet )
5894                 {
5895                     nRet = MA_NOACTIVATE;
5896                     rDef = FALSE;
5897                 }
5898             }
5899             break;
5900 
5901         case WM_KEYDOWN:
5902         case WM_KEYUP:
5903         case WM_DEADCHAR:
5904         case WM_CHAR:
5905         case WM_UNICHAR:    // MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0
5906         case WM_SYSKEYDOWN:
5907         case WM_SYSKEYUP:
5908         case WM_SYSCHAR:
5909             ImplSalYieldMutexAcquireWithWait();
5910             rDef = !ImplHandleKeyMsg( hWnd, nMsg, wParam, lParam, nRet );
5911             ImplSalYieldMutexRelease();
5912             break;
5913 
5914         case WM_MOUSEWHEEL:
5915             // FALLTHROUGH intended
5916         case WM_MOUSEHWHEEL:
5917             // Gegen Rekursion absichern, falls wir vom IE oder dem externen
5918             // Fenster die Message wieder zurückbekommen
5919             if ( !bInWheelMsg )
5920             {
5921                 bInWheelMsg++;
5922                 rDef = !ImplHandleWheelMsg( hWnd, nMsg, wParam, lParam );
5923                 // Wenn wir die Message nicht ausgewertet haben, schauen wir
5924                 // noch einmal nach, ob dort ein geplugtes Fenster steht,
5925                 // welches wir dann benachrichtigen
5926                 if ( rDef )
5927                     rDef = ImplSalWheelMousePos( hWnd, nMsg, wParam, lParam, nRet );
5928                 bInWheelMsg--;
5929             }
5930             break;
5931 
5932         case WM_COMMAND:
5933             ImplSalYieldMutexAcquireWithWait();
5934             rDef = !ImplHandleCommand( hWnd, wParam, lParam );
5935             ImplSalYieldMutexRelease();
5936             break;
5937 
5938         case WM_INITMENUPOPUP:
5939             ImplSalYieldMutexAcquireWithWait();
5940             rDef = !ImplHandleMenuActivate( hWnd, wParam, lParam );
5941             ImplSalYieldMutexRelease();
5942             break;
5943 
5944         case WM_MENUSELECT:
5945             ImplSalYieldMutexAcquireWithWait();
5946             rDef = !ImplHandleMenuSelect( hWnd, wParam, lParam );
5947             ImplSalYieldMutexRelease();
5948             break;
5949 
5950         case WM_SYSCOMMAND:
5951             ImplSalYieldMutexAcquireWithWait();
5952             nRet = ImplHandleSysCommand( hWnd, wParam, lParam );
5953             ImplSalYieldMutexRelease();
5954             if ( nRet )
5955                 rDef = FALSE;
5956             break;
5957 
5958         case WM_MENUCHAR:
5959             nRet = ImplMenuChar( hWnd, wParam, lParam );
5960             if( nRet )
5961                 rDef = FALSE;
5962             break;
5963 
5964         case WM_MEASUREITEM:
5965             nRet = ImplMeasureItem(hWnd, wParam, lParam);
5966             if( nRet )
5967                 rDef = FALSE;
5968             break;
5969 
5970         case WM_DRAWITEM:
5971             nRet = ImplDrawItem(hWnd, wParam, lParam);
5972             if( nRet )
5973                 rDef = FALSE;
5974             break;
5975 
5976         case WM_MOVE:
5977         case SAL_MSG_POSTMOVE:
5978             ImplHandleMoveMsg( hWnd );
5979             rDef = FALSE;
5980             break;
5981         case WM_SIZE:
5982             ImplHandleSizeMsg( hWnd, wParam, lParam );
5983             rDef = FALSE;
5984             break;
5985         case SAL_MSG_POSTCALLSIZE:
5986             ImplCallSizeHdl( hWnd );
5987             rDef = FALSE;
5988             break;
5989 
5990         case WM_GETMINMAXINFO:
5991             if ( ImplHandleMinMax( hWnd, lParam ) )
5992                 rDef = FALSE;
5993             break;
5994 
5995         case WM_ERASEBKGND:
5996             nRet = 1;
5997             rDef = FALSE;
5998             break;
5999         case WM_PAINT:
6000             bCheckTimers = ImplHandlePaintMsg( hWnd );
6001             rDef = FALSE;
6002             break;
6003         case SAL_MSG_POSTPAINT:
6004             ImplHandlePaintMsg2( hWnd, (RECT*)wParam );
6005             bCheckTimers = true;
6006             rDef = FALSE;
6007             break;
6008 
6009         case SAL_MSG_FORCEPALETTE:
6010             ImplHandleForcePalette( hWnd );
6011             rDef = FALSE;
6012             break;
6013 
6014         case WM_QUERYNEWPALETTE:
6015         case SAL_MSG_POSTQUERYNEWPAL:
6016             nRet = ImplHandlePalette( TRUE, hWnd, nMsg, wParam, lParam, rDef );
6017             break;
6018 
6019         case WM_ACTIVATE:
6020             // Wenn wir aktiviert werden, dann wollen wir auch unsere
6021             // Palette setzen. Wir machen dieses in Activate,
6022             // damit andere externe Child-Fenster auch unsere Palette
6023             // überschreiben können. So wird unsere jedenfalls nur einmal
6024             // gesetzt und nicht immer rekursiv, da an allen anderen Stellen
6025             // diese nur als Background-Palette gesetzt wird
6026             if ( LOWORD( wParam ) != WA_INACTIVE )
6027                 ImplSendMessage( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 );
6028             break;
6029 
6030         case WM_ENABLE:
6031             // #95133# a system dialog is opened/closed, using our app window as parent
6032             {
6033                 WinSalFrame* pFrame = GetWindowPtr( hWnd );
6034                 Window *pWin = NULL;
6035                 if( pFrame )
6036                     pWin = pFrame->GetWindow();
6037 
6038                 if( !wParam )
6039                 {
6040                     ImplSVData* pSVData = ImplGetSVData();
6041                     pSVData->maAppData.mnModalMode++;
6042 
6043                     // #106431#, hide SplashScreen
6044                     if( pSVData->mpIntroWindow )
6045                         pSVData->mpIntroWindow->Hide();
6046 
6047                     if( pWin )
6048                     {
6049                         pWin->EnableInput( FALSE, TRUE, TRUE, NULL );
6050                         pWin->ImplIncModalCount();  // #106303# support frame based modal count
6051                     }
6052                 }
6053                 else
6054                 {
6055                     ImplGetSVData()->maAppData.mnModalMode--;
6056                     if( pWin )
6057                     {
6058                         pWin->EnableInput( TRUE, TRUE, TRUE, NULL );
6059                         pWin->ImplDecModalCount();  // #106303# support frame based modal count
6060                     }
6061                 }
6062             }
6063             break;
6064 
6065         case WM_KILLFOCUS:
6066             DestroyCaret();
6067         case WM_SETFOCUS:
6068         case SAL_MSG_POSTFOCUS:
6069             ImplHandleFocusMsg( hWnd );
6070             rDef = FALSE;
6071             break;
6072 
6073         case WM_CLOSE:
6074             ImplHandleCloseMsg( hWnd );
6075             rDef = FALSE;
6076             break;
6077 
6078         case WM_QUERYENDSESSION:
6079             if( !bInQueryEnd )
6080             {
6081                 // handle queryendsession only once
6082                 bInQueryEnd = TRUE;
6083                 nRet = !ImplHandleShutDownMsg( hWnd );
6084                 rDef = FALSE;
6085 
6086                 // Issue #16314#: ImplHandleShutDownMsg causes a PostMessage in case of allowing shutdown.
6087                 // This posted message was never processed and cause Windows XP to hang after log off
6088                 // if there are multiple sessions and the current session wasn't the first one started.
6089                 // So if shutdown is allowed we assume that a post message was done and retrieve all
6090                 // messages in the message queue and dispatch them before we return control to the system.
6091 
6092                 if ( nRet )
6093                 {
6094                     MSG msg;
6095 
6096                     while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
6097                     {
6098                         DispatchMessage( &msg );
6099                     }
6100                 }
6101             }
6102             else
6103             {
6104                 ImplSalYieldMutexAcquireWithWait();
6105                 ImplSalYieldMutexRelease();
6106                 rDef = TRUE;
6107             }
6108             break;
6109 
6110         case WM_ENDSESSION:
6111             if( !wParam )
6112                 bInQueryEnd = FALSE; // no shutdown: allow query again
6113             nRet = FALSE;
6114             rDef = FALSE;
6115             break;
6116 
6117         case WM_DISPLAYCHANGE:
6118         case WM_SETTINGCHANGE:
6119         case WM_DEVMODECHANGE:
6120         case WM_FONTCHANGE:
6121         case WM_SYSCOLORCHANGE:
6122         case WM_TIMECHANGE:
6123             ImplHandleSettingsChangeMsg( hWnd, nMsg, wParam, lParam );
6124             break;
6125 
6126         case WM_THEMECHANGED:
6127             GetSalData()->mbThemeChanged = TRUE;
6128             break;
6129 
6130         case SAL_MSG_USEREVENT:
6131             ImplHandleUserEvent( hWnd, lParam );
6132             rDef = FALSE;
6133             break;
6134 
6135         case SAL_MSG_CAPTUREMOUSE:
6136             SetCapture( hWnd );
6137             rDef = FALSE;
6138             break;
6139         case SAL_MSG_RELEASEMOUSE:
6140             if ( ::GetCapture() == hWnd )
6141                 ReleaseCapture();
6142             rDef = FALSE;
6143             break;
6144         case SAL_MSG_TOTOP:
6145             ImplSalToTop( hWnd, (sal_uInt16)wParam );
6146             rDef = FALSE;
6147             break;
6148         case SAL_MSG_SHOW:
6149             ImplSalShow( hWnd, (sal_Bool)wParam, (sal_Bool)lParam );
6150             rDef = FALSE;
6151             break;
6152         case SAL_MSG_SETINPUTCONTEXT:
6153             ImplSalFrameSetInputContext( hWnd, (const SalInputContext*)(void*)lParam );
6154             rDef = FALSE;
6155             break;
6156         case SAL_MSG_ENDEXTTEXTINPUT:
6157             ImplSalFrameEndExtTextInput( hWnd, (sal_uInt16)(sal_uLong)(void*)wParam );
6158             rDef = FALSE;
6159             break;
6160 
6161         case WM_INPUTLANGCHANGE:
6162             ImplHandleInputLangChange( hWnd, wParam, lParam );
6163             break;
6164 
6165         case WM_IME_CHAR:
6166             // #103487#, some IMEs (e.g. those that do not work onspot)
6167             //           may send WM_IME_CHAR instead of WM_IME_COMPOSITION
6168             // we just handle it like a WM_CHAR message - seems to work fine
6169             ImplSalYieldMutexAcquireWithWait();
6170             rDef = !ImplHandleKeyMsg( hWnd, WM_CHAR, wParam, lParam, nRet );
6171             ImplSalYieldMutexRelease();
6172             break;
6173 
6174          case WM_IME_STARTCOMPOSITION:
6175             rDef = ImplHandleIMEStartComposition( hWnd );
6176             break;
6177 
6178         case WM_IME_COMPOSITION:
6179             rDef = ImplHandleIMEComposition( hWnd, lParam );
6180             break;
6181 
6182         case WM_IME_ENDCOMPOSITION:
6183             rDef = ImplHandleIMEEndComposition( hWnd );
6184             break;
6185 
6186         case WM_IME_NOTIFY:
6187             ImplHandleIMENotify( hWnd, wParam );
6188             break;
6189 
6190 #ifdef WNT
6191         case WM_GETOBJECT:
6192             {
6193                 if (!Application::IsEnableAccessInterface())
6194                 {
6195                     break;
6196                 }
6197                 else
6198                 {
6199                     // IA2 should be enabled automatically
6200                     AllSettings aSettings = Application::GetSettings();
6201                     MiscSettings aMisc = aSettings.GetMiscSettings();
6202                     aMisc.SetEnableATToolSupport( sal_True );
6203                     aSettings.SetMiscSettings( aMisc );
6204                     Application::SetSettings( aSettings );
6205 
6206                     if (Application::GetSettings().GetMiscSettings().GetEnableATToolSupport())
6207                     {
6208                         // Make sure to launch Accessibility only the following criteria are satisfied to avoid RFT interrupts regular acc processing
6209                         if (g_acc_manager1 == NULL)
6210                         {
6211                             sal_Bool bCancelled(sal_False);
6212                             InitAccessBridge(sal_False,bCancelled);
6213                             if( bCancelled )
6214                                 break;
6215                         }
6216                         if (g_acc_manager1 != NULL)
6217                         {
6218                             // MT: mhOnSetTitleWnd not set to reasonable value anywhere...
6219                             /*
6220                             sal_Bool bSkipSetTitleClient = sal_False;
6221                             SalFrame* pFrame = GetWindowPtr( hWnd );
6222                             if(pFrame)
6223                             {
6224                             bSkipSetTitleClient = (lParam == OBJID_CLIENT && hWnd == ((WinSalFrame*)pFrame)->mhOnSetTitleWnd);
6225                             }
6226                             */
6227                             if ( (lParam == OBJID_CLIENT ) /* && !bSkipSetTitleClient */ )
6228                             {
6229                                 long RetResult = g_acc_manager1->getAccObjectPtr((long)hWnd, lParam, wParam);
6230                                 if(RetResult != 0)
6231                                 {
6232                                     rDef = FALSE;
6233                                     return (HRESULT)RetResult;
6234                                 }
6235                             }
6236                         }
6237                     }
6238                 }
6239                 break;
6240             }
6241 #endif
6242 
6243         case WM_APPCOMMAND:
6244             if( ImplHandleAppCommand( hWnd, lParam ) )
6245             {
6246                 rDef = false;
6247                 nRet = 1;
6248             }
6249             break;
6250 #if WINVER >= 0x0500
6251         case WM_IME_REQUEST:
6252             if ( PtrToInt( wParam ) == IMR_RECONVERTSTRING )
6253             {
6254                 nRet = ImplHandleIMEReconvertString( hWnd, lParam );
6255                 rDef = FALSE;
6256             }
6257         else if( PtrToInt( wParam ) == IMR_CONFIRMRECONVERTSTRING )
6258         {
6259         nRet = ImplHandleIMEConfirmReconvertString( hWnd, lParam );
6260         rDef = FALSE;
6261         }
6262             break;
6263 #endif // WINVER >= 0x0500
6264     }
6265 
6266     // WheelMouse-Message abfangen
6267     if ( rDef && (nMsg == aSalShlData.mnWheelMsgId) && aSalShlData.mnWheelMsgId )
6268     {
6269         // Gegen Rekursion absichern, falls wir vom IE oder dem externen
6270         // Fenster die Message wieder zurückbekommen
6271         if ( !bInWheelMsg )
6272         {
6273             bInWheelMsg++;
6274             // Zuerst wollen wir die Message dispatchen und dann darf auch
6275             // das SystemWindow drankommen
6276             WORD nKeyState = 0;
6277             if ( GetKeyState( VK_SHIFT ) & 0x8000 )
6278                 nKeyState |= MK_SHIFT;
6279             if ( GetKeyState( VK_CONTROL ) & 0x8000 )
6280                 nKeyState |= MK_CONTROL;
6281             // Mutex handling is inside from this call
6282             rDef = !ImplHandleWheelMsg( hWnd,
6283                                         WM_MOUSEWHEEL,
6284                                         MAKEWPARAM( nKeyState, (WORD)wParam ),
6285                                         lParam );
6286             if ( rDef )
6287             {
6288                 HWND hWheelWnd = ::GetFocus();
6289                 if ( hWheelWnd && (hWheelWnd != hWnd) )
6290                 {
6291                     nRet = ImplSendMessage( hWheelWnd, nMsg, wParam, lParam );
6292                     rDef = FALSE;
6293                 }
6294                 else
6295                     rDef = ImplSalWheelMousePos( hWnd, nMsg, wParam, lParam, nRet );
6296             }
6297             bInWheelMsg--;
6298         }
6299     }
6300 
6301     if( bCheckTimers )
6302     {
6303         SalData* pSalData = GetSalData();
6304         if( pSalData->mnNextTimerTime )
6305         {
6306             DWORD nCurTime = GetTickCount();
6307             if( pSalData->mnNextTimerTime < nCurTime )
6308             {
6309                 MSG aMsg;
6310                 if( ! ImplPeekMessage( &aMsg, 0, WM_PAINT, WM_PAINT, PM_NOREMOVE | PM_NOYIELD ) )
6311                     ImplPostMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_POSTTIMER, 0, nCurTime );
6312             }
6313         }
6314     }
6315 
6316     return nRet;
6317 }
6318 
SalFrameWndProcA(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)6319 LRESULT CALLBACK SalFrameWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
6320 {
6321     int bDef = TRUE;
6322     LRESULT nRet = 0;
6323 #ifdef __MINGW32__
6324     jmp_buf jmpbuf;
6325     __SEHandler han;
6326     if (__builtin_setjmp(jmpbuf) == 0)
6327     {
6328         han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
6329 #else
6330     __try
6331     {
6332 #endif
6333         nRet = SalFrameWndProc( hWnd, nMsg, wParam, lParam, bDef );
6334     }
6335 #ifdef __MINGW32__
6336     han.Reset();
6337 #else
6338     __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
6339     {
6340     }
6341 #endif
6342     if ( bDef )
6343         nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
6344     return nRet;
6345 }
6346 
6347 LRESULT CALLBACK SalFrameWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
6348 {
6349     int bDef = TRUE;
6350     LRESULT nRet = 0;
6351 #ifdef __MINGW32__
6352     jmp_buf jmpbuf;
6353     __SEHandler han;
6354     if (__builtin_setjmp(jmpbuf) == 0)
6355     {
6356         han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
6357 #else
6358     __try
6359     {
6360 #endif
6361         nRet = SalFrameWndProc( hWnd, nMsg, wParam, lParam, bDef );
6362     }
6363 #ifdef __MINGW32__
6364     han.Reset();
6365 #else
6366     __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
6367     {
6368     }
6369 #endif
6370 
6371     if ( bDef )
6372         nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
6373     return nRet;
6374 }
6375 
6376 // -----------------------------------------------------------------------
6377 
6378 sal_Bool ImplHandleGlobalMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT& rlResult )
6379 {
6380     // handle all messages concerning all frames so they get processed only once
6381     // Must work for Unicode and none Unicode
6382     sal_Bool bResult = FALSE;
6383     if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) )
6384     {
6385         int bDef = TRUE;
6386         rlResult = ImplHandlePalette( FALSE, hWnd, nMsg, wParam, lParam, bDef );
6387         bResult = (bDef != 0);
6388     }
6389     else if( nMsg == WM_DISPLAYCHANGE )
6390     {
6391         WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem());
6392         if( pSys )
6393             pSys->clearMonitors();
6394         bResult = (pSys != NULL);
6395     }
6396     return bResult;
6397 }
6398 
6399 // -----------------------------------------------------------------------
6400 
6401 sal_Bool ImplWriteLastError( DWORD lastError, const char *szApiCall )
6402 {
6403     static int first=1;
6404     // if VCL_LOGFILE_ENABLED is set, Win32 API error messages can be written
6405     // to %TMP%/vcl.log or %TEMP%/vcl.log
6406     static char *logEnabled = getenv("VCL_LOGFILE_ENABLED");
6407     if( logEnabled )
6408     {
6409         sal_Bool bSuccess = FALSE;
6410         static char *szTmp = getenv("TMP");
6411         if( !szTmp || !*szTmp )
6412             szTmp = getenv("TEMP");
6413         if( szTmp && *szTmp )
6414         {
6415             char fname[5000];
6416             strcpy( fname, szTmp );
6417             if( fname[strlen(fname) - 1] != '\\' )
6418                 strcat( fname, "\\");
6419             strcat( fname, "vcl.log" );
6420             FILE *fp = fopen( fname, "a" ); // always append
6421             if( fp )
6422             {
6423                 if( first )
6424                 {
6425                     first = 0;
6426                     fprintf( fp, "Process ID: %d (0x%x)\n", GetCurrentProcessId(), GetCurrentProcessId() );
6427                 }
6428                 time_t aclock;
6429                 time( &aclock );                           // Get time in seconds
6430                 struct tm *newtime = localtime( &aclock ); // Convert time to struct tm form
6431                 fprintf( fp, asctime( newtime ) );         // print time stamp
6432 
6433                 fprintf( fp, "%s returned %u (0x%x)\n", szApiCall, lastError, lastError );
6434                 bSuccess = TRUE;    // may be FormatMessage fails but we wrote at least the error code
6435 
6436                 LPVOID lpMsgBuf;
6437                 if (FormatMessageA(
6438                     FORMAT_MESSAGE_ALLOCATE_BUFFER |
6439                     FORMAT_MESSAGE_FROM_SYSTEM |
6440                     FORMAT_MESSAGE_IGNORE_INSERTS,
6441                     NULL,
6442                     lastError,
6443                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
6444                     (LPSTR) &lpMsgBuf,
6445                     0,
6446                     NULL ))
6447                 {
6448                     fprintf( fp, " %s\n", (LPSTR)lpMsgBuf );
6449                     LocalFree( lpMsgBuf );
6450                 }
6451 
6452                 fclose( fp );
6453             }
6454         }
6455         return bSuccess;
6456     }
6457     else
6458         return TRUE;
6459 }
6460 
6461 // -----------------------------------------------------------------------
6462 
6463 #ifdef WNT
6464 bool IsWNTInitAccessBridge()
6465 {
6466     return NULL != g_acc_manager1;
6467 }
6468 #endif
6469 #ifdef WNT
6470 bool WNTEnableAccessInterface(bool bEnable)
6471 {
6472     ImplSVData* pSVData = ImplGetSVData();
6473 
6474     BOOL bPreVal = pSVData->maAppData.m_bEnableAccessInterface;
6475     long nEnable= bEnable;
6476     ::InterlockedExchange(
6477         (LPLONG)&(pSVData->maAppData.m_bEnableAccessInterface),
6478         nEnable);
6479 
6480     return bPreVal;
6481 }
6482 #endif
6483 
6484 /* vim: set noet sw=4 ts=4: */
6485