Fixed some issues found by winapi_check.
[wine] / dlls / imm32 / imewnd.c
1 /*
2  *      Implementation of the 'IME window' class
3  *
4  *      Copyright 2000 Hidenori Takeshima
5  *
6  *
7  * FIXME:
8  *      - handle all messages.
9  *      - handle all notifications.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26 #include "config.h"
27
28 #include "winbase.h"
29 #include "windef.h"
30 #include "wingdi.h"
31 #include "winuser.h"
32 #include "winerror.h"
33 #include "immddk.h"
34
35 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(imm);
37
38 #include "imm_private.h"
39
40 #define IMM32_CONVERSION_BUFSIZE                200
41
42 static CHAR IMM32_szIMEClass[] = "IME";
43 static CHAR IMM32_szIMEWindowName[] = "Default IME";
44
45 typedef struct
46 {
47         HWND    hwndSelf;
48         HWND    hwndActive;
49         DWORD   dwBufUsed;
50         union
51         {
52                 CHAR    A[IMM32_CONVERSION_BUFSIZE];
53                 WCHAR   W[IMM32_CONVERSION_BUFSIZE];
54         }               buf;
55 } IMM32_IMEWNDPARAM;
56
57
58 static BOOL IMM32_IsUIMessage( UINT nMsg );
59
60 static
61 LRESULT IMM32_IMEWnd_WM_KEYDOWN( IMM32_IMEWNDPARAM* pParam,
62                                  WPARAM wParam, LPARAM lParam )
63 {
64         BYTE                    bKeyState[ 256 ];
65         DWORD                   dwTransBufSize;
66         UINT                    nNumOfMsg;
67         LRESULT                 lr;
68         HIMC                    hIMC;
69         IMM32_IMC*              pIMC;
70         const IMM32_IMEKL*      pkl;
71
72         if ( pParam->hwndActive == (HWND)NULL )
73                 return 0;
74
75         /* get context -> get pkl. */
76         hIMC = ImmGetContext( pParam->hwndActive );
77         if ( hIMC == NULLIMC )
78                 return 0;
79         pIMC = IMM32_LockIMC( hIMC );
80         if ( pIMC == NULL )
81         {
82                 ImmReleaseContext( pParam->hwndActive, hIMC );
83                 return 0;
84         }
85         pkl = pIMC->pkl;
86
87         GetKeyboardState( bKeyState );
88         if ( !pkl->handlers.pImeProcessKey
89                 ( hIMC, wParam, lParam, bKeyState ) )
90         {
91                 lr = SendMessageA( pParam->hwndActive, WM_IME_KEYDOWN,
92                                    wParam, lParam );
93                 goto end;
94         }
95
96         dwTransBufSize = 0;
97         nNumOfMsg = pkl->handlers.pImeToAsciiEx
98                 ( wParam, (lParam>>16)&0xff, 
99                   bKeyState, &dwTransBufSize,
100                   0, /* FIXME!!! - 1 if a menu is active */
101                   hIMC );
102
103         /* FIXME - process generated messages */
104         /* I cannot use ImmGenerateMessage() since
105          * the IME window must handle generated messages. */
106
107         /* NOTE - I must check pkl->fUnicode. */
108         FIXME( "%d messages generated.\n", nNumOfMsg );
109
110         lr = 0;
111 end:
112         IMM32_UnlockIMC( hIMC );
113         ImmReleaseContext( pParam->hwndActive, hIMC );
114
115         return lr;
116 }
117
118 static
119 LRESULT IMM32_IMEWnd_WM_KEYUP( IMM32_IMEWNDPARAM* pParam,
120                                WPARAM wParam, LPARAM lParam )
121 {
122         BYTE                    bKeyState[ 256 ];
123         LRESULT                 lr;
124         HIMC                    hIMC;
125         IMM32_IMC*              pIMC;
126         const IMM32_IMEKL*      pkl;
127
128         if ( pParam->hwndActive == (HWND)NULL )
129                 return 0;
130
131         /* get context -> get pkl. */
132         hIMC = ImmGetContext( pParam->hwndActive );
133         if ( hIMC == NULLIMC )
134                 return 0;
135         pIMC = IMM32_LockIMC( hIMC );
136         if ( pIMC == NULL )
137         {
138                 ImmReleaseContext( pParam->hwndActive, hIMC );
139                 return 0;
140         }
141         pkl = pIMC->pkl;
142
143         GetKeyboardState( bKeyState );
144         if ( !pkl->handlers.pImeProcessKey
145                 ( hIMC, wParam, lParam, bKeyState ) )
146         {
147                 lr = SendMessageA( pParam->hwndActive, WM_IME_KEYUP,
148                                    wParam, lParam );
149                 goto end;
150         }
151
152         lr = 0;
153 end:
154         IMM32_UnlockIMC( hIMC );
155         ImmReleaseContext( pParam->hwndActive, hIMC );
156
157         return lr;
158 }
159
160
161 static
162 LRESULT CALLBACK IMM32_IMEWndProc( HWND hwnd, UINT nMsg,
163                                    WPARAM wParam, LPARAM lParam )
164 {
165         IMM32_IMEWNDPARAM* pParam =
166                 (IMM32_IMEWNDPARAM*)GetWindowLongA( hwnd, 0L );
167
168         if ( nMsg == WM_CREATE )
169         {
170                 pParam = (IMM32_IMEWNDPARAM*)IMM32_HeapAlloc(
171                                 HEAP_ZERO_MEMORY, sizeof(IMM32_IMEWNDPARAM) );
172                 if ( pParam == NULL )
173                         return -1L;
174                 SetWindowLongA( hwnd, 0L, (LONG)pParam );
175
176                 /* Initialize pParam. */
177                 pParam->hwndSelf = hwnd;
178                 pParam->hwndActive = (HWND)NULL;
179                 pParam->dwBufUsed = 0;
180
181                 return 0;
182         }
183         else if ( nMsg == WM_DESTROY )
184         {
185                 /* Uninitialize pParam. */
186
187                 IMM32_HeapFree( pParam );
188                 SetWindowLongA( hwnd, 0L, (LONG)NULL );
189                 return 0;
190         }
191
192         if ( pParam == NULL )
193         {
194                 if ( IMM32_IsUIMessage( nMsg ) )
195                         return 0;
196                 return DefWindowProcA( hwnd, nMsg, wParam, lParam );
197         }
198
199         /* FIXME - handle all messages. */
200         /* FIXME - handle all notifications. */
201         switch ( nMsg )
202         {
203         case WM_KEYDOWN:
204                 return IMM32_IMEWnd_WM_KEYDOWN( pParam, wParam, lParam );
205         case WM_KEYUP:
206                 return IMM32_IMEWnd_WM_KEYUP( pParam, wParam, lParam );
207         case WM_IME_KEYDOWN:
208                 ERR( "Why WM_IME_KEYDOWN is generated?\n" );
209                 return 0;
210         case WM_IME_KEYUP:
211                 ERR( "Why WM_IME_KEYUP is generated?\n" );
212                 return 0;
213         case WM_IME_CHAR:
214                 FIXME( "ignore WM_IME_CHAR - wParam %08x, lParam %08lx.\n",
215                        wParam, lParam );
216                 return 0;
217         case WM_CHAR:
218                 /* TranslateMessage don't support IME HKL. - FIXME? */
219                 FIXME( "ignore WM_CHAR - wParam %08x, lParam %08lx.\n",
220                        wParam, lParam );
221                 return 0;
222         case WM_IME_CONTROL:
223         case WM_IME_REQUEST:
224         case WM_IME_STARTCOMPOSITION:
225         case WM_IME_ENDCOMPOSITION:
226         case WM_IME_COMPOSITION:
227         case WM_IME_SETCONTEXT:
228         case WM_IME_NOTIFY:
229         case WM_IME_COMPOSITIONFULL:
230         case WM_IME_SELECT:
231         case 0x287: /* What is this message? IMM32.DLL returns TRUE. */
232                 FIXME( "handle message %08x\n", nMsg );
233                 return 0;
234         }
235
236         return DefWindowProcA( hwnd, nMsg, wParam, lParam );
237 }
238
239
240 /***********************************************************************
241  *              IMM32_RegisterClass (internal)
242  */
243 BOOL IMM32_RegisterIMEWndClass( HINSTANCE hInstDLL )
244 {
245         WNDCLASSA       wc;
246
247         /* SDK says the "IME" window class is a system global class. */
248         wc.style                = CS_GLOBALCLASS;
249         wc.lpfnWndProc          = IMM32_IMEWndProc;
250         wc.cbClsExtra           = 0;
251         wc.cbWndExtra           = sizeof(LONG);
252         wc.hInstance            = hInstDLL;
253         wc.hIcon                = (HICON)NULL;
254         wc.hCursor              = LoadCursorA((HINSTANCE)NULL,IDC_ARROWA);
255         wc.hbrBackground        = (HBRUSH)NULL;
256         wc.lpszMenuName         = NULL;
257         wc.lpszClassName        = IMM32_szIMEClass;
258         if ( !RegisterClassA( &wc ) )
259                 return FALSE;
260
261         return TRUE;
262 }
263
264 /***********************************************************************
265  *              IMM32_UnregisterClass (internal)
266  */
267 void IMM32_UnregisterIMEWndClass( HINSTANCE hInstDLL )
268 {
269         (void)UnregisterClassA( IMM32_szIMEClass, hInstDLL );
270 }
271
272 /***********************************************************************
273  *              IMM32_CreateDefaultIMEWnd (internal)
274  */
275
276 HWND IMM32_CreateDefaultIMEWnd( void )
277 {
278         return CreateWindowExA( 0L,
279                                 IMM32_szIMEClass,
280                                 IMM32_szIMEWindowName,
281                                 WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED,
282                                 0, 0, 0, 0,
283                                 (HWND)NULL,
284                                 (HMENU)NULL,
285                                 (HINSTANCE)GetModuleHandleA(NULL),
286                                 NULL );
287 }
288
289 static BOOL IMM32_IsUIMessage( UINT nMsg )
290 {
291         switch ( nMsg )
292         {
293         case WM_IME_STARTCOMPOSITION:
294         case WM_IME_ENDCOMPOSITION:
295         case WM_IME_COMPOSITION:
296         case WM_IME_SETCONTEXT:
297         case WM_IME_NOTIFY:
298         case WM_IME_COMPOSITIONFULL:
299         case WM_IME_SELECT:
300         case 0x287: /* What is this message? IMM32.DLL returns TRUE. */
301                 return TRUE;
302         }
303
304         return FALSE;
305 }
306
307
308 /***********************************************************************
309  *              ImmIsUIMessageA (IMM32.@)
310  */
311 BOOL WINAPI ImmIsUIMessageA(
312         HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
313 {
314         TRACE("(0x%08x, %d, %d, %ld)\n",
315               hwndIME, msg, wParam, lParam);
316
317         if ( !IMM32_IsUIMessage( msg ) )
318                 return FALSE;
319         if ( hwndIME == (HWND)NULL )
320                 return TRUE;
321
322         switch ( msg )
323         {
324         case WM_IME_STARTCOMPOSITION:
325         case WM_IME_ENDCOMPOSITION:
326         case WM_IME_COMPOSITION:
327         case WM_IME_SETCONTEXT:
328         case WM_IME_NOTIFY:
329         case WM_IME_COMPOSITIONFULL:
330         case WM_IME_SELECT:
331                 SendMessageA( hwndIME, msg, wParam, lParam );
332                 break;
333         case 0x287: /* What is this message? */
334                 FIXME("(0x%08x, %d, %d, %ld) - unknown message 0x287.\n",
335                       hwndIME, msg, wParam, lParam);
336                 SendMessageA( hwndIME, msg, wParam, lParam );
337                 break;
338         }
339
340         return TRUE;
341 }
342
343 /***********************************************************************
344  *              ImmIsUIMessageW (IMM32.@)
345  */
346 BOOL WINAPI ImmIsUIMessageW(
347         HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
348 {
349         TRACE("(0x%08x, %d, %d, %ld)\n",
350               hwndIME, msg, wParam, lParam);
351
352         if ( !IMM32_IsUIMessage( msg ) )
353                 return FALSE;
354         if ( hwndIME == (HWND)NULL )
355                 return TRUE;
356
357         switch ( msg )
358         {
359         case WM_IME_STARTCOMPOSITION:
360         case WM_IME_ENDCOMPOSITION:
361         case WM_IME_COMPOSITION:
362         case WM_IME_SETCONTEXT:
363         case WM_IME_NOTIFY:
364         case WM_IME_COMPOSITIONFULL:
365         case WM_IME_SELECT:
366                 SendMessageW( hwndIME, msg, wParam, lParam );
367                 break;
368         case 0x287: /* What is this message? */
369                 FIXME("(0x%08x, %d, %d, %ld) - unknown message 0x287.\n",
370                       hwndIME, msg, wParam, lParam);
371                 SendMessageW( hwndIME, msg, wParam, lParam );
372                 break;
373         }
374
375         return TRUE;
376 }