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