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