Bugfix: DdeNameService was broken.
[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
8 #include <string.h>
9 #include "wine/winuser16.h"
10 #include "heap.h"
11 #include "module.h"
12 #include "user.h"
13 #include "region.h"
14 #include "win.h"
15 #include "hook.h"
16 #include "message.h"
17 #include "queue.h"
18 #include "options.h"
19 #include "task.h"
20 #include "winpos.h"
21 #include "dce.h"
22 #include "nonclient.h"
23 #include "debugtools.h"
24 #include "local.h"
25 #include "ldt.h"
26
27 DEFAULT_DEBUG_CHANNEL(win)
28
29 #define HAS_DLGFRAME(style,exStyle) \
30     (((exStyle) & WS_EX_DLGMODALFRAME) || \
31      (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
32
33 #define HAS_THICKFRAME(style) \
34     (((style) & WS_THICKFRAME) && \
35      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
36
37 #define  SWP_AGG_NOGEOMETRYCHANGE \
38     (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
39 #define  SWP_AGG_NOPOSCHANGE \
40     (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
41 #define  SWP_AGG_STATUSFLAGS \
42     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
43
44 #define EMPTYPOINT(pt)          ((*(LONG*)&(pt)) == -1)
45
46 #define PLACE_MIN               0x0001
47 #define PLACE_MAX               0x0002
48 #define PLACE_RECT              0x0004
49
50 #define SWP_EX_NOCOPY           0x0001
51 #define SWP_EX_PAINTSELF        0x0002
52 #define SWP_EX_NONCLIENT        0x0004
53
54 #define MINMAX_NOSWP            0x00010000
55
56 /* ----- internal variables ----- */
57
58 static HWND hwndPrevActive  = 0;  /* Previously active window */
59 static HWND hGlobalShellWindow=0; /*the shell*/
60 static HWND hGlobalTaskmanWindow=0;
61 static HWND hGlobalProgmanWindow=0;
62
63 static LPCSTR atomInternalPos;
64
65 extern HQUEUE16 hActiveQueue;
66
67 /***********************************************************************
68  *           WINPOS_CreateInternalPosAtom
69  */
70 BOOL WINPOS_CreateInternalPosAtom()
71 {
72     LPSTR str = "SysIP";
73     atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
74     return (atomInternalPos) ? TRUE : FALSE;
75 }
76
77 /***********************************************************************
78  *           WINPOS_CheckInternalPos
79  *
80  * Called when a window is destroyed.
81  */
82 void WINPOS_CheckInternalPos( WND* wndPtr )
83 {
84     LPINTERNALPOS lpPos;
85     MESSAGEQUEUE *pMsgQ = 0;
86     HWND hwnd = wndPtr->hwndSelf;
87
88     lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
89
90     /* Retrieve the message queue associated with this window */
91     pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
92     if ( !pMsgQ )
93     {
94         WARN("\tMessage queue not found. Exiting!\n" );
95         return;
96     }
97
98     if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
99
100     if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
101     {
102         PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
103         WARN("\tattempt to activate destroyed window!\n");
104     }
105
106     if( lpPos )
107     {
108         if( IsWindow(lpPos->hwndIconTitle) ) 
109             DestroyWindow( lpPos->hwndIconTitle );
110         HeapFree( SystemHeap, 0, lpPos );
111     }
112
113     QUEUE_Unlock( pMsgQ );
114     return;
115 }
116
117 /***********************************************************************
118  *           WINPOS_FindIconPos
119  *
120  * Find a suitable place for an iconic window.
121  */
122 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
123 {
124     RECT16 rectParent;
125     short x, y, xspacing, yspacing;
126
127     GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
128     if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
129         (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
130         return pt;  /* The icon already has a suitable position */
131
132     xspacing = GetSystemMetrics(SM_CXICONSPACING);
133     yspacing = GetSystemMetrics(SM_CYICONSPACING);
134
135     y = rectParent.bottom;
136     for (;;)
137     {
138         for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
139         {
140               /* Check if another icon already occupies this spot */
141             WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
142             while (childPtr)
143             {
144                 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
145                 {
146                     if ((childPtr->rectWindow.left < x + xspacing) &&
147                         (childPtr->rectWindow.right >= x) &&
148                         (childPtr->rectWindow.top <= y) &&
149                         (childPtr->rectWindow.bottom > y - yspacing))
150                         break;  /* There's a window in there */
151                 }
152                 WIN_UpdateWndPtr(&childPtr,childPtr->next);
153             }
154             WIN_ReleaseWndPtr(childPtr);
155             if (!childPtr) /* No window was found, so it's OK for us */
156             {
157                 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
158                 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
159                 return pt;
160             }
161         }
162         y -= yspacing;
163     }
164 }
165
166
167 /***********************************************************************
168  *           ArrangeIconicWindows16   (USER.170)
169  */
170 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent) 
171 {
172     return ArrangeIconicWindows(parent);
173 }
174 /***********************************************************************
175  *           ArrangeIconicWindows   (USER32.7)
176  */
177 UINT WINAPI ArrangeIconicWindows( HWND parent )
178 {
179     RECT rectParent;
180     HWND hwndChild;
181     INT x, y, xspacing, yspacing;
182
183     GetClientRect( parent, &rectParent );
184     x = rectParent.left;
185     y = rectParent.bottom;
186     xspacing = GetSystemMetrics(SM_CXICONSPACING);
187     yspacing = GetSystemMetrics(SM_CYICONSPACING);
188
189     hwndChild = GetWindow( parent, GW_CHILD );
190     while (hwndChild)
191     {
192         if( IsIconic( hwndChild ) )
193         {
194             WND *wndPtr = WIN_FindWndPtr(hwndChild);
195             
196             WINPOS_ShowIconTitle( wndPtr, FALSE );
197                
198             SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
199                             y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
200                             SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
201             if( IsWindow(hwndChild) )
202                 WINPOS_ShowIconTitle(wndPtr , TRUE );
203             WIN_ReleaseWndPtr(wndPtr);
204
205             if (x <= rectParent.right - xspacing) x += xspacing;
206             else
207             {
208                 x = rectParent.left;
209                 y -= yspacing;
210             }
211         }
212         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
213     }
214     return yspacing;
215 }
216
217
218 /***********************************************************************
219  *             SwitchToThisWindow16   (USER.172)
220  */
221 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
222 {
223     SwitchToThisWindow( hwnd, restore );
224 }
225
226
227 /***********************************************************************
228  *             SwitchToThisWindow   (USER32.539)
229  */
230 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
231 {
232     ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
233 }
234
235
236 /***********************************************************************
237  *           GetWindowRect16   (USER.32)
238  */
239 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect ) 
240 {
241     WND * wndPtr = WIN_FindWndPtr( hwnd ); 
242     if (!wndPtr) return;
243     
244     CONV_RECT32TO16( &wndPtr->rectWindow, rect );
245     if (wndPtr->dwStyle & WS_CHILD)
246         MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
247     WIN_ReleaseWndPtr(wndPtr);
248 }
249
250
251 /***********************************************************************
252  *           GetWindowRect   (USER32.308)
253  */
254 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect ) 
255 {
256     WND * wndPtr = WIN_FindWndPtr( hwnd ); 
257     if (!wndPtr) return FALSE;
258     
259     *rect = wndPtr->rectWindow;
260     if (wndPtr->dwStyle & WS_CHILD)
261         MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
262     WIN_ReleaseWndPtr(wndPtr);
263     return TRUE;
264 }
265
266
267 /***********************************************************************
268  *           GetWindowRgn 
269  */
270 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
271
272 {
273   RECT    rect;
274   WND * wndPtr = WIN_FindWndPtr( hwnd ); 
275   if (!wndPtr) return (ERROR);
276
277   FIXME("GetWindowRgn: doesn't really do regions\n"); 
278   
279   memset (&rect, 0, sizeof(rect));
280
281   GetWindowRect ( hwnd, &rect );
282
283   FIXME("Check whether a valid region here\n");
284
285   SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
286
287   WIN_ReleaseWndPtr(wndPtr);
288   return (SIMPLEREGION);
289 }
290
291 /***********************************************************************
292  *           SetWindowRgn 
293  */
294 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
295
296 {
297
298   FIXME("SetWindowRgn: stub\n"); 
299   return TRUE;
300 }
301
302 /***********************************************************************
303  *           SetWindowRgn16 
304  */
305 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
306
307 {
308
309   FIXME("SetWindowRgn16: stub\n"); 
310   return TRUE;
311 }
312
313
314 /***********************************************************************
315  *           GetClientRect16   (USER.33)
316  */
317 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect ) 
318 {
319     WND * wndPtr = WIN_FindWndPtr( hwnd );
320
321     rect->left = rect->top = rect->right = rect->bottom = 0;
322     if (wndPtr) 
323     {
324         rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
325         rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
326     }
327     WIN_ReleaseWndPtr(wndPtr);
328 }
329
330
331 /***********************************************************************
332  *           GetClientRect   (USER.220)
333  */
334 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect ) 
335 {
336     WND * wndPtr = WIN_FindWndPtr( hwnd );
337
338     rect->left = rect->top = rect->right = rect->bottom = 0;
339     if (!wndPtr) return FALSE;
340     rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
341     rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
342
343     WIN_ReleaseWndPtr(wndPtr);
344     return TRUE;
345 }
346
347
348 /*******************************************************************
349  *         ClientToScreen16   (USER.28)
350  */
351 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
352 {
353     MapWindowPoints16( hwnd, 0, lppnt, 1 );
354 }
355
356
357 /*******************************************************************
358  *         ClientToScreen   (USER32.52)
359  */
360 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
361 {
362     MapWindowPoints( hwnd, 0, lppnt, 1 );
363     return TRUE;
364 }
365
366
367 /*******************************************************************
368  *         ScreenToClient16   (USER.29)
369  */
370 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
371 {
372     MapWindowPoints16( 0, hwnd, lppnt, 1 );
373 }
374
375
376 /*******************************************************************
377  *         ScreenToClient   (USER32.447)
378  */
379 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
380 {
381     MapWindowPoints( 0, hwnd, lppnt, 1 );
382     return TRUE;
383 }
384
385
386 /***********************************************************************
387  *           WINPOS_WindowFromPoint
388  *
389  * Find the window and hittest for a given point.
390  */
391 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
392 {
393     WND *wndPtr;
394     INT16 hittest = HTERROR;
395     INT16 retvalue;
396     POINT16 xy = pt;
397
398    *ppWnd = NULL;
399     wndPtr = WIN_LockWndPtr(wndScope->child);
400    
401     if( wndScope->flags & WIN_MANAGED )
402     {
403         /* In managed mode we have to check wndScope first as it is also
404          * a window which received the mouse event. */
405
406         if( wndScope->dwStyle & WS_DISABLED )
407         {
408             retvalue = HTERROR;
409             goto end;
410         }
411         if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
412             pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
413             goto hittest;
414     }
415     MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
416
417     for (;;)
418     {
419         while (wndPtr)
420         {
421             /* If point is in window, and window is visible, and it  */
422             /* is enabled (or it's a top-level window), then explore */
423             /* its children. Otherwise, go to the next window.       */
424
425             if ((wndPtr->dwStyle & WS_VISIBLE) &&
426                 (!(wndPtr->dwStyle & WS_DISABLED) ||
427                  ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
428                 (xy.x >= wndPtr->rectWindow.left) &&
429                 (xy.x < wndPtr->rectWindow.right) &&
430                 (xy.y >= wndPtr->rectWindow.top) &&
431                 (xy.y < wndPtr->rectWindow.bottom))
432             {
433                 *ppWnd = wndPtr;  /* Got a suitable window */
434
435                 /* If window is minimized or disabled, return at once */
436                 if (wndPtr->dwStyle & WS_MINIMIZE)
437                 {
438                     retvalue = HTCAPTION;
439                     goto end;
440                 }
441                 if (wndPtr->dwStyle & WS_DISABLED)
442                 {
443                     retvalue = HTERROR;
444                     goto end;
445                 }
446
447                 /* If point is not in client area, ignore the children */
448                 if ((xy.x < wndPtr->rectClient.left) ||
449                     (xy.x >= wndPtr->rectClient.right) ||
450                     (xy.y < wndPtr->rectClient.top) ||
451                     (xy.y >= wndPtr->rectClient.bottom)) break;
452
453                 xy.x -= wndPtr->rectClient.left;
454                 xy.y -= wndPtr->rectClient.top;
455                 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
456             }
457             else
458             {
459                 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
460             }
461         }
462
463 hittest:
464         /* If nothing found, try the scope window */
465         if (!*ppWnd) *ppWnd = wndScope;
466
467         /* Send the WM_NCHITTEST message (only if to the same task) */
468         if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
469         {
470             hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST, 
471                                                  0, MAKELONG( pt.x, pt.y ) );
472             if (hittest != HTTRANSPARENT)
473             {
474                 retvalue = hittest;  /* Found the window */
475                 goto end;
476         }
477         }
478         else
479         {
480             retvalue = HTCLIENT;
481             goto end;
482         }
483
484         /* If no children found in last search, make point relative to parent */
485         if (!wndPtr)
486         {
487             xy.x += (*ppWnd)->rectClient.left;
488             xy.y += (*ppWnd)->rectClient.top;
489         }
490
491         /* Restart the search from the next sibling */
492         WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
493         *ppWnd = (*ppWnd)->parent;
494     }
495
496 end:
497     WIN_ReleaseWndPtr(wndPtr);
498     return retvalue;
499 }
500
501
502 /*******************************************************************
503  *         WindowFromPoint16   (USER.30)
504  */
505 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
506 {
507     WND *pWnd;
508     WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
509     WIN_ReleaseDesktop();
510     return pWnd->hwndSelf;
511 }
512
513
514 /*******************************************************************
515  *         WindowFromPoint   (USER32.582)
516  */
517 HWND WINAPI WindowFromPoint( POINT pt )
518 {
519     WND *pWnd;
520     POINT16 pt16;
521     CONV_POINT32TO16( &pt, &pt16 );
522     WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
523     WIN_ReleaseDesktop();
524     return (HWND)pWnd->hwndSelf;
525 }
526
527
528 /*******************************************************************
529  *         ChildWindowFromPoint16   (USER.191)
530  */
531 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
532 {
533     POINT pt32;
534     CONV_POINT16TO32( &pt, &pt32 );
535     return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
536 }
537
538
539 /*******************************************************************
540  *         ChildWindowFromPoint   (USER32.49)
541  */
542 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
543 {
544     /* pt is in the client coordinates */
545
546     WND* wnd = WIN_FindWndPtr(hwndParent);
547     RECT rect;
548     HWND retvalue;
549
550     if( !wnd ) return 0;
551
552     /* get client rect fast */
553     rect.top = rect.left = 0;
554     rect.right = wnd->rectClient.right - wnd->rectClient.left;
555     rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
556
557     if (!PtInRect( &rect, pt ))
558     {
559         retvalue = 0;
560         goto end;
561     }
562     WIN_UpdateWndPtr(&wnd,wnd->child);
563     while ( wnd )
564     {
565         if (PtInRect( &wnd->rectWindow, pt ))
566         {
567             retvalue = wnd->hwndSelf;
568             goto end;
569         }
570         WIN_UpdateWndPtr(&wnd,wnd->next);
571     }
572     retvalue = hwndParent;
573 end:
574     WIN_ReleaseWndPtr(wnd);
575     return retvalue;
576 }
577
578 /*******************************************************************
579  *         ChildWindowFromPointEx16   (USER.50)
580  */
581 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
582 {
583     POINT pt32;
584     CONV_POINT16TO32( &pt, &pt32 );
585     return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
586 }
587
588
589 /*******************************************************************
590  *         ChildWindowFromPointEx32   (USER32.50)
591  */
592 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
593                 UINT uFlags)
594 {
595     /* pt is in the client coordinates */
596
597     WND* wnd = WIN_FindWndPtr(hwndParent);
598     RECT rect;
599     HWND retvalue;
600
601     if( !wnd ) return 0;
602
603     /* get client rect fast */
604     rect.top = rect.left = 0;
605     rect.right = wnd->rectClient.right - wnd->rectClient.left;
606     rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
607
608     if (!PtInRect( &rect, pt ))
609     {
610         retvalue = 0;
611         goto end;
612     }
613     WIN_UpdateWndPtr(&wnd,wnd->child);
614
615     while ( wnd )
616     {
617         if (PtInRect( &wnd->rectWindow, pt )) {
618                 if ( (uFlags & CWP_SKIPINVISIBLE) && 
619                                 !(wnd->dwStyle & WS_VISIBLE) );
620                 else if ( (uFlags & CWP_SKIPDISABLED) && 
621                                 (wnd->dwStyle & WS_DISABLED) );
622                 else if ( (uFlags & CWP_SKIPTRANSPARENT) && 
623                                 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
624                 else
625                 {
626                     retvalue = wnd->hwndSelf;
627                     goto end;
628                 }
629                 
630         }
631         WIN_UpdateWndPtr(&wnd,wnd->next);
632     }
633     retvalue = hwndParent;
634 end:
635     WIN_ReleaseWndPtr(wnd);
636     return retvalue;
637 }
638
639
640 /*******************************************************************
641  *         WINPOS_GetWinOffset
642  *
643  * Calculate the offset between the origin of the two windows. Used
644  * to implement MapWindowPoints.
645  */
646 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
647                                  POINT *offset )
648 {
649     WND * wndPtr = 0;
650
651     offset->x = offset->y = 0;
652     if (hwndFrom == hwndTo ) return;
653
654       /* Translate source window origin to screen coords */
655     if (hwndFrom)
656     {
657         if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
658         {
659             ERR("bad hwndFrom = %04x\n",hwndFrom);
660             return;
661         }
662         while (wndPtr->parent)
663         {
664             offset->x += wndPtr->rectClient.left;
665             offset->y += wndPtr->rectClient.top;
666             WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
667         }
668         WIN_ReleaseWndPtr(wndPtr);
669     }
670
671       /* Translate origin to destination window coords */
672     if (hwndTo)
673     {
674         if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
675         {
676             ERR("bad hwndTo = %04x\n", hwndTo );
677             return;
678         }
679         while (wndPtr->parent)
680         {
681             offset->x -= wndPtr->rectClient.left;
682             offset->y -= wndPtr->rectClient.top;
683             WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
684         }    
685         WIN_ReleaseWndPtr(wndPtr);
686     }
687 }
688
689
690 /*******************************************************************
691  *         MapWindowPoints16   (USER.258)
692  */
693 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
694                                LPPOINT16 lppt, UINT16 count )
695 {
696     POINT offset;
697
698     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
699     while (count--)
700     {
701         lppt->x += offset.x;
702         lppt->y += offset.y;
703         lppt++;
704     }
705 }
706
707
708 /*******************************************************************
709  *         MapWindowPoints   (USER32.386)
710  */
711 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
712                                LPPOINT lppt, UINT count )
713 {
714     POINT offset;
715
716     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
717     while (count--)
718     {
719         lppt->x += offset.x;
720         lppt->y += offset.y;
721         lppt++;
722     }
723     return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
724 }
725
726
727 /***********************************************************************
728  *           IsIconic16   (USER.31)
729  */
730 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
731 {
732     return IsIconic(hWnd);
733 }
734
735
736 /***********************************************************************
737  *           IsIconic   (USER32.345)
738  */
739 BOOL WINAPI IsIconic(HWND hWnd)
740 {
741     BOOL retvalue;
742     WND * wndPtr = WIN_FindWndPtr(hWnd);
743     if (wndPtr == NULL) return FALSE;
744     retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
745     WIN_ReleaseWndPtr(wndPtr);
746     return retvalue;
747 }
748  
749  
750 /***********************************************************************
751  *           IsZoomed   (USER.272)
752  */
753 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
754 {
755     return IsZoomed(hWnd);
756 }
757
758
759 /***********************************************************************
760  *           IsZoomed   (USER.352)
761  */
762 BOOL WINAPI IsZoomed(HWND hWnd)
763 {
764     BOOL retvalue;
765     WND * wndPtr = WIN_FindWndPtr(hWnd);
766     if (wndPtr == NULL) return FALSE;
767     retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
768     WIN_ReleaseWndPtr(wndPtr);
769     return retvalue;
770 }
771
772
773 /*******************************************************************
774  *         GetActiveWindow    (USER.60)
775  */
776 HWND16 WINAPI GetActiveWindow16(void)
777 {
778     return (HWND16)GetActiveWindow();
779 }
780
781 /*******************************************************************
782  *         GetActiveWindow    (USER32.205)
783  */
784 HWND WINAPI GetActiveWindow(void)
785 {
786     MESSAGEQUEUE *pCurMsgQ = 0;
787     HWND hwndActive = 0;
788
789     /* Get the messageQ for the current thread */
790     if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
791 {
792         WARN("\tCurrent message queue not found. Exiting!\n" );
793         return 0;
794     }
795
796     /* Return the current active window from the perQ data of the current message Q */
797     hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
798
799     QUEUE_Unlock( pCurMsgQ );
800     return hwndActive;
801 }
802
803
804 /*******************************************************************
805  *         WINPOS_CanActivate
806  */
807 static BOOL WINPOS_CanActivate(WND* pWnd)
808 {
809     if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD)) 
810         == WS_VISIBLE) ) return TRUE;
811     return FALSE;
812 }
813
814
815 /*******************************************************************
816  *         SetActiveWindow16    (USER.59)
817  */
818 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
819 {
820     return SetActiveWindow(hwnd);
821 }
822
823
824 /*******************************************************************
825  *         SetActiveWindow    (USER32.463)
826  */
827 HWND WINAPI SetActiveWindow( HWND hwnd )
828 {
829     HWND prev = 0;
830     WND *wndPtr = WIN_FindWndPtr( hwnd );
831     MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
832
833     if ( !WINPOS_CanActivate(wndPtr) )
834     {
835         prev = 0;
836         goto end;
837     }
838
839     /* Get the messageQ for the current thread */
840     if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
841     {
842         WARN("\tCurrent message queue not found. Exiting!\n" );
843         goto CLEANUP;
844     }
845     
846     /* Retrieve the message queue associated with this window */
847     pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
848     if ( !pMsgQ )
849     {
850         WARN("\tWindow message queue not found. Exiting!\n" );
851         goto CLEANUP;
852     }
853
854     /* Make sure that the window is associated with the calling threads
855      * message queue. It must share the same perQ data.
856      */
857     
858     if ( pCurMsgQ->pQData != pMsgQ->pQData )
859         goto CLEANUP;
860     
861     /* Save current active window */
862     prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
863     
864     WINPOS_SetActiveWindow( hwnd, 0, 0 );
865
866 CLEANUP:
867     /* Unlock the queues before returning */
868     if ( pMsgQ )
869         QUEUE_Unlock( pMsgQ );
870     if ( pCurMsgQ )
871         QUEUE_Unlock( pCurMsgQ );
872     
873 end:
874     WIN_ReleaseWndPtr(wndPtr);
875     return prev;
876 }
877
878
879 /*******************************************************************
880  *         GetForegroundWindow16    (USER.608)
881  */
882 HWND16 WINAPI GetForegroundWindow16(void)
883 {
884     return (HWND16)GetForegroundWindow();
885 }
886
887
888 /*******************************************************************
889  *         SetForegroundWindow16    (USER.609)
890  */
891 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
892 {
893     return SetForegroundWindow( hwnd );
894 }
895
896
897 /*******************************************************************
898  *         GetForegroundWindow    (USER32.241)
899  */
900 HWND WINAPI GetForegroundWindow(void)
901 {
902     HWND hwndActive = 0;
903
904     /* Get the foreground window (active window of hActiveQueue) */
905     if ( hActiveQueue )
906     {
907         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
908         if ( pActiveQueue )
909             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
910
911         QUEUE_Unlock( pActiveQueue );
912     }
913
914     return hwndActive;
915 }
916
917 /*******************************************************************
918  *         SetForegroundWindow    (USER32.482)
919  */
920 BOOL WINAPI SetForegroundWindow( HWND hwnd )
921 {
922     return WINPOS_ChangeActiveWindow( hwnd, FALSE );
923 }
924
925
926 /*******************************************************************
927  *         GetShellWindow16    (USER.600)
928  */
929 HWND16 WINAPI GetShellWindow16(void)
930 {
931     return GetShellWindow();
932 }
933
934 /*******************************************************************
935  *         SetShellWindow    (USER32.504)
936  */
937 HWND WINAPI SetShellWindow(HWND hwndshell)
938 {   WARN("(hWnd=%08x) semi stub\n",hwndshell );
939
940     hGlobalShellWindow = hwndshell;
941     return hGlobalShellWindow;
942 }
943
944
945 /*******************************************************************
946  *         GetShellWindow    (USER32.287)
947  */
948 HWND WINAPI GetShellWindow(void)
949 {   WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
950
951     return hGlobalShellWindow;
952 }
953
954
955 /***********************************************************************
956  *           BringWindowToTop16   (USER.45)
957  */
958 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
959 {
960     return BringWindowToTop(hwnd);
961 }
962
963
964 /***********************************************************************
965  *           BringWindowToTop   (USER32.11)
966  */
967 BOOL WINAPI BringWindowToTop( HWND hwnd )
968 {
969     return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
970 }
971
972
973 /***********************************************************************
974  *           MoveWindow16   (USER.56)
975  */
976 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
977                             BOOL16 repaint )
978 {
979     return MoveWindow(hwnd,x,y,cx,cy,repaint);
980 }
981
982
983 /***********************************************************************
984  *           MoveWindow   (USER32.399)
985  */
986 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
987                             BOOL repaint )
988 {    
989     int flags = SWP_NOZORDER | SWP_NOACTIVATE;
990     if (!repaint) flags |= SWP_NOREDRAW;
991     TRACE("%04x %d,%d %dx%d %d\n", 
992             hwnd, x, y, cx, cy, repaint );
993     return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
994 }
995
996 /***********************************************************************
997  *           WINPOS_InitInternalPos
998  */
999 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt, 
1000                                              LPRECT restoreRect )
1001 {
1002     LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1003                                                       atomInternalPos );
1004     if( !lpPos )
1005     {
1006         /* this happens when the window is minimized/maximized 
1007          * for the first time (rectWindow is not adjusted yet) */
1008
1009         lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1010         if( !lpPos ) return NULL;
1011
1012         SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1013         lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1014         CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1015         *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1016     }
1017
1018     if( wnd->dwStyle & WS_MINIMIZE ) 
1019         CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1020     else if( wnd->dwStyle & WS_MAXIMIZE ) 
1021         CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1022     else if( restoreRect ) 
1023         CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1024
1025     return lpPos;
1026 }
1027
1028 /***********************************************************************
1029  *           WINPOS_RedrawIconTitle
1030  */
1031 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1032 {
1033     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1034     if( lpPos )
1035     {
1036         if( lpPos->hwndIconTitle )
1037         {
1038             SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1039             InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1040             return TRUE;
1041         }
1042     }
1043     return FALSE;
1044 }
1045
1046 /***********************************************************************
1047  *           WINPOS_ShowIconTitle
1048  */
1049 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1050 {
1051     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1052
1053     if( lpPos && !(pWnd->flags & WIN_MANAGED))
1054     {
1055         HWND16 hWnd = lpPos->hwndIconTitle;
1056
1057         TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1058
1059         if( !hWnd )
1060             lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1061         if( bShow )
1062         {
1063             if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL) 
1064             {
1065                 if( !(pWnd->dwStyle & WS_VISIBLE) )
1066                 {
1067                    SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1068                    SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1069                                  SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1070                 }
1071                 WIN_ReleaseWndPtr(pWnd);
1072             }
1073         }
1074         else ShowWindow( hWnd, SW_HIDE );
1075     }
1076     return FALSE;
1077 }
1078
1079 /*******************************************************************
1080  *           WINPOS_GetMinMaxInfo
1081  *
1082  * Get the minimized and maximized information for a window.
1083  */
1084 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1085                            POINT *minTrack, POINT *maxTrack )
1086 {
1087     LPINTERNALPOS lpPos;
1088     MINMAXINFO MinMax;
1089     INT xinc, yinc;
1090
1091     /* Compute default values */
1092
1093     MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1094     MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1095     MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1096     MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1097     MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1098     MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1099
1100     if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1101     else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1102     {
1103         xinc = GetSystemMetrics(SM_CXDLGFRAME);
1104         yinc = GetSystemMetrics(SM_CYDLGFRAME);
1105     }
1106     else
1107     {
1108         xinc = yinc = 0;
1109         if (HAS_THICKFRAME(wndPtr->dwStyle))
1110         {
1111             xinc += GetSystemMetrics(SM_CXFRAME);
1112             yinc += GetSystemMetrics(SM_CYFRAME);
1113         }
1114         if (wndPtr->dwStyle & WS_BORDER)
1115         {
1116             xinc += GetSystemMetrics(SM_CXBORDER);
1117             yinc += GetSystemMetrics(SM_CYBORDER);
1118         }
1119     }
1120     MinMax.ptMaxSize.x += 2 * xinc;
1121     MinMax.ptMaxSize.y += 2 * yinc;
1122
1123     lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1124     if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1125         CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1126     else
1127     {
1128         MinMax.ptMaxPosition.x = -xinc;
1129         MinMax.ptMaxPosition.y = -yinc;
1130     }
1131
1132     SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1133
1134       /* Some sanity checks */
1135
1136     TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1137                       MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1138                       MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1139                       MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1140                       MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1141     MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
1142                                    MinMax.ptMinTrackSize.x );
1143     MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
1144                                    MinMax.ptMinTrackSize.y );
1145
1146     if (maxSize) *maxSize = MinMax.ptMaxSize;
1147     if (maxPos) *maxPos = MinMax.ptMaxPosition;
1148     if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1149     if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1150 }
1151
1152 /***********************************************************************
1153  *           WINPOS_MinMaximize
1154  *
1155  * Fill in lpRect and return additional flags to be used with SetWindowPos().
1156  * This function assumes that 'cmd' is different from the current window
1157  * state.
1158  */
1159 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1160 {
1161     UINT swpFlags = 0;
1162     POINT pt, size;
1163     LPINTERNALPOS lpPos;
1164
1165     TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1166
1167     size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1168     lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1169
1170     if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1171     {
1172         if( wndPtr->dwStyle & WS_MINIMIZE )
1173         {
1174             if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1175                 return (SWP_NOSIZE | SWP_NOMOVE);
1176             swpFlags |= SWP_NOCOPYBITS;
1177         }
1178         switch( cmd )
1179         {
1180             case SW_MINIMIZE:
1181                  if( wndPtr->dwStyle & WS_MAXIMIZE)
1182                  {
1183                      wndPtr->flags |= WIN_RESTORE_MAX;
1184                      wndPtr->dwStyle &= ~WS_MAXIMIZE;
1185                  }
1186                  else
1187                      wndPtr->flags &= ~WIN_RESTORE_MAX;
1188                  wndPtr->dwStyle |= WS_MINIMIZE;
1189
1190                  if( wndPtr->flags & WIN_NATIVE )
1191                      if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1192                          swpFlags |= MINMAX_NOSWP;
1193
1194                  lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1195
1196                  SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1197                                     GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1198                  swpFlags |= SWP_NOCOPYBITS;
1199                  break;
1200
1201             case SW_MAXIMIZE:
1202                 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1203                 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1204                 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1205
1206                  if( wndPtr->dwStyle & WS_MINIMIZE )
1207                  {
1208                      if( wndPtr->flags & WIN_NATIVE )
1209                          if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1210                              swpFlags |= MINMAX_NOSWP;
1211
1212                      WINPOS_ShowIconTitle( wndPtr, FALSE );
1213                      wndPtr->dwStyle &= ~WS_MINIMIZE;
1214                  }
1215                  wndPtr->dwStyle |= WS_MAXIMIZE;
1216
1217                  SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1218                                     size.x, size.y );
1219                  break;
1220
1221             case SW_RESTORE:
1222                  if( wndPtr->dwStyle & WS_MINIMIZE )
1223                  {
1224                      if( wndPtr->flags & WIN_NATIVE )
1225                          if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1226                              swpFlags |= MINMAX_NOSWP;
1227
1228                      wndPtr->dwStyle &= ~WS_MINIMIZE;
1229                      WINPOS_ShowIconTitle( wndPtr, FALSE );
1230
1231                      if( wndPtr->flags & WIN_RESTORE_MAX)
1232                      {
1233                          /* Restore to maximized position */
1234                          CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1235                          WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1236                          CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1237                          wndPtr->dwStyle |= WS_MAXIMIZE;
1238                          SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1239                          break;
1240                      }
1241                  } 
1242                  else 
1243                      if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1244                      else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1245
1246                  /* Restore to normal position */
1247
1248                 *lpRect = lpPos->rectNormal; 
1249                  lpRect->right -= lpRect->left; 
1250                  lpRect->bottom -= lpRect->top;
1251
1252                  break;
1253         }
1254     } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1255     return swpFlags;
1256 }
1257
1258 /***********************************************************************
1259  *           ShowWindowAsync   (USER32.535)
1260  *
1261  * doesn't wait; returns immediately.
1262  * used by threads to toggle windows in other (possibly hanging) threads
1263  */
1264 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1265 {
1266     /* FIXME: does ShowWindow() return immediately ? */
1267     return ShowWindow(hwnd, cmd);
1268 }
1269
1270
1271 /***********************************************************************
1272  *           ShowWindow16   (USER.42)
1273  */
1274 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd ) 
1275 {    
1276     return ShowWindow(hwnd,cmd);
1277 }
1278
1279
1280 /***********************************************************************
1281  *           ShowWindow   (USER32.534)
1282  */
1283 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd ) 
1284 {    
1285     WND*        wndPtr = WIN_FindWndPtr( hwnd );
1286     BOOL        wasVisible, showFlag;
1287     RECT16      newPos = {0, 0, 0, 0};
1288     UINT        swp = 0;
1289
1290     if (!wndPtr) return FALSE;
1291
1292     TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1293
1294     wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1295
1296     switch(cmd)
1297     {
1298         case SW_HIDE:
1299             if (!wasVisible) goto END;;
1300             swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
1301                         SWP_NOACTIVATE | SWP_NOZORDER;
1302             if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
1303             {
1304                 /* Revert focus to parent */
1305                 SetFocus( GetParent(hwnd) );
1306             }
1307             break;
1308
1309         case SW_SHOWMINNOACTIVE:
1310             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1311             /* fall through */
1312         case SW_SHOWMINIMIZED:
1313             swp |= SWP_SHOWWINDOW;
1314             /* fall through */
1315         case SW_MINIMIZE:
1316             swp |= SWP_FRAMECHANGED;
1317             if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1318                  swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1319             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1320             break;
1321
1322         case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1323             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1324             if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1325                  swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1326             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1327             break;
1328
1329         case SW_SHOWNA:
1330             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1331             /* fall through */
1332         case SW_SHOW:
1333             swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1334
1335             /*
1336              * ShowWindow has a little peculiar behavior that if the
1337              * window is already the topmost window, it will not
1338              * activate it.
1339              */
1340             if (GetTopWindow((HWND)0)==hwnd)
1341               swp |= SWP_NOACTIVATE;
1342
1343             break;
1344
1345         case SW_SHOWNOACTIVATE:
1346             swp |= SWP_NOZORDER;
1347             if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1348             /* fall through */
1349         case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
1350         case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1351         case SW_RESTORE:
1352             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1353
1354             if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1355                  swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1356             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1357             break;
1358     }
1359
1360     showFlag = (cmd != SW_HIDE);
1361     if (showFlag != wasVisible)
1362     {
1363         SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1364         if (!IsWindow( hwnd )) goto END;
1365     }
1366
1367     if ((wndPtr->dwStyle & WS_CHILD) &&
1368         !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1369         (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1370     {
1371         /* Don't call SetWindowPos() on invisible child windows */
1372         if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1373         else wndPtr->dwStyle |= WS_VISIBLE;
1374     }
1375     else
1376     {
1377         /* We can't activate a child window */
1378         if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1379         if (!(swp & MINMAX_NOSWP))
1380             SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top, 
1381                                           newPos.right, newPos.bottom, LOWORD(swp) );
1382         if (!IsWindow( hwnd )) goto END;
1383         else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1384     }
1385
1386     if (wndPtr->flags & WIN_NEED_SIZE)
1387     {
1388         /* should happen only in CreateWindowEx() */
1389         int wParam = SIZE_RESTORED;
1390
1391         wndPtr->flags &= ~WIN_NEED_SIZE;
1392         if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1393         else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1394         SendMessageA( hwnd, WM_SIZE, wParam,
1395                      MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1396                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1397         SendMessageA( hwnd, WM_MOVE, 0,
1398                    MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1399     }
1400
1401 END:
1402     WIN_ReleaseWndPtr(wndPtr);
1403     return wasVisible;
1404 }
1405
1406
1407 /***********************************************************************
1408  *           GetInternalWindowPos16   (USER.460)
1409  */
1410 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1411                                       LPPOINT16 ptIcon )
1412 {
1413     WINDOWPLACEMENT16 wndpl;
1414     if (GetWindowPlacement16( hwnd, &wndpl )) 
1415     {
1416         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1417         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1418         return wndpl.showCmd;
1419     }
1420     return 0;
1421 }
1422
1423
1424 /***********************************************************************
1425  *           GetInternalWindowPos   (USER32.245)
1426  */
1427 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1428                                       LPPOINT ptIcon )
1429 {
1430     WINDOWPLACEMENT wndpl;
1431     if (GetWindowPlacement( hwnd, &wndpl ))
1432     {
1433         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1434         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1435         return wndpl.showCmd;
1436     }
1437     return 0;
1438 }
1439
1440 /***********************************************************************
1441  *           GetWindowPlacement16   (USER.370)
1442  */
1443 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1444 {
1445     WND *pWnd = WIN_FindWndPtr( hwnd );
1446     LPINTERNALPOS lpPos;
1447     
1448     if(!pWnd ) return FALSE;
1449
1450     lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1451                              *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1452         wndpl->length  = sizeof(*wndpl);
1453         if( pWnd->dwStyle & WS_MINIMIZE )
1454             wndpl->showCmd = SW_SHOWMINIMIZED;
1455         else 
1456             wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1457                              ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1458         if( pWnd->flags & WIN_RESTORE_MAX )
1459             wndpl->flags = WPF_RESTORETOMAXIMIZED;
1460         else
1461             wndpl->flags = 0;
1462         wndpl->ptMinPosition = lpPos->ptIconPos;
1463         wndpl->ptMaxPosition = lpPos->ptMaxPos;
1464         wndpl->rcNormalPosition = lpPos->rectNormal;
1465
1466     WIN_ReleaseWndPtr(pWnd);
1467         return TRUE;
1468     }
1469
1470
1471 /***********************************************************************
1472  *           GetWindowPlacement   (USER32.307)
1473  *
1474  * Win95:
1475  * Fails if wndpl->length of Win95 (!) apps is invalid.
1476  */
1477 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1478 {
1479     if( pwpl32 )
1480     {
1481         WINDOWPLACEMENT16 wpl;
1482         wpl.length = sizeof(wpl);
1483         if( GetWindowPlacement16( hwnd, &wpl ) )
1484         {
1485             pwpl32->length = sizeof(*pwpl32);
1486             pwpl32->flags = wpl.flags;
1487             pwpl32->showCmd = wpl.showCmd;
1488             CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1489             CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1490             CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1491             return TRUE;
1492         }
1493     }
1494     return FALSE;
1495 }
1496
1497
1498 /***********************************************************************
1499  *           WINPOS_SetPlacement
1500  */
1501 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1502                                                 UINT flags )
1503 {
1504     WND *pWnd = WIN_FindWndPtr( hwnd );
1505     if( pWnd )
1506     {
1507         LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1508                              *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1509
1510         if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1511         if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1512         if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1513
1514         if( pWnd->dwStyle & WS_MINIMIZE )
1515         {
1516             WINPOS_ShowIconTitle( pWnd, FALSE );
1517             if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1518                 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1519                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1520         } 
1521         else if( pWnd->dwStyle & WS_MAXIMIZE )
1522         {
1523             if( !EMPTYPOINT(lpPos->ptMaxPos) )
1524                 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1525                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1526         }
1527         else if( flags & PLACE_RECT )
1528                 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1529                                 lpPos->rectNormal.right - lpPos->rectNormal.left,
1530                                 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1531                                 SWP_NOZORDER | SWP_NOACTIVATE );
1532
1533         ShowWindow( hwnd, wndpl->showCmd );
1534         if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1535         {
1536             if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1537
1538             /* SDK: ...valid only the next time... */
1539             if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1540         }
1541         WIN_ReleaseWndPtr(pWnd);
1542         return TRUE;
1543     }
1544     return FALSE;
1545 }
1546
1547
1548 /***********************************************************************
1549  *           SetWindowPlacement16   (USER.371)
1550  */
1551 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1552 {
1553     return WINPOS_SetPlacement( hwnd, wndpl,
1554                                 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1555 }
1556
1557 /***********************************************************************
1558  *           SetWindowPlacement   (USER32.519)
1559  *
1560  * Win95:
1561  * Fails if wndpl->length of Win95 (!) apps is invalid.
1562  */
1563 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1564 {
1565     if( pwpl32 )
1566     {
1567         WINDOWPLACEMENT16 wpl;
1568
1569         wpl.length = sizeof(WINDOWPLACEMENT16);
1570         wpl.flags = pwpl32->flags;
1571         wpl.showCmd = pwpl32->showCmd;
1572         wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1573         wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1574         wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1575         wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1576         wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1577         wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1578         wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1579         wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1580
1581         return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1582     }
1583     return FALSE;
1584 }
1585
1586
1587 /***********************************************************************
1588  *           SetInternalWindowPos16   (USER.461)
1589  */
1590 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1591                                     LPRECT16 rect, LPPOINT16 pt )
1592 {
1593     if( IsWindow16(hwnd) )
1594     {
1595         WINDOWPLACEMENT16 wndpl;
1596         UINT flags;
1597
1598         wndpl.length  = sizeof(wndpl);
1599         wndpl.showCmd = showCmd;
1600         wndpl.flags = flags = 0;
1601
1602         if( pt )
1603         {
1604             flags |= PLACE_MIN;
1605             wndpl.flags |= WPF_SETMINPOSITION;
1606             wndpl.ptMinPosition = *pt;
1607         }
1608         if( rect )
1609         {
1610             flags |= PLACE_RECT;
1611             wndpl.rcNormalPosition = *rect;
1612         }
1613         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1614     }
1615 }
1616
1617
1618 /***********************************************************************
1619  *           SetInternalWindowPos   (USER32.483)
1620  */
1621 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1622                                     LPRECT rect, LPPOINT pt )
1623 {
1624     if( IsWindow(hwnd) )
1625     {
1626         WINDOWPLACEMENT16 wndpl;
1627         UINT flags;
1628
1629         wndpl.length  = sizeof(wndpl);
1630         wndpl.showCmd = showCmd;
1631         wndpl.flags = flags = 0;
1632
1633         if( pt )
1634         {
1635             flags |= PLACE_MIN;
1636             wndpl.flags |= WPF_SETMINPOSITION;
1637             CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1638         }
1639         if( rect )
1640         {
1641             flags |= PLACE_RECT;
1642             CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1643         }
1644         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1645     }
1646 }
1647
1648 /*******************************************************************
1649  *         WINPOS_SetActiveWindow
1650  *
1651  * SetActiveWindow() back-end. This is the only function that
1652  * can assign active status to a window. It must be called only
1653  * for the top level windows.
1654  */
1655 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1656 {
1657     CBTACTIVATESTRUCT16* cbtStruct;
1658     WND*     wndPtr=0, *wndTemp;
1659     HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1660     MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1661     WORD     wIconized = 0;
1662     HWND     hwndActive = 0;
1663     BOOL     bRet = 0;
1664
1665     TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1666
1667     /* Get current active window from the active queue */
1668     if ( hActiveQueue )
1669     {
1670         pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1671         if ( pOldActiveQueue )
1672             hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1673     }
1674
1675     /* paranoid checks */
1676     if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1677         goto CLEANUP_END;
1678
1679 /*  if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1680  *      return 0;
1681  */
1682     wndPtr = WIN_FindWndPtr(hWnd);
1683     hOldActiveQueue = hActiveQueue;
1684
1685     if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1686     {
1687         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1688         WIN_ReleaseWndPtr(wndTemp);
1689     }
1690     else
1691         TRACE("no current active window.\n");
1692
1693     /* call CBT hook chain */
1694     if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1695     {
1696         cbtStruct->fMouse     = fMouse;
1697         cbtStruct->hWndActive = hwndActive;
1698         bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1699                                      (LPARAM)SEGPTR_GET(cbtStruct) );
1700         SEGPTR_FREE(cbtStruct);
1701         if (bRet) goto CLEANUP_END;
1702     }
1703
1704     /* set prev active wnd to current active wnd and send notification */
1705     if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1706     {
1707         MESSAGEQUEUE *pTempActiveQueue = 0;
1708         
1709         if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1710         {
1711             if (GetSysModalWindow16() != hWnd) 
1712                 goto CLEANUP_END;
1713             /* disregard refusal if hWnd is sysmodal */
1714         }
1715
1716         SendMessageA( hwndPrevActive, WM_ACTIVATE,
1717                         MAKEWPARAM( WA_INACTIVE, wIconized ),
1718                         (LPARAM)hWnd );
1719
1720         /* check if something happened during message processing
1721          * (global active queue may have changed)
1722          */
1723         pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1724         if(!pTempActiveQueue)
1725             goto CLEANUP_END;
1726
1727         hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1728         QUEUE_Unlock( pTempActiveQueue );
1729         if( hwndPrevActive != hwndActive )
1730             goto CLEANUP_END;
1731     }
1732
1733     /* Set new active window in the message queue */
1734     hwndActive = hWnd;
1735     if ( wndPtr )
1736     {
1737         pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1738         if ( pNewActiveQueue )
1739             PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1740     }
1741     else /* have to do this or MDI frame activation goes to hell */
1742         if( pOldActiveQueue )
1743             PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1744
1745     /* send palette messages */
1746     if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1747         SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1748
1749     /* if prev wnd is minimized redraw icon title */
1750     if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1751
1752     /* managed windows will get ConfigureNotify event */  
1753     if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1754     {
1755         /* check Z-order and bring hWnd to the top */
1756         for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1757         {
1758             if (wndTemp->dwStyle & WS_VISIBLE) break;
1759         }
1760         WIN_ReleaseDesktop();
1761         WIN_ReleaseWndPtr(wndTemp);
1762
1763         if( wndTemp != wndPtr )
1764             SetWindowPos(hWnd, HWND_TOP, 0,0,0,0, 
1765                            SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1766         if (!IsWindow(hWnd))  
1767             goto CLEANUP;
1768     }
1769
1770     /* Get a handle to the new active queue */
1771     hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1772
1773     /* send WM_ACTIVATEAPP if necessary */
1774     if (hOldActiveQueue != hNewActiveQueue)
1775     {
1776         WND **list, **ppWnd;
1777         WND *pDesktop = WIN_GetDesktop();
1778
1779         if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1780         {
1781             for (ppWnd = list; *ppWnd; ppWnd++)
1782             {
1783                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1784
1785                 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1786                    SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1787                                    0, QUEUE_GetQueueTask(hNewActiveQueue) );
1788             }
1789             WIN_ReleaseWinArray(list);
1790         }
1791
1792         hActiveQueue = hNewActiveQueue;
1793
1794         if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1795         {
1796             for (ppWnd = list; *ppWnd; ppWnd++)
1797             {
1798                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1799
1800                 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1801                    SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1802                                   1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1803             }
1804             WIN_ReleaseWinArray(list);
1805         }
1806         WIN_ReleaseDesktop();
1807         
1808         if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1809     }
1810
1811     if (hWnd)
1812     {
1813         /* walk up to the first unowned window */
1814         wndTemp = WIN_LockWndPtr(wndPtr);
1815         while (wndTemp->owner)
1816         {
1817             WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1818         }
1819         /* and set last active owned popup */
1820         wndTemp->hwndLastActive = hWnd;
1821
1822         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1823         WIN_ReleaseWndPtr(wndTemp);
1824         SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1825         SendMessageA( hWnd, WM_ACTIVATE,
1826                  MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1827                  (LPARAM)hwndPrevActive );
1828         if( !IsWindow(hWnd) ) goto CLEANUP;
1829     }
1830
1831     /* change focus if possible */
1832     if ( fChangeFocus )
1833     {
1834         if ( pNewActiveQueue )
1835         {
1836             HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1837
1838             if ( WIN_GetTopParent( hOldFocus ) != hwndActive )
1839                 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus, 
1840                                    (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1841                                    0 : hwndActive );
1842         }
1843
1844         if ( pOldActiveQueue && 
1845              ( !pNewActiveQueue || 
1846                 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1847         {
1848             HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1849             if ( hOldFocus )
1850                 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1851         }
1852     }
1853
1854     if( !hwndPrevActive && wndPtr )
1855         (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1856
1857     /* if active wnd is minimized redraw icon title */
1858     if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1859
1860     bRet = (hWnd == hwndActive);  /* Success? */
1861     
1862 CLEANUP: /* Unlock the message queues before returning */
1863
1864     if ( pNewActiveQueue )
1865         QUEUE_Unlock( pNewActiveQueue );
1866
1867 CLEANUP_END:
1868
1869     if ( pOldActiveQueue )
1870         QUEUE_Unlock( pOldActiveQueue );
1871
1872     WIN_ReleaseWndPtr(wndPtr);
1873     return bRet;
1874 }
1875
1876 /*******************************************************************
1877  *         WINPOS_ActivateOtherWindow
1878  *
1879  *  Activates window other than pWnd.
1880  */
1881 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1882 {
1883   BOOL  bRet = 0;
1884   WND*          pWndTo = NULL;
1885     HWND       hwndActive = 0;
1886
1887     /* Get current active window from the active queue */
1888     if ( hActiveQueue )
1889     {
1890         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1891         if ( pActiveQueue )
1892         {
1893             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1894             QUEUE_Unlock( pActiveQueue );
1895         }
1896     }
1897
1898   if( pWnd->hwndSelf == hwndPrevActive )
1899       hwndPrevActive = 0;
1900
1901   if( hwndActive != pWnd->hwndSelf && 
1902     ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1903       return 0;
1904
1905   if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1906       !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) ) 
1907   {
1908       WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1909
1910       WIN_ReleaseWndPtr(pWndTo);
1911       pWndTo = WIN_FindWndPtr(hwndPrevActive);
1912
1913       while( !WINPOS_CanActivate(pWndTo) ) 
1914       {
1915          /* by now owned windows should've been taken care of */
1916           WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1917           WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1918           if( !pWndTo ) break;
1919       }
1920       WIN_ReleaseWndPtr(pWndPtr);
1921   }
1922
1923   bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1924
1925   /* switch desktop queue to current active */
1926   if( pWndTo )
1927   {
1928       WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1929       WIN_ReleaseWndPtr(pWndTo);
1930       WIN_ReleaseDesktop();
1931   }
1932
1933   hwndPrevActive = 0;
1934   return bRet;  
1935 }
1936
1937 /*******************************************************************
1938  *         WINPOS_ChangeActiveWindow
1939  *
1940  */
1941 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1942 {
1943     WND *wndPtr, *wndTemp;
1944     BOOL retvalue;
1945     HWND hwndActive = 0;
1946
1947     /* Get current active window from the active queue */
1948     if ( hActiveQueue )
1949     {
1950         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1951         if ( pActiveQueue )
1952         {
1953             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1954             QUEUE_Unlock( pActiveQueue );
1955         }
1956     }
1957
1958     if (!hWnd)
1959         return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1960
1961     wndPtr = WIN_FindWndPtr(hWnd);
1962     if( !wndPtr ) return FALSE;
1963
1964     /* child windows get WM_CHILDACTIVATE message */
1965     if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1966     {
1967         retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1968         goto end;
1969     }
1970
1971     if( hWnd == hwndActive )
1972     {
1973         retvalue = FALSE;
1974         goto end;
1975     }
1976
1977     if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1978     {
1979         retvalue = FALSE;
1980         goto end;
1981     }
1982
1983     /* switch desktop queue to current active */
1984     wndTemp = WIN_GetDesktop();
1985     if( wndPtr->parent == wndTemp)
1986         wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
1987     WIN_ReleaseDesktop();
1988
1989     retvalue = TRUE;
1990 end:
1991     WIN_ReleaseWndPtr(wndPtr);
1992     return retvalue;
1993 }
1994
1995
1996 /***********************************************************************
1997  *           WINPOS_SendNCCalcSize
1998  *
1999  * Send a WM_NCCALCSIZE message to a window.
2000  * All parameters are read-only except newClientRect.
2001  * oldWindowRect, oldClientRect and winpos must be non-NULL only
2002  * when calcValidRect is TRUE.
2003  */
2004 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2005                             RECT *newWindowRect, RECT *oldWindowRect,
2006                             RECT *oldClientRect, WINDOWPOS *winpos,
2007                             RECT *newClientRect )
2008 {
2009     NCCALCSIZE_PARAMS params;
2010     WINDOWPOS winposCopy;
2011     LONG result;
2012
2013     params.rgrc[0] = *newWindowRect;
2014     if (calcValidRect)
2015     {
2016         winposCopy = *winpos;
2017         params.rgrc[1] = *oldWindowRect;
2018         params.rgrc[2] = *oldClientRect;
2019         params.lppos = &winposCopy;
2020     }
2021     result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2022                              (LPARAM)&params );
2023     TRACE("%d,%d-%d,%d\n",
2024                  params.rgrc[0].left, params.rgrc[0].top,
2025                  params.rgrc[0].right, params.rgrc[0].bottom );
2026
2027     /* If the application send back garbage, ignore it */
2028     if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2029         *newClientRect = params.rgrc[0];
2030
2031     return result;
2032 }
2033
2034
2035 /***********************************************************************
2036  *           WINPOS_HandleWindowPosChanging16
2037  *
2038  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2039  */
2040 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2041 {
2042     POINT maxSize, minTrack;
2043     if (winpos->flags & SWP_NOSIZE) return 0;
2044     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2045         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2046     {
2047         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2048         if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2049         if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2050         if (!(wndPtr->dwStyle & WS_MINIMIZE))
2051         {
2052             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2053             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2054         }
2055     }
2056     return 0;
2057 }
2058
2059
2060 /***********************************************************************
2061  *           WINPOS_HandleWindowPosChanging
2062  *
2063  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2064  */
2065 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2066 {
2067     POINT maxSize;
2068     if (winpos->flags & SWP_NOSIZE) return 0;
2069     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2070         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2071     {
2072         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2073         winpos->cx = MIN( winpos->cx, maxSize.x );
2074         winpos->cy = MIN( winpos->cy, maxSize.y );
2075     }
2076     return 0;
2077 }
2078
2079 /***********************************************************************
2080  *           SWP_DoOwnedPopups
2081  *
2082  * fix Z order taking into account owned popups -
2083  * basically we need to maintain them above the window that owns them
2084  *
2085  * FIXME: hide/show owned popups when owner visibility changes.
2086  */
2087 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2088 {
2089     WND*        w = WIN_LockWndPtr(pDesktop->child);
2090
2091     WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2092
2093     if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2094     {
2095         /* make sure this popup stays above the owner */
2096
2097         HWND hwndLocalPrev = HWND_TOP;
2098
2099         if( hwndInsertAfter != HWND_TOP )
2100         {
2101             while( w != wndPtr->owner )
2102             {
2103                 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2104                 if( hwndLocalPrev == hwndInsertAfter ) break;
2105                 WIN_UpdateWndPtr(&w,w->next);
2106             }
2107             hwndInsertAfter = hwndLocalPrev;
2108         }
2109     }
2110     else if( wndPtr->dwStyle & WS_CHILD )
2111         goto END; 
2112
2113     WIN_UpdateWndPtr(&w, pDesktop->child);
2114
2115     while( w )
2116     {
2117         if( w == wndPtr ) break; 
2118
2119         if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2120         {
2121             SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, 
2122                  SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2123             hwndInsertAfter = w->hwndSelf;
2124         }
2125         WIN_UpdateWndPtr(&w, w->next);
2126     }
2127
2128 END:
2129     WIN_ReleaseWndPtr(w);
2130     return hwndInsertAfter;
2131 }
2132
2133 /***********************************************************************
2134  *           SWP_CopyValidBits
2135  *
2136  * Make window look nice without excessive repainting
2137  *
2138  * visible and update regions are in window coordinates
2139  * client and window rectangles are in parent client coordinates
2140  *
2141  * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2142  *        window rects have the same origin.
2143  *
2144  * Returns: uFlags and a dirty region in *pVisRgn.
2145  */
2146 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2147                                LPRECT lpOldWndRect,
2148                                LPRECT lpOldClientRect, UINT uFlags )
2149 {
2150  RECT r;
2151  HRGN newVisRgn, dirtyRgn;
2152  INT  my = COMPLEXREGION;
2153
2154  TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2155               Wnd->rectWindow.left, Wnd->rectWindow.top,
2156               Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2157               lpOldWndRect->left, lpOldWndRect->top,
2158               lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2159  TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2160               Wnd->rectClient.left, Wnd->rectClient.top,
2161               Wnd->rectClient.right, Wnd->rectClient.bottom,
2162               lpOldClientRect->left, lpOldClientRect->top,
2163               lpOldClientRect->right,lpOldClientRect->bottom );
2164
2165  if( Wnd->hrgnUpdate == 1 )
2166      uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2167
2168  newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2169  dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2170
2171  if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2172      my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2173
2174  if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2175  {
2176 nocopy:
2177
2178      TRACE("\twon't copy anything!\n");
2179
2180      /* set dirtyRgn to the sum of old and new visible regions 
2181       * in parent client coordinates */
2182
2183      OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2184      OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2185
2186      CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2187  }
2188  else                   /* copy valid bits to a new location */
2189  {
2190      INT  dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2191      HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2192
2193      /* subtract already invalid region inside Wnd from the dst region */
2194
2195      if( Wnd->hrgnUpdate )
2196          if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2197              goto nocopy;
2198
2199      /* check if entire window can be copied */
2200
2201      ow = lpOldWndRect->right - lpOldWndRect->left;
2202      oh = lpOldWndRect->bottom - lpOldWndRect->top;
2203      nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2204      nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2205
2206      ocw = lpOldClientRect->right - lpOldClientRect->left;
2207      och = lpOldClientRect->bottom - lpOldClientRect->top;
2208      ncw = Wnd->rectClient.right  - Wnd->rectClient.left;
2209      nch = Wnd->rectClient.bottom  - Wnd->rectClient.top;
2210
2211      if(  (ocw != ncw) || (och != nch) ||
2212           ( ow !=  nw) || ( oh !=  nh) ||
2213           ((lpOldClientRect->top - lpOldWndRect->top)   != 
2214            (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2215           ((lpOldClientRect->left - lpOldWndRect->left) !=
2216            (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2217      {
2218         dx = Wnd->rectClient.left - lpOldClientRect->left;
2219         dy = Wnd->rectClient.top - lpOldClientRect->top;
2220
2221         /* restrict valid bits to the common client rect */
2222
2223         r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2224         r.top = Wnd->rectClient.top  - Wnd->rectWindow.top;
2225         r.right = r.left + MIN( ocw, ncw );
2226         r.bottom = r.top + MIN( och, nch );
2227
2228         REGION_CropRgn( hrgnValid, hrgnValid, &r, 
2229                         (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2230         GetRgnBox( hrgnValid, &r );
2231         if( IsRectEmpty( &r ) )
2232             goto nocopy;
2233         r = *lpOldClientRect;
2234      }
2235      else
2236      {
2237         dx = Wnd->rectWindow.left - lpOldWndRect->left;
2238         dy = Wnd->rectWindow.top -  lpOldWndRect->top;
2239         if( !(uFlags & SWP_EX_PAINTSELF) )
2240             OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2241         r = *lpOldWndRect;
2242      }
2243
2244      if( !(uFlags & SWP_EX_PAINTSELF) )
2245      {
2246         /* Move remaining regions to parent coordinates */
2247         OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2248         OffsetRgn( *pVisRgn,  lpOldWndRect->left, lpOldWndRect->top );
2249      }
2250      else
2251         OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2252
2253      TRACE("\tcomputing dirty region!\n");
2254
2255      /* Compute combined dirty region (old + new - valid) */
2256      CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2257      CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2258
2259      /* Blt valid bits, r is the rect to copy  */
2260
2261      if( dx || dy )
2262      {
2263          RECT rClip;
2264          HDC hDC;
2265          DC* dc;
2266
2267          /* get DC and clip rect with drawable rect to avoid superfluous expose events
2268             from copying clipped areas */
2269
2270          if( uFlags & SWP_EX_PAINTSELF )
2271          {
2272              hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2273                             DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2274              rClip.right = nw; rClip.bottom = nh;
2275          }
2276          else
2277          {
2278              hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2279                             DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2280              rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2281              rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2282          }
2283          rClip.left = rClip.top = 0;    
2284
2285          if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2286          {
2287             if( oh > nh ) r.bottom = r.top  + nh;
2288             if( ow < nw ) r.right = r.left  + nw;
2289
2290             if( IntersectRect( &r, &r, &rClip ) )
2291             {
2292                 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2293
2294                  /* When you copy the bits without repainting, parent doesn't
2295                     get validated appropriately. Therefore, we have to validate
2296                     the parent with the windows' updated region when the
2297                     parent's update region is not empty. */
2298
2299                 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2300                 {
2301                   OffsetRect(&r, dx, dy);
2302                   ValidateRect(Wnd->parent->hwndSelf, &r);
2303                 }
2304             }
2305
2306             GDI_HEAP_UNLOCK( hDC );
2307          }
2308          ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ? 
2309                      Wnd->hwndSelf :  Wnd->parent->hwndSelf, hDC); 
2310      }
2311  }
2312
2313  /* *pVisRgn now points to the invalidated region */
2314
2315  DeleteObject(newVisRgn);
2316  DeleteObject(dirtyRgn);
2317  return uFlags;
2318 }
2319
2320 /***********************************************************************
2321  *           SWP_DoSimpleFrameChanged
2322  *
2323  * NOTE: old and new client rect origins are identical, only
2324  *       extents may have changed. Window extents are the same.
2325  */
2326 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2327 {
2328     INT  i = 0;
2329     RECT rect;
2330     HRGN hrgn = 0;
2331
2332     if( !(swpFlags & SWP_NOCLIENTSIZE) )
2333     {
2334         /* Client rect changed its position/size, most likely a scrollar
2335          * was added/removed.
2336          *
2337          * FIXME: WVR alignment flags 
2338          */
2339
2340         if( wndPtr->rectClient.right >  pOldClientRect->right ) /* right edge */
2341         {
2342             i++;
2343             rect.top = 0; 
2344             rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2345             rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2346             if(!(uFlags & SWP_EX_NOCOPY))
2347                 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2348             else
2349             {
2350                 rect.left = 0;
2351                 goto redraw;
2352             }
2353         }
2354
2355         if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2356         {
2357             if( i )
2358                 hrgn = CreateRectRgnIndirect( &rect );
2359             rect.left = 0;
2360             rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2361             rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2362             if(!(uFlags & SWP_EX_NOCOPY))
2363                 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2364             else
2365                 rect.top = 0;
2366             if( i++ ) 
2367                 REGION_UnionRectWithRgn( hrgn, &rect );
2368         }
2369
2370         if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2371         {
2372             rect = wndPtr->rectWindow;
2373             OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2374                                wndPtr->rectWindow.top - wndPtr->rectClient.top );
2375             i++;
2376         }
2377     }
2378
2379     if( i )
2380     {
2381 redraw:
2382         PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2383                             RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2384     }
2385     else
2386     {
2387         WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2388     }
2389
2390     if( hrgn > 1 )
2391         DeleteObject( hrgn );
2392 }
2393
2394 /***********************************************************************
2395  *           SWP_DoWinPosChanging
2396  */
2397 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos, 
2398                                   RECT* pNewWindowRect, RECT* pNewClientRect )
2399 {
2400       /* Send WM_WINDOWPOSCHANGING message */
2401
2402     if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2403         SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2404
2405       /* Calculate new position and size */
2406
2407     *pNewWindowRect = wndPtr->rectWindow;
2408     *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2409                                                     : wndPtr->rectClient;
2410
2411     if (!(pWinpos->flags & SWP_NOSIZE))
2412     {
2413         pNewWindowRect->right  = pNewWindowRect->left + pWinpos->cx;
2414         pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2415     }
2416     if (!(pWinpos->flags & SWP_NOMOVE))
2417     {
2418         pNewWindowRect->left    = pWinpos->x;
2419         pNewWindowRect->top     = pWinpos->y;
2420         pNewWindowRect->right  += pWinpos->x - wndPtr->rectWindow.left;
2421         pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2422
2423         OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2424                                     pWinpos->y - wndPtr->rectWindow.top );
2425     }
2426
2427     pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2428     return TRUE;
2429 }
2430
2431 /***********************************************************************
2432  *           SWP_DoNCCalcSize
2433  */
2434 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2435                               RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2436 {
2437     UINT wvrFlags = 0;
2438
2439       /* Send WM_NCCALCSIZE message to get new client area */
2440     if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2441     {
2442          wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2443                                     &wndPtr->rectWindow, &wndPtr->rectClient,
2444                                     pWinpos, pNewClientRect );
2445
2446          /* FIXME: WVR_ALIGNxxx */
2447
2448          if( pNewClientRect->left != wndPtr->rectClient.left ||
2449              pNewClientRect->top != wndPtr->rectClient.top )
2450              pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2451
2452          if( (pNewClientRect->right - pNewClientRect->left !=
2453               wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2454              (pNewClientRect->bottom - pNewClientRect->top !=
2455               wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2456              pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2457     }
2458     else
2459       if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2460                                 pNewClientRect->top != wndPtr->rectClient.top) )
2461             pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2462     return wvrFlags;
2463 }
2464
2465 /***********************************************************************
2466  *           SetWindowPos   (USER.2)
2467  */
2468 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2469                               INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2470 {
2471     return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2472 }
2473
2474 /***********************************************************************
2475  *           SetWindowPos   (USER32.520)
2476  */
2477 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2478                           INT x, INT y, INT cx, INT cy, UINT flags )
2479 {
2480     WINDOWPOS   winpos;
2481     WND *       wndPtr,*wndTemp;
2482     RECT        newWindowRect, newClientRect;
2483     RECT        oldWindowRect, oldClientRect;
2484     HRGN        visRgn = 0;
2485     UINT        wvrFlags = 0, uFlags = 0;
2486     BOOL        retvalue, resync = FALSE, bChangePos;
2487     HWND        hwndActive = 0;
2488
2489     /* Get current active window from the active queue */
2490     if ( hActiveQueue )
2491     {
2492         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2493         if ( pActiveQueue )
2494         {
2495             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2496             QUEUE_Unlock( pActiveQueue );
2497         }
2498     }
2499
2500     TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n", 
2501                                                  hwnd, x, y, x+cx, y+cy, flags);  
2502
2503     bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2504     flags &= ~SWP_WINE_NOHOSTMOVE;
2505
2506
2507       /* ------------------------------------------------------------------------ CHECKS */
2508
2509       /* Check window handle */
2510
2511     if (hwnd == GetDesktopWindow()) return FALSE;
2512     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2513
2514     TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2515                           wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2516
2517       /* Fix redundant flags */
2518
2519     if(wndPtr->dwStyle & WS_VISIBLE)
2520         flags &= ~SWP_SHOWWINDOW;
2521     else
2522     {
2523         if (!(flags & SWP_SHOWWINDOW)) 
2524               flags |= SWP_NOREDRAW;
2525         flags &= ~SWP_HIDEWINDOW;
2526     }
2527
2528     if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2529
2530     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2531         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2532         flags |= SWP_NOSIZE;    /* Already the right size */
2533
2534     if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2535         flags |= SWP_NOMOVE;    /* Already the right position */
2536
2537     if (hwnd == hwndActive)
2538         flags |= SWP_NOACTIVATE;   /* Already active */
2539     else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2540     {
2541         if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2542         {
2543             flags &= ~SWP_NOZORDER;
2544             hwndInsertAfter = HWND_TOP;           
2545             goto Pos;
2546         }
2547     }
2548
2549       /* Check hwndInsertAfter */
2550
2551       /* FIXME: TOPMOST not supported yet */
2552     if ((hwndInsertAfter == HWND_TOPMOST) ||
2553         (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2554
2555       /* hwndInsertAfter must be a sibling of the window */
2556     if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2557     {
2558          WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2559
2560          if( wnd ) {
2561              if( wnd->parent != wndPtr->parent )
2562              {
2563                  retvalue = FALSE;
2564                  WIN_ReleaseWndPtr(wnd);
2565                  goto END;
2566              }
2567            if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2568          }
2569          WIN_ReleaseWndPtr(wnd);
2570     }
2571
2572 Pos:  /* ------------------------------------------------------------------------ MAIN part */
2573
2574       /* Fill the WINDOWPOS structure */
2575
2576     winpos.hwnd = hwnd;
2577     winpos.hwndInsertAfter = hwndInsertAfter;
2578     winpos.x = x;
2579     winpos.y = y;
2580     winpos.cx = cx;
2581     winpos.cy = cy;
2582     winpos.flags = flags;
2583     
2584     SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2585
2586     if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2587     {
2588         if( wndPtr->parent == WIN_GetDesktop() )
2589             hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2590                                         hwndInsertAfter, winpos.flags );
2591         WIN_ReleaseDesktop();
2592     }
2593
2594     if(!(wndPtr->flags & WIN_NATIVE) )
2595     {
2596         if( hwndInsertAfter == HWND_TOP )
2597            winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2598         else
2599         if( hwndInsertAfter == HWND_BOTTOM )
2600            winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2601         else
2602         if( !(winpos.flags & SWP_NOZORDER) )
2603            if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2604                winpos.flags |= SWP_NOZORDER;
2605
2606         if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2607             ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2608                           != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2609         {
2610             /* get a previous visible region for SWP_CopyValidBits() */
2611             DWORD flags = DCX_WINDOW;
2612   
2613             if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2614                flags |= DCX_CLIPSIBLINGS;
2615
2616             visRgn = DCE_GetVisRgn(hwnd, flags, 0, 0);
2617         }
2618     }
2619
2620     /* Common operations */
2621
2622     wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2623
2624     if(!(winpos.flags & SWP_NOZORDER))
2625     {
2626         if ( WIN_UnlinkWindow( winpos.hwnd ) )
2627            WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2628     }
2629
2630     /* Reset active DCEs */
2631
2632     if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) && 
2633                                          wndPtr->dwStyle & WS_VISIBLE) || 
2634         (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) ) 
2635     {
2636         RECT rect;
2637
2638         UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2639         DCE_InvalidateDCE(wndPtr, &rect);
2640     }
2641
2642     oldWindowRect = wndPtr->rectWindow;
2643     oldClientRect = wndPtr->rectClient;
2644
2645     /* Find out if we have to redraw the whole client rect */
2646
2647     if( oldClientRect.bottom - oldClientRect.top ==
2648         newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2649
2650     if( oldClientRect.right - oldClientRect.left ==
2651         newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2652
2653     if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2654            (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2655     {
2656         uFlags |= SWP_EX_NOCOPY;
2657     }
2658 /* 
2659  *  Use this later in CopyValidBits()
2660  *
2661     else if( 0  )
2662         uFlags |= SWP_EX_NONCLIENT; 
2663  */
2664
2665     /* FIXME: actually do something with WVR_VALIDRECTS */
2666
2667     wndPtr->rectWindow = newWindowRect;
2668     wndPtr->rectClient = newClientRect;
2669
2670     if (wndPtr->flags & WIN_NATIVE)     /* -------------------------------------------- hosted window */
2671     {
2672         BOOL bCallDriver = TRUE;
2673         HWND tempInsertAfter = winpos.hwndInsertAfter;
2674
2675         winpos.hwndInsertAfter = hwndInsertAfter;
2676
2677         if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2678         {
2679           /* This is the only place where we need to force repainting of the contents
2680              of windows created by the host window system, all other cases go through the
2681              expose event handling */
2682
2683             if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2684             {
2685                 cx = newWindowRect.right - newWindowRect.left;
2686                 cy = newWindowRect.bottom - newWindowRect.top;
2687
2688                 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2689                 winpos.hwndInsertAfter = tempInsertAfter;
2690                 bCallDriver = FALSE;
2691
2692                 if( winpos.flags & SWP_NOCLIENTMOVE )
2693                     SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2694                 else
2695                 {
2696                     /* client area moved but window extents remained the same, copy valid bits */
2697
2698                     visRgn = CreateRectRgn( 0, 0, cx, cy );
2699                     uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect, 
2700                                                 uFlags | SWP_EX_PAINTSELF );
2701                 }
2702             }
2703         }
2704
2705         if( bCallDriver )
2706         {
2707             if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2708             {
2709                 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2710                     (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2711                    !(uFlags & SWP_EX_NOCOPY) )
2712                 {
2713                   /* The origin of the client rect didn't move so we can try to repaint
2714                    * only the nonclient area by setting bit gravity hint for the host window system.
2715                    */
2716
2717                     if( !(wndPtr->flags & WIN_MANAGED) )
2718                     {
2719                         HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2720                                                      newWindowRect.bottom - newWindowRect.top);
2721                         RECT rcn = newClientRect;
2722                         RECT rco = oldClientRect;
2723
2724                         OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2725                         OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2726                         IntersectRect( &rcn, &rcn, &rco );
2727                         visRgn = CreateRectRgnIndirect( &rcn );
2728                         CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2729                         DeleteObject( hrgn );
2730                         uFlags = SWP_EX_PAINTSELF;
2731                     }
2732                     wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2733                 }
2734                 else
2735                     wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2736             }
2737
2738             wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2739             winpos.hwndInsertAfter = tempInsertAfter;
2740         }
2741
2742         if( winpos.flags & SWP_SHOWWINDOW )
2743         {
2744                 HWND focus, curr;
2745
2746                 wndPtr->dwStyle |= WS_VISIBLE;
2747
2748                 if (wndPtr->flags & WIN_MANAGED) resync = TRUE; 
2749
2750                 /* focus was set to unmapped window, reset host focus 
2751                  * since the window is now visible */
2752
2753                 focus = curr = GetFocus();
2754                 while (curr) 
2755                 {
2756                     if (curr == hwnd) 
2757                     {
2758                         WND *pFocus = WIN_FindWndPtr( focus );
2759                         if (pFocus)
2760                             pFocus->pDriver->pSetFocus(pFocus);
2761                         WIN_ReleaseWndPtr(pFocus);
2762                         break;
2763                     }
2764                     curr = GetParent(curr);
2765                 }
2766         }
2767     }
2768     else                                /* -------------------------------------------- emulated window */
2769     {
2770             if( winpos.flags & SWP_SHOWWINDOW )
2771             {
2772                 wndPtr->dwStyle |= WS_VISIBLE;
2773                 uFlags |= SWP_EX_PAINTSELF;
2774                 visRgn = 1; /* redraw the whole window */
2775             }
2776             else if( !(winpos.flags & SWP_NOREDRAW) )
2777             {
2778                 if( winpos.flags & SWP_HIDEWINDOW )
2779                 {
2780                     if( visRgn > 1 ) /* map to parent */
2781                         OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2782                     else
2783                         visRgn = 0;
2784                 }
2785                 else
2786                 {
2787                     if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2788                          uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect, 
2789                                                             &oldClientRect, uFlags);
2790                     else
2791                     {
2792                         /* nothing moved, redraw frame if needed */
2793                          
2794                         if( winpos.flags & SWP_FRAMECHANGED )
2795                             SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2796                         if( visRgn )
2797                         {
2798                             DeleteObject( visRgn );
2799                             visRgn = 0;
2800                         } 
2801                     }
2802                 }
2803             }
2804     }
2805
2806     if( winpos.flags & SWP_HIDEWINDOW )
2807     {
2808         wndPtr->dwStyle &= ~WS_VISIBLE;
2809
2810         if (hwnd == CARET_GetHwnd()) DestroyCaret();
2811
2812         /* FIXME: This will cause the window to be activated irrespective
2813          * of whether it is owned by the same thread. Has to be done
2814          * asynchronously.
2815          */
2816
2817         if (winpos.hwnd == hwndActive)
2818             WINPOS_ActivateOtherWindow( wndPtr );
2819     }
2820
2821     /* ------------------------------------------------------------------------ FINAL */
2822
2823     if (wndPtr->flags & WIN_NATIVE)
2824         EVENT_Synchronize();  /* Synchronize with the host window system */
2825
2826     if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2827     { 
2828         /* Simulate a mouse event to set the cursor */
2829         DWORD posX, posY, keyState;
2830
2831         if ( EVENT_QueryPointer( &posX, &posY, &keyState ) )
2832         {
2833             int iWndsLocks = WIN_SuspendWndsLock();
2834
2835             hardware_event( WM_MOUSEMOVE, keyState, 0,
2836                             posX, posY, GetTickCount(), 0 );
2837
2838             WIN_RestoreWndsLock(iWndsLocks);
2839         }
2840     }
2841
2842     wndTemp = WIN_GetDesktop();
2843
2844     /* repaint invalidated region (if any) 
2845      *
2846      * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2847      *        and force update after ChangeActiveWindow() to avoid painting frames twice.
2848      */
2849
2850     if( visRgn )
2851     {
2852         if( !(winpos.flags & SWP_NOREDRAW) )
2853         {
2854  
2855             /*  Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2856                 its parent and sibling and so on, and then erase the parent window 
2857                 back ground if the parent is either a top-level window or its parent's parent  
2858                 is top-level window. Rely on the system to repaint other affected 
2859                 windows later on.  */ 
2860             if( uFlags & SWP_EX_PAINTSELF )
2861             {
2862                 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, 
2863                                 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2864                                 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2865             }
2866             else
2867             {
2868                     PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, 
2869                                 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN, 
2870                                 RDW_EX_USEHRGN );
2871             }
2872
2873             if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2874                 {
2875                 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, 
2876                                 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2877             }
2878         }
2879         if( visRgn != 1 )
2880             DeleteObject( visRgn );
2881     }
2882
2883     WIN_ReleaseDesktop();
2884
2885     if (!(flags & SWP_NOACTIVATE))
2886             WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2887
2888       /* And last, send the WM_WINDOWPOSCHANGED message */
2889
2890     TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2891
2892     if ( resync ||
2893         (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) && 
2894          !(winpos.flags & SWP_NOSENDCHANGING)) )
2895     {
2896         SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2897         if (resync) EVENT_Synchronize();
2898     }
2899
2900     retvalue = TRUE;
2901 END:
2902     WIN_ReleaseWndPtr(wndPtr);
2903     return retvalue;
2904 }
2905
2906                                         
2907 /***********************************************************************
2908  *           BeginDeferWindowPos16   (USER.259)
2909  */
2910 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2911 {
2912     return BeginDeferWindowPos( count );
2913 }
2914
2915
2916 /***********************************************************************
2917  *           BeginDeferWindowPos   (USER32.9)
2918  */
2919 HDWP WINAPI BeginDeferWindowPos( INT count )
2920 {
2921     HDWP handle;
2922     DWP *pDWP;
2923
2924     if (count <= 0) return 0;
2925     handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2926     if (!handle) return 0;
2927     pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2928     pDWP->actualCount    = 0;
2929     pDWP->suggestedCount = count;
2930     pDWP->valid          = TRUE;
2931     pDWP->wMagic         = DWP_MAGIC;
2932     pDWP->hwndParent     = 0;
2933     return handle;
2934 }
2935
2936
2937 /***********************************************************************
2938  *           DeferWindowPos16   (USER.260)
2939  */
2940 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2941                                 INT16 x, INT16 y, INT16 cx, INT16 cy,
2942                                 UINT16 flags )
2943 {
2944     return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2945                              x, y, cx, cy, flags );
2946 }
2947
2948
2949 /***********************************************************************
2950  *           DeferWindowPos   (USER32.128)
2951  */
2952 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2953                                 INT x, INT y, INT cx, INT cy,
2954                                 UINT flags )
2955 {
2956     DWP *pDWP;
2957     int i;
2958     HDWP newhdwp = hdwp,retvalue;
2959     /* HWND parent; */
2960     WND *pWnd;
2961
2962     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2963     if (!pDWP) return 0;
2964     if (hwnd == GetDesktopWindow()) return 0;
2965
2966     if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2967         USER_HEAP_FREE( hdwp );
2968         return 0;
2969     }
2970         
2971 /* Numega Bounds Checker Demo dislikes the following code.
2972    In fact, I've not been able to find any "same parent" requirement in any docu
2973    [AM 980509]
2974  */
2975 #if 0
2976     /* All the windows of a DeferWindowPos() must have the same parent */
2977     parent = pWnd->parent->hwndSelf;
2978     if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2979     else if (parent != pDWP->hwndParent)
2980     {
2981         USER_HEAP_FREE( hdwp );
2982         retvalue = 0;
2983         goto END;
2984     }
2985 #endif
2986
2987     for (i = 0; i < pDWP->actualCount; i++)
2988     {
2989         if (pDWP->winPos[i].hwnd == hwnd)
2990         {
2991               /* Merge with the other changes */
2992             if (!(flags & SWP_NOZORDER))
2993             {
2994                 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2995             }
2996             if (!(flags & SWP_NOMOVE))
2997             {
2998                 pDWP->winPos[i].x = x;
2999                 pDWP->winPos[i].y = y;
3000             }                
3001             if (!(flags & SWP_NOSIZE))
3002             {
3003                 pDWP->winPos[i].cx = cx;
3004                 pDWP->winPos[i].cy = cy;
3005             }
3006             pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3007                                                SWP_NOZORDER | SWP_NOREDRAW |
3008                                                SWP_NOACTIVATE | SWP_NOCOPYBITS|
3009                                                SWP_NOOWNERZORDER);
3010             pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3011                                               SWP_FRAMECHANGED);
3012             retvalue = hdwp;
3013             goto END;
3014         }
3015     }
3016     if (pDWP->actualCount >= pDWP->suggestedCount)
3017     {
3018         newhdwp = USER_HEAP_REALLOC( hdwp,
3019                       sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3020         if (!newhdwp)
3021         {
3022             retvalue = 0;
3023             goto END;
3024         }
3025         pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3026         pDWP->suggestedCount++;
3027     }
3028     pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3029     pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3030     pDWP->winPos[pDWP->actualCount].x = x;
3031     pDWP->winPos[pDWP->actualCount].y = y;
3032     pDWP->winPos[pDWP->actualCount].cx = cx;
3033     pDWP->winPos[pDWP->actualCount].cy = cy;
3034     pDWP->winPos[pDWP->actualCount].flags = flags;
3035     pDWP->actualCount++;
3036     retvalue = newhdwp;
3037 END:
3038     WIN_ReleaseWndPtr(pWnd);
3039     return retvalue;
3040 }
3041
3042
3043 /***********************************************************************
3044  *           EndDeferWindowPos16   (USER.261)
3045  */
3046 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3047 {
3048     return EndDeferWindowPos( hdwp );
3049 }
3050
3051
3052 /***********************************************************************
3053  *           EndDeferWindowPos   (USER32.173)
3054  */
3055 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3056 {
3057     DWP *pDWP;
3058     WINDOWPOS *winpos;
3059     BOOL res = TRUE;
3060     int i;
3061
3062     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3063     if (!pDWP) return FALSE;
3064     for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3065     {
3066         if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3067                                     winpos->x, winpos->y, winpos->cx,
3068                                     winpos->cy, winpos->flags ))) break;
3069     }
3070     USER_HEAP_FREE( hdwp );
3071     return res;
3072 }
3073
3074
3075 /***********************************************************************
3076  *           TileChildWindows   (USER.199)
3077  */
3078 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3079 {
3080     FIXME("(%04x, %d): stub\n", parent, action);
3081 }
3082
3083 /***********************************************************************
3084  *           CascageChildWindows   (USER.198)
3085  */
3086 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3087 {
3088     FIXME("(%04x, %d): stub\n", parent, action);
3089 }
3090
3091 /***********************************************************************
3092  *           SetProgmanWindow                   [USER32.522]
3093  */
3094 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3095 {
3096         hGlobalProgmanWindow = hwnd;
3097         return hGlobalProgmanWindow;
3098 }
3099
3100 /***********************************************************************
3101  *           GetProgmanWindow                   [USER32.289]
3102  */
3103 HRESULT WINAPI GetProgmanWindow ( )
3104 {
3105         return hGlobalProgmanWindow;
3106 }
3107
3108 /***********************************************************************
3109  *           SetShellWindowEx                   [USER32.531]
3110  * hwndProgman =  Progman[Program Manager]
3111  *                |-> SHELLDLL_DefView
3112  * hwndListView = |   |-> SysListView32
3113  *                |   |   |-> tooltips_class32
3114  *                |   |
3115  *                |   |-> SysHeader32
3116  *                |   
3117  *                |-> ProxyTarget
3118  */
3119 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3120 {
3121         FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3122         hGlobalShellWindow = hwndProgman;
3123         return hGlobalShellWindow;
3124
3125 }
3126
3127 /***********************************************************************
3128  *           SetTaskmanWindow                   [USER32.537]
3129  * NOTES
3130  *   hwnd = MSTaskSwWClass 
3131  *          |-> SysTabControl32
3132  */
3133 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3134 {
3135         hGlobalTaskmanWindow = hwnd;
3136         return hGlobalTaskmanWindow;
3137 }
3138
3139 /***********************************************************************
3140  *           GetTaskmanWindow                   [USER32.304]
3141  */
3142 HRESULT WINAPI GetTaskmanWindow ( )
3143 {       
3144         return hGlobalTaskmanWindow;
3145 }