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