Changed the GDI driver interface to pass an opaque PHYSDEV pointer
[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 "wine/debug.h"
30 #include "spy.h"
31 #include "windef.h"
32 #include "wingdi.h"
33 #include "winnls.h"
34 #include "wine/unicode.h"
35 #include "wine/winuser16.h"
36 #include "wine/server.h"
37 #include "imm.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("%04x %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 = 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=(%i,%i - %i,%i)\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 = 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         return NC_HandleSetCursor( hwnd, wParam, lParam );
531
532     case WM_SYSCOMMAND:
533         return NC_HandleSysCommand( hwnd, wParam, lParam );
534
535     case WM_KEYDOWN:
536         if(wParam == VK_F10) iF10Key = VK_F10;
537         break;
538
539     case WM_SYSKEYDOWN:
540         if( HIWORD(lParam) & KEYDATA_ALT )
541         {
542             /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
543               if( wParam == VK_MENU && !iMenuSysKey )
544                 iMenuSysKey = 1;
545               else
546                 iMenuSysKey = 0;
547             
548             iF10Key = 0;
549
550             if( wParam == VK_F4 )       /* try to close the window */
551             {
552                 HWND top = GetAncestor( hwnd, GA_ROOT );
553                 if (!(GetClassLongW( top, GCL_STYLE ) & CS_NOCLOSE))
554                     PostMessageW( top, WM_SYSCOMMAND, SC_CLOSE, 0 );
555             }
556         } 
557         else if( wParam == VK_F10 )
558                 iF10Key = 1;
559              else
560                 if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
561                     SendMessageW( hwnd, WM_SYSCOMMAND, SC_KEYMENU, VK_SPACE );
562         break;
563
564     case WM_KEYUP:
565     case WM_SYSKEYUP:
566         /* Press and release F10 or ALT */
567         if (((wParam == VK_MENU) && iMenuSysKey) ||
568             ((wParam == VK_F10) && iF10Key))
569               SendMessageW( GetAncestor( hwnd, GA_ROOT ), WM_SYSCOMMAND, SC_KEYMENU, 0L );
570         iMenuSysKey = iF10Key = 0;
571         break;
572
573     case WM_SYSCHAR:
574         iMenuSysKey = 0;
575         if (wParam == VK_RETURN && IsIconic(hwnd))
576         {
577             PostMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
578             break;
579         } 
580         if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
581         {
582             if (wParam == VK_TAB || wParam == VK_ESCAPE) break;
583             if (wParam == VK_SPACE && (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD))
584                 SendMessageW( GetParent(hwnd), msg, wParam, lParam );
585             else
586                 SendMessageW( hwnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
587         } 
588         else /* check for Ctrl-Esc */
589             if (wParam != VK_ESCAPE) MessageBeep(0);
590         break;
591
592     case WM_SHOWWINDOW:
593         {
594             LONG style = GetWindowLongW( hwnd, GWL_STYLE );
595             if (!lParam) return 0; /* sent from ShowWindow */
596             if (!(style & WS_POPUP)) return 0;
597             if ((style & WS_VISIBLE) && wParam) return 0;
598             if (!(style & WS_VISIBLE) && !wParam) return 0;
599             if (!GetWindow( hwnd, GW_OWNER )) return 0;
600             ShowWindow( hwnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE );
601             break;
602         }
603
604     case WM_CANCELMODE:
605         if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
606         if (GetCapture() == hwnd) ReleaseCapture();
607         break;
608
609     case WM_VKEYTOITEM:
610     case WM_CHARTOITEM:
611         return -1;
612
613     case WM_DROPOBJECT:
614         return DRAG_FILE;  
615
616     case WM_QUERYDROPOBJECT:
617         return (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
618
619     case WM_QUERYDRAGICON:
620         {
621             UINT len;
622
623             HICON hIcon = GetClassLongW( hwnd, GCL_HICON );
624             HINSTANCE instance = GetWindowLongW( hwnd, GWL_HINSTANCE );
625             if (hIcon) return hIcon;
626             for(len=1; len<64; len++)
627                 if((hIcon = LoadIconW(instance, MAKEINTRESOURCEW(len))))
628                     return (LRESULT)hIcon;
629             return (LRESULT)LoadIconW(0, IDI_APPLICATIONW);
630         }
631         break;
632
633     case WM_ISACTIVEICON:
634         {
635             WND *wndPtr = WIN_GetPtr( hwnd );
636             BOOL ret = (wndPtr->flags & WIN_NCACTIVATED) != 0;
637             WIN_ReleasePtr( wndPtr );
638             return ret;
639         }
640
641     case WM_NOTIFYFORMAT:
642       if (IsWindowUnicode(hwnd)) return NFR_UNICODE;
643       else return NFR_ANSI;
644         
645     case WM_QUERYOPEN:
646     case WM_QUERYENDSESSION:
647         return 1;
648
649     case WM_SETICON:
650         if (USER_Driver.pSetWindowIcon)
651             return USER_Driver.pSetWindowIcon( hwnd, lParam, (wParam != ICON_SMALL) );
652         else
653         {
654             HICON hOldIcon = SetClassLongW( hwnd, (wParam != ICON_SMALL) ? GCL_HICON : GCL_HICONSM,
655                                             lParam);
656             SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE |
657                          SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
658             return hOldIcon;
659         }
660
661     case WM_GETICON:
662         return GetClassLongW( hwnd, (wParam != ICON_SMALL) ? GCL_HICON : GCL_HICONSM );
663
664     case WM_HELP:
665         SendMessageW( GetParent(hwnd), msg, wParam, lParam );
666         break;
667     }
668
669     return 0;
670 }
671
672
673
674 /***********************************************************************
675  *              DefWindowProc (USER.107)
676  */
677 LRESULT WINAPI DefWindowProc16( HWND16 hwnd16, UINT16 msg, WPARAM16 wParam,
678                                 LPARAM lParam )
679 {
680     LRESULT result = 0;
681     HWND hwnd = WIN_Handle32( hwnd16 );
682
683     if (!WIN_IsCurrentProcess( hwnd ))
684     {
685         if (!IsWindow( hwnd )) return 0;
686         ERR( "called for other process window %x\n", hwnd );
687         return 0;
688     }
689     SPY_EnterMessage( SPY_DEFWNDPROC16, hwnd, msg, wParam, lParam );
690
691     switch(msg)
692     {
693     case WM_NCCREATE:
694         {
695             CREATESTRUCT16 *cs = MapSL(lParam);
696             /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
697              * may have child window IDs instead of window name */
698             if (HIWORD(cs->lpszName))
699                 DEFWND_SetTextA( hwnd, MapSL(cs->lpszName) );
700             result = 1;
701         }
702         break;
703
704     case WM_NCCALCSIZE:
705         {
706             RECT rect32;
707             CONV_RECT16TO32( MapSL(lParam), &rect32 );
708             result = NC_HandleNCCalcSize( hwnd, &rect32 );
709             CONV_RECT32TO16( &rect32, MapSL(lParam) );
710         }
711         break;
712
713     case WM_WINDOWPOSCHANGING:
714         result = WINPOS_HandleWindowPosChanging16( hwnd, MapSL(lParam) );
715         break;
716
717     case WM_WINDOWPOSCHANGED:
718         {
719             WINDOWPOS16 * winPos = MapSL(lParam);
720             DEFWND_HandleWindowPosChanged( hwnd, winPos->flags );
721         }
722         break;
723
724     case WM_GETTEXT:
725     case WM_SETTEXT:
726         result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)MapSL(lParam) );
727         break;
728
729     default:
730         result = DefWindowProcA( hwnd, msg, wParam, lParam );
731         break;
732     }
733
734     SPY_ExitMessage( SPY_RESULT_DEFWND16, hwnd, msg, result, wParam, lParam );
735     return result;
736 }
737
738
739 /***********************************************************************
740  *              DefWindowProcA (USER32.@)
741  *
742  */
743 LRESULT WINAPI DefWindowProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
744 {
745     LRESULT result = 0;
746     HWND full_handle;
747
748     if (!(full_handle = WIN_IsCurrentProcess( hwnd )))
749     {
750         if (!IsWindow( hwnd )) return 0;
751         ERR( "called for other process window %x\n", hwnd );
752         return 0;
753     }
754     hwnd = full_handle;
755
756     SPY_EnterMessage( SPY_DEFWNDPROC, hwnd, msg, wParam, lParam );
757
758     switch(msg)
759     {
760     case WM_NCCREATE:
761         {
762             CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
763             /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
764              * may have child window IDs instead of window name */
765             if (HIWORD(cs->lpszName))
766                 DEFWND_SetTextA( hwnd, cs->lpszName );
767             result = 1;
768         }
769         break;
770
771     case WM_NCCALCSIZE:
772         result = NC_HandleNCCalcSize( hwnd, (RECT *)lParam );
773         break;
774
775     case WM_WINDOWPOSCHANGING:
776         result = WINPOS_HandleWindowPosChanging( hwnd, (WINDOWPOS *)lParam );
777         break;
778
779     case WM_WINDOWPOSCHANGED:
780         {
781             WINDOWPOS * winPos = (WINDOWPOS *)lParam;
782             DEFWND_HandleWindowPosChanged( hwnd, winPos->flags );
783         }
784         break;
785
786     case WM_GETTEXTLENGTH:
787         {
788             WND *wndPtr = WIN_GetPtr( hwnd );
789             if (wndPtr && wndPtr->text)
790                 result = WideCharToMultiByte( CP_ACP, 0, wndPtr->text, strlenW(wndPtr->text),
791                                               NULL, 0, NULL, NULL );
792             WIN_ReleasePtr( wndPtr );
793         }
794         break;
795
796     case WM_GETTEXT:
797         if (wParam)
798         {
799             LPSTR dest = (LPSTR)lParam;
800             WND *wndPtr = WIN_GetPtr( hwnd );
801
802             if (!wndPtr) break;
803             if (wndPtr->text)
804             {
805                 if (!WideCharToMultiByte( CP_ACP, 0, wndPtr->text, -1,
806                                           dest, wParam, NULL, NULL )) dest[wParam-1] = 0;
807                 result = strlen( dest );
808             }
809             else dest[0] = '\0';
810             WIN_ReleasePtr( wndPtr );
811         }
812         break;
813
814     case WM_SETTEXT:
815         DEFWND_SetTextA( hwnd, (LPCSTR)lParam );
816         if( (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CAPTION) == WS_CAPTION )
817             NC_HandleNCPaint( hwnd , (HRGN)1 );  /* Repaint caption */
818         result = 1; /* success. FIXME: check text length */
819         break;
820
821     /* for far east users (IMM32) - <hidenori@a2.ctktv.ne.jp> */
822     case WM_IME_CHAR:
823         {
824             CHAR    chChar1 = (CHAR)( (wParam>>8) & 0xff );
825             CHAR    chChar2 = (CHAR)( wParam & 0xff );
826
827             SendMessageA( hwnd, WM_CHAR, (WPARAM)chChar1, lParam );
828             if ( IsDBCSLeadByte( chChar1 ) )
829                 SendMessageA( hwnd, WM_CHAR, (WPARAM)chChar2, lParam );
830         }
831         break;
832     case WM_IME_KEYDOWN:
833         result = SendMessageA( hwnd, WM_KEYDOWN, wParam, lParam );
834         break;
835     case WM_IME_KEYUP:
836         result = SendMessageA( hwnd, WM_KEYUP, wParam, lParam );
837         break;
838
839     case WM_IME_STARTCOMPOSITION:
840     case WM_IME_COMPOSITION:
841     case WM_IME_ENDCOMPOSITION:
842     case WM_IME_SELECT:
843         {
844             HWND hwndIME;
845
846             hwndIME = DEFWND_ImmGetDefaultIMEWnd( hwnd );
847             if (hwndIME)
848                 result = SendMessageA( hwndIME, msg, wParam, lParam );
849         }
850         break;
851     case WM_IME_SETCONTEXT:
852         {
853             HWND hwndIME;
854
855             hwndIME = DEFWND_ImmGetDefaultIMEWnd( hwnd );
856             if (hwndIME)
857                 result = DEFWND_ImmIsUIMessageA( hwndIME, msg, wParam, lParam );
858         }
859         break;
860
861     default:
862         result = DEFWND_DefWinProc( hwnd, msg, wParam, lParam );
863         break;
864     }
865
866     SPY_ExitMessage( SPY_RESULT_DEFWND, hwnd, msg, result, wParam, lParam );
867     return result;
868 }
869
870
871 /***********************************************************************
872  *              DefWindowProcW (USER32.@) Calls default window message handler
873  * 
874  * Calls default window procedure for messages not processed 
875  *  by application.
876  *
877  *  RETURNS
878  *     Return value is dependent upon the message.
879 */
880 LRESULT WINAPI DefWindowProcW( 
881     HWND hwnd,      /* [in] window procedure receiving message */
882     UINT msg,       /* [in] message identifier */
883     WPARAM wParam,  /* [in] first message parameter */
884     LPARAM lParam )   /* [in] second message parameter */
885 {
886     LRESULT result = 0;
887     HWND full_handle;
888
889     if (!(full_handle = WIN_IsCurrentProcess( hwnd )))
890     {
891         if (!IsWindow( hwnd )) return 0;
892         ERR( "called for other process window %x\n", hwnd );
893         return 0;
894     }
895     hwnd = full_handle;
896     SPY_EnterMessage( SPY_DEFWNDPROC, hwnd, msg, wParam, lParam );
897
898     switch(msg)
899     {
900     case WM_NCCREATE:
901         {
902             CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
903             /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
904              * may have child window IDs instead of window name */
905             if (HIWORD(cs->lpszName))
906                 DEFWND_SetTextW( hwnd, cs->lpszName );
907             result = 1;
908         }
909         break;
910
911     case WM_NCCALCSIZE:
912         result = NC_HandleNCCalcSize( hwnd, (RECT *)lParam );
913         break;
914
915     case WM_WINDOWPOSCHANGING:
916         result = WINPOS_HandleWindowPosChanging( hwnd, (WINDOWPOS *)lParam );
917         break;
918
919     case WM_WINDOWPOSCHANGED:
920         {
921             WINDOWPOS * winPos = (WINDOWPOS *)lParam;
922             DEFWND_HandleWindowPosChanged( hwnd, winPos->flags );
923         }
924         break;
925
926     case WM_GETTEXTLENGTH:
927         {
928             WND *wndPtr = WIN_GetPtr( hwnd );
929             if (wndPtr && wndPtr->text) result = (LRESULT)strlenW(wndPtr->text);
930             WIN_ReleasePtr( wndPtr );
931         }
932         break;
933
934     case WM_GETTEXT:
935         if (wParam)
936         {
937             LPWSTR dest = (LPWSTR)lParam;
938             WND *wndPtr = WIN_GetPtr( hwnd );
939
940             if (!wndPtr) break;
941             if (wndPtr->text)
942             {
943                 lstrcpynW( dest, wndPtr->text, wParam );
944                 result = strlenW( dest );
945             }
946             else dest[0] = '\0';
947             WIN_ReleasePtr( wndPtr );
948         }
949         break;
950
951     case WM_SETTEXT:
952         DEFWND_SetTextW( hwnd, (LPCWSTR)lParam );
953         if( (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CAPTION) == WS_CAPTION )
954             NC_HandleNCPaint( hwnd , (HRGN)1 );  /* Repaint caption */
955         result = 1; /* success. FIXME: check text length */
956         break;
957
958     /* for far east users (IMM32) - <hidenori@a2.ctktv.ne.jp> */
959     case WM_IME_CHAR:
960         SendMessageW( hwnd, WM_CHAR, wParam, lParam );
961         break;
962     case WM_IME_SETCONTEXT:
963         {
964             HWND hwndIME;
965
966             hwndIME = DEFWND_ImmGetDefaultIMEWnd( hwnd );
967             if (hwndIME)
968                 result = DEFWND_ImmIsUIMessageW( hwndIME, msg, wParam, lParam );
969         }
970         break;
971
972     default:
973         result = DEFWND_DefWinProc( hwnd, msg, wParam, lParam );
974         break;
975     }
976     SPY_ExitMessage( SPY_RESULT_DEFWND, hwnd, msg, result, wParam, lParam );
977     return result;
978 }