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