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