Windows with WS_EX_TOOLWINDOW style should not have min/max buttons.
[wine] / windows / winpos.c
1 /*
2  * Window position related functions.
3  *
4  * Copyright 1993, 1994, 1995 Alexandre Julliard
5  *                       1995, 1996, 1999 Alex Korobka
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdarg.h>
26 #include <string.h>
27 #include "winerror.h"
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "winerror.h"
32 #include "ntstatus.h"
33 #include "wine/winuser16.h"
34 #include "wine/server.h"
35 #include "controls.h"
36 #include "user.h"
37 #include "win.h"
38 #include "message.h"
39 #include "winpos.h"
40 #include "nonclient.h"
41 #include "wine/debug.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(win);
44
45 #define HAS_DLGFRAME(style,exStyle) \
46     (((exStyle) & WS_EX_DLGMODALFRAME) || \
47      (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
48
49 #define HAS_THICKFRAME(style) \
50     (((style) & WS_THICKFRAME) && \
51      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
52
53 #define EMPTYPOINT(pt)          ((*(LONG*)&(pt)) == -1)
54
55 #define PLACE_MIN               0x0001
56 #define PLACE_MAX               0x0002
57 #define PLACE_RECT              0x0004
58
59
60 #define DWP_MAGIC  ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
61
62 typedef struct
63 {
64     INT       actualCount;
65     INT       suggestedCount;
66     BOOL      valid;
67     INT       wMagic;
68     HWND      hwndParent;
69     WINDOWPOS winPos[1];
70 } DWP;
71
72 /* ----- internal variables ----- */
73
74 static LPCSTR atomInternalPos;
75
76
77 /***********************************************************************
78  *           WINPOS_CreateInternalPosAtom
79  */
80 BOOL WINPOS_CreateInternalPosAtom()
81 {
82     LPCSTR str = "SysIP";
83     atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
84     return (atomInternalPos) ? TRUE : FALSE;
85 }
86
87 /***********************************************************************
88  *           WINPOS_CheckInternalPos
89  *
90  * Called when a window is destroyed.
91  */
92 void WINPOS_CheckInternalPos( HWND hwnd )
93 {
94     LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
95
96     if( lpPos )
97     {
98         if( IsWindow(lpPos->hwndIconTitle) )
99             DestroyWindow( lpPos->hwndIconTitle );
100         HeapFree( GetProcessHeap(), 0, lpPos );
101     }
102 }
103
104 /***********************************************************************
105  *              ArrangeIconicWindows (USER32.@)
106  */
107 UINT WINAPI ArrangeIconicWindows( HWND parent )
108 {
109     RECT rectParent;
110     HWND hwndChild;
111     INT x, y, xspacing, yspacing;
112
113     GetClientRect( parent, &rectParent );
114     x = rectParent.left;
115     y = rectParent.bottom;
116     xspacing = GetSystemMetrics(SM_CXICONSPACING);
117     yspacing = GetSystemMetrics(SM_CYICONSPACING);
118
119     hwndChild = GetWindow( parent, GW_CHILD );
120     while (hwndChild)
121     {
122         if( IsIconic( hwndChild ) )
123         {
124             WINPOS_ShowIconTitle( hwndChild, FALSE );
125
126             SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
127                             y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
128                             SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
129             if( IsWindow(hwndChild) )
130                 WINPOS_ShowIconTitle(hwndChild , TRUE );
131
132             if (x <= rectParent.right - xspacing) x += xspacing;
133             else
134             {
135                 x = rectParent.left;
136                 y -= yspacing;
137             }
138         }
139         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
140     }
141     return yspacing;
142 }
143
144
145 /***********************************************************************
146  *              SwitchToThisWindow (USER32.@)
147  */
148 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
149 {
150     ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
151 }
152
153
154 /***********************************************************************
155  *              GetWindowRect (USER32.@)
156  */
157 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
158 {
159     BOOL ret = WIN_GetRectangles( hwnd, rect, NULL );
160     if (ret)
161     {
162         MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 );
163         TRACE( "hwnd %p (%ld,%ld)-(%ld,%ld)\n",
164                hwnd, rect->left, rect->top, rect->right, rect->bottom);
165     }
166     return ret;
167 }
168
169
170 /***********************************************************************
171  *              GetWindowRgn (USER32.@)
172  */
173 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
174 {
175     int nRet = ERROR;
176     NTSTATUS status;
177     HRGN win_rgn = 0;
178     RGNDATA *data;
179     size_t size = 256;
180
181     do
182     {
183         if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) + size - 1 )))
184         {
185             SetLastError( ERROR_OUTOFMEMORY );
186             return ERROR;
187         }
188         SERVER_START_REQ( get_window_region )
189         {
190             req->window = hwnd;
191             wine_server_set_reply( req, data->Buffer, size );
192             if (!(status = wine_server_call( req )))
193             {
194                 size_t reply_size = wine_server_reply_size( reply );
195                 if (reply_size)
196                 {
197                     data->rdh.dwSize   = sizeof(data->rdh);
198                     data->rdh.iType    = RDH_RECTANGLES;
199                     data->rdh.nCount   = reply_size / sizeof(RECT);
200                     data->rdh.nRgnSize = reply_size;
201                     win_rgn = ExtCreateRegion( NULL, size, data );
202                 }
203             }
204             else size = reply->total_size;
205         }
206         SERVER_END_REQ;
207         HeapFree( GetProcessHeap(), 0, data );
208     } while (status == STATUS_BUFFER_OVERFLOW);
209
210     if (status) SetLastError( RtlNtStatusToDosError(status) );
211     else if (win_rgn)
212     {
213         nRet = CombineRgn( hrgn, win_rgn, 0, RGN_COPY );
214         DeleteObject( win_rgn );
215     }
216     return nRet;
217 }
218
219
220 /***********************************************************************
221  *              SetWindowRgn (USER32.@)
222  */
223 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
224 {
225     static const RECT empty_rect;
226     BOOL ret;
227
228     if (hrgn)
229     {
230         RGNDATA *data;
231         DWORD size;
232
233         if (!(size = GetRegionData( hrgn, 0, NULL ))) return FALSE;
234         if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE;
235         if (!GetRegionData( hrgn, size, data ))
236         {
237             HeapFree( GetProcessHeap(), 0, data );
238             return FALSE;
239         }
240         SERVER_START_REQ( set_window_region )
241         {
242             req->window = hwnd;
243             if (data->rdh.nCount)
244                 wine_server_add_data( req, data->Buffer, data->rdh.nCount * sizeof(RECT) );
245             else
246                 wine_server_add_data( req, &empty_rect, sizeof(empty_rect) );
247             ret = !wine_server_call_err( req );
248         }
249         SERVER_END_REQ;
250     }
251     else  /* clear existing region */
252     {
253         SERVER_START_REQ( set_window_region )
254         {
255             req->window = hwnd;
256             ret = !wine_server_call_err( req );
257         }
258         SERVER_END_REQ;
259     }
260
261     if (ret && USER_Driver.pSetWindowRgn)
262         ret = USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw );
263
264     if (ret && bRedraw) RedrawWindow( hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE );
265     return ret;
266 }
267
268
269 /***********************************************************************
270  *              GetClientRect (USER32.@)
271  */
272 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
273 {
274     BOOL ret;
275
276     rect->right = rect->bottom = 0;
277     if ((ret = WIN_GetRectangles( hwnd, NULL, rect )))
278     {
279         rect->right -= rect->left;
280         rect->bottom -= rect->top;
281     }
282     rect->left = rect->top = 0;
283     return ret;
284 }
285
286
287 /*******************************************************************
288  *              ClientToScreen (USER32.@)
289  */
290 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
291 {
292     MapWindowPoints( hwnd, 0, lppnt, 1 );
293     return TRUE;
294 }
295
296
297 /*******************************************************************
298  *              ScreenToClient (USER32.@)
299  */
300 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
301 {
302     MapWindowPoints( 0, hwnd, lppnt, 1 );
303     return TRUE;
304 }
305
306
307 /***********************************************************************
308  *           list_children_from_point
309  *
310  * Get the list of children that can contain point from the server.
311  * Point is in screen coordinates.
312  * Returned list must be freed by caller.
313  */
314 static HWND *list_children_from_point( HWND hwnd, POINT pt )
315 {
316     HWND *list;
317     int size = 32;
318
319     for (;;)
320     {
321         int count = 0;
322
323         if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
324
325         SERVER_START_REQ( get_window_children_from_point )
326         {
327             req->parent = hwnd;
328             req->x = pt.x;
329             req->y = pt.y;
330             wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
331             if (!wine_server_call( req )) count = reply->count;
332         }
333         SERVER_END_REQ;
334         if (count && count < size)
335         {
336             list[count] = 0;
337             return list;
338         }
339         HeapFree( GetProcessHeap(), 0, list );
340         if (!count) break;
341         size = count + 1;  /* restart with a large enough buffer */
342     }
343     return NULL;
344 }
345
346
347 /***********************************************************************
348  *           WINPOS_WindowFromPoint
349  *
350  * Find the window and hittest for a given point.
351  */
352 HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
353 {
354     int i, res;
355     HWND ret, *list;
356
357     if (!hwndScope) hwndScope = GetDesktopWindow();
358
359     *hittest = HTNOWHERE;
360
361     if (!(list = list_children_from_point( hwndScope, pt ))) return 0;
362
363     /* now determine the hittest */
364
365     for (i = 0; list[i]; i++)
366     {
367         LONG style = GetWindowLongW( list[i], GWL_STYLE );
368
369         /* If window is minimized or disabled, return at once */
370         if (style & WS_MINIMIZE)
371         {
372             *hittest = HTCAPTION;
373             break;
374         }
375         if (style & WS_DISABLED)
376         {
377             *hittest = HTERROR;
378             break;
379         }
380         /* Send WM_NCCHITTEST (if same thread) */
381         if (!WIN_IsCurrentThread( list[i] ))
382         {
383             *hittest = HTCLIENT;
384             break;
385         }
386         res = SendMessageA( list[i], WM_NCHITTEST, 0, MAKELONG(pt.x,pt.y) );
387         if (res != HTTRANSPARENT)
388         {
389             *hittest = res;  /* Found the window */
390             break;
391         }
392         /* continue search with next window in z-order */
393     }
394     ret = list[i];
395     HeapFree( GetProcessHeap(), 0, list );
396     TRACE( "scope %p (%ld,%ld) returning %p\n", hwndScope, pt.x, pt.y, ret );
397     return ret;
398 }
399
400
401 /*******************************************************************
402  *              WindowFromPoint (USER32.@)
403  */
404 HWND WINAPI WindowFromPoint( POINT pt )
405 {
406     INT hittest;
407     return WINPOS_WindowFromPoint( 0, pt, &hittest );
408 }
409
410
411 /*******************************************************************
412  *              ChildWindowFromPoint (USER32.@)
413  */
414 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
415 {
416     return ChildWindowFromPointEx( hwndParent, pt, CWP_ALL );
417 }
418
419 /*******************************************************************
420  *              ChildWindowFromPointEx (USER32.@)
421  */
422 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt, UINT uFlags)
423 {
424     /* pt is in the client coordinates */
425     HWND *list;
426     int i;
427     RECT rect;
428     HWND retvalue;
429
430     GetClientRect( hwndParent, &rect );
431     if (!PtInRect( &rect, pt )) return 0;
432     if (!(list = WIN_ListChildren( hwndParent ))) return 0;
433
434     for (i = 0; list[i]; i++)
435     {
436         if (!WIN_GetRectangles( list[i], &rect, NULL )) continue;
437         if (!PtInRect( &rect, pt )) continue;
438         if (uFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED))
439         {
440             LONG style = GetWindowLongW( list[i], GWL_STYLE );
441             if ((uFlags & CWP_SKIPINVISIBLE) && !(style & WS_VISIBLE)) continue;
442             if ((uFlags & CWP_SKIPDISABLED) && (style & WS_DISABLED)) continue;
443         }
444         if (uFlags & CWP_SKIPTRANSPARENT)
445         {
446             if (GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_TRANSPARENT) continue;
447         }
448         break;
449     }
450     retvalue = list[i];
451     HeapFree( GetProcessHeap(), 0, list );
452     if (!retvalue) retvalue = hwndParent;
453     return retvalue;
454 }
455
456
457 /*******************************************************************
458  *         WINPOS_GetWinOffset
459  *
460  * Calculate the offset between the origin of the two windows. Used
461  * to implement MapWindowPoints.
462  */
463 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, POINT *offset )
464 {
465     WND * wndPtr;
466
467     offset->x = offset->y = 0;
468
469     /* Translate source window origin to screen coords */
470     if (hwndFrom)
471     {
472         HWND hwnd = hwndFrom;
473
474         while (hwnd)
475         {
476             if (hwnd == hwndTo) return;
477             if (!(wndPtr = WIN_GetPtr( hwnd )))
478             {
479                 ERR( "bad hwndFrom = %p\n", hwnd );
480                 return;
481             }
482             if (wndPtr == WND_OTHER_PROCESS) goto other_process;
483             offset->x += wndPtr->rectClient.left;
484             offset->y += wndPtr->rectClient.top;
485             hwnd = wndPtr->parent;
486             WIN_ReleasePtr( wndPtr );
487         }
488     }
489
490     /* Translate origin to destination window coords */
491     if (hwndTo)
492     {
493         HWND hwnd = hwndTo;
494
495         while (hwnd)
496         {
497             if (!(wndPtr = WIN_GetPtr( hwnd )))
498             {
499                 ERR( "bad hwndTo = %p\n", hwnd );
500                 return;
501             }
502             if (wndPtr == WND_OTHER_PROCESS) goto other_process;
503             offset->x -= wndPtr->rectClient.left;
504             offset->y -= wndPtr->rectClient.top;
505             hwnd = wndPtr->parent;
506             WIN_ReleasePtr( wndPtr );
507         }
508     }
509     return;
510
511  other_process:  /* one of the parents may belong to another process, do it the hard way */
512     offset->x = offset->y = 0;
513     SERVER_START_REQ( get_windows_offset )
514     {
515         req->from = hwndFrom;
516         req->to   = hwndTo;
517         if (!wine_server_call( req ))
518         {
519             offset->x = reply->x;
520             offset->y = reply->y;
521         }
522     }
523     SERVER_END_REQ;
524 }
525
526
527 /*******************************************************************
528  *              MapWindowPoints (USER.258)
529  */
530 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
531                                LPPOINT16 lppt, UINT16 count )
532 {
533     POINT offset;
534
535     WINPOS_GetWinOffset( WIN_Handle32(hwndFrom), WIN_Handle32(hwndTo), &offset );
536     while (count--)
537     {
538         lppt->x += offset.x;
539         lppt->y += offset.y;
540         lppt++;
541     }
542 }
543
544
545 /*******************************************************************
546  *              MapWindowPoints (USER32.@)
547  */
548 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, UINT count )
549 {
550     POINT offset;
551
552     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
553     while (count--)
554     {
555         lppt->x += offset.x;
556         lppt->y += offset.y;
557         lppt++;
558     }
559     return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
560 }
561
562
563 /***********************************************************************
564  *              IsIconic (USER32.@)
565  */
566 BOOL WINAPI IsIconic(HWND hWnd)
567 {
568     return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MINIMIZE) != 0;
569 }
570
571
572 /***********************************************************************
573  *              IsZoomed (USER32.@)
574  */
575 BOOL WINAPI IsZoomed(HWND hWnd)
576 {
577     return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MAXIMIZE) != 0;
578 }
579
580
581 /*******************************************************************
582  *              AllowSetForegroundWindow (USER32.@)
583  */
584 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
585 {
586     /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
587      * implemented, then fix this function. */
588     return TRUE;
589 }
590
591
592 /*******************************************************************
593  *              LockSetForegroundWindow (USER32.@)
594  */
595 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
596 {
597     /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
598      * implemented, then fix this function. */
599     return TRUE;
600 }
601
602
603 /***********************************************************************
604  *              BringWindowToTop (USER32.@)
605  */
606 BOOL WINAPI BringWindowToTop( HWND hwnd )
607 {
608     return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
609 }
610
611
612 /***********************************************************************
613  *              MoveWindow (USER32.@)
614  */
615 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
616                             BOOL repaint )
617 {
618     int flags = SWP_NOZORDER | SWP_NOACTIVATE;
619     if (!repaint) flags |= SWP_NOREDRAW;
620     TRACE("%p %d,%d %dx%d %d\n", hwnd, x, y, cx, cy, repaint );
621     return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
622 }
623
624 /***********************************************************************
625  *           WINPOS_InitInternalPos
626  */
627 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt, const RECT *restoreRect )
628 {
629     LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
630                                                       atomInternalPos );
631     if( !lpPos )
632     {
633         /* this happens when the window is minimized/maximized
634          * for the first time (rectWindow is not adjusted yet) */
635
636         lpPos = HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS) );
637         if( !lpPos ) return NULL;
638
639         SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
640         lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
641         lpPos->rectNormal.left   = wnd->rectWindow.left;
642         lpPos->rectNormal.top    = wnd->rectWindow.top;
643         lpPos->rectNormal.right  = wnd->rectWindow.right;
644         lpPos->rectNormal.bottom = wnd->rectWindow.bottom;
645         lpPos->ptIconPos.x = lpPos->ptIconPos.y = -1;
646         lpPos->ptMaxPos.x = lpPos->ptMaxPos.y = -1;
647     }
648
649     if( wnd->dwStyle & WS_MINIMIZE )
650     {
651         lpPos->ptIconPos.x = pt.x;
652         lpPos->ptIconPos.y = pt.y;
653     }
654     else if( wnd->dwStyle & WS_MAXIMIZE )
655     {
656         lpPos->ptMaxPos.x = pt.x;
657         lpPos->ptMaxPos.y = pt.y;
658     }
659     else if( restoreRect )
660     {
661         lpPos->rectNormal.left   = restoreRect->left;
662         lpPos->rectNormal.top    = restoreRect->top;
663         lpPos->rectNormal.right  = restoreRect->right;
664         lpPos->rectNormal.bottom = restoreRect->bottom;
665     }
666     return lpPos;
667 }
668
669 /***********************************************************************
670  *           WINPOS_RedrawIconTitle
671  */
672 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
673 {
674     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
675     if( lpPos )
676     {
677         if( lpPos->hwndIconTitle )
678         {
679             SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
680             InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
681             return TRUE;
682         }
683     }
684     return FALSE;
685 }
686
687 /***********************************************************************
688  *           WINPOS_ShowIconTitle
689  */
690 BOOL WINPOS_ShowIconTitle( HWND hwnd, BOOL bShow )
691 {
692     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
693
694     if( lpPos && !(GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_MANAGED))
695     {
696         HWND title = lpPos->hwndIconTitle;
697
698         TRACE("%p %i\n", hwnd, (bShow != 0) );
699
700         if( !title )
701             lpPos->hwndIconTitle = title = ICONTITLE_Create( hwnd );
702         if( bShow )
703         {
704             if (!IsWindowVisible(title))
705             {
706                 SendMessageA( title, WM_SHOWWINDOW, TRUE, 0 );
707                 SetWindowPos( title, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
708                               SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
709             }
710         }
711         else ShowWindow( title, SW_HIDE );
712     }
713     return FALSE;
714 }
715
716 /*******************************************************************
717  *           WINPOS_GetMinMaxInfo
718  *
719  * Get the minimized and maximized information for a window.
720  */
721 void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
722                            POINT *minTrack, POINT *maxTrack )
723 {
724     LPINTERNALPOS lpPos;
725     MINMAXINFO MinMax;
726     INT xinc, yinc;
727     LONG style = GetWindowLongA( hwnd, GWL_STYLE );
728     LONG exstyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
729     RECT rc;
730
731     /* Compute default values */
732
733     GetWindowRect(hwnd, &rc);
734     MinMax.ptReserved.x = rc.left;
735     MinMax.ptReserved.y = rc.top;
736
737     if (style & WS_CHILD)
738     {
739         if ((style & WS_CAPTION) == WS_CAPTION)
740             style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
741
742         GetClientRect(GetParent(hwnd), &rc);
743         AdjustWindowRectEx(&rc, style, 0, exstyle);
744
745         /* avoid calculating this twice */
746         style &= ~(WS_DLGFRAME | WS_BORDER | WS_THICKFRAME);
747
748         MinMax.ptMaxSize.x = rc.right - rc.left;
749         MinMax.ptMaxSize.y = rc.bottom - rc.top;
750     }
751     else
752     {
753         MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
754         MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
755     }
756     MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
757     MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
758     MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
759     MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
760
761     if (HAS_DLGFRAME( style, exstyle ))
762     {
763         xinc = GetSystemMetrics(SM_CXDLGFRAME);
764         yinc = GetSystemMetrics(SM_CYDLGFRAME);
765     }
766     else
767     {
768         xinc = yinc = 0;
769         if (HAS_THICKFRAME(style))
770         {
771             xinc += GetSystemMetrics(SM_CXFRAME);
772             yinc += GetSystemMetrics(SM_CYFRAME);
773         }
774         if (style & WS_BORDER)
775         {
776             xinc += GetSystemMetrics(SM_CXBORDER);
777             yinc += GetSystemMetrics(SM_CYBORDER);
778         }
779     }
780     MinMax.ptMaxSize.x += 2 * xinc;
781     MinMax.ptMaxSize.y += 2 * yinc;
782
783     lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
784     if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
785     {
786         MinMax.ptMaxPosition.x = lpPos->ptMaxPos.x;
787         MinMax.ptMaxPosition.y = lpPos->ptMaxPos.y;
788     }
789     else
790     {
791         MinMax.ptMaxPosition.x = -xinc;
792         MinMax.ptMaxPosition.y = -yinc;
793     }
794
795     SendMessageA( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
796
797       /* Some sanity checks */
798
799     TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
800                       MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
801                       MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
802                       MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
803                       MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
804     MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
805                                    MinMax.ptMinTrackSize.x );
806     MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
807                                    MinMax.ptMinTrackSize.y );
808
809     if (maxSize) *maxSize = MinMax.ptMaxSize;
810     if (maxPos) *maxPos = MinMax.ptMaxPosition;
811     if (minTrack) *minTrack = MinMax.ptMinTrackSize;
812     if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
813 }
814
815 /***********************************************************************
816  *              ShowWindowAsync (USER32.@)
817  *
818  * doesn't wait; returns immediately.
819  * used by threads to toggle windows in other (possibly hanging) threads
820  */
821 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
822 {
823     HWND full_handle;
824
825     if (is_broadcast(hwnd))
826     {
827         SetLastError( ERROR_INVALID_PARAMETER );
828         return FALSE;
829     }
830
831     if ((full_handle = WIN_IsCurrentThread( hwnd )))
832     {
833         if (USER_Driver.pShowWindow)
834             return USER_Driver.pShowWindow( full_handle, cmd );
835         return FALSE;
836     }
837     return SendNotifyMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
838 }
839
840
841 /***********************************************************************
842  *              ShowWindow (USER32.@)
843  */
844 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
845 {
846     HWND full_handle;
847
848     if (is_broadcast(hwnd))
849     {
850         SetLastError( ERROR_INVALID_PARAMETER );
851         return FALSE;
852     }
853     if ((full_handle = WIN_IsCurrentThread( hwnd )))
854     {
855         if (USER_Driver.pShowWindow)
856             return USER_Driver.pShowWindow( full_handle, cmd );
857         return FALSE;
858     }
859     return SendMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
860 }
861
862
863 /***********************************************************************
864  *              GetInternalWindowPos (USER32.@)
865  */
866 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
867                                       LPPOINT ptIcon )
868 {
869     WINDOWPLACEMENT wndpl;
870     if (GetWindowPlacement( hwnd, &wndpl ))
871     {
872         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
873         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
874         return wndpl.showCmd;
875     }
876     return 0;
877 }
878
879
880 /***********************************************************************
881  *              GetWindowPlacement (USER32.@)
882  *
883  * Win95:
884  * Fails if wndpl->length of Win95 (!) apps is invalid.
885  */
886 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
887 {
888     WND *pWnd = WIN_FindWndPtr( hwnd );
889     LPINTERNALPOS lpPos;
890
891     if(!pWnd ) return FALSE;
892
893     lpPos = WINPOS_InitInternalPos( pWnd, *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
894     wndpl->length  = sizeof(*wndpl);
895     if( pWnd->dwStyle & WS_MINIMIZE )
896         wndpl->showCmd = SW_SHOWMINIMIZED;
897     else
898         wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE ) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
899     if( pWnd->flags & WIN_RESTORE_MAX )
900         wndpl->flags = WPF_RESTORETOMAXIMIZED;
901     else
902         wndpl->flags = 0;
903     wndpl->ptMinPosition.x = lpPos->ptIconPos.x;
904     wndpl->ptMinPosition.y = lpPos->ptIconPos.y;
905     wndpl->ptMaxPosition.x = lpPos->ptMaxPos.x;
906     wndpl->ptMaxPosition.y = lpPos->ptMaxPos.y;
907     wndpl->rcNormalPosition.left   = lpPos->rectNormal.left;
908     wndpl->rcNormalPosition.top    = lpPos->rectNormal.top;
909     wndpl->rcNormalPosition.right  = lpPos->rectNormal.right;
910     wndpl->rcNormalPosition.bottom = lpPos->rectNormal.bottom;
911     WIN_ReleaseWndPtr(pWnd);
912     return TRUE;
913 }
914
915
916 /***********************************************************************
917  *           WINPOS_SetPlacement
918  */
919 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT *wndpl, UINT flags )
920 {
921     WND *pWnd = WIN_FindWndPtr( hwnd );
922     if( pWnd )
923     {
924         LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
925                              *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
926
927         if( flags & PLACE_MIN )
928         {
929             lpPos->ptIconPos.x = wndpl->ptMinPosition.x;
930             lpPos->ptIconPos.y = wndpl->ptMinPosition.y;
931         }
932         if( flags & PLACE_MAX )
933         {
934             lpPos->ptMaxPos.x = wndpl->ptMaxPosition.x;
935             lpPos->ptMaxPos.y = wndpl->ptMaxPosition.y;
936         }
937         if( flags & PLACE_RECT)
938         {
939             lpPos->rectNormal.left   = wndpl->rcNormalPosition.left;
940             lpPos->rectNormal.top    = wndpl->rcNormalPosition.top;
941             lpPos->rectNormal.right  = wndpl->rcNormalPosition.right;
942             lpPos->rectNormal.bottom = wndpl->rcNormalPosition.bottom;
943         }
944         if( pWnd->dwStyle & WS_MINIMIZE )
945         {
946             WINPOS_ShowIconTitle( pWnd->hwndSelf, FALSE );
947             if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
948                 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
949                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
950         }
951         else if( pWnd->dwStyle & WS_MAXIMIZE )
952         {
953             if( !EMPTYPOINT(lpPos->ptMaxPos) )
954                 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
955                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
956         }
957         else if( flags & PLACE_RECT )
958                 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
959                                 lpPos->rectNormal.right - lpPos->rectNormal.left,
960                                 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
961                                 SWP_NOZORDER | SWP_NOACTIVATE );
962
963         ShowWindow( hwnd, wndpl->showCmd );
964         if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
965         {
966             if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd->hwndSelf, TRUE );
967
968             /* SDK: ...valid only the next time... */
969             if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
970         }
971         WIN_ReleaseWndPtr(pWnd);
972         return TRUE;
973     }
974     return FALSE;
975 }
976
977
978 /***********************************************************************
979  *              SetWindowPlacement (USER32.@)
980  *
981  * Win95:
982  * Fails if wndpl->length of Win95 (!) apps is invalid.
983  */
984 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *wpl )
985 {
986     if (!wpl) return FALSE;
987     return WINPOS_SetPlacement( hwnd, wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
988 }
989
990
991 /***********************************************************************
992  *              AnimateWindow (USER32.@)
993  *              Shows/Hides a window with an animation
994  *              NO ANIMATION YET
995  */
996 BOOL WINAPI AnimateWindow(HWND hwnd, DWORD dwTime, DWORD dwFlags)
997 {
998         FIXME("partial stub\n");
999
1000         /* If trying to show/hide and it's already   *
1001          * shown/hidden or invalid window, fail with *
1002          * invalid parameter                         */
1003         if(!IsWindow(hwnd) ||
1004            (IsWindowVisible(hwnd) && !(dwFlags & AW_HIDE)) ||
1005            (!IsWindowVisible(hwnd) && (dwFlags & AW_HIDE)))
1006         {
1007                 SetLastError(ERROR_INVALID_PARAMETER);
1008                 return FALSE;
1009         }
1010
1011         ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA));
1012
1013         return TRUE;
1014 }
1015
1016 /***********************************************************************
1017  *              SetInternalWindowPos (USER32.@)
1018  */
1019 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1020                                     LPRECT rect, LPPOINT pt )
1021 {
1022     if( IsWindow(hwnd) )
1023     {
1024         WINDOWPLACEMENT wndpl;
1025         UINT flags;
1026
1027         wndpl.length  = sizeof(wndpl);
1028         wndpl.showCmd = showCmd;
1029         wndpl.flags = flags = 0;
1030
1031         if( pt )
1032         {
1033             flags |= PLACE_MIN;
1034             wndpl.flags |= WPF_SETMINPOSITION;
1035             wndpl.ptMinPosition = *pt;
1036         }
1037         if( rect )
1038         {
1039             flags |= PLACE_RECT;
1040             wndpl.rcNormalPosition = *rect;
1041         }
1042         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1043     }
1044 }
1045
1046
1047 /*******************************************************************
1048  *         can_activate_window
1049  *
1050  * Check if we can activate the specified window.
1051  */
1052 static BOOL can_activate_window( HWND hwnd )
1053 {
1054     LONG style;
1055
1056     if (!hwnd) return FALSE;
1057     style = GetWindowLongW( hwnd, GWL_STYLE );
1058     if (!(style & WS_VISIBLE)) return FALSE;
1059     if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
1060     return !(style & WS_DISABLED);
1061 }
1062
1063
1064 /*******************************************************************
1065  *         WINPOS_ActivateOtherWindow
1066  *
1067  *  Activates window other than pWnd.
1068  */
1069 void WINPOS_ActivateOtherWindow(HWND hwnd)
1070 {
1071     HWND hwndTo, fg;
1072
1073     if ((GetWindowLongW( hwnd, GWL_STYLE ) & WS_POPUP) && (hwndTo = GetWindow( hwnd, GW_OWNER )))
1074     {
1075         hwndTo = GetAncestor( hwndTo, GA_ROOT );
1076         if (can_activate_window( hwndTo )) goto done;
1077     }
1078
1079     hwndTo = hwnd;
1080     for (;;)
1081     {
1082         if (!(hwndTo = GetWindow( hwndTo, GW_HWNDNEXT ))) break;
1083         if (can_activate_window( hwndTo )) break;
1084     }
1085
1086  done:
1087     fg = GetForegroundWindow();
1088     TRACE("win = %p fg = %p\n", hwndTo, fg);
1089     if (!fg || (hwnd == fg))
1090     {
1091         if (SetForegroundWindow( hwndTo )) return;
1092     }
1093     if (!SetActiveWindow( hwndTo )) SetActiveWindow(0);
1094 }
1095
1096
1097 /***********************************************************************
1098  *           WINPOS_HandleWindowPosChanging16
1099  *
1100  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1101  */
1102 LONG WINPOS_HandleWindowPosChanging16( HWND hwnd, WINDOWPOS16 *winpos )
1103 {
1104     POINT minTrack, maxTrack;
1105     LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1106
1107     if (winpos->flags & SWP_NOSIZE) return 0;
1108     if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
1109     {
1110         WINPOS_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack );
1111         if (winpos->cx > maxTrack.x) winpos->cx = maxTrack.x;
1112         if (winpos->cy > maxTrack.y) winpos->cy = maxTrack.y;
1113         if (!(style & WS_MINIMIZE))
1114         {
1115             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1116             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1117         }
1118     }
1119     return 0;
1120 }
1121
1122
1123 /***********************************************************************
1124  *           WINPOS_HandleWindowPosChanging
1125  *
1126  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1127  */
1128 LONG WINPOS_HandleWindowPosChanging( HWND hwnd, WINDOWPOS *winpos )
1129 {
1130     POINT minTrack, maxTrack;
1131     LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1132
1133     if (winpos->flags & SWP_NOSIZE) return 0;
1134     if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
1135     {
1136         WINPOS_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack );
1137         if (winpos->cx > maxTrack.x) winpos->cx = maxTrack.x;
1138         if (winpos->cy > maxTrack.y) winpos->cy = maxTrack.y;
1139         if (!(style & WS_MINIMIZE))
1140         {
1141             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1142             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1143         }
1144     }
1145     return 0;
1146 }
1147
1148
1149 /***********************************************************************
1150  *           dump_winpos_flags
1151  */
1152 static void dump_winpos_flags(UINT flags)
1153 {
1154     TRACE("flags:");
1155     if(flags & SWP_NOSIZE) TRACE(" SWP_NOSIZE");
1156     if(flags & SWP_NOMOVE) TRACE(" SWP_NOMOVE");
1157     if(flags & SWP_NOZORDER) TRACE(" SWP_NOZORDER");
1158     if(flags & SWP_NOREDRAW) TRACE(" SWP_NOREDRAW");
1159     if(flags & SWP_NOACTIVATE) TRACE(" SWP_NOACTIVATE");
1160     if(flags & SWP_FRAMECHANGED) TRACE(" SWP_FRAMECHANGED");
1161     if(flags & SWP_SHOWWINDOW) TRACE(" SWP_SHOWWINDOW");
1162     if(flags & SWP_HIDEWINDOW) TRACE(" SWP_HIDEWINDOW");
1163     if(flags & SWP_NOCOPYBITS) TRACE(" SWP_NOCOPYBITS");
1164     if(flags & SWP_NOOWNERZORDER) TRACE(" SWP_NOOWNERZORDER");
1165     if(flags & SWP_NOSENDCHANGING) TRACE(" SWP_NOSENDCHANGING");
1166     if(flags & SWP_DEFERERASE) TRACE(" SWP_DEFERERASE");
1167     if(flags & SWP_ASYNCWINDOWPOS) TRACE(" SWP_ASYNCWINDOWPOS");
1168
1169 #define DUMPED_FLAGS \
1170     (SWP_NOSIZE | \
1171     SWP_NOMOVE | \
1172     SWP_NOZORDER | \
1173     SWP_NOREDRAW | \
1174     SWP_NOACTIVATE | \
1175     SWP_FRAMECHANGED | \
1176     SWP_SHOWWINDOW | \
1177     SWP_HIDEWINDOW | \
1178     SWP_NOCOPYBITS | \
1179     SWP_NOOWNERZORDER | \
1180     SWP_NOSENDCHANGING | \
1181     SWP_DEFERERASE | \
1182     SWP_ASYNCWINDOWPOS)
1183
1184     if(flags & ~DUMPED_FLAGS) TRACE(" %08x", flags & ~DUMPED_FLAGS);
1185     TRACE("\n");
1186 #undef DUMPED_FLAGS
1187 }
1188
1189 /***********************************************************************
1190  *              SetWindowPos (USER32.@)
1191  */
1192 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
1193                           INT x, INT y, INT cx, INT cy, UINT flags )
1194 {
1195     WINDOWPOS winpos;
1196
1197     TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
1198           hwnd, hwndInsertAfter, x, y, cx, cy, flags);
1199     if(TRACE_ON(win)) dump_winpos_flags(flags);
1200
1201     if (is_broadcast(hwnd))
1202     {
1203         SetLastError( ERROR_INVALID_PARAMETER );
1204         return FALSE;
1205     }
1206
1207     winpos.hwnd = WIN_GetFullHandle(hwnd);
1208     winpos.hwndInsertAfter = WIN_GetFullHandle(hwndInsertAfter);
1209     winpos.x = x;
1210     winpos.y = y;
1211     winpos.cx = cx;
1212     winpos.cy = cy;
1213     winpos.flags = flags;
1214     if (WIN_IsCurrentThread( hwnd ))
1215     {
1216         if (USER_Driver.pSetWindowPos)
1217             return USER_Driver.pSetWindowPos( &winpos );
1218         return FALSE;
1219     }
1220     return SendMessageW( winpos.hwnd, WM_WINE_SETWINDOWPOS, 0, (LPARAM)&winpos );
1221 }
1222
1223
1224 /***********************************************************************
1225  *              BeginDeferWindowPos (USER32.@)
1226  */
1227 HDWP WINAPI BeginDeferWindowPos( INT count )
1228 {
1229     HDWP handle;
1230     DWP *pDWP;
1231
1232     TRACE("%d\n", count);
1233
1234     if (count < 0)
1235     {
1236         SetLastError(ERROR_INVALID_PARAMETER);
1237         return 0;
1238     }
1239     /* Windows allows zero count, in which case it allocates context for 8 moves */
1240     if (count == 0) count = 8;
1241
1242     handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
1243     if (!handle) return 0;
1244     pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
1245     pDWP->actualCount    = 0;
1246     pDWP->suggestedCount = count;
1247     pDWP->valid          = TRUE;
1248     pDWP->wMagic         = DWP_MAGIC;
1249     pDWP->hwndParent     = 0;
1250
1251     TRACE("returning hdwp %p\n", handle);
1252     return handle;
1253 }
1254
1255
1256 /***********************************************************************
1257  *              DeferWindowPos (USER32.@)
1258  */
1259 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
1260                                 INT x, INT y, INT cx, INT cy,
1261                                 UINT flags )
1262 {
1263     DWP *pDWP;
1264     int i;
1265     HDWP newhdwp = hdwp,retvalue;
1266
1267     TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
1268           hdwp, hwnd, hwndAfter, x, y, cx, cy, flags);
1269
1270     hwnd = WIN_GetFullHandle( hwnd );
1271     if (hwnd == GetDesktopWindow()) return 0;
1272
1273     if (!(pDWP = USER_HEAP_LIN_ADDR( hdwp ))) return 0;
1274
1275     USER_Lock();
1276
1277     for (i = 0; i < pDWP->actualCount; i++)
1278     {
1279         if (pDWP->winPos[i].hwnd == hwnd)
1280         {
1281               /* Merge with the other changes */
1282             if (!(flags & SWP_NOZORDER))
1283             {
1284                 pDWP->winPos[i].hwndInsertAfter = WIN_GetFullHandle(hwndAfter);
1285             }
1286             if (!(flags & SWP_NOMOVE))
1287             {
1288                 pDWP->winPos[i].x = x;
1289                 pDWP->winPos[i].y = y;
1290             }
1291             if (!(flags & SWP_NOSIZE))
1292             {
1293                 pDWP->winPos[i].cx = cx;
1294                 pDWP->winPos[i].cy = cy;
1295             }
1296             pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
1297                                                SWP_NOZORDER | SWP_NOREDRAW |
1298                                                SWP_NOACTIVATE | SWP_NOCOPYBITS|
1299                                                SWP_NOOWNERZORDER);
1300             pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
1301                                               SWP_FRAMECHANGED);
1302             retvalue = hdwp;
1303             goto END;
1304         }
1305     }
1306     if (pDWP->actualCount >= pDWP->suggestedCount)
1307     {
1308         newhdwp = USER_HEAP_REALLOC( hdwp,
1309                       sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
1310         if (!newhdwp)
1311         {
1312             retvalue = 0;
1313             goto END;
1314         }
1315         pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
1316         pDWP->suggestedCount++;
1317     }
1318     pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
1319     pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
1320     pDWP->winPos[pDWP->actualCount].x = x;
1321     pDWP->winPos[pDWP->actualCount].y = y;
1322     pDWP->winPos[pDWP->actualCount].cx = cx;
1323     pDWP->winPos[pDWP->actualCount].cy = cy;
1324     pDWP->winPos[pDWP->actualCount].flags = flags;
1325     pDWP->actualCount++;
1326     retvalue = newhdwp;
1327 END:
1328     USER_Unlock();
1329     return retvalue;
1330 }
1331
1332
1333 /***********************************************************************
1334  *              EndDeferWindowPos (USER32.@)
1335  */
1336 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
1337 {
1338     DWP *pDWP;
1339     WINDOWPOS *winpos;
1340     BOOL res = TRUE;
1341     int i;
1342
1343     TRACE("%p\n", hdwp);
1344
1345     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1346     if (!pDWP) return FALSE;
1347     for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
1348     {
1349         if (!USER_Driver.pSetWindowPos || !(res = USER_Driver.pSetWindowPos( winpos ))) break;
1350     }
1351     USER_HEAP_FREE( hdwp );
1352     return res;
1353 }
1354
1355
1356 /***********************************************************************
1357  *              TileChildWindows (USER.199)
1358  */
1359 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
1360 {
1361     FIXME("(%04x, %d): stub\n", parent, action);
1362 }
1363
1364 /***********************************************************************
1365  *              CascadeChildWindows (USER.198)
1366  */
1367 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
1368 {
1369     FIXME("(%04x, %d): stub\n", parent, action);
1370 }