urlmon: Added TYMED_FILE support to CopyStgMedium.
[wine] / dlls / user32 / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdarg.h>
26 #include <string.h>
27 #include "ntstatus.h"
28 #define WIN32_NO_STATUS
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winerror.h"
33 #include "wine/server.h"
34 #include "controls.h"
35 #include "user_private.h"
36 #include "win.h"
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(win);
40
41 #define SWP_AGG_NOGEOMETRYCHANGE \
42     (SWP_NOSIZE | SWP_NOCLIENTSIZE | SWP_NOZORDER)
43 #define SWP_AGG_NOPOSCHANGE \
44     (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER)
45 #define SWP_AGG_STATUSFLAGS \
46     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
47
48 #define HAS_DLGFRAME(style,exStyle) \
49     (((exStyle) & WS_EX_DLGMODALFRAME) || \
50      (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
51
52 #define HAS_THICKFRAME(style) \
53     (((style) & WS_THICKFRAME) && \
54      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
55
56 #define EMPTYPOINT(pt)          ((*(LONG*)&(pt)) == -1)
57
58 #define PLACE_MIN               0x0001
59 #define PLACE_MAX               0x0002
60 #define PLACE_RECT              0x0004
61
62
63 #define DWP_MAGIC  ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
64
65 typedef struct
66 {
67     INT       actualCount;
68     INT       suggestedCount;
69     BOOL      valid;
70     INT       wMagic;
71     HWND      hwndParent;
72     WINDOWPOS winPos[1];
73 } DWP;
74
75 typedef struct
76 {
77     RECT16   rectNormal;
78     POINT16  ptIconPos;
79     POINT16  ptMaxPos;
80     HWND     hwndIconTitle;
81 } INTERNALPOS, *LPINTERNALPOS;
82
83 /* ----- internal functions ----- */
84
85 static const WCHAR SysIP_W[] = { 'S','y','s','I','P',0 };
86
87 static inline INTERNALPOS *get_internal_pos( HWND hwnd )
88 {
89     return GetPropW( hwnd, SysIP_W );
90 }
91
92 static inline void set_internal_pos( HWND hwnd, INTERNALPOS *pos )
93 {
94     SetPropW( hwnd, SysIP_W, pos );
95 }
96
97 /***********************************************************************
98  *           WINPOS_CheckInternalPos
99  *
100  * Called when a window is destroyed.
101  */
102 void WINPOS_CheckInternalPos( HWND hwnd )
103 {
104     LPINTERNALPOS lpPos = get_internal_pos( hwnd );
105
106     if ( lpPos )
107     {
108         if( IsWindow(lpPos->hwndIconTitle) )
109             DestroyWindow( lpPos->hwndIconTitle );
110         HeapFree( GetProcessHeap(), 0, lpPos );
111     }
112 }
113
114 /***********************************************************************
115  *              ArrangeIconicWindows (USER32.@)
116  */
117 UINT WINAPI ArrangeIconicWindows( HWND parent )
118 {
119     RECT rectParent;
120     HWND hwndChild;
121     INT x, y, xspacing, yspacing;
122
123     GetClientRect( parent, &rectParent );
124     x = rectParent.left;
125     y = rectParent.bottom;
126     xspacing = GetSystemMetrics(SM_CXICONSPACING);
127     yspacing = GetSystemMetrics(SM_CYICONSPACING);
128
129     hwndChild = GetWindow( parent, GW_CHILD );
130     while (hwndChild)
131     {
132         if( IsIconic( hwndChild ) )
133         {
134             WINPOS_ShowIconTitle( hwndChild, FALSE );
135
136             SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
137                             y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
138                             SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
139             if( IsWindow(hwndChild) )
140                 WINPOS_ShowIconTitle(hwndChild , TRUE );
141
142             if (x <= rectParent.right - xspacing) x += xspacing;
143             else
144             {
145                 x = rectParent.left;
146                 y -= yspacing;
147             }
148         }
149         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
150     }
151     return yspacing;
152 }
153
154
155 /***********************************************************************
156  *              SwitchToThisWindow (USER32.@)
157  */
158 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
159 {
160     ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
161 }
162
163
164 /***********************************************************************
165  *              GetWindowRect (USER32.@)
166  */
167 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
168 {
169     BOOL ret = WIN_GetRectangles( hwnd, rect, NULL );
170     if (ret)
171     {
172         MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 );
173         TRACE( "hwnd %p (%s)\n", hwnd, wine_dbgstr_rect(rect) );
174     }
175     return ret;
176 }
177
178
179 /***********************************************************************
180  *              GetWindowRgn (USER32.@)
181  */
182 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
183 {
184     int nRet = ERROR;
185     NTSTATUS status;
186     HRGN win_rgn = 0;
187     RGNDATA *data;
188     size_t size = 256;
189
190     do
191     {
192         if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) + size - 1 )))
193         {
194             SetLastError( ERROR_OUTOFMEMORY );
195             return ERROR;
196         }
197         SERVER_START_REQ( get_window_region )
198         {
199             req->window = hwnd;
200             wine_server_set_reply( req, data->Buffer, size );
201             if (!(status = wine_server_call( req )))
202             {
203                 size_t reply_size = wine_server_reply_size( reply );
204                 if (reply_size)
205                 {
206                     data->rdh.dwSize   = sizeof(data->rdh);
207                     data->rdh.iType    = RDH_RECTANGLES;
208                     data->rdh.nCount   = reply_size / sizeof(RECT);
209                     data->rdh.nRgnSize = reply_size;
210                     win_rgn = ExtCreateRegion( NULL, size, data );
211                 }
212             }
213             else size = reply->total_size;
214         }
215         SERVER_END_REQ;
216         HeapFree( GetProcessHeap(), 0, data );
217     } while (status == STATUS_BUFFER_OVERFLOW);
218
219     if (status) SetLastError( RtlNtStatusToDosError(status) );
220     else if (win_rgn)
221     {
222         nRet = CombineRgn( hrgn, win_rgn, 0, RGN_COPY );
223         DeleteObject( win_rgn );
224     }
225     return nRet;
226 }
227
228
229 /***********************************************************************
230  *              SetWindowRgn (USER32.@)
231  */
232 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
233 {
234     static const RECT empty_rect;
235     BOOL ret;
236
237     if (hrgn)
238     {
239         RGNDATA *data;
240         DWORD size;
241
242         if (!(size = GetRegionData( hrgn, 0, NULL ))) return FALSE;
243         if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE;
244         if (!GetRegionData( hrgn, size, data ))
245         {
246             HeapFree( GetProcessHeap(), 0, data );
247             return FALSE;
248         }
249         SERVER_START_REQ( set_window_region )
250         {
251             req->window = hwnd;
252             req->redraw = (bRedraw != 0);
253             if (data->rdh.nCount)
254                 wine_server_add_data( req, data->Buffer, data->rdh.nCount * sizeof(RECT) );
255             else
256                 wine_server_add_data( req, &empty_rect, sizeof(empty_rect) );
257             ret = !wine_server_call_err( req );
258         }
259         SERVER_END_REQ;
260     }
261     else  /* clear existing region */
262     {
263         SERVER_START_REQ( set_window_region )
264         {
265             req->window = hwnd;
266             req->redraw = (bRedraw != 0);
267             ret = !wine_server_call_err( req );
268         }
269         SERVER_END_REQ;
270     }
271
272     if (ret) ret = USER_Driver->pSetWindowRgn( hwnd, hrgn, bRedraw );
273
274     if (ret)
275     {
276         UINT swp_flags = SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_FRAMECHANGED;
277         if (hrgn) swp_flags |= SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE;
278         if (!bRedraw) swp_flags |= SWP_NOREDRAW;
279         SetWindowPos( hwnd, 0, 0, 0, 0, 0, swp_flags );
280     }
281     return ret;
282 }
283
284
285 /***********************************************************************
286  *              GetClientRect (USER32.@)
287  */
288 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
289 {
290     BOOL ret;
291
292     if ((ret = WIN_GetRectangles( hwnd, NULL, rect )))
293     {
294         rect->right -= rect->left;
295         rect->bottom -= rect->top;
296         rect->left = rect->top = 0;
297     }
298     return ret;
299 }
300
301
302 /*******************************************************************
303  *              ClientToScreen (USER32.@)
304  */
305 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
306 {
307     MapWindowPoints( hwnd, 0, lppnt, 1 );
308     return TRUE;
309 }
310
311
312 /*******************************************************************
313  *              ScreenToClient (USER32.@)
314  */
315 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
316 {
317     MapWindowPoints( 0, hwnd, lppnt, 1 );
318     return TRUE;
319 }
320
321
322 /***********************************************************************
323  *           list_children_from_point
324  *
325  * Get the list of children that can contain point from the server.
326  * Point is in screen coordinates.
327  * Returned list must be freed by caller.
328  */
329 static HWND *list_children_from_point( HWND hwnd, POINT pt )
330 {
331     HWND *list;
332     int size = 32;
333
334     for (;;)
335     {
336         int count = 0;
337
338         if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
339
340         SERVER_START_REQ( get_window_children_from_point )
341         {
342             req->parent = hwnd;
343             req->x = pt.x;
344             req->y = pt.y;
345             wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
346             if (!wine_server_call( req )) count = reply->count;
347         }
348         SERVER_END_REQ;
349         if (count && count < size)
350         {
351             list[count] = 0;
352             return list;
353         }
354         HeapFree( GetProcessHeap(), 0, list );
355         if (!count) break;
356         size = count + 1;  /* restart with a large enough buffer */
357     }
358     return NULL;
359 }
360
361
362 /***********************************************************************
363  *           WINPOS_WindowFromPoint
364  *
365  * Find the window and hittest for a given point.
366  */
367 HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
368 {
369     int i, res;
370     HWND ret, *list;
371
372     if (!hwndScope) hwndScope = GetDesktopWindow();
373
374     *hittest = HTNOWHERE;
375
376     if (!(list = list_children_from_point( hwndScope, pt ))) return 0;
377
378     /* now determine the hittest */
379
380     for (i = 0; list[i]; i++)
381     {
382         LONG style = GetWindowLongW( list[i], GWL_STYLE );
383
384         /* If window is minimized or disabled, return at once */
385         if (style & WS_MINIMIZE)
386         {
387             *hittest = HTCAPTION;
388             break;
389         }
390         if (style & WS_DISABLED)
391         {
392             *hittest = HTERROR;
393             break;
394         }
395         /* Send WM_NCCHITTEST (if same thread) */
396         if (!WIN_IsCurrentThread( list[i] ))
397         {
398             *hittest = HTCLIENT;
399             break;
400         }
401         res = SendMessageW( list[i], WM_NCHITTEST, 0, MAKELONG(pt.x,pt.y) );
402         if (res != HTTRANSPARENT)
403         {
404             *hittest = res;  /* Found the window */
405             break;
406         }
407         /* continue search with next window in z-order */
408     }
409     ret = list[i];
410     HeapFree( GetProcessHeap(), 0, list );
411     TRACE( "scope %p (%d,%d) returning %p\n", hwndScope, pt.x, pt.y, ret );
412     return ret;
413 }
414
415
416 /*******************************************************************
417  *              WindowFromPoint (USER32.@)
418  */
419 HWND WINAPI WindowFromPoint( POINT pt )
420 {
421     INT hittest;
422     return WINPOS_WindowFromPoint( 0, pt, &hittest );
423 }
424
425
426 /*******************************************************************
427  *              ChildWindowFromPoint (USER32.@)
428  */
429 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
430 {
431     return ChildWindowFromPointEx( hwndParent, pt, CWP_ALL );
432 }
433
434 /*******************************************************************
435  *              RealChildWindowFromPoint (USER32.@)
436  */
437 HWND WINAPI RealChildWindowFromPoint( HWND hwndParent, POINT pt )
438 {
439     return ChildWindowFromPointEx( hwndParent, pt, CWP_SKIPTRANSPARENT );
440 }
441
442 /*******************************************************************
443  *              ChildWindowFromPointEx (USER32.@)
444  */
445 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt, UINT uFlags)
446 {
447     /* pt is in the client coordinates */
448     HWND *list;
449     int i;
450     RECT rect;
451     HWND retvalue;
452
453     GetClientRect( hwndParent, &rect );
454     if (!PtInRect( &rect, pt )) return 0;
455     if (!(list = WIN_ListChildren( hwndParent ))) return hwndParent;
456
457     for (i = 0; list[i]; i++)
458     {
459         if (!WIN_GetRectangles( list[i], &rect, NULL )) continue;
460         if (!PtInRect( &rect, pt )) continue;
461         if (uFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED))
462         {
463             LONG style = GetWindowLongW( list[i], GWL_STYLE );
464             if ((uFlags & CWP_SKIPINVISIBLE) && !(style & WS_VISIBLE)) continue;
465             if ((uFlags & CWP_SKIPDISABLED) && (style & WS_DISABLED)) continue;
466         }
467         if (uFlags & CWP_SKIPTRANSPARENT)
468         {
469             if (GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_TRANSPARENT) continue;
470         }
471         break;
472     }
473     retvalue = list[i];
474     HeapFree( GetProcessHeap(), 0, list );
475     if (!retvalue) retvalue = hwndParent;
476     return retvalue;
477 }
478
479
480 /*******************************************************************
481  *         WINPOS_GetWinOffset
482  *
483  * Calculate the offset between the origin of the two windows. Used
484  * to implement MapWindowPoints.
485  */
486 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, POINT *offset )
487 {
488     WND * wndPtr;
489
490     offset->x = offset->y = 0;
491
492     /* Translate source window origin to screen coords */
493     if (hwndFrom)
494     {
495         HWND hwnd = hwndFrom;
496
497         while (hwnd)
498         {
499             if (hwnd == hwndTo) return;
500             if (!(wndPtr = WIN_GetPtr( hwnd )))
501             {
502                 ERR( "bad hwndFrom = %p\n", hwnd );
503                 return;
504             }
505             if (wndPtr == WND_DESKTOP) break;
506             if (wndPtr == WND_OTHER_PROCESS) goto other_process;
507             offset->x += wndPtr->rectClient.left;
508             offset->y += wndPtr->rectClient.top;
509             hwnd = wndPtr->parent;
510             WIN_ReleasePtr( wndPtr );
511         }
512     }
513
514     /* Translate origin to destination window coords */
515     if (hwndTo)
516     {
517         HWND hwnd = hwndTo;
518
519         while (hwnd)
520         {
521             if (!(wndPtr = WIN_GetPtr( hwnd )))
522             {
523                 ERR( "bad hwndTo = %p\n", hwnd );
524                 return;
525             }
526             if (wndPtr == WND_DESKTOP) break;
527             if (wndPtr == WND_OTHER_PROCESS) goto other_process;
528             offset->x -= wndPtr->rectClient.left;
529             offset->y -= wndPtr->rectClient.top;
530             hwnd = wndPtr->parent;
531             WIN_ReleasePtr( wndPtr );
532         }
533     }
534     return;
535
536  other_process:  /* one of the parents may belong to another process, do it the hard way */
537     offset->x = offset->y = 0;
538     SERVER_START_REQ( get_windows_offset )
539     {
540         req->from = hwndFrom;
541         req->to   = hwndTo;
542         if (!wine_server_call( req ))
543         {
544             offset->x = reply->x;
545             offset->y = reply->y;
546         }
547     }
548     SERVER_END_REQ;
549 }
550
551
552 /*******************************************************************
553  *              MapWindowPoints (USER.258)
554  */
555 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
556                                LPPOINT16 lppt, UINT16 count )
557 {
558     POINT offset;
559
560     WINPOS_GetWinOffset( WIN_Handle32(hwndFrom), WIN_Handle32(hwndTo), &offset );
561     while (count--)
562     {
563         lppt->x += offset.x;
564         lppt->y += offset.y;
565         lppt++;
566     }
567 }
568
569
570 /*******************************************************************
571  *              MapWindowPoints (USER32.@)
572  */
573 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, UINT count )
574 {
575     POINT offset;
576
577     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
578     while (count--)
579     {
580         lppt->x += offset.x;
581         lppt->y += offset.y;
582         lppt++;
583     }
584     return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
585 }
586
587
588 /***********************************************************************
589  *              IsIconic (USER32.@)
590  */
591 BOOL WINAPI IsIconic(HWND hWnd)
592 {
593     return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MINIMIZE) != 0;
594 }
595
596
597 /***********************************************************************
598  *              IsZoomed (USER32.@)
599  */
600 BOOL WINAPI IsZoomed(HWND hWnd)
601 {
602     return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MAXIMIZE) != 0;
603 }
604
605
606 /*******************************************************************
607  *              AllowSetForegroundWindow (USER32.@)
608  */
609 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
610 {
611     /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
612      * implemented, then fix this function. */
613     return TRUE;
614 }
615
616
617 /*******************************************************************
618  *              LockSetForegroundWindow (USER32.@)
619  */
620 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
621 {
622     /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
623      * implemented, then fix this function. */
624     return TRUE;
625 }
626
627
628 /***********************************************************************
629  *              BringWindowToTop (USER32.@)
630  */
631 BOOL WINAPI BringWindowToTop( HWND hwnd )
632 {
633     return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
634 }
635
636
637 /***********************************************************************
638  *              MoveWindow (USER32.@)
639  */
640 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
641                             BOOL repaint )
642 {
643     int flags = SWP_NOZORDER | SWP_NOACTIVATE;
644     if (!repaint) flags |= SWP_NOREDRAW;
645     TRACE("%p %d,%d %dx%d %d\n", hwnd, x, y, cx, cy, repaint );
646     return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
647 }
648
649 /***********************************************************************
650  *           WINPOS_InitInternalPos
651  */
652 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd )
653 {
654     LPINTERNALPOS lpPos = get_internal_pos( wnd->hwndSelf );
655     if( !lpPos )
656     {
657         /* this happens when the window is minimized/maximized
658          * for the first time (rectWindow is not adjusted yet) */
659
660         lpPos = HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS) );
661         if( !lpPos ) return NULL;
662
663         set_internal_pos( wnd->hwndSelf, lpPos );
664         lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
665         lpPos->rectNormal.left   = wnd->rectWindow.left;
666         lpPos->rectNormal.top    = wnd->rectWindow.top;
667         lpPos->rectNormal.right  = wnd->rectWindow.right;
668         lpPos->rectNormal.bottom = wnd->rectWindow.bottom;
669         lpPos->ptIconPos.x = lpPos->ptIconPos.y = -1;
670         lpPos->ptMaxPos.x = lpPos->ptMaxPos.y = -1;
671     }
672
673     if( wnd->dwStyle & WS_MINIMIZE )
674     {
675         lpPos->ptIconPos.x = wnd->rectWindow.left;
676         lpPos->ptIconPos.y = wnd->rectWindow.top;
677     }
678     else if( wnd->dwStyle & WS_MAXIMIZE )
679     {
680         lpPos->ptMaxPos.x = wnd->rectWindow.left;
681         lpPos->ptMaxPos.y = wnd->rectWindow.top;
682     }
683     else
684     {
685         lpPos->rectNormal.left   = wnd->rectWindow.left;
686         lpPos->rectNormal.top    = wnd->rectWindow.top;
687         lpPos->rectNormal.right  = wnd->rectWindow.right;
688         lpPos->rectNormal.bottom = wnd->rectWindow.bottom;
689     }
690     return lpPos;
691 }
692
693 /***********************************************************************
694  *           WINPOS_RedrawIconTitle
695  */
696 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
697 {
698     LPINTERNALPOS lpPos = get_internal_pos( hWnd );
699     if( lpPos )
700     {
701         if( lpPos->hwndIconTitle )
702         {
703             SendMessageW( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
704             InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
705             return TRUE;
706         }
707     }
708     return FALSE;
709 }
710
711 /***********************************************************************
712  *           WINPOS_ShowIconTitle
713  */
714 BOOL WINPOS_ShowIconTitle( HWND hwnd, BOOL bShow )
715 {
716     LPINTERNALPOS lpPos = get_internal_pos( hwnd );
717
718     if (lpPos && !GetPropA( hwnd, "__wine_x11_managed" ))
719     {
720         HWND title = lpPos->hwndIconTitle;
721
722         TRACE("%p %i\n", hwnd, (bShow != 0) );
723
724         if( !title )
725             lpPos->hwndIconTitle = title = ICONTITLE_Create( hwnd );
726         if( bShow )
727         {
728             if (!IsWindowVisible(title))
729             {
730                 SendMessageW( title, WM_SHOWWINDOW, TRUE, 0 );
731                 SetWindowPos( title, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
732                               SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
733             }
734         }
735         else ShowWindow( title, SW_HIDE );
736     }
737     return FALSE;
738 }
739
740 /*******************************************************************
741  *           WINPOS_GetMinMaxInfo
742  *
743  * Get the minimized and maximized information for a window.
744  */
745 void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
746                            POINT *minTrack, POINT *maxTrack )
747 {
748     LPINTERNALPOS lpPos;
749     MINMAXINFO MinMax;
750     HMONITOR monitor;
751     INT xinc, yinc;
752     LONG style = GetWindowLongA( hwnd, GWL_STYLE );
753     LONG exstyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
754     RECT rc;
755
756     /* Compute default values */
757
758     GetWindowRect(hwnd, &rc);
759     MinMax.ptReserved.x = rc.left;
760     MinMax.ptReserved.y = rc.top;
761
762     if (style & WS_CHILD)
763     {
764         if ((style & WS_CAPTION) == WS_CAPTION)
765             style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
766
767         GetClientRect(GetAncestor(hwnd,GA_PARENT), &rc);
768         AdjustWindowRectEx(&rc, style, ((style & WS_POPUP) && GetMenu(hwnd)), exstyle);
769
770         /* avoid calculating this twice */
771         style &= ~(WS_DLGFRAME | WS_BORDER | WS_THICKFRAME);
772
773         MinMax.ptMaxSize.x = rc.right - rc.left;
774         MinMax.ptMaxSize.y = rc.bottom - rc.top;
775     }
776     else
777     {
778         MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
779         MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
780     }
781     MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
782     MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
783     MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXMAXTRACK);
784     MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYMAXTRACK);
785
786     if (HAS_DLGFRAME( style, exstyle ))
787     {
788         xinc = GetSystemMetrics(SM_CXDLGFRAME);
789         yinc = GetSystemMetrics(SM_CYDLGFRAME);
790     }
791     else
792     {
793         xinc = yinc = 0;
794         if (HAS_THICKFRAME(style))
795         {
796             xinc += GetSystemMetrics(SM_CXFRAME);
797             yinc += GetSystemMetrics(SM_CYFRAME);
798         }
799         if (style & WS_BORDER)
800         {
801             xinc += GetSystemMetrics(SM_CXBORDER);
802             yinc += GetSystemMetrics(SM_CYBORDER);
803         }
804     }
805     MinMax.ptMaxSize.x += 2 * xinc;
806     MinMax.ptMaxSize.y += 2 * yinc;
807
808     lpPos = get_internal_pos( hwnd );
809     if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
810     {
811         MinMax.ptMaxPosition.x = lpPos->ptMaxPos.x;
812         MinMax.ptMaxPosition.y = lpPos->ptMaxPos.y;
813     }
814     else
815     {
816         MinMax.ptMaxPosition.x = -xinc;
817         MinMax.ptMaxPosition.y = -yinc;
818     }
819
820     SendMessageW( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
821
822     /* if the app didn't change the values, adapt them for the current monitor */
823
824     if ((monitor = MonitorFromWindow( hwnd, MONITOR_DEFAULTTOPRIMARY )))
825     {
826         MONITORINFO mon_info;
827
828         mon_info.cbSize = sizeof(mon_info);
829         GetMonitorInfoW( monitor, &mon_info );
830
831         if (MinMax.ptMaxSize.x == GetSystemMetrics(SM_CXSCREEN) + 2 * xinc &&
832             MinMax.ptMaxSize.y == GetSystemMetrics(SM_CYSCREEN) + 2 * yinc)
833         {
834             MinMax.ptMaxSize.x = (mon_info.rcWork.right - mon_info.rcWork.left) + 2 * xinc;
835             MinMax.ptMaxSize.y = (mon_info.rcWork.bottom - mon_info.rcWork.top) + 2 * yinc;
836         }
837         if (MinMax.ptMaxPosition.x == -xinc && MinMax.ptMaxPosition.y == -yinc)
838         {
839             MinMax.ptMaxPosition.x = mon_info.rcWork.left - xinc;
840             MinMax.ptMaxPosition.y = mon_info.rcWork.top - yinc;
841         }
842     }
843
844       /* Some sanity checks */
845
846     TRACE("%d %d / %d %d / %d %d / %d %d\n",
847                       MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
848                       MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
849                       MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
850                       MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
851     MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
852                                    MinMax.ptMinTrackSize.x );
853     MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
854                                    MinMax.ptMinTrackSize.y );
855
856     if (maxSize) *maxSize = MinMax.ptMaxSize;
857     if (maxPos) *maxPos = MinMax.ptMaxPosition;
858     if (minTrack) *minTrack = MinMax.ptMinTrackSize;
859     if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
860 }
861
862 /***********************************************************************
863  *              ShowWindowAsync (USER32.@)
864  *
865  * doesn't wait; returns immediately.
866  * used by threads to toggle windows in other (possibly hanging) threads
867  */
868 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
869 {
870     HWND full_handle;
871
872     if (is_broadcast(hwnd))
873     {
874         SetLastError( ERROR_INVALID_PARAMETER );
875         return FALSE;
876     }
877
878     if ((full_handle = WIN_IsCurrentThread( hwnd )))
879         return USER_Driver->pShowWindow( full_handle, cmd );
880
881     return SendNotifyMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
882 }
883
884
885 /***********************************************************************
886  *              ShowWindow (USER32.@)
887  */
888 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
889 {
890     HWND full_handle;
891
892     if (is_broadcast(hwnd))
893     {
894         SetLastError( ERROR_INVALID_PARAMETER );
895         return FALSE;
896     }
897     if ((full_handle = WIN_IsCurrentThread( hwnd )))
898         return USER_Driver->pShowWindow( full_handle, cmd );
899
900     return SendMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
901 }
902
903
904 /***********************************************************************
905  *              GetInternalWindowPos (USER32.@)
906  */
907 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
908                                       LPPOINT ptIcon )
909 {
910     WINDOWPLACEMENT wndpl;
911     if (GetWindowPlacement( hwnd, &wndpl ))
912     {
913         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
914         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
915         return wndpl.showCmd;
916     }
917     return 0;
918 }
919
920
921 /***********************************************************************
922  *              GetWindowPlacement (USER32.@)
923  *
924  * Win95:
925  * Fails if wndpl->length of Win95 (!) apps is invalid.
926  */
927 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
928 {
929     WND *pWnd = WIN_GetPtr( hwnd );
930     LPINTERNALPOS lpPos;
931
932     if (!pWnd || pWnd == WND_DESKTOP) return FALSE;
933     if (pWnd == WND_OTHER_PROCESS)
934     {
935         if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
936         return FALSE;
937     }
938
939     lpPos = WINPOS_InitInternalPos( pWnd );
940     wndpl->length  = sizeof(*wndpl);
941     if( pWnd->dwStyle & WS_MINIMIZE )
942         wndpl->showCmd = SW_SHOWMINIMIZED;
943     else
944         wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE ) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
945     if( pWnd->flags & WIN_RESTORE_MAX )
946         wndpl->flags = WPF_RESTORETOMAXIMIZED;
947     else
948         wndpl->flags = 0;
949     wndpl->ptMinPosition.x = lpPos->ptIconPos.x;
950     wndpl->ptMinPosition.y = lpPos->ptIconPos.y;
951     wndpl->ptMaxPosition.x = lpPos->ptMaxPos.x;
952     wndpl->ptMaxPosition.y = lpPos->ptMaxPos.y;
953     wndpl->rcNormalPosition.left   = lpPos->rectNormal.left;
954     wndpl->rcNormalPosition.top    = lpPos->rectNormal.top;
955     wndpl->rcNormalPosition.right  = lpPos->rectNormal.right;
956     wndpl->rcNormalPosition.bottom = lpPos->rectNormal.bottom;
957     WIN_ReleasePtr( pWnd );
958     return TRUE;
959 }
960
961
962 /***********************************************************************
963  *           WINPOS_SetPlacement
964  */
965 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT *wndpl, UINT flags )
966 {
967     LPINTERNALPOS lpPos;
968     DWORD style;
969     WND *pWnd = WIN_GetPtr( hwnd );
970
971     if (!pWnd || pWnd == WND_OTHER_PROCESS || pWnd == WND_DESKTOP) return FALSE;
972     lpPos = WINPOS_InitInternalPos( pWnd );
973
974     if( flags & PLACE_MIN )
975     {
976         lpPos->ptIconPos.x = wndpl->ptMinPosition.x;
977         lpPos->ptIconPos.y = wndpl->ptMinPosition.y;
978     }
979     if( flags & PLACE_MAX )
980     {
981         lpPos->ptMaxPos.x = wndpl->ptMaxPosition.x;
982         lpPos->ptMaxPos.y = wndpl->ptMaxPosition.y;
983     }
984     if( flags & PLACE_RECT)
985     {
986         lpPos->rectNormal.left   = wndpl->rcNormalPosition.left;
987         lpPos->rectNormal.top    = wndpl->rcNormalPosition.top;
988         lpPos->rectNormal.right  = wndpl->rcNormalPosition.right;
989         lpPos->rectNormal.bottom = wndpl->rcNormalPosition.bottom;
990     }
991
992     style = pWnd->dwStyle;
993     WIN_ReleasePtr( pWnd );
994
995     if( style & WS_MINIMIZE )
996     {
997         WINPOS_ShowIconTitle( hwnd, FALSE );
998         if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
999             SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1000                           0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1001     }
1002     else if( style & WS_MAXIMIZE )
1003     {
1004         if( !EMPTYPOINT(lpPos->ptMaxPos) )
1005             SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1006                           0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1007     }
1008     else if( flags & PLACE_RECT )
1009         SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1010                       lpPos->rectNormal.right - lpPos->rectNormal.left,
1011                       lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1012                       SWP_NOZORDER | SWP_NOACTIVATE );
1013
1014     ShowWindow( hwnd, wndpl->showCmd );
1015
1016     if (IsIconic( hwnd ))
1017     {
1018         if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE) WINPOS_ShowIconTitle( hwnd, TRUE );
1019
1020         /* SDK: ...valid only the next time... */
1021         if( wndpl->flags & WPF_RESTORETOMAXIMIZED )
1022         {
1023             pWnd = WIN_GetPtr( hwnd );
1024             if (pWnd && pWnd != WND_OTHER_PROCESS)
1025             {
1026                 pWnd->flags |= WIN_RESTORE_MAX;
1027                 WIN_ReleasePtr( pWnd );
1028             }
1029         }
1030     }
1031     return TRUE;
1032 }
1033
1034
1035 /***********************************************************************
1036  *              SetWindowPlacement (USER32.@)
1037  *
1038  * Win95:
1039  * Fails if wndpl->length of Win95 (!) apps is invalid.
1040  */
1041 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *wpl )
1042 {
1043     if (!wpl) return FALSE;
1044     return WINPOS_SetPlacement( hwnd, wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1045 }
1046
1047
1048 /***********************************************************************
1049  *              AnimateWindow (USER32.@)
1050  *              Shows/Hides a window with an animation
1051  *              NO ANIMATION YET
1052  */
1053 BOOL WINAPI AnimateWindow(HWND hwnd, DWORD dwTime, DWORD dwFlags)
1054 {
1055         FIXME("partial stub\n");
1056
1057         /* If trying to show/hide and it's already   *
1058          * shown/hidden or invalid window, fail with *
1059          * invalid parameter                         */
1060         if(!IsWindow(hwnd) ||
1061            (IsWindowVisible(hwnd) && !(dwFlags & AW_HIDE)) ||
1062            (!IsWindowVisible(hwnd) && (dwFlags & AW_HIDE)))
1063         {
1064                 SetLastError(ERROR_INVALID_PARAMETER);
1065                 return FALSE;
1066         }
1067
1068         ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA));
1069
1070         return TRUE;
1071 }
1072
1073 /***********************************************************************
1074  *              SetInternalWindowPos (USER32.@)
1075  */
1076 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1077                                     LPRECT rect, LPPOINT pt )
1078 {
1079     if( IsWindow(hwnd) )
1080     {
1081         WINDOWPLACEMENT wndpl;
1082         UINT flags;
1083
1084         wndpl.length  = sizeof(wndpl);
1085         wndpl.showCmd = showCmd;
1086         wndpl.flags = flags = 0;
1087
1088         if( pt )
1089         {
1090             flags |= PLACE_MIN;
1091             wndpl.flags |= WPF_SETMINPOSITION;
1092             wndpl.ptMinPosition = *pt;
1093         }
1094         if( rect )
1095         {
1096             flags |= PLACE_RECT;
1097             wndpl.rcNormalPosition = *rect;
1098         }
1099         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1100     }
1101 }
1102
1103
1104 /*******************************************************************
1105  *         can_activate_window
1106  *
1107  * Check if we can activate the specified window.
1108  */
1109 static BOOL can_activate_window( HWND hwnd )
1110 {
1111     LONG style;
1112
1113     if (!hwnd) return FALSE;
1114     style = GetWindowLongW( hwnd, GWL_STYLE );
1115     if (!(style & WS_VISIBLE)) return FALSE;
1116     if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
1117     return !(style & WS_DISABLED);
1118 }
1119
1120
1121 /*******************************************************************
1122  *         WINPOS_ActivateOtherWindow
1123  *
1124  *  Activates window other than pWnd.
1125  */
1126 void WINPOS_ActivateOtherWindow(HWND hwnd)
1127 {
1128     HWND hwndTo, fg;
1129
1130     if ((GetWindowLongW( hwnd, GWL_STYLE ) & WS_POPUP) && (hwndTo = GetWindow( hwnd, GW_OWNER )))
1131     {
1132         hwndTo = GetAncestor( hwndTo, GA_ROOT );
1133         if (can_activate_window( hwndTo )) goto done;
1134     }
1135
1136     hwndTo = hwnd;
1137     for (;;)
1138     {
1139         if (!(hwndTo = GetWindow( hwndTo, GW_HWNDNEXT ))) break;
1140         if (can_activate_window( hwndTo )) break;
1141     }
1142
1143  done:
1144     fg = GetForegroundWindow();
1145     TRACE("win = %p fg = %p\n", hwndTo, fg);
1146     if (!fg || (hwnd == fg))
1147     {
1148         if (SetForegroundWindow( hwndTo )) return;
1149     }
1150     if (!SetActiveWindow( hwndTo )) SetActiveWindow(0);
1151 }
1152
1153
1154 /***********************************************************************
1155  *           WINPOS_HandleWindowPosChanging
1156  *
1157  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1158  */
1159 LONG WINPOS_HandleWindowPosChanging( HWND hwnd, WINDOWPOS *winpos )
1160 {
1161     POINT minTrack, maxTrack;
1162     LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1163
1164     if (winpos->flags & SWP_NOSIZE) return 0;
1165     if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
1166     {
1167         WINPOS_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack );
1168         if (winpos->cx > maxTrack.x) winpos->cx = maxTrack.x;
1169         if (winpos->cy > maxTrack.y) winpos->cy = maxTrack.y;
1170         if (!(style & WS_MINIMIZE))
1171         {
1172             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1173             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1174         }
1175     }
1176     return 0;
1177 }
1178
1179
1180 /***********************************************************************
1181  *           dump_winpos_flags
1182  */
1183 static void dump_winpos_flags(UINT flags)
1184 {
1185     TRACE("flags:");
1186     if(flags & SWP_NOSIZE) TRACE(" SWP_NOSIZE");
1187     if(flags & SWP_NOMOVE) TRACE(" SWP_NOMOVE");
1188     if(flags & SWP_NOZORDER) TRACE(" SWP_NOZORDER");
1189     if(flags & SWP_NOREDRAW) TRACE(" SWP_NOREDRAW");
1190     if(flags & SWP_NOACTIVATE) TRACE(" SWP_NOACTIVATE");
1191     if(flags & SWP_FRAMECHANGED) TRACE(" SWP_FRAMECHANGED");
1192     if(flags & SWP_SHOWWINDOW) TRACE(" SWP_SHOWWINDOW");
1193     if(flags & SWP_HIDEWINDOW) TRACE(" SWP_HIDEWINDOW");
1194     if(flags & SWP_NOCOPYBITS) TRACE(" SWP_NOCOPYBITS");
1195     if(flags & SWP_NOOWNERZORDER) TRACE(" SWP_NOOWNERZORDER");
1196     if(flags & SWP_NOSENDCHANGING) TRACE(" SWP_NOSENDCHANGING");
1197     if(flags & SWP_DEFERERASE) TRACE(" SWP_DEFERERASE");
1198     if(flags & SWP_ASYNCWINDOWPOS) TRACE(" SWP_ASYNCWINDOWPOS");
1199
1200 #define DUMPED_FLAGS \
1201     (SWP_NOSIZE | \
1202     SWP_NOMOVE | \
1203     SWP_NOZORDER | \
1204     SWP_NOREDRAW | \
1205     SWP_NOACTIVATE | \
1206     SWP_FRAMECHANGED | \
1207     SWP_SHOWWINDOW | \
1208     SWP_HIDEWINDOW | \
1209     SWP_NOCOPYBITS | \
1210     SWP_NOOWNERZORDER | \
1211     SWP_NOSENDCHANGING | \
1212     SWP_DEFERERASE | \
1213     SWP_ASYNCWINDOWPOS)
1214
1215     if(flags & ~DUMPED_FLAGS) TRACE(" %08x", flags & ~DUMPED_FLAGS);
1216     TRACE("\n");
1217 #undef DUMPED_FLAGS
1218 }
1219
1220 /***********************************************************************
1221  *           SWP_DoWinPosChanging
1222  */
1223 static BOOL SWP_DoWinPosChanging( WINDOWPOS* pWinpos, RECT* pNewWindowRect, RECT* pNewClientRect )
1224 {
1225     WND *wndPtr;
1226
1227     /* Send WM_WINDOWPOSCHANGING message */
1228
1229     if (!(pWinpos->flags & SWP_NOSENDCHANGING))
1230         SendMessageW( pWinpos->hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
1231
1232     if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) ||
1233         wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
1234
1235     /* Calculate new position and size */
1236
1237     *pNewWindowRect = wndPtr->rectWindow;
1238     *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
1239                                                     : wndPtr->rectClient;
1240
1241     if (!(pWinpos->flags & SWP_NOSIZE))
1242     {
1243         pNewWindowRect->right  = pNewWindowRect->left + pWinpos->cx;
1244         pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
1245     }
1246     if (!(pWinpos->flags & SWP_NOMOVE))
1247     {
1248         pNewWindowRect->left    = pWinpos->x;
1249         pNewWindowRect->top     = pWinpos->y;
1250         pNewWindowRect->right  += pWinpos->x - wndPtr->rectWindow.left;
1251         pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
1252
1253         OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
1254                                     pWinpos->y - wndPtr->rectWindow.top );
1255     }
1256     pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
1257
1258     TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n",
1259            pWinpos->hwnd, pWinpos->hwndInsertAfter, pWinpos->x, pWinpos->y,
1260            pWinpos->cx, pWinpos->cy, pWinpos->flags );
1261     TRACE( "current %s style %08x new %s\n",
1262            wine_dbgstr_rect( &wndPtr->rectWindow ), wndPtr->dwStyle,
1263            wine_dbgstr_rect( pNewWindowRect ));
1264
1265     WIN_ReleasePtr( wndPtr );
1266     return TRUE;
1267 }
1268
1269 /***********************************************************************
1270  *           get_valid_rects
1271  *
1272  * Compute the valid rects from the old and new client rect and WVR_* flags.
1273  * Helper for WM_NCCALCSIZE handling.
1274  */
1275 static inline void get_valid_rects( const RECT *old_client, const RECT *new_client, UINT flags,
1276                                     RECT *valid )
1277 {
1278     int cx, cy;
1279
1280     if (flags & WVR_REDRAW)
1281     {
1282         SetRectEmpty( &valid[0] );
1283         SetRectEmpty( &valid[1] );
1284         return;
1285     }
1286
1287     if (flags & WVR_VALIDRECTS)
1288     {
1289         if (!IntersectRect( &valid[0], &valid[0], new_client ) ||
1290             !IntersectRect( &valid[1], &valid[1], old_client ))
1291         {
1292             SetRectEmpty( &valid[0] );
1293             SetRectEmpty( &valid[1] );
1294             return;
1295         }
1296         flags = WVR_ALIGNLEFT | WVR_ALIGNTOP;
1297     }
1298     else
1299     {
1300         valid[0] = *new_client;
1301         valid[1] = *old_client;
1302     }
1303
1304     /* make sure the rectangles have the same size */
1305     cx = min( valid[0].right - valid[0].left, valid[1].right - valid[1].left );
1306     cy = min( valid[0].bottom - valid[0].top, valid[1].bottom - valid[1].top );
1307
1308     if (flags & WVR_ALIGNBOTTOM)
1309     {
1310         valid[0].top = valid[0].bottom - cy;
1311         valid[1].top = valid[1].bottom - cy;
1312     }
1313     else
1314     {
1315         valid[0].bottom = valid[0].top + cy;
1316         valid[1].bottom = valid[1].top + cy;
1317     }
1318     if (flags & WVR_ALIGNRIGHT)
1319     {
1320         valid[0].left = valid[0].right - cx;
1321         valid[1].left = valid[1].right - cx;
1322     }
1323     else
1324     {
1325         valid[0].right = valid[0].left + cx;
1326         valid[1].right = valid[1].left + cx;
1327     }
1328 }
1329
1330 struct move_owned_info
1331 {
1332     HWND owner;
1333     HWND insert_after;
1334 };
1335
1336 static BOOL CALLBACK move_owned_popups( HWND hwnd, LPARAM lparam )
1337 {
1338     struct move_owned_info *info = (struct move_owned_info *)lparam;
1339
1340     if (hwnd == info->owner) return FALSE;
1341     if ((GetWindowLongW( hwnd, GWL_STYLE ) & WS_POPUP) &&
1342         GetWindow( hwnd, GW_OWNER ) == info->owner)
1343     {
1344         SetWindowPos( hwnd, info->insert_after, 0, 0, 0, 0,
1345                       SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE |
1346                       SWP_NOSENDCHANGING | SWP_DEFERERASE );
1347         info->insert_after = hwnd;
1348     }
1349     return TRUE;
1350 }
1351
1352 /***********************************************************************
1353  *           SWP_DoOwnedPopups
1354  *
1355  * fix Z order taking into account owned popups -
1356  * basically we need to maintain them above the window that owns them
1357  *
1358  * FIXME: hide/show owned popups when owner visibility changes.
1359  */
1360 static HWND SWP_DoOwnedPopups(HWND hwnd, HWND hwndInsertAfter)
1361 {
1362     HWND owner = GetWindow( hwnd, GW_OWNER );
1363     LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1364     struct move_owned_info info;
1365
1366     TRACE("(%p) hInsertAfter = %p\n", hwnd, hwndInsertAfter );
1367
1368     if ((style & WS_POPUP) && owner)
1369     {
1370         /* make sure this popup stays above the owner */
1371
1372         if (hwndInsertAfter != HWND_TOP && hwndInsertAfter != HWND_TOPMOST)
1373         {
1374             HWND hwndLocalPrev = HWND_TOP;
1375             HWND prev = GetWindow( owner, GW_HWNDPREV );
1376
1377             while (prev && prev != hwndInsertAfter)
1378             {
1379                 if (hwndLocalPrev == HWND_TOP && GetWindowLongW( prev, GWL_STYLE ) & WS_VISIBLE)
1380                     hwndLocalPrev = prev;
1381                 prev = GetWindow( prev, GW_HWNDPREV );
1382             }
1383             if (!prev) hwndInsertAfter = hwndLocalPrev;
1384         }
1385     }
1386     else if (style & WS_CHILD) return hwndInsertAfter;
1387
1388     info.owner = hwnd;
1389     info.insert_after = hwndInsertAfter;
1390     EnumWindows( move_owned_popups, (LPARAM)&info );
1391     return info.insert_after;
1392 }
1393
1394 /***********************************************************************
1395  *           SWP_DoNCCalcSize
1396  */
1397 static UINT SWP_DoNCCalcSize( WINDOWPOS* pWinpos, const RECT* pNewWindowRect, RECT* pNewClientRect,
1398                               RECT *validRects )
1399 {
1400     UINT wvrFlags = 0;
1401     WND *wndPtr;
1402
1403     if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1404
1405       /* Send WM_NCCALCSIZE message to get new client area */
1406     if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
1407     {
1408         NCCALCSIZE_PARAMS params;
1409         WINDOWPOS winposCopy;
1410
1411         params.rgrc[0] = *pNewWindowRect;
1412         params.rgrc[1] = wndPtr->rectWindow;
1413         params.rgrc[2] = wndPtr->rectClient;
1414         params.lppos = &winposCopy;
1415         winposCopy = *pWinpos;
1416         WIN_ReleasePtr( wndPtr );
1417
1418         wvrFlags = SendMessageW( pWinpos->hwnd, WM_NCCALCSIZE, TRUE, (LPARAM)&params );
1419
1420         *pNewClientRect = params.rgrc[0];
1421
1422         if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1423
1424         TRACE( "hwnd %p old win %s old client %s new win %s new client %s\n", pWinpos->hwnd,
1425                wine_dbgstr_rect(&wndPtr->rectWindow), wine_dbgstr_rect(&wndPtr->rectClient),
1426                wine_dbgstr_rect(pNewWindowRect), wine_dbgstr_rect(pNewClientRect) );
1427
1428         if( pNewClientRect->left != wndPtr->rectClient.left ||
1429             pNewClientRect->top != wndPtr->rectClient.top )
1430             pWinpos->flags &= ~SWP_NOCLIENTMOVE;
1431
1432         if( (pNewClientRect->right - pNewClientRect->left !=
1433              wndPtr->rectClient.right - wndPtr->rectClient.left))
1434             pWinpos->flags &= ~SWP_NOCLIENTSIZE;
1435         else
1436             wvrFlags &= ~WVR_HREDRAW;
1437
1438         if (pNewClientRect->bottom - pNewClientRect->top !=
1439              wndPtr->rectClient.bottom - wndPtr->rectClient.top)
1440             pWinpos->flags &= ~SWP_NOCLIENTSIZE;
1441         else
1442             wvrFlags &= ~WVR_VREDRAW;
1443
1444         validRects[0] = params.rgrc[1];
1445         validRects[1] = params.rgrc[2];
1446     }
1447     else
1448     {
1449         if (!(pWinpos->flags & SWP_NOMOVE) &&
1450             (pNewClientRect->left != wndPtr->rectClient.left ||
1451              pNewClientRect->top != wndPtr->rectClient.top))
1452             pWinpos->flags &= ~SWP_NOCLIENTMOVE;
1453     }
1454
1455     if (pWinpos->flags & (SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_SHOWWINDOW | SWP_HIDEWINDOW))
1456     {
1457         SetRectEmpty( &validRects[0] );
1458         SetRectEmpty( &validRects[1] );
1459     }
1460     else get_valid_rects( &wndPtr->rectClient, pNewClientRect, wvrFlags, validRects );
1461
1462     WIN_ReleasePtr( wndPtr );
1463     return wvrFlags;
1464 }
1465
1466 /* fix redundant flags and values in the WINDOWPOS structure */
1467 static BOOL fixup_flags( WINDOWPOS *winpos )
1468 {
1469     HWND parent;
1470     WND *wndPtr = WIN_GetPtr( winpos->hwnd );
1471     BOOL ret = TRUE;
1472
1473     if (!wndPtr || wndPtr == WND_OTHER_PROCESS)
1474     {
1475         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1476         return FALSE;
1477     }
1478     winpos->hwnd = wndPtr->hwndSelf;  /* make it a full handle */
1479
1480     /* Finally make sure that all coordinates are valid */
1481     if (winpos->x < -32768) winpos->x = -32768;
1482     else if (winpos->x > 32767) winpos->x = 32767;
1483     if (winpos->y < -32768) winpos->y = -32768;
1484     else if (winpos->y > 32767) winpos->y = 32767;
1485
1486     if (winpos->cx < 0) winpos->cx = 0;
1487     else if (winpos->cx > 32767) winpos->cx = 32767;
1488     if (winpos->cy < 0) winpos->cy = 0;
1489     else if (winpos->cy > 32767) winpos->cy = 32767;
1490
1491     parent = GetAncestor( winpos->hwnd, GA_PARENT );
1492     if (!IsWindowVisible( parent )) winpos->flags |= SWP_NOREDRAW;
1493
1494     if (wndPtr->dwStyle & WS_VISIBLE) winpos->flags &= ~SWP_SHOWWINDOW;
1495     else
1496     {
1497         winpos->flags &= ~SWP_HIDEWINDOW;
1498         if (!(winpos->flags & SWP_SHOWWINDOW)) winpos->flags |= SWP_NOREDRAW;
1499     }
1500
1501     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == winpos->cx) &&
1502         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == winpos->cy))
1503         winpos->flags |= SWP_NOSIZE;    /* Already the right size */
1504
1505     if ((wndPtr->rectWindow.left == winpos->x) && (wndPtr->rectWindow.top == winpos->y))
1506         winpos->flags |= SWP_NOMOVE;    /* Already the right position */
1507
1508     if ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)
1509     {
1510         if (!(winpos->flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW)) && /* Bring to the top when activating */
1511             (winpos->flags & SWP_NOZORDER ||
1512              (winpos->hwndInsertAfter != HWND_TOPMOST && winpos->hwndInsertAfter != HWND_NOTOPMOST)))
1513         {
1514             winpos->flags &= ~SWP_NOZORDER;
1515             winpos->hwndInsertAfter = HWND_TOP;
1516         }
1517     }
1518
1519     /* Check hwndInsertAfter */
1520     if (winpos->flags & SWP_NOZORDER) goto done;
1521
1522     /* fix sign extension */
1523     if (winpos->hwndInsertAfter == (HWND)0xffff) winpos->hwndInsertAfter = HWND_TOPMOST;
1524     else if (winpos->hwndInsertAfter == (HWND)0xfffe) winpos->hwndInsertAfter = HWND_NOTOPMOST;
1525
1526     /* hwndInsertAfter must be a sibling of the window */
1527     if (winpos->hwndInsertAfter == HWND_TOP)
1528     {
1529         if (GetWindow(winpos->hwnd, GW_HWNDFIRST) == winpos->hwnd)
1530             winpos->flags |= SWP_NOZORDER;
1531     }
1532     else if (winpos->hwndInsertAfter == HWND_BOTTOM)
1533     {
1534         if (!(wndPtr->dwExStyle & WS_EX_TOPMOST) && GetWindow(winpos->hwnd, GW_HWNDLAST) == winpos->hwnd)
1535             winpos->flags |= SWP_NOZORDER;
1536     }
1537     else if (winpos->hwndInsertAfter == HWND_TOPMOST)
1538     {
1539         if ((wndPtr->dwExStyle & WS_EX_TOPMOST) && GetWindow(winpos->hwnd, GW_HWNDFIRST) == winpos->hwnd)
1540             winpos->flags |= SWP_NOZORDER;
1541     }
1542     else if (winpos->hwndInsertAfter == HWND_NOTOPMOST)
1543     {
1544         if (!(wndPtr->dwExStyle & WS_EX_TOPMOST))
1545             winpos->flags |= SWP_NOZORDER;
1546     }
1547     else
1548     {
1549         if (GetAncestor( winpos->hwndInsertAfter, GA_PARENT ) != parent) ret = FALSE;
1550         else
1551         {
1552             /* don't need to change the Zorder of hwnd if it's already inserted
1553              * after hwndInsertAfter or when inserting hwnd after itself.
1554              */
1555             if ((winpos->hwnd == winpos->hwndInsertAfter) ||
1556                 (winpos->hwnd == GetWindow( winpos->hwndInsertAfter, GW_HWNDNEXT )))
1557                 winpos->flags |= SWP_NOZORDER;
1558         }
1559     }
1560  done:
1561     WIN_ReleasePtr( wndPtr );
1562     return ret;
1563 }
1564
1565
1566 /***********************************************************************
1567  *              set_window_pos
1568  *
1569  * Backend implementation of SetWindowPos.
1570  */
1571 BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
1572                      const RECT *window_rect, const RECT *client_rect, const RECT *valid_rects )
1573 {
1574     WND *win;
1575     BOOL ret;
1576     RECT visible_rect;
1577
1578     if (!(win = WIN_GetPtr( hwnd ))) return FALSE;
1579     if (win == WND_DESKTOP || win == WND_OTHER_PROCESS) return FALSE;
1580
1581     SERVER_START_REQ( set_window_pos )
1582     {
1583         req->handle        = hwnd;
1584         req->previous      = insert_after;
1585         req->flags         = swp_flags;
1586         req->window.left   = window_rect->left;
1587         req->window.top    = window_rect->top;
1588         req->window.right  = window_rect->right;
1589         req->window.bottom = window_rect->bottom;
1590         req->client.left   = client_rect->left;
1591         req->client.top    = client_rect->top;
1592         req->client.right  = client_rect->right;
1593         req->client.bottom = client_rect->bottom;
1594         if (!IsRectEmpty( &valid_rects[0] ))
1595             wine_server_add_data( req, valid_rects, 2 * sizeof(*valid_rects) );
1596         if ((ret = !wine_server_call( req )))
1597         {
1598             win->dwStyle    = reply->new_style;
1599             win->dwExStyle  = reply->new_ex_style;
1600             win->rectWindow = *window_rect;
1601             win->rectClient = *client_rect;
1602             visible_rect.left   = reply->visible.left;
1603             visible_rect.top    = reply->visible.top;
1604             visible_rect.right  = reply->visible.right;
1605             visible_rect.bottom = reply->visible.bottom;
1606         }
1607     }
1608     SERVER_END_REQ;
1609     WIN_ReleasePtr( win );
1610
1611     if (ret)
1612         USER_Driver->pSetWindowPos( hwnd, insert_after, swp_flags, window_rect,
1613                                     client_rect, &visible_rect, valid_rects );
1614     return ret;
1615 }
1616
1617
1618 /***********************************************************************
1619  *              USER_SetWindowPos
1620  *
1621  *     User32 internal function
1622  */
1623 BOOL USER_SetWindowPos( WINDOWPOS * winpos )
1624 {
1625     RECT newWindowRect, newClientRect, valid_rects[2];
1626     UINT orig_flags;
1627     
1628     orig_flags = winpos->flags;
1629     
1630     /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
1631     if (!(winpos->flags & SWP_NOMOVE))
1632     {
1633         if (winpos->x < -32768) winpos->x = -32768;
1634         else if (winpos->x > 32767) winpos->x = 32767;
1635         if (winpos->y < -32768) winpos->y = -32768;
1636         else if (winpos->y > 32767) winpos->y = 32767;
1637     }
1638     if (!(winpos->flags & SWP_NOSIZE))
1639     {
1640         if (winpos->cx < 0) winpos->cx = 0;
1641         else if (winpos->cx > 32767) winpos->cx = 32767;
1642         if (winpos->cy < 0) winpos->cy = 0;
1643         else if (winpos->cy > 32767) winpos->cy = 32767;
1644     }
1645
1646     if (!SWP_DoWinPosChanging( winpos, &newWindowRect, &newClientRect )) return FALSE;
1647
1648     /* Fix redundant flags */
1649     if (!fixup_flags( winpos )) return FALSE;
1650
1651     if((winpos->flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
1652     {
1653         if (GetAncestor( winpos->hwnd, GA_PARENT ) == GetDesktopWindow())
1654             winpos->hwndInsertAfter = SWP_DoOwnedPopups( winpos->hwnd, winpos->hwndInsertAfter );
1655     }
1656
1657     /* Common operations */
1658
1659     SWP_DoNCCalcSize( winpos, &newWindowRect, &newClientRect, valid_rects );
1660
1661     if (!set_window_pos( winpos->hwnd, winpos->hwndInsertAfter, orig_flags,
1662                          &newWindowRect, &newClientRect, valid_rects ))
1663         return FALSE;
1664
1665     /* erase parent when hiding or resizing child */
1666     if (!(orig_flags & SWP_DEFERERASE) &&
1667         ((orig_flags & SWP_HIDEWINDOW) ||
1668          (!(orig_flags & SWP_SHOWWINDOW) &&
1669           (winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOGEOMETRYCHANGE)))
1670     {
1671         HWND parent = GetAncestor( winpos->hwnd, GA_PARENT );
1672         if (!parent || parent == GetDesktopWindow()) parent = winpos->hwnd;
1673         erase_now( parent, 0 );
1674     }
1675
1676     if( winpos->flags & SWP_HIDEWINDOW )
1677         HideCaret(winpos->hwnd);
1678     else if (winpos->flags & SWP_SHOWWINDOW)
1679         ShowCaret(winpos->hwnd);
1680
1681     if (!(winpos->flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW)))
1682     {
1683         /* child windows get WM_CHILDACTIVATE message */
1684         if ((GetWindowLongW( winpos->hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD)
1685             SendMessageW( winpos->hwnd, WM_CHILDACTIVATE, 0, 0 );
1686         else
1687             SetForegroundWindow( winpos->hwnd );
1688     }
1689
1690       /* And last, send the WM_WINDOWPOSCHANGED message */
1691
1692     TRACE("\tstatus flags = %04x\n", winpos->flags & SWP_AGG_STATUSFLAGS);
1693
1694     if (((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE))
1695     {
1696         /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
1697            and always contains final window position.
1698          */
1699         winpos->x = newWindowRect.left;
1700         winpos->y = newWindowRect.top;
1701         winpos->cx = newWindowRect.right - newWindowRect.left;
1702         winpos->cy = newWindowRect.bottom - newWindowRect.top;
1703         SendMessageW( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)winpos );
1704     }
1705     return TRUE;
1706 }
1707
1708 /***********************************************************************
1709  *              SetWindowPos (USER32.@)
1710  */
1711 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
1712                           INT x, INT y, INT cx, INT cy, UINT flags )
1713 {
1714     WINDOWPOS winpos;
1715
1716     TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
1717           hwnd, hwndInsertAfter, x, y, cx, cy, flags);
1718     if(TRACE_ON(win)) dump_winpos_flags(flags);
1719
1720     if (is_broadcast(hwnd))
1721     {
1722         SetLastError( ERROR_INVALID_PARAMETER );
1723         return FALSE;
1724     }
1725
1726     winpos.hwnd = WIN_GetFullHandle(hwnd);
1727     winpos.hwndInsertAfter = WIN_GetFullHandle(hwndInsertAfter);
1728     winpos.x = x;
1729     winpos.y = y;
1730     winpos.cx = cx;
1731     winpos.cy = cy;
1732     winpos.flags = flags;
1733     
1734     if (WIN_IsCurrentThread( hwnd ))
1735         return USER_SetWindowPos(&winpos);
1736
1737     return SendMessageW( winpos.hwnd, WM_WINE_SETWINDOWPOS, 0, (LPARAM)&winpos );
1738 }
1739
1740
1741 /***********************************************************************
1742  *              BeginDeferWindowPos (USER32.@)
1743  */
1744 HDWP WINAPI BeginDeferWindowPos( INT count )
1745 {
1746     HDWP handle;
1747     DWP *pDWP;
1748
1749     TRACE("%d\n", count);
1750
1751     if (count < 0)
1752     {
1753         SetLastError(ERROR_INVALID_PARAMETER);
1754         return 0;
1755     }
1756     /* Windows allows zero count, in which case it allocates context for 8 moves */
1757     if (count == 0) count = 8;
1758
1759     handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
1760     if (!handle) return 0;
1761     pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
1762     pDWP->actualCount    = 0;
1763     pDWP->suggestedCount = count;
1764     pDWP->valid          = TRUE;
1765     pDWP->wMagic         = DWP_MAGIC;
1766     pDWP->hwndParent     = 0;
1767
1768     TRACE("returning hdwp %p\n", handle);
1769     return handle;
1770 }
1771
1772
1773 /***********************************************************************
1774  *              DeferWindowPos (USER32.@)
1775  */
1776 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
1777                                 INT x, INT y, INT cx, INT cy,
1778                                 UINT flags )
1779 {
1780     DWP *pDWP;
1781     int i;
1782     HDWP newhdwp = hdwp,retvalue;
1783
1784     TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
1785           hdwp, hwnd, hwndAfter, x, y, cx, cy, flags);
1786
1787     hwnd = WIN_GetFullHandle( hwnd );
1788     if (hwnd == GetDesktopWindow()) return 0;
1789
1790     if (!(pDWP = USER_HEAP_LIN_ADDR( hdwp ))) return 0;
1791
1792     USER_Lock();
1793
1794     for (i = 0; i < pDWP->actualCount; i++)
1795     {
1796         if (pDWP->winPos[i].hwnd == hwnd)
1797         {
1798               /* Merge with the other changes */
1799             if (!(flags & SWP_NOZORDER))
1800             {
1801                 pDWP->winPos[i].hwndInsertAfter = WIN_GetFullHandle(hwndAfter);
1802             }
1803             if (!(flags & SWP_NOMOVE))
1804             {
1805                 pDWP->winPos[i].x = x;
1806                 pDWP->winPos[i].y = y;
1807             }
1808             if (!(flags & SWP_NOSIZE))
1809             {
1810                 pDWP->winPos[i].cx = cx;
1811                 pDWP->winPos[i].cy = cy;
1812             }
1813             pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
1814                                                SWP_NOZORDER | SWP_NOREDRAW |
1815                                                SWP_NOACTIVATE | SWP_NOCOPYBITS|
1816                                                SWP_NOOWNERZORDER);
1817             pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
1818                                               SWP_FRAMECHANGED);
1819             retvalue = hdwp;
1820             goto END;
1821         }
1822     }
1823     if (pDWP->actualCount >= pDWP->suggestedCount)
1824     {
1825         newhdwp = USER_HEAP_REALLOC( hdwp,
1826                       sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
1827         if (!newhdwp)
1828         {
1829             retvalue = 0;
1830             goto END;
1831         }
1832         pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
1833         pDWP->suggestedCount++;
1834     }
1835     pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
1836     pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
1837     pDWP->winPos[pDWP->actualCount].x = x;
1838     pDWP->winPos[pDWP->actualCount].y = y;
1839     pDWP->winPos[pDWP->actualCount].cx = cx;
1840     pDWP->winPos[pDWP->actualCount].cy = cy;
1841     pDWP->winPos[pDWP->actualCount].flags = flags;
1842     pDWP->actualCount++;
1843     retvalue = newhdwp;
1844 END:
1845     USER_Unlock();
1846     return retvalue;
1847 }
1848
1849
1850 /***********************************************************************
1851  *              EndDeferWindowPos (USER32.@)
1852  */
1853 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
1854 {
1855     DWP *pDWP;
1856     WINDOWPOS *winpos;
1857     BOOL res = TRUE;
1858     int i;
1859
1860     TRACE("%p\n", hdwp);
1861
1862     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1863     if (!pDWP) return FALSE;
1864     for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
1865     {
1866         TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
1867                winpos->hwnd, winpos->hwndInsertAfter, winpos->x, winpos->y,
1868                winpos->cx, winpos->cy, winpos->flags);
1869
1870         if (!(res = USER_SetWindowPos( winpos ))) break;
1871     }
1872     USER_HEAP_FREE( hdwp );
1873     return res;
1874 }
1875
1876
1877 /***********************************************************************
1878  *              TileChildWindows (USER.199)
1879  */
1880 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
1881 {
1882     FIXME("(%04x, %d): stub\n", parent, action);
1883 }
1884
1885 /***********************************************************************
1886  *              CascadeChildWindows (USER.198)
1887  */
1888 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
1889 {
1890     FIXME("(%04x, %d): stub\n", parent, action);
1891 }