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