Release 961201
[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 <stdio.h>
10 #include "win.h"
11 #include "user.h"
12 #include "heap.h"
13 #include "nonclient.h"
14 #include "winpos.h"
15 #include "string32.h"
16 #include "syscolor.h"
17 #include "sysmetrics.h"
18 #include "stddebug.h"
19 #include "debug.h"
20 #include "spy.h"
21
22   /* Last COLOR id */
23 #define COLOR_MAX   COLOR_BTNHIGHLIGHT
24
25   /* bits in the dwKeyData */
26 #define KEYDATA_ALT             0x2000
27 #define KEYDATA_PREVSTATE       0x4000
28
29 static short iF10Key = 0;
30 static short iMenuSysKey = 0;
31
32 /***********************************************************************
33  *           DEFWND_HandleWindowPosChanged
34  *
35  * Handle the WM_WINDOWPOSCHANGED message.
36  */
37 static void DEFWND_HandleWindowPosChanged( WND *wndPtr, UINT32 flags )
38 {
39     WPARAM16 wp = SIZE_RESTORED;
40
41     if (!(flags & SWP_NOCLIENTMOVE))
42         SendMessage16( wndPtr->hwndSelf, WM_MOVE, 0,
43                     MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top));
44     if (!(flags & SWP_NOCLIENTSIZE))
45     {
46         if (wndPtr->dwStyle & WS_MAXIMIZE) wp = SIZE_MAXIMIZED;
47         else if (wndPtr->dwStyle & WS_MINIMIZE) wp = SIZE_MINIMIZED;
48
49         SendMessage16( wndPtr->hwndSelf, WM_SIZE, wp, 
50                      MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
51                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
52     }
53 }
54
55
56 /***********************************************************************
57  *           DEFWND_SetText
58  *
59  * Set the window text.
60  */
61 void DEFWND_SetText( WND *wndPtr, LPCSTR text )
62 {
63     if (!text) text = "";
64     if (wndPtr->text) HeapFree( SystemHeap, 0, wndPtr->text );
65     wndPtr->text = HEAP_strdupA( SystemHeap, 0, text );
66     if (wndPtr->window) XStoreName( display, wndPtr->window, wndPtr->text );
67 }
68
69
70 /***********************************************************************
71  *           DEFWND_DefWinProc
72  *
73  * Default window procedure for messages that are the same in Win16 and Win32.
74  */
75 static LRESULT DEFWND_DefWinProc( WND *wndPtr, UINT32 msg, WPARAM32 wParam,
76                                   LPARAM lParam )
77 {
78     switch(msg)
79     {
80     case WM_NCPAINT:
81         return NC_HandleNCPaint( wndPtr->hwndSelf, (HRGN32)wParam );
82
83     case WM_NCHITTEST:
84         return NC_HandleNCHitTest( wndPtr->hwndSelf, MAKEPOINT16(lParam) );
85
86     case WM_NCLBUTTONDOWN:
87         return NC_HandleNCLButtonDown( wndPtr->hwndSelf, wParam, lParam );
88
89     case WM_LBUTTONDBLCLK:
90     case WM_NCLBUTTONDBLCLK:
91         return NC_HandleNCLButtonDblClk( wndPtr, wParam, lParam );
92
93     case WM_NCACTIVATE:
94         return NC_HandleNCActivate( wndPtr, wParam );
95
96     case WM_NCDESTROY:
97         if (wndPtr->text) HeapFree( SystemHeap, 0, wndPtr->text );
98         wndPtr->text = NULL;
99         if (wndPtr->pVScroll) HeapFree( SystemHeap, 0, wndPtr->pVScroll );
100         if (wndPtr->pHScroll) HeapFree( SystemHeap, 0, wndPtr->pHScroll );
101         wndPtr->pVScroll = wndPtr->pHScroll = NULL;
102         return 0;
103
104     case WM_PAINTICON:
105     case WM_PAINT:
106         {
107             PAINTSTRUCT16 ps;
108             HDC16 hdc = BeginPaint16( wndPtr->hwndSelf, &ps );
109             if( hdc ) 
110             {
111               if( (wndPtr->dwStyle & WS_MINIMIZE) && wndPtr->class->hIcon )
112               {
113                 int x = (wndPtr->rectWindow.right - wndPtr->rectWindow.left -
114                         SYSMETRICS_CXICON)/2;
115                 int y = (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top -
116                         SYSMETRICS_CYICON)/2;
117                 dprintf_win(stddeb,"Painting class icon: vis rect=(%i,%i - %i,%i)\n",
118                 ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom );
119                 DrawIcon( hdc, x, y, wndPtr->class->hIcon );
120               }
121               EndPaint16( wndPtr->hwndSelf, &ps );
122             }
123             return 0;
124         }
125
126     case WM_SETREDRAW:
127         if (!wParam)
128         {
129             ValidateRect32( wndPtr->hwndSelf, NULL );
130             wndPtr->flags |= WIN_NO_REDRAW;
131         }
132         else wndPtr->flags &= ~WIN_NO_REDRAW;
133         return 0;
134
135     case WM_CLOSE:
136         DestroyWindow( wndPtr->hwndSelf );
137         return 0;
138
139     case WM_MOUSEACTIVATE:
140         if (wndPtr->dwStyle & WS_CHILD)
141         {
142             LONG ret = SendMessage16( wndPtr->parent->hwndSelf,
143                                       WM_MOUSEACTIVATE, wParam, lParam );
144             if (ret) return ret;
145         }
146         return MA_ACTIVATE;
147
148     case WM_ACTIVATE:
149         if (LOWORD(wParam) != WA_INACTIVE) SetFocus32( wndPtr->hwndSelf );
150         break;
151
152     case WM_ERASEBKGND:
153     case WM_ICONERASEBKGND:
154         {
155             if (!wndPtr->class->hbrBackground) return 0;
156
157             /* FIXME: should fill icon text with hbrushActiveCaption 
158                       instead of this */
159
160             if (wndPtr->dwStyle & WS_MINIMIZE )
161             {
162                  if( wndPtr->flags & WIN_NCACTIVATED )
163                  {
164                    FillWindow( GetParent16(wndPtr->hwndSelf), wndPtr->hwndSelf,
165                                (HDC16)wParam, sysColorObjects.hbrushActiveCaption );
166                    return 1;
167                  }
168
169                  /* FIXME: should draw parent' background somehow
170                              (e.g for textured desktop) ? */
171             }
172
173             if (wndPtr->class->hbrBackground <= (HBRUSH16)(COLOR_MAX+1))
174             {
175                 HBRUSH32 hbrush = CreateSolidBrush32( 
176                          GetSysColor(((DWORD)wndPtr->class->hbrBackground)-1));
177                  FillWindow( GetParent16(wndPtr->hwndSelf), wndPtr->hwndSelf,
178                              (HDC16)wParam, hbrush);
179                  DeleteObject32( hbrush );
180             }
181             else FillWindow( GetParent16(wndPtr->hwndSelf), wndPtr->hwndSelf,
182                              (HDC16)wParam, wndPtr->class->hbrBackground );
183             return 1;
184         }
185
186     case WM_GETDLGCODE:
187         return 0;
188
189     case WM_CTLCOLORMSGBOX:
190     case WM_CTLCOLOREDIT:
191     case WM_CTLCOLORLISTBOX:
192     case WM_CTLCOLORBTN:
193     case WM_CTLCOLORDLG:
194     case WM_CTLCOLORSTATIC:
195         SetBkColor( (HDC32)wParam, GetSysColor(COLOR_WINDOW) );
196         SetTextColor( (HDC32)wParam, GetSysColor(COLOR_WINDOWTEXT) );
197         return (LRESULT)sysColorObjects.hbrushWindow;
198
199     case WM_CTLCOLORSCROLLBAR:
200         SetBkColor( (HDC32)wParam, RGB(255, 255, 255) );
201         SetTextColor( (HDC32)wParam, RGB(0, 0, 0) );
202         UnrealizeObject32( sysColorObjects.hbrushScrollbar );
203         return (LRESULT)sysColorObjects.hbrushScrollbar;
204
205     case WM_CTLCOLOR:
206         {
207             if (HIWORD(lParam) == CTLCOLOR_SCROLLBAR)
208             {
209                 SetBkColor( (HDC32)wParam, RGB(255, 255, 255) );
210                 SetTextColor( (HDC32)wParam, RGB(0, 0, 0) );
211                 UnrealizeObject32( sysColorObjects.hbrushScrollbar );
212                 return (LRESULT)sysColorObjects.hbrushScrollbar;
213             }
214             else
215             {
216                 SetBkColor( (HDC32)wParam, GetSysColor(COLOR_WINDOW) );
217                 SetTextColor( (HDC32)wParam, GetSysColor(COLOR_WINDOWTEXT) );
218                 return (LRESULT)sysColorObjects.hbrushWindow;
219             }
220         }
221         
222     case WM_GETTEXTLENGTH:
223         if (wndPtr->text) return (LRESULT)strlen(wndPtr->text);
224         return 0;
225
226     case WM_SETCURSOR:
227         if (wndPtr->dwStyle & WS_CHILD)
228             if (SendMessage16(wndPtr->parent->hwndSelf, WM_SETCURSOR,
229                             wParam, lParam))
230                 return TRUE;
231         return NC_HandleSetCursor( wndPtr->hwndSelf, wParam, lParam );
232
233     case WM_SYSCOMMAND:
234         return NC_HandleSysCommand( wndPtr->hwndSelf, wParam,
235                                     MAKEPOINT16(lParam) );
236
237     case WM_KEYDOWN:
238         if(wParam == VK_F10) iF10Key = VK_F10;
239         break;
240
241     case WM_SYSKEYDOWN:
242         if( HIWORD(lParam) & KEYDATA_ALT )
243           {
244             /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
245               if( wParam == VK_MENU && !iMenuSysKey )
246                 iMenuSysKey = 1;
247               else
248                 iMenuSysKey = 0;
249             
250             iF10Key = 0;
251
252           } 
253         else if( wParam == VK_F10 )
254                  iF10Key = 1;
255              else
256                  if( wParam == VK_ESCAPE && GetKeyState(VK_SHIFT) < 0 )
257                      SendMessage16( wndPtr->hwndSelf, WM_SYSCOMMAND,
258                                     (WPARAM16)SC_KEYMENU, (LPARAM)VK_SPACE);
259         break;
260
261     case WM_KEYUP:
262     case WM_SYSKEYUP:
263         /* Press and release F10 or ALT */
264         if (((wParam == VK_MENU) && iMenuSysKey) ||
265             ((wParam == VK_F10) && iF10Key))
266               SendMessage16( WIN_GetTopParent(wndPtr->hwndSelf),
267                              WM_SYSCOMMAND, SC_KEYMENU, 0L );
268         iMenuSysKey = iF10Key = 0;
269         break;
270
271     case WM_SYSCHAR:
272         iMenuSysKey = 0;
273         if (wParam == VK_RETURN && (wndPtr->dwStyle & WS_MINIMIZE))
274         {
275             PostMessage( wndPtr->hwndSelf, WM_SYSCOMMAND,
276                          (WPARAM16)SC_RESTORE, 0L ); 
277             break;
278         } 
279         if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
280         {
281             if (wParam == VK_TAB || wParam == VK_ESCAPE) break;
282             if (wParam == VK_SPACE && (wndPtr->dwStyle & WS_CHILD))
283                 SendMessage16( wndPtr->parent->hwndSelf, msg, wParam, lParam );
284             else
285                 SendMessage16( wndPtr->hwndSelf, WM_SYSCOMMAND,
286                                (WPARAM16)SC_KEYMENU, (LPARAM)(DWORD)wParam );
287         } 
288         else /* check for Ctrl-Esc */
289             if (wParam != VK_ESCAPE) MessageBeep(0);
290         break;
291
292     case WM_SHOWWINDOW:
293         if (!lParam) return 0; /* sent from ShowWindow */
294         if (!(wndPtr->dwStyle & WS_POPUP) || !wndPtr->owner) return 0;
295         if ((wndPtr->dwStyle & WS_VISIBLE) && wParam) return 0;
296         else if (!(wndPtr->dwStyle & WS_VISIBLE) && !wParam) return 0;
297         ShowWindow( wndPtr->hwndSelf, wParam ? SW_SHOWNOACTIVATE : SW_HIDE );
298         break; 
299
300     case WM_CANCELMODE:
301         /* EndMenu() should be called if in menu state but currently it's
302            impossible to detect - menu code should be updated*/
303         if (GetCapture32() == wndPtr->hwndSelf) ReleaseCapture();
304         break;
305
306     case WM_VKEYTOITEM:
307     case WM_CHARTOITEM:
308         return -1;
309
310     case WM_DROPOBJECT:
311         return DRAG_FILE;  
312
313     case WM_QUERYDROPOBJECT:
314         if (wndPtr->dwExStyle & WS_EX_ACCEPTFILES) return 1;
315         break;
316
317     case WM_QUERYDRAGICON:
318         {
319             HICON16 hI = 0;
320             UINT16 len = 1;
321             while(len < 64)
322                 if( (hI = LoadIcon16(wndPtr->hInstance,MAKEINTRESOURCE(len))) )
323                     return (LRESULT)hI;
324         }
325         break;
326
327     case WM_QUERYOPEN:
328     case WM_QUERYENDSESSION:
329         return 1;
330     }
331     return 0;
332 }
333
334
335
336 /***********************************************************************
337  *           DefWindowProc16   (USER.107)
338  */
339 LRESULT DefWindowProc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
340                          LPARAM lParam )
341 {
342     WND * wndPtr = WIN_FindWndPtr( hwnd );
343     LRESULT result = 0;
344
345     if (!wndPtr) return 0;
346     SPY_EnterMessage( SPY_DEFWNDPROC16, hwnd, msg, wParam, lParam );
347
348     switch(msg)
349     {
350     case WM_NCCREATE:
351         {
352             CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
353             if (cs->lpszName)
354                 DEFWND_SetText( wndPtr, (LPSTR)PTR_SEG_TO_LIN(cs->lpszName) );
355             result = 1;
356         }
357         break;
358
359     case WM_NCCALCSIZE:
360         result = NC_HandleNCCalcSize(wndPtr, (RECT16 *)PTR_SEG_TO_LIN(lParam));
361         break;
362
363     case WM_WINDOWPOSCHANGING:
364         result = WINPOS_HandleWindowPosChanging16( wndPtr,
365                                        (WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam) );
366         break;
367
368     case WM_WINDOWPOSCHANGED:
369         {
370             WINDOWPOS16 * winPos = (WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam);
371             DEFWND_HandleWindowPosChanged( wndPtr, winPos->flags );
372         }
373         break;
374
375     case WM_GETTEXT:
376         if (wParam && wndPtr->text)
377         {
378             lstrcpyn32A( (LPSTR)PTR_SEG_TO_LIN(lParam), wndPtr->text, wParam );
379             result = (LRESULT)strlen( (LPSTR)PTR_SEG_TO_LIN(lParam) );
380         }
381         break;
382
383     case WM_SETTEXT:
384         DEFWND_SetText( wndPtr, (LPSTR)PTR_SEG_TO_LIN(lParam) );
385         NC_HandleNCPaint( hwnd , (HRGN32)1 );  /* Repaint caption */
386         break;
387
388     default:
389         result = DEFWND_DefWinProc( wndPtr, msg, wParam, lParam );
390         break;
391     }
392
393     SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, result );
394     return result;
395 }
396
397
398 /***********************************************************************
399  *           DefWindowProc32A   (USER32.125)
400  */
401 LRESULT DefWindowProc32A( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
402                           LPARAM lParam )
403 {
404     WND * wndPtr = WIN_FindWndPtr( hwnd );
405     LRESULT result = 0;
406
407     if (!wndPtr) return 0;
408     SPY_EnterMessage( SPY_DEFWNDPROC32, hwnd, msg, wParam, lParam );
409
410     switch(msg)
411     {
412     case WM_NCCREATE:
413         {
414             CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
415             if (cs->lpszName) DEFWND_SetText( wndPtr, cs->lpszName );
416             result = 1;
417         }
418         break;
419
420     case WM_NCCALCSIZE:
421         {
422             RECT16 rect16;
423             CONV_RECT32TO16( (RECT32 *)lParam, &rect16 );
424             result = NC_HandleNCCalcSize( wndPtr, &rect16 );
425             CONV_RECT16TO32( &rect16, (RECT32 *)lParam );
426         }
427         break;
428
429     case WM_WINDOWPOSCHANGING:
430         result = WINPOS_HandleWindowPosChanging32( wndPtr,
431                                                    (WINDOWPOS32 *)lParam );
432         break;
433
434     case WM_WINDOWPOSCHANGED:
435         {
436             WINDOWPOS32 * winPos = (WINDOWPOS32 *)lParam;
437             DEFWND_HandleWindowPosChanged( wndPtr, winPos->flags );
438         }
439         break;
440
441     case WM_GETTEXT:
442         if (wParam && wndPtr->text)
443         {
444             lstrcpyn32A( (LPSTR)lParam, wndPtr->text, wParam );
445             result = (LRESULT)strlen( (LPSTR)lParam );
446         }
447         break;
448
449     case WM_SETTEXT:
450         DEFWND_SetText( wndPtr, (LPSTR)lParam );
451         NC_HandleNCPaint( hwnd , (HRGN32)1 );  /* Repaint caption */
452         break;
453
454     default:
455         result = DEFWND_DefWinProc( wndPtr, msg, wParam, lParam );
456         break;
457     }
458
459     SPY_ExitMessage( SPY_RESULT_OK32, hwnd, msg, result );
460     return result;
461 }
462
463
464 /***********************************************************************
465  *           DefWindowProc32W   (USER32.126)
466  */
467 LRESULT DefWindowProc32W( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
468                           LPARAM lParam )
469 {
470     LRESULT result;
471
472     switch(msg)
473     {
474     case WM_NCCREATE:
475         {
476             CREATESTRUCT32W *cs = (CREATESTRUCT32W *)lParam;
477             if (cs->lpszName)
478             {
479                 WND *wndPtr = WIN_FindWndPtr( hwnd );
480                 LPSTR str = STRING32_DupUniToAnsi( cs->lpszName );
481                 DEFWND_SetText( wndPtr, str );
482                 free( str );
483             }
484             result = 1;
485         }
486         break;
487
488     case WM_GETTEXT:
489         {
490             LPSTR str = malloc( wParam );
491             result = DefWindowProc32A( hwnd, msg, wParam, (LPARAM)str );
492             STRING32_AnsiToUni( (LPWSTR)lParam, str );
493             free( str );
494         }
495         break;
496
497     case WM_SETTEXT:
498         {
499             LPSTR str = STRING32_DupUniToAnsi( (LPWSTR)lParam );
500             result = DefWindowProc32A( hwnd, msg, wParam, (LPARAM)str );
501             free( str );
502         }
503         break;
504
505     default:
506         result = DefWindowProc32A( hwnd, msg, wParam, lParam );
507         break;
508     }
509     return result;
510 }