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