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