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