Moved ForceWindowRaise to the USER driver and removed the WND driver.
[wine] / windows / winpos.c
1 /*
2  * Window position related functions.
3  *
4  * Copyright 1993, 1994, 1995 Alexandre Julliard
5  *                       1995, 1996, 1999 Alex Korobka
6  */
7
8 #include <string.h>
9 #include "winerror.h"
10 #include "windef.h"
11 #include "wingdi.h"
12 #include "winerror.h"
13 #include "wine/winuser16.h"
14 #include "controls.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "region.h"
18 #include "win.h"
19 #include "hook.h"
20 #include "message.h"
21 #include "queue.h"
22 #include "winpos.h"
23 #include "dce.h"
24 #include "nonclient.h"
25 #include "debugtools.h"
26 #include "input.h"
27
28 DEFAULT_DEBUG_CHANNEL(win);
29
30 #define HAS_DLGFRAME(style,exStyle) \
31     (((exStyle) & WS_EX_DLGMODALFRAME) || \
32      (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
33
34 #define HAS_THICKFRAME(style) \
35     (((style) & WS_THICKFRAME) && \
36      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
37
38 #define EMPTYPOINT(pt)          ((*(LONG*)&(pt)) == -1)
39
40 #define PLACE_MIN               0x0001
41 #define PLACE_MAX               0x0002
42 #define PLACE_RECT              0x0004
43
44
45 #define DWP_MAGIC  ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
46
47 typedef struct
48 {
49     INT       actualCount;
50     INT       suggestedCount;
51     BOOL      valid;
52     INT       wMagic;
53     HWND      hwndParent;
54     WINDOWPOS winPos[1];
55 } DWP;
56
57 /* ----- internal variables ----- */
58
59 static HWND hwndPrevActive  = 0;  /* Previously active window */
60 static HWND hGlobalShellWindow=0; /*the shell*/
61 static HWND hGlobalTaskmanWindow=0;
62 static HWND hGlobalProgmanWindow=0;
63
64 static LPCSTR atomInternalPos;
65
66 extern HQUEUE16 hActiveQueue;
67
68 /***********************************************************************
69  *           WINPOS_CreateInternalPosAtom
70  */
71 BOOL WINPOS_CreateInternalPosAtom()
72 {
73     LPSTR str = "SysIP";
74     atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
75     return (atomInternalPos) ? TRUE : FALSE;
76 }
77
78 /***********************************************************************
79  *           WINPOS_CheckInternalPos
80  *
81  * Called when a window is destroyed.
82  */
83 void WINPOS_CheckInternalPos( WND* wndPtr )
84 {
85     LPINTERNALPOS lpPos;
86     MESSAGEQUEUE *pMsgQ = 0;
87     HWND hwnd = wndPtr->hwndSelf;
88
89     lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
90
91     /* Retrieve the message queue associated with this window */
92     pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
93     if ( !pMsgQ )
94     {
95         WARN("\tMessage queue not found. Exiting!\n" );
96         return;
97     }
98
99     if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
100
101     if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
102     {
103         PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
104         WARN("\tattempt to activate destroyed window!\n");
105     }
106
107     if( lpPos )
108     {
109         if( IsWindow(lpPos->hwndIconTitle) ) 
110             DestroyWindow( lpPos->hwndIconTitle );
111         HeapFree( GetProcessHeap(), 0, lpPos );
112     }
113
114     QUEUE_Unlock( pMsgQ );
115     return;
116 }
117
118 /***********************************************************************
119  *              ArrangeIconicWindows (USER.170)
120  */
121 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent) 
122 {
123     return ArrangeIconicWindows(parent);
124 }
125 /***********************************************************************
126  *              ArrangeIconicWindows (USER32.@)
127  */
128 UINT WINAPI ArrangeIconicWindows( HWND parent )
129 {
130     RECT rectParent;
131     HWND hwndChild;
132     INT x, y, xspacing, yspacing;
133
134     GetClientRect( parent, &rectParent );
135     x = rectParent.left;
136     y = rectParent.bottom;
137     xspacing = GetSystemMetrics(SM_CXICONSPACING);
138     yspacing = GetSystemMetrics(SM_CYICONSPACING);
139
140     hwndChild = GetWindow( parent, GW_CHILD );
141     while (hwndChild)
142     {
143         if( IsIconic( hwndChild ) )
144         {
145             WND *wndPtr = WIN_FindWndPtr(hwndChild);
146             
147             WINPOS_ShowIconTitle( wndPtr, FALSE );
148                
149             SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
150                             y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
151                             SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
152             if( IsWindow(hwndChild) )
153                 WINPOS_ShowIconTitle(wndPtr , TRUE );
154             WIN_ReleaseWndPtr(wndPtr);
155
156             if (x <= rectParent.right - xspacing) x += xspacing;
157             else
158             {
159                 x = rectParent.left;
160                 y -= yspacing;
161             }
162         }
163         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
164     }
165     return yspacing;
166 }
167
168
169 /***********************************************************************
170  *              SwitchToThisWindow (USER.172)
171  */
172 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
173 {
174     SwitchToThisWindow( hwnd, restore );
175 }
176
177
178 /***********************************************************************
179  *              SwitchToThisWindow (USER32.@)
180  */
181 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
182 {
183     ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
184 }
185
186
187 /***********************************************************************
188  *              GetWindowRect (USER.32)
189  */
190 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect ) 
191 {
192     WND * wndPtr = WIN_FindWndPtr( hwnd ); 
193     if (!wndPtr) return;
194     
195     CONV_RECT32TO16( &wndPtr->rectWindow, rect );
196     if (wndPtr->parent)
197         MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
198     WIN_ReleaseWndPtr(wndPtr);
199 }
200
201
202 /***********************************************************************
203  *              GetWindowRect (USER32.@)
204  */
205 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect ) 
206 {
207     WND * wndPtr = WIN_FindWndPtr( hwnd ); 
208     if (!wndPtr) return FALSE;
209     
210     *rect = wndPtr->rectWindow;
211     if (wndPtr->parent)
212         MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
213     WIN_ReleaseWndPtr(wndPtr);
214     return TRUE;
215 }
216
217
218 /***********************************************************************
219  *              GetWindowRgn (USER32.@)
220  */
221 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
222 {
223     int nRet = ERROR;
224     WND *wndPtr = WIN_FindWndPtr( hwnd );
225     if (wndPtr)
226     {
227         if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
228         WIN_ReleaseWndPtr(wndPtr);
229     }
230     return nRet;
231 }
232
233 /***********************************************************************
234  *              SetWindowRgn (USER32.@)
235  */
236 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
237 {
238     RECT rect;
239     WND *wndPtr;
240     int ret = FALSE;
241
242     if (USER_Driver.pSetWindowRgn)
243         return USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw );
244
245     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
246
247     if (wndPtr->hrgnWnd == hrgn)
248     {
249         ret = TRUE;
250         goto done;
251     }
252
253     if (hrgn) /* verify that region really exists */
254     {
255         if (GetRgnBox( hrgn, &rect ) == ERROR) goto done;
256     }
257
258     if (wndPtr->hrgnWnd)
259     {
260         /* delete previous region */
261         DeleteObject(wndPtr->hrgnWnd);
262         wndPtr->hrgnWnd = 0;
263     }
264     wndPtr->hrgnWnd = hrgn;
265
266     /* Size the window to the rectangle of the new region (if it isn't NULL) */
267     if (hrgn) SetWindowPos( hwnd, 0, rect.left, rect.top,
268                             rect.right  - rect.left, rect.bottom - rect.top,
269                             SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE |
270                             SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
271     ret = TRUE;
272
273  done:
274     WIN_ReleaseWndPtr(wndPtr);
275     return ret;
276 }
277
278 /***********************************************************************
279  *              SetWindowRgn (USER.668)
280  */
281 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
282
283 {
284
285   FIXME("SetWindowRgn16: stub\n"); 
286   return TRUE;
287 }
288
289
290 /***********************************************************************
291  *              GetClientRect (USER.33)
292  */
293 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect ) 
294 {
295     WND * wndPtr = WIN_FindWndPtr( hwnd );
296
297     rect->left = rect->top = rect->right = rect->bottom = 0;
298     if (wndPtr) 
299     {
300         rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
301         rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
302     }
303     WIN_ReleaseWndPtr(wndPtr);
304 }
305
306
307 /***********************************************************************
308  *              GetClientRect (USER32.@)
309  */
310 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect ) 
311 {
312     WND * wndPtr = WIN_FindWndPtr( hwnd );
313
314     rect->left = rect->top = rect->right = rect->bottom = 0;
315     if (!wndPtr) return FALSE;
316     rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
317     rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
318
319     WIN_ReleaseWndPtr(wndPtr);
320     return TRUE;
321 }
322
323
324 /*******************************************************************
325  *              ClientToScreen (USER.28)
326  */
327 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
328 {
329     MapWindowPoints16( hwnd, 0, lppnt, 1 );
330 }
331
332
333 /*******************************************************************
334  *              ClientToScreen (USER32.@)
335  */
336 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
337 {
338     MapWindowPoints( hwnd, 0, lppnt, 1 );
339     return TRUE;
340 }
341
342
343 /*******************************************************************
344  *              ScreenToClient (USER.29)
345  */
346 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
347 {
348     MapWindowPoints16( 0, hwnd, lppnt, 1 );
349 }
350
351
352 /*******************************************************************
353  *              ScreenToClient (USER32.@)
354  */
355 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
356 {
357     MapWindowPoints( 0, hwnd, lppnt, 1 );
358     return TRUE;
359 }
360
361
362 /***********************************************************************
363  *           WINPOS_WindowFromPoint
364  *
365  * Find the window and hittest for a given point.
366  */
367 HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
368 {
369     WND *wndScope, *wndPtr, *wndTmp;
370     HWND hwnd_ret = 0;
371     POINT xy = pt;
372
373     TRACE("scope %04x %ld,%ld\n", hwndScope, pt.x, pt.y);
374
375     if (!hwndScope) hwndScope = GetDesktopWindow();
376     if (!(wndScope = WIN_FindWndPtr( hwndScope ))) return 0;
377
378     *hittest = HTERROR;
379     wndPtr = WIN_LockWndPtr(wndScope->child);
380
381     if( wndScope->dwStyle & WS_DISABLED )
382     {
383         *hittest = HTERROR;
384         goto end;
385     }
386
387     if (wndScope->parent)
388         MapWindowPoints( GetDesktopWindow(), wndScope->parent->hwndSelf, &xy, 1 );
389
390     if (xy.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
391         xy.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom ||
392         wndScope->dwStyle & WS_MINIMIZE)
393         goto hittest;
394
395     xy.x -= wndScope->rectClient.left;
396     xy.y -= wndScope->rectClient.top;
397
398     for (;;)
399     {
400         while (wndPtr)
401         {
402             /* If point is in window, and window is visible, and it  */
403             /* is enabled (or it's a top-level window), then explore */
404             /* its children. Otherwise, go to the next window.       */
405
406              if ((wndPtr->dwStyle & WS_VISIBLE) &&
407                 ((wndPtr->dwExStyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) != (WS_EX_LAYERED | WS_EX_TRANSPARENT)) &&
408                 (!(wndPtr->dwStyle & WS_DISABLED) ||
409                  ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
410                 (wndPtr->hrgnWnd ?
411                 PtInRegion(wndPtr->hrgnWnd, xy.x - wndPtr->rectWindow.left,
412                            xy.y - wndPtr->rectWindow.top) :
413                 ((xy.x >= wndPtr->rectWindow.left) &&
414                  (xy.x < wndPtr->rectWindow.right) &&
415                  (xy.y >= wndPtr->rectWindow.top) &&
416                  (xy.y < wndPtr->rectWindow.bottom))))
417             {
418                 TRACE("%ld,%ld is inside %04x\n", xy.x, xy.y, wndPtr->hwndSelf);
419                 hwnd_ret = wndPtr->hwndSelf;  /* Got a suitable window */
420
421                 /* If window is minimized or disabled, return at once */
422                 if (wndPtr->dwStyle & WS_MINIMIZE)
423                 {
424                     *hittest = HTCAPTION;
425                     goto end;
426                 }
427                 if (wndPtr->dwStyle & WS_DISABLED)
428                 {
429                     *hittest = HTERROR;
430                     goto end;
431                 }
432
433                 /* If point is not in client area, ignore the children */
434                 if ((xy.x < wndPtr->rectClient.left) ||
435                     (xy.x >= wndPtr->rectClient.right) ||
436                     (xy.y < wndPtr->rectClient.top) ||
437                     (xy.y >= wndPtr->rectClient.bottom)) break;
438
439                 xy.x -= wndPtr->rectClient.left;
440                 xy.y -= wndPtr->rectClient.top;
441                 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
442             }
443             else
444             {
445                 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
446             }
447         }
448
449 hittest:
450         /* If nothing found, try the scope window */
451         if (!hwnd_ret) hwnd_ret = hwndScope;
452
453         /* Send the WM_NCHITTEST message (only if to the same task) */
454         if (GetWindowThreadProcessId( hwnd_ret, NULL ) == GetCurrentThreadId())
455         {
456             INT res = SendMessageA( hwnd_ret, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ) );
457             if (res != HTTRANSPARENT)
458             {
459                 *hittest = res;  /* Found the window */
460                 goto end;
461             }
462         }
463         else
464         {
465             *hittest = HTCLIENT;
466             goto end;
467         }
468
469         if (!(wndTmp = WIN_FindWndPtr( hwnd_ret ))) break;
470
471         /* If no children found in last search, make point relative to parent */
472         if (!wndPtr)
473         {
474             xy.x += wndTmp->rectClient.left;
475             xy.y += wndTmp->rectClient.top;
476         }
477
478         /* Restart the search from the next sibling */
479         WIN_UpdateWndPtr(&wndPtr,wndTmp->next);
480         hwnd_ret = wndTmp->parent ? wndTmp->parent->hwndSelf : 0;
481         WIN_ReleaseWndPtr( wndTmp );
482     }
483
484 end:
485     WIN_ReleaseWndPtr(wndPtr);
486     WIN_ReleaseWndPtr(wndScope);
487     return hwnd_ret;
488 }
489
490
491 /*******************************************************************
492  *              WindowFromPoint (USER.30)
493  */
494 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
495 {
496     POINT pt32;
497
498     CONV_POINT16TO32( &pt, &pt32 );
499     return WindowFromPoint( pt32 );
500 }
501
502
503 /*******************************************************************
504  *              WindowFromPoint (USER32.@)
505  */
506 HWND WINAPI WindowFromPoint( POINT pt )
507 {
508     INT hittest;
509     return WINPOS_WindowFromPoint( 0, pt, &hittest );
510 }
511
512
513 /*******************************************************************
514  *              ChildWindowFromPoint (USER.191)
515  */
516 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
517 {
518     POINT pt32;
519     CONV_POINT16TO32( &pt, &pt32 );
520     return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
521 }
522
523
524 /*******************************************************************
525  *              ChildWindowFromPoint (USER32.@)
526  */
527 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
528 {
529     /* pt is in the client coordinates */
530
531     WND* wnd = WIN_FindWndPtr(hwndParent);
532     RECT rect;
533     HWND retvalue;
534
535     if( !wnd ) return 0;
536
537     /* get client rect fast */
538     rect.top = rect.left = 0;
539     rect.right = wnd->rectClient.right - wnd->rectClient.left;
540     rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
541
542     if (!PtInRect( &rect, pt ))
543     {
544         retvalue = 0;
545         goto end;
546     }
547     WIN_UpdateWndPtr(&wnd,wnd->child);
548     while ( wnd )
549     {
550         if (PtInRect( &wnd->rectWindow, pt ))
551         {
552             retvalue = wnd->hwndSelf;
553             goto end;
554         }
555         WIN_UpdateWndPtr(&wnd,wnd->next);
556     }
557     retvalue = hwndParent;
558 end:
559     WIN_ReleaseWndPtr(wnd);
560     return retvalue;
561 }
562
563 /*******************************************************************
564  *              ChildWindowFromPointEx (USER.399)
565  */
566 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
567 {
568     POINT pt32;
569     CONV_POINT16TO32( &pt, &pt32 );
570     return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
571 }
572
573
574 /*******************************************************************
575  *              ChildWindowFromPointEx (USER32.@)
576  */
577 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
578                 UINT uFlags)
579 {
580     /* pt is in the client coordinates */
581
582     WND* wnd = WIN_FindWndPtr(hwndParent);
583     RECT rect;
584     HWND retvalue;
585
586     if( !wnd ) return 0;
587
588     /* get client rect fast */
589     rect.top = rect.left = 0;
590     rect.right = wnd->rectClient.right - wnd->rectClient.left;
591     rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
592
593     if (!PtInRect( &rect, pt ))
594     {
595         retvalue = 0;
596         goto end;
597     }
598     WIN_UpdateWndPtr(&wnd,wnd->child);
599
600     while ( wnd )
601     {
602         if (PtInRect( &wnd->rectWindow, pt )) {
603                 if ( (uFlags & CWP_SKIPINVISIBLE) && 
604                                 !(wnd->dwStyle & WS_VISIBLE) );
605                 else if ( (uFlags & CWP_SKIPDISABLED) && 
606                                 (wnd->dwStyle & WS_DISABLED) );
607                 else if ( (uFlags & CWP_SKIPTRANSPARENT) && 
608                                 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
609                 else
610                 {
611                     retvalue = wnd->hwndSelf;
612                     goto end;
613                 }
614                 
615         }
616         WIN_UpdateWndPtr(&wnd,wnd->next);
617     }
618     retvalue = hwndParent;
619 end:
620     WIN_ReleaseWndPtr(wnd);
621     return retvalue;
622 }
623
624
625 /*******************************************************************
626  *         WINPOS_GetWinOffset
627  *
628  * Calculate the offset between the origin of the two windows. Used
629  * to implement MapWindowPoints.
630  */
631 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
632                                  POINT *offset )
633 {
634     WND * wndPtr = 0;
635
636     offset->x = offset->y = 0;
637     if (hwndFrom == hwndTo ) return;
638
639       /* Translate source window origin to screen coords */
640     if (hwndFrom)
641     {
642         if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
643         {
644             ERR("bad hwndFrom = %04x\n",hwndFrom);
645             return;
646         }
647         while (wndPtr->parent)
648         {
649             offset->x += wndPtr->rectClient.left;
650             offset->y += wndPtr->rectClient.top;
651             WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
652         }
653         WIN_ReleaseWndPtr(wndPtr);
654     }
655
656       /* Translate origin to destination window coords */
657     if (hwndTo)
658     {
659         if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
660         {
661             ERR("bad hwndTo = %04x\n", hwndTo );
662             return;
663         }
664         while (wndPtr->parent)
665         {
666             offset->x -= wndPtr->rectClient.left;
667             offset->y -= wndPtr->rectClient.top;
668             WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
669         }    
670         WIN_ReleaseWndPtr(wndPtr);
671     }
672 }
673
674
675 /*******************************************************************
676  *              MapWindowPoints (USER.258)
677  */
678 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
679                                LPPOINT16 lppt, UINT16 count )
680 {
681     POINT offset;
682
683     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
684     while (count--)
685     {
686         lppt->x += offset.x;
687         lppt->y += offset.y;
688         lppt++;
689     }
690 }
691
692
693 /*******************************************************************
694  *              MapWindowPoints (USER32.@)
695  */
696 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
697                                LPPOINT lppt, UINT count )
698 {
699     POINT offset;
700
701     WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
702     while (count--)
703     {
704         lppt->x += offset.x;
705         lppt->y += offset.y;
706         lppt++;
707     }
708     return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
709 }
710
711
712 /***********************************************************************
713  *              IsIconic (USER.31)
714  */
715 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
716 {
717     return IsIconic(hWnd);
718 }
719
720
721 /***********************************************************************
722  *              IsIconic (USER32.@)
723  */
724 BOOL WINAPI IsIconic(HWND hWnd)
725 {
726     BOOL retvalue;
727     WND * wndPtr = WIN_FindWndPtr(hWnd);
728     if (wndPtr == NULL) return FALSE;
729     retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
730     WIN_ReleaseWndPtr(wndPtr);
731     return retvalue;
732 }
733  
734  
735 /***********************************************************************
736  *              IsZoomed (USER.272)
737  */
738 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
739 {
740     return IsZoomed(hWnd);
741 }
742
743
744 /***********************************************************************
745  *              IsZoomed (USER32.@)
746  */
747 BOOL WINAPI IsZoomed(HWND hWnd)
748 {
749     BOOL retvalue;
750     WND * wndPtr = WIN_FindWndPtr(hWnd);
751     if (wndPtr == NULL) return FALSE;
752     retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
753     WIN_ReleaseWndPtr(wndPtr);
754     return retvalue;
755 }
756
757
758 /*******************************************************************
759  *              GetActiveWindow (USER.60)
760  */
761 HWND16 WINAPI GetActiveWindow16(void)
762 {
763     return (HWND16)GetActiveWindow();
764 }
765
766 /*******************************************************************
767  *              GetActiveWindow (USER32.@)
768  */
769 HWND WINAPI GetActiveWindow(void)
770 {
771     MESSAGEQUEUE *pCurMsgQ = 0;
772     HWND hwndActive = 0;
773
774     /* Get the messageQ for the current thread */
775     if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
776 {
777         WARN("\tCurrent message queue not found. Exiting!\n" );
778         return 0;
779     }
780
781     /* Return the current active window from the perQ data of the current message Q */
782     hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
783
784     QUEUE_Unlock( pCurMsgQ );
785     return hwndActive;
786 }
787
788
789 /*******************************************************************
790  *         WINPOS_CanActivate
791  */
792 static BOOL WINPOS_CanActivate(WND* pWnd)
793 {
794     if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
795        == WS_VISIBLE ) ) return TRUE;
796     return FALSE;
797 }
798
799
800 /*******************************************************************
801  *              SetActiveWindow (USER.59)
802  */
803 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
804 {
805     return SetActiveWindow(hwnd);
806 }
807
808
809 /*******************************************************************
810  *              SetActiveWindow (USER32.@)
811  */
812 HWND WINAPI SetActiveWindow( HWND hwnd )
813 {
814     HWND prev = 0;
815     WND *wndPtr = WIN_FindWndPtr( hwnd );
816     MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
817
818     if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
819     {
820         prev = 0;
821         goto end;
822     }
823
824     /* Get the messageQ for the current thread */
825     if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
826     {
827         WARN("\tCurrent message queue not found. Exiting!\n" );
828         goto CLEANUP;
829     }
830     
831     /* Retrieve the message queue associated with this window */
832     pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
833     if ( !pMsgQ )
834     {
835         WARN("\tWindow message queue not found. Exiting!\n" );
836         goto CLEANUP;
837     }
838
839     /* Make sure that the window is associated with the calling threads
840      * message queue. It must share the same perQ data.
841      */
842     
843     if ( pCurMsgQ->pQData != pMsgQ->pQData )
844         goto CLEANUP;
845     
846     /* Save current active window */
847     prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
848     
849     WINPOS_SetActiveWindow( hwnd, 0, 0 );
850
851 CLEANUP:
852     /* Unlock the queues before returning */
853     if ( pMsgQ )
854         QUEUE_Unlock( pMsgQ );
855     if ( pCurMsgQ )
856         QUEUE_Unlock( pCurMsgQ );
857     
858 end:
859     WIN_ReleaseWndPtr(wndPtr);
860     return prev;
861 }
862
863
864 /*******************************************************************
865  *              GetForegroundWindow (USER.608)
866  */
867 HWND16 WINAPI GetForegroundWindow16(void)
868 {
869     return (HWND16)GetForegroundWindow();
870 }
871
872
873 /*******************************************************************
874  *              SetForegroundWindow (USER.609)
875  */
876 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
877 {
878     return SetForegroundWindow( hwnd );
879 }
880
881
882 /*******************************************************************
883  *              GetForegroundWindow (USER32.@)
884  */
885 HWND WINAPI GetForegroundWindow(void)
886 {
887     HWND hwndActive = 0;
888
889     /* Get the foreground window (active window of hActiveQueue) */
890     if ( hActiveQueue )
891     {
892         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
893         if ( pActiveQueue )
894             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
895
896         QUEUE_Unlock( pActiveQueue );
897     }
898
899     return hwndActive;
900 }
901
902 /*******************************************************************
903  *              SetForegroundWindow (USER32.@)
904  */
905 BOOL WINAPI SetForegroundWindow( HWND hwnd )
906 {
907     return WINPOS_ChangeActiveWindow( hwnd, FALSE );
908 }
909
910
911 /*******************************************************************
912  *              AllowSetForegroundWindow (USER32.@)
913  */
914 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
915 {
916     /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
917      * implemented, then fix this function. */
918     return TRUE;
919 }
920
921
922 /*******************************************************************
923  *              LockSetForegroundWindow (USER32.@)
924  */
925 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
926 {
927     /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
928      * implemented, then fix this function. */
929     return TRUE;
930 }
931
932
933 /*******************************************************************
934  *              GetShellWindow (USER.600)
935  */
936 HWND16 WINAPI GetShellWindow16(void)
937 {
938     return GetShellWindow();
939 }
940
941 /*******************************************************************
942  *              SetShellWindow (USER32.@)
943  */
944 HWND WINAPI SetShellWindow(HWND hwndshell)
945 {   WARN("(hWnd=%08x) semi stub\n",hwndshell );
946
947     hGlobalShellWindow = hwndshell;
948     return hGlobalShellWindow;
949 }
950
951
952 /*******************************************************************
953  *              GetShellWindow (USER32.@)
954  */
955 HWND WINAPI GetShellWindow(void)
956 {   WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
957
958     return hGlobalShellWindow;
959 }
960
961
962 /***********************************************************************
963  *              BringWindowToTop (USER.45)
964  */
965 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
966 {
967     return BringWindowToTop(hwnd);
968 }
969
970
971 /***********************************************************************
972  *              BringWindowToTop (USER32.@)
973  */
974 BOOL WINAPI BringWindowToTop( HWND hwnd )
975 {
976     return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
977 }
978
979
980 /***********************************************************************
981  *              MoveWindow (USER.56)
982  */
983 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
984                             BOOL16 repaint )
985 {
986     return MoveWindow(hwnd,x,y,cx,cy,repaint);
987 }
988
989
990 /***********************************************************************
991  *              MoveWindow (USER32.@)
992  */
993 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
994                             BOOL repaint )
995 {    
996     int flags = SWP_NOZORDER | SWP_NOACTIVATE;
997     if (!repaint) flags |= SWP_NOREDRAW;
998     TRACE("%04x %d,%d %dx%d %d\n", 
999             hwnd, x, y, cx, cy, repaint );
1000     return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1001 }
1002
1003 /***********************************************************************
1004  *           WINPOS_InitInternalPos
1005  */
1006 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt, 
1007                                              LPRECT restoreRect )
1008 {
1009     LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1010                                                       atomInternalPos );
1011     if( !lpPos )
1012     {
1013         /* this happens when the window is minimized/maximized 
1014          * for the first time (rectWindow is not adjusted yet) */
1015
1016         lpPos = HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS) );
1017         if( !lpPos ) return NULL;
1018
1019         SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1020         lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1021         CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1022         *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1023     }
1024
1025     if( wnd->dwStyle & WS_MINIMIZE ) 
1026         CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1027     else if( wnd->dwStyle & WS_MAXIMIZE ) 
1028         CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1029     else if( restoreRect ) 
1030         CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1031
1032     return lpPos;
1033 }
1034
1035 /***********************************************************************
1036  *           WINPOS_RedrawIconTitle
1037  */
1038 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1039 {
1040     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1041     if( lpPos )
1042     {
1043         if( lpPos->hwndIconTitle )
1044         {
1045             SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1046             InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1047             return TRUE;
1048         }
1049     }
1050     return FALSE;
1051 }
1052
1053 /***********************************************************************
1054  *           WINPOS_ShowIconTitle
1055  */
1056 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1057 {
1058     LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1059
1060     if( lpPos && !(pWnd->dwExStyle & WS_EX_MANAGED))
1061     {
1062         HWND16 hWnd = lpPos->hwndIconTitle;
1063
1064         TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1065
1066         if( !hWnd )
1067             lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1068         if( bShow )
1069         {
1070             if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL) 
1071             {
1072                 if( !(pWnd->dwStyle & WS_VISIBLE) )
1073                 {
1074                    SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1075                    SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1076                                  SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1077                 }
1078                 WIN_ReleaseWndPtr(pWnd);
1079             }
1080         }
1081         else ShowWindow( hWnd, SW_HIDE );
1082     }
1083     return FALSE;
1084 }
1085
1086 /*******************************************************************
1087  *           WINPOS_GetMinMaxInfo
1088  *
1089  * Get the minimized and maximized information for a window.
1090  */
1091 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1092                            POINT *minTrack, POINT *maxTrack )
1093 {
1094     LPINTERNALPOS lpPos;
1095     MINMAXINFO MinMax;
1096     INT xinc, yinc;
1097
1098     /* Compute default values */
1099
1100     MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1101     MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1102     MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1103     MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1104     MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1105     MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1106
1107     if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1108     {
1109         xinc = GetSystemMetrics(SM_CXDLGFRAME);
1110         yinc = GetSystemMetrics(SM_CYDLGFRAME);
1111     }
1112     else
1113     {
1114         xinc = yinc = 0;
1115         if (HAS_THICKFRAME(wndPtr->dwStyle))
1116         {
1117             xinc += GetSystemMetrics(SM_CXFRAME);
1118             yinc += GetSystemMetrics(SM_CYFRAME);
1119         }
1120         if (wndPtr->dwStyle & WS_BORDER)
1121         {
1122             xinc += GetSystemMetrics(SM_CXBORDER);
1123             yinc += GetSystemMetrics(SM_CYBORDER);
1124         }
1125     }
1126     MinMax.ptMaxSize.x += 2 * xinc;
1127     MinMax.ptMaxSize.y += 2 * yinc;
1128
1129     lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1130     if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1131         CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1132     else
1133     {
1134         MinMax.ptMaxPosition.x = -xinc;
1135         MinMax.ptMaxPosition.y = -yinc;
1136     }
1137
1138     SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1139
1140       /* Some sanity checks */
1141
1142     TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1143                       MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1144                       MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1145                       MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1146                       MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1147     MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1148                                    MinMax.ptMinTrackSize.x );
1149     MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1150                                    MinMax.ptMinTrackSize.y );
1151
1152     if (maxSize) *maxSize = MinMax.ptMaxSize;
1153     if (maxPos) *maxPos = MinMax.ptMaxPosition;
1154     if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1155     if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1156 }
1157
1158 /***********************************************************************
1159  *              ShowWindowAsync (USER32.@)
1160  *
1161  * doesn't wait; returns immediately.
1162  * used by threads to toggle windows in other (possibly hanging) threads
1163  */
1164 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1165 {
1166     /* FIXME: does ShowWindow() return immediately ? */
1167     return ShowWindow(hwnd, cmd);
1168 }
1169
1170
1171 /***********************************************************************
1172  *              ShowWindow (USER.42)
1173  */
1174 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd ) 
1175 {    
1176     return ShowWindow(hwnd,cmd);
1177 }
1178
1179
1180 /***********************************************************************
1181  *              ShowWindow (USER32.@)
1182  */
1183 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1184 {
1185     return USER_Driver.pShowWindow( hwnd, cmd );
1186 }
1187
1188
1189 /***********************************************************************
1190  *              GetInternalWindowPos (USER.460)
1191  */
1192 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1193                                       LPPOINT16 ptIcon )
1194 {
1195     WINDOWPLACEMENT16 wndpl;
1196     if (GetWindowPlacement16( hwnd, &wndpl )) 
1197     {
1198         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1199         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1200         return wndpl.showCmd;
1201     }
1202     return 0;
1203 }
1204
1205
1206 /***********************************************************************
1207  *              GetInternalWindowPos (USER32.@)
1208  */
1209 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1210                                       LPPOINT ptIcon )
1211 {
1212     WINDOWPLACEMENT wndpl;
1213     if (GetWindowPlacement( hwnd, &wndpl ))
1214     {
1215         if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1216         if (ptIcon)  *ptIcon = wndpl.ptMinPosition;
1217         return wndpl.showCmd;
1218     }
1219     return 0;
1220 }
1221
1222 /***********************************************************************
1223  *              GetWindowPlacement (USER.370)
1224  */
1225 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1226 {
1227     WND *pWnd = WIN_FindWndPtr( hwnd );
1228     LPINTERNALPOS lpPos;
1229     
1230     if(!pWnd ) return FALSE;
1231
1232     lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1233                              *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1234         wndpl->length  = sizeof(*wndpl);
1235         if( pWnd->dwStyle & WS_MINIMIZE )
1236             wndpl->showCmd = SW_SHOWMINIMIZED;
1237         else 
1238             wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1239                              ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1240         if( pWnd->flags & WIN_RESTORE_MAX )
1241             wndpl->flags = WPF_RESTORETOMAXIMIZED;
1242         else
1243             wndpl->flags = 0;
1244         wndpl->ptMinPosition = lpPos->ptIconPos;
1245         wndpl->ptMaxPosition = lpPos->ptMaxPos;
1246         wndpl->rcNormalPosition = lpPos->rectNormal;
1247
1248     WIN_ReleaseWndPtr(pWnd);
1249         return TRUE;
1250     }
1251
1252
1253 /***********************************************************************
1254  *              GetWindowPlacement (USER32.@)
1255  *
1256  * Win95:
1257  * Fails if wndpl->length of Win95 (!) apps is invalid.
1258  */
1259 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1260 {
1261     if( pwpl32 )
1262     {
1263         WINDOWPLACEMENT16 wpl;
1264         wpl.length = sizeof(wpl);
1265         if( GetWindowPlacement16( hwnd, &wpl ) )
1266         {
1267             pwpl32->length = sizeof(*pwpl32);
1268             pwpl32->flags = wpl.flags;
1269             pwpl32->showCmd = wpl.showCmd;
1270             CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1271             CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1272             CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1273             return TRUE;
1274         }
1275     }
1276     return FALSE;
1277 }
1278
1279
1280 /***********************************************************************
1281  *           WINPOS_SetPlacement
1282  */
1283 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1284                                                 UINT flags )
1285 {
1286     WND *pWnd = WIN_FindWndPtr( hwnd );
1287     if( pWnd )
1288     {
1289         LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1290                              *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1291
1292         if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1293         if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1294         if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1295
1296         if( pWnd->dwStyle & WS_MINIMIZE )
1297         {
1298             WINPOS_ShowIconTitle( pWnd, FALSE );
1299             if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1300                 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1301                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1302         } 
1303         else if( pWnd->dwStyle & WS_MAXIMIZE )
1304         {
1305             if( !EMPTYPOINT(lpPos->ptMaxPos) )
1306                 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1307                                 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1308         }
1309         else if( flags & PLACE_RECT )
1310                 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1311                                 lpPos->rectNormal.right - lpPos->rectNormal.left,
1312                                 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1313                                 SWP_NOZORDER | SWP_NOACTIVATE );
1314
1315         ShowWindow( hwnd, wndpl->showCmd );
1316         if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1317         {
1318             if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1319
1320             /* SDK: ...valid only the next time... */
1321             if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1322         }
1323         WIN_ReleaseWndPtr(pWnd);
1324         return TRUE;
1325     }
1326     return FALSE;
1327 }
1328
1329
1330 /***********************************************************************
1331  *              SetWindowPlacement (USER.371)
1332  */
1333 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1334 {
1335     return WINPOS_SetPlacement( hwnd, wndpl,
1336                                 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1337 }
1338
1339 /***********************************************************************
1340  *              SetWindowPlacement (USER32.@)
1341  *
1342  * Win95:
1343  * Fails if wndpl->length of Win95 (!) apps is invalid.
1344  */
1345 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1346 {
1347     if( pwpl32 )
1348     {
1349         WINDOWPLACEMENT16 wpl;
1350
1351         wpl.length = sizeof(WINDOWPLACEMENT16);
1352         wpl.flags = pwpl32->flags;
1353         wpl.showCmd = pwpl32->showCmd;
1354         wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1355         wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1356         wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1357         wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1358         wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1359         wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1360         wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1361         wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1362
1363         return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1364     }
1365     return FALSE;
1366 }
1367
1368
1369 /***********************************************************************
1370  *              SetInternalWindowPos (USER.461)
1371  */
1372 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1373                                     LPRECT16 rect, LPPOINT16 pt )
1374 {
1375     if( IsWindow16(hwnd) )
1376     {
1377         WINDOWPLACEMENT16 wndpl;
1378         UINT flags;
1379
1380         wndpl.length  = sizeof(wndpl);
1381         wndpl.showCmd = showCmd;
1382         wndpl.flags = flags = 0;
1383
1384         if( pt )
1385         {
1386             flags |= PLACE_MIN;
1387             wndpl.flags |= WPF_SETMINPOSITION;
1388             wndpl.ptMinPosition = *pt;
1389         }
1390         if( rect )
1391         {
1392             flags |= PLACE_RECT;
1393             wndpl.rcNormalPosition = *rect;
1394         }
1395         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1396     }
1397 }
1398
1399 /***********************************************************************
1400  *              AnimateWindow (USER32.@)
1401  *              Shows/Hides a window with an animation
1402  *              NO ANIMATION YET
1403  */
1404 BOOL WINAPI AnimateWindow(HWND hwnd, DWORD dwTime, DWORD dwFlags)
1405 {
1406         FIXME("partial stub\n");
1407
1408         /* If trying to show/hide and it's already   *
1409          * shown/hidden or invalid window, fail with *
1410          * invalid parameter                         */
1411         if(!IsWindow(hwnd) ||
1412            (IsWindowVisible(hwnd) && !(dwFlags & AW_HIDE)) ||
1413            (!IsWindowVisible(hwnd) && (dwFlags & AW_HIDE)))
1414         {
1415                 SetLastError(ERROR_INVALID_PARAMETER);
1416                 return FALSE;
1417         }
1418
1419         ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA));
1420
1421         return TRUE;
1422 }
1423
1424 /***********************************************************************
1425  *              SetInternalWindowPos (USER32.@)
1426  */
1427 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1428                                     LPRECT rect, LPPOINT pt )
1429 {
1430     if( IsWindow(hwnd) )
1431     {
1432         WINDOWPLACEMENT16 wndpl;
1433         UINT flags;
1434
1435         wndpl.length  = sizeof(wndpl);
1436         wndpl.showCmd = showCmd;
1437         wndpl.flags = flags = 0;
1438
1439         if( pt )
1440         {
1441             flags |= PLACE_MIN;
1442             wndpl.flags |= WPF_SETMINPOSITION;
1443             CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1444         }
1445         if( rect )
1446         {
1447             flags |= PLACE_RECT;
1448             CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1449         }
1450         WINPOS_SetPlacement( hwnd, &wndpl, flags );
1451     }
1452 }
1453
1454 /*******************************************************************
1455  *         WINPOS_SetActiveWindow
1456  *
1457  * SetActiveWindow() back-end. This is the only function that
1458  * can assign active status to a window. It must be called only
1459  * for the top level windows.
1460  */
1461 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1462 {
1463     WND*     wndPtr=0, *wndTemp;
1464     HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1465     MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1466     WORD     wIconized = 0;
1467     HWND     hwndActive = 0;
1468     BOOL     bRet = 0;
1469
1470     TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1471
1472     /* Get current active window from the active queue */
1473     if ( hActiveQueue )
1474     {
1475         pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1476         if ( pOldActiveQueue )
1477             hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1478     }
1479
1480     /* paranoid checks */
1481     if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1482         goto CLEANUP_END;
1483
1484 /*  if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1485  *      return 0;
1486  */
1487     wndPtr = WIN_FindWndPtr(hWnd);
1488     hOldActiveQueue = hActiveQueue;
1489
1490     if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1491     {
1492         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1493         WIN_ReleaseWndPtr(wndTemp);
1494     }
1495     else
1496         TRACE("no current active window.\n");
1497
1498     /* call CBT hook chain */
1499     if (HOOK_IsHooked( WH_CBT ))
1500     {
1501         CBTACTIVATESTRUCT cbt;
1502         cbt.fMouse     = fMouse;
1503         cbt.hWndActive = hwndActive;
1504         if (HOOK_CallHooksA( WH_CBT, HCBT_ACTIVATE, hWnd, (LPARAM)&cbt )) goto CLEANUP_END;
1505     }
1506
1507     /* set prev active wnd to current active wnd and send notification */
1508     if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1509     {
1510         MESSAGEQUEUE *pTempActiveQueue = 0;
1511         
1512         if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1513         {
1514             if (GetSysModalWindow16() != hWnd) 
1515                 goto CLEANUP_END;
1516             /* disregard refusal if hWnd is sysmodal */
1517         }
1518
1519         SendMessageA( hwndPrevActive, WM_ACTIVATE,
1520                         MAKEWPARAM( WA_INACTIVE, wIconized ),
1521                         (LPARAM)hWnd );
1522
1523         /* check if something happened during message processing
1524          * (global active queue may have changed)
1525          */
1526         pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1527         if(!pTempActiveQueue)
1528             goto CLEANUP_END;
1529
1530         hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1531         QUEUE_Unlock( pTempActiveQueue );
1532         if( hwndPrevActive != hwndActive )
1533             goto CLEANUP_END;
1534     }
1535
1536     /* Set new active window in the message queue */
1537     hwndActive = hWnd;
1538     if ( wndPtr )
1539     {
1540         pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1541         if ( pNewActiveQueue )
1542             PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1543     }
1544     else /* have to do this or MDI frame activation goes to hell */
1545         if( pOldActiveQueue )
1546             PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1547
1548     /* send palette messages */
1549     if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1550         SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1551
1552     /* if prev wnd is minimized redraw icon title */
1553     if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1554
1555     /* managed windows will get ConfigureNotify event */  
1556     if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1557     {
1558         /* check Z-order and bring hWnd to the top */
1559         for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1560         {
1561             if (wndTemp->dwStyle & WS_VISIBLE) break;
1562         }
1563         WIN_ReleaseDesktop();
1564         WIN_ReleaseWndPtr(wndTemp);
1565
1566         if( wndTemp != wndPtr )
1567             SetWindowPos(hWnd, HWND_TOP, 0,0,0,0, 
1568                            SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1569         if (!IsWindow(hWnd))  
1570             goto CLEANUP;
1571     }
1572
1573     /* Get a handle to the new active queue */
1574     hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1575
1576     /* send WM_ACTIVATEAPP if necessary */
1577     if (hOldActiveQueue != hNewActiveQueue)
1578     {
1579         WND **list, **ppWnd;
1580         WND *pDesktop = WIN_GetDesktop();
1581
1582         if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1583         {
1584             DWORD new_thread = GetWindowThreadProcessId( hwndActive, NULL );
1585             for (ppWnd = list; *ppWnd; ppWnd++)
1586             {
1587                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1588
1589                 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1590                     SendMessageW( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP, 0, new_thread );
1591             }
1592             WIN_ReleaseWinArray(list);
1593         }
1594
1595         hActiveQueue = hNewActiveQueue;
1596
1597         if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1598         {
1599             DWORD old_thread = GetWindowThreadProcessId( hwndPrevActive, NULL );
1600             for (ppWnd = list; *ppWnd; ppWnd++)
1601             {
1602                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1603
1604                 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1605                     SendMessageW( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP, 1, old_thread );
1606             }
1607             WIN_ReleaseWinArray(list);
1608         }
1609         WIN_ReleaseDesktop();
1610         
1611         if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1612     }
1613
1614     if (hWnd)
1615     {
1616         /* walk up to the first unowned window */
1617         wndTemp = WIN_LockWndPtr(wndPtr);
1618         while (wndTemp->owner)
1619         {
1620             WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1621         }
1622         /* and set last active owned popup */
1623         wndTemp->hwndLastActive = hWnd;
1624
1625         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1626         WIN_ReleaseWndPtr(wndTemp);
1627         SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1628         SendMessageA( hWnd, WM_ACTIVATE,
1629                  MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1630                  (LPARAM)hwndPrevActive );
1631         if( !IsWindow(hWnd) ) goto CLEANUP;
1632     }
1633
1634     /* change focus if possible */
1635     if ( fChangeFocus )
1636     {
1637         if ( pNewActiveQueue )
1638         {
1639             HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1640
1641             if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1642                 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus, 
1643                                    (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1644                                    0 : hwndActive );
1645         }
1646
1647         if ( pOldActiveQueue && 
1648              ( !pNewActiveQueue || 
1649                 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1650         {
1651             HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1652             if ( hOldFocus )
1653                 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1654         }
1655     }
1656
1657     if( !hwndPrevActive && wndPtr )
1658     {
1659         if (USER_Driver.pForceWindowRaise) USER_Driver.pForceWindowRaise( wndPtr->hwndSelf );
1660     }
1661
1662     /* if active wnd is minimized redraw icon title */
1663     if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1664
1665     bRet = (hWnd == hwndActive);  /* Success? */
1666     
1667 CLEANUP: /* Unlock the message queues before returning */
1668
1669     if ( pNewActiveQueue )
1670         QUEUE_Unlock( pNewActiveQueue );
1671
1672 CLEANUP_END:
1673
1674     if ( pOldActiveQueue )
1675         QUEUE_Unlock( pOldActiveQueue );
1676
1677     WIN_ReleaseWndPtr(wndPtr);
1678     return bRet;
1679 }
1680
1681 /*******************************************************************
1682  *         WINPOS_ActivateOtherWindow
1683  *
1684  *  Activates window other than pWnd.
1685  */
1686 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1687 {
1688   BOOL  bRet = 0;
1689   WND*          pWndTo = NULL;
1690     HWND       hwndActive = 0;
1691
1692     /* Get current active window from the active queue */
1693     if ( hActiveQueue )
1694     {
1695         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1696         if ( pActiveQueue )
1697         {
1698             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1699             QUEUE_Unlock( pActiveQueue );
1700         }
1701     }
1702
1703   if( pWnd->hwndSelf == hwndPrevActive )
1704       hwndPrevActive = 0;
1705
1706   if( hwndActive != pWnd->hwndSelf && 
1707     ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1708       return 0;
1709
1710   if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1711       !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) ) 
1712   {
1713       WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1714
1715       WIN_ReleaseWndPtr(pWndTo);
1716       pWndTo = WIN_FindWndPtr(hwndPrevActive);
1717
1718       while( !WINPOS_CanActivate(pWndTo) ) 
1719       {
1720          /* by now owned windows should've been taken care of */
1721           WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1722           WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1723           if( !pWndTo ) break;
1724       }
1725       WIN_ReleaseWndPtr(pWndPtr);
1726   }
1727
1728   bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1729
1730   if( pWndTo ) WIN_ReleaseWndPtr(pWndTo);
1731
1732   hwndPrevActive = 0;
1733   return bRet;  
1734 }
1735
1736 /*******************************************************************
1737  *         WINPOS_ChangeActiveWindow
1738  *
1739  */
1740 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1741 {
1742     WND *wndPtr;
1743     BOOL retvalue;
1744     HWND hwndActive = 0;
1745
1746     /* Get current active window from the active queue */
1747     if ( hActiveQueue )
1748     {
1749         MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1750         if ( pActiveQueue )
1751         {
1752             hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1753             QUEUE_Unlock( pActiveQueue );
1754         }
1755     }
1756
1757     if (!hWnd)
1758         return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1759
1760     wndPtr = WIN_FindWndPtr(hWnd);
1761     if( !wndPtr ) return FALSE;
1762
1763     /* child windows get WM_CHILDACTIVATE message */
1764     if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1765     {
1766         retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1767         goto end;
1768     }
1769
1770     if( hWnd == hwndActive )
1771     {
1772         retvalue = FALSE;
1773         goto end;
1774     }
1775
1776     if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1777     {
1778         retvalue = FALSE;
1779         goto end;
1780     }
1781
1782     retvalue = TRUE;
1783 end:
1784     WIN_ReleaseWndPtr(wndPtr);
1785     return retvalue;
1786 }
1787
1788
1789 /***********************************************************************
1790  *           WINPOS_SendNCCalcSize
1791  *
1792  * Send a WM_NCCALCSIZE message to a window.
1793  * All parameters are read-only except newClientRect.
1794  * oldWindowRect, oldClientRect and winpos must be non-NULL only
1795  * when calcValidRect is TRUE.
1796  */
1797 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
1798                             RECT *newWindowRect, RECT *oldWindowRect,
1799                             RECT *oldClientRect, WINDOWPOS *winpos,
1800                             RECT *newClientRect )
1801 {
1802     NCCALCSIZE_PARAMS params;
1803     WINDOWPOS winposCopy;
1804     LONG result;
1805
1806     params.rgrc[0] = *newWindowRect;
1807     if (calcValidRect)
1808     {
1809         winposCopy = *winpos;
1810         params.rgrc[1] = *oldWindowRect;
1811         params.rgrc[2] = *oldClientRect;
1812         params.lppos = &winposCopy;
1813     }
1814     result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
1815                              (LPARAM)&params );
1816     TRACE("%d,%d-%d,%d\n",
1817                  params.rgrc[0].left, params.rgrc[0].top,
1818                  params.rgrc[0].right, params.rgrc[0].bottom );
1819
1820     /* If the application send back garbage, ignore it */
1821     if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
1822         *newClientRect = params.rgrc[0];
1823
1824     return result;
1825 }
1826
1827
1828 /***********************************************************************
1829  *           WINPOS_HandleWindowPosChanging16
1830  *
1831  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1832  */
1833 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
1834 {
1835     POINT maxSize, minTrack;
1836     if (winpos->flags & SWP_NOSIZE) return 0;
1837     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1838         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1839     {
1840         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
1841         if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
1842         if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
1843         if (!(wndPtr->dwStyle & WS_MINIMIZE))
1844         {
1845             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1846             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1847         }
1848     }
1849     return 0;
1850 }
1851
1852
1853 /***********************************************************************
1854  *           WINPOS_HandleWindowPosChanging
1855  *
1856  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1857  */
1858 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
1859 {
1860     POINT maxSize, minTrack;
1861     if (winpos->flags & SWP_NOSIZE) return 0;
1862     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1863         ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1864     {
1865         WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
1866         winpos->cx = min( winpos->cx, maxSize.x );
1867         winpos->cy = min( winpos->cy, maxSize.y );
1868         if (!(wndPtr->dwStyle & WS_MINIMIZE))
1869         {
1870             if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1871             if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1872         }
1873     }
1874     return 0;
1875 }
1876
1877 /***********************************************************************
1878  *              SetWindowPos (USER.232)
1879  */
1880 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
1881                               INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
1882 {
1883     return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
1884 }
1885
1886 /***********************************************************************
1887  *              SetWindowPos (USER32.@)
1888  */
1889 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
1890                           INT x, INT y, INT cx, INT cy, UINT flags )
1891 {
1892     WINDOWPOS winpos;
1893
1894     winpos.hwnd = hwnd;
1895     winpos.hwndInsertAfter = hwndInsertAfter;
1896     winpos.x = x;
1897     winpos.y = y;
1898     winpos.cx = cx;
1899     winpos.cy = cy;
1900     winpos.flags = flags;
1901     return USER_Driver.pSetWindowPos( &winpos );
1902 }
1903
1904
1905 /***********************************************************************
1906  *              BeginDeferWindowPos (USER.259)
1907  */
1908 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
1909 {
1910     return BeginDeferWindowPos( count );
1911 }
1912
1913
1914 /***********************************************************************
1915  *              BeginDeferWindowPos (USER32.@)
1916  */
1917 HDWP WINAPI BeginDeferWindowPos( INT count )
1918 {
1919     HDWP handle;
1920     DWP *pDWP;
1921
1922     if (count < 0) 
1923     {
1924         SetLastError(ERROR_INVALID_PARAMETER);
1925         return 0;
1926     }
1927     /* Windows allows zero count, in which case it allocates context for 8 moves */
1928     if (count == 0) count = 8;
1929
1930     handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
1931     if (!handle) return 0;
1932     pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
1933     pDWP->actualCount    = 0;
1934     pDWP->suggestedCount = count;
1935     pDWP->valid          = TRUE;
1936     pDWP->wMagic         = DWP_MAGIC;
1937     pDWP->hwndParent     = 0;
1938     return handle;
1939 }
1940
1941
1942 /***********************************************************************
1943  *              DeferWindowPos (USER.260)
1944  */
1945 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
1946                                 INT16 x, INT16 y, INT16 cx, INT16 cy,
1947                                 UINT16 flags )
1948 {
1949     return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
1950                              x, y, cx, cy, flags );
1951 }
1952
1953
1954 /***********************************************************************
1955  *              DeferWindowPos (USER32.@)
1956  */
1957 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
1958                                 INT x, INT y, INT cx, INT cy,
1959                                 UINT flags )
1960 {
1961     DWP *pDWP;
1962     int i;
1963     HDWP newhdwp = hdwp,retvalue;
1964     /* HWND parent; */
1965     WND *pWnd;
1966
1967     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1968     if (!pDWP) return 0;
1969     if (hwnd == GetDesktopWindow()) return 0;
1970
1971     if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
1972         USER_HEAP_FREE( hdwp );
1973         return 0;
1974     }
1975         
1976 /* Numega Bounds Checker Demo dislikes the following code.
1977    In fact, I've not been able to find any "same parent" requirement in any docu
1978    [AM 980509]
1979  */
1980 #if 0
1981     /* All the windows of a DeferWindowPos() must have the same parent */
1982     parent = pWnd->parent->hwndSelf;
1983     if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
1984     else if (parent != pDWP->hwndParent)
1985     {
1986         USER_HEAP_FREE( hdwp );
1987         retvalue = 0;
1988         goto END;
1989     }
1990 #endif
1991
1992     for (i = 0; i < pDWP->actualCount; i++)
1993     {
1994         if (pDWP->winPos[i].hwnd == hwnd)
1995         {
1996               /* Merge with the other changes */
1997             if (!(flags & SWP_NOZORDER))
1998             {
1999                 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2000             }
2001             if (!(flags & SWP_NOMOVE))
2002             {
2003                 pDWP->winPos[i].x = x;
2004                 pDWP->winPos[i].y = y;
2005             }                
2006             if (!(flags & SWP_NOSIZE))
2007             {
2008                 pDWP->winPos[i].cx = cx;
2009                 pDWP->winPos[i].cy = cy;
2010             }
2011             pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2012                                                SWP_NOZORDER | SWP_NOREDRAW |
2013                                                SWP_NOACTIVATE | SWP_NOCOPYBITS|
2014                                                SWP_NOOWNERZORDER);
2015             pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2016                                               SWP_FRAMECHANGED);
2017             retvalue = hdwp;
2018             goto END;
2019         }
2020     }
2021     if (pDWP->actualCount >= pDWP->suggestedCount)
2022     {
2023         newhdwp = USER_HEAP_REALLOC( hdwp,
2024                       sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
2025         if (!newhdwp)
2026         {
2027             retvalue = 0;
2028             goto END;
2029         }
2030         pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2031         pDWP->suggestedCount++;
2032     }
2033     pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2034     pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2035     pDWP->winPos[pDWP->actualCount].x = x;
2036     pDWP->winPos[pDWP->actualCount].y = y;
2037     pDWP->winPos[pDWP->actualCount].cx = cx;
2038     pDWP->winPos[pDWP->actualCount].cy = cy;
2039     pDWP->winPos[pDWP->actualCount].flags = flags;
2040     pDWP->actualCount++;
2041     retvalue = newhdwp;
2042 END:
2043     WIN_ReleaseWndPtr(pWnd);
2044     return retvalue;
2045 }
2046
2047
2048 /***********************************************************************
2049  *              EndDeferWindowPos (USER.261)
2050  */
2051 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2052 {
2053     return EndDeferWindowPos( hdwp );
2054 }
2055
2056
2057 /***********************************************************************
2058  *              EndDeferWindowPos (USER32.@)
2059  */
2060 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
2061 {
2062     DWP *pDWP;
2063     WINDOWPOS *winpos;
2064     BOOL res = TRUE;
2065     int i;
2066
2067     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2068     if (!pDWP) return FALSE;
2069     for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2070     {
2071         if (!(res = USER_Driver.pSetWindowPos( winpos ))) break;
2072     }
2073     USER_HEAP_FREE( hdwp );
2074     return res;
2075 }
2076
2077
2078 /***********************************************************************
2079  *              TileChildWindows (USER.199)
2080  */
2081 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
2082 {
2083     FIXME("(%04x, %d): stub\n", parent, action);
2084 }
2085
2086 /***********************************************************************
2087  *              CascadeChildWindows (USER.198)
2088  */
2089 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
2090 {
2091     FIXME("(%04x, %d): stub\n", parent, action);
2092 }
2093
2094 /***********************************************************************
2095  *              SetProgmanWindow (USER32.@)
2096  */
2097 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
2098 {
2099         hGlobalProgmanWindow = hwnd;
2100         return hGlobalProgmanWindow;
2101 }
2102
2103 /***********************************************************************
2104  *              GetProgmanWindow (USER32.@)
2105  */
2106 HRESULT WINAPI GetProgmanWindow ( )
2107 {
2108         return hGlobalProgmanWindow;
2109 }
2110
2111 /***********************************************************************
2112  *              SetShellWindowEx (USER32.@)
2113  * hwndProgman =  Progman[Program Manager]
2114  *                |-> SHELLDLL_DefView
2115  * hwndListView = |   |-> SysListView32
2116  *                |   |   |-> tooltips_class32
2117  *                |   |
2118  *                |   |-> SysHeader32
2119  *                |   
2120  *                |-> ProxyTarget
2121  */
2122 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
2123 {
2124         FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
2125         hGlobalShellWindow = hwndProgman;
2126         return hGlobalShellWindow;
2127
2128 }
2129
2130 /***********************************************************************
2131  *              SetTaskmanWindow (USER32.@)
2132  * NOTES
2133  *   hwnd = MSTaskSwWClass 
2134  *          |-> SysTabControl32
2135  */
2136 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
2137 {
2138         hGlobalTaskmanWindow = hwnd;
2139         return hGlobalTaskmanWindow;
2140 }
2141
2142 /***********************************************************************
2143  *              GetTaskmanWindow (USER32.@)
2144  */
2145 HRESULT WINAPI GetTaskmanWindow ( )
2146 {       
2147         return hGlobalTaskmanWindow;
2148 }