Converted to the new debug interface, using script written by Patrik
[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             break;
1335
1336         case SW_SHOWNOACTIVATE:
1337             swp |= SWP_NOZORDER;
1338             if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1339             /* fall through */
1340         case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
1341         case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1342         case SW_RESTORE:
1343             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1344
1345             if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1346                  swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1347             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1348             break;
1349     }
1350
1351     showFlag = (cmd != SW_HIDE);
1352     if (showFlag != wasVisible)
1353     {
1354         SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1355         if (!IsWindow( hwnd )) goto END;
1356     }
1357
1358     if ((wndPtr->dwStyle & WS_CHILD) &&
1359         !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1360         (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1361     {
1362         /* Don't call SetWindowPos() on invisible child windows */
1363         if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1364         else wndPtr->dwStyle |= WS_VISIBLE;
1365     }
1366     else
1367     {
1368         /* We can't activate a child window */
1369         if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1370         if (!(swp & MINMAX_NOSWP))
1371             SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top, 
1372                                           newPos.right, newPos.bottom, LOWORD(swp) );
1373         if (!IsWindow( hwnd )) goto END;
1374         else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1375     }
1376
1377     if (wndPtr->flags & WIN_NEED_SIZE)
1378     {
1379         /* should happen only in CreateWindowEx() */
1380         int wParam = SIZE_RESTORED;
1381
1382         wndPtr->flags &= ~WIN_NEED_SIZE;
1383         if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1384         else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1385         SendMessageA( hwnd, WM_SIZE, wParam,
1386                      MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1387                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1388         SendMessageA( hwnd, WM_MOVE, 0,
1389                    MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1390     }
1391
1392 END:
1393     WIN_ReleaseWndPtr(wndPtr);
1394     return wasVisible;
1395 }
1396
1397
1398 /***********************************************************************
1399  *           GetInternalWindowPos16   (USER.460)
1400  */
1401 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1402                                       LPPOINT16 ptIcon )
1403 {
1404     WINDOWPLACEMENT16 wndpl;
1405     if (GetWindowPlacement16( hwnd, &wndpl )) 
1406     {
1407         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1408         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1409         return wndpl.showCmd;
1410     }
1411     return 0;
1412 }
1413
1414
1415 /***********************************************************************
1416  *           GetInternalWindowPos   (USER32.245)
1417  */
1418 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1419                                       LPPOINT ptIcon )
1420 {
1421     WINDOWPLACEMENT wndpl;
1422     if (GetWindowPlacement( hwnd, &wndpl ))
1423     {
1424         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1425         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1426         return wndpl.showCmd;
1427     }
1428     return 0;
1429 }
1430
1431 /***********************************************************************
1432  *           GetWindowPlacement16   (USER.370)
1433  */
1434 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1435 {
1436     WND *pWnd = WIN_FindWndPtr( hwnd );
1437     LPINTERNALPOS lpPos;
1438     
1439     if(!pWnd ) return FALSE;
1440
1441     lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1442                              *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1443         wndpl->length  = sizeof(*wndpl);
1444         if( pWnd->dwStyle & WS_MINIMIZE )
1445             wndpl->showCmd = SW_SHOWMINIMIZED;
1446         else 
1447             wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1448                              ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1449         if( pWnd->flags & WIN_RESTORE_MAX )
1450             wndpl->flags = WPF_RESTORETOMAXIMIZED;
1451         else
1452             wndpl->flags = 0;
1453         wndpl->ptMinPosition = lpPos->ptIconPos;
1454         wndpl->ptMaxPosition = lpPos->ptMaxPos;
1455         wndpl->rcNormalPosition = lpPos->rectNormal;
1456
1457     WIN_ReleaseWndPtr(pWnd);
1458         return TRUE;
1459     }
1460
1461
1462 /***********************************************************************
1463  *           GetWindowPlacement   (USER32.307)
1464  *
1465  * Win95:
1466  * Fails if wndpl->length of Win95 (!) apps is invalid.
1467  */
1468 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1469 {
1470     if( pwpl32 )
1471     {
1472         WINDOWPLACEMENT16 wpl;
1473         wpl.length = sizeof(wpl);
1474         if( GetWindowPlacement16( hwnd, &wpl ) )
1475         {
1476             pwpl32->length = sizeof(*pwpl32);
1477             pwpl32->flags = wpl.flags;
1478             pwpl32->showCmd = wpl.showCmd;
1479             CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1480             CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1481             CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1482             return TRUE;
1483         }
1484     }
1485     return FALSE;
1486 }
1487
1488
1489 /***********************************************************************
1490  *           WINPOS_SetPlacement
1491  */
1492 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1493                                                 UINT flags )
1494 {
1495     WND *pWnd = WIN_FindWndPtr( hwnd );
1496     if( pWnd )
1497     {
1498         LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1499                              *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1500
1501         if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1502         if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1503         if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1504
1505         if( pWnd->dwStyle & WS_MINIMIZE )
1506         {
1507             WINPOS_ShowIconTitle( pWnd, FALSE );
1508             if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1509                 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1510                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1511         } 
1512         else if( pWnd->dwStyle & WS_MAXIMIZE )
1513         {
1514             if( !EMPTYPOINT(lpPos->ptMaxPos) )
1515                 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1516                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1517         }
1518         else if( flags & PLACE_RECT )
1519                 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1520                                 lpPos->rectNormal.right - lpPos->rectNormal.left,
1521                                 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1522                                 SWP_NOZORDER | SWP_NOACTIVATE );
1523
1524         ShowWindow( hwnd, wndpl->showCmd );
1525         if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1526         {
1527             if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1528
1529             /* SDK: ...valid only the next time... */
1530             if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1531         }
1532         WIN_ReleaseWndPtr(pWnd);
1533         return TRUE;
1534     }
1535     return FALSE;
1536 }
1537
1538
1539 /***********************************************************************
1540  *           SetWindowPlacement16   (USER.371)
1541  */
1542 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1543 {
1544     return WINPOS_SetPlacement( hwnd, wndpl,
1545                                 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1546 }
1547
1548 /***********************************************************************
1549  *           SetWindowPlacement   (USER32.519)
1550  *
1551  * Win95:
1552  * Fails if wndpl->length of Win95 (!) apps is invalid.
1553  */
1554 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1555 {
1556     if( pwpl32 )
1557     {
1558         WINDOWPLACEMENT16 wpl;
1559
1560         wpl.length = sizeof(WINDOWPLACEMENT16);
1561         wpl.flags = pwpl32->flags;
1562         wpl.showCmd = pwpl32->showCmd;
1563         wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1564         wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1565         wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1566         wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1567         wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1568         wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1569         wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1570         wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1571
1572         return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1573     }
1574     return FALSE;
1575 }
1576
1577
1578 /***********************************************************************
1579  *           SetInternalWindowPos16   (USER.461)
1580  */
1581 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1582                                     LPRECT16 rect, LPPOINT16 pt )
1583 {
1584     if( IsWindow16(hwnd) )
1585     {
1586         WINDOWPLACEMENT16 wndpl;
1587         UINT flags;
1588
1589         wndpl.length  = sizeof(wndpl);
1590         wndpl.showCmd = showCmd;
1591         wndpl.flags = flags = 0;
1592
1593         if( pt )
1594         {
1595             flags |= PLACE_MIN;
1596             wndpl.flags |= WPF_SETMINPOSITION;
1597             wndpl.ptMinPosition = *pt;
1598         }
1599         if( rect )
1600         {
1601             flags |= PLACE_RECT;
1602             wndpl.rcNormalPosition = *rect;
1603         }
1604         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1605     }
1606 }
1607
1608
1609 /***********************************************************************
1610  *           SetInternalWindowPos   (USER32.483)
1611  */
1612 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1613                                     LPRECT rect, LPPOINT pt )
1614 {
1615     if( IsWindow(hwnd) )
1616     {
1617         WINDOWPLACEMENT16 wndpl;
1618         UINT flags;
1619
1620         wndpl.length  = sizeof(wndpl);
1621         wndpl.showCmd = showCmd;
1622         wndpl.flags = flags = 0;
1623
1624         if( pt )
1625         {
1626             flags |= PLACE_MIN;
1627             wndpl.flags |= WPF_SETMINPOSITION;
1628             CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1629         }
1630         if( rect )
1631         {
1632             flags |= PLACE_RECT;
1633             CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1634         }
1635         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1636     }
1637 }
1638
1639 /*******************************************************************
1640  *         WINPOS_SetActiveWindow
1641  *
1642  * SetActiveWindow() back-end. This is the only function that
1643  * can assign active status to a window. It must be called only
1644  * for the top level windows.
1645  */
1646 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1647 {
1648     CBTACTIVATESTRUCT16* cbtStruct;
1649     WND*     wndPtr=0, *wndTemp;
1650     HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1651     MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1652     WORD     wIconized = 0;
1653     HWND     hwndActive = 0;
1654     BOOL     bRet = 0;
1655
1656     TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1657
1658     /* Get current active window from the active queue */
1659     if ( hActiveQueue )
1660     {
1661         pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1662         if ( pOldActiveQueue )
1663             hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1664     }
1665
1666     /* paranoid checks */
1667     if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1668         goto CLEANUP_END;
1669
1670 /*  if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1671  *      return 0;
1672  */
1673     wndPtr = WIN_FindWndPtr(hWnd);
1674     hOldActiveQueue = hActiveQueue;
1675
1676     if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1677     {
1678         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1679         WIN_ReleaseWndPtr(wndTemp);
1680     }
1681     else
1682         TRACE("no current active window.\n");
1683
1684     /* call CBT hook chain */
1685     if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1686     {
1687         cbtStruct->fMouse     = fMouse;
1688         cbtStruct->hWndActive = hwndActive;
1689         bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1690                                      (LPARAM)SEGPTR_GET(cbtStruct) );
1691         SEGPTR_FREE(cbtStruct);
1692         if (bRet) goto CLEANUP_END;
1693     }
1694
1695     /* set prev active wnd to current active wnd and send notification */
1696     if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1697     {
1698         MESSAGEQUEUE *pTempActiveQueue = 0;
1699         
1700         if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1701         {
1702             if (GetSysModalWindow16() != hWnd) 
1703                 goto CLEANUP_END;
1704             /* disregard refusal if hWnd is sysmodal */
1705         }
1706
1707         SendMessageA( hwndPrevActive, WM_ACTIVATE,
1708                         MAKEWPARAM( WA_INACTIVE, wIconized ),
1709                         (LPARAM)hWnd );
1710
1711         /* check if something happened during message processing
1712          * (global active queue may have changed)
1713          */
1714         pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1715         if(!pTempActiveQueue)
1716             goto CLEANUP_END;
1717
1718         hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1719         QUEUE_Unlock( pTempActiveQueue );
1720         if( hwndPrevActive != hwndActive )
1721             goto CLEANUP_END;
1722     }
1723
1724     /* Set new active window in the message queue */
1725     hwndActive = hWnd;
1726     if ( wndPtr )
1727     {
1728         pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1729         if ( pNewActiveQueue )
1730             PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1731     }
1732     else /* have to do this or MDI frame activation goes to hell */
1733         if( pOldActiveQueue )
1734             PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1735
1736     /* send palette messages */
1737     if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1738         SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1739
1740     /* if prev wnd is minimized redraw icon title */
1741     if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1742
1743     /* managed windows will get ConfigureNotify event */  
1744     if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1745     {
1746         /* check Z-order and bring hWnd to the top */
1747         for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1748         {
1749             if (wndTemp->dwStyle & WS_VISIBLE) break;
1750         }
1751         WIN_ReleaseDesktop();
1752         WIN_ReleaseWndPtr(wndTemp);
1753
1754         if( wndTemp != wndPtr )
1755             SetWindowPos(hWnd, HWND_TOP, 0,0,0,0, 
1756                            SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1757         if (!IsWindow(hWnd))  
1758             goto CLEANUP;
1759     }
1760
1761     /* Get a handle to the new active queue */
1762     hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1763
1764     /* send WM_ACTIVATEAPP if necessary */
1765     if (hOldActiveQueue != hNewActiveQueue)
1766     {
1767         WND **list, **ppWnd;
1768         WND *pDesktop = WIN_GetDesktop();
1769
1770         if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1771         {
1772             for (ppWnd = list; *ppWnd; ppWnd++)
1773             {
1774                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1775
1776                 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1777                    SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1778                                    0, QUEUE_GetQueueTask(hNewActiveQueue) );
1779             }
1780             WIN_ReleaseWinArray(list);
1781         }
1782
1783         hActiveQueue = hNewActiveQueue;
1784
1785         if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1786         {
1787             for (ppWnd = list; *ppWnd; ppWnd++)
1788             {
1789                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1790
1791                 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1792                    SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1793                                   1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1794             }
1795             WIN_ReleaseWinArray(list);
1796         }
1797         WIN_ReleaseDesktop();
1798         
1799         if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1800     }
1801
1802     if (hWnd)
1803     {
1804         /* walk up to the first unowned window */
1805         wndTemp = WIN_LockWndPtr(wndPtr);
1806         while (wndTemp->owner)
1807         {
1808             WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1809         }
1810         /* and set last active owned popup */
1811         wndTemp->hwndLastActive = hWnd;
1812
1813         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1814         WIN_ReleaseWndPtr(wndTemp);
1815         SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1816         SendMessageA( hWnd, WM_ACTIVATE,
1817                  MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1818                  (LPARAM)hwndPrevActive );
1819         if( !IsWindow(hWnd) ) goto CLEANUP;
1820     }
1821
1822     /* change focus if possible */
1823     if ( fChangeFocus )
1824     {
1825         if ( pNewActiveQueue )
1826         {
1827             HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1828
1829             if ( WIN_GetTopParent( hOldFocus ) != hwndActive )
1830                 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus, 
1831                                    (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1832                                    0 : hwndActive );
1833         }
1834
1835         if ( pOldActiveQueue && 
1836              ( !pNewActiveQueue || 
1837                 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1838         {
1839             HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1840             if ( hOldFocus )
1841                 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1842         }
1843     }
1844
1845     if( !hwndPrevActive && wndPtr )
1846         (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1847
1848     /* if active wnd is minimized redraw icon title */
1849     if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1850
1851     bRet = (hWnd == hwndActive);  /* Success? */
1852     
1853 CLEANUP: /* Unlock the message queues before returning */
1854
1855     if ( pNewActiveQueue )
1856         QUEUE_Unlock( pNewActiveQueue );
1857
1858 CLEANUP_END:
1859
1860     if ( pOldActiveQueue )
1861         QUEUE_Unlock( pOldActiveQueue );
1862
1863     WIN_ReleaseWndPtr(wndPtr);
1864     return bRet;
1865 }
1866
1867 /*******************************************************************
1868  *         WINPOS_ActivateOtherWindow
1869  *
1870  *  Activates window other than pWnd.
1871  */
1872 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1873 {
1874   BOOL  bRet = 0;
1875   WND*          pWndTo = NULL;
1876     HWND       hwndActive = 0;
1877
1878     /* Get current active window from the active queue */
1879     if ( hActiveQueue )
1880     {
1881         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1882         if ( pActiveQueue )
1883         {
1884             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1885             QUEUE_Unlock( pActiveQueue );
1886         }
1887     }
1888
1889   if( pWnd->hwndSelf == hwndPrevActive )
1890       hwndPrevActive = 0;
1891
1892   if( hwndActive != pWnd->hwndSelf && 
1893     ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1894       return 0;
1895
1896   if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1897       !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) ) 
1898   {
1899       WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1900
1901       WIN_ReleaseWndPtr(pWndTo);
1902       pWndTo = WIN_FindWndPtr(hwndPrevActive);
1903
1904       while( !WINPOS_CanActivate(pWndTo) ) 
1905       {
1906          /* by now owned windows should've been taken care of */
1907           WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1908           WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1909           if( !pWndTo ) break;
1910       }
1911       WIN_ReleaseWndPtr(pWndPtr);
1912   }
1913
1914   bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1915
1916   /* switch desktop queue to current active */
1917   if( pWndTo )
1918   {
1919       WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1920       WIN_ReleaseWndPtr(pWndTo);
1921       WIN_ReleaseDesktop();
1922   }
1923
1924   hwndPrevActive = 0;
1925   return bRet;  
1926 }
1927
1928 /*******************************************************************
1929  *         WINPOS_ChangeActiveWindow
1930  *
1931  */
1932 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1933 {
1934     WND *wndPtr, *wndTemp;
1935     BOOL retvalue;
1936     HWND hwndActive = 0;
1937
1938     /* Get current active window from the active queue */
1939     if ( hActiveQueue )
1940     {
1941         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1942         if ( pActiveQueue )
1943         {
1944             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1945             QUEUE_Unlock( pActiveQueue );
1946         }
1947     }
1948
1949     if (!hWnd)
1950         return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1951
1952     wndPtr = WIN_FindWndPtr(hWnd);
1953     if( !wndPtr ) return FALSE;
1954
1955     /* child windows get WM_CHILDACTIVATE message */
1956     if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1957     {
1958         retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1959         goto end;
1960     }
1961
1962     if( hWnd == hwndActive )
1963     {
1964         retvalue = FALSE;
1965         goto end;
1966     }
1967
1968     if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1969     {
1970         retvalue = FALSE;
1971         goto end;
1972     }
1973
1974     /* switch desktop queue to current active */
1975     wndTemp = WIN_GetDesktop();
1976     if( wndPtr->parent == wndTemp)
1977         wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
1978     WIN_ReleaseDesktop();
1979
1980     retvalue = TRUE;
1981 end:
1982     WIN_ReleaseWndPtr(wndPtr);
1983     return retvalue;
1984 }
1985
1986
1987 /***********************************************************************
1988  *           WINPOS_SendNCCalcSize
1989  *
1990  * Send a WM_NCCALCSIZE message to a window.
1991  * All parameters are read-only except newClientRect.
1992  * oldWindowRect, oldClientRect and winpos must be non-NULL only
1993  * when calcValidRect is TRUE.
1994  */
1995 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
1996                             RECT *newWindowRect, RECT *oldWindowRect,
1997                             RECT *oldClientRect, WINDOWPOS *winpos,
1998                             RECT *newClientRect )
1999 {
2000     NCCALCSIZE_PARAMS params;
2001     WINDOWPOS winposCopy;
2002     LONG result;
2003
2004     params.rgrc[0] = *newWindowRect;
2005     if (calcValidRect)
2006     {
2007         winposCopy = *winpos;
2008         params.rgrc[1] = *oldWindowRect;
2009         params.rgrc[2] = *oldClientRect;
2010         params.lppos = &winposCopy;
2011     }
2012     result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2013                              (LPARAM)&params );
2014     TRACE("%d,%d-%d,%d\n",
2015                  params.rgrc[0].left, params.rgrc[0].top,
2016                  params.rgrc[0].right, params.rgrc[0].bottom );
2017     *newClientRect = params.rgrc[0];
2018     return result;
2019 }
2020
2021
2022 /***********************************************************************
2023  *           WINPOS_HandleWindowPosChanging16
2024  *
2025  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2026  */
2027 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2028 {
2029     POINT maxSize, minTrack;
2030     if (winpos->flags & SWP_NOSIZE) return 0;
2031     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2032         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2033     {
2034         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2035         if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2036         if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2037         if (!(wndPtr->dwStyle & WS_MINIMIZE))
2038         {
2039             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2040             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2041         }
2042     }
2043     return 0;
2044 }
2045
2046
2047 /***********************************************************************
2048  *           WINPOS_HandleWindowPosChanging
2049  *
2050  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2051  */
2052 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2053 {
2054     POINT maxSize;
2055     if (winpos->flags & SWP_NOSIZE) return 0;
2056     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2057         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2058     {
2059         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2060         winpos->cx = MIN( winpos->cx, maxSize.x );
2061         winpos->cy = MIN( winpos->cy, maxSize.y );
2062     }
2063     return 0;
2064 }
2065
2066 /***********************************************************************
2067  *           SWP_DoOwnedPopups
2068  *
2069  * fix Z order taking into account owned popups -
2070  * basically we need to maintain them above the window that owns them
2071  *
2072  * FIXME: hide/show owned popups when owner visibility changes.
2073  */
2074 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2075 {
2076     WND*        w = WIN_LockWndPtr(pDesktop->child);
2077
2078     WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2079
2080     if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2081     {
2082         /* make sure this popup stays above the owner */
2083
2084         HWND hwndLocalPrev = HWND_TOP;
2085
2086         if( hwndInsertAfter != HWND_TOP )
2087         {
2088             while( w != wndPtr->owner )
2089             {
2090                 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2091                 if( hwndLocalPrev == hwndInsertAfter ) break;
2092                 WIN_UpdateWndPtr(&w,w->next);
2093             }
2094             hwndInsertAfter = hwndLocalPrev;
2095         }
2096     }
2097     else if( wndPtr->dwStyle & WS_CHILD )
2098         goto END; 
2099
2100     WIN_UpdateWndPtr(&w, pDesktop->child);
2101
2102     while( w )
2103     {
2104         if( w == wndPtr ) break; 
2105
2106         if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2107         {
2108             SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, 
2109                  SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2110             hwndInsertAfter = w->hwndSelf;
2111         }
2112         WIN_UpdateWndPtr(&w, w->next);
2113     }
2114
2115 END:
2116     WIN_ReleaseWndPtr(w);
2117     return hwndInsertAfter;
2118 }
2119
2120 /***********************************************************************
2121  *           SWP_CopyValidBits
2122  *
2123  * Make window look nice without excessive repainting
2124  *
2125  * visible and update regions are in window coordinates
2126  * client and window rectangles are in parent client coordinates
2127  *
2128  * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2129  *        window rects have the same origin.
2130  *
2131  * Returns: uFlags and a dirty region in *pVisRgn.
2132  */
2133 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2134                                LPRECT lpOldWndRect,
2135                                LPRECT lpOldClientRect, UINT uFlags )
2136 {
2137  RECT r;
2138  HRGN newVisRgn, dirtyRgn;
2139  INT  my = COMPLEXREGION;
2140
2141  TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2142               Wnd->rectWindow.left, Wnd->rectWindow.top,
2143               Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2144               lpOldWndRect->left, lpOldWndRect->top,
2145               lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2146  TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2147               Wnd->rectClient.left, Wnd->rectClient.top,
2148               Wnd->rectClient.right, Wnd->rectClient.bottom,
2149               lpOldClientRect->left, lpOldClientRect->top,
2150               lpOldClientRect->right,lpOldClientRect->bottom );
2151
2152  if( Wnd->hrgnUpdate == 1 )
2153      uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2154
2155  newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2156  dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2157
2158  if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2159      my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2160
2161  if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2162  {
2163 nocopy:
2164
2165      TRACE("\twon't copy anything!\n");
2166
2167      /* set dirtyRgn to the sum of old and new visible regions 
2168       * in parent client coordinates */
2169
2170      OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2171      OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2172
2173      CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2174  }
2175  else                   /* copy valid bits to a new location */
2176  {
2177      INT  dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2178      HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2179
2180      /* subtract already invalid region inside Wnd from the dst region */
2181
2182      if( Wnd->hrgnUpdate )
2183          if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2184              goto nocopy;
2185
2186      /* check if entire window can be copied */
2187
2188      ow = lpOldWndRect->right - lpOldWndRect->left;
2189      oh = lpOldWndRect->bottom - lpOldWndRect->top;
2190      nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2191      nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2192
2193      ocw = lpOldClientRect->right - lpOldClientRect->left;
2194      och = lpOldClientRect->bottom - lpOldClientRect->top;
2195      ncw = Wnd->rectClient.right  - Wnd->rectClient.left;
2196      nch = Wnd->rectClient.bottom  - Wnd->rectClient.top;
2197
2198      if(  (ocw != ncw) || (och != nch) ||
2199           ( ow !=  nw) || ( oh !=  nh) ||
2200           ((lpOldClientRect->top - lpOldWndRect->top)   != 
2201            (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2202           ((lpOldClientRect->left - lpOldWndRect->left) !=
2203            (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2204      {
2205         dx = Wnd->rectClient.left - lpOldClientRect->left;
2206         dy = Wnd->rectClient.top - lpOldClientRect->top;
2207
2208         /* restrict valid bits to the common client rect */
2209
2210         r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2211         r.top = Wnd->rectClient.top  - Wnd->rectWindow.top;
2212         r.right = r.left + MIN( ocw, ncw );
2213         r.bottom = r.top + MIN( och, nch );
2214
2215         REGION_CropRgn( hrgnValid, hrgnValid, &r, 
2216                         (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2217         GetRgnBox( hrgnValid, &r );
2218         if( IsRectEmpty( &r ) )
2219             goto nocopy;
2220         r = *lpOldClientRect;
2221      }
2222      else
2223      {
2224         dx = Wnd->rectWindow.left - lpOldWndRect->left;
2225         dy = Wnd->rectWindow.top -  lpOldWndRect->top;
2226         if( !(uFlags & SWP_EX_PAINTSELF) )
2227             OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2228         r = *lpOldWndRect;
2229      }
2230
2231      if( !(uFlags & SWP_EX_PAINTSELF) )
2232      {
2233         /* Move remaining regions to parent coordinates */
2234         OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2235         OffsetRgn( *pVisRgn,  lpOldWndRect->left, lpOldWndRect->top );
2236      }
2237      else
2238         OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2239
2240      TRACE("\tcomputing dirty region!\n");
2241
2242      /* Compute combined dirty region (old + new - valid) */
2243      CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2244      CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2245
2246      /* Blt valid bits, r is the rect to copy  */
2247
2248      if( dx || dy )
2249      {
2250          RECT rClip;
2251          HDC hDC;
2252          DC* dc;
2253
2254          /* get DC and clip rect with drawable rect to avoid superfluous expose events
2255             from copying clipped areas */
2256
2257          if( uFlags & SWP_EX_PAINTSELF )
2258          {
2259              hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2260                             DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2261              rClip.right = nw; rClip.bottom = nh;
2262          }
2263          else
2264          {
2265              hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2266                             DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2267              rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2268              rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2269          }
2270          rClip.left = rClip.top = 0;    
2271
2272          if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2273          {
2274             if( oh > nh ) r.bottom = r.top  + nh;
2275             if( ow < nw ) r.right = r.left  + nw;
2276
2277             if( IntersectRect( &r, &r, &rClip ) )
2278                 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2279
2280             GDI_HEAP_UNLOCK( hDC );
2281          }
2282          ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ? 
2283                      Wnd->hwndSelf :  Wnd->parent->hwndSelf, hDC); 
2284      }
2285  }
2286
2287  /* *pVisRgn now points to the invalidated region */
2288
2289  DeleteObject(newVisRgn);
2290  DeleteObject(dirtyRgn);
2291  return uFlags;
2292 }
2293
2294 /***********************************************************************
2295  *           SWP_DoSimpleFrameChanged
2296  *
2297  * NOTE: old and new client rect origins are identical, only
2298  *       extents may have changed. Window extents are the same.
2299  */
2300 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2301 {
2302     INT  i = 0;
2303     RECT rect;
2304     HRGN hrgn = 0;
2305
2306     if( !(swpFlags & SWP_NOCLIENTSIZE) )
2307     {
2308         /* Client rect changed its position/size, most likely a scrollar
2309          * was added/removed.
2310          *
2311          * FIXME: WVR alignment flags 
2312          */
2313
2314         if( wndPtr->rectClient.right >  pOldClientRect->right ) /* right edge */
2315         {
2316             i++;
2317             rect.top = 0; 
2318             rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2319             rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2320             if(!(uFlags & SWP_EX_NOCOPY))
2321                 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2322             else
2323             {
2324                 rect.left = 0;
2325                 goto redraw;
2326             }
2327         }
2328
2329         if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2330         {
2331             if( i )
2332                 hrgn = CreateRectRgnIndirect( &rect );
2333             rect.left = 0;
2334             rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2335             rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2336             if(!(uFlags & SWP_EX_NOCOPY))
2337                 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2338             else
2339                 rect.top = 0;
2340             if( i++ ) 
2341                 REGION_UnionRectWithRgn( hrgn, &rect );
2342         }
2343
2344         if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2345         {
2346             rect = wndPtr->rectWindow;
2347             OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2348                                wndPtr->rectWindow.top - wndPtr->rectClient.top );
2349             i++;
2350         }
2351     }
2352
2353     if( i )
2354     {
2355 redraw:
2356         PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2357                             RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2358     }
2359     else
2360     {
2361         WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2362     }
2363
2364     if( hrgn > 1 )
2365         DeleteObject( hrgn );
2366 }
2367
2368 /***********************************************************************
2369  *           SWP_DoWinPosChanging
2370  */
2371 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos, 
2372                                   RECT* pNewWindowRect, RECT* pNewClientRect )
2373 {
2374       /* Send WM_WINDOWPOSCHANGING message */
2375
2376     if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2377         SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2378
2379       /* Calculate new position and size */
2380
2381     *pNewWindowRect = wndPtr->rectWindow;
2382     *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2383                                                     : wndPtr->rectClient;
2384
2385     if (!(pWinpos->flags & SWP_NOSIZE))
2386     {
2387         pNewWindowRect->right  = pNewWindowRect->left + pWinpos->cx;
2388         pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2389     }
2390     if (!(pWinpos->flags & SWP_NOMOVE))
2391     {
2392         pNewWindowRect->left    = pWinpos->x;
2393         pNewWindowRect->top     = pWinpos->y;
2394         pNewWindowRect->right  += pWinpos->x - wndPtr->rectWindow.left;
2395         pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2396
2397         OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2398                                     pWinpos->y - wndPtr->rectWindow.top );
2399     }
2400
2401     pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2402     return TRUE;
2403 }
2404
2405 /***********************************************************************
2406  *           SWP_DoNCCalcSize
2407  */
2408 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2409                               RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2410 {
2411     UINT wvrFlags = 0;
2412
2413       /* Send WM_NCCALCSIZE message to get new client area */
2414     if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2415     {
2416          wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2417                                     &wndPtr->rectWindow, &wndPtr->rectClient,
2418                                     pWinpos, pNewClientRect );
2419
2420          /* FIXME: WVR_ALIGNxxx */
2421
2422          if( pNewClientRect->left != wndPtr->rectClient.left ||
2423              pNewClientRect->top != wndPtr->rectClient.top )
2424              pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2425
2426          if( (pNewClientRect->right - pNewClientRect->left !=
2427               wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2428              (pNewClientRect->bottom - pNewClientRect->top !=
2429               wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2430              pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2431     }
2432     else
2433       if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2434                                 pNewClientRect->top != wndPtr->rectClient.top) )
2435             pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2436     return wvrFlags;
2437 }
2438
2439 /***********************************************************************
2440  *           SetWindowPos   (USER.2)
2441  */
2442 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2443                               INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2444 {
2445     return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2446 }
2447
2448 /***********************************************************************
2449  *           SetWindowPos   (USER32.520)
2450  */
2451 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2452                           INT x, INT y, INT cx, INT cy, UINT flags )
2453 {
2454     WINDOWPOS   winpos;
2455     WND *       wndPtr,*wndTemp;
2456     RECT        newWindowRect, newClientRect;
2457     RECT        oldWindowRect, oldClientRect;
2458     HRGN        visRgn = 0;
2459     UINT        wvrFlags = 0, uFlags = 0;
2460     BOOL        retvalue, resync = FALSE, bChangePos;
2461     HWND        hwndActive = 0;
2462
2463     /* Get current active window from the active queue */
2464     if ( hActiveQueue )
2465     {
2466         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2467         if ( pActiveQueue )
2468         {
2469             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2470             QUEUE_Unlock( pActiveQueue );
2471         }
2472     }
2473
2474     TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n", 
2475                                                  hwnd, x, y, x+cx, y+cy, flags);  
2476
2477     bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2478     flags &= ~SWP_WINE_NOHOSTMOVE;
2479
2480
2481       /* ------------------------------------------------------------------------ CHECKS */
2482
2483       /* Check window handle */
2484
2485     if (hwnd == GetDesktopWindow()) return FALSE;
2486     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2487
2488     TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2489                           wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2490
2491       /* Fix redundant flags */
2492
2493     if(wndPtr->dwStyle & WS_VISIBLE)
2494         flags &= ~SWP_SHOWWINDOW;
2495     else
2496     {
2497         if (!(flags & SWP_SHOWWINDOW)) 
2498               flags |= SWP_NOREDRAW;
2499         flags &= ~SWP_HIDEWINDOW;
2500     }
2501
2502     if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2503
2504     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2505         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2506         flags |= SWP_NOSIZE;    /* Already the right size */
2507
2508     if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2509         flags |= SWP_NOMOVE;    /* Already the right position */
2510
2511     if (hwnd == hwndActive)
2512         flags |= SWP_NOACTIVATE;   /* Already active */
2513     else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2514     {
2515         if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2516         {
2517             flags &= ~SWP_NOZORDER;
2518             hwndInsertAfter = HWND_TOP;           
2519             goto Pos;
2520         }
2521     }
2522
2523       /* Check hwndInsertAfter */
2524
2525       /* FIXME: TOPMOST not supported yet */
2526     if ((hwndInsertAfter == HWND_TOPMOST) ||
2527         (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2528
2529       /* hwndInsertAfter must be a sibling of the window */
2530     if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2531     {
2532          WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2533
2534          if( wnd ) {
2535              if( wnd->parent != wndPtr->parent )
2536              {
2537                  retvalue = FALSE;
2538                  WIN_ReleaseWndPtr(wnd);
2539                  goto END;
2540              }
2541            if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2542          }
2543          WIN_ReleaseWndPtr(wnd);
2544     }
2545
2546 Pos:  /* ------------------------------------------------------------------------ MAIN part */
2547
2548       /* Fill the WINDOWPOS structure */
2549
2550     winpos.hwnd = hwnd;
2551     winpos.hwndInsertAfter = hwndInsertAfter;
2552     winpos.x = x;
2553     winpos.y = y;
2554     winpos.cx = cx;
2555     winpos.cy = cy;
2556     winpos.flags = flags;
2557     
2558     SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2559
2560     if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2561     {
2562         if( wndPtr->parent == WIN_GetDesktop() )
2563             hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2564                                         hwndInsertAfter, winpos.flags );
2565         WIN_ReleaseDesktop();
2566     }
2567
2568     if(!(wndPtr->flags & WIN_NATIVE) )
2569     {
2570         if( hwndInsertAfter == HWND_TOP )
2571            winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2572         else
2573         if( hwndInsertAfter == HWND_BOTTOM )
2574            winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2575         else
2576         if( !(winpos.flags & SWP_NOZORDER) )
2577            if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2578                winpos.flags |= SWP_NOZORDER;
2579
2580         if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2581             ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2582                           != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2583         {
2584             /* get a previous visible region for SWP_CopyValidBits() */
2585
2586             visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2587         }
2588     }
2589
2590     /* Common operations */
2591
2592     wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2593
2594     if(!(winpos.flags & SWP_NOZORDER))
2595     {
2596         if ( WIN_UnlinkWindow( winpos.hwnd ) )
2597            WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2598     }
2599
2600     /* Reset active DCEs */
2601
2602     if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) && 
2603                                          wndPtr->dwStyle & WS_VISIBLE) || 
2604         (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) ) 
2605     {
2606         RECT rect;
2607
2608         UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2609         DCE_InvalidateDCE(wndPtr, &rect);
2610     }
2611
2612     oldWindowRect = wndPtr->rectWindow;
2613     oldClientRect = wndPtr->rectClient;
2614
2615     /* Find out if we have to redraw the whole client rect */
2616
2617     if( oldClientRect.bottom - oldClientRect.top ==
2618         newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2619
2620     if( oldClientRect.right - oldClientRect.left ==
2621         newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2622
2623     if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2624            (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2625     {
2626         uFlags |= SWP_EX_NOCOPY;
2627     }
2628 /* 
2629  *  Use this later in CopyValidBits()
2630  *
2631     else if( 0  )
2632         uFlags |= SWP_EX_NONCLIENT; 
2633  */
2634
2635     /* FIXME: actually do something with WVR_VALIDRECTS */
2636
2637     wndPtr->rectWindow = newWindowRect;
2638     wndPtr->rectClient = newClientRect;
2639
2640     if (wndPtr->flags & WIN_NATIVE)     /* -------------------------------------------- hosted window */
2641     {
2642         BOOL bCallDriver = TRUE;
2643         HWND tempInsertAfter = winpos.hwndInsertAfter;
2644
2645         winpos.hwndInsertAfter = hwndInsertAfter;
2646
2647         if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2648         {
2649           /* This is the only place where we need to force repainting of the contents
2650              of windows created by the host window system, all other cases go through the
2651              expose event handling */
2652
2653             if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2654             {
2655                 cx = newWindowRect.right - newWindowRect.left;
2656                 cy = newWindowRect.bottom - newWindowRect.top;
2657
2658                 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2659                 winpos.hwndInsertAfter = tempInsertAfter;
2660                 bCallDriver = FALSE;
2661
2662                 if( winpos.flags & SWP_NOCLIENTMOVE )
2663                     SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2664                 else
2665                 {
2666                     /* client area moved but window extents remained the same, copy valid bits */
2667
2668                     visRgn = CreateRectRgn( 0, 0, cx, cy );
2669                     uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect, 
2670                                                 uFlags | SWP_EX_PAINTSELF );
2671                 }
2672             }
2673         }
2674
2675         if( bCallDriver )
2676         {
2677             if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2678             {
2679                 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2680                     (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2681                    !(uFlags & SWP_EX_NOCOPY) )
2682                 {
2683                   /* The origin of the client rect didn't move so we can try to repaint
2684                    * only the nonclient area by setting bit gravity hint for the host window system.
2685                    */
2686
2687                     if( !(wndPtr->flags & WIN_MANAGED) )
2688                     {
2689                         HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2690                                                      newWindowRect.bottom - newWindowRect.top);
2691                         RECT rcn = newClientRect;
2692                         RECT rco = oldClientRect;
2693
2694                         OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2695                         OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2696                         IntersectRect( &rcn, &rcn, &rco );
2697                         visRgn = CreateRectRgnIndirect( &rcn );
2698                         CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2699                         DeleteObject( hrgn );
2700                         uFlags = SWP_EX_PAINTSELF;
2701                     }
2702                     wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2703                 }
2704                 else
2705                     wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2706             }
2707
2708             wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2709             winpos.hwndInsertAfter = tempInsertAfter;
2710         }
2711
2712         if( winpos.flags & SWP_SHOWWINDOW )
2713         {
2714                 HWND focus, curr;
2715
2716                 wndPtr->dwStyle |= WS_VISIBLE;
2717
2718                 if (wndPtr->flags & WIN_MANAGED) resync = TRUE; 
2719
2720                 /* focus was set to unmapped window, reset host focus 
2721                  * since the window is now visible */
2722
2723                 focus = curr = GetFocus();
2724                 while (curr) 
2725                 {
2726                     if (curr == hwnd) 
2727                     {
2728                         WND *pFocus = WIN_FindWndPtr( focus );
2729                         if (pFocus)
2730                             pFocus->pDriver->pSetFocus(pFocus);
2731                         WIN_ReleaseWndPtr(pFocus);
2732                         break;
2733                     }
2734                     curr = GetParent(curr);
2735                 }
2736         }
2737     }
2738     else                                /* -------------------------------------------- emulated window */
2739     {
2740             if( winpos.flags & SWP_SHOWWINDOW )
2741             {
2742                 wndPtr->dwStyle |= WS_VISIBLE;
2743                 uFlags |= SWP_EX_PAINTSELF;
2744                 visRgn = 1; /* redraw the whole window */
2745             }
2746             else if( !(winpos.flags & SWP_NOREDRAW) )
2747             {
2748                 if( winpos.flags & SWP_HIDEWINDOW )
2749                 {
2750                     if( visRgn > 1 ) /* map to parent */
2751                         OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2752                     else
2753                         visRgn = 0;
2754                 }
2755                 else
2756                 {
2757                     if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2758                          uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect, 
2759                                                             &oldClientRect, uFlags);
2760                     else
2761                     {
2762                         /* nothing moved, redraw frame if needed */
2763                          
2764                         if( winpos.flags & SWP_FRAMECHANGED )
2765                             SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2766                         if( visRgn )
2767                         {
2768                             DeleteObject( visRgn );
2769                             visRgn = 0;
2770                         } 
2771                     }
2772                 }
2773             }
2774     }
2775
2776     if( winpos.flags & SWP_HIDEWINDOW )
2777     {
2778         wndPtr->dwStyle &= ~WS_VISIBLE;
2779
2780         if (hwnd == CARET_GetHwnd()) DestroyCaret();
2781
2782         /* FIXME: This will cause the window to be activated irrespective
2783          * of whether it is owned by the same thread. Has to be done
2784          * asynchronously.
2785          */
2786
2787         if (winpos.hwnd == hwndActive)
2788             WINPOS_ActivateOtherWindow( wndPtr );
2789     }
2790
2791     /* ------------------------------------------------------------------------ FINAL */
2792
2793     if (wndPtr->flags & WIN_NATIVE)
2794         EVENT_Synchronize( TRUE );  /* Synchronize with the host window system */
2795
2796     if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2797     { 
2798         /* Simulate a mouse event to set the cursor */
2799         DWORD posX, posY, keyState;
2800
2801         if ( EVENT_QueryPointer( &posX, &posY, &keyState ) )
2802         {
2803             int iWndsLocks = WIN_SuspendWndsLock();
2804
2805             hardware_event( WM_MOUSEMOVE, keyState, 0,
2806                             posX, posY, GetTickCount(), 0 );
2807
2808             WIN_RestoreWndsLock(iWndsLocks);
2809         }
2810     }
2811
2812     wndTemp = WIN_GetDesktop();
2813
2814     /* repaint invalidated region (if any) 
2815      *
2816      * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2817      *        and force update after ChangeActiveWindow() to avoid painting frames twice.
2818      */
2819
2820     if( visRgn )
2821     {
2822         if( !(winpos.flags & SWP_NOREDRAW) )
2823         {
2824             if (wndPtr->parent == wndTemp)
2825             {   
2826                 /*  Desktop does not receive wm_paint message so we use RDW_ERASENOW to erase the 
2827                     the desktop window  */
2828  
2829             if( uFlags & SWP_EX_PAINTSELF )
2830             {
2831                 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE | RDW_FRAME |
2832                                   ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
2833                                     RDW_ALLCHILDREN, RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2834             }
2835             else
2836             {
2837                     PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, 
2838                           RDW_ERASE | RDW_ERASENOW | RDW_INVALIDATE | RDW_ALLCHILDREN, RDW_EX_USEHRGN );
2839                 }
2840             }
2841             else
2842             {
2843                 if( uFlags & SWP_EX_PAINTSELF )
2844                 {
2845                     /*  Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2846                         its parent and sibling and so on, and then update the parent window, 
2847                         the non-top-level window. Rely on the system to repaint other affected 
2848                         windows later on.  */ 
2849
2850                     PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE | 
2851                          RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN, RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2852                 }
2853                 else
2854                 {
2855                     PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, 
2856                          RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN, RDW_EX_USEHRGN );
2857
2858                     UpdateWindow( wndPtr->parent->hwndSelf);
2859                 }
2860             }
2861         }
2862         if( visRgn != 1 )
2863             DeleteObject( visRgn );
2864     }
2865
2866     WIN_ReleaseDesktop();
2867
2868     if (!(flags & SWP_NOACTIVATE))
2869             WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2870
2871       /* And last, send the WM_WINDOWPOSCHANGED message */
2872
2873     TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2874
2875     if ( resync ||
2876         (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) && 
2877          !(winpos.flags & SWP_NOSENDCHANGING)) )
2878     {
2879         SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2880         if (resync) EVENT_Synchronize ( TRUE );
2881     }
2882
2883     retvalue = TRUE;
2884 END:
2885     WIN_ReleaseWndPtr(wndPtr);
2886     return retvalue;
2887 }
2888
2889                                         
2890 /***********************************************************************
2891  *           BeginDeferWindowPos16   (USER.259)
2892  */
2893 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2894 {
2895     return BeginDeferWindowPos( count );
2896 }
2897
2898
2899 /***********************************************************************
2900  *           BeginDeferWindowPos   (USER32.9)
2901  */
2902 HDWP WINAPI BeginDeferWindowPos( INT count )
2903 {
2904     HDWP handle;
2905     DWP *pDWP;
2906
2907     if (count <= 0) return 0;
2908     handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2909     if (!handle) return 0;
2910     pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2911     pDWP->actualCount    = 0;
2912     pDWP->suggestedCount = count;
2913     pDWP->valid          = TRUE;
2914     pDWP->wMagic         = DWP_MAGIC;
2915     pDWP->hwndParent     = 0;
2916     return handle;
2917 }
2918
2919
2920 /***********************************************************************
2921  *           DeferWindowPos16   (USER.260)
2922  */
2923 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2924                                 INT16 x, INT16 y, INT16 cx, INT16 cy,
2925                                 UINT16 flags )
2926 {
2927     return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2928                              x, y, cx, cy, flags );
2929 }
2930
2931
2932 /***********************************************************************
2933  *           DeferWindowPos   (USER32.128)
2934  */
2935 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2936                                 INT x, INT y, INT cx, INT cy,
2937                                 UINT flags )
2938 {
2939     DWP *pDWP;
2940     int i;
2941     HDWP newhdwp = hdwp,retvalue;
2942     /* HWND parent; */
2943     WND *pWnd;
2944
2945     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2946     if (!pDWP) return 0;
2947     if (hwnd == GetDesktopWindow()) return 0;
2948
2949     if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2950         USER_HEAP_FREE( hdwp );
2951         return 0;
2952     }
2953         
2954 /* Numega Bounds Checker Demo dislikes the following code.
2955    In fact, I've not been able to find any "same parent" requirement in any docu
2956    [AM 980509]
2957  */
2958 #if 0
2959     /* All the windows of a DeferWindowPos() must have the same parent */
2960     parent = pWnd->parent->hwndSelf;
2961     if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2962     else if (parent != pDWP->hwndParent)
2963     {
2964         USER_HEAP_FREE( hdwp );
2965         retvalue = 0;
2966         goto END;
2967     }
2968 #endif
2969
2970     for (i = 0; i < pDWP->actualCount; i++)
2971     {
2972         if (pDWP->winPos[i].hwnd == hwnd)
2973         {
2974               /* Merge with the other changes */
2975             if (!(flags & SWP_NOZORDER))
2976             {
2977                 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2978             }
2979             if (!(flags & SWP_NOMOVE))
2980             {
2981                 pDWP->winPos[i].x = x;
2982                 pDWP->winPos[i].y = y;
2983             }                
2984             if (!(flags & SWP_NOSIZE))
2985             {
2986                 pDWP->winPos[i].cx = cx;
2987                 pDWP->winPos[i].cy = cy;
2988             }
2989             pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2990                                                SWP_NOZORDER | SWP_NOREDRAW |
2991                                                SWP_NOACTIVATE | SWP_NOCOPYBITS|
2992                                                SWP_NOOWNERZORDER);
2993             pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2994                                               SWP_FRAMECHANGED);
2995             retvalue = hdwp;
2996             goto END;
2997         }
2998     }
2999     if (pDWP->actualCount >= pDWP->suggestedCount)
3000     {
3001         newhdwp = USER_HEAP_REALLOC( hdwp,
3002                       sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3003         if (!newhdwp)
3004         {
3005             retvalue = 0;
3006             goto END;
3007         }
3008         pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3009         pDWP->suggestedCount++;
3010     }
3011     pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3012     pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3013     pDWP->winPos[pDWP->actualCount].x = x;
3014     pDWP->winPos[pDWP->actualCount].y = y;
3015     pDWP->winPos[pDWP->actualCount].cx = cx;
3016     pDWP->winPos[pDWP->actualCount].cy = cy;
3017     pDWP->winPos[pDWP->actualCount].flags = flags;
3018     pDWP->actualCount++;
3019     retvalue = newhdwp;
3020 END:
3021     WIN_ReleaseWndPtr(pWnd);
3022     return retvalue;
3023 }
3024
3025
3026 /***********************************************************************
3027  *           EndDeferWindowPos16   (USER.261)
3028  */
3029 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3030 {
3031     return EndDeferWindowPos( hdwp );
3032 }
3033
3034
3035 /***********************************************************************
3036  *           EndDeferWindowPos   (USER32.173)
3037  */
3038 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3039 {
3040     DWP *pDWP;
3041     WINDOWPOS *winpos;
3042     BOOL res = TRUE;
3043     int i;
3044
3045     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3046     if (!pDWP) return FALSE;
3047     for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3048     {
3049         if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3050                                     winpos->x, winpos->y, winpos->cx,
3051                                     winpos->cy, winpos->flags ))) break;
3052     }
3053     USER_HEAP_FREE( hdwp );
3054     return res;
3055 }
3056
3057
3058 /***********************************************************************
3059  *           TileChildWindows   (USER.199)
3060  */
3061 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3062 {
3063     FIXME("(%04x, %d): stub\n", parent, action);
3064 }
3065
3066 /***********************************************************************
3067  *           CascageChildWindows   (USER.198)
3068  */
3069 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3070 {
3071     FIXME("(%04x, %d): stub\n", parent, action);
3072 }
3073
3074 /***********************************************************************
3075  *           SetProgmanWindow                   [USER32.522]
3076  */
3077 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3078 {
3079         hGlobalProgmanWindow = hwnd;
3080         return hGlobalProgmanWindow;
3081 }
3082
3083 /***********************************************************************
3084  *           GetProgmanWindow                   [USER32.289]
3085  */
3086 HRESULT WINAPI GetProgmanWindow ( )
3087 {
3088         return hGlobalProgmanWindow;
3089 }
3090
3091 /***********************************************************************
3092  *           SetShellWindowEx                   [USER32.531]
3093  * hwndProgman =  Progman[Program Manager]
3094  *                |-> SHELLDLL_DefView
3095  * hwndListView = |   |-> SysListView32
3096  *                |   |   |-> tooltips_class32
3097  *                |   |
3098  *                |   |-> SysHeader32
3099  *                |   
3100  *                |-> ProxyTarget
3101  */
3102 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3103 {
3104         FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3105         hGlobalShellWindow = hwndProgman;
3106         return hGlobalShellWindow;
3107
3108 }
3109
3110 /***********************************************************************
3111  *           SetTaskmanWindow                   [USER32.537]
3112  * NOTES
3113  *   hwnd = MSTaskSwWClass 
3114  *          |-> SysTabControl32
3115  */
3116 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3117 {
3118         hGlobalTaskmanWindow = hwnd;
3119         return hGlobalTaskmanWindow;
3120 }
3121
3122 /***********************************************************************
3123  *           GetTaskmanWindow                   [USER32.304]
3124  */
3125 HRESULT WINAPI GetTaskmanWindow ( )
3126 {       
3127         return hGlobalTaskmanWindow;
3128 }