Added mappings for a few messages.
[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->hwndSelf, wParam, lParam );
311
312     case WM_LBUTTONDBLCLK:
313     case WM_NCLBUTTONDBLCLK:
314         return NC_HandleNCLButtonDblClk( wndPtr->hwndSelf, 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->hwndSelf, 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             HDC hdc = (HDC)wParam;
461             HBRUSH hbr = GetClassLongW( wndPtr->hwndSelf, GCL_HBRBACKGROUND );
462             if (!hbr) return 0;
463
464             /* GetClientRect used to be GetClipBox, but it is not what
465              * Windows does, and it breaks badly with CS_PARENTDC */
466             GetClientRect( wndPtr->hwndSelf, &rect );
467             DPtoLP( hdc, (LPPOINT)&rect, 2 );
468             FillRect( hdc, &rect, hbr );
469             return 1;
470         }
471
472     case WM_GETDLGCODE:
473         return 0;
474
475     case WM_CTLCOLORMSGBOX:
476     case WM_CTLCOLOREDIT:
477     case WM_CTLCOLORLISTBOX:
478     case WM_CTLCOLORBTN:
479     case WM_CTLCOLORDLG:
480     case WM_CTLCOLORSTATIC:
481     case WM_CTLCOLORSCROLLBAR:
482         return (LRESULT)DEFWND_ControlColor( (HDC)wParam, msg - WM_CTLCOLORMSGBOX );
483
484     case WM_CTLCOLOR:
485         return (LRESULT)DEFWND_ControlColor( (HDC)wParam, HIWORD(lParam) );
486         
487     case WM_SETCURSOR:
488         if (wndPtr->dwStyle & WS_CHILD)
489         {
490             /* with the exception of the border around a resizable wnd,
491              * give the parent first chance to set the cursor */
492             if ((LOWORD(lParam) < HTSIZEFIRST) || (LOWORD(lParam) > HTSIZELAST))
493             {
494                 if (pSendMessage(wndPtr->parent->hwndSelf, WM_SETCURSOR, wParam, lParam))
495                     return TRUE;
496             }
497         }
498         return NC_HandleSetCursor( wndPtr->hwndSelf, wParam, lParam );
499
500     case WM_SYSCOMMAND:
501         {
502             POINT pt;
503             pt.x = SLOWORD(lParam);
504             pt.y = SHIWORD(lParam);
505             return NC_HandleSysCommand( wndPtr->hwndSelf, wParam, pt );
506         }
507
508     case WM_KEYDOWN:
509         if(wParam == VK_F10) iF10Key = VK_F10;
510         break;
511
512     case WM_SYSKEYDOWN:
513         if( HIWORD(lParam) & KEYDATA_ALT )
514         {
515             /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
516               if( wParam == VK_MENU && !iMenuSysKey )
517                 iMenuSysKey = 1;
518               else
519                 iMenuSysKey = 0;
520             
521             iF10Key = 0;
522
523             if( wParam == VK_F4 )       /* try to close the window */
524             {
525                 HWND hWnd = WIN_GetTopParent( wndPtr->hwndSelf );
526                 wndPtr = WIN_FindWndPtr( hWnd );
527                 if( wndPtr && !(wndPtr->clsStyle & CS_NOCLOSE) )
528                     pPostMessage( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
529                 WIN_ReleaseWndPtr(wndPtr);
530             }
531         } 
532         else if( wParam == VK_F10 )
533                 iF10Key = 1;
534              else
535                 if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
536                     pSendMessage( wndPtr->hwndSelf, WM_SYSCOMMAND, SC_KEYMENU, VK_SPACE );
537         break;
538
539     case WM_KEYUP:
540     case WM_SYSKEYUP:
541         /* Press and release F10 or ALT */
542         if (((wParam == VK_MENU) && iMenuSysKey) ||
543             ((wParam == VK_F10) && iF10Key))
544               pSendMessage( WIN_GetTopParent(wndPtr->hwndSelf),
545                              WM_SYSCOMMAND, SC_KEYMENU, 0L );
546         iMenuSysKey = iF10Key = 0;
547         break;
548
549     case WM_SYSCHAR:
550         iMenuSysKey = 0;
551         if (wParam == VK_RETURN && (wndPtr->dwStyle & WS_MINIMIZE))
552         {
553             pPostMessage( wndPtr->hwndSelf, WM_SYSCOMMAND, SC_RESTORE, 0L );
554             break;
555         } 
556         if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
557         {
558             if (wParam == VK_TAB || wParam == VK_ESCAPE) break;
559             if (wParam == VK_SPACE && (wndPtr->dwStyle & WS_CHILD))
560                 pSendMessage( wndPtr->parent->hwndSelf, msg, wParam, lParam );
561             else
562                 pSendMessage( wndPtr->hwndSelf, WM_SYSCOMMAND, SC_KEYMENU, wParam );
563         } 
564         else /* check for Ctrl-Esc */
565             if (wParam != VK_ESCAPE) MessageBeep(0);
566         break;
567
568     case WM_SHOWWINDOW:
569         if (!lParam) return 0; /* sent from ShowWindow */
570         if (!(wndPtr->dwStyle & WS_POPUP) || !wndPtr->owner) return 0;
571         if ((wndPtr->dwStyle & WS_VISIBLE) && wParam) return 0;
572         else if (!(wndPtr->dwStyle & WS_VISIBLE) && !wParam) return 0;
573         ShowWindow( wndPtr->hwndSelf, wParam ? SW_SHOWNOACTIVATE : SW_HIDE );
574         break; 
575
576     case WM_CANCELMODE:
577         if (wndPtr->parent == WIN_GetDesktop()) EndMenu();
578         if (GetCapture() == wndPtr->hwndSelf) ReleaseCapture();
579         WIN_ReleaseDesktop();
580         break;
581
582     case WM_VKEYTOITEM:
583     case WM_CHARTOITEM:
584         return -1;
585
586     case WM_DROPOBJECT:
587         return DRAG_FILE;  
588
589     case WM_QUERYDROPOBJECT:
590         if (wndPtr->dwExStyle & WS_EX_ACCEPTFILES) return 1;
591         break;
592
593     case WM_QUERYDRAGICON:
594         {
595             UINT len;
596
597             HICON hIcon = GetClassLongW( wndPtr->hwndSelf, GCL_HICON );
598             if (hIcon) return hIcon;
599             for(len=1; len<64; len++)
600                 if((hIcon = LoadIconW(wndPtr->hInstance, MAKEINTRESOURCEW(len))))
601                     return (LRESULT)hIcon;
602             return (LRESULT)LoadIconW(0, IDI_APPLICATIONW);
603         }
604         break;
605
606     case WM_ISACTIVEICON:
607         return ((wndPtr->flags & WIN_NCACTIVATED) != 0);
608
609     case WM_NOTIFYFORMAT:
610       if (IsWindowUnicode(wndPtr->hwndSelf)) return NFR_UNICODE;
611       else return NFR_ANSI;
612         
613     case WM_QUERYOPEN:
614     case WM_QUERYENDSESSION:
615         return 1;
616
617     case WM_SETICON:
618         if (USER_Driver.pSetWindowIcon)
619             return USER_Driver.pSetWindowIcon( wndPtr->hwndSelf, lParam, (wParam != ICON_SMALL) );
620         else
621         {
622                 int index = (wParam != ICON_SMALL) ? GCL_HICON : GCL_HICONSM;
623                 HICON hOldIcon = GetClassLongW(wndPtr->hwndSelf, index); 
624                 SetClassLongW(wndPtr->hwndSelf, index, lParam);
625
626                 SetWindowPos(wndPtr->hwndSelf, 0, 0, 0, 0, 0, SWP_FRAMECHANGED
627                          | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
628                          | SWP_NOZORDER);
629                 return hOldIcon;
630         }
631
632     case WM_GETICON:
633         {
634                 int index = (wParam != ICON_SMALL) ? GCL_HICON : GCL_HICONSM;
635                 return GetClassLongW(wndPtr->hwndSelf, index); 
636         }
637
638     case WM_HELP:
639         pSendMessage( wndPtr->parent->hwndSelf, msg, wParam, lParam );
640         break;
641     }
642
643     return 0;
644 }
645
646
647
648 /***********************************************************************
649  *              DefWindowProc (USER.107)
650  */
651 LRESULT WINAPI DefWindowProc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
652                                 LPARAM lParam )
653 {
654     WND * wndPtr = WIN_FindWndPtr( hwnd );
655     LRESULT result = 0;
656
657     if (!wndPtr) return 0;
658     SPY_EnterMessage( SPY_DEFWNDPROC16, hwnd, msg, wParam, lParam );
659
660     switch(msg)
661     {
662     case WM_NCCREATE:
663         {
664             CREATESTRUCT16 *cs = MapSL(lParam);
665             /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
666              * may have child window IDs instead of window name */
667             if (HIWORD(cs->lpszName))
668                 DEFWND_SetTextA( wndPtr, MapSL(cs->lpszName) );
669             result = 1;
670         }
671         break;
672
673     case WM_NCCALCSIZE:
674         {
675             RECT rect32;
676             CONV_RECT16TO32( MapSL(lParam), &rect32 );
677             result = NC_HandleNCCalcSize( hwnd, &rect32 );
678             CONV_RECT32TO16( &rect32, MapSL(lParam) );
679         }
680         break;
681
682     case WM_WINDOWPOSCHANGING:
683         result = WINPOS_HandleWindowPosChanging16( hwnd, MapSL(lParam) );
684         break;
685
686     case WM_WINDOWPOSCHANGED:
687         {
688             WINDOWPOS16 * winPos = MapSL(lParam);
689             DEFWND_HandleWindowPosChanged( wndPtr, winPos->flags );
690         }
691         break;
692
693     case WM_GETTEXTLENGTH:
694         if (wndPtr->text)
695             result = WideCharToMultiByte( CP_ACP, 0, wndPtr->text, strlenW(wndPtr->text),
696                                           NULL, 0, NULL, NULL );
697         break;
698
699     case WM_GETTEXT:
700         if (wParam && wndPtr->text)
701         {
702             LPSTR dest = MapSL(lParam);
703             if (!WideCharToMultiByte( CP_ACP, 0, wndPtr->text, -1, dest, wParam, NULL, NULL ))
704                 dest[wParam-1] = 0;
705             result = strlen(dest);
706         }
707         break;
708
709     case WM_SETTEXT:
710         DEFWND_SetTextA( wndPtr, MapSL(lParam) );
711         if( (wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION )
712             NC_HandleNCPaint( hwnd , (HRGN)1 );
713         result = 1; /* success. FIXME: check text length */
714         break;
715
716     default:
717         result = DEFWND_DefWinProc( wndPtr, msg, wParam, lParam, FALSE );
718         break;
719     }
720
721     WIN_ReleaseWndPtr(wndPtr);
722     SPY_ExitMessage( SPY_RESULT_DEFWND16, hwnd, msg, result, wParam, lParam );
723     return result;
724 }
725
726
727 /***********************************************************************
728  *              DefWindowProcA (USER32.@)
729  *
730  */
731 LRESULT WINAPI DefWindowProcA( HWND hwnd, UINT msg, WPARAM wParam,
732                                  LPARAM lParam )
733 {
734     WND * wndPtr = WIN_FindWndPtr( hwnd );
735     LRESULT result = 0;
736
737     if (!wndPtr) return 0;
738     SPY_EnterMessage( SPY_DEFWNDPROC, hwnd, msg, wParam, lParam );
739
740     switch(msg)
741     {
742     case WM_NCCREATE:
743         {
744             CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
745             /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
746              * may have child window IDs instead of window name */
747             if (HIWORD(cs->lpszName))
748                 DEFWND_SetTextA( wndPtr, cs->lpszName );
749             result = 1;
750         }
751         break;
752
753     case WM_NCCALCSIZE:
754         result = NC_HandleNCCalcSize( hwnd, (RECT *)lParam );
755         break;
756
757     case WM_WINDOWPOSCHANGING:
758         result = WINPOS_HandleWindowPosChanging( hwnd, (WINDOWPOS *)lParam );
759         break;
760
761     case WM_WINDOWPOSCHANGED:
762         {
763             WINDOWPOS * winPos = (WINDOWPOS *)lParam;
764             DEFWND_HandleWindowPosChanged( wndPtr, winPos->flags );
765         }
766         break;
767
768     case WM_GETTEXTLENGTH:
769         if (wndPtr->text)
770             result = WideCharToMultiByte( CP_ACP, 0, wndPtr->text, strlenW(wndPtr->text),
771                                           NULL, 0, NULL, NULL );
772         break;
773
774     case WM_GETTEXT:
775         if (wParam && wndPtr->text)
776         {
777             if (!WideCharToMultiByte( CP_ACP, 0, wndPtr->text, -1,
778                                       (LPSTR)lParam, wParam, NULL, NULL ))
779                 ((LPSTR)lParam)[wParam-1] = 0;
780             result = (LRESULT)strlen( (LPSTR)lParam );
781         }
782         break;
783
784     case WM_SETTEXT:
785         DEFWND_SetTextA( wndPtr, (LPCSTR)lParam );
786         if( (wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION )
787             NC_HandleNCPaint( hwnd , (HRGN)1 );  /* Repaint caption */
788         result = 1; /* success. FIXME: check text length */
789         break;
790
791     /* for far east users (IMM32) - <hidenori@a2.ctktv.ne.jp> */
792     case WM_IME_CHAR:
793         {
794             CHAR    chChar1 = (CHAR)( (wParam>>8) & 0xff );
795             CHAR    chChar2 = (CHAR)( wParam & 0xff );
796
797             SendMessageA( hwnd, WM_CHAR, (WPARAM)chChar1, lParam );
798             if ( IsDBCSLeadByte( chChar1 ) )
799                 SendMessageA( hwnd, WM_CHAR, (WPARAM)chChar2, lParam );
800         }
801         break;
802     case WM_IME_KEYDOWN:
803         result = SendMessageA( hwnd, WM_KEYDOWN, wParam, lParam );
804         break;
805     case WM_IME_KEYUP:
806         result = SendMessageA( hwnd, WM_KEYUP, wParam, lParam );
807         break;
808
809     case WM_IME_STARTCOMPOSITION:
810     case WM_IME_COMPOSITION:
811     case WM_IME_ENDCOMPOSITION:
812     case WM_IME_SELECT:
813         {
814             HWND hwndIME;
815
816             hwndIME = DEFWND_ImmGetDefaultIMEWnd( hwnd );
817             if (hwndIME)
818                 result = SendMessageA( hwndIME, msg, wParam, lParam );
819         }
820         break;
821     case WM_IME_SETCONTEXT:
822         {
823             HWND hwndIME;
824
825             hwndIME = DEFWND_ImmGetDefaultIMEWnd( hwnd );
826             if (hwndIME)
827                 result = DEFWND_ImmIsUIMessageA( hwndIME, msg, wParam, lParam );
828         }
829         break;
830
831     default:
832         result = DEFWND_DefWinProc( wndPtr, msg, wParam, lParam, FALSE );
833         break;
834     }
835
836     WIN_ReleaseWndPtr(wndPtr);
837     SPY_ExitMessage( SPY_RESULT_DEFWND, hwnd, msg, result, wParam, lParam );
838     return result;
839 }
840
841
842 /***********************************************************************
843  *              DefWindowProcW (USER32.@) Calls default window message handler
844  * 
845  * Calls default window procedure for messages not processed 
846  *  by application.
847  *
848  *  RETURNS
849  *     Return value is dependent upon the message.
850 */
851 LRESULT WINAPI DefWindowProcW( 
852     HWND hwnd,      /* [in] window procedure receiving message */
853     UINT msg,       /* [in] message identifier */
854     WPARAM wParam,  /* [in] first message parameter */
855     LPARAM lParam )   /* [in] second message parameter */
856 {
857     WND * wndPtr = WIN_FindWndPtr( hwnd );
858     LRESULT result = 0;
859
860     if (!wndPtr) return 0;
861     SPY_EnterMessage( SPY_DEFWNDPROC, hwnd, msg, wParam, lParam );
862
863     switch(msg)
864     {
865     case WM_NCCREATE:
866         {
867             CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
868             /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
869              * may have child window IDs instead of window name */
870             if (HIWORD(cs->lpszName))
871                 DEFWND_SetTextW( wndPtr, cs->lpszName );
872             result = 1;
873         }
874         break;
875
876     case WM_NCCALCSIZE:
877         result = NC_HandleNCCalcSize( hwnd, (RECT *)lParam );
878         break;
879
880     case WM_WINDOWPOSCHANGING:
881         result = WINPOS_HandleWindowPosChanging( hwnd, (WINDOWPOS *)lParam );
882         break;
883
884     case WM_WINDOWPOSCHANGED:
885         {
886             WINDOWPOS * winPos = (WINDOWPOS *)lParam;
887             DEFWND_HandleWindowPosChanged( wndPtr, winPos->flags );
888         }
889         break;
890
891     case WM_GETTEXTLENGTH:
892         if (wndPtr->text) result = (LRESULT)strlenW(wndPtr->text);
893         break;
894
895     case WM_GETTEXT:
896         if (wParam && wndPtr->text)
897         {
898             lstrcpynW( (LPWSTR)lParam, wndPtr->text, wParam );
899             result = strlenW( (LPWSTR)lParam );
900         }
901         break;
902
903     case WM_SETTEXT:
904         DEFWND_SetTextW( wndPtr, (LPCWSTR)lParam );
905         if( (wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION )
906             NC_HandleNCPaint( hwnd , (HRGN)1 );  /* Repaint caption */
907         result = 1; /* success. FIXME: check text length */
908         break;
909
910     /* for far east users (IMM32) - <hidenori@a2.ctktv.ne.jp> */
911     case WM_IME_CHAR:
912         SendMessageW( hwnd, WM_CHAR, wParam, lParam );
913         break;
914     case WM_IME_SETCONTEXT:
915         {
916             HWND hwndIME;
917
918             hwndIME = DEFWND_ImmGetDefaultIMEWnd( hwnd );
919             if (hwndIME)
920                 result = DEFWND_ImmIsUIMessageW( hwndIME, msg, wParam, lParam );
921         }
922         break;
923
924     default:
925         result = DEFWND_DefWinProc( wndPtr, msg, wParam, lParam, TRUE );
926         break;
927     }
928     WIN_ReleaseWndPtr(wndPtr);
929     SPY_ExitMessage( SPY_RESULT_DEFWND, hwnd, msg, result, wParam, lParam );
930     return result;
931 }