Don't close groups of polylines.
[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  *         ChildWindowFromPointEx   (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_VISIBLE | WS_CHILD))
815        == WS_VISIBLE ) ) return TRUE;
816     return FALSE;
817 }
818
819
820 /*******************************************************************
821  *         SetActiveWindow16    (USER.59)
822  */
823 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
824 {
825     return SetActiveWindow(hwnd);
826 }
827
828
829 /*******************************************************************
830  *         SetActiveWindow    (USER32.463)
831  */
832 HWND WINAPI SetActiveWindow( HWND hwnd )
833 {
834     HWND prev = 0;
835     WND *wndPtr = WIN_FindWndPtr( hwnd );
836     MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
837
838     if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
839     {
840         prev = 0;
841         goto end;
842     }
843
844     /* Get the messageQ for the current thread */
845     if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
846     {
847         WARN("\tCurrent message queue not found. Exiting!\n" );
848         goto CLEANUP;
849     }
850     
851     /* Retrieve the message queue associated with this window */
852     pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
853     if ( !pMsgQ )
854     {
855         WARN("\tWindow message queue not found. Exiting!\n" );
856         goto CLEANUP;
857     }
858
859     /* Make sure that the window is associated with the calling threads
860      * message queue. It must share the same perQ data.
861      */
862     
863     if ( pCurMsgQ->pQData != pMsgQ->pQData )
864         goto CLEANUP;
865     
866     /* Save current active window */
867     prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
868     
869     WINPOS_SetActiveWindow( hwnd, 0, 0 );
870
871 CLEANUP:
872     /* Unlock the queues before returning */
873     if ( pMsgQ )
874         QUEUE_Unlock( pMsgQ );
875     if ( pCurMsgQ )
876         QUEUE_Unlock( pCurMsgQ );
877     
878 end:
879     WIN_ReleaseWndPtr(wndPtr);
880     return prev;
881 }
882
883
884 /*******************************************************************
885  *         GetForegroundWindow16    (USER.608)
886  */
887 HWND16 WINAPI GetForegroundWindow16(void)
888 {
889     return (HWND16)GetForegroundWindow();
890 }
891
892
893 /*******************************************************************
894  *         SetForegroundWindow16    (USER.609)
895  */
896 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
897 {
898     return SetForegroundWindow( hwnd );
899 }
900
901
902 /*******************************************************************
903  *         GetForegroundWindow    (USER32.241)
904  */
905 HWND WINAPI GetForegroundWindow(void)
906 {
907     HWND hwndActive = 0;
908
909     /* Get the foreground window (active window of hActiveQueue) */
910     if ( hActiveQueue )
911     {
912         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
913         if ( pActiveQueue )
914             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
915
916         QUEUE_Unlock( pActiveQueue );
917     }
918
919     return hwndActive;
920 }
921
922 /*******************************************************************
923  *         SetForegroundWindow    (USER32.482)
924  */
925 BOOL WINAPI SetForegroundWindow( HWND hwnd )
926 {
927     return WINPOS_ChangeActiveWindow( hwnd, FALSE );
928 }
929
930
931 /*******************************************************************
932  *         GetShellWindow16    (USER.600)
933  */
934 HWND16 WINAPI GetShellWindow16(void)
935 {
936     return GetShellWindow();
937 }
938
939 /*******************************************************************
940  *         SetShellWindow    (USER32.504)
941  */
942 HWND WINAPI SetShellWindow(HWND hwndshell)
943 {   WARN("(hWnd=%08x) semi stub\n",hwndshell );
944
945     hGlobalShellWindow = hwndshell;
946     return hGlobalShellWindow;
947 }
948
949
950 /*******************************************************************
951  *         GetShellWindow    (USER32.287)
952  */
953 HWND WINAPI GetShellWindow(void)
954 {   WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
955
956     return hGlobalShellWindow;
957 }
958
959
960 /***********************************************************************
961  *           BringWindowToTop16   (USER.45)
962  */
963 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
964 {
965     return BringWindowToTop(hwnd);
966 }
967
968
969 /***********************************************************************
970  *           BringWindowToTop   (USER32.11)
971  */
972 BOOL WINAPI BringWindowToTop( HWND hwnd )
973 {
974     return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
975 }
976
977
978 /***********************************************************************
979  *           MoveWindow16   (USER.56)
980  */
981 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
982                             BOOL16 repaint )
983 {
984     return MoveWindow(hwnd,x,y,cx,cy,repaint);
985 }
986
987
988 /***********************************************************************
989  *           MoveWindow   (USER32.399)
990  */
991 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
992                             BOOL repaint )
993 {    
994     int flags = SWP_NOZORDER | SWP_NOACTIVATE;
995     if (!repaint) flags |= SWP_NOREDRAW;
996     TRACE("%04x %d,%d %dx%d %d\n", 
997             hwnd, x, y, cx, cy, repaint );
998     return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
999 }
1000
1001 /***********************************************************************
1002  *           WINPOS_InitInternalPos
1003  */
1004 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt, 
1005                                              LPRECT restoreRect )
1006 {
1007     LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1008                                                       atomInternalPos );
1009     if( !lpPos )
1010     {
1011         /* this happens when the window is minimized/maximized 
1012          * for the first time (rectWindow is not adjusted yet) */
1013
1014         lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1015         if( !lpPos ) return NULL;
1016
1017         SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1018         lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1019         CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1020         *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1021     }
1022
1023     if( wnd->dwStyle & WS_MINIMIZE ) 
1024         CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1025     else if( wnd->dwStyle & WS_MAXIMIZE ) 
1026         CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1027     else if( restoreRect ) 
1028         CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1029
1030     return lpPos;
1031 }
1032
1033 /***********************************************************************
1034  *           WINPOS_RedrawIconTitle
1035  */
1036 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1037 {
1038     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1039     if( lpPos )
1040     {
1041         if( lpPos->hwndIconTitle )
1042         {
1043             SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1044             InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1045             return TRUE;
1046         }
1047     }
1048     return FALSE;
1049 }
1050
1051 /***********************************************************************
1052  *           WINPOS_ShowIconTitle
1053  */
1054 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1055 {
1056     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1057
1058     if( lpPos && !(pWnd->flags & WIN_MANAGED))
1059     {
1060         HWND16 hWnd = lpPos->hwndIconTitle;
1061
1062         TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1063
1064         if( !hWnd )
1065             lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1066         if( bShow )
1067         {
1068             if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL) 
1069             {
1070                 if( !(pWnd->dwStyle & WS_VISIBLE) )
1071                 {
1072                    SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1073                    SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1074                                  SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1075                 }
1076                 WIN_ReleaseWndPtr(pWnd);
1077             }
1078         }
1079         else ShowWindow( hWnd, SW_HIDE );
1080     }
1081     return FALSE;
1082 }
1083
1084 /*******************************************************************
1085  *           WINPOS_GetMinMaxInfo
1086  *
1087  * Get the minimized and maximized information for a window.
1088  */
1089 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1090                            POINT *minTrack, POINT *maxTrack )
1091 {
1092     LPINTERNALPOS lpPos;
1093     MINMAXINFO MinMax;
1094     INT xinc, yinc;
1095
1096     /* Compute default values */
1097
1098     MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1099     MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1100     MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1101     MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1102     MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1103     MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1104
1105     if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1106     else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1107     {
1108         xinc = GetSystemMetrics(SM_CXDLGFRAME);
1109         yinc = GetSystemMetrics(SM_CYDLGFRAME);
1110     }
1111     else
1112     {
1113         xinc = yinc = 0;
1114         if (HAS_THICKFRAME(wndPtr->dwStyle))
1115         {
1116             xinc += GetSystemMetrics(SM_CXFRAME);
1117             yinc += GetSystemMetrics(SM_CYFRAME);
1118         }
1119         if (wndPtr->dwStyle & WS_BORDER)
1120         {
1121             xinc += GetSystemMetrics(SM_CXBORDER);
1122             yinc += GetSystemMetrics(SM_CYBORDER);
1123         }
1124     }
1125     MinMax.ptMaxSize.x += 2 * xinc;
1126     MinMax.ptMaxSize.y += 2 * yinc;
1127
1128     lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1129     if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1130         CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1131     else
1132     {
1133         MinMax.ptMaxPosition.x = -xinc;
1134         MinMax.ptMaxPosition.y = -yinc;
1135     }
1136
1137     SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1138
1139       /* Some sanity checks */
1140
1141     TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1142                       MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1143                       MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1144                       MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1145                       MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1146     MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1147                                    MinMax.ptMinTrackSize.x );
1148     MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1149                                    MinMax.ptMinTrackSize.y );
1150
1151     if (maxSize) *maxSize = MinMax.ptMaxSize;
1152     if (maxPos) *maxPos = MinMax.ptMaxPosition;
1153     if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1154     if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1155 }
1156
1157 /***********************************************************************
1158  *           WINPOS_MinMaximize
1159  *
1160  * Fill in lpRect and return additional flags to be used with SetWindowPos().
1161  * This function assumes that 'cmd' is different from the current window
1162  * state.
1163  */
1164 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1165 {
1166     UINT swpFlags = 0;
1167     POINT pt, size;
1168     LPINTERNALPOS lpPos;
1169
1170     TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1171
1172     size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1173     lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1174
1175     if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1176     {
1177         if( wndPtr->dwStyle & WS_MINIMIZE )
1178         {
1179             if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1180                 return (SWP_NOSIZE | SWP_NOMOVE);
1181             swpFlags |= SWP_NOCOPYBITS;
1182         }
1183         switch( cmd )
1184         {
1185             case SW_MINIMIZE:
1186                  if( wndPtr->dwStyle & WS_MAXIMIZE)
1187                  {
1188                      wndPtr->flags |= WIN_RESTORE_MAX;
1189                      wndPtr->dwStyle &= ~WS_MAXIMIZE;
1190                  }
1191                  else
1192                      wndPtr->flags &= ~WIN_RESTORE_MAX;
1193                  wndPtr->dwStyle |= WS_MINIMIZE;
1194
1195                  if( wndPtr->flags & WIN_NATIVE )
1196                      if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1197                          swpFlags |= MINMAX_NOSWP;
1198
1199                  lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1200
1201                  SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1202                                     GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1203                  swpFlags |= SWP_NOCOPYBITS;
1204                  break;
1205
1206             case SW_MAXIMIZE:
1207                 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1208                 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1209                 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1210
1211                  if( wndPtr->dwStyle & WS_MINIMIZE )
1212                  {
1213                      if( wndPtr->flags & WIN_NATIVE )
1214                          if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1215                              swpFlags |= MINMAX_NOSWP;
1216
1217                      WINPOS_ShowIconTitle( wndPtr, FALSE );
1218                      wndPtr->dwStyle &= ~WS_MINIMIZE;
1219                  }
1220                  wndPtr->dwStyle |= WS_MAXIMIZE;
1221
1222                  SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1223                                     size.x, size.y );
1224                  break;
1225
1226             case SW_RESTORE:
1227                  if( wndPtr->dwStyle & WS_MINIMIZE )
1228                  {
1229                      if( wndPtr->flags & WIN_NATIVE )
1230                          if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1231                              swpFlags |= MINMAX_NOSWP;
1232
1233                      wndPtr->dwStyle &= ~WS_MINIMIZE;
1234                      WINPOS_ShowIconTitle( wndPtr, FALSE );
1235
1236                      if( wndPtr->flags & WIN_RESTORE_MAX)
1237                      {
1238                          /* Restore to maximized position */
1239                          CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1240                          WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1241                          CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1242                          wndPtr->dwStyle |= WS_MAXIMIZE;
1243                          SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1244                          break;
1245                      }
1246                  } 
1247                  else 
1248                      if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1249                      else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1250
1251                  /* Restore to normal position */
1252
1253                 *lpRect = lpPos->rectNormal; 
1254                  lpRect->right -= lpRect->left; 
1255                  lpRect->bottom -= lpRect->top;
1256
1257                  break;
1258         }
1259     } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1260     return swpFlags;
1261 }
1262
1263 /***********************************************************************
1264  *           ShowWindowAsync   (USER32.535)
1265  *
1266  * doesn't wait; returns immediately.
1267  * used by threads to toggle windows in other (possibly hanging) threads
1268  */
1269 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1270 {
1271     /* FIXME: does ShowWindow() return immediately ? */
1272     return ShowWindow(hwnd, cmd);
1273 }
1274
1275
1276 /***********************************************************************
1277  *           ShowWindow16   (USER.42)
1278  */
1279 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd ) 
1280 {    
1281     return ShowWindow(hwnd,cmd);
1282 }
1283
1284
1285 /***********************************************************************
1286  *           ShowWindow   (USER32.534)
1287  */
1288 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd ) 
1289 {    
1290     WND*        wndPtr = WIN_FindWndPtr( hwnd );
1291     BOOL        wasVisible, showFlag;
1292     RECT16      newPos = {0, 0, 0, 0};
1293     UINT        swp = 0;
1294
1295     if (!wndPtr) return FALSE;
1296
1297     TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1298
1299     wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1300
1301     switch(cmd)
1302     {
1303         case SW_HIDE:
1304             if (!wasVisible) goto END;;
1305             swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
1306                         SWP_NOACTIVATE | SWP_NOZORDER;
1307             break;
1308
1309         case SW_SHOWMINNOACTIVE:
1310             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1311             /* fall through */
1312         case SW_SHOWMINIMIZED:
1313             swp |= SWP_SHOWWINDOW;
1314             /* fall through */
1315         case SW_MINIMIZE:
1316             swp |= SWP_FRAMECHANGED;
1317             if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1318                  swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1319             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1320             break;
1321
1322         case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1323             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1324             if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1325                  swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1326             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1327             break;
1328
1329         case SW_SHOWNA:
1330             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1331             /* fall through */
1332         case SW_SHOW:
1333             swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1334
1335             /*
1336              * ShowWindow has a little peculiar behavior that if the
1337              * window is already the topmost window, it will not
1338              * activate it.
1339              */
1340             if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1341               swp |= SWP_NOACTIVATE;
1342
1343             break;
1344
1345         case SW_SHOWNOACTIVATE:
1346             swp |= SWP_NOZORDER;
1347             if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1348             /* fall through */
1349         case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
1350         case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1351         case SW_RESTORE:
1352             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1353
1354             if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1355                  swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1356             else swp |= SWP_NOSIZE | SWP_NOMOVE;
1357             break;
1358     }
1359
1360     showFlag = (cmd != SW_HIDE);
1361     if (showFlag != wasVisible)
1362     {
1363         SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1364         if (!IsWindow( hwnd )) goto END;
1365     }
1366
1367     if ((wndPtr->dwStyle & WS_CHILD) &&
1368         !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1369         (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1370     {
1371         /* Don't call SetWindowPos() on invisible child windows */
1372         if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1373         else wndPtr->dwStyle |= WS_VISIBLE;
1374     }
1375     else
1376     {
1377         /* We can't activate a child window */
1378         if ((wndPtr->dwStyle & WS_CHILD) &&
1379             !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1380             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1381         if (!(swp & MINMAX_NOSWP))
1382         {
1383             SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top, 
1384                                           newPos.right, newPos.bottom, LOWORD(swp) );
1385             if (cmd == SW_HIDE)
1386             {
1387                /* FIXME: This will cause the window to be activated irrespective
1388                 * of whether it is owned by the same thread. Has to be done
1389                 * asynchronously.
1390                 */
1391
1392                if (hwnd == GetActiveWindow())
1393                   WINPOS_ActivateOtherWindow(wndPtr);
1394
1395                /* Revert focus to parent */
1396                if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1397                   SetFocus( GetParent(hwnd) );
1398             }
1399         }
1400         if (!IsWindow( hwnd )) goto END;
1401         else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1402     }
1403
1404     if (wndPtr->flags & WIN_NEED_SIZE)
1405     {
1406         /* should happen only in CreateWindowEx() */
1407         int wParam = SIZE_RESTORED;
1408
1409         wndPtr->flags &= ~WIN_NEED_SIZE;
1410         if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1411         else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1412         SendMessageA( hwnd, WM_SIZE, wParam,
1413                      MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1414                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1415         SendMessageA( hwnd, WM_MOVE, 0,
1416                    MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1417     }
1418
1419 END:
1420     WIN_ReleaseWndPtr(wndPtr);
1421     return wasVisible;
1422 }
1423
1424
1425 /***********************************************************************
1426  *           GetInternalWindowPos16   (USER.460)
1427  */
1428 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1429                                       LPPOINT16 ptIcon )
1430 {
1431     WINDOWPLACEMENT16 wndpl;
1432     if (GetWindowPlacement16( hwnd, &wndpl )) 
1433     {
1434         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1435         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1436         return wndpl.showCmd;
1437     }
1438     return 0;
1439 }
1440
1441
1442 /***********************************************************************
1443  *           GetInternalWindowPos   (USER32.245)
1444  */
1445 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1446                                       LPPOINT ptIcon )
1447 {
1448     WINDOWPLACEMENT wndpl;
1449     if (GetWindowPlacement( hwnd, &wndpl ))
1450     {
1451         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1452         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1453         return wndpl.showCmd;
1454     }
1455     return 0;
1456 }
1457
1458 /***********************************************************************
1459  *           GetWindowPlacement16   (USER.370)
1460  */
1461 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1462 {
1463     WND *pWnd = WIN_FindWndPtr( hwnd );
1464     LPINTERNALPOS lpPos;
1465     
1466     if(!pWnd ) return FALSE;
1467
1468     lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1469                              *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1470         wndpl->length  = sizeof(*wndpl);
1471         if( pWnd->dwStyle & WS_MINIMIZE )
1472             wndpl->showCmd = SW_SHOWMINIMIZED;
1473         else 
1474             wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1475                              ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1476         if( pWnd->flags & WIN_RESTORE_MAX )
1477             wndpl->flags = WPF_RESTORETOMAXIMIZED;
1478         else
1479             wndpl->flags = 0;
1480         wndpl->ptMinPosition = lpPos->ptIconPos;
1481         wndpl->ptMaxPosition = lpPos->ptMaxPos;
1482         wndpl->rcNormalPosition = lpPos->rectNormal;
1483
1484     WIN_ReleaseWndPtr(pWnd);
1485         return TRUE;
1486     }
1487
1488
1489 /***********************************************************************
1490  *           GetWindowPlacement   (USER32.307)
1491  *
1492  * Win95:
1493  * Fails if wndpl->length of Win95 (!) apps is invalid.
1494  */
1495 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1496 {
1497     if( pwpl32 )
1498     {
1499         WINDOWPLACEMENT16 wpl;
1500         wpl.length = sizeof(wpl);
1501         if( GetWindowPlacement16( hwnd, &wpl ) )
1502         {
1503             pwpl32->length = sizeof(*pwpl32);
1504             pwpl32->flags = wpl.flags;
1505             pwpl32->showCmd = wpl.showCmd;
1506             CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1507             CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1508             CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1509             return TRUE;
1510         }
1511     }
1512     return FALSE;
1513 }
1514
1515
1516 /***********************************************************************
1517  *           WINPOS_SetPlacement
1518  */
1519 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1520                                                 UINT flags )
1521 {
1522     WND *pWnd = WIN_FindWndPtr( hwnd );
1523     if( pWnd )
1524     {
1525         LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1526                              *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1527
1528         if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1529         if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1530         if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1531
1532         if( pWnd->dwStyle & WS_MINIMIZE )
1533         {
1534             WINPOS_ShowIconTitle( pWnd, FALSE );
1535             if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1536                 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1537                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1538         } 
1539         else if( pWnd->dwStyle & WS_MAXIMIZE )
1540         {
1541             if( !EMPTYPOINT(lpPos->ptMaxPos) )
1542                 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1543                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1544         }
1545         else if( flags & PLACE_RECT )
1546                 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1547                                 lpPos->rectNormal.right - lpPos->rectNormal.left,
1548                                 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1549                                 SWP_NOZORDER | SWP_NOACTIVATE );
1550
1551         ShowWindow( hwnd, wndpl->showCmd );
1552         if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1553         {
1554             if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1555
1556             /* SDK: ...valid only the next time... */
1557             if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1558         }
1559         WIN_ReleaseWndPtr(pWnd);
1560         return TRUE;
1561     }
1562     return FALSE;
1563 }
1564
1565
1566 /***********************************************************************
1567  *           SetWindowPlacement16   (USER.371)
1568  */
1569 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1570 {
1571     return WINPOS_SetPlacement( hwnd, wndpl,
1572                                 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1573 }
1574
1575 /***********************************************************************
1576  *           SetWindowPlacement   (USER32.519)
1577  *
1578  * Win95:
1579  * Fails if wndpl->length of Win95 (!) apps is invalid.
1580  */
1581 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1582 {
1583     if( pwpl32 )
1584     {
1585         WINDOWPLACEMENT16 wpl;
1586
1587         wpl.length = sizeof(WINDOWPLACEMENT16);
1588         wpl.flags = pwpl32->flags;
1589         wpl.showCmd = pwpl32->showCmd;
1590         wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1591         wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1592         wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1593         wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1594         wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1595         wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1596         wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1597         wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1598
1599         return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1600     }
1601     return FALSE;
1602 }
1603
1604
1605 /***********************************************************************
1606  *           SetInternalWindowPos16   (USER.461)
1607  */
1608 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1609                                     LPRECT16 rect, LPPOINT16 pt )
1610 {
1611     if( IsWindow16(hwnd) )
1612     {
1613         WINDOWPLACEMENT16 wndpl;
1614         UINT flags;
1615
1616         wndpl.length  = sizeof(wndpl);
1617         wndpl.showCmd = showCmd;
1618         wndpl.flags = flags = 0;
1619
1620         if( pt )
1621         {
1622             flags |= PLACE_MIN;
1623             wndpl.flags |= WPF_SETMINPOSITION;
1624             wndpl.ptMinPosition = *pt;
1625         }
1626         if( rect )
1627         {
1628             flags |= PLACE_RECT;
1629             wndpl.rcNormalPosition = *rect;
1630         }
1631         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1632     }
1633 }
1634
1635
1636 /***********************************************************************
1637  *           SetInternalWindowPos   (USER32.483)
1638  */
1639 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1640                                     LPRECT rect, LPPOINT pt )
1641 {
1642     if( IsWindow(hwnd) )
1643     {
1644         WINDOWPLACEMENT16 wndpl;
1645         UINT flags;
1646
1647         wndpl.length  = sizeof(wndpl);
1648         wndpl.showCmd = showCmd;
1649         wndpl.flags = flags = 0;
1650
1651         if( pt )
1652         {
1653             flags |= PLACE_MIN;
1654             wndpl.flags |= WPF_SETMINPOSITION;
1655             CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1656         }
1657         if( rect )
1658         {
1659             flags |= PLACE_RECT;
1660             CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1661         }
1662         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1663     }
1664 }
1665
1666 /*******************************************************************
1667  *         WINPOS_SetActiveWindow
1668  *
1669  * SetActiveWindow() back-end. This is the only function that
1670  * can assign active status to a window. It must be called only
1671  * for the top level windows.
1672  */
1673 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1674 {
1675     CBTACTIVATESTRUCT16* cbtStruct;
1676     WND*     wndPtr=0, *wndTemp;
1677     HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1678     MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1679     WORD     wIconized = 0;
1680     HWND     hwndActive = 0;
1681     BOOL     bRet = 0;
1682
1683     TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1684
1685     /* Get current active window from the active queue */
1686     if ( hActiveQueue )
1687     {
1688         pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1689         if ( pOldActiveQueue )
1690             hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1691     }
1692
1693     /* paranoid checks */
1694     if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1695         goto CLEANUP_END;
1696
1697 /*  if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1698  *      return 0;
1699  */
1700     wndPtr = WIN_FindWndPtr(hWnd);
1701     hOldActiveQueue = hActiveQueue;
1702
1703     if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1704     {
1705         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1706         WIN_ReleaseWndPtr(wndTemp);
1707     }
1708     else
1709         TRACE("no current active window.\n");
1710
1711     /* call CBT hook chain */
1712     if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1713     {
1714         cbtStruct->fMouse     = fMouse;
1715         cbtStruct->hWndActive = hwndActive;
1716         bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1717                                      (LPARAM)SEGPTR_GET(cbtStruct) );
1718         SEGPTR_FREE(cbtStruct);
1719         if (bRet) goto CLEANUP_END;
1720     }
1721
1722     /* set prev active wnd to current active wnd and send notification */
1723     if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1724     {
1725         MESSAGEQUEUE *pTempActiveQueue = 0;
1726         
1727         if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1728         {
1729             if (GetSysModalWindow16() != hWnd) 
1730                 goto CLEANUP_END;
1731             /* disregard refusal if hWnd is sysmodal */
1732         }
1733
1734         SendMessageA( hwndPrevActive, WM_ACTIVATE,
1735                         MAKEWPARAM( WA_INACTIVE, wIconized ),
1736                         (LPARAM)hWnd );
1737
1738         /* check if something happened during message processing
1739          * (global active queue may have changed)
1740          */
1741         pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1742         if(!pTempActiveQueue)
1743             goto CLEANUP_END;
1744
1745         hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1746         QUEUE_Unlock( pTempActiveQueue );
1747         if( hwndPrevActive != hwndActive )
1748             goto CLEANUP_END;
1749     }
1750
1751     /* Set new active window in the message queue */
1752     hwndActive = hWnd;
1753     if ( wndPtr )
1754     {
1755         pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1756         if ( pNewActiveQueue )
1757             PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1758     }
1759     else /* have to do this or MDI frame activation goes to hell */
1760         if( pOldActiveQueue )
1761             PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1762
1763     /* send palette messages */
1764     if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1765         SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1766
1767     /* if prev wnd is minimized redraw icon title */
1768     if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1769
1770     /* managed windows will get ConfigureNotify event */  
1771     if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1772     {
1773         /* check Z-order and bring hWnd to the top */
1774         for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1775         {
1776             if (wndTemp->dwStyle & WS_VISIBLE) break;
1777         }
1778         WIN_ReleaseDesktop();
1779         WIN_ReleaseWndPtr(wndTemp);
1780
1781         if( wndTemp != wndPtr )
1782             SetWindowPos(hWnd, HWND_TOP, 0,0,0,0, 
1783                            SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1784         if (!IsWindow(hWnd))  
1785             goto CLEANUP;
1786     }
1787
1788     /* Get a handle to the new active queue */
1789     hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1790
1791     /* send WM_ACTIVATEAPP if necessary */
1792     if (hOldActiveQueue != hNewActiveQueue)
1793     {
1794         WND **list, **ppWnd;
1795         WND *pDesktop = WIN_GetDesktop();
1796
1797         if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1798         {
1799             for (ppWnd = list; *ppWnd; ppWnd++)
1800             {
1801                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1802
1803                 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1804                    SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1805                                    0, QUEUE_GetQueueTask(hNewActiveQueue) );
1806             }
1807             WIN_ReleaseWinArray(list);
1808         }
1809
1810         hActiveQueue = hNewActiveQueue;
1811
1812         if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1813         {
1814             for (ppWnd = list; *ppWnd; ppWnd++)
1815             {
1816                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1817
1818                 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1819                    SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1820                                   1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1821             }
1822             WIN_ReleaseWinArray(list);
1823         }
1824         WIN_ReleaseDesktop();
1825         
1826         if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1827     }
1828
1829     if (hWnd)
1830     {
1831         /* walk up to the first unowned window */
1832         wndTemp = WIN_LockWndPtr(wndPtr);
1833         while (wndTemp->owner)
1834         {
1835             WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1836         }
1837         /* and set last active owned popup */
1838         wndTemp->hwndLastActive = hWnd;
1839
1840         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1841         WIN_ReleaseWndPtr(wndTemp);
1842         SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1843         SendMessageA( hWnd, WM_ACTIVATE,
1844                  MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1845                  (LPARAM)hwndPrevActive );
1846         if( !IsWindow(hWnd) ) goto CLEANUP;
1847     }
1848
1849     /* change focus if possible */
1850     if ( fChangeFocus )
1851     {
1852         if ( pNewActiveQueue )
1853         {
1854             HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1855
1856             if ( WIN_GetTopParent( hOldFocus ) != hwndActive )
1857                 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus, 
1858                                    (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1859                                    0 : hwndActive );
1860         }
1861
1862         if ( pOldActiveQueue && 
1863              ( !pNewActiveQueue || 
1864                 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1865         {
1866             HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1867             if ( hOldFocus )
1868                 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1869         }
1870     }
1871
1872     if( !hwndPrevActive && wndPtr )
1873         (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1874
1875     /* if active wnd is minimized redraw icon title */
1876     if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1877
1878     bRet = (hWnd == hwndActive);  /* Success? */
1879     
1880 CLEANUP: /* Unlock the message queues before returning */
1881
1882     if ( pNewActiveQueue )
1883         QUEUE_Unlock( pNewActiveQueue );
1884
1885 CLEANUP_END:
1886
1887     if ( pOldActiveQueue )
1888         QUEUE_Unlock( pOldActiveQueue );
1889
1890     WIN_ReleaseWndPtr(wndPtr);
1891     return bRet;
1892 }
1893
1894 /*******************************************************************
1895  *         WINPOS_ActivateOtherWindow
1896  *
1897  *  Activates window other than pWnd.
1898  */
1899 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1900 {
1901   BOOL  bRet = 0;
1902   WND*          pWndTo = NULL;
1903     HWND       hwndActive = 0;
1904
1905     /* Get current active window from the active queue */
1906     if ( hActiveQueue )
1907     {
1908         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1909         if ( pActiveQueue )
1910         {
1911             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1912             QUEUE_Unlock( pActiveQueue );
1913         }
1914     }
1915
1916   if( pWnd->hwndSelf == hwndPrevActive )
1917       hwndPrevActive = 0;
1918
1919   if( hwndActive != pWnd->hwndSelf && 
1920     ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1921       return 0;
1922
1923   if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1924       !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) ) 
1925   {
1926       WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1927
1928       WIN_ReleaseWndPtr(pWndTo);
1929       pWndTo = WIN_FindWndPtr(hwndPrevActive);
1930
1931       while( !WINPOS_CanActivate(pWndTo) ) 
1932       {
1933          /* by now owned windows should've been taken care of */
1934           WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1935           WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1936           if( !pWndTo ) break;
1937       }
1938       WIN_ReleaseWndPtr(pWndPtr);
1939   }
1940
1941   bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1942
1943   /* switch desktop queue to current active */
1944   if( pWndTo )
1945   {
1946       WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1947       WIN_ReleaseWndPtr(pWndTo);
1948       WIN_ReleaseDesktop();
1949   }
1950
1951   hwndPrevActive = 0;
1952   return bRet;  
1953 }
1954
1955 /*******************************************************************
1956  *         WINPOS_ChangeActiveWindow
1957  *
1958  */
1959 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1960 {
1961     WND *wndPtr, *wndTemp;
1962     BOOL retvalue;
1963     HWND hwndActive = 0;
1964
1965     /* Get current active window from the active queue */
1966     if ( hActiveQueue )
1967     {
1968         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1969         if ( pActiveQueue )
1970         {
1971             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1972             QUEUE_Unlock( pActiveQueue );
1973         }
1974     }
1975
1976     if (!hWnd)
1977         return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1978
1979     wndPtr = WIN_FindWndPtr(hWnd);
1980     if( !wndPtr ) return FALSE;
1981
1982     /* child windows get WM_CHILDACTIVATE message */
1983     if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1984     {
1985         retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1986         goto end;
1987     }
1988
1989     if( hWnd == hwndActive )
1990     {
1991         retvalue = FALSE;
1992         goto end;
1993     }
1994
1995     if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1996     {
1997         retvalue = FALSE;
1998         goto end;
1999     }
2000
2001     /* switch desktop queue to current active */
2002     wndTemp = WIN_GetDesktop();
2003     if( wndPtr->parent == wndTemp)
2004         wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2005     WIN_ReleaseDesktop();
2006
2007     retvalue = TRUE;
2008 end:
2009     WIN_ReleaseWndPtr(wndPtr);
2010     return retvalue;
2011 }
2012
2013
2014 /***********************************************************************
2015  *           WINPOS_SendNCCalcSize
2016  *
2017  * Send a WM_NCCALCSIZE message to a window.
2018  * All parameters are read-only except newClientRect.
2019  * oldWindowRect, oldClientRect and winpos must be non-NULL only
2020  * when calcValidRect is TRUE.
2021  */
2022 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2023                             RECT *newWindowRect, RECT *oldWindowRect,
2024                             RECT *oldClientRect, WINDOWPOS *winpos,
2025                             RECT *newClientRect )
2026 {
2027     NCCALCSIZE_PARAMS params;
2028     WINDOWPOS winposCopy;
2029     LONG result;
2030
2031     params.rgrc[0] = *newWindowRect;
2032     if (calcValidRect)
2033     {
2034         winposCopy = *winpos;
2035         params.rgrc[1] = *oldWindowRect;
2036         params.rgrc[2] = *oldClientRect;
2037         params.lppos = &winposCopy;
2038     }
2039     result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2040                              (LPARAM)&params );
2041     TRACE("%d,%d-%d,%d\n",
2042                  params.rgrc[0].left, params.rgrc[0].top,
2043                  params.rgrc[0].right, params.rgrc[0].bottom );
2044
2045     /* If the application send back garbage, ignore it */
2046     if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2047         *newClientRect = params.rgrc[0];
2048
2049     return result;
2050 }
2051
2052
2053 /***********************************************************************
2054  *           WINPOS_HandleWindowPosChanging16
2055  *
2056  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2057  */
2058 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2059 {
2060     POINT maxSize, minTrack;
2061     if (winpos->flags & SWP_NOSIZE) return 0;
2062     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2063         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2064     {
2065         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2066         if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2067         if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2068         if (!(wndPtr->dwStyle & WS_MINIMIZE))
2069         {
2070             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2071             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2072         }
2073     }
2074     return 0;
2075 }
2076
2077
2078 /***********************************************************************
2079  *           WINPOS_HandleWindowPosChanging
2080  *
2081  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2082  */
2083 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2084 {
2085     POINT maxSize;
2086     if (winpos->flags & SWP_NOSIZE) return 0;
2087     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2088         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2089     {
2090         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2091         winpos->cx = min( winpos->cx, maxSize.x );
2092         winpos->cy = min( winpos->cy, maxSize.y );
2093     }
2094     return 0;
2095 }
2096
2097 /***********************************************************************
2098  *           SWP_DoOwnedPopups
2099  *
2100  * fix Z order taking into account owned popups -
2101  * basically we need to maintain them above the window that owns them
2102  *
2103  * FIXME: hide/show owned popups when owner visibility changes.
2104  */
2105 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2106 {
2107     WND*        w = WIN_LockWndPtr(pDesktop->child);
2108
2109     WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2110
2111     if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2112     {
2113         /* make sure this popup stays above the owner */
2114
2115         HWND hwndLocalPrev = HWND_TOP;
2116
2117         if( hwndInsertAfter != HWND_TOP )
2118         {
2119             while( w != wndPtr->owner )
2120             {
2121                 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2122                 if( hwndLocalPrev == hwndInsertAfter ) break;
2123                 WIN_UpdateWndPtr(&w,w->next);
2124             }
2125             hwndInsertAfter = hwndLocalPrev;
2126         }
2127     }
2128     else if( wndPtr->dwStyle & WS_CHILD )
2129         goto END; 
2130
2131     WIN_UpdateWndPtr(&w, pDesktop->child);
2132
2133     while( w )
2134     {
2135         if( w == wndPtr ) break; 
2136
2137         if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2138         {
2139             SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, 
2140                  SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2141             hwndInsertAfter = w->hwndSelf;
2142         }
2143         WIN_UpdateWndPtr(&w, w->next);
2144     }
2145
2146 END:
2147     WIN_ReleaseWndPtr(w);
2148     return hwndInsertAfter;
2149 }
2150
2151 /***********************************************************************
2152  *           SWP_CopyValidBits
2153  *
2154  * Make window look nice without excessive repainting
2155  *
2156  * visible and update regions are in window coordinates
2157  * client and window rectangles are in parent client coordinates
2158  *
2159  * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2160  *        window rects have the same origin.
2161  *
2162  * Returns: uFlags and a dirty region in *pVisRgn.
2163  */
2164 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2165                                LPRECT lpOldWndRect,
2166                                LPRECT lpOldClientRect, UINT uFlags )
2167 {
2168  RECT r;
2169  HRGN newVisRgn, dirtyRgn;
2170  INT  my = COMPLEXREGION;
2171
2172  TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2173               Wnd->rectWindow.left, Wnd->rectWindow.top,
2174               Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2175               lpOldWndRect->left, lpOldWndRect->top,
2176               lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2177  TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2178               Wnd->rectClient.left, Wnd->rectClient.top,
2179               Wnd->rectClient.right, Wnd->rectClient.bottom,
2180               lpOldClientRect->left, lpOldClientRect->top,
2181               lpOldClientRect->right,lpOldClientRect->bottom );
2182
2183  if( Wnd->hrgnUpdate == 1 )
2184      uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2185
2186  newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2187  dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2188
2189  if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2190      my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2191
2192  if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2193  {
2194 nocopy:
2195
2196      TRACE("\twon't copy anything!\n");
2197
2198      /* set dirtyRgn to the sum of old and new visible regions 
2199       * in parent client coordinates */
2200
2201      OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2202      OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2203
2204      CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2205  }
2206  else                   /* copy valid bits to a new location */
2207  {
2208      INT  dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2209      HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2210
2211      /* subtract already invalid region inside Wnd from the dst region */
2212
2213      if( Wnd->hrgnUpdate )
2214          if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2215              goto nocopy;
2216
2217      /* check if entire window can be copied */
2218
2219      ow = lpOldWndRect->right - lpOldWndRect->left;
2220      oh = lpOldWndRect->bottom - lpOldWndRect->top;
2221      nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2222      nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2223
2224      ocw = lpOldClientRect->right - lpOldClientRect->left;
2225      och = lpOldClientRect->bottom - lpOldClientRect->top;
2226      ncw = Wnd->rectClient.right  - Wnd->rectClient.left;
2227      nch = Wnd->rectClient.bottom  - Wnd->rectClient.top;
2228
2229      if(  (ocw != ncw) || (och != nch) ||
2230           ( ow !=  nw) || ( oh !=  nh) ||
2231           ((lpOldClientRect->top - lpOldWndRect->top)   != 
2232            (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2233           ((lpOldClientRect->left - lpOldWndRect->left) !=
2234            (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2235      {
2236         dx = Wnd->rectClient.left - lpOldClientRect->left;
2237         dy = Wnd->rectClient.top - lpOldClientRect->top;
2238
2239         /* restrict valid bits to the common client rect */
2240
2241         r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2242         r.top = Wnd->rectClient.top  - Wnd->rectWindow.top;
2243         r.right = r.left + min( ocw, ncw );
2244         r.bottom = r.top + min( och, nch );
2245
2246         REGION_CropRgn( hrgnValid, hrgnValid, &r, 
2247                         (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2248         GetRgnBox( hrgnValid, &r );
2249         if( IsRectEmpty( &r ) )
2250             goto nocopy;
2251         r = *lpOldClientRect;
2252      }
2253      else
2254      {
2255         dx = Wnd->rectWindow.left - lpOldWndRect->left;
2256         dy = Wnd->rectWindow.top -  lpOldWndRect->top;
2257         if( !(uFlags & SWP_EX_PAINTSELF) )
2258             OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2259         r = *lpOldWndRect;
2260      }
2261
2262      if( !(uFlags & SWP_EX_PAINTSELF) )
2263      {
2264         /* Move remaining regions to parent coordinates */
2265         OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2266         OffsetRgn( *pVisRgn,  lpOldWndRect->left, lpOldWndRect->top );
2267      }
2268      else
2269         OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2270
2271      TRACE("\tcomputing dirty region!\n");
2272
2273      /* Compute combined dirty region (old + new - valid) */
2274      CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2275      CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2276
2277      /* Blt valid bits, r is the rect to copy  */
2278
2279      if( dx || dy )
2280      {
2281          RECT rClip;
2282          HDC hDC;
2283          DC* dc;
2284
2285          /* get DC and clip rect with drawable rect to avoid superfluous expose events
2286             from copying clipped areas */
2287
2288          if( uFlags & SWP_EX_PAINTSELF )
2289          {
2290              hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2291                             DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2292              rClip.right = nw; rClip.bottom = nh;
2293          }
2294          else
2295          {
2296              hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2297                             DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2298              rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2299              rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2300          }
2301          rClip.left = rClip.top = 0;    
2302
2303          if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2304          {
2305             if( oh > nh ) r.bottom = r.top  + nh;
2306             if( ow < nw ) r.right = r.left  + nw;
2307
2308             if( IntersectRect( &r, &r, &rClip ) )
2309             {
2310                 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2311
2312                  /* When you copy the bits without repainting, parent doesn't
2313                     get validated appropriately. Therefore, we have to validate
2314                     the parent with the windows' updated region when the
2315                     parent's update region is not empty. */
2316
2317                 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2318                 {
2319                   OffsetRect(&r, dx, dy);
2320                   ValidateRect(Wnd->parent->hwndSelf, &r);
2321                 }
2322             }
2323
2324             GDI_HEAP_UNLOCK( hDC );
2325          }
2326          ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ? 
2327                      Wnd->hwndSelf :  Wnd->parent->hwndSelf, hDC); 
2328      }
2329  }
2330
2331  /* *pVisRgn now points to the invalidated region */
2332
2333  DeleteObject(newVisRgn);
2334  DeleteObject(dirtyRgn);
2335  return uFlags;
2336 }
2337
2338 /***********************************************************************
2339  *           SWP_DoSimpleFrameChanged
2340  *
2341  * NOTE: old and new client rect origins are identical, only
2342  *       extents may have changed. Window extents are the same.
2343  */
2344 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2345 {
2346     INT  i = 0;
2347     RECT rect;
2348     HRGN hrgn = 0;
2349
2350     if( !(swpFlags & SWP_NOCLIENTSIZE) )
2351     {
2352         /* Client rect changed its position/size, most likely a scrollar
2353          * was added/removed.
2354          *
2355          * FIXME: WVR alignment flags 
2356          */
2357
2358         if( wndPtr->rectClient.right >  pOldClientRect->right ) /* right edge */
2359         {
2360             i++;
2361             rect.top = 0; 
2362             rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2363             rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2364             if(!(uFlags & SWP_EX_NOCOPY))
2365                 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2366             else
2367             {
2368                 rect.left = 0;
2369                 goto redraw;
2370             }
2371         }
2372
2373         if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2374         {
2375             if( i )
2376                 hrgn = CreateRectRgnIndirect( &rect );
2377             rect.left = 0;
2378             rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2379             rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2380             if(!(uFlags & SWP_EX_NOCOPY))
2381                 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2382             else
2383                 rect.top = 0;
2384             if( i++ ) 
2385                 REGION_UnionRectWithRgn( hrgn, &rect );
2386         }
2387
2388         if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2389         {
2390             rect = wndPtr->rectWindow;
2391             OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2392                                wndPtr->rectWindow.top - wndPtr->rectClient.top );
2393             i++;
2394         }
2395     }
2396
2397     if( i )
2398     {
2399 redraw:
2400         PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2401                             RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2402     }
2403     else
2404     {
2405         WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2406     }
2407
2408     if( hrgn > 1 )
2409         DeleteObject( hrgn );
2410 }
2411
2412 /***********************************************************************
2413  *           SWP_DoWinPosChanging
2414  */
2415 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos, 
2416                                   RECT* pNewWindowRect, RECT* pNewClientRect )
2417 {
2418       /* Send WM_WINDOWPOSCHANGING message */
2419
2420     if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2421         SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2422
2423       /* Calculate new position and size */
2424
2425     *pNewWindowRect = wndPtr->rectWindow;
2426     *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2427                                                     : wndPtr->rectClient;
2428
2429     if (!(pWinpos->flags & SWP_NOSIZE))
2430     {
2431         pNewWindowRect->right  = pNewWindowRect->left + pWinpos->cx;
2432         pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2433     }
2434     if (!(pWinpos->flags & SWP_NOMOVE))
2435     {
2436         pNewWindowRect->left    = pWinpos->x;
2437         pNewWindowRect->top     = pWinpos->y;
2438         pNewWindowRect->right  += pWinpos->x - wndPtr->rectWindow.left;
2439         pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2440
2441         OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2442                                     pWinpos->y - wndPtr->rectWindow.top );
2443     }
2444
2445     pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2446     return TRUE;
2447 }
2448
2449 /***********************************************************************
2450  *           SWP_DoNCCalcSize
2451  */
2452 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2453                               RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2454 {
2455     UINT wvrFlags = 0;
2456
2457       /* Send WM_NCCALCSIZE message to get new client area */
2458     if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2459     {
2460          wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2461                                     &wndPtr->rectWindow, &wndPtr->rectClient,
2462                                     pWinpos, pNewClientRect );
2463
2464          /* FIXME: WVR_ALIGNxxx */
2465
2466          if( pNewClientRect->left != wndPtr->rectClient.left ||
2467              pNewClientRect->top != wndPtr->rectClient.top )
2468              pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2469
2470          if( (pNewClientRect->right - pNewClientRect->left !=
2471               wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2472              (pNewClientRect->bottom - pNewClientRect->top !=
2473               wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2474              pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2475     }
2476     else
2477       if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2478                                 pNewClientRect->top != wndPtr->rectClient.top) )
2479             pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2480     return wvrFlags;
2481 }
2482
2483 /***********************************************************************
2484  *           SetWindowPos   (USER.2)
2485  */
2486 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2487                               INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2488 {
2489     return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2490 }
2491
2492 /***********************************************************************
2493  *           SetWindowPos   (USER32.520)
2494  */
2495 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2496                           INT x, INT y, INT cx, INT cy, UINT flags )
2497 {
2498     WINDOWPOS   winpos;
2499     WND *       wndPtr,*wndTemp;
2500     RECT        newWindowRect, newClientRect;
2501     RECT        oldWindowRect, oldClientRect;
2502     HRGN        visRgn = 0;
2503     UINT        wvrFlags = 0, uFlags = 0;
2504     BOOL        retvalue, resync = FALSE, bChangePos;
2505     HWND        hwndActive = 0;
2506
2507     /* Get current active window from the active queue */
2508     if ( hActiveQueue )
2509     {
2510         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2511         if ( pActiveQueue )
2512         {
2513             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2514             QUEUE_Unlock( pActiveQueue );
2515         }
2516     }
2517
2518     TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n", 
2519                                                  hwnd, x, y, x+cx, y+cy, flags);  
2520
2521     bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2522     flags &= ~SWP_WINE_NOHOSTMOVE;
2523
2524
2525       /* ------------------------------------------------------------------------ CHECKS */
2526
2527       /* Check window handle */
2528
2529     if (hwnd == GetDesktopWindow()) return FALSE;
2530     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2531
2532     TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2533                           wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2534
2535       /* Fix redundant flags */
2536
2537     if(wndPtr->dwStyle & WS_VISIBLE)
2538         flags &= ~SWP_SHOWWINDOW;
2539     else
2540     {
2541         if (!(flags & SWP_SHOWWINDOW)) 
2542               flags |= SWP_NOREDRAW;
2543         flags &= ~SWP_HIDEWINDOW;
2544     }
2545
2546     if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2547
2548     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2549         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2550         flags |= SWP_NOSIZE;    /* Already the right size */
2551
2552     if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2553         flags |= SWP_NOMOVE;    /* Already the right position */
2554
2555     if (hwnd == hwndActive)
2556         flags |= SWP_NOACTIVATE;   /* Already active */
2557     else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2558     {
2559         if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2560         {
2561             flags &= ~SWP_NOZORDER;
2562             hwndInsertAfter = HWND_TOP;           
2563             goto Pos;
2564         }
2565     }
2566
2567       /* Check hwndInsertAfter */
2568
2569       /* FIXME: TOPMOST not supported yet */
2570     if ((hwndInsertAfter == HWND_TOPMOST) ||
2571         (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2572
2573       /* hwndInsertAfter must be a sibling of the window */
2574     if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2575     {
2576          WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2577
2578          if( wnd ) {
2579              if( wnd->parent != wndPtr->parent )
2580              {
2581                  retvalue = FALSE;
2582                  WIN_ReleaseWndPtr(wnd);
2583                  goto END;
2584              }
2585            if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2586          }
2587          WIN_ReleaseWndPtr(wnd);
2588     }
2589
2590 Pos:  /* ------------------------------------------------------------------------ MAIN part */
2591
2592       /* Fill the WINDOWPOS structure */
2593
2594     winpos.hwnd = hwnd;
2595     winpos.hwndInsertAfter = hwndInsertAfter;
2596     winpos.x = x;
2597     winpos.y = y;
2598     winpos.cx = cx;
2599     winpos.cy = cy;
2600     winpos.flags = flags;
2601     
2602     SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2603
2604     if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2605     {
2606         if( wndPtr->parent == WIN_GetDesktop() )
2607             hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2608                                         hwndInsertAfter, winpos.flags );
2609         WIN_ReleaseDesktop();
2610     }
2611
2612     if(!(wndPtr->flags & WIN_NATIVE) )
2613     {
2614         if( hwndInsertAfter == HWND_TOP )
2615            winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2616         else
2617         if( hwndInsertAfter == HWND_BOTTOM )
2618            winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2619         else
2620         if( !(winpos.flags & SWP_NOZORDER) )
2621            if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2622                winpos.flags |= SWP_NOZORDER;
2623
2624         if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2625             ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2626                           != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2627         {
2628             /* get a previous visible region for SWP_CopyValidBits() */
2629             DWORD flags = DCX_WINDOW;
2630   
2631             if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2632                flags |= DCX_CLIPSIBLINGS;
2633
2634             visRgn = DCE_GetVisRgn(hwnd, flags, 0, 0);
2635         }
2636     }
2637
2638     /* Common operations */
2639
2640     wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2641
2642     if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2643     {
2644         if ( WIN_UnlinkWindow( winpos.hwnd ) )
2645            WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2646     }
2647
2648     /* Reset active DCEs */
2649
2650     if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) && 
2651                                          wndPtr->dwStyle & WS_VISIBLE) || 
2652         (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) ) 
2653     {
2654         RECT rect;
2655
2656         UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2657         DCE_InvalidateDCE(wndPtr, &rect);
2658     }
2659
2660     oldWindowRect = wndPtr->rectWindow;
2661     oldClientRect = wndPtr->rectClient;
2662
2663     /* Find out if we have to redraw the whole client rect */
2664
2665     if( oldClientRect.bottom - oldClientRect.top ==
2666         newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2667
2668     if( oldClientRect.right - oldClientRect.left ==
2669         newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2670
2671     if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2672            (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2673     {
2674         uFlags |= SWP_EX_NOCOPY;
2675     }
2676 /* 
2677  *  Use this later in CopyValidBits()
2678  *
2679     else if( 0  )
2680         uFlags |= SWP_EX_NONCLIENT; 
2681  */
2682
2683     /* FIXME: actually do something with WVR_VALIDRECTS */
2684
2685     wndPtr->rectWindow = newWindowRect;
2686     wndPtr->rectClient = newClientRect;
2687
2688     if (wndPtr->flags & WIN_NATIVE)     /* -------------------------------------------- hosted window */
2689     {
2690         BOOL bCallDriver = TRUE;
2691         HWND tempInsertAfter = winpos.hwndInsertAfter;
2692
2693         winpos.hwndInsertAfter = hwndInsertAfter;
2694
2695         if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2696         {
2697           /* This is the only place where we need to force repainting of the contents
2698              of windows created by the host window system, all other cases go through the
2699              expose event handling */
2700
2701             if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2702             {
2703                 cx = newWindowRect.right - newWindowRect.left;
2704                 cy = newWindowRect.bottom - newWindowRect.top;
2705
2706                 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2707                 winpos.hwndInsertAfter = tempInsertAfter;
2708                 bCallDriver = FALSE;
2709
2710                 if( winpos.flags & SWP_NOCLIENTMOVE )
2711                     SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2712                 else
2713                 {
2714                     /* client area moved but window extents remained the same, copy valid bits */
2715
2716                     visRgn = CreateRectRgn( 0, 0, cx, cy );
2717                     uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect, 
2718                                                 uFlags | SWP_EX_PAINTSELF );
2719                 }
2720             }
2721         }
2722
2723         if( bCallDriver )
2724         {
2725             if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2726             {
2727                 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2728                     (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2729                    !(uFlags & SWP_EX_NOCOPY) )
2730                 {
2731                   /* The origin of the client rect didn't move so we can try to repaint
2732                    * only the nonclient area by setting bit gravity hint for the host window system.
2733                    */
2734
2735                     if( !(wndPtr->flags & WIN_MANAGED) )
2736                     {
2737                         HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2738                                                      newWindowRect.bottom - newWindowRect.top);
2739                         RECT rcn = newClientRect;
2740                         RECT rco = oldClientRect;
2741
2742                         OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2743                         OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2744                         IntersectRect( &rcn, &rcn, &rco );
2745                         visRgn = CreateRectRgnIndirect( &rcn );
2746                         CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2747                         DeleteObject( hrgn );
2748                         uFlags = SWP_EX_PAINTSELF;
2749                     }
2750                     wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2751                 }
2752                 else
2753                     wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2754             }
2755
2756             wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2757             winpos.hwndInsertAfter = tempInsertAfter;
2758         }
2759
2760         if( winpos.flags & SWP_SHOWWINDOW )
2761         {
2762                 HWND focus, curr;
2763
2764                 wndPtr->dwStyle |= WS_VISIBLE;
2765
2766                 if (wndPtr->flags & WIN_MANAGED) resync = TRUE; 
2767
2768                 /* focus was set to unmapped window, reset host focus 
2769                  * since the window is now visible */
2770
2771                 focus = curr = GetFocus();
2772                 while (curr) 
2773                 {
2774                     if (curr == hwnd) 
2775                     {
2776                         WND *pFocus = WIN_FindWndPtr( focus );
2777                         if (pFocus)
2778                             pFocus->pDriver->pSetFocus(pFocus);
2779                         WIN_ReleaseWndPtr(pFocus);
2780                         break;
2781                     }
2782                     curr = GetParent(curr);
2783                 }
2784         }
2785     }
2786     else                                /* -------------------------------------------- emulated window */
2787     {
2788             if( winpos.flags & SWP_SHOWWINDOW )
2789             {
2790                 wndPtr->dwStyle |= WS_VISIBLE;
2791                 uFlags |= SWP_EX_PAINTSELF;
2792                 visRgn = 1; /* redraw the whole window */
2793             }
2794             else if( !(winpos.flags & SWP_NOREDRAW) )
2795             {
2796                 if( winpos.flags & SWP_HIDEWINDOW )
2797                 {
2798                     if( visRgn > 1 ) /* map to parent */
2799                         OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2800                     else
2801                         visRgn = 0;
2802                 }
2803                 else
2804                 {
2805                     if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2806                          uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect, 
2807                                                             &oldClientRect, uFlags);
2808                     else
2809                     {
2810                         /* nothing moved, redraw frame if needed */
2811                          
2812                         if( winpos.flags & SWP_FRAMECHANGED )
2813                             SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2814                         if( visRgn )
2815                         {
2816                             DeleteObject( visRgn );
2817                             visRgn = 0;
2818                         } 
2819                     }
2820                 }
2821             }
2822     }
2823
2824     if( winpos.flags & SWP_HIDEWINDOW )
2825     {
2826         wndPtr->dwStyle &= ~WS_VISIBLE;
2827
2828         if (hwnd == CARET_GetHwnd()) DestroyCaret();
2829     }
2830
2831     /* ------------------------------------------------------------------------ FINAL */
2832
2833     if (wndPtr->flags & WIN_NATIVE)
2834         EVENT_Synchronize();  /* Synchronize with the host window system */
2835
2836     if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2837     { 
2838         /* Simulate a mouse event to set the cursor */
2839         int iWndsLocks = WIN_SuspendWndsLock();
2840         
2841         hardware_event( WM_MOUSEMOVE, GET_KEYSTATE(), 0,
2842                         PosX, PosY, GetTickCount(), 0 );
2843         
2844         WIN_RestoreWndsLock(iWndsLocks);
2845     }
2846
2847     wndTemp = WIN_GetDesktop();
2848
2849     /* repaint invalidated region (if any) 
2850      *
2851      * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2852      *        and force update after ChangeActiveWindow() to avoid painting frames twice.
2853      */
2854
2855     if( visRgn )
2856     {
2857         if( !(winpos.flags & SWP_NOREDRAW) )
2858         {
2859  
2860             /*  Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2861                 its parent and sibling and so on, and then erase the parent window 
2862                 back ground if the parent is either a top-level window or its parent's parent  
2863                 is top-level window. Rely on the system to repaint other affected 
2864                 windows later on.  */ 
2865             if( uFlags & SWP_EX_PAINTSELF )
2866             {
2867                 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, 
2868                                 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2869                                 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2870             }
2871             else
2872             {
2873                     PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, 
2874                                 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN, 
2875                                 RDW_EX_USEHRGN );
2876             }
2877
2878             if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2879                 {
2880                 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, 
2881                                 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2882             }
2883         }
2884         if( visRgn != 1 )
2885             DeleteObject( visRgn );
2886     }
2887
2888     WIN_ReleaseDesktop();
2889
2890     if (!(flags & SWP_NOACTIVATE))
2891             WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2892
2893       /* And last, send the WM_WINDOWPOSCHANGED message */
2894
2895     TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2896
2897     if ( resync ||
2898         (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) && 
2899          !(winpos.flags & SWP_NOSENDCHANGING)) )
2900     {
2901         SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2902         if (resync) EVENT_Synchronize();
2903     }
2904
2905     retvalue = TRUE;
2906 END:
2907     WIN_ReleaseWndPtr(wndPtr);
2908     return retvalue;
2909 }
2910
2911                                         
2912 /***********************************************************************
2913  *           BeginDeferWindowPos16   (USER.259)
2914  */
2915 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2916 {
2917     return BeginDeferWindowPos( count );
2918 }
2919
2920
2921 /***********************************************************************
2922  *           BeginDeferWindowPos   (USER32.9)
2923  */
2924 HDWP WINAPI BeginDeferWindowPos( INT count )
2925 {
2926     HDWP handle;
2927     DWP *pDWP;
2928
2929     if (count <= 0) return 0;
2930     handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2931     if (!handle) return 0;
2932     pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2933     pDWP->actualCount    = 0;
2934     pDWP->suggestedCount = count;
2935     pDWP->valid          = TRUE;
2936     pDWP->wMagic         = DWP_MAGIC;
2937     pDWP->hwndParent     = 0;
2938     return handle;
2939 }
2940
2941
2942 /***********************************************************************
2943  *           DeferWindowPos16   (USER.260)
2944  */
2945 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2946                                 INT16 x, INT16 y, INT16 cx, INT16 cy,
2947                                 UINT16 flags )
2948 {
2949     return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2950                              x, y, cx, cy, flags );
2951 }
2952
2953
2954 /***********************************************************************
2955  *           DeferWindowPos   (USER32.128)
2956  */
2957 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2958                                 INT x, INT y, INT cx, INT cy,
2959                                 UINT flags )
2960 {
2961     DWP *pDWP;
2962     int i;
2963     HDWP newhdwp = hdwp,retvalue;
2964     /* HWND parent; */
2965     WND *pWnd;
2966
2967     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2968     if (!pDWP) return 0;
2969     if (hwnd == GetDesktopWindow()) return 0;
2970
2971     if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2972         USER_HEAP_FREE( hdwp );
2973         return 0;
2974     }
2975         
2976 /* Numega Bounds Checker Demo dislikes the following code.
2977    In fact, I've not been able to find any "same parent" requirement in any docu
2978    [AM 980509]
2979  */
2980 #if 0
2981     /* All the windows of a DeferWindowPos() must have the same parent */
2982     parent = pWnd->parent->hwndSelf;
2983     if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2984     else if (parent != pDWP->hwndParent)
2985     {
2986         USER_HEAP_FREE( hdwp );
2987         retvalue = 0;
2988         goto END;
2989     }
2990 #endif
2991
2992     for (i = 0; i < pDWP->actualCount; i++)
2993     {
2994         if (pDWP->winPos[i].hwnd == hwnd)
2995         {
2996               /* Merge with the other changes */
2997             if (!(flags & SWP_NOZORDER))
2998             {
2999                 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3000             }
3001             if (!(flags & SWP_NOMOVE))
3002             {
3003                 pDWP->winPos[i].x = x;
3004                 pDWP->winPos[i].y = y;
3005             }                
3006             if (!(flags & SWP_NOSIZE))
3007             {
3008                 pDWP->winPos[i].cx = cx;
3009                 pDWP->winPos[i].cy = cy;
3010             }
3011             pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3012                                                SWP_NOZORDER | SWP_NOREDRAW |
3013                                                SWP_NOACTIVATE | SWP_NOCOPYBITS|
3014                                                SWP_NOOWNERZORDER);
3015             pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3016                                               SWP_FRAMECHANGED);
3017             retvalue = hdwp;
3018             goto END;
3019         }
3020     }
3021     if (pDWP->actualCount >= pDWP->suggestedCount)
3022     {
3023         newhdwp = USER_HEAP_REALLOC( hdwp,
3024                       sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3025         if (!newhdwp)
3026         {
3027             retvalue = 0;
3028             goto END;
3029         }
3030         pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3031         pDWP->suggestedCount++;
3032     }
3033     pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3034     pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3035     pDWP->winPos[pDWP->actualCount].x = x;
3036     pDWP->winPos[pDWP->actualCount].y = y;
3037     pDWP->winPos[pDWP->actualCount].cx = cx;
3038     pDWP->winPos[pDWP->actualCount].cy = cy;
3039     pDWP->winPos[pDWP->actualCount].flags = flags;
3040     pDWP->actualCount++;
3041     retvalue = newhdwp;
3042 END:
3043     WIN_ReleaseWndPtr(pWnd);
3044     return retvalue;
3045 }
3046
3047
3048 /***********************************************************************
3049  *           EndDeferWindowPos16   (USER.261)
3050  */
3051 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3052 {
3053     return EndDeferWindowPos( hdwp );
3054 }
3055
3056
3057 /***********************************************************************
3058  *           EndDeferWindowPos   (USER32.173)
3059  */
3060 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3061 {
3062     DWP *pDWP;
3063     WINDOWPOS *winpos;
3064     BOOL res = TRUE;
3065     int i;
3066
3067     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3068     if (!pDWP) return FALSE;
3069     for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3070     {
3071         if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3072                                     winpos->x, winpos->y, winpos->cx,
3073                                     winpos->cy, winpos->flags ))) break;
3074     }
3075     USER_HEAP_FREE( hdwp );
3076     return res;
3077 }
3078
3079
3080 /***********************************************************************
3081  *           TileChildWindows   (USER.199)
3082  */
3083 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3084 {
3085     FIXME("(%04x, %d): stub\n", parent, action);
3086 }
3087
3088 /***********************************************************************
3089  *           CascadeChildWindows   (USER.198)
3090  */
3091 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3092 {
3093     FIXME("(%04x, %d): stub\n", parent, action);
3094 }
3095
3096 /***********************************************************************
3097  *           SetProgmanWindow                   [USER32.522]
3098  */
3099 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3100 {
3101         hGlobalProgmanWindow = hwnd;
3102         return hGlobalProgmanWindow;
3103 }
3104
3105 /***********************************************************************
3106  *           GetProgmanWindow                   [USER32.289]
3107  */
3108 HRESULT WINAPI GetProgmanWindow ( )
3109 {
3110         return hGlobalProgmanWindow;
3111 }
3112
3113 /***********************************************************************
3114  *           SetShellWindowEx                   [USER32.531]
3115  * hwndProgman =  Progman[Program Manager]
3116  *                |-> SHELLDLL_DefView
3117  * hwndListView = |   |-> SysListView32
3118  *                |   |   |-> tooltips_class32
3119  *                |   |
3120  *                |   |-> SysHeader32
3121  *                |   
3122  *                |-> ProxyTarget
3123  */
3124 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3125 {
3126         FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3127         hGlobalShellWindow = hwndProgman;
3128         return hGlobalShellWindow;
3129
3130 }
3131
3132 /***********************************************************************
3133  *           SetTaskmanWindow                   [USER32.537]
3134  * NOTES
3135  *   hwnd = MSTaskSwWClass 
3136  *          |-> SysTabControl32
3137  */
3138 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3139 {
3140         hGlobalTaskmanWindow = hwnd;
3141         return hGlobalTaskmanWindow;
3142 }
3143
3144 /***********************************************************************
3145  *           GetTaskmanWindow                   [USER32.304]
3146  */
3147 HRESULT WINAPI GetTaskmanWindow ( )
3148 {       
3149         return hGlobalTaskmanWindow;
3150 }