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