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