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