Add more tests for text placement in single and multiline edit
[wine] / dlls / user / msg16.c
1 /*
2  * 16-bit messaging support
3  *
4  * Copyright 2001 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "wine/winuser16.h"
22 #include "wownt32.h"
23 #include "winerror.h"
24 #include "win.h"
25 #include "user_private.h"
26 #include "winproc.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(msg);
30
31 DWORD USER16_AlertableWait = 0;
32
33 /***********************************************************************
34  *              SendMessage  (USER.111)
35  */
36 LRESULT WINAPI SendMessage16( HWND16 hwnd16, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
37 {
38     LRESULT result;
39     UINT msg32;
40     WPARAM wparam32;
41     HWND hwnd = WIN_Handle32( hwnd16 );
42
43     if (hwnd != HWND_BROADCAST && WIN_IsCurrentThread(hwnd))
44     {
45         /* call 16-bit window proc directly */
46         WNDPROC16 winproc;
47
48         /* first the WH_CALLWNDPROC hook */
49         if (HOOK_IsHooked( WH_CALLWNDPROC ))
50         {
51             LPARAM lparam32 = lparam;
52
53             if (WINPROC_MapMsg16To32A( hwnd, msg, wparam, &msg32, &wparam32, &lparam32 ) != -1)
54             {
55                 CWPSTRUCT cwp;
56
57                 cwp.hwnd    = hwnd;
58                 cwp.message = msg32;
59                 cwp.wParam  = wparam32;
60                 cwp.lParam  = lparam32;
61                 HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp, FALSE );
62                 WINPROC_UnmapMsg16To32A( hwnd, msg32, wparam32, lparam32, 0 );
63                 /* FIXME: should reflect changes back into the message we send */
64             }
65         }
66
67         if (!(winproc = (WNDPROC16)GetWindowLong16( hwnd16, GWLP_WNDPROC ))) return 0;
68
69         SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wparam, lparam );
70         result = CallWindowProc16( (WNDPROC16)winproc, hwnd16, msg, wparam, lparam );
71         SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, result, wparam, lparam );
72     }
73     else  /* map to 32-bit unicode for inter-thread/process message */
74     {
75         if (WINPROC_MapMsg16To32W( hwnd, msg, wparam, &msg32, &wparam32, &lparam ) == -1)
76             return 0;
77         result = WINPROC_UnmapMsg16To32W( hwnd, msg32, wparam32, lparam,
78                                           SendMessageW( hwnd, msg32, wparam32, lparam ) );
79     }
80     return result;
81 }
82
83
84 /***********************************************************************
85  *              PostMessage  (USER.110)
86  */
87 BOOL16 WINAPI PostMessage16( HWND16 hwnd16, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
88 {
89     WPARAM wparam32;
90     UINT msg32;
91     HWND hwnd = WIN_Handle32( hwnd16 );
92
93     switch (WINPROC_MapMsg16To32W( hwnd, msg, wparam, &msg32, &wparam32, &lparam ))
94     {
95     case 0:
96         return PostMessageW( hwnd, msg32, wparam32, lparam );
97     case 1:
98         ERR( "16-bit message 0x%04x contains pointer, cannot post\n", msg );
99         return FALSE;
100     default:
101         return FALSE;
102     }
103 }
104
105
106 /***********************************************************************
107  *              PostAppMessage (USER.116)
108  */
109 BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
110 {
111     WPARAM wparam32;
112     UINT msg32;
113     DWORD tid = HTASK_32( hTask );
114     if (!tid) return FALSE;
115
116     switch (WINPROC_MapMsg16To32W( 0, msg, wparam, &msg32, &wparam32, &lparam ))
117     {
118     case 0:
119         return PostThreadMessageW( tid, msg32, wparam32, lparam );
120     case 1:
121         ERR( "16-bit message %x contains pointer, cannot post\n", msg );
122         return FALSE;
123     default:
124         return FALSE;
125     }
126 }
127
128
129 /***********************************************************************
130  *              InSendMessage  (USER.192)
131  */
132 BOOL16 WINAPI InSendMessage16(void)
133 {
134     return InSendMessage();
135 }
136
137
138 /***********************************************************************
139  *              ReplyMessage  (USER.115)
140  */
141 void WINAPI ReplyMessage16( LRESULT result )
142 {
143     ReplyMessage( result );
144 }
145
146
147 /***********************************************************************
148  *              PeekMessage32 (USER.819)
149  */
150 BOOL16 WINAPI PeekMessage32_16( MSG32_16 *msg16, HWND16 hwnd16,
151                                 UINT16 first, UINT16 last, UINT16 flags,
152                                 BOOL16 wHaveParamHigh )
153 {
154     MSG msg;
155     HWND hwnd = WIN_Handle32( hwnd16 );
156
157     if(USER16_AlertableWait)
158         MsgWaitForMultipleObjectsEx( 0, NULL, 1, 0, MWMO_ALERTABLE );
159     if (!PeekMessageW( &msg, hwnd, first, last, flags )) return FALSE;
160
161     msg16->msg.hwnd    = HWND_16( msg.hwnd );
162     msg16->msg.lParam  = msg.lParam;
163     msg16->msg.time    = msg.time;
164     msg16->msg.pt.x    = (INT16)msg.pt.x;
165     msg16->msg.pt.y    = (INT16)msg.pt.y;
166     if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
167
168     return (WINPROC_MapMsg32WTo16( msg.hwnd, msg.message, msg.wParam,
169                                    &msg16->msg.message, &msg16->msg.wParam,
170                                    &msg16->msg.lParam ) != -1);
171 }
172
173
174 /***********************************************************************
175  *              DefWindowProc (USER.107)
176  */
177 LRESULT WINAPI DefWindowProc16( HWND16 hwnd16, UINT16 msg, WPARAM16 wParam, LPARAM lParam )
178 {
179     LRESULT result;
180     HWND hwnd = WIN_Handle32( hwnd16 );
181
182     SPY_EnterMessage( SPY_DEFWNDPROC16, hwnd, msg, wParam, lParam );
183
184     switch(msg)
185     {
186     case WM_NCCREATE:
187         {
188             CREATESTRUCT16 *cs16 = MapSL(lParam);
189             CREATESTRUCTA cs32;
190
191             cs32.lpCreateParams = (LPVOID)cs16->lpCreateParams;
192             cs32.hInstance      = HINSTANCE_32(cs16->hInstance);
193             cs32.hMenu          = HMENU_32(cs16->hMenu);
194             cs32.hwndParent     = WIN_Handle32(cs16->hwndParent);
195             cs32.cy             = cs16->cy;
196             cs32.cx             = cs16->cx;
197             cs32.y              = cs16->y;
198             cs32.x              = cs16->x;
199             cs32.style          = cs16->style;
200             cs32.dwExStyle      = cs16->dwExStyle;
201             cs32.lpszName       = MapSL(cs16->lpszName);
202             cs32.lpszClass      = MapSL(cs16->lpszClass);
203             result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)&cs32 );
204         }
205         break;
206
207     case WM_NCCALCSIZE:
208         {
209             RECT16 *rect16 = MapSL(lParam);
210             RECT rect32;
211
212             rect32.left    = rect16->left;
213             rect32.top     = rect16->top;
214             rect32.right   = rect16->right;
215             rect32.bottom  = rect16->bottom;
216
217             result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)&rect32 );
218
219             rect16->left   = rect32.left;
220             rect16->top    = rect32.top;
221             rect16->right  = rect32.right;
222             rect16->bottom = rect32.bottom;
223         }
224         break;
225
226     case WM_WINDOWPOSCHANGING:
227     case WM_WINDOWPOSCHANGED:
228         {
229             WINDOWPOS16 *pos16 = MapSL(lParam);
230             WINDOWPOS pos32;
231
232             pos32.hwnd             = WIN_Handle32(pos16->hwnd);
233             pos32.hwndInsertAfter  = WIN_Handle32(pos16->hwndInsertAfter);
234             pos32.x                = pos16->x;
235             pos32.y                = pos16->y;
236             pos32.cx               = pos16->cx;
237             pos32.cy               = pos16->cy;
238             pos32.flags            = pos16->flags;
239
240             result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)&pos32 );
241
242             pos16->hwnd            = HWND_16(pos32.hwnd);
243             pos16->hwndInsertAfter = HWND_16(pos32.hwndInsertAfter);
244             pos16->x               = pos32.x;
245             pos16->y               = pos32.y;
246             pos16->cx              = pos32.cx;
247             pos16->cy              = pos32.cy;
248             pos16->flags           = pos32.flags;
249         }
250         break;
251
252     case WM_GETTEXT:
253     case WM_SETTEXT:
254         result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)MapSL(lParam) );
255         break;
256
257     default:
258         result = DefWindowProcA( hwnd, msg, wParam, lParam );
259         break;
260     }
261
262     SPY_ExitMessage( SPY_RESULT_DEFWND16, hwnd, msg, result, wParam, lParam );
263     return result;
264 }
265
266
267 /***********************************************************************
268  *              PeekMessage  (USER.109)
269  */
270 BOOL16 WINAPI PeekMessage16( MSG16 *msg, HWND16 hwnd,
271                              UINT16 first, UINT16 last, UINT16 flags )
272 {
273     return PeekMessage32_16( (MSG32_16 *)msg, hwnd, first, last, flags, FALSE );
274 }
275
276
277 /***********************************************************************
278  *              GetMessage32  (USER.820)
279  */
280 BOOL16 WINAPI GetMessage32_16( MSG32_16 *msg16, HWND16 hwnd16, UINT16 first,
281                                UINT16 last, BOOL16 wHaveParamHigh )
282 {
283     MSG msg;
284     HWND hwnd = WIN_Handle32( hwnd16 );
285
286     do
287     {
288         if(USER16_AlertableWait)
289             MsgWaitForMultipleObjectsEx( 0, NULL, INFINITE, 0, MWMO_ALERTABLE );
290         GetMessageW( &msg, hwnd, first, last );
291         msg16->msg.hwnd    = HWND_16( msg.hwnd );
292         msg16->msg.lParam  = msg.lParam;
293         msg16->msg.time    = msg.time;
294         msg16->msg.pt.x    = (INT16)msg.pt.x;
295         msg16->msg.pt.y    = (INT16)msg.pt.y;
296         if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
297     }
298     while (WINPROC_MapMsg32WTo16( msg.hwnd, msg.message, msg.wParam,
299                                   &msg16->msg.message, &msg16->msg.wParam,
300                                   &msg16->msg.lParam ) == -1);
301
302     TRACE( "message %04x, hwnd %p, filter(%04x - %04x)\n",
303            msg16->msg.message, hwnd, first, last );
304
305     return msg16->msg.message != WM_QUIT;
306 }
307
308
309 /***********************************************************************
310  *              GetMessage  (USER.108)
311  */
312 BOOL16 WINAPI GetMessage16( MSG16 *msg, HWND16 hwnd, UINT16 first, UINT16 last )
313 {
314     return GetMessage32_16( (MSG32_16 *)msg, hwnd, first, last, FALSE );
315 }
316
317
318 /***********************************************************************
319  *              TranslateMessage32 (USER.821)
320  */
321 BOOL16 WINAPI TranslateMessage32_16( const MSG32_16 *msg, BOOL16 wHaveParamHigh )
322 {
323     MSG msg32;
324
325     msg32.hwnd    = WIN_Handle32( msg->msg.hwnd );
326     msg32.message = msg->msg.message;
327     msg32.wParam  = MAKEWPARAM( msg->msg.wParam, wHaveParamHigh ? msg->wParamHigh : 0 );
328     msg32.lParam  = msg->msg.lParam;
329     return TranslateMessage( &msg32 );
330 }
331
332
333 /***********************************************************************
334  *              TranslateMessage (USER.113)
335  */
336 BOOL16 WINAPI TranslateMessage16( const MSG16 *msg )
337 {
338     return TranslateMessage32_16( (const MSG32_16 *)msg, FALSE );
339 }
340
341
342 /***********************************************************************
343  *              DispatchMessage (USER.114)
344  */
345 LONG WINAPI DispatchMessage16( const MSG16* msg )
346 {
347     WND * wndPtr;
348     WNDPROC16 winproc;
349     LONG retval;
350     HWND hwnd = WIN_Handle32( msg->hwnd );
351
352       /* Process timer messages */
353     if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
354     {
355         if (msg->lParam)
356             return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
357                                      msg->message, msg->wParam, GetTickCount() );
358     }
359
360     if (!(wndPtr = WIN_GetPtr( hwnd )))
361     {
362         if (msg->hwnd) SetLastError( ERROR_INVALID_WINDOW_HANDLE );
363         return 0;
364     }
365     if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
366     {
367         if (IsWindow( hwnd )) SetLastError( ERROR_MESSAGE_SYNC_ONLY );
368         else SetLastError( ERROR_INVALID_WINDOW_HANDLE );
369         return 0;
370     }
371     winproc = (WNDPROC16)wndPtr->winproc;
372     WIN_ReleasePtr( wndPtr );
373
374     SPY_EnterMessage( SPY_DISPATCHMESSAGE16, hwnd, msg->message, msg->wParam, msg->lParam );
375     retval = CallWindowProc16( winproc, msg->hwnd, msg->message, msg->wParam, msg->lParam );
376     SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg->message, retval, msg->wParam, msg->lParam );
377
378     return retval;
379 }
380
381
382 /***********************************************************************
383  *              DispatchMessage32 (USER.822)
384  */
385 LONG WINAPI DispatchMessage32_16( const MSG32_16 *msg16, BOOL16 wHaveParamHigh )
386 {
387     if (wHaveParamHigh == FALSE)
388         return DispatchMessage16( &msg16->msg );
389     else
390     {
391         MSG msg;
392
393         msg.hwnd    = WIN_Handle32( msg16->msg.hwnd );
394         msg.message = msg16->msg.message;
395         msg.wParam  = MAKEWPARAM( msg16->msg.wParam, msg16->wParamHigh );
396         msg.lParam  = msg16->msg.lParam;
397         msg.time    = msg16->msg.time;
398         msg.pt.x    = msg16->msg.pt.x;
399         msg.pt.y    = msg16->msg.pt.y;
400         return DispatchMessageA( &msg );
401     }
402 }
403
404
405 /***********************************************************************
406  *              IsDialogMessage (USER.90)
407  */
408 BOOL16 WINAPI IsDialogMessage16( HWND16 hwndDlg, MSG16 *msg16 )
409 {
410     MSG msg;
411     HWND hwndDlg32;
412
413     msg.hwnd  = WIN_Handle32(msg16->hwnd);
414     hwndDlg32 = WIN_Handle32(hwndDlg);
415
416     switch(msg16->message)
417     {
418     case WM_KEYDOWN:
419     case WM_CHAR:
420     case WM_SYSCHAR:
421         msg.lParam = msg16->lParam;
422         WINPROC_MapMsg16To32W( msg.hwnd, msg16->message, msg16->wParam,
423                                &msg.message, &msg.wParam, &msg.lParam );
424         /* these messages don't need an unmap */
425         return IsDialogMessageW( hwndDlg32, &msg );
426     }
427
428     if ((hwndDlg32 != msg.hwnd) && !IsChild( hwndDlg32, msg.hwnd )) return FALSE;
429     TranslateMessage16( msg16 );
430     DispatchMessage16( msg16 );
431     return TRUE;
432 }
433
434
435 /***********************************************************************
436  *              MsgWaitForMultipleObjects  (USER.640)
437  */
438 DWORD WINAPI MsgWaitForMultipleObjects16( DWORD count, CONST HANDLE *handles,
439                                           BOOL wait_all, DWORD timeout, DWORD mask )
440 {
441     return MsgWaitForMultipleObjectsEx( count, handles, timeout, mask,
442                                         wait_all ? MWMO_WAITALL : 0 );
443 }
444
445
446 /**********************************************************************
447  *              SetDoubleClickTime (USER.20)
448  */
449 void WINAPI SetDoubleClickTime16( UINT16 interval )
450 {
451     SetDoubleClickTime( interval );
452 }
453
454
455 /**********************************************************************
456  *              GetDoubleClickTime (USER.21)
457  */
458 UINT16 WINAPI GetDoubleClickTime16(void)
459 {
460     return GetDoubleClickTime();
461 }
462
463
464 /***********************************************************************
465  *              PostQuitMessage (USER.6)
466  */
467 void WINAPI PostQuitMessage16( INT16 exitCode )
468 {
469     PostQuitMessage( exitCode );
470 }
471
472
473 /**********************************************************************
474  *              GetKeyState (USER.106)
475  */
476 INT16 WINAPI GetKeyState16(INT16 vkey)
477 {
478     return GetKeyState(vkey);
479 }
480
481
482 /**********************************************************************
483  *              GetKeyboardState (USER.222)
484  */
485 BOOL WINAPI GetKeyboardState16( LPBYTE state )
486 {
487     return GetKeyboardState( state );
488 }
489
490
491 /**********************************************************************
492  *              SetKeyboardState (USER.223)
493  */
494 BOOL WINAPI SetKeyboardState16( LPBYTE state )
495 {
496     return SetKeyboardState( state );
497 }
498
499
500 /***********************************************************************
501  *              SetMessageQueue (USER.266)
502  */
503 BOOL16 WINAPI SetMessageQueue16( INT16 size )
504 {
505     return SetMessageQueue( size );
506 }
507
508
509 /***********************************************************************
510  *              GetQueueStatus (USER.334)
511  */
512 DWORD WINAPI GetQueueStatus16( UINT16 flags )
513 {
514     return GetQueueStatus( flags );
515 }
516
517
518 /***********************************************************************
519  *              GetInputState (USER.335)
520  */
521 BOOL16 WINAPI GetInputState16(void)
522 {
523     return GetInputState();
524 }
525
526
527 /**********************************************************************
528  *           TranslateAccelerator      (USER.178)
529  */
530 INT16 WINAPI TranslateAccelerator16( HWND16 hwnd, HACCEL16 hAccel, LPMSG16 msg )
531 {
532     MSG msg32;
533
534     if (!msg) return 0;
535     msg32.message = msg->message;
536     /* msg32.hwnd not used */
537     msg32.wParam  = msg->wParam;
538     msg32.lParam  = msg->lParam;
539     return TranslateAcceleratorW( WIN_Handle32(hwnd), HACCEL_32(hAccel), &msg32 );
540 }
541
542
543 /**********************************************************************
544  *              TranslateMDISysAccel (USER.451)
545  */
546 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
547 {
548     if (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN)
549     {
550         MSG msg32;
551         msg32.hwnd    = WIN_Handle32(msg->hwnd);
552         msg32.message = msg->message;
553         msg32.wParam  = msg->wParam;
554         msg32.lParam  = msg->lParam;
555         /* MDICLIENTINFO is still the same for win32 and win16 ... */
556         return TranslateMDISysAccel( WIN_Handle32(hwndClient), &msg32 );
557     }
558     return 0;
559 }