If the window is already the topmost window in ShowWindow(SW_SHOW), it
[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     *newClientRect = params.rgrc[0];
2027     return result;
2028 }
2029
2030
2031 /***********************************************************************
2032  *           WINPOS_HandleWindowPosChanging16
2033  *
2034  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2035  */
2036 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2037 {
2038     POINT maxSize, minTrack;
2039     if (winpos->flags & SWP_NOSIZE) return 0;
2040     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2041         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2042     {
2043         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2044         if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2045         if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2046         if (!(wndPtr->dwStyle & WS_MINIMIZE))
2047         {
2048             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2049             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2050         }
2051     }
2052     return 0;
2053 }
2054
2055
2056 /***********************************************************************
2057  *           WINPOS_HandleWindowPosChanging
2058  *
2059  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2060  */
2061 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2062 {
2063     POINT maxSize;
2064     if (winpos->flags & SWP_NOSIZE) return 0;
2065     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2066         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2067     {
2068         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2069         winpos->cx = MIN( winpos->cx, maxSize.x );
2070         winpos->cy = MIN( winpos->cy, maxSize.y );
2071     }
2072     return 0;
2073 }
2074
2075 /***********************************************************************
2076  *           SWP_DoOwnedPopups
2077  *
2078  * fix Z order taking into account owned popups -
2079  * basically we need to maintain them above the window that owns them
2080  *
2081  * FIXME: hide/show owned popups when owner visibility changes.
2082  */
2083 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2084 {
2085     WND*        w = WIN_LockWndPtr(pDesktop->child);
2086
2087     WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2088
2089     if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2090     {
2091         /* make sure this popup stays above the owner */
2092
2093         HWND hwndLocalPrev = HWND_TOP;
2094
2095         if( hwndInsertAfter != HWND_TOP )
2096         {
2097             while( w != wndPtr->owner )
2098             {
2099                 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2100                 if( hwndLocalPrev == hwndInsertAfter ) break;
2101                 WIN_UpdateWndPtr(&w,w->next);
2102             }
2103             hwndInsertAfter = hwndLocalPrev;
2104         }
2105     }
2106     else if( wndPtr->dwStyle & WS_CHILD )
2107         goto END; 
2108
2109     WIN_UpdateWndPtr(&w, pDesktop->child);
2110
2111     while( w )
2112     {
2113         if( w == wndPtr ) break; 
2114
2115         if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2116         {
2117             SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, 
2118                  SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2119             hwndInsertAfter = w->hwndSelf;
2120         }
2121         WIN_UpdateWndPtr(&w, w->next);
2122     }
2123
2124 END:
2125     WIN_ReleaseWndPtr(w);
2126     return hwndInsertAfter;
2127 }
2128
2129 /***********************************************************************
2130  *           SWP_CopyValidBits
2131  *
2132  * Make window look nice without excessive repainting
2133  *
2134  * visible and update regions are in window coordinates
2135  * client and window rectangles are in parent client coordinates
2136  *
2137  * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2138  *        window rects have the same origin.
2139  *
2140  * Returns: uFlags and a dirty region in *pVisRgn.
2141  */
2142 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2143                                LPRECT lpOldWndRect,
2144                                LPRECT lpOldClientRect, UINT uFlags )
2145 {
2146  RECT r;
2147  HRGN newVisRgn, dirtyRgn;
2148  INT  my = COMPLEXREGION;
2149
2150  TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2151               Wnd->rectWindow.left, Wnd->rectWindow.top,
2152               Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2153               lpOldWndRect->left, lpOldWndRect->top,
2154               lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2155  TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2156               Wnd->rectClient.left, Wnd->rectClient.top,
2157               Wnd->rectClient.right, Wnd->rectClient.bottom,
2158               lpOldClientRect->left, lpOldClientRect->top,
2159               lpOldClientRect->right,lpOldClientRect->bottom );
2160
2161  if( Wnd->hrgnUpdate == 1 )
2162      uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2163
2164  newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2165  dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2166
2167  if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2168      my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2169
2170  if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2171  {
2172 nocopy:
2173
2174      TRACE("\twon't copy anything!\n");
2175
2176      /* set dirtyRgn to the sum of old and new visible regions 
2177       * in parent client coordinates */
2178
2179      OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2180      OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2181
2182      CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2183  }
2184  else                   /* copy valid bits to a new location */
2185  {
2186      INT  dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2187      HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2188
2189      /* subtract already invalid region inside Wnd from the dst region */
2190
2191      if( Wnd->hrgnUpdate )
2192          if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2193              goto nocopy;
2194
2195      /* check if entire window can be copied */
2196
2197      ow = lpOldWndRect->right - lpOldWndRect->left;
2198      oh = lpOldWndRect->bottom - lpOldWndRect->top;
2199      nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2200      nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2201
2202      ocw = lpOldClientRect->right - lpOldClientRect->left;
2203      och = lpOldClientRect->bottom - lpOldClientRect->top;
2204      ncw = Wnd->rectClient.right  - Wnd->rectClient.left;
2205      nch = Wnd->rectClient.bottom  - Wnd->rectClient.top;
2206
2207      if(  (ocw != ncw) || (och != nch) ||
2208           ( ow !=  nw) || ( oh !=  nh) ||
2209           ((lpOldClientRect->top - lpOldWndRect->top)   != 
2210            (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2211           ((lpOldClientRect->left - lpOldWndRect->left) !=
2212            (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2213      {
2214         dx = Wnd->rectClient.left - lpOldClientRect->left;
2215         dy = Wnd->rectClient.top - lpOldClientRect->top;
2216
2217         /* restrict valid bits to the common client rect */
2218
2219         r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2220         r.top = Wnd->rectClient.top  - Wnd->rectWindow.top;
2221         r.right = r.left + MIN( ocw, ncw );
2222         r.bottom = r.top + MIN( och, nch );
2223
2224         REGION_CropRgn( hrgnValid, hrgnValid, &r, 
2225                         (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2226         GetRgnBox( hrgnValid, &r );
2227         if( IsRectEmpty( &r ) )
2228             goto nocopy;
2229         r = *lpOldClientRect;
2230      }
2231      else
2232      {
2233         dx = Wnd->rectWindow.left - lpOldWndRect->left;
2234         dy = Wnd->rectWindow.top -  lpOldWndRect->top;
2235         if( !(uFlags & SWP_EX_PAINTSELF) )
2236             OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2237         r = *lpOldWndRect;
2238      }
2239
2240      if( !(uFlags & SWP_EX_PAINTSELF) )
2241      {
2242         /* Move remaining regions to parent coordinates */
2243         OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2244         OffsetRgn( *pVisRgn,  lpOldWndRect->left, lpOldWndRect->top );
2245      }
2246      else
2247         OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2248
2249      TRACE("\tcomputing dirty region!\n");
2250
2251      /* Compute combined dirty region (old + new - valid) */
2252      CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2253      CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2254
2255      /* Blt valid bits, r is the rect to copy  */
2256
2257      if( dx || dy )
2258      {
2259          RECT rClip;
2260          HDC hDC;
2261          DC* dc;
2262
2263          /* get DC and clip rect with drawable rect to avoid superfluous expose events
2264             from copying clipped areas */
2265
2266          if( uFlags & SWP_EX_PAINTSELF )
2267          {
2268              hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2269                             DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2270              rClip.right = nw; rClip.bottom = nh;
2271          }
2272          else
2273          {
2274              hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2275                             DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2276              rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2277              rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2278          }
2279          rClip.left = rClip.top = 0;    
2280
2281          if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2282          {
2283             if( oh > nh ) r.bottom = r.top  + nh;
2284             if( ow < nw ) r.right = r.left  + nw;
2285
2286             if( IntersectRect( &r, &r, &rClip ) )
2287             {
2288                 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2289
2290                  /* When you copy the bits without repainting, parent doesn't
2291                     get validated appropriately. Therefore, we have to validate
2292                     the parent with the windows' updated region when the
2293                     parent's update region is not empty. */
2294
2295                 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2296                 {
2297                   OffsetRect(&r, dx, dy);
2298                   ValidateRect(Wnd->parent->hwndSelf, &r);
2299                 }
2300             }
2301
2302             GDI_HEAP_UNLOCK( hDC );
2303          }
2304          ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ? 
2305                      Wnd->hwndSelf :  Wnd->parent->hwndSelf, hDC); 
2306      }
2307  }
2308
2309  /* *pVisRgn now points to the invalidated region */
2310
2311  DeleteObject(newVisRgn);
2312  DeleteObject(dirtyRgn);
2313  return uFlags;
2314 }
2315
2316 /***********************************************************************
2317  *           SWP_DoSimpleFrameChanged
2318  *
2319  * NOTE: old and new client rect origins are identical, only
2320  *       extents may have changed. Window extents are the same.
2321  */
2322 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2323 {
2324     INT  i = 0;
2325     RECT rect;
2326     HRGN hrgn = 0;
2327
2328     if( !(swpFlags & SWP_NOCLIENTSIZE) )
2329     {
2330         /* Client rect changed its position/size, most likely a scrollar
2331          * was added/removed.
2332          *
2333          * FIXME: WVR alignment flags 
2334          */
2335
2336         if( wndPtr->rectClient.right >  pOldClientRect->right ) /* right edge */
2337         {
2338             i++;
2339             rect.top = 0; 
2340             rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2341             rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2342             if(!(uFlags & SWP_EX_NOCOPY))
2343                 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2344             else
2345             {
2346                 rect.left = 0;
2347                 goto redraw;
2348             }
2349         }
2350
2351         if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2352         {
2353             if( i )
2354                 hrgn = CreateRectRgnIndirect( &rect );
2355             rect.left = 0;
2356             rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2357             rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2358             if(!(uFlags & SWP_EX_NOCOPY))
2359                 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2360             else
2361                 rect.top = 0;
2362             if( i++ ) 
2363                 REGION_UnionRectWithRgn( hrgn, &rect );
2364         }
2365
2366         if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2367         {
2368             rect = wndPtr->rectWindow;
2369             OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2370                                wndPtr->rectWindow.top - wndPtr->rectClient.top );
2371             i++;
2372         }
2373     }
2374
2375     if( i )
2376     {
2377 redraw:
2378         PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2379                             RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2380     }
2381     else
2382     {
2383         WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2384     }
2385
2386     if( hrgn > 1 )
2387         DeleteObject( hrgn );
2388 }
2389
2390 /***********************************************************************
2391  *           SWP_DoWinPosChanging
2392  */
2393 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos, 
2394                                   RECT* pNewWindowRect, RECT* pNewClientRect )
2395 {
2396       /* Send WM_WINDOWPOSCHANGING message */
2397
2398     if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2399         SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2400
2401       /* Calculate new position and size */
2402
2403     *pNewWindowRect = wndPtr->rectWindow;
2404     *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2405                                                     : wndPtr->rectClient;
2406
2407     if (!(pWinpos->flags & SWP_NOSIZE))
2408     {
2409         pNewWindowRect->right  = pNewWindowRect->left + pWinpos->cx;
2410         pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2411     }
2412     if (!(pWinpos->flags & SWP_NOMOVE))
2413     {
2414         pNewWindowRect->left    = pWinpos->x;
2415         pNewWindowRect->top     = pWinpos->y;
2416         pNewWindowRect->right  += pWinpos->x - wndPtr->rectWindow.left;
2417         pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2418
2419         OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2420                                     pWinpos->y - wndPtr->rectWindow.top );
2421     }
2422
2423     pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2424     return TRUE;
2425 }
2426
2427 /***********************************************************************
2428  *           SWP_DoNCCalcSize
2429  */
2430 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2431                               RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2432 {
2433     UINT wvrFlags = 0;
2434
2435       /* Send WM_NCCALCSIZE message to get new client area */
2436     if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2437     {
2438          wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2439                                     &wndPtr->rectWindow, &wndPtr->rectClient,
2440                                     pWinpos, pNewClientRect );
2441
2442          /* FIXME: WVR_ALIGNxxx */
2443
2444          if( pNewClientRect->left != wndPtr->rectClient.left ||
2445              pNewClientRect->top != wndPtr->rectClient.top )
2446              pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2447
2448          if( (pNewClientRect->right - pNewClientRect->left !=
2449               wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2450              (pNewClientRect->bottom - pNewClientRect->top !=
2451               wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2452              pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2453     }
2454     else
2455       if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2456                                 pNewClientRect->top != wndPtr->rectClient.top) )
2457             pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2458     return wvrFlags;
2459 }
2460
2461 /***********************************************************************
2462  *           SetWindowPos   (USER.2)
2463  */
2464 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2465                               INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2466 {
2467     return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2468 }
2469
2470 /***********************************************************************
2471  *           SetWindowPos   (USER32.520)
2472  */
2473 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2474                           INT x, INT y, INT cx, INT cy, UINT flags )
2475 {
2476     WINDOWPOS   winpos;
2477     WND *       wndPtr,*wndTemp;
2478     RECT        newWindowRect, newClientRect;
2479     RECT        oldWindowRect, oldClientRect;
2480     HRGN        visRgn = 0;
2481     UINT        wvrFlags = 0, uFlags = 0;
2482     BOOL        retvalue, resync = FALSE, bChangePos;
2483     HWND        hwndActive = 0;
2484
2485     /* Get current active window from the active queue */
2486     if ( hActiveQueue )
2487     {
2488         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2489         if ( pActiveQueue )
2490         {
2491             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2492             QUEUE_Unlock( pActiveQueue );
2493         }
2494     }
2495
2496     TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n", 
2497                                                  hwnd, x, y, x+cx, y+cy, flags);  
2498
2499     bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2500     flags &= ~SWP_WINE_NOHOSTMOVE;
2501
2502
2503       /* ------------------------------------------------------------------------ CHECKS */
2504
2505       /* Check window handle */
2506
2507     if (hwnd == GetDesktopWindow()) return FALSE;
2508     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2509
2510     TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2511                           wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2512
2513       /* Fix redundant flags */
2514
2515     if(wndPtr->dwStyle & WS_VISIBLE)
2516         flags &= ~SWP_SHOWWINDOW;
2517     else
2518     {
2519         if (!(flags & SWP_SHOWWINDOW)) 
2520               flags |= SWP_NOREDRAW;
2521         flags &= ~SWP_HIDEWINDOW;
2522     }
2523
2524     if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2525
2526     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2527         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2528         flags |= SWP_NOSIZE;    /* Already the right size */
2529
2530     if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2531         flags |= SWP_NOMOVE;    /* Already the right position */
2532
2533     if (hwnd == hwndActive)
2534         flags |= SWP_NOACTIVATE;   /* Already active */
2535     else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2536     {
2537         if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2538         {
2539             flags &= ~SWP_NOZORDER;
2540             hwndInsertAfter = HWND_TOP;           
2541             goto Pos;
2542         }
2543     }
2544
2545       /* Check hwndInsertAfter */
2546
2547       /* FIXME: TOPMOST not supported yet */
2548     if ((hwndInsertAfter == HWND_TOPMOST) ||
2549         (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2550
2551       /* hwndInsertAfter must be a sibling of the window */
2552     if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2553     {
2554          WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2555
2556          if( wnd ) {
2557              if( wnd->parent != wndPtr->parent )
2558              {
2559                  retvalue = FALSE;
2560                  WIN_ReleaseWndPtr(wnd);
2561                  goto END;
2562              }
2563            if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2564          }
2565          WIN_ReleaseWndPtr(wnd);
2566     }
2567
2568 Pos:  /* ------------------------------------------------------------------------ MAIN part */
2569
2570       /* Fill the WINDOWPOS structure */
2571
2572     winpos.hwnd = hwnd;
2573     winpos.hwndInsertAfter = hwndInsertAfter;
2574     winpos.x = x;
2575     winpos.y = y;
2576     winpos.cx = cx;
2577     winpos.cy = cy;
2578     winpos.flags = flags;
2579     
2580     SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2581
2582     if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2583     {
2584         if( wndPtr->parent == WIN_GetDesktop() )
2585             hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2586                                         hwndInsertAfter, winpos.flags );
2587         WIN_ReleaseDesktop();
2588     }
2589
2590     if(!(wndPtr->flags & WIN_NATIVE) )
2591     {
2592         if( hwndInsertAfter == HWND_TOP )
2593            winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2594         else
2595         if( hwndInsertAfter == HWND_BOTTOM )
2596            winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2597         else
2598         if( !(winpos.flags & SWP_NOZORDER) )
2599            if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2600                winpos.flags |= SWP_NOZORDER;
2601
2602         if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2603             ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2604                           != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2605         {
2606             /* get a previous visible region for SWP_CopyValidBits() */
2607             DWORD flags = DCX_WINDOW;
2608   
2609             if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2610                flags |= DCX_CLIPSIBLINGS;
2611
2612             visRgn = DCE_GetVisRgn(hwnd, flags, 0, 0);
2613         }
2614     }
2615
2616     /* Common operations */
2617
2618     wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2619
2620     if(!(winpos.flags & SWP_NOZORDER))
2621     {
2622         if ( WIN_UnlinkWindow( winpos.hwnd ) )
2623            WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2624     }
2625
2626     /* Reset active DCEs */
2627
2628     if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) && 
2629                                          wndPtr->dwStyle & WS_VISIBLE) || 
2630         (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) ) 
2631     {
2632         RECT rect;
2633
2634         UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2635         DCE_InvalidateDCE(wndPtr, &rect);
2636     }
2637
2638     oldWindowRect = wndPtr->rectWindow;
2639     oldClientRect = wndPtr->rectClient;
2640
2641     /* Find out if we have to redraw the whole client rect */
2642
2643     if( oldClientRect.bottom - oldClientRect.top ==
2644         newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2645
2646     if( oldClientRect.right - oldClientRect.left ==
2647         newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2648
2649     if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2650            (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2651     {
2652         uFlags |= SWP_EX_NOCOPY;
2653     }
2654 /* 
2655  *  Use this later in CopyValidBits()
2656  *
2657     else if( 0  )
2658         uFlags |= SWP_EX_NONCLIENT; 
2659  */
2660
2661     /* FIXME: actually do something with WVR_VALIDRECTS */
2662
2663     wndPtr->rectWindow = newWindowRect;
2664     wndPtr->rectClient = newClientRect;
2665
2666     if (wndPtr->flags & WIN_NATIVE)     /* -------------------------------------------- hosted window */
2667     {
2668         BOOL bCallDriver = TRUE;
2669         HWND tempInsertAfter = winpos.hwndInsertAfter;
2670
2671         winpos.hwndInsertAfter = hwndInsertAfter;
2672
2673         if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2674         {
2675           /* This is the only place where we need to force repainting of the contents
2676              of windows created by the host window system, all other cases go through the
2677              expose event handling */
2678
2679             if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2680             {
2681                 cx = newWindowRect.right - newWindowRect.left;
2682                 cy = newWindowRect.bottom - newWindowRect.top;
2683
2684                 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2685                 winpos.hwndInsertAfter = tempInsertAfter;
2686                 bCallDriver = FALSE;
2687
2688                 if( winpos.flags & SWP_NOCLIENTMOVE )
2689                     SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2690                 else
2691                 {
2692                     /* client area moved but window extents remained the same, copy valid bits */
2693
2694                     visRgn = CreateRectRgn( 0, 0, cx, cy );
2695                     uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect, 
2696                                                 uFlags | SWP_EX_PAINTSELF );
2697                 }
2698             }
2699         }
2700
2701         if( bCallDriver )
2702         {
2703             if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2704             {
2705                 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2706                     (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2707                    !(uFlags & SWP_EX_NOCOPY) )
2708                 {
2709                   /* The origin of the client rect didn't move so we can try to repaint
2710                    * only the nonclient area by setting bit gravity hint for the host window system.
2711                    */
2712
2713                     if( !(wndPtr->flags & WIN_MANAGED) )
2714                     {
2715                         HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2716                                                      newWindowRect.bottom - newWindowRect.top);
2717                         RECT rcn = newClientRect;
2718                         RECT rco = oldClientRect;
2719
2720                         OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2721                         OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2722                         IntersectRect( &rcn, &rcn, &rco );
2723                         visRgn = CreateRectRgnIndirect( &rcn );
2724                         CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2725                         DeleteObject( hrgn );
2726                         uFlags = SWP_EX_PAINTSELF;
2727                     }
2728                     wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2729                 }
2730                 else
2731                     wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2732             }
2733
2734             wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2735             winpos.hwndInsertAfter = tempInsertAfter;
2736         }
2737
2738         if( winpos.flags & SWP_SHOWWINDOW )
2739         {
2740                 HWND focus, curr;
2741
2742                 wndPtr->dwStyle |= WS_VISIBLE;
2743
2744                 if (wndPtr->flags & WIN_MANAGED) resync = TRUE; 
2745
2746                 /* focus was set to unmapped window, reset host focus 
2747                  * since the window is now visible */
2748
2749                 focus = curr = GetFocus();
2750                 while (curr) 
2751                 {
2752                     if (curr == hwnd) 
2753                     {
2754                         WND *pFocus = WIN_FindWndPtr( focus );
2755                         if (pFocus)
2756                             pFocus->pDriver->pSetFocus(pFocus);
2757                         WIN_ReleaseWndPtr(pFocus);
2758                         break;
2759                     }
2760                     curr = GetParent(curr);
2761                 }
2762         }
2763     }
2764     else                                /* -------------------------------------------- emulated window */
2765     {
2766             if( winpos.flags & SWP_SHOWWINDOW )
2767             {
2768                 wndPtr->dwStyle |= WS_VISIBLE;
2769                 uFlags |= SWP_EX_PAINTSELF;
2770                 visRgn = 1; /* redraw the whole window */
2771             }
2772             else if( !(winpos.flags & SWP_NOREDRAW) )
2773             {
2774                 if( winpos.flags & SWP_HIDEWINDOW )
2775                 {
2776                     if( visRgn > 1 ) /* map to parent */
2777                         OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2778                     else
2779                         visRgn = 0;
2780                 }
2781                 else
2782                 {
2783                     if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2784                          uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect, 
2785                                                             &oldClientRect, uFlags);
2786                     else
2787                     {
2788                         /* nothing moved, redraw frame if needed */
2789                          
2790                         if( winpos.flags & SWP_FRAMECHANGED )
2791                             SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2792                         if( visRgn )
2793                         {
2794                             DeleteObject( visRgn );
2795                             visRgn = 0;
2796                         } 
2797                     }
2798                 }
2799             }
2800     }
2801
2802     if( winpos.flags & SWP_HIDEWINDOW )
2803     {
2804         wndPtr->dwStyle &= ~WS_VISIBLE;
2805
2806         if (hwnd == CARET_GetHwnd()) DestroyCaret();
2807
2808         /* FIXME: This will cause the window to be activated irrespective
2809          * of whether it is owned by the same thread. Has to be done
2810          * asynchronously.
2811          */
2812
2813         if (winpos.hwnd == hwndActive)
2814             WINPOS_ActivateOtherWindow( wndPtr );
2815     }
2816
2817     /* ------------------------------------------------------------------------ FINAL */
2818
2819     if (wndPtr->flags & WIN_NATIVE)
2820         EVENT_Synchronize();  /* Synchronize with the host window system */
2821
2822     if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2823     { 
2824         /* Simulate a mouse event to set the cursor */
2825         DWORD posX, posY, keyState;
2826
2827         if ( EVENT_QueryPointer( &posX, &posY, &keyState ) )
2828         {
2829             int iWndsLocks = WIN_SuspendWndsLock();
2830
2831             hardware_event( WM_MOUSEMOVE, keyState, 0,
2832                             posX, posY, GetTickCount(), 0 );
2833
2834             WIN_RestoreWndsLock(iWndsLocks);
2835         }
2836     }
2837
2838     wndTemp = WIN_GetDesktop();
2839
2840     /* repaint invalidated region (if any) 
2841      *
2842      * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2843      *        and force update after ChangeActiveWindow() to avoid painting frames twice.
2844      */
2845
2846     if( visRgn )
2847     {
2848         if( !(winpos.flags & SWP_NOREDRAW) )
2849         {
2850  
2851             /*  Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2852                 its parent and sibling and so on, and then erase the parent window 
2853                 back ground if the parent is either a top-level window or its parent's parent  
2854                 is top-level window. Rely on the system to repaint other affected 
2855                 windows later on.  */ 
2856             if( uFlags & SWP_EX_PAINTSELF )
2857             {
2858                 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, 
2859                                 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2860                                 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2861             }
2862             else
2863             {
2864                     PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, 
2865                                 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN, 
2866                                 RDW_EX_USEHRGN );
2867             }
2868
2869             if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2870                 {
2871                 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, 
2872                                 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2873             }
2874         }
2875         if( visRgn != 1 )
2876             DeleteObject( visRgn );
2877     }
2878
2879     WIN_ReleaseDesktop();
2880
2881     if (!(flags & SWP_NOACTIVATE))
2882             WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2883
2884       /* And last, send the WM_WINDOWPOSCHANGED message */
2885
2886     TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2887
2888     if ( resync ||
2889         (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) && 
2890          !(winpos.flags & SWP_NOSENDCHANGING)) )
2891     {
2892         SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2893         if (resync) EVENT_Synchronize();
2894     }
2895
2896     retvalue = TRUE;
2897 END:
2898     WIN_ReleaseWndPtr(wndPtr);
2899     return retvalue;
2900 }
2901
2902                                         
2903 /***********************************************************************
2904  *           BeginDeferWindowPos16   (USER.259)
2905  */
2906 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2907 {
2908     return BeginDeferWindowPos( count );
2909 }
2910
2911
2912 /***********************************************************************
2913  *           BeginDeferWindowPos   (USER32.9)
2914  */
2915 HDWP WINAPI BeginDeferWindowPos( INT count )
2916 {
2917     HDWP handle;
2918     DWP *pDWP;
2919
2920     if (count <= 0) return 0;
2921     handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2922     if (!handle) return 0;
2923     pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2924     pDWP->actualCount    = 0;
2925     pDWP->suggestedCount = count;
2926     pDWP->valid          = TRUE;
2927     pDWP->wMagic         = DWP_MAGIC;
2928     pDWP->hwndParent     = 0;
2929     return handle;
2930 }
2931
2932
2933 /***********************************************************************
2934  *           DeferWindowPos16   (USER.260)
2935  */
2936 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2937                                 INT16 x, INT16 y, INT16 cx, INT16 cy,
2938                                 UINT16 flags )
2939 {
2940     return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2941                              x, y, cx, cy, flags );
2942 }
2943
2944
2945 /***********************************************************************
2946  *           DeferWindowPos   (USER32.128)
2947  */
2948 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2949                                 INT x, INT y, INT cx, INT cy,
2950                                 UINT flags )
2951 {
2952     DWP *pDWP;
2953     int i;
2954     HDWP newhdwp = hdwp,retvalue;
2955     /* HWND parent; */
2956     WND *pWnd;
2957
2958     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2959     if (!pDWP) return 0;
2960     if (hwnd == GetDesktopWindow()) return 0;
2961
2962     if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2963         USER_HEAP_FREE( hdwp );
2964         return 0;
2965     }
2966         
2967 /* Numega Bounds Checker Demo dislikes the following code.
2968    In fact, I've not been able to find any "same parent" requirement in any docu
2969    [AM 980509]
2970  */
2971 #if 0
2972     /* All the windows of a DeferWindowPos() must have the same parent */
2973     parent = pWnd->parent->hwndSelf;
2974     if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2975     else if (parent != pDWP->hwndParent)
2976     {
2977         USER_HEAP_FREE( hdwp );
2978         retvalue = 0;
2979         goto END;
2980     }
2981 #endif
2982
2983     for (i = 0; i < pDWP->actualCount; i++)
2984     {
2985         if (pDWP->winPos[i].hwnd == hwnd)
2986         {
2987               /* Merge with the other changes */
2988             if (!(flags & SWP_NOZORDER))
2989             {
2990                 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2991             }
2992             if (!(flags & SWP_NOMOVE))
2993             {
2994                 pDWP->winPos[i].x = x;
2995                 pDWP->winPos[i].y = y;
2996             }                
2997             if (!(flags & SWP_NOSIZE))
2998             {
2999                 pDWP->winPos[i].cx = cx;
3000                 pDWP->winPos[i].cy = cy;
3001             }
3002             pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3003                                                SWP_NOZORDER | SWP_NOREDRAW |
3004                                                SWP_NOACTIVATE | SWP_NOCOPYBITS|
3005                                                SWP_NOOWNERZORDER);
3006             pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3007                                               SWP_FRAMECHANGED);
3008             retvalue = hdwp;
3009             goto END;
3010         }
3011     }
3012     if (pDWP->actualCount >= pDWP->suggestedCount)
3013     {
3014         newhdwp = USER_HEAP_REALLOC( hdwp,
3015                       sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3016         if (!newhdwp)
3017         {
3018             retvalue = 0;
3019             goto END;
3020         }
3021         pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3022         pDWP->suggestedCount++;
3023     }
3024     pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3025     pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3026     pDWP->winPos[pDWP->actualCount].x = x;
3027     pDWP->winPos[pDWP->actualCount].y = y;
3028     pDWP->winPos[pDWP->actualCount].cx = cx;
3029     pDWP->winPos[pDWP->actualCount].cy = cy;
3030     pDWP->winPos[pDWP->actualCount].flags = flags;
3031     pDWP->actualCount++;
3032     retvalue = newhdwp;
3033 END:
3034     WIN_ReleaseWndPtr(pWnd);
3035     return retvalue;
3036 }
3037
3038
3039 /***********************************************************************
3040  *           EndDeferWindowPos16   (USER.261)
3041  */
3042 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3043 {
3044     return EndDeferWindowPos( hdwp );
3045 }
3046
3047
3048 /***********************************************************************
3049  *           EndDeferWindowPos   (USER32.173)
3050  */
3051 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3052 {
3053     DWP *pDWP;
3054     WINDOWPOS *winpos;
3055     BOOL res = TRUE;
3056     int i;
3057
3058     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3059     if (!pDWP) return FALSE;
3060     for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3061     {
3062         if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3063                                     winpos->x, winpos->y, winpos->cx,
3064                                     winpos->cy, winpos->flags ))) break;
3065     }
3066     USER_HEAP_FREE( hdwp );
3067     return res;
3068 }
3069
3070
3071 /***********************************************************************
3072  *           TileChildWindows   (USER.199)
3073  */
3074 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3075 {
3076     FIXME("(%04x, %d): stub\n", parent, action);
3077 }
3078
3079 /***********************************************************************
3080  *           CascageChildWindows   (USER.198)
3081  */
3082 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3083 {
3084     FIXME("(%04x, %d): stub\n", parent, action);
3085 }
3086
3087 /***********************************************************************
3088  *           SetProgmanWindow                   [USER32.522]
3089  */
3090 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3091 {
3092         hGlobalProgmanWindow = hwnd;
3093         return hGlobalProgmanWindow;
3094 }
3095
3096 /***********************************************************************
3097  *           GetProgmanWindow                   [USER32.289]
3098  */
3099 HRESULT WINAPI GetProgmanWindow ( )
3100 {
3101         return hGlobalProgmanWindow;
3102 }
3103
3104 /***********************************************************************
3105  *           SetShellWindowEx                   [USER32.531]
3106  * hwndProgman =  Progman[Program Manager]
3107  *                |-> SHELLDLL_DefView
3108  * hwndListView = |   |-> SysListView32
3109  *                |   |   |-> tooltips_class32
3110  *                |   |
3111  *                |   |-> SysHeader32
3112  *                |   
3113  *                |-> ProxyTarget
3114  */
3115 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3116 {
3117         FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3118         hGlobalShellWindow = hwndProgman;
3119         return hGlobalShellWindow;
3120
3121 }
3122
3123 /***********************************************************************
3124  *           SetTaskmanWindow                   [USER32.537]
3125  * NOTES
3126  *   hwnd = MSTaskSwWClass 
3127  *          |-> SysTabControl32
3128  */
3129 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3130 {
3131         hGlobalTaskmanWindow = hwnd;
3132         return hGlobalTaskmanWindow;
3133 }
3134
3135 /***********************************************************************
3136  *           GetTaskmanWindow                   [USER32.304]
3137  */
3138 HRESULT WINAPI GetTaskmanWindow ( )
3139 {       
3140         return hGlobalTaskmanWindow;
3141 }