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