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