-Fixed MESSAGE functions that were thunking down to 16 bits implementation.
[wine] / windows / defwnd.c
1 /*
2  * Default window procedure
3  *
4  * Copyright 1993, 1996 Alexandre Julliard
5  *           1995 Alex Korobka
6  */
7
8 #include <stdlib.h>
9 #include "win.h"
10 #include "user.h"
11 #include "heap.h"
12 #include "nonclient.h"
13 #include "winpos.h"
14 #include "dce.h"
15 #include "sysmetrics.h"
16 #include "debug.h"
17 #include "spy.h"
18 #include "tweak.h"
19 #include "wine/winuser16.h"
20
21   /* Last COLOR id */
22 #define COLOR_MAX   COLOR_BTNHIGHLIGHT
23
24   /* bits in the dwKeyData */
25 #define KEYDATA_ALT             0x2000
26 #define KEYDATA_PREVSTATE       0x4000
27
28 static short iF10Key = 0;
29 static short iMenuSysKey = 0;
30
31 /***********************************************************************
32  *           DEFWND_HandleWindowPosChanged
33  *
34  * Handle the WM_WINDOWPOSCHANGED message.
35  */
36 static void DEFWND_HandleWindowPosChanged( WND *wndPtr, UINT32 flags )
37 {
38     WPARAM16 wp = SIZE_RESTORED;
39
40     if (!(flags & SWP_NOCLIENTMOVE))
41         SendMessage16( wndPtr->hwndSelf, WM_MOVE, 0,
42                     MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top));
43     if (!(flags & SWP_NOCLIENTSIZE))
44     {
45         if (wndPtr->dwStyle & WS_MAXIMIZE) wp = SIZE_MAXIMIZED;
46         else if (wndPtr->dwStyle & WS_MINIMIZE) wp = SIZE_MINIMIZED;
47
48         SendMessage16( wndPtr->hwndSelf, WM_SIZE, wp, 
49                      MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
50                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
51     }
52 }
53
54
55 /***********************************************************************
56  *           DEFWND_SetText
57  *
58  * Set the window text.
59  */
60 void DEFWND_SetText( WND *wndPtr, LPCSTR text )
61 {
62     if (!text) text = "";
63     if (wndPtr->text) HeapFree( SystemHeap, 0, wndPtr->text );
64     wndPtr->text = HEAP_strdupA( SystemHeap, 0, text );    
65     wndPtr->pDriver->pSetText(wndPtr, wndPtr->text);
66 }
67
68 /***********************************************************************
69  *           DEFWND_ControlColor
70  *
71  * Default colors for control painting.
72  */
73 HBRUSH32 DEFWND_ControlColor( HDC32 hDC, UINT16 ctlType )
74 {
75     if( ctlType == CTLCOLOR_SCROLLBAR)
76     {
77         HBRUSH32 hb = GetSysColorBrush32(COLOR_SCROLLBAR);
78         SetBkColor32( hDC, RGB(255, 255, 255) );
79         SetTextColor32( hDC, RGB(0, 0, 0) );
80         UnrealizeObject32( hb );
81         return hb;
82     }
83
84     SetTextColor32( hDC, GetSysColor32(COLOR_WINDOWTEXT));
85
86     if (TWEAK_WineLook > WIN31_LOOK) {
87         if ((ctlType == CTLCOLOR_EDIT) || (ctlType == CTLCOLOR_LISTBOX))
88             SetBkColor32( hDC, GetSysColor32(COLOR_WINDOW) );
89         else {
90             SetBkColor32( hDC, GetSysColor32(COLOR_3DFACE) );
91             return GetSysColorBrush32(COLOR_3DFACE);
92         }
93     }
94     else
95         SetBkColor32( hDC, GetSysColor32(COLOR_WINDOW) );
96     return GetSysColorBrush32(COLOR_WINDOW);
97 }
98
99
100 /***********************************************************************
101  *           DEFWND_SetRedraw
102  */
103 static void DEFWND_SetRedraw( WND* wndPtr, WPARAM32 wParam )
104 {
105     BOOL32 bVisible = wndPtr->dwStyle & WS_VISIBLE;
106
107     TRACE(win,"%04x %i\n", wndPtr->hwndSelf, (wParam!=0) );
108
109     if( wParam )
110     {
111         if( !bVisible )
112         {
113             wndPtr->dwStyle |= WS_VISIBLE;
114             DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
115         }
116     }
117     else if( bVisible )
118     {
119         if( wndPtr->dwStyle & WS_MINIMIZE ) wParam = RDW_VALIDATE;
120         else wParam = RDW_ALLCHILDREN | RDW_VALIDATE;
121
122         PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, wParam, 0 );
123         DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
124         wndPtr->dwStyle &= ~WS_VISIBLE;
125     }
126 }
127
128 /***********************************************************************
129  *           DEFWND_DefWinProc
130  *
131  * Default window procedure for messages that are the same in Win16 and Win32.
132  */
133 static LRESULT DEFWND_DefWinProc( WND *wndPtr, UINT32 msg, WPARAM32 wParam,
134                                   LPARAM lParam )
135 {
136     switch(msg)
137     {
138     case WM_NCPAINT:
139         return NC_HandleNCPaint( wndPtr->hwndSelf, (HRGN32)wParam );
140
141     case WM_NCHITTEST:
142         return NC_HandleNCHitTest( wndPtr->hwndSelf, MAKEPOINT16(lParam) );
143
144     case WM_NCLBUTTONDOWN:
145         return NC_HandleNCLButtonDown( wndPtr, wParam, lParam );
146
147     case WM_LBUTTONDBLCLK:
148     case WM_NCLBUTTONDBLCLK:
149         return NC_HandleNCLButtonDblClk( wndPtr, wParam, lParam );
150
151     case WM_RBUTTONDOWN:
152     case WM_NCRBUTTONDOWN:
153         if ((wndPtr->flags & WIN_ISWIN32) || (TWEAK_WineLook > WIN31_LOOK))
154         {
155             ClientToScreen16(wndPtr->hwndSelf, (LPPOINT16)&lParam);
156             SendMessage32A( wndPtr->hwndSelf, WM_CONTEXTMENU,
157                             wndPtr->hwndSelf, lParam);
158         }
159         break;
160
161     case WM_CONTEXTMENU:
162         if( wndPtr->dwStyle & WS_CHILD )
163             SendMessage32A( wndPtr->parent->hwndSelf, msg, wParam, lParam );
164         else
165           if (wndPtr->hSysMenu)
166           { /*
167             TrackPopupMenu32(wndPtr->hSysMenu,TPM_LEFTALIGN | TPM_RETURNCMD,LOWORD(lParam),HIWORD(lParam),0,wndPtr->hwndSelf,NULL);
168             DestroyMenu32(wndPtr->hSysMenu);
169             */
170             FIXME(win,"Display default popup menu\n");
171           /* Track system popup if click was in the caption area. */
172           }
173         break;
174
175     case WM_NCACTIVATE:
176         return NC_HandleNCActivate( wndPtr, wParam );
177
178     case WM_NCDESTROY:
179         if (wndPtr->text) HeapFree( SystemHeap, 0, wndPtr->text );
180         wndPtr->text = NULL;
181         if (wndPtr->pVScroll) HeapFree( SystemHeap, 0, wndPtr->pVScroll );
182         if (wndPtr->pHScroll) HeapFree( SystemHeap, 0, wndPtr->pHScroll );
183         wndPtr->pVScroll = wndPtr->pHScroll = NULL;
184         return 0;
185
186     case WM_PAINTICON:
187     case WM_PAINT:
188         {
189             PAINTSTRUCT16 ps;
190             HDC16 hdc = BeginPaint16( wndPtr->hwndSelf, &ps );
191             if( hdc ) 
192             {
193               if( (wndPtr->dwStyle & WS_MINIMIZE) && wndPtr->class->hIcon )
194               {
195                 int x = (wndPtr->rectWindow.right - wndPtr->rectWindow.left -
196                         SYSMETRICS_CXICON)/2;
197                 int y = (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top -
198                         SYSMETRICS_CYICON)/2;
199                 TRACE(win,"Painting class icon: vis rect=(%i,%i - %i,%i)\n",
200                 ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom );
201                 DrawIcon32( hdc, x, y, wndPtr->class->hIcon );
202               }
203               EndPaint16( wndPtr->hwndSelf, &ps );
204             }
205             return 0;
206         }
207
208     case WM_SETREDRAW:
209         DEFWND_SetRedraw( wndPtr, wParam );
210         return 0;
211
212     case WM_CLOSE:
213         DestroyWindow32( wndPtr->hwndSelf );
214         return 0;
215
216     case WM_MOUSEACTIVATE:
217         if (wndPtr->dwStyle & WS_CHILD)
218         {
219             LONG ret = SendMessage16( wndPtr->parent->hwndSelf,
220                                       WM_MOUSEACTIVATE, wParam, lParam );
221             if (ret) return ret;
222         }
223
224         /* Caption clicks are handled by the NC_HandleNCLButtonDown() */ 
225         return (LOWORD(lParam) == HTCAPTION) ? MA_NOACTIVATE : MA_ACTIVATE;
226
227     case WM_ACTIVATE:
228         if (LOWORD(wParam) != WA_INACTIVE) 
229                 SetWindowPos32(wndPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0,
230                          SWP_NOMOVE | SWP_NOSIZE);
231         break;
232
233     case WM_ERASEBKGND:
234     case WM_ICONERASEBKGND:
235         {
236             if (!wndPtr->class->hbrBackground) return 0;
237
238             if (wndPtr->class->hbrBackground <= (HBRUSH16)(COLOR_MAX+1))
239             {
240                 HBRUSH32 hbrush = CreateSolidBrush32( 
241                        GetSysColor32(((DWORD)wndPtr->class->hbrBackground)-1));
242                  FillWindow( GetParent16(wndPtr->hwndSelf), wndPtr->hwndSelf,
243                              (HDC16)wParam, hbrush);
244                  DeleteObject32( hbrush );
245             }
246             else FillWindow( GetParent16(wndPtr->hwndSelf), wndPtr->hwndSelf,
247                              (HDC16)wParam, wndPtr->class->hbrBackground );
248             return 1;
249         }
250
251     case WM_GETDLGCODE:
252         return 0;
253
254     case WM_CTLCOLORMSGBOX:
255     case WM_CTLCOLOREDIT:
256     case WM_CTLCOLORLISTBOX:
257     case WM_CTLCOLORBTN:
258     case WM_CTLCOLORDLG:
259     case WM_CTLCOLORSTATIC:
260     case WM_CTLCOLORSCROLLBAR:
261         return (LRESULT)DEFWND_ControlColor( (HDC32)wParam, msg - WM_CTLCOLORMSGBOX );
262
263     case WM_CTLCOLOR:
264         return (LRESULT)DEFWND_ControlColor( (HDC32)wParam, HIWORD(lParam) );
265         
266     case WM_GETTEXTLENGTH:
267         if (wndPtr->text) return (LRESULT)strlen(wndPtr->text);
268         return 0;
269
270     case WM_SETCURSOR:
271         if (wndPtr->dwStyle & WS_CHILD)
272             if (SendMessage16(wndPtr->parent->hwndSelf, WM_SETCURSOR,
273                             wParam, lParam))
274                 return TRUE;
275         return NC_HandleSetCursor( wndPtr->hwndSelf, wParam, lParam );
276
277     case WM_SYSCOMMAND:
278         return NC_HandleSysCommand( wndPtr->hwndSelf, wParam,
279                                     MAKEPOINT16(lParam) );
280
281     case WM_KEYDOWN:
282         if(wParam == VK_F10) iF10Key = VK_F10;
283         break;
284
285     case WM_SYSKEYDOWN:
286         if( HIWORD(lParam) & KEYDATA_ALT )
287         {
288             /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
289               if( wParam == VK_MENU && !iMenuSysKey )
290                 iMenuSysKey = 1;
291               else
292                 iMenuSysKey = 0;
293             
294             iF10Key = 0;
295
296             if( wParam == VK_F4 )       /* try to close the window */
297             {
298                 HWND32 hWnd = WIN_GetTopParent( wndPtr->hwndSelf );
299                 wndPtr = WIN_FindWndPtr( hWnd );
300                 if( wndPtr && !(wndPtr->class->style & CS_NOCLOSE) )
301                     PostMessage16( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
302             }
303         } 
304         else if( wParam == VK_F10 )
305                 iF10Key = 1;
306              else
307                 if( wParam == VK_ESCAPE && (GetKeyState32(VK_SHIFT) & 0x8000))
308                     SendMessage16( wndPtr->hwndSelf, WM_SYSCOMMAND,
309                                   (WPARAM16)SC_KEYMENU, (LPARAM)VK_SPACE);
310         break;
311
312     case WM_KEYUP:
313     case WM_SYSKEYUP:
314         /* Press and release F10 or ALT */
315         if (((wParam == VK_MENU) && iMenuSysKey) ||
316             ((wParam == VK_F10) && iF10Key))
317               SendMessage16( WIN_GetTopParent(wndPtr->hwndSelf),
318                              WM_SYSCOMMAND, SC_KEYMENU, 0L );
319         iMenuSysKey = iF10Key = 0;
320         break;
321
322     case WM_SYSCHAR:
323         iMenuSysKey = 0;
324         if (wParam == VK_RETURN && (wndPtr->dwStyle & WS_MINIMIZE))
325         {
326             PostMessage16( wndPtr->hwndSelf, WM_SYSCOMMAND,
327                            (WPARAM16)SC_RESTORE, 0L ); 
328             break;
329         } 
330         if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
331         {
332             if (wParam == VK_TAB || wParam == VK_ESCAPE) break;
333             if (wParam == VK_SPACE && (wndPtr->dwStyle & WS_CHILD))
334                 SendMessage16( wndPtr->parent->hwndSelf, msg, wParam, lParam );
335             else
336                 SendMessage16( wndPtr->hwndSelf, WM_SYSCOMMAND,
337                                (WPARAM16)SC_KEYMENU, (LPARAM)(DWORD)wParam );
338         } 
339         else /* check for Ctrl-Esc */
340             if (wParam != VK_ESCAPE) MessageBeep32(0);
341         break;
342
343     case WM_SHOWWINDOW:
344         if (!lParam) return 0; /* sent from ShowWindow */
345         if (!(wndPtr->dwStyle & WS_POPUP) || !wndPtr->owner) return 0;
346         if ((wndPtr->dwStyle & WS_VISIBLE) && wParam) return 0;
347         else if (!(wndPtr->dwStyle & WS_VISIBLE) && !wParam) return 0;
348         ShowWindow32( wndPtr->hwndSelf, wParam ? SW_SHOWNOACTIVATE : SW_HIDE );
349         break; 
350
351     case WM_CANCELMODE:
352         if (wndPtr->parent == WIN_GetDesktop()) EndMenu();
353         if (GetCapture32() == wndPtr->hwndSelf) ReleaseCapture();
354         break;
355
356     case WM_VKEYTOITEM:
357     case WM_CHARTOITEM:
358         return -1;
359
360     case WM_DROPOBJECT:
361         return DRAG_FILE;  
362
363     case WM_QUERYDROPOBJECT:
364         if (wndPtr->dwExStyle & WS_EX_ACCEPTFILES) return 1;
365         break;
366
367     case WM_QUERYDRAGICON:
368         {
369             HICON16 hIcon=0;
370             UINT16 len;
371
372             if( (hIcon=wndPtr->class->hCursor) ) return (LRESULT)hIcon;
373             for(len=1; len<64; len++)
374                 if((hIcon=LoadIcon16(wndPtr->hInstance,MAKEINTRESOURCE16(len))))
375                     return (LRESULT)hIcon;
376             return (LRESULT)LoadIcon16(0,IDI_APPLICATION16);
377         }
378         break;
379
380     case WM_ISACTIVEICON:
381         return ((wndPtr->flags & WIN_NCACTIVATED) != 0);
382
383     case WM_QUERYOPEN:
384     case WM_QUERYENDSESSION:
385         return 1;
386     }
387     return 0;
388 }
389
390
391
392 /***********************************************************************
393  *           DefWindowProc16   (USER.107)
394  */
395 LRESULT WINAPI DefWindowProc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
396                                 LPARAM lParam )
397 {
398     WND * wndPtr = WIN_FindWndPtr( hwnd );
399     LRESULT result = 0;
400
401     if (!wndPtr) return 0;
402     SPY_EnterMessage( SPY_DEFWNDPROC16, hwnd, msg, wParam, lParam );
403
404     switch(msg)
405     {
406     case WM_NCCREATE:
407         {
408             CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
409             if (cs->lpszName)
410                 DEFWND_SetText( wndPtr, (LPSTR)PTR_SEG_TO_LIN(cs->lpszName) );
411             result = 1;
412         }
413         break;
414
415     case WM_NCCALCSIZE:
416         {
417             RECT32 rect32;
418             CONV_RECT16TO32( (RECT16 *)PTR_SEG_TO_LIN(lParam), &rect32 );
419             result = NC_HandleNCCalcSize( wndPtr, &rect32 );
420             CONV_RECT32TO16( &rect32, (RECT16 *)PTR_SEG_TO_LIN(lParam) );
421         }
422         break;
423
424     case WM_WINDOWPOSCHANGING:
425         result = WINPOS_HandleWindowPosChanging16( wndPtr,
426                                        (WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam) );
427         break;
428
429     case WM_WINDOWPOSCHANGED:
430         {
431             WINDOWPOS16 * winPos = (WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam);
432             DEFWND_HandleWindowPosChanged( wndPtr, winPos->flags );
433         }
434         break;
435
436     case WM_GETTEXT:
437         if (wParam && wndPtr->text)
438         {
439             lstrcpyn32A( (LPSTR)PTR_SEG_TO_LIN(lParam), wndPtr->text, wParam );
440             result = (LRESULT)strlen( (LPSTR)PTR_SEG_TO_LIN(lParam) );
441         }
442         break;
443
444     case WM_SETTEXT:
445         DEFWND_SetText( wndPtr, (LPSTR)PTR_SEG_TO_LIN(lParam) );
446         if( wndPtr->dwStyle & WS_CAPTION ) NC_HandleNCPaint( hwnd , (HRGN32)1 );
447         break;
448
449     default:
450         result = DEFWND_DefWinProc( wndPtr, msg, wParam, lParam );
451         break;
452     }
453
454     SPY_ExitMessage( SPY_RESULT_DEFWND16, hwnd, msg, result );
455     return result;
456 }
457
458
459 /***********************************************************************
460  *  DefWindowProc32A [USER32.126] 
461  *
462  */
463 LRESULT WINAPI DefWindowProc32A( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
464                                  LPARAM lParam )
465 {
466     WND * wndPtr = WIN_FindWndPtr( hwnd );
467     LRESULT result = 0;
468
469     if (!wndPtr) return 0;
470     SPY_EnterMessage( SPY_DEFWNDPROC32, hwnd, msg, wParam, lParam );
471
472     switch(msg)
473     {
474     case WM_NCCREATE:
475         {
476             CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
477             if (cs->lpszName) DEFWND_SetText( wndPtr, cs->lpszName );
478             result = 1;
479         }
480         break;
481
482     case WM_NCCALCSIZE:
483         result = NC_HandleNCCalcSize( wndPtr, (RECT32 *)lParam );
484         break;
485
486     case WM_WINDOWPOSCHANGING:
487         result = WINPOS_HandleWindowPosChanging32( wndPtr,
488                                                    (WINDOWPOS32 *)lParam );
489         break;
490
491     case WM_WINDOWPOSCHANGED:
492         {
493             WINDOWPOS32 * winPos = (WINDOWPOS32 *)lParam;
494             DEFWND_HandleWindowPosChanged( wndPtr, winPos->flags );
495         }
496         break;
497
498     case WM_GETTEXT:
499         if (wParam && wndPtr->text)
500         {
501             lstrcpyn32A( (LPSTR)lParam, wndPtr->text, wParam );
502             result = (LRESULT)strlen( (LPSTR)lParam );
503         }
504         break;
505
506     case WM_SETTEXT:
507         DEFWND_SetText( wndPtr, (LPSTR)lParam );
508         NC_HandleNCPaint( hwnd , (HRGN32)1 );  /* Repaint caption */
509         break;
510
511     default:
512         result = DEFWND_DefWinProc( wndPtr, msg, wParam, lParam );
513         break;
514     }
515
516     SPY_ExitMessage( SPY_RESULT_DEFWND32, hwnd, msg, result );
517     return result;
518 }
519
520
521 /***********************************************************************
522  * DefWindowProc32W [USER32.127] Calls default window message handler
523  * 
524  * Calls default window procedure for messages not processed 
525  *  by application.
526  *
527  *  RETURNS
528  *     Return value is dependent upon the message.
529 */
530 LRESULT WINAPI DefWindowProc32W( 
531     HWND32 hwnd,      /* [in] window procedure recieving message */
532     UINT32 msg,       /* [in] message identifier */
533     WPARAM32 wParam,  /* [in] first message parameter */
534     LPARAM lParam )   /* [in] second message parameter */
535 {
536     LRESULT result;
537
538     switch(msg)
539     {
540     case WM_NCCREATE:
541         {
542             CREATESTRUCT32W *cs = (CREATESTRUCT32W *)lParam;
543             if (cs->lpszName)
544             {
545                 WND *wndPtr = WIN_FindWndPtr( hwnd );
546                 LPSTR str = HEAP_strdupWtoA(GetProcessHeap(), 0, cs->lpszName);
547                 DEFWND_SetText( wndPtr, str );
548                 HeapFree( GetProcessHeap(), 0, str );
549             }
550             result = 1;
551         }
552         break;
553
554     case WM_GETTEXT:
555         {
556             LPSTR str = HeapAlloc( GetProcessHeap(), 0, wParam );
557             result = DefWindowProc32A( hwnd, msg, wParam, (LPARAM)str );
558             lstrcpynAtoW( (LPWSTR)lParam, str, wParam );
559             HeapFree( GetProcessHeap(), 0, str );
560         }
561         break;
562
563     case WM_SETTEXT:
564         {
565             LPSTR str = HEAP_strdupWtoA( GetProcessHeap(), 0, (LPWSTR)lParam );
566             result = DefWindowProc32A( hwnd, msg, wParam, (LPARAM)str );
567             HeapFree( GetProcessHeap(), 0, str );
568         }
569         break;
570
571     default:
572         result = DefWindowProc32A( hwnd, msg, wParam, lParam );
573         break;
574     }
575     return result;
576 }