Removed W->A from DEFWND_ImmIsUIMessageW.
[wine] / windows / defwnd.c
1 /*
2  * Default window procedure
3  *
4  * Copyright 1993, 1996 Alexandre Julliard
5  *           1995 Alex Korobka
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <string.h>
26 #include <stdarg.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "winnls.h"
32 #include "imm.h"
33 #include "win.h"
34 #include "user.h"
35 #include "controls.h"
36 #include "nonclient.h"
37 #include "winpos.h"
38 #include "dce.h"
39 #include "message.h"
40 #include "wine/unicode.h"
41 #include "wine/winuser16.h"
42 #include "wine/server.h"
43 #include "wine/debug.h"
44
45 WINE_DEFAULT_DEBUG_CHANNEL(win);
46
47   /* bits in the dwKeyData */
48 #define KEYDATA_ALT             0x2000
49 #define KEYDATA_PREVSTATE       0x4000
50
51 static short iF10Key = 0;
52 static short iMenuSysKey = 0;
53
54 /***********************************************************************
55  *           DEFWND_HandleWindowPosChanged
56  *
57  * Handle the WM_WINDOWPOSCHANGED message.
58  */
59 static void DEFWND_HandleWindowPosChanged( HWND hwnd, UINT flags )
60 {
61     RECT rect;
62     WND *wndPtr = WIN_GetPtr( hwnd );
63
64     rect = wndPtr->rectClient;
65     WIN_ReleasePtr( wndPtr );
66
67     if (!(flags & SWP_NOCLIENTMOVE))
68         SendMessageW( hwnd, WM_MOVE, 0, MAKELONG(rect.left, rect.top));
69
70     if (!(flags & SWP_NOCLIENTSIZE))
71     {
72         WPARAM wp = SIZE_RESTORED;
73         if (IsZoomed(hwnd)) wp = SIZE_MAXIMIZED;
74         else if (IsIconic(hwnd)) wp = SIZE_MINIMIZED;
75
76         SendMessageW( hwnd, WM_SIZE, wp, MAKELONG(rect.right-rect.left, rect.bottom-rect.top) );
77     }
78 }
79
80
81 /***********************************************************************
82  *           DEFWND_SetTextA
83  *
84  * Set the window text.
85  */
86 static void DEFWND_SetTextA( HWND hwnd, LPCSTR text )
87 {
88     int count;
89     WCHAR *textW;
90     WND *wndPtr;
91
92     if (!text) text = "";
93     count = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 );
94
95     if (!(wndPtr = WIN_GetPtr( hwnd ))) return;
96     if ((textW = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
97     {
98         if (wndPtr->text) HeapFree(GetProcessHeap(), 0, wndPtr->text);
99         wndPtr->text = textW;
100         MultiByteToWideChar( CP_ACP, 0, text, -1, textW, count );
101         SERVER_START_REQ( set_window_text )
102         {
103             req->handle = hwnd;
104             wine_server_add_data( req, textW, (count-1) * sizeof(WCHAR) );
105             wine_server_call( req );
106         }
107         SERVER_END_REQ;
108     }
109     else
110         ERR("Not enough memory for window text\n");
111     WIN_ReleasePtr( wndPtr );
112
113     if (USER_Driver.pSetWindowText) USER_Driver.pSetWindowText( hwnd, textW );
114 }
115
116 /***********************************************************************
117  *           DEFWND_SetTextW
118  *
119  * Set the window text.
120  */
121 static void DEFWND_SetTextW( HWND hwnd, LPCWSTR text )
122 {
123     static const WCHAR empty_string[] = {0};
124     WND *wndPtr;
125     int count;
126
127     if (!text) text = empty_string;
128     count = strlenW(text) + 1;
129
130     if (!(wndPtr = WIN_GetPtr( hwnd ))) return;
131     if (wndPtr->text) HeapFree(GetProcessHeap(), 0, wndPtr->text);
132     if ((wndPtr->text = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
133     {
134         strcpyW( wndPtr->text, text );
135         SERVER_START_REQ( set_window_text )
136         {
137             req->handle = hwnd;
138             wine_server_add_data( req, wndPtr->text, (count-1) * sizeof(WCHAR) );
139             wine_server_call( req );
140         }
141         SERVER_END_REQ;
142     }
143     else
144         ERR("Not enough memory for window text\n");
145     text = wndPtr->text;
146     WIN_ReleasePtr( wndPtr );
147
148     if (USER_Driver.pSetWindowText) USER_Driver.pSetWindowText( hwnd, text );
149 }
150
151 /***********************************************************************
152  *           DEFWND_ControlColor
153  *
154  * Default colors for control painting.
155  */
156 HBRUSH DEFWND_ControlColor( HDC hDC, UINT ctlType )
157 {
158     if( ctlType == CTLCOLOR_SCROLLBAR)
159     {
160         HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
161         COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
162         SetTextColor( hDC, GetSysColor(COLOR_3DFACE));
163         SetBkColor( hDC, bk);
164
165         /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
166          * we better use 0x55aa bitmap brush to make scrollbar's background
167          * look different from the window background.
168          */
169         if (bk == GetSysColor(COLOR_WINDOW))
170             return UITOOLS_GetPattern55AABrush();
171
172         UnrealizeObject( hb );
173         return hb;
174     }
175
176     SetTextColor( hDC, GetSysColor(COLOR_WINDOWTEXT));
177
178     if ((ctlType == CTLCOLOR_EDIT) || (ctlType == CTLCOLOR_LISTBOX))
179         SetBkColor( hDC, GetSysColor(COLOR_WINDOW) );
180     else {
181         SetBkColor( hDC, GetSysColor(COLOR_3DFACE) );
182         return GetSysColorBrush(COLOR_3DFACE);
183     }
184     return GetSysColorBrush(COLOR_WINDOW);
185 }
186
187
188 /***********************************************************************
189  *           DEFWND_SetRedraw
190  */
191 static void DEFWND_SetRedraw( HWND hwnd, WPARAM wParam )
192 {
193     WND *wndPtr = WIN_FindWndPtr( hwnd );
194     BOOL bVisible = wndPtr->dwStyle & WS_VISIBLE;
195
196     TRACE("%p %i\n", hwnd, (wParam!=0) );
197
198     if( wParam )
199     {
200         if( !bVisible )
201         {
202             WIN_SetStyle( hwnd, wndPtr->dwStyle | WS_VISIBLE );
203             DCE_InvalidateDCE( hwnd, &wndPtr->rectWindow );
204         }
205     }
206     else if( bVisible )
207     {
208         if( wndPtr->dwStyle & WS_MINIMIZE ) wParam = RDW_VALIDATE;
209         else wParam = RDW_ALLCHILDREN | RDW_VALIDATE;
210
211         RedrawWindow( hwnd, NULL, 0, wParam );
212         DCE_InvalidateDCE( hwnd, &wndPtr->rectWindow );
213         WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
214     }
215     WIN_ReleaseWndPtr( wndPtr );
216 }
217
218 /***********************************************************************
219  *           DEFWND_Print
220  *
221  * This method handles the default behavior for the WM_PRINT message.
222  */
223 static void DEFWND_Print( HWND hwnd, HDC hdc, ULONG uFlags)
224 {
225   /*
226    * Visibility flag.
227    */
228   if ( (uFlags & PRF_CHECKVISIBLE) &&
229        !IsWindowVisible(hwnd) )
230       return;
231
232   /*
233    * Unimplemented flags.
234    */
235   if ( (uFlags & PRF_CHILDREN) ||
236        (uFlags & PRF_OWNED)    ||
237        (uFlags & PRF_NONCLIENT) )
238   {
239     WARN("WM_PRINT message with unsupported flags\n");
240   }
241
242   /*
243    * Background
244    */
245   if ( uFlags & PRF_ERASEBKGND)
246     SendMessageW(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
247
248   /*
249    * Client area
250    */
251   if ( uFlags & PRF_CLIENT)
252     SendMessageW(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, PRF_CLIENT);
253 }
254
255
256 /*
257  * helpers for calling IMM32
258  *
259  * WM_IME_* messages are generated only by IMM32,
260  * so I assume imm32 is already LoadLibrary-ed.
261  */
262 static HWND DEFWND_ImmGetDefaultIMEWnd( HWND hwnd )
263 {
264     HINSTANCE hInstIMM = GetModuleHandleA( "imm32" );
265     HWND (WINAPI *pFunc)(HWND);
266     HWND hwndRet = 0;
267
268     if (!hInstIMM)
269     {
270         ERR( "cannot get IMM32 handle\n" );
271         return 0;
272     }
273
274     pFunc = (void*)GetProcAddress(hInstIMM,"ImmGetDefaultIMEWnd");
275     if ( pFunc != NULL )
276         hwndRet = (*pFunc)( hwnd );
277
278     return hwndRet;
279 }
280
281 static BOOL DEFWND_ImmIsUIMessageA( HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam )
282 {
283     HINSTANCE hInstIMM = GetModuleHandleA( "imm32" );
284     BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
285     BOOL fRet = FALSE;
286
287     if (!hInstIMM)
288     {
289         ERR( "cannot get IMM32 handle\n" );
290         return FALSE;
291     }
292
293     pFunc = (void*)GetProcAddress(hInstIMM,"ImmIsUIMessageA");
294     if ( pFunc != NULL )
295         fRet = (*pFunc)( hwndIME, msg, wParam, lParam );
296
297     return fRet;
298 }
299
300 static BOOL DEFWND_ImmIsUIMessageW( HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam )
301 {
302     static const WCHAR imm32W[] = {'i','m','m','3','2',0};
303
304     HINSTANCE hInstIMM = GetModuleHandleW( imm32W );
305     BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
306     BOOL fRet = FALSE;
307
308     if (!hInstIMM)
309     {
310         ERR( "cannot get IMM32 handle\n" );
311         return FALSE;
312     }
313
314     pFunc = (void*)GetProcAddress(hInstIMM,"ImmIsUIMessageW");
315     if ( pFunc != NULL )
316         fRet = (*pFunc)( hwndIME, msg, wParam, lParam );
317
318     return fRet;
319 }
320
321
322
323 /***********************************************************************
324  *           DEFWND_DefWinProc
325  *
326  * Default window procedure for messages that are the same in Win16 and Win32.
327  */
328 static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
329 {
330     switch(msg)
331     {
332     case WM_NCPAINT:
333         return NC_HandleNCPaint( hwnd, (HRGN)wParam );
334
335     case WM_NCHITTEST:
336         {
337             POINT pt;
338             pt.x = (short)LOWORD(lParam);
339             pt.y = (short)HIWORD(lParam);
340             return NC_HandleNCHitTest( hwnd, pt );
341         }
342
343     case WM_NCLBUTTONDOWN:
344         return NC_HandleNCLButtonDown( hwnd, wParam, lParam );
345
346     case WM_LBUTTONDBLCLK:
347     case WM_NCLBUTTONDBLCLK:
348         return NC_HandleNCLButtonDblClk( hwnd, wParam, lParam );
349
350     case WM_NCRBUTTONDOWN:
351         /* in Windows, capture is taken when right-clicking on the caption bar */
352         if (wParam==HTCAPTION)
353         {
354             SetCapture(hwnd);
355         }
356         break;
357
358     case WM_RBUTTONUP:
359         {
360             POINT pt;
361
362             if (hwnd == GetCapture())
363                 /* release capture if we took it on WM_NCRBUTTONDOWN */
364                 ReleaseCapture();
365
366             pt.x = (short)LOWORD(lParam);
367             pt.y = (short)HIWORD(lParam);
368             ClientToScreen(hwnd, &pt);
369             SendMessageW( hwnd, WM_CONTEXTMENU, (WPARAM)hwnd, MAKELPARAM(pt.x, pt.y) );
370         }
371         break;
372
373     case WM_NCRBUTTONUP:
374         /*
375          * FIXME : we must NOT send WM_CONTEXTMENU on a WM_NCRBUTTONUP (checked
376          * in Windows), but what _should_ we do? According to MSDN :
377          * "If it is appropriate to do so, the system sends the WM_SYSCOMMAND
378          * message to the window". When is it appropriate?
379          */
380         break;
381
382     case WM_CONTEXTMENU:
383         if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)
384             SendMessageW( GetParent(hwnd), msg, wParam, lParam );
385         else
386         {
387             LONG hitcode;
388             POINT pt;
389             WND *wndPtr = WIN_GetPtr( hwnd );
390             HMENU hMenu = wndPtr->hSysMenu;
391             WIN_ReleasePtr( wndPtr );
392             if (!hMenu) return 0;
393             pt.x = (short)LOWORD(lParam);
394             pt.y = (short)HIWORD(lParam);
395             hitcode = NC_HandleNCHitTest(hwnd, pt);
396
397             /* Track system popup if click was in the caption area. */
398             if (hitcode==HTCAPTION || hitcode==HTSYSMENU)
399                TrackPopupMenu(GetSystemMenu(hwnd, FALSE),
400                                TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
401                                pt.x, pt.y, 0, hwnd, NULL);
402         }
403         break;
404
405     case WM_NCACTIVATE:
406         return NC_HandleNCActivate( hwnd, wParam );
407
408     case WM_NCDESTROY:
409         {
410             WND *wndPtr = WIN_GetPtr( hwnd );
411             if (!wndPtr) return 0;
412             if (wndPtr->text) HeapFree( GetProcessHeap(), 0, wndPtr->text );
413             wndPtr->text = NULL;
414             if (wndPtr->pVScroll) HeapFree( GetProcessHeap(), 0, wndPtr->pVScroll );
415             if (wndPtr->pHScroll) HeapFree( GetProcessHeap(), 0, wndPtr->pHScroll );
416             wndPtr->pVScroll = wndPtr->pHScroll = NULL;
417             WIN_ReleasePtr( wndPtr );
418             return 0;
419         }
420
421     case WM_PRINT:
422         DEFWND_Print(hwnd, (HDC)wParam, lParam);
423         return 0;
424
425     case WM_PAINTICON:
426     case WM_PAINT:
427         {
428             PAINTSTRUCT ps;
429             HDC hdc = BeginPaint( hwnd, &ps );
430             if( hdc )
431             {
432               HICON hIcon;
433               if (IsIconic(hwnd) && ((hIcon = (HICON)GetClassLongW( hwnd, GCL_HICON))) )
434               {
435                   RECT rc;
436                   int x, y;
437
438                   GetClientRect( hwnd, &rc );
439                   x = (rc.right - rc.left - GetSystemMetrics(SM_CXICON))/2;
440                   y = (rc.bottom - rc.top - GetSystemMetrics(SM_CYICON))/2;
441                   TRACE("Painting class icon: vis rect=(%ld,%ld - %ld,%ld)\n",
442                         ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom );
443                   DrawIcon( hdc, x, y, hIcon );
444               }
445               EndPaint( hwnd, &ps );
446             }
447             return 0;
448         }
449
450     case WM_SYNCPAINT:
451         RedrawWindow ( hwnd, NULL, 0, RDW_ERASENOW | RDW_ERASE | RDW_ALLCHILDREN );
452         return 0;
453
454     case WM_SETREDRAW:
455         DEFWND_SetRedraw( hwnd, wParam );
456         return 0;
457
458     case WM_CLOSE:
459         DestroyWindow( hwnd );
460         return 0;
461
462     case WM_MOUSEACTIVATE:
463         if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)
464         {
465             LONG ret = SendMessageW( GetParent(hwnd), WM_MOUSEACTIVATE, wParam, lParam );
466             if (ret) return ret;
467         }
468
469         /* Caption clicks are handled by the NC_HandleNCLButtonDown() */
470         return (LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE;
471
472     case WM_ACTIVATE:
473         /* The default action in Windows is to set the keyboard focus to
474          * the window, if it's being activated and not minimized */
475         if (LOWORD(wParam) != WA_INACTIVE) {
476             if (!IsIconic(hwnd)) SetFocus(hwnd);
477         }
478         break;
479
480     case WM_MOUSEWHEEL:
481         if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)
482             return SendMessageW( GetParent(hwnd), WM_MOUSEWHEEL, wParam, lParam );
483         break;
484
485     case WM_ERASEBKGND:
486     case WM_ICONERASEBKGND:
487         {
488             RECT rect;
489             HDC hdc = (HDC)wParam;
490             HBRUSH hbr = (HBRUSH)GetClassLongW( hwnd, GCL_HBRBACKGROUND );
491             if (!hbr) return 0;
492
493             if (GetClassLongW( hwnd, GCL_STYLE ) & CS_PARENTDC)
494             {
495                 /* can't use GetClipBox with a parent DC or we fill the whole parent */
496                 GetClientRect( hwnd, &rect );
497                 DPtoLP( hdc, (LPPOINT)&rect, 2 );
498             }
499             else GetClipBox( hdc, &rect );
500             FillRect( hdc, &rect, hbr );
501             return 1;
502         }
503
504     case WM_GETDLGCODE:
505         return 0;
506
507     case WM_CTLCOLORMSGBOX:
508     case WM_CTLCOLOREDIT:
509     case WM_CTLCOLORLISTBOX:
510     case WM_CTLCOLORBTN:
511     case WM_CTLCOLORDLG:
512     case WM_CTLCOLORSTATIC:
513     case WM_CTLCOLORSCROLLBAR:
514         return (LRESULT)DEFWND_ControlColor( (HDC)wParam, msg - WM_CTLCOLORMSGBOX );
515
516     case WM_CTLCOLOR:
517         return (LRESULT)DEFWND_ControlColor( (HDC)wParam, HIWORD(lParam) );
518
519     case WM_SETCURSOR:
520         if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)
521         {
522             /* with the exception of the border around a resizable wnd,
523              * give the parent first chance to set the cursor */
524             if ((LOWORD(lParam) < HTSIZEFIRST) || (LOWORD(lParam) > HTSIZELAST))
525             {
526                 if (SendMessageW(GetParent(hwnd), WM_SETCURSOR, wParam, lParam)) return TRUE;
527             }
528         }
529         NC_HandleSetCursor( hwnd, wParam, lParam );
530         break;
531
532     case WM_SYSCOMMAND:
533         return NC_HandleSysCommand( hwnd, wParam, lParam );
534
535     case WM_KEYDOWN:
536         if(wParam == VK_F10) iF10Key = VK_F10;
537         break;
538
539     case WM_SYSKEYDOWN:
540         if( HIWORD(lParam) & KEYDATA_ALT )
541         {
542             /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
543               if( wParam == VK_MENU && !iMenuSysKey )
544                 iMenuSysKey = 1;
545               else
546                 iMenuSysKey = 0;
547
548             iF10Key = 0;
549
550             if( wParam == VK_F4 )       /* try to close the window */
551             {
552                 HWND top = GetAncestor( hwnd, GA_ROOT );
553                 if (!(GetClassLongW( top, GCL_STYLE ) & CS_NOCLOSE))
554                     PostMessageW( top, WM_SYSCOMMAND, SC_CLOSE, 0 );
555             }
556         }
557         else if( wParam == VK_F10 )
558             iF10Key = 1;
559         else if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
560             SendMessageW( hwnd, WM_SYSCOMMAND, SC_KEYMENU, ' ' );
561         break;
562
563     case WM_KEYUP:
564     case WM_SYSKEYUP:
565         /* Press and release F10 or ALT */
566         if (((wParam == VK_MENU) && iMenuSysKey) ||
567             ((wParam == VK_F10) && iF10Key))
568               SendMessageW( GetAncestor( hwnd, GA_ROOT ), WM_SYSCOMMAND, SC_KEYMENU, 0L );
569         iMenuSysKey = iF10Key = 0;
570         break;
571
572     case WM_SYSCHAR:
573     {
574         iMenuSysKey = 0;
575         if (wParam == '\r' && IsIconic(hwnd))
576         {
577             PostMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
578             break;
579         }
580         if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
581         {
582             if (wParam == '\t' || wParam == '\x1b') break;
583             if (wParam == ' ' && (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD))
584                 SendMessageW( GetParent(hwnd), msg, wParam, lParam );
585             else
586                 SendMessageW( hwnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
587         }
588         else /* check for Ctrl-Esc */
589             if (wParam != '\x1b') MessageBeep(0);
590         break;
591     }
592
593     case WM_SHOWWINDOW:
594         {
595             LONG style = GetWindowLongW( hwnd, GWL_STYLE );
596             if (!lParam) return 0; /* sent from ShowWindow */
597             if (!(style & WS_POPUP)) return 0;
598             if ((style & WS_VISIBLE) && wParam) return 0;
599             if (!(style & WS_VISIBLE) && !wParam) return 0;
600             if (!GetWindow( hwnd, GW_OWNER )) return 0;
601             ShowWindow( hwnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE );
602             break;
603         }
604
605     case WM_CANCELMODE:
606         if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
607         if (GetCapture() == hwnd) ReleaseCapture();
608         break;
609
610     case WM_VKEYTOITEM:
611     case WM_CHARTOITEM:
612         return -1;
613
614     case WM_DROPOBJECT:
615         return DRAG_FILE;
616
617     case WM_QUERYDROPOBJECT:
618         return (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
619
620     case WM_QUERYDRAGICON:
621         {
622             UINT len;
623
624             HICON hIcon = (HICON)GetClassLongW( hwnd, GCL_HICON );
625             HINSTANCE instance = (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
626             if (hIcon) return (LRESULT)hIcon;
627             for(len=1; len<64; len++)
628                 if((hIcon = LoadIconW(instance, MAKEINTRESOURCEW(len))))
629                     return (LRESULT)hIcon;
630             return (LRESULT)LoadIconW(0, (LPWSTR)IDI_APPLICATION);
631         }
632         break;
633
634     case WM_ISACTIVEICON:
635         {
636             WND *wndPtr = WIN_GetPtr( hwnd );
637             BOOL ret = (wndPtr->flags & WIN_NCACTIVATED) != 0;
638             WIN_ReleasePtr( wndPtr );
639             return ret;
640         }
641
642     case WM_NOTIFYFORMAT:
643       if (IsWindowUnicode(hwnd)) return NFR_UNICODE;
644       else return NFR_ANSI;
645
646     case WM_QUERYOPEN:
647     case WM_QUERYENDSESSION:
648         return 1;
649
650     case WM_SETICON:
651         {
652             HICON ret;
653             WND *wndPtr = WIN_GetPtr( hwnd );
654
655             switch(wParam)
656             {
657             case ICON_SMALL:
658                 ret = wndPtr->hIconSmall;
659                 wndPtr->hIconSmall = (HICON)lParam;
660                 break;
661             case ICON_BIG:
662                 ret = wndPtr->hIcon;
663                 wndPtr->hIcon = (HICON)lParam;
664                 break;
665             default:
666                 ret = 0;
667                 break;
668             }
669             WIN_ReleasePtr( wndPtr );
670
671             if (USER_Driver.pSetWindowIcon)
672                 USER_Driver.pSetWindowIcon( hwnd, wParam, (HICON)lParam );
673
674             SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE |
675                          SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
676
677             return (LRESULT)ret;
678         }
679
680     case WM_GETICON:
681         {
682             HICON ret;
683             WND *wndPtr = WIN_GetPtr( hwnd );
684
685             switch(wParam)
686             {
687             case ICON_SMALL:
688                 ret = wndPtr->hIconSmall;
689                 break;
690             case ICON_BIG:
691                 ret = wndPtr->hIcon;
692                 break;
693             case ICON_SMALL2:
694                 ret = wndPtr->hIconSmall;
695                 if (!ret) ret = (HICON)GetClassLongA( hwnd, GCL_HICONSM );
696                 /* FIXME: should have a default here if class icon is null */
697                 break;
698             default:
699                 ret = 0;
700                 break;
701             }
702             WIN_ReleasePtr( wndPtr );
703             return (LRESULT)ret;
704         }
705
706     case WM_HELP:
707         SendMessageW( GetParent(hwnd), msg, wParam, lParam );
708         break;
709     }
710
711     return 0;
712 }
713
714
715
716 /***********************************************************************
717  *              DefWindowProc (USER.107)
718  */
719 LRESULT WINAPI DefWindowProc16( HWND16 hwnd16, UINT16 msg, WPARAM16 wParam,
720                                 LPARAM lParam )
721 {
722     LRESULT result = 0;
723     HWND hwnd = WIN_Handle32( hwnd16 );
724
725     if (!WIN_IsCurrentProcess( hwnd ))
726     {
727         if (!IsWindow( hwnd )) return 0;
728         ERR( "called for other process window %p\n", hwnd );
729         return 0;
730     }
731     SPY_EnterMessage( SPY_DEFWNDPROC16, hwnd, msg, wParam, lParam );
732
733     switch(msg)
734     {
735     case WM_NCCREATE:
736         {
737             CREATESTRUCT16 *cs = MapSL(lParam);
738             /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
739              * may have child window IDs instead of window name */
740             if (HIWORD(cs->lpszName))
741                 DEFWND_SetTextA( hwnd, MapSL(cs->lpszName) );
742             result = 1;
743         }
744         break;
745
746     case WM_NCCALCSIZE:
747         {
748             RECT rect32;
749             RECT16 *rect16 = MapSL(lParam);
750
751             rect32.left   = rect16->left;
752             rect32.top    = rect16->top;
753             rect32.right  = rect16->right;
754             rect32.bottom = rect16->bottom;
755             result = NC_HandleNCCalcSize( hwnd, &rect32 );
756             rect16->left   = rect32.left;
757             rect16->top    = rect32.top;
758             rect16->right  = rect32.right;
759             rect16->bottom = rect32.bottom;
760         }
761         break;
762
763     case WM_WINDOWPOSCHANGING:
764         result = WINPOS_HandleWindowPosChanging16( hwnd, MapSL(lParam) );
765         break;
766
767     case WM_WINDOWPOSCHANGED:
768         {
769             WINDOWPOS16 * winPos = MapSL(lParam);
770             DEFWND_HandleWindowPosChanged( hwnd, winPos->flags );
771         }
772         break;
773
774     case WM_GETTEXT:
775     case WM_SETTEXT:
776         result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)MapSL(lParam) );
777         break;
778
779     default:
780         result = DefWindowProcA( hwnd, msg, wParam, lParam );
781         break;
782     }
783
784     SPY_ExitMessage( SPY_RESULT_DEFWND16, hwnd, msg, result, wParam, lParam );
785     return result;
786 }
787
788
789 /***********************************************************************
790  *              DefWindowProcA (USER32.@)
791  *
792  */
793 LRESULT WINAPI DefWindowProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
794 {
795     LRESULT result = 0;
796     HWND full_handle;
797
798     if (!(full_handle = WIN_IsCurrentProcess( hwnd )))
799     {
800         if (!IsWindow( hwnd )) return 0;
801         ERR( "called for other process window %p\n", hwnd );
802         return 0;
803     }
804     hwnd = full_handle;
805
806     SPY_EnterMessage( SPY_DEFWNDPROC, hwnd, msg, wParam, lParam );
807
808     switch(msg)
809     {
810     case WM_NCCREATE:
811         {
812             CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
813             /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
814              * may have child window IDs instead of window name */
815             if (HIWORD(cs->lpszName))
816                 DEFWND_SetTextA( hwnd, cs->lpszName );
817             result = 1;
818         }
819         break;
820
821     case WM_NCCALCSIZE:
822         result = NC_HandleNCCalcSize( hwnd, (RECT *)lParam );
823         break;
824
825     case WM_WINDOWPOSCHANGING:
826         result = WINPOS_HandleWindowPosChanging( hwnd, (WINDOWPOS *)lParam );
827         break;
828
829     case WM_WINDOWPOSCHANGED:
830         {
831             WINDOWPOS * winPos = (WINDOWPOS *)lParam;
832             DEFWND_HandleWindowPosChanged( hwnd, winPos->flags );
833         }
834         break;
835
836     case WM_GETTEXTLENGTH:
837         {
838             WND *wndPtr = WIN_GetPtr( hwnd );
839             if (wndPtr && wndPtr->text)
840                 result = WideCharToMultiByte( CP_ACP, 0, wndPtr->text, strlenW(wndPtr->text),
841                                               NULL, 0, NULL, NULL );
842             WIN_ReleasePtr( wndPtr );
843         }
844         break;
845
846     case WM_GETTEXT:
847         if (wParam)
848         {
849             LPSTR dest = (LPSTR)lParam;
850             WND *wndPtr = WIN_GetPtr( hwnd );
851
852             if (!wndPtr) break;
853             if (wndPtr->text)
854             {
855                 if (!WideCharToMultiByte( CP_ACP, 0, wndPtr->text, -1,
856                                           dest, wParam, NULL, NULL )) dest[wParam-1] = 0;
857                 result = strlen( dest );
858             }
859             else dest[0] = '\0';
860             WIN_ReleasePtr( wndPtr );
861         }
862         break;
863
864     case WM_SETTEXT:
865         DEFWND_SetTextA( hwnd, (LPCSTR)lParam );
866         if( (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CAPTION) == WS_CAPTION )
867             NC_HandleNCPaint( hwnd , (HRGN)1 );  /* Repaint caption */
868         result = 1; /* success. FIXME: check text length */
869         break;
870
871     /* for far east users (IMM32) - <hidenori@a2.ctktv.ne.jp> */
872     case WM_IME_CHAR:
873         {
874             CHAR    chChar1 = (CHAR)( (wParam>>8) & 0xff );
875             CHAR    chChar2 = (CHAR)( wParam & 0xff );
876
877             if (chChar1)
878                 SendMessageA( hwnd, WM_CHAR, (WPARAM)chChar1, lParam );
879             SendMessageA( hwnd, WM_CHAR, (WPARAM)chChar2, lParam );
880         }
881         break;
882     case WM_IME_KEYDOWN:
883         result = SendMessageA( hwnd, WM_KEYDOWN, wParam, lParam );
884         break;
885     case WM_IME_KEYUP:
886         result = SendMessageA( hwnd, WM_KEYUP, wParam, lParam );
887         break;
888
889     case WM_IME_STARTCOMPOSITION:
890     case WM_IME_COMPOSITION:
891     case WM_IME_ENDCOMPOSITION:
892     case WM_IME_SELECT:
893         {
894             HWND hwndIME;
895
896             hwndIME = DEFWND_ImmGetDefaultIMEWnd( hwnd );
897             if (hwndIME)
898                 result = SendMessageA( hwndIME, msg, wParam, lParam );
899         }
900         break;
901     case WM_IME_SETCONTEXT:
902         {
903             HWND hwndIME;
904
905             hwndIME = DEFWND_ImmGetDefaultIMEWnd( hwnd );
906             if (hwndIME)
907                 result = DEFWND_ImmIsUIMessageA( hwndIME, msg, wParam, lParam );
908         }
909         break;
910
911     case WM_INPUTLANGCHANGEREQUEST:
912         /* notify about the switch only if it's really our current layout */
913         if ((HKL)lParam == GetKeyboardLayout(0))
914             result = SendMessageA( hwnd, WM_INPUTLANGCHANGE, wParam, lParam );
915         else
916             result = 0;
917         break;
918
919     case WM_SYSCHAR:
920     {
921         BYTE ch = LOWORD(wParam);
922         WCHAR wch;
923         MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1);
924         wParam = MAKEWPARAM( wch, HIWORD(wParam) );
925     }
926     /* fall through */
927     default:
928         result = DEFWND_DefWinProc( hwnd, msg, wParam, lParam );
929         break;
930     }
931
932     SPY_ExitMessage( SPY_RESULT_DEFWND, hwnd, msg, result, wParam, lParam );
933     return result;
934 }
935
936
937 /***********************************************************************
938  *              DefWindowProcW (USER32.@) Calls default window message handler
939  *
940  * Calls default window procedure for messages not processed
941  *  by application.
942  *
943  *  RETURNS
944  *     Return value is dependent upon the message.
945 */
946 LRESULT WINAPI DefWindowProcW(
947     HWND hwnd,      /* [in] window procedure receiving message */
948     UINT msg,       /* [in] message identifier */
949     WPARAM wParam,  /* [in] first message parameter */
950     LPARAM lParam )   /* [in] second message parameter */
951 {
952     LRESULT result = 0;
953     HWND full_handle;
954
955     if (!(full_handle = WIN_IsCurrentProcess( hwnd )))
956     {
957         if (!IsWindow( hwnd )) return 0;
958         ERR( "called for other process window %p\n", hwnd );
959         return 0;
960     }
961     hwnd = full_handle;
962     SPY_EnterMessage( SPY_DEFWNDPROC, hwnd, msg, wParam, lParam );
963
964     switch(msg)
965     {
966     case WM_NCCREATE:
967         {
968             CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
969             /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
970              * may have child window IDs instead of window name */
971             if (HIWORD(cs->lpszName))
972                 DEFWND_SetTextW( hwnd, cs->lpszName );
973             result = 1;
974         }
975         break;
976
977     case WM_NCCALCSIZE:
978         result = NC_HandleNCCalcSize( hwnd, (RECT *)lParam );
979         break;
980
981     case WM_WINDOWPOSCHANGING:
982         result = WINPOS_HandleWindowPosChanging( hwnd, (WINDOWPOS *)lParam );
983         break;
984
985     case WM_WINDOWPOSCHANGED:
986         {
987             WINDOWPOS * winPos = (WINDOWPOS *)lParam;
988             DEFWND_HandleWindowPosChanged( hwnd, winPos->flags );
989         }
990         break;
991
992     case WM_GETTEXTLENGTH:
993         {
994             WND *wndPtr = WIN_GetPtr( hwnd );
995             if (wndPtr && wndPtr->text) result = (LRESULT)strlenW(wndPtr->text);
996             WIN_ReleasePtr( wndPtr );
997         }
998         break;
999
1000     case WM_GETTEXT:
1001         if (wParam)
1002         {
1003             LPWSTR dest = (LPWSTR)lParam;
1004             WND *wndPtr = WIN_GetPtr( hwnd );
1005
1006             if (!wndPtr) break;
1007             if (wndPtr->text)
1008             {
1009                 lstrcpynW( dest, wndPtr->text, wParam );
1010                 result = strlenW( dest );
1011             }
1012             else dest[0] = '\0';
1013             WIN_ReleasePtr( wndPtr );
1014         }
1015         break;
1016
1017     case WM_SETTEXT:
1018         DEFWND_SetTextW( hwnd, (LPCWSTR)lParam );
1019         if( (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CAPTION) == WS_CAPTION )
1020             NC_HandleNCPaint( hwnd , (HRGN)1 );  /* Repaint caption */
1021         result = 1; /* success. FIXME: check text length */
1022         break;
1023
1024     /* for far east users (IMM32) - <hidenori@a2.ctktv.ne.jp> */
1025     case WM_IME_CHAR:
1026         SendMessageW( hwnd, WM_CHAR, wParam, lParam );
1027         break;
1028     case WM_IME_SETCONTEXT:
1029         {
1030             HWND hwndIME;
1031
1032             hwndIME = DEFWND_ImmGetDefaultIMEWnd( hwnd );
1033             if (hwndIME)
1034                 result = DEFWND_ImmIsUIMessageW( hwndIME, msg, wParam, lParam );
1035         }
1036         break;
1037
1038     case WM_INPUTLANGCHANGEREQUEST:
1039         /* notify about the switch only if it's really our current layout */
1040         if ((HKL)lParam == GetKeyboardLayout(0))
1041             result = SendMessageW( hwnd, WM_INPUTLANGCHANGE, wParam, lParam );
1042         else
1043             result = 0;
1044         break;
1045
1046     default:
1047         result = DEFWND_DefWinProc( hwnd, msg, wParam, lParam );
1048         break;
1049     }
1050     SPY_ExitMessage( SPY_RESULT_DEFWND, hwnd, msg, result, wParam, lParam );
1051     return result;
1052 }