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