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