- Better implementation of window non-client area functions.
[reactos.git] / reactos / lib / user32 / windows / defwnd.c
1 /* $Id: defwnd.c,v 1.102 2003/10/25 22:57:34 navaraf Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS user32.dll
5 * FILE: lib/user32/windows/window.c
6 * PURPOSE: Window management
7 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * UPDATE HISTORY:
9 * 06-06-2001 CSH Created
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <windows.h>
15 #include <user32.h>
16 #include <window.h>
17 #include <user32/wininternal.h>
18 #include <string.h>
19 #include <menu.h>
20 #include <cursor.h>
21 #include <winpos.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26 LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn);
27 LRESULT DefWndNCCalcSize(HWND hWnd, BOOL CalcSizeStruct, RECT *Rect);
28 LRESULT DefWndNCActivate(HWND hWnd, WPARAM wParam);
29 LRESULT DefWndNCHitTest(HWND hWnd, POINT Point);
30 LRESULT DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam);
31 LRESULT DefWndNCLButtonDblClk(HWND hWnd, WPARAM wParam, LPARAM lParam);
32 LRESULT DefWndNCLButtonUp(HWND hWnd, WPARAM wParam, LPARAM lParam);
33
34 /* GLOBALS *******************************************************************/
35
36 /* TODO: widgets will be cached here.
37 static HBITMAP hbClose;
38 static HBITMAP hbCloseD;
39 static HBITMAP hbMinimize;
40 static HBITMAP hbMinimizeD;
41 static HBITMAP hbRestore;
42 static HBITMAP hbRestoreD;
43 static HBITMAP hbMaximize;
44 static HBITMAP hbScrUp;
45 static HBITMAP hbScrDwn;
46 static HBITMAP hbScrLeft;
47 static HBITMAP hbScrRight;
48 */
49
50
51 static COLORREF SysColours[] =
52 {
53 RGB(192, 192, 192) /* COLOR_SCROLLBAR */,
54 RGB(58, 110, 165) /* COLOR_BACKGROUND */,
55 RGB(0, 0, 128) /* COLOR_ACTIVECAPTION */,
56 RGB(128, 128, 128) /* COLOR_INACTIVECAPTION */,
57 RGB(192, 192, 192) /* COLOR_MENU */,
58 RGB(255, 255, 255) /* COLOR_WINDOW */,
59 RGB(0, 0, 0) /* COLOR_WINDOWFRAME */,
60 RGB(0, 0, 0) /* COLOR_MENUTEXT */,
61 RGB(0, 0, 0) /* COLOR_WINDOWTEXT */,
62 RGB(255, 255, 255) /* COLOR_CAPTIONTEXT */,
63 RGB(192, 192, 192) /* COLOR_ACTIVEBORDER */,
64 RGB(192, 192, 192) /* COLOR_INACTIVEBORDER */,
65 RGB(128, 128, 128) /* COLOR_APPWORKSPACE */,
66 RGB(0, 0, 128) /* COLOR_HILIGHT */,
67 RGB(255, 255, 255) /* COLOR_HILIGHTTEXT */,
68 RGB(192, 192, 192) /* COLOR_BTNFACE */,
69 RGB(128, 128, 128) /* COLOR_BTNSHADOW */,
70 RGB(128, 128, 128) /* COLOR_GRAYTEXT */,
71 RGB(0, 0, 0) /* COLOR_BTNTEXT */,
72 RGB(192, 192, 192) /* COLOR_INACTIVECAPTIONTEXT */,
73 RGB(255, 255, 255) /* COLOR_BTNHILIGHT */,
74 RGB(32, 32, 32) /* COLOR_3DDKSHADOW */,
75 RGB(224, 224, 224) /* COLOR_3DLIGHT */,
76 RGB(0, 0, 0) /* COLOR_INFOTEXT */,
77 RGB(255, 255, 192) /* COLOR_INFOBK */,
78 RGB(180, 180, 180) /* COLOR_ALTERNATEBTNFACE */,
79 RGB(0, 0, 255) /* COLOR_HOTLIGHT */,
80 RGB(16, 132, 208) /* COLOR_GRADIENTACTIVECAPTION */,
81 RGB(181, 181, 181) /* COLOR_GRADIENTINACTIVECAPTION */,
82 };
83
84 #define NUM_SYSCOLORS (sizeof(SysColours) / sizeof(SysColours[0]))
85
86 ATOM AtomInternalPos;
87
88 /* Bits in the dwKeyData */
89 #define KEYDATA_ALT 0x2000
90
91 /* FUNCTIONS *****************************************************************/
92
93 VOID
94 UserSetupInternalPos(VOID)
95 {
96 LPSTR Str = "SysIP";
97 AtomInternalPos = GlobalAddAtomA(Str);
98 }
99
100 /*
101 * @implemented
102 */
103 DWORD STDCALL
104 GetSysColor(int nIndex)
105 {
106 return SysColours[nIndex];
107 }
108
109 /*
110 * @implemented
111 */
112 HPEN STDCALL
113 GetSysColorPen(int nIndex)
114 {
115 static HPEN SysPens[NUM_SYSCOLORS];
116
117 if (nIndex < 0 || NUM_SYSCOLORS < nIndex)
118 {
119 SetLastError(ERROR_INVALID_PARAMETER);
120 return NULL;
121 }
122
123 /* FIXME should register this object with DeleteObject() so it
124 can't be deleted */
125 if (NULL == SysPens[nIndex])
126 {
127 SysPens[nIndex] = CreatePen(PS_SOLID, 1, SysColours[nIndex]);
128 }
129
130 return SysPens[nIndex];
131 }
132
133 /*
134 * @implemented
135 */
136 HBRUSH STDCALL
137 GetSysColorBrush(int nIndex)
138 {
139 static HBRUSH SysBrushes[NUM_SYSCOLORS];
140
141 if (nIndex < 0 || NUM_SYSCOLORS < nIndex)
142 {
143 SetLastError(ERROR_INVALID_PARAMETER);
144 return NULL;
145 }
146
147 /* FIXME should register this object with DeleteObject() so it
148 can't be deleted */
149 if (NULL == SysBrushes[nIndex])
150 {
151 SysBrushes[nIndex] = (HBRUSH) ((DWORD) CreateSolidBrush(SysColours[nIndex]) | 0x00800000);
152 }
153
154 return SysBrushes[nIndex];
155 }
156
157 /*
158 * @unimplemented
159 */
160 LRESULT STDCALL
161 DefFrameProcA( HWND hWnd,
162 HWND hWndMDIClient,
163 UINT uMsg,
164 WPARAM wParam,
165 LPARAM lParam )
166 {
167 UNIMPLEMENTED;
168 return ((LRESULT)0);
169 }
170
171 /*
172 * @unimplemented
173 */
174 LRESULT STDCALL
175 DefFrameProcW(HWND hWnd,
176 HWND hWndMDIClient,
177 UINT uMsg,
178 WPARAM wParam,
179 LPARAM lParam)
180 {
181 UNIMPLEMENTED;
182 return ((LRESULT)0);
183 }
184
185 PINTERNALPOS
186 UserGetInternalPos(HWND hWnd)
187 {
188 PINTERNALPOS lpPos;
189 lpPos = (PINTERNALPOS)GetPropA(hWnd, (LPSTR)(DWORD)AtomInternalPos);
190 return(lpPos);
191 }
192
193 ULONG
194 UserHasAnyFrameStyle(ULONG Style, ULONG ExStyle)
195 {
196 return ((Style & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) ||
197 (ExStyle & WS_EX_DLGMODALFRAME) ||
198 (!(Style & (WS_CHILD | WS_POPUP))));
199 }
200
201 ULONG
202 UserHasDlgFrameStyle(ULONG Style, ULONG ExStyle)
203 {
204 return ((ExStyle & WS_EX_DLGMODALFRAME) ||
205 ((Style & WS_DLGFRAME) && (!(Style & WS_THICKFRAME))));
206 }
207
208 ULONG
209 UserHasThickFrameStyle(ULONG Style, ULONG ExStyle)
210 {
211 return ((Style & WS_THICKFRAME) &&
212 (!((Style & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)));
213 }
214
215 ULONG
216 UserHasThinFrameStyle(ULONG Style, ULONG ExStyle)
217 {
218 return ((Style & WS_BORDER) || (!(Style & (WS_CHILD | WS_POPUP))));
219 }
220
221 ULONG
222 UserHasBigFrameStyle(ULONG Style, ULONG ExStyle)
223 {
224 return ((Style & (WS_THICKFRAME | WS_DLGFRAME)) ||
225 (ExStyle & WS_EX_DLGMODALFRAME));
226 }
227
228 void
229 UserGetInsideRectNC(HWND hWnd, RECT *rect)
230 {
231 RECT WindowRect;
232 ULONG Style;
233 ULONG ExStyle;
234
235 Style = GetWindowLongW(hWnd, GWL_STYLE);
236 ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
237 GetWindowRect(hWnd, &WindowRect);
238 rect->top = rect->left = 0;
239 rect->right = WindowRect.right - WindowRect.left;
240 rect->bottom = WindowRect.bottom - WindowRect.top;
241
242 if (Style & WS_ICONIC)
243 {
244 return;
245 }
246
247 /* Remove frame from rectangle */
248 if (UserHasThickFrameStyle(Style, ExStyle ))
249 {
250 InflateRect(rect, -GetSystemMetrics(SM_CXFRAME),
251 -GetSystemMetrics(SM_CYFRAME));
252 }
253 else
254 {
255 if (UserHasDlgFrameStyle(Style, ExStyle ))
256 {
257 InflateRect(rect, -GetSystemMetrics(SM_CXDLGFRAME),
258 -GetSystemMetrics(SM_CYDLGFRAME));
259 /* FIXME: this isn't in NC_AdjustRect? why not? */
260 if (ExStyle & WS_EX_DLGMODALFRAME)
261 InflateRect( rect, -1, 0 );
262 }
263 else
264 {
265 if (UserHasThinFrameStyle(Style, ExStyle))
266 {
267 InflateRect(rect, -GetSystemMetrics(SM_CXBORDER),
268 -GetSystemMetrics(SM_CYBORDER));
269 }
270 }
271 }
272 }
273
274
275 VOID
276 DefWndSetRedraw(HWND hWnd, WPARAM wParam)
277 {
278 UNIMPLEMENTED;
279 }
280
281
282 LRESULT
283 DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam)
284 {
285 /* Not for child windows. */
286 if (hWnd != (HWND)wParam)
287 {
288 return(0);
289 }
290
291 switch(LOWORD(lParam))
292 {
293 case HTERROR:
294 {
295 WORD Msg = HIWORD(lParam);
296 if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN ||
297 Msg == WM_RBUTTONDOWN || Msg == WM_XBUTTONDOWN)
298 {
299 MessageBeep(0);
300 }
301 break;
302 }
303
304 case HTCLIENT:
305 {
306 HICON hCursor = (HICON)GetClassLongW(hWnd, GCL_HCURSOR);
307 if (hCursor)
308 {
309 SetCursor(hCursor);
310 return(TRUE);
311 }
312 return(FALSE);
313 }
314
315 case HTLEFT:
316 case HTRIGHT:
317 {
318 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZEWE)));
319 }
320
321 case HTTOP:
322 case HTBOTTOM:
323 {
324 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENS)));
325 }
326
327 case HTTOPLEFT:
328 case HTBOTTOMRIGHT:
329 {
330 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENWSE)));
331 }
332
333 case HTBOTTOMLEFT:
334 case HTTOPRIGHT:
335 {
336 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENESW)));
337 }
338 }
339 return((LRESULT)SetCursor(LoadCursorW(0, IDC_ARROW)));
340 }
341
342 static LONG
343 DefWndStartSizeMove(HWND hWnd, WPARAM wParam, POINT *capturePoint)
344 {
345 LONG hittest = 0;
346 POINT pt;
347 MSG msg;
348 RECT rectWindow;
349 ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
350
351 GetWindowRect(hWnd, &rectWindow);
352
353 if ((wParam & 0xfff0) == SC_MOVE)
354 {
355 /* Move pointer at the center of the caption */
356 RECT rect;
357 UserGetInsideRectNC(hWnd, &rect);
358 if (Style & WS_SYSMENU)
359 rect.left += GetSystemMetrics(SM_CXSIZE) + 1;
360 if (Style & WS_MINIMIZEBOX)
361 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
362 if (Style & WS_MAXIMIZEBOX)
363 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
364 pt.x = rectWindow.left + (rect.right - rect.left) / 2;
365 pt.y = rectWindow.top + rect.top + GetSystemMetrics(SM_CYSIZE)/2;
366 hittest = HTCAPTION;
367 *capturePoint = pt;
368 }
369 else /* SC_SIZE */
370 {
371 while(!hittest)
372 {
373 GetMessageW(&msg, NULL, 0, 0);
374 switch(msg.message)
375 {
376 case WM_MOUSEMOVE:
377 hittest = DefWndNCHitTest(hWnd, msg.pt);
378 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
379 hittest = 0;
380 break;
381
382 case WM_LBUTTONUP:
383 return 0;
384
385 case WM_KEYDOWN:
386 switch(msg.wParam)
387 {
388 case VK_UP:
389 hittest = HTTOP;
390 pt.x =(rectWindow.left+rectWindow.right)/2;
391 pt.y = rectWindow.top + GetSystemMetrics(SM_CYFRAME) / 2;
392 break;
393 case VK_DOWN:
394 hittest = HTBOTTOM;
395 pt.x =(rectWindow.left+rectWindow.right)/2;
396 pt.y = rectWindow.bottom - GetSystemMetrics(SM_CYFRAME) / 2;
397 break;
398 case VK_LEFT:
399 hittest = HTLEFT;
400 pt.x = rectWindow.left + GetSystemMetrics(SM_CXFRAME) / 2;
401 pt.y =(rectWindow.top+rectWindow.bottom)/2;
402 break;
403 case VK_RIGHT:
404 hittest = HTRIGHT;
405 pt.x = rectWindow.right - GetSystemMetrics(SM_CXFRAME) / 2;
406 pt.y =(rectWindow.top+rectWindow.bottom)/2;
407 break;
408 case VK_RETURN:
409 case VK_ESCAPE: return 0;
410 }
411 }
412 }
413 *capturePoint = pt;
414 }
415 SetCursorPos( pt.x, pt.y );
416 DefWndHandleSetCursor(hWnd, (WPARAM)hWnd, MAKELONG(hittest, WM_MOUSEMOVE));
417 return hittest;
418 }
419
420 #define ON_LEFT_BORDER(hit) \
421 (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
422 #define ON_RIGHT_BORDER(hit) \
423 (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
424 #define ON_TOP_BORDER(hit) \
425 (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
426 #define ON_BOTTOM_BORDER(hit) \
427 (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
428
429 VOID STATIC
430 UserDrawWindowFrame(HDC hdc, const RECT *rect,
431 ULONG width, ULONG height, DWORD rop )
432 {
433 HBRUSH hbrush = SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
434 PatBlt( hdc, rect->left, rect->top,
435 rect->right - rect->left - width, height, rop );
436 PatBlt( hdc, rect->left, rect->top + height, width,
437 rect->bottom - rect->top - height, rop );
438 PatBlt( hdc, rect->left + width, rect->bottom - 1,
439 rect->right - rect->left - width, -height, rop );
440 PatBlt( hdc, rect->right - 1, rect->top, -width,
441 rect->bottom - rect->top - height, rop );
442 SelectObject( hdc, hbrush );
443 }
444
445 VOID STATIC
446 UserDrawMovingFrame(HDC hdc, RECT *rect, BOOL thickframe)
447 {
448 if (thickframe)
449 {
450 UserDrawWindowFrame(hdc, rect, GetSystemMetrics(SM_CXFRAME),
451 GetSystemMetrics(SM_CYFRAME), PATINVERT );
452 }
453 else DrawFocusRect( hdc, rect );
454 }
455
456 VOID STATIC
457 DefWndDoSizeMove(HWND hwnd, WORD wParam)
458 {
459 MSG msg;
460 RECT sizingRect, mouseRect, origRect, clipRect;
461 HDC hdc;
462 LONG hittest = (LONG)(wParam & 0x0f);
463 HCURSOR hDragCursor = 0, hOldCursor = 0;
464 POINT minTrack, maxTrack;
465 POINT capturePoint, pt;
466 ULONG Style = GetWindowLongW(hwnd, GWL_STYLE);
467 ULONG ExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
468 BOOL thickframe = UserHasThickFrameStyle(Style, ExStyle);
469 BOOL iconic = Style & WS_MINIMIZE;
470 BOOL moved = FALSE;
471 DWORD dwPoint = GetMessagePos();
472 BOOL DragFullWindows = FALSE;
473 HWND hWndParent;
474
475 SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
476
477 pt.x = SLOWORD(dwPoint);
478 pt.y = SHIWORD(dwPoint);
479 capturePoint = pt;
480
481 if (IsZoomed(hwnd) || !IsWindowVisible(hwnd))
482 {
483 return;
484 }
485
486 if ((wParam & 0xfff0) == SC_MOVE)
487 {
488 if (!hittest)
489 {
490 hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
491 }
492 if (!hittest)
493 {
494 return;
495 }
496 }
497 else /* SC_SIZE */
498 {
499 if (!thickframe)
500 {
501 return;
502 }
503 if (hittest && hittest != HTSYSMENU)
504 {
505 hittest += 2;
506 }
507 else
508 {
509 SetCapture(hwnd);
510 hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
511 if (!hittest)
512 {
513 ReleaseCapture();
514 return;
515 }
516 }
517 }
518
519 if (Style & WS_CHILD)
520 {
521 hWndParent = GetParent(hwnd);
522 }
523
524 /* Get min/max info */
525
526 WinPosGetMinMaxInfo(hwnd, NULL, NULL, &minTrack, &maxTrack);
527 GetWindowRect(hwnd, &sizingRect);
528 if (Style & WS_CHILD)
529 {
530 MapWindowPoints( 0, hWndParent, (LPPOINT)&sizingRect, 2 );
531 GetClientRect(hWndParent, &mouseRect );
532 clipRect = mouseRect;
533 MapWindowPoints(hWndParent, HWND_DESKTOP, (LPPOINT)&clipRect, 2);
534 }
535 else
536 {
537 SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN),
538 GetSystemMetrics(SM_CYSCREEN));
539 SystemParametersInfoW(SPI_GETWORKAREA, 0, &clipRect, 0);
540 }
541 ClipCursor(&clipRect);
542
543 origRect = sizingRect;
544 if (ON_LEFT_BORDER(hittest))
545 {
546 mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x );
547 mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
548 }
549 else if (ON_RIGHT_BORDER(hittest))
550 {
551 mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x );
552 mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
553 }
554 if (ON_TOP_BORDER(hittest))
555 {
556 mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
557 mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
558 }
559 else if (ON_BOTTOM_BORDER(hittest))
560 {
561 mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y );
562 mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
563 }
564 if (Style & WS_CHILD)
565 {
566 MapWindowPoints( hWndParent, 0, (LPPOINT)&mouseRect, 2 );
567 }
568 SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
569
570 if (GetCapture() != hwnd) SetCapture( hwnd );
571
572 if (Style & WS_CHILD)
573 {
574 /* Retrieve a default cache DC (without using the window style) */
575 hdc = GetDCEx(hWndParent, 0, DCX_CACHE);
576 }
577 else
578 {
579 hdc = GetDC( 0 );
580 }
581
582 if( iconic ) /* create a cursor for dragging */
583 {
584 HICON hIcon = (HICON)GetClassLongW(hwnd, GCL_HICON);
585 if(!hIcon) hIcon = (HICON)SendMessageW( hwnd, WM_QUERYDRAGICON, 0, 0L);
586 if( hIcon ) hDragCursor = CursorIconToCursor( hIcon, TRUE );
587 if( !hDragCursor ) iconic = FALSE;
588 }
589
590 /* invert frame if WIN31_LOOK to indicate mouse click on caption */
591 if( !iconic && !DragFullWindows)
592 {
593 UserDrawMovingFrame( hdc, &sizingRect, thickframe );
594 }
595
596 while(1)
597 {
598 int dx = 0, dy = 0;
599
600 GetMessageW(&msg, 0, 0, 0);
601
602 /* Exit on button-up, Return, or Esc */
603 if ((msg.message == WM_LBUTTONUP) ||
604 ((msg.message == WM_KEYDOWN) &&
605 ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
606
607 if (msg.message == WM_PAINT)
608 {
609 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
610 UpdateWindow( msg.hwnd );
611 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
612 continue;
613 }
614
615 if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
616 continue; /* We are not interested in other messages */
617
618 pt = msg.pt;
619
620 if (msg.message == WM_KEYDOWN) switch(msg.wParam)
621 {
622 case VK_UP: pt.y -= 8; break;
623 case VK_DOWN: pt.y += 8; break;
624 case VK_LEFT: pt.x -= 8; break;
625 case VK_RIGHT: pt.x += 8; break;
626 }
627
628 pt.x = max( pt.x, mouseRect.left );
629 pt.x = min( pt.x, mouseRect.right );
630 pt.y = max( pt.y, mouseRect.top );
631 pt.y = min( pt.y, mouseRect.bottom );
632
633 dx = pt.x - capturePoint.x;
634 dy = pt.y - capturePoint.y;
635
636 if (dx || dy)
637 {
638 if( !moved )
639 {
640 moved = TRUE;
641
642 if( iconic ) /* ok, no system popup tracking */
643 {
644 hOldCursor = SetCursor(hDragCursor);
645 ShowCursor( TRUE );
646 WinPosShowIconTitle( hwnd, FALSE );
647 }
648 }
649
650 if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
651 else
652 {
653 RECT newRect = sizingRect;
654 WPARAM wpSizingHit = 0;
655
656 if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
657 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
658 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
659 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
660 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
661 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
662 capturePoint = pt;
663
664 /* determine the hit location */
665 if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
666 wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
667 SendMessageA( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&newRect );
668
669 if (!iconic)
670 {
671 if(!DragFullWindows)
672 UserDrawMovingFrame( hdc, &newRect, thickframe );
673 else {
674 /* To avoid any deadlocks, all the locks on the windows
675 structures must be suspended before the SetWindowPos */
676 SetWindowPos( hwnd, 0, newRect.left, newRect.top,
677 newRect.right - newRect.left,
678 newRect.bottom - newRect.top,
679 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
680 }
681 }
682 sizingRect = newRect;
683 }
684 }
685 }
686
687 ReleaseCapture();
688 ClipCursor(NULL);
689 if( iconic )
690 {
691 if( moved ) /* restore cursors, show icon title later on */
692 {
693 ShowCursor( FALSE );
694 SetCursor( hOldCursor );
695 }
696 DestroyCursor( hDragCursor );
697 }
698 else if(!DragFullWindows)
699 UserDrawMovingFrame( hdc, &sizingRect, thickframe );
700
701 if (Style & WS_CHILD)
702 ReleaseDC( hWndParent, hdc );
703 else
704 ReleaseDC( 0, hdc );
705
706 SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 );
707 SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
708
709 /* window moved or resized */
710 if (moved)
711 {
712 /* if the moving/resizing isn't canceled call SetWindowPos
713 * with the new position or the new size of the window
714 */
715 if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
716 {
717 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
718 if(!DragFullWindows)
719 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
720 sizingRect.right - sizingRect.left,
721 sizingRect.bottom - sizingRect.top,
722 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
723 }
724 else { /* restore previous size/position */
725 if(DragFullWindows)
726 SetWindowPos( hwnd, 0, origRect.left, origRect.top,
727 origRect.right - origRect.left,
728 origRect.bottom - origRect.top,
729 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
730 }
731 }
732
733 if( IsWindow(hwnd) )
734 if( Style & WS_MINIMIZE )
735 {
736 /* Single click brings up the system menu when iconized */
737
738 if( !moved )
739 {
740 if( Style & WS_SYSMENU )
741 SendMessageA( hwnd, WM_SYSCOMMAND,
742 SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
743 }
744 else WinPosShowIconTitle( hwnd, TRUE );
745 }
746 }
747
748
749 LRESULT
750 DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt)
751 {
752 switch (wParam & 0xfff0)
753 {
754 case SC_MOVE:
755 case SC_SIZE:
756 DefWndDoSizeMove(hWnd, wParam);
757 break;
758 case SC_CLOSE:
759 SendMessageA(hWnd, WM_CLOSE, 0, 0);
760 break;
761 case SC_MOUSEMENU:
762 MenuTrackMouseMenuBar(hWnd, wParam, Pt);
763 break;
764 case SC_KEYMENU:
765 MenuTrackKbdMenuBar(hWnd, wParam, Pt.x);
766 break;
767 default:
768 /* FIXME: Implement */
769 UNIMPLEMENTED;
770 break;
771 }
772
773 return(0);
774 }
775
776 LRESULT
777 DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
778 {
779 POINT maxSize, minTrack;
780 LONG style = GetWindowLongA(hWnd, GWL_STYLE);
781
782 if (Pos->flags & SWP_NOSIZE) return 0;
783 if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
784 {
785 WinPosGetMinMaxInfo(hWnd, &maxSize, NULL, &minTrack, NULL);
786 Pos->cx = min(Pos->cx, maxSize.x);
787 Pos->cy = min(Pos->cy, maxSize.y);
788 if (!(style & WS_MINIMIZE))
789 {
790 if (Pos->cx < minTrack.x) Pos->cx = minTrack.x;
791 if (Pos->cy < minTrack.y) Pos->cy = minTrack.y;
792 }
793 }
794 return 0;
795 }
796
797 /* Undocumented flags. */
798 #define SWP_NOCLIENTMOVE 0x0800
799 #define SWP_NOCLIENTSIZE 0x1000
800
801 LRESULT
802 DefWndHandleWindowPosChanged(HWND hWnd, WINDOWPOS* Pos)
803 {
804 RECT Rect;
805
806 GetClientRect(hWnd, &Rect);
807 MapWindowPoints(hWnd, (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD ?
808 GetParent(hWnd) : NULL), (LPPOINT) &Rect, 2);
809
810 if (! (Pos->flags & SWP_NOCLIENTMOVE))
811 {
812 SendMessageW(hWnd, WM_MOVE, 0, MAKELONG(Rect.left, Rect.top));
813 }
814
815 if (! (Pos->flags & SWP_NOCLIENTSIZE))
816 {
817 WPARAM wp = SIZE_RESTORED;
818 if (IsZoomed(hWnd))
819 {
820 wp = SIZE_MAXIMIZED;
821 }
822 else if (IsIconic(hWnd))
823 {
824 wp = SIZE_MINIMIZED;
825 }
826 SendMessageW(hWnd, WM_SIZE, wp,
827 MAKELONG(Rect.right - Rect.left, Rect.bottom - Rect.top));
828 }
829
830 return 0;
831 }
832
833 /***********************************************************************
834 * DefWndControlColor
835 *
836 * Default colors for control painting.
837 */
838 static HBRUSH
839 DefWndControlColor(HDC hDC, UINT ctlType)
840 {
841 if (CTLCOLOR_SCROLLBAR == ctlType)
842 {
843 HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
844 COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
845 SetTextColor(hDC, GetSysColor(COLOR_3DFACE));
846 SetBkColor(hDC, bk);
847
848 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
849 * we better use 0x55aa bitmap brush to make scrollbar's background
850 * look different from the window background.
851 */
852 if (bk == GetSysColor(COLOR_WINDOW))
853 {
854 #if 0 /* FIXME */
855 return CACHE_GetPattern55AABrush();
856 #else
857 return NULL;
858 #endif
859 }
860 UnrealizeObject(hb);
861 return hb;
862 }
863
864 SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
865
866 if ((CTLCOLOR_EDIT == ctlType) || (CTLCOLOR_LISTBOX == ctlType))
867 {
868 SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
869 }
870 else
871 {
872 SetBkColor(hDC, GetSysColor(COLOR_3DFACE));
873 return GetSysColorBrush(COLOR_3DFACE);
874 }
875
876 return GetSysColorBrush(COLOR_WINDOW);
877 }
878
879
880 LRESULT STDCALL
881 User32DefWindowProc(HWND hWnd,
882 UINT Msg,
883 WPARAM wParam,
884 LPARAM lParam,
885 BOOL bUnicode)
886 {
887 switch (Msg)
888 {
889 case WM_NCPAINT:
890 {
891 return DefWndNCPaint(hWnd, (HRGN)wParam);
892 }
893
894 case WM_NCCALCSIZE:
895 {
896 return DefWndNCCalcSize(hWnd, (BOOL)wParam, (RECT*)lParam);
897 }
898
899 case WM_NCACTIVATE:
900 {
901 return DefWndNCActivate(hWnd, wParam);
902 }
903
904 case WM_NCHITTEST:
905 {
906 POINT Point;
907 Point.x = SLOWORD(lParam);
908 Point.y = SHIWORD(lParam);
909 return (DefWndNCHitTest(hWnd, Point));
910 }
911
912 case WM_NCLBUTTONDOWN:
913 {
914 return (DefWndNCLButtonDown(hWnd, wParam, lParam));
915 }
916
917 case WM_NCLBUTTONUP:
918 {
919 return (DefWndNCLButtonUp(hWnd, wParam, lParam));
920 }
921
922 case WM_LBUTTONDBLCLK:
923 case WM_NCLBUTTONDBLCLK:
924 {
925 return (DefWndNCLButtonDblClk(hWnd, wParam, lParam));
926 }
927
928 case WM_NCRBUTTONDOWN:
929 {
930 if (wParam == HTCAPTION)
931 {
932 SetCapture(hWnd);
933 }
934 break;
935 }
936
937 case WM_WINDOWPOSCHANGING:
938 {
939 return (DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
940 }
941
942 case WM_WINDOWPOSCHANGED:
943 {
944 return (DefWndHandleWindowPosChanged(hWnd, (WINDOWPOS*)lParam));
945 }
946
947 case WM_RBUTTONUP:
948 {
949 POINT Pt;
950 if (hWnd == GetCapture())
951 {
952 ReleaseCapture();
953 }
954 Pt.x = SLOWORD(lParam);
955 Pt.y = SHIWORD(lParam);
956 ClientToScreen(hWnd, &Pt);
957 lParam = MAKELPARAM(Pt.x, Pt.y);
958 if (bUnicode)
959 {
960 SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
961 }
962 else
963 {
964 SendMessageA(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
965 }
966 break;
967 }
968
969 case WM_CONTEXTMENU:
970 {
971 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
972 {
973 if (bUnicode)
974 {
975 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
976 }
977 else
978 {
979 SendMessageA(GetParent(hWnd), WM_CONTEXTMENU, wParam, lParam);
980 }
981 }
982 else
983 {
984 LONG HitCode;
985 POINT Pt;
986
987 Pt.x = SLOWORD(lParam);
988 Pt.y = SHIWORD(lParam);
989 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
990 {
991 ScreenToClient(GetParent(hWnd), &Pt);
992 }
993
994 HitCode = DefWndNCHitTest(hWnd, Pt);
995
996 if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
997 {
998 TrackPopupMenu(GetSystemMenu(hWnd, FALSE),
999 TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
1000 Pt.x, Pt.y, 0, hWnd, NULL);
1001 }
1002 }
1003 break;
1004 }
1005
1006 case WM_PRINT:
1007 {
1008 /* FIXME: Implement. */
1009 return (0);
1010 }
1011
1012 case WM_PAINTICON:
1013 case WM_PAINT:
1014 {
1015 PAINTSTRUCT Ps;
1016 HDC hDC = BeginPaint(hWnd, &Ps);
1017 if (hDC)
1018 {
1019 HICON hIcon;
1020 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
1021 (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
1022 {
1023 RECT ClientRect;
1024 INT x, y;
1025 GetClientRect(hWnd, &ClientRect);
1026 x = (ClientRect.right - ClientRect.left -
1027 GetSystemMetrics(SM_CXICON)) / 2;
1028 y = (ClientRect.bottom - ClientRect.top -
1029 GetSystemMetrics(SM_CYICON)) / 2;
1030 DrawIcon(hDC, x, y, hIcon);
1031 }
1032 EndPaint(hWnd, &Ps);
1033 }
1034 return (0);
1035 }
1036
1037 case WM_SYNCPAINT:
1038 {
1039 HRGN hRgn;
1040 hRgn = CreateRectRgn(0, 0, 0, 0);
1041 if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
1042 {
1043 RedrawWindow(hWnd, NULL, hRgn,
1044 RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
1045 RDW_ALLCHILDREN);
1046 }
1047 DeleteObject(hRgn);
1048 return (0);
1049 }
1050
1051 case WM_SETREDRAW:
1052 {
1053 DefWndSetRedraw(hWnd, wParam);
1054 return (0);
1055 }
1056
1057 case WM_CLOSE:
1058 {
1059 DestroyWindow(hWnd);
1060 return (0);
1061 }
1062
1063 case WM_MOUSEACTIVATE:
1064 {
1065 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1066 {
1067 LONG Ret;
1068 if (bUnicode)
1069 {
1070 Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
1071 wParam, lParam);
1072 }
1073 else
1074 {
1075 Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
1076 wParam, lParam);
1077 }
1078 if (Ret)
1079 {
1080 return (Ret);
1081 }
1082 }
1083 return ((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
1084 }
1085
1086 case WM_ACTIVATE:
1087 {
1088 /* Check if the window is minimized. */
1089 if (LOWORD(lParam) != WA_INACTIVE &&
1090 !(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
1091 {
1092 SetFocus(hWnd);
1093 }
1094 break;
1095 }
1096
1097 case WM_MOUSEWHEEL:
1098 {
1099 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1100 {
1101 if (bUnicode)
1102 {
1103 return (SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
1104 wParam, lParam));
1105 }
1106 else
1107 {
1108 return (SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
1109 wParam, lParam));
1110 }
1111 }
1112 break;
1113 }
1114
1115 case WM_ERASEBKGND:
1116 case WM_ICONERASEBKGND:
1117 {
1118 RECT Rect;
1119 HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
1120
1121 if (NULL == hBrush)
1122 {
1123 return 0;
1124 }
1125 if (GetClassLongW(hWnd, GCL_STYLE) & CS_PARENTDC)
1126 {
1127 /* can't use GetClipBox with a parent DC or we fill the whole parent */
1128 GetClientRect(hWnd, &Rect);
1129 DPtoLP((HDC)wParam, (LPPOINT)&Rect, 2);
1130 }
1131 else
1132 {
1133 GetClipBox((HDC)wParam, &Rect);
1134 }
1135 FillRect((HDC)wParam, &Rect, hBrush);
1136 return (1);
1137 }
1138
1139 case WM_CTLCOLORMSGBOX:
1140 case WM_CTLCOLOREDIT:
1141 case WM_CTLCOLORLISTBOX:
1142 case WM_CTLCOLORBTN:
1143 case WM_CTLCOLORDLG:
1144 case WM_CTLCOLORSTATIC:
1145 case WM_CTLCOLORSCROLLBAR:
1146 return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
1147
1148 case WM_SETCURSOR:
1149 {
1150 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1151 {
1152 if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
1153 {
1154 BOOL bResult;
1155 if (bUnicode)
1156 {
1157 bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
1158 wParam, lParam);
1159 }
1160 else
1161 {
1162 bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
1163 wParam, lParam);
1164 }
1165 if (bResult)
1166 {
1167 return(TRUE);
1168 }
1169 }
1170 }
1171 return (DefWndHandleSetCursor(hWnd, wParam, lParam));
1172 }
1173
1174 case WM_SYSCOMMAND:
1175 {
1176 POINT Pt;
1177 Pt.x = SLOWORD(lParam);
1178 Pt.y = SHIWORD(lParam);
1179 return (DefWndHandleSysCommand(hWnd, wParam, Pt));
1180 }
1181
1182 /* FIXME: Handle key messages. */
1183 /*
1184 case WM_KEYDOWN:
1185 case WM_KEYUP:
1186 case WM_SYSKEYUP:
1187 case WM_SYSCHAR:
1188 */
1189
1190 /* FIXME: This is also incomplete. */
1191 case WM_SYSKEYDOWN:
1192 {
1193 if (HIWORD(lParam) & KEYDATA_ALT)
1194 {
1195 if (wParam == VK_F4) /* Try to close the window */
1196 {
1197 HWND top = GetAncestor(hWnd, GA_ROOT);
1198 if (!(GetClassLongW(top, GCL_STYLE) & CS_NOCLOSE))
1199 {
1200 if (bUnicode)
1201 PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1202 else
1203 PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1204 }
1205 }
1206 }
1207 break;
1208 }
1209
1210 case WM_SHOWWINDOW:
1211 {
1212 LONG Style;
1213
1214 if (!lParam)
1215 return 0;
1216 Style = GetWindowLongW(hWnd, GWL_STYLE);
1217 if (!(Style & WS_POPUP))
1218 return 0;
1219 if ((Style & WS_VISIBLE) && wParam)
1220 return 0;
1221 if (!(Style & WS_VISIBLE) && !wParam)
1222 return 0;
1223 if (!GetWindow(hWnd, GW_OWNER))
1224 return 0;
1225 ShowWindow(hWnd, wParam ? SW_SHOWNA : SW_HIDE);
1226 break;
1227 }
1228
1229 case WM_CANCELMODE:
1230 {
1231 /* FIXME: Check for a desktop. */
1232 if (GetCapture() == hWnd)
1233 {
1234 ReleaseCapture();
1235 }
1236 break;
1237 }
1238
1239 case WM_VKEYTOITEM:
1240 case WM_CHARTOITEM:
1241 return (-1);
1242
1243 case WM_DROPOBJECT:
1244 /* FIXME: Implement this. */
1245 break;
1246
1247 case WM_QUERYDROPOBJECT:
1248 {
1249 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
1250 {
1251 return(1);
1252 }
1253 break;
1254 }
1255
1256 case WM_QUERYDRAGICON:
1257 {
1258 UINT Len;
1259 HICON hIcon;
1260
1261 hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
1262 if (hIcon)
1263 {
1264 return ((LRESULT)hIcon);
1265 }
1266 for (Len = 1; Len < 64; Len++)
1267 {
1268 if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
1269 {
1270 return((LRESULT)hIcon);
1271 }
1272 }
1273 return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
1274 }
1275
1276 /* FIXME: WM_ISACTIVEICON */
1277
1278 case WM_NOTIFYFORMAT:
1279 {
1280 if (IsWindowUnicode(hWnd))
1281 {
1282 return(NFR_UNICODE);
1283 }
1284 else
1285 {
1286 return(NFR_ANSI);
1287 }
1288 }
1289
1290 case WM_SETICON:
1291 {
1292 INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1293 HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
1294 SetClassLongW(hWnd, Index, lParam);
1295 SetWindowPos(hWnd, 0, 0, 0, 0, 0,
1296 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
1297 SWP_NOACTIVATE | SWP_NOZORDER);
1298 return ((LRESULT)hOldIcon);
1299 }
1300
1301 case WM_GETICON:
1302 {
1303 INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1304 return (GetClassLongW(hWnd, Index));
1305 }
1306
1307 case WM_HELP:
1308 {
1309 if (bUnicode)
1310 {
1311 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1312 }
1313 else
1314 {
1315 SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
1316 }
1317 break;
1318 }
1319
1320 case WM_SYSTIMER:
1321 {
1322 THRDCARETINFO CaretInfo;
1323 switch(wParam)
1324 {
1325 case 0xffff: /* Caret timer */
1326 /* switch showing byte in win32k and get information about the caret */
1327 if(NtUserCallOneParam((DWORD)&CaretInfo, ONEPARAM_ROUTINE_SWITCHCARETSHOWING) && (CaretInfo.hWnd == hWnd))
1328 {
1329 DrawCaret(hWnd, &CaretInfo);
1330 }
1331 break;
1332 }
1333 break;
1334 }
1335
1336 case WM_QUERYOPEN:
1337 case WM_QUERYENDSESSION:
1338 {
1339 return (1);
1340 }
1341 }
1342 return 0;
1343 }
1344
1345
1346 LRESULT STDCALL
1347 DefWindowProcA(HWND hWnd,
1348 UINT Msg,
1349 WPARAM wParam,
1350 LPARAM lParam)
1351 {
1352 static LPSTR WindowTextAtom = 0;
1353 PSTR WindowText;
1354
1355 switch (Msg)
1356 {
1357 case WM_NCCREATE:
1358 {
1359 CREATESTRUCTA *Cs = (CREATESTRUCTA*)lParam;
1360 if (HIWORD(Cs->lpszName))
1361 {
1362 if (0 == WindowTextAtom)
1363 {
1364 WindowTextAtom =
1365 (LPSTR)(ULONG)GlobalAddAtomA("USER32!WindowTextAtomA");
1366 }
1367 WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1368 (strlen(Cs->lpszName) + 1) * sizeof(CHAR));
1369 strcpy(WindowText, Cs->lpszName);
1370 SetPropA(hWnd, WindowTextAtom, WindowText);
1371 }
1372 return (1);
1373 }
1374
1375 case WM_GETTEXTLENGTH:
1376 {
1377 if (WindowTextAtom == 0 ||
1378 (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
1379 {
1380 return(0);
1381 }
1382 return (strlen(WindowText));
1383 }
1384
1385 case WM_GETTEXT:
1386 {
1387 if (WindowTextAtom == 0 ||
1388 (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
1389 {
1390 if (wParam > 1)
1391 {
1392 *((PSTR)lParam) = '\0';
1393 }
1394 return (0);
1395 }
1396 strncpy((LPSTR)lParam, WindowText, wParam);
1397 return (min(wParam, strlen(WindowText)));
1398 }
1399
1400 case WM_SETTEXT:
1401 {
1402 if (0 == WindowTextAtom)
1403 {
1404 WindowTextAtom =
1405 (LPSTR)(DWORD)GlobalAddAtomA("USER32!WindowTextAtomA");
1406 }
1407 if (WindowTextAtom != 0 &&
1408 (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
1409 {
1410 RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
1411 }
1412 WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1413 (strlen((PSTR)lParam) + 1) * sizeof(CHAR));
1414 strcpy(WindowText, (PSTR)lParam);
1415 SetPropA(hWnd, WindowTextAtom, WindowText);
1416 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1417 {
1418 DefWndNCPaint(hWnd, (HRGN)1);
1419 }
1420 return (1);
1421 }
1422
1423 /*
1424 FIXME: Implement these.
1425 case WM_IME_CHAR:
1426 case WM_IME_KEYDOWN:
1427 case WM_IME_KEYUP:
1428 case WM_IME_STARTCOMPOSITION:
1429 case WM_IME_COMPOSITION:
1430 case WM_IME_ENDCOMPOSITION:
1431 case WM_IME_SELECT:
1432 case WM_IME_SETCONTEXT:
1433 */
1434
1435 case WM_NCDESTROY:
1436 {
1437 if (WindowTextAtom != 0 &&
1438 (WindowText = RemovePropA(hWnd, WindowTextAtom)) == NULL)
1439 {
1440 RtlFreeHeap(GetProcessHeap(), 0, WindowText);
1441 }
1442 return(0);
1443 }
1444 }
1445
1446 return User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
1447 }
1448
1449
1450 LRESULT STDCALL
1451 DefWindowProcW(HWND hWnd,
1452 UINT Msg,
1453 WPARAM wParam,
1454 LPARAM lParam)
1455 {
1456 static LPWSTR WindowTextAtom = 0;
1457 PWSTR WindowText;
1458
1459 switch (Msg)
1460 {
1461 case WM_NCCREATE:
1462 {
1463 CREATESTRUCTW* CreateStruct = (CREATESTRUCTW*)lParam;
1464 if (HIWORD(CreateStruct->lpszName))
1465 {
1466 if (0 == WindowTextAtom)
1467 {
1468 WindowTextAtom =
1469 (LPWSTR)(DWORD)GlobalAddAtomW(L"USER32!WindowTextAtomW");
1470 }
1471 WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1472 (wcslen(CreateStruct->lpszName) + 1) * sizeof(WCHAR));
1473 wcscpy(WindowText, CreateStruct->lpszName);
1474 SetPropW(hWnd, WindowTextAtom, WindowText);
1475 }
1476 return (1);
1477 }
1478
1479 case WM_GETTEXTLENGTH:
1480 {
1481 if (WindowTextAtom == 0 ||
1482 (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
1483 {
1484 return(0);
1485 }
1486 return (wcslen(WindowText));
1487 }
1488
1489 case WM_GETTEXT:
1490 {
1491 if (WindowTextAtom == 0 ||
1492 (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
1493 {
1494 if (wParam > 1)
1495 {
1496 ((PWSTR)lParam) = '\0';
1497 }
1498 return (0);
1499 }
1500 wcsncpy((PWSTR)lParam, WindowText, wParam);
1501 return (min(wParam, wcslen(WindowText)));
1502 }
1503
1504 case WM_SETTEXT:
1505 {
1506 if (WindowTextAtom == 0)
1507 {
1508 WindowTextAtom =
1509 (LPWSTR)(DWORD)GlobalAddAtomW(L"USER32!WindowTextAtomW");
1510 }
1511 if (WindowTextAtom != 0 &&
1512 (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
1513 {
1514 RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
1515 }
1516 WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1517 (wcslen((PWSTR)lParam) + 1) * sizeof(WCHAR));
1518 wcscpy(WindowText, (PWSTR)lParam);
1519 SetPropW(hWnd, WindowTextAtom, WindowText);
1520 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1521 {
1522 DefWndNCPaint(hWnd, (HRGN)1);
1523 }
1524 return (1);
1525 }
1526
1527 case WM_IME_CHAR:
1528 {
1529 SendMessageW(hWnd, WM_CHAR, wParam, lParam);
1530 return (0);
1531 }
1532
1533 case WM_IME_SETCONTEXT:
1534 {
1535 /* FIXME */
1536 return (0);
1537 }
1538
1539 case WM_NCDESTROY:
1540 {
1541 if (WindowTextAtom != 0 &&
1542 (WindowText = RemovePropW(hWnd, WindowTextAtom)) == NULL)
1543 {
1544 RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
1545 }
1546 return (0);
1547 }
1548 }
1549
1550 return User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
1551 }
1552