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