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