Update shell xxxAW wrapper prototypes for fixed SHLWAPI functions.
[wine] / dlls / ttydrv / wnd.c
1 /*
2  * TTY window driver
3  *
4  * Copyright 1998,1999 Patrik Stridvall
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include "gdi.h"
24 #include "ttydrv.h"
25 #include "region.h"
26 #include "win.h"
27 #include "winpos.h"
28 #include "wine/debug.h"
29 #include "hook.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(ttydrv);
32
33 #define SWP_AGG_NOGEOMETRYCHANGE \
34     (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
35 #define SWP_AGG_NOPOSCHANGE \
36     (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
37 #define SWP_AGG_STATUSFLAGS \
38     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
39
40 /**********************************************************************
41  *              CreateWindow   (TTYDRV.@)
42  */
43 BOOL TTYDRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
44 {
45     BOOL ret;
46     HWND hwndLinkAfter;
47
48 #ifdef WINE_CURSES
49     WND *wndPtr = WIN_FindWndPtr( hwnd );
50     WINDOW *window;
51     INT cellWidth=8, cellHeight=8; /* FIXME: Hardcoded */
52
53     TRACE("(%x)\n", hwnd);
54
55     /* Only create top-level windows */
56     if (!(wndPtr->dwStyle & WS_CHILD))
57     {
58         if (!wndPtr->parent)  /* desktop */
59             window = root_window;
60         else
61         {
62             int x = wndPtr->rectWindow.left;
63             int y = wndPtr->rectWindow.top;
64             int cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
65             int cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
66
67             window = subwin( root_window, cy/cellHeight, cx/cellWidth,
68                              y/cellHeight, x/cellWidth);
69             werase(window);
70             wrefresh(window);
71         }
72         wndPtr->pDriverData = window;
73     }
74     WIN_ReleaseWndPtr( wndPtr );
75 #else /* defined(WINE_CURSES) */
76     FIXME("(%x): stub\n", hwnd);
77 #endif /* defined(WINE_CURSES) */
78
79     /* Call the WH_CBT hook */
80
81     hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
82  ? HWND_BOTTOM : HWND_TOP;
83
84     if (HOOK_IsHooked( WH_CBT ))
85     {
86         CBT_CREATEWNDA cbtc;
87         LRESULT lret;
88
89         cbtc.lpcs = cs;
90         cbtc.hwndInsertAfter = hwndLinkAfter;
91         lret = (unicode) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND,
92                                                        (WPARAM)hwnd, (LPARAM)&cbtc)
93                         : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND,
94                                                        (WPARAM)hwnd, (LPARAM)&cbtc);
95         if (lret)
96         {
97             TRACE("CBT-hook returned !0\n");
98             return FALSE;
99         } 
100     }
101
102     if (unicode)
103     {
104         ret = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
105         if (ret) ret = (SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
106     }
107     else
108     {
109         ret = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
110         if (ret) ret = (SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
111     }
112     return ret;
113 }
114
115 /***********************************************************************
116  *              DestroyWindow   (TTYDRV.@)
117  */
118 BOOL TTYDRV_DestroyWindow( HWND hwnd )
119 {
120 #ifdef WINE_CURSES
121     WND *wndPtr = WIN_FindWndPtr( hwnd );
122     WINDOW *window = wndPtr->pDriverData;
123
124     TRACE("(%x)\n", hwnd);
125
126     if (window && window != root_window) delwin(window);
127     wndPtr->pDriverData = NULL;
128     WIN_ReleaseWndPtr( wndPtr );
129 #else /* defined(WINE_CURSES) */
130     FIXME("(%x): stub\n", hwnd);
131 #endif /* defined(WINE_CURSES) */
132     return TRUE;
133 }
134
135
136 /***********************************************************************
137  *           DCE_OffsetVisRgn
138  *
139  * Change region from DC-origin relative coordinates to screen coords.
140  */
141
142 static void DCE_OffsetVisRgn( HDC hDC, HRGN hVisRgn )
143 {
144     DC *dc;
145     if (!(dc = DC_GetDCPtr( hDC ))) return;
146
147     OffsetRgn( hVisRgn, dc->DCOrgX, dc->DCOrgY );
148
149     GDI_ReleaseObj( hDC );
150 }
151
152
153 /***********************************************************************
154  *           DCE_GetVisRect
155  *
156  * Calculate the visible rectangle of a window (i.e. the client or
157  * window area clipped by the client area of all ancestors) in the
158  * corresponding coordinates. Return FALSE if the visible region is empty.
159  */
160 static BOOL DCE_GetVisRect( WND *wndPtr, BOOL clientArea, RECT *lprect )
161 {
162     *lprect = clientArea ? wndPtr->rectClient : wndPtr->rectWindow;
163
164     if (wndPtr->dwStyle & WS_VISIBLE)
165     {
166         INT xoffset = lprect->left;
167         INT yoffset = lprect->top;
168
169         while ((wndPtr = WIN_FindWndPtr( GetAncestor(wndPtr->hwndSelf,GA_PARENT) )))
170         {
171             if ( (wndPtr->dwStyle & (WS_ICONIC | WS_VISIBLE)) != WS_VISIBLE )
172             {
173                 WIN_ReleaseWndPtr(wndPtr);
174                 goto fail;
175             }
176
177             xoffset += wndPtr->rectClient.left;
178             yoffset += wndPtr->rectClient.top;
179             OffsetRect( lprect, wndPtr->rectClient.left,
180                         wndPtr->rectClient.top );
181
182             if( (wndPtr->rectClient.left >= wndPtr->rectClient.right) ||
183                 (wndPtr->rectClient.top >= wndPtr->rectClient.bottom) ||
184                 (lprect->left >= wndPtr->rectClient.right) ||
185                 (lprect->right <= wndPtr->rectClient.left) ||
186                 (lprect->top >= wndPtr->rectClient.bottom) ||
187                 (lprect->bottom <= wndPtr->rectClient.top) )
188             {
189                 WIN_ReleaseWndPtr(wndPtr);
190                 goto fail;
191             }
192
193             lprect->left = max( lprect->left, wndPtr->rectClient.left );
194             lprect->right = min( lprect->right, wndPtr->rectClient.right );
195             lprect->top = max( lprect->top, wndPtr->rectClient.top );
196             lprect->bottom = min( lprect->bottom, wndPtr->rectClient.bottom );
197
198             WIN_ReleaseWndPtr(wndPtr);
199         }
200         OffsetRect( lprect, -xoffset, -yoffset );
201         return TRUE;
202     }
203
204 fail:
205     SetRectEmpty( lprect );
206     return FALSE;
207 }
208
209
210 /***********************************************************************
211  *           DCE_AddClipRects
212  *
213  * Go through the linked list of windows from pWndStart to pWndEnd,
214  * adding to the clip region the intersection of the target rectangle
215  * with an offset window rectangle.
216  */
217 static void DCE_AddClipRects( HWND parent, HWND end, HRGN hrgnClip, LPRECT lpRect, int x, int y )
218 {
219     RECT rect;
220     WND *pWnd;
221     int i;
222     HWND *list = WIN_ListChildren( parent );
223
224     if (!list) return;
225     for (i = 0; list[i]; i++)
226     {
227         if (list[i] == end) break;
228         if (!(pWnd = WIN_FindWndPtr( list[i] ))) continue;
229         if (pWnd->dwStyle & WS_VISIBLE)
230         {
231             rect.left = pWnd->rectWindow.left + x;
232             rect.top = pWnd->rectWindow.top + y;
233             rect.right = pWnd->rectWindow.right + x;
234             rect.bottom = pWnd->rectWindow.bottom + y;
235             if( IntersectRect( &rect, &rect, lpRect ))
236             {
237                 if(!REGION_UnionRectWithRgn( hrgnClip, &rect ))
238                 {
239                     WIN_ReleaseWndPtr( pWnd );
240                     break;
241                 }
242             }
243         }
244         WIN_ReleaseWndPtr( pWnd );
245     }
246     HeapFree( GetProcessHeap(), 0, list );
247 }
248
249
250 /***********************************************************************
251  *           DCE_GetVisRgn
252  *
253  * Return the visible region of a window, i.e. the client or window area
254  * clipped by the client area of all ancestors, and then optionally
255  * by siblings and children.
256  */
257 static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
258 {
259     HRGN hrgnVis = 0;
260     RECT rect;
261     WND *wndPtr = WIN_FindWndPtr( hwnd );
262     WND *childWnd = WIN_FindWndPtr( hwndChild );
263
264     /* Get visible rectangle and create a region with it. */
265
266     if (wndPtr && DCE_GetVisRect(wndPtr, !(flags & DCX_WINDOW), &rect))
267     {
268         if((hrgnVis = CreateRectRgnIndirect( &rect )))
269         {
270             HRGN hrgnClip = CreateRectRgn( 0, 0, 0, 0 );
271             INT xoffset, yoffset;
272
273             if( hrgnClip )
274             {
275                 /* Compute obscured region for the visible rectangle by 
276                  * clipping children, siblings, and ancestors. Note that
277                  * DCE_GetVisRect() returns a rectangle either in client
278                  * or in window coordinates (for DCX_WINDOW request). */
279
280                 if (flags & DCX_CLIPCHILDREN)
281                 {
282                     if( flags & DCX_WINDOW )
283                     {
284                         /* adjust offsets since child window rectangles are 
285                          * in client coordinates */
286
287                         xoffset = wndPtr->rectClient.left - wndPtr->rectWindow.left;
288                         yoffset = wndPtr->rectClient.top - wndPtr->rectWindow.top;
289                     }
290                     else
291                         xoffset = yoffset = 0;
292
293                     DCE_AddClipRects( wndPtr->hwndSelf, 0, hrgnClip, &rect, xoffset, yoffset );
294                 }
295
296                 /* We may need to clip children of child window, if a window with PARENTDC
297                  * class style and CLIPCHILDREN window style (like in Free Agent 16
298                  * preference dialogs) gets here, we take the region for the parent window
299                  * but apparently still need to clip the children of the child window... */
300
301                 if( (cflags & DCX_CLIPCHILDREN) && childWnd)
302                 {
303                     if( flags & DCX_WINDOW )
304                     {
305                         /* adjust offsets since child window rectangles are 
306                          * in client coordinates */
307
308                         xoffset = wndPtr->rectClient.left - wndPtr->rectWindow.left;
309                         yoffset = wndPtr->rectClient.top - wndPtr->rectWindow.top;
310                     }
311                     else
312                         xoffset = yoffset = 0;
313
314                     /* client coordinates of child window */
315                     xoffset += childWnd->rectClient.left;
316                     yoffset += childWnd->rectClient.top;
317
318                     DCE_AddClipRects( childWnd->hwndSelf, 0, hrgnClip,
319                                       &rect, xoffset, yoffset );
320                 }
321
322                 /* sibling window rectangles are in client 
323                  * coordinates of the parent window */
324
325                 if (flags & DCX_WINDOW)
326                 {
327                     xoffset = -wndPtr->rectWindow.left;
328                     yoffset = -wndPtr->rectWindow.top;
329                 }
330                 else
331                 {
332                     xoffset = -wndPtr->rectClient.left;
333                     yoffset = -wndPtr->rectClient.top;
334                 }
335
336                 if (flags & DCX_CLIPSIBLINGS && wndPtr->parent )
337                     DCE_AddClipRects( wndPtr->parent, wndPtr->hwndSelf,
338                                       hrgnClip, &rect, xoffset, yoffset );
339
340                 /* Clip siblings of all ancestors that have the
341                  * WS_CLIPSIBLINGS style
342                  */
343
344                 while (wndPtr->parent)
345                 {
346                     WND *ptr = WIN_FindWndPtr( wndPtr->parent );
347                     WIN_ReleaseWndPtr( wndPtr );
348                     wndPtr = ptr;
349                     xoffset -= wndPtr->rectClient.left;
350                     yoffset -= wndPtr->rectClient.top;
351                     if(wndPtr->dwStyle & WS_CLIPSIBLINGS && wndPtr->parent)
352                     {
353                         DCE_AddClipRects( wndPtr->parent, wndPtr->hwndSelf,
354                                           hrgnClip, &rect, xoffset, yoffset );
355                     }
356                 }
357
358                 /* Now once we've got a jumbo clip region we have
359                  * to substract it from the visible rectangle.
360                  */
361                 CombineRgn( hrgnVis, hrgnVis, hrgnClip, RGN_DIFF );
362                 DeleteObject( hrgnClip );
363             }
364             else
365             {
366                 DeleteObject( hrgnVis );
367                 hrgnVis = 0;
368             }
369         }
370     }
371     else
372         hrgnVis = CreateRectRgn(0, 0, 0, 0); /* empty */
373     WIN_ReleaseWndPtr(wndPtr);
374     WIN_ReleaseWndPtr(childWnd);
375     return hrgnVis;
376 }
377
378
379 /***********************************************************************
380  *              GetDC   (TTYDRV.@)
381  *
382  * Set the drawable, origin and dimensions for the DC associated to
383  * a given window.
384  */
385 BOOL TTYDRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
386 {
387     WND *wndPtr = WIN_FindWndPtr(hwnd);
388     DC *dc;
389     BOOL updateVisRgn;
390     HRGN hrgnVisible = 0;
391
392     if (!wndPtr) return FALSE;
393
394     if (!(dc = DC_GetDCPtr( hdc )))
395     {
396         WIN_ReleaseWndPtr( wndPtr );
397         return FALSE;
398     }
399
400     if(flags & DCX_WINDOW)
401     {
402         dc->DCOrgX = wndPtr->rectWindow.left;
403         dc->DCOrgY = wndPtr->rectWindow.top;
404     }
405     else
406     {
407         dc->DCOrgX = wndPtr->rectClient.left;
408         dc->DCOrgY = wndPtr->rectClient.top;
409     }
410     updateVisRgn = (dc->flags & DC_DIRTY) != 0;
411     GDI_ReleaseObj( hdc );
412
413     if (updateVisRgn)
414     {
415         if (flags & DCX_PARENTCLIP)
416         {
417             WND *parentPtr = WIN_FindWndPtr( wndPtr->parent );
418
419             if( wndPtr->dwStyle & WS_VISIBLE && !(parentPtr->dwStyle & WS_MINIMIZE) )
420             {
421                 DWORD dcxFlags;
422
423                 if( parentPtr->dwStyle & WS_CLIPSIBLINGS )
424                     dcxFlags = DCX_CLIPSIBLINGS | (flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW));
425                 else
426                     dcxFlags = flags & ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW);
427
428                 hrgnVisible = DCE_GetVisRgn( parentPtr->hwndSelf, dcxFlags,
429                                              wndPtr->hwndSelf, flags );
430                 if( flags & DCX_WINDOW )
431                     OffsetRgn( hrgnVisible, -wndPtr->rectWindow.left,
432                                -wndPtr->rectWindow.top );
433                 else
434                     OffsetRgn( hrgnVisible, -wndPtr->rectClient.left,
435                                -wndPtr->rectClient.top );
436                 DCE_OffsetVisRgn( hdc, hrgnVisible );
437             }
438             else
439                 hrgnVisible = CreateRectRgn( 0, 0, 0, 0 );
440             WIN_ReleaseWndPtr(parentPtr);
441         }
442         else
443         {
444             hrgnVisible = DCE_GetVisRgn( hwnd, flags, 0, 0 );
445             DCE_OffsetVisRgn( hdc, hrgnVisible );
446         }
447         SelectVisRgn16( hdc, hrgnVisible );
448     }
449
450     /* apply additional region operation (if any) */
451
452     if( flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN) )
453     {
454         if( !hrgnVisible ) hrgnVisible = CreateRectRgn( 0, 0, 0, 0 );
455
456         TRACE("\tsaved VisRgn, clipRgn = %04x\n", hrgn);
457
458         SaveVisRgn16( hdc );
459         CombineRgn( hrgnVisible, hrgn, 0, RGN_COPY );
460         DCE_OffsetVisRgn( hdc, hrgnVisible );
461         CombineRgn( hrgnVisible, InquireVisRgn16( hdc ), hrgnVisible,
462                       (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
463         SelectVisRgn16( hdc, hrgnVisible );
464     }
465
466     if (hrgnVisible) DeleteObject( hrgnVisible );
467
468     WIN_ReleaseWndPtr( wndPtr );
469     return TRUE;
470 }
471
472
473 /***********************************************************************
474  *              SetWindowPos   (TTYDRV.@)
475  */
476 BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos )
477 {
478     WND *wndPtr;
479     RECT newWindowRect, newClientRect;
480     BOOL retvalue;
481     HWND hwndActive = GetForegroundWindow();
482
483     TRACE( "hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
484            winpos->hwnd, winpos->x, winpos->y,
485            winpos->x + winpos->cx, winpos->y + winpos->cy, winpos->flags);
486
487     /* ------------------------------------------------------------------------ CHECKS */
488
489       /* Check window handle */
490
491     if (winpos->hwnd == GetDesktopWindow()) return FALSE;
492     if (!(wndPtr = WIN_FindWndPtr( winpos->hwnd ))) return FALSE;
493
494     TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n",
495           wndPtr->rectWindow.left, wndPtr->rectWindow.top,
496           wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
497
498     /* Fix redundant flags */
499
500     if(wndPtr->dwStyle & WS_VISIBLE)
501         winpos->flags &= ~SWP_SHOWWINDOW;
502     else
503     {
504         if (!(winpos->flags & SWP_SHOWWINDOW)) winpos->flags |= SWP_NOREDRAW;
505         winpos->flags &= ~SWP_HIDEWINDOW;
506     }
507
508     if ( winpos->cx < 0 ) winpos->cx = 0;
509     if ( winpos->cy < 0 ) winpos->cy = 0;
510
511     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == winpos->cx) &&
512         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == winpos->cy))
513         winpos->flags |= SWP_NOSIZE;    /* Already the right size */
514
515     if ((wndPtr->rectWindow.left == winpos->x) && (wndPtr->rectWindow.top == winpos->y))
516         winpos->flags |= SWP_NOMOVE;    /* Already the right position */
517
518     if (winpos->hwnd == hwndActive)
519         winpos->flags |= SWP_NOACTIVATE;   /* Already active */
520     else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
521     {
522         if(!(winpos->flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
523         {
524             winpos->flags &= ~SWP_NOZORDER;
525             winpos->hwndInsertAfter = HWND_TOP;
526             goto Pos;
527         }
528     }
529
530     /* Check hwndInsertAfter */
531
532       /* FIXME: TOPMOST not supported yet */
533     if ((winpos->hwndInsertAfter == HWND_TOPMOST) ||
534         (winpos->hwndInsertAfter == HWND_NOTOPMOST)) winpos->hwndInsertAfter = HWND_TOP;
535
536     /* hwndInsertAfter must be a sibling of the window */
537     if ((winpos->hwndInsertAfter != HWND_TOP) && (winpos->hwndInsertAfter != HWND_BOTTOM))
538     {
539         WND* wnd = WIN_FindWndPtr(winpos->hwndInsertAfter);
540
541         if( wnd ) {
542             if( wnd->parent != wndPtr->parent )
543             {
544                 retvalue = FALSE;
545                 WIN_ReleaseWndPtr(wnd);
546                 goto END;
547             }
548             /* don't need to change the Zorder of hwnd if it's already inserted
549              * after hwndInsertAfter or when inserting hwnd after itself.
550              */
551             if ((winpos->hwnd == winpos->hwndInsertAfter) ||
552                 (winpos->hwnd == GetWindow( winpos->hwndInsertAfter, GW_HWNDNEXT )))
553                 winpos->flags |= SWP_NOZORDER;
554         }
555         WIN_ReleaseWndPtr(wnd);
556     }
557
558  Pos:  /* ------------------------------------------------------------------------ MAIN part */
559
560       /* Send WM_WINDOWPOSCHANGING message */
561
562     if (!(winpos->flags & SWP_NOSENDCHANGING))
563         SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)winpos );
564
565       /* Calculate new position and size */
566
567     newWindowRect = wndPtr->rectWindow;
568     newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
569                                                     : wndPtr->rectClient;
570
571     if (!(winpos->flags & SWP_NOSIZE))
572     {
573         newWindowRect.right  = newWindowRect.left + winpos->cx;
574         newWindowRect.bottom = newWindowRect.top + winpos->cy;
575     }
576     if (!(winpos->flags & SWP_NOMOVE))
577     {
578         newWindowRect.left    = winpos->x;
579         newWindowRect.top     = winpos->y;
580         newWindowRect.right  += winpos->x - wndPtr->rectWindow.left;
581         newWindowRect.bottom += winpos->y - wndPtr->rectWindow.top;
582
583         OffsetRect( &newClientRect, winpos->x - wndPtr->rectWindow.left,
584                     winpos->y - wndPtr->rectWindow.top );
585     }
586
587     if( winpos->hwndInsertAfter == HWND_TOP )
588     {
589         if (GetWindow( wndPtr->hwndSelf, GW_HWNDFIRST ) == wndPtr->hwndSelf)
590             winpos->flags |= SWP_NOZORDER;
591     }
592     else
593         if( winpos->hwndInsertAfter == HWND_BOTTOM )
594         {
595             if (!GetWindow( wndPtr->hwndSelf, GW_HWNDNEXT ))
596                 winpos->flags |= SWP_NOZORDER;
597         }
598         else
599             if( !(winpos->flags & SWP_NOZORDER) )
600                 if( GetWindow(winpos->hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
601                     winpos->flags |= SWP_NOZORDER;
602
603     /* Common operations */
604
605       /* Send WM_NCCALCSIZE message to get new client area */
606     if( (winpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
607     {
608         NCCALCSIZE_PARAMS params;
609         WINDOWPOS winposCopy;
610
611         params.rgrc[0] = newWindowRect;
612         params.rgrc[1] = wndPtr->rectWindow;
613         params.rgrc[2] = wndPtr->rectClient;
614         params.lppos = &winposCopy;
615         winposCopy = *winpos;
616
617         SendMessageW( winpos->hwnd, WM_NCCALCSIZE, TRUE, (LPARAM)&params );
618
619         TRACE( "%d,%d-%d,%d\n", params.rgrc[0].left, params.rgrc[0].top,
620                params.rgrc[0].right, params.rgrc[0].bottom );
621
622         /* If the application send back garbage, ignore it */
623         if (params.rgrc[0].left <= params.rgrc[0].right &&
624             params.rgrc[0].top <= params.rgrc[0].bottom)
625             newClientRect = params.rgrc[0];
626
627          /* FIXME: WVR_ALIGNxxx */
628
629         if( newClientRect.left != wndPtr->rectClient.left ||
630             newClientRect.top != wndPtr->rectClient.top )
631             winpos->flags &= ~SWP_NOCLIENTMOVE;
632
633         if( (newClientRect.right - newClientRect.left !=
634              wndPtr->rectClient.right - wndPtr->rectClient.left) ||
635             (newClientRect.bottom - newClientRect.top !=
636              wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
637             winpos->flags &= ~SWP_NOCLIENTSIZE;
638     }
639
640     if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter)
641     {
642         HWND parent = GetAncestor( winpos->hwnd, GA_PARENT );
643         if (parent) WIN_LinkWindow( winpos->hwnd, parent, winpos->hwndInsertAfter );
644     }
645
646     /* FIXME: actually do something with WVR_VALIDRECTS */
647
648     WIN_SetRectangles( winpos->hwnd, &newWindowRect, &newClientRect );
649
650     if( winpos->flags & SWP_SHOWWINDOW )
651         WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle | WS_VISIBLE );
652     else if( winpos->flags & SWP_HIDEWINDOW )
653         WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
654
655     /* ------------------------------------------------------------------------ FINAL */
656
657     /* repaint invalidated region (if any)
658      *
659      * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
660      *        and force update after ChangeActiveWindow() to avoid painting frames twice.
661      */
662
663     if( !(winpos->flags & SWP_NOREDRAW) )
664     {
665         RedrawWindow( wndPtr->parent, NULL, 0,
666                       RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN );
667         if (wndPtr->parent == GetDesktopWindow())
668             RedrawWindow( wndPtr->parent, NULL, 0,
669                           RDW_ERASENOW | RDW_NOCHILDREN );
670     }
671
672     if (!(winpos->flags & SWP_NOACTIVATE)) SetActiveWindow( winpos->hwnd );
673
674       /* And last, send the WM_WINDOWPOSCHANGED message */
675
676     TRACE("\tstatus flags = %04x\n", winpos->flags & SWP_AGG_STATUSFLAGS);
677
678     if ((((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
679           !(winpos->flags & SWP_NOSENDCHANGING)) )
680         SendMessageA( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)winpos );
681
682     retvalue = TRUE;
683  END:
684     WIN_ReleaseWndPtr(wndPtr);
685     return retvalue;
686 }
687
688
689 /***********************************************************************
690  *              WINPOS_MinMaximize   (internal)
691  *
692  *Lifted from x11 driver        
693  */
694 static UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
695 {
696     WND *wndPtr;
697     UINT swpFlags = 0;
698     WINDOWPLACEMENT wpl;
699
700     TRACE("0x%04x %u\n", hwnd, cmd );
701     FIXME("(%x): stub\n", hwnd);
702
703     wpl.length = sizeof(wpl);
704     GetWindowPlacement( hwnd, &wpl );
705
706     /* If I glark this right, yields an immutable window*/
707     swpFlags = SWP_NOSIZE | SWP_NOMOVE;
708
709     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
710
711     /*cmd handling goes here.  see dlls/x1drv/winpos.c*/
712
713     WIN_ReleaseWndPtr( wndPtr );
714     return swpFlags;
715 }
716
717 /***********************************************************************
718  *              ShowWindow   (TTYDRV.@)
719  *
720  *Lifted from x11 driver
721  *Sets the specified windows' show state.       
722  */
723 BOOL TTYDRV_ShowWindow( HWND hwnd, INT cmd )
724 {
725     WND*        wndPtr = WIN_FindWndPtr( hwnd );
726     BOOL        wasVisible, showFlag;
727     RECT        newPos = {0, 0, 0, 0};
728     UINT        swp = 0;
729
730     if (!wndPtr) return FALSE;
731     hwnd = wndPtr->hwndSelf;  /* make it a full handle */
732
733     TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
734
735     wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
736
737     switch(cmd)
738     {
739         case SW_HIDE:
740             if (!wasVisible) goto END;;
741             swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
742                         SWP_NOACTIVATE | SWP_NOZORDER;
743             break;
744
745         case SW_SHOWMINNOACTIVE:
746             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
747             /* fall through */
748         case SW_SHOWMINIMIZED:
749             swp |= SWP_SHOWWINDOW;
750             /* fall through */
751         case SW_MINIMIZE:
752             swp |= SWP_FRAMECHANGED;
753             if( !(wndPtr->dwStyle & WS_MINIMIZE) )
754                  swp |= WINPOS_MinMaximize( hwnd, SW_MINIMIZE, &newPos );
755             else swp |= SWP_NOSIZE | SWP_NOMOVE;
756             break;
757
758         case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
759             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
760             if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
761                  swp |= WINPOS_MinMaximize( hwnd, SW_MAXIMIZE, &newPos );
762             else swp |= SWP_NOSIZE | SWP_NOMOVE;
763             break;
764
765         case SW_SHOWNA:
766             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
767             /* fall through */
768         case SW_SHOW:
769             swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
770
771             /*
772              * ShowWindow has a little peculiar behavior that if the
773              * window is already the topmost window, it will not
774              * activate it.
775              */
776             if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
777               swp |= SWP_NOACTIVATE;
778
779             break;
780
781         case SW_SHOWNOACTIVATE:
782             swp |= SWP_NOZORDER;
783             if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
784             /* fall through */
785         case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
786         case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
787         case SW_RESTORE:
788             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
789
790             if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
791                  swp |= WINPOS_MinMaximize( hwnd, SW_RESTORE, &newPos );
792             else swp |= SWP_NOSIZE | SWP_NOMOVE;
793             break;
794     }
795
796     showFlag = (cmd != SW_HIDE);
797     if (showFlag != wasVisible)
798     {
799         SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
800         if (!IsWindow( hwnd )) goto END;
801     }
802
803     /* We can't activate a child window */
804     if ((wndPtr->dwStyle & WS_CHILD) &&
805         !(wndPtr->dwExStyle & WS_EX_MDICHILD))
806         swp |= SWP_NOACTIVATE | SWP_NOZORDER;
807
808     SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
809                   newPos.right, newPos.bottom, LOWORD(swp) );
810     if (cmd == SW_HIDE)
811     {
812         /* FIXME: This will cause the window to be activated irrespective
813          * of whether it is owned by the same thread. Has to be done
814          * asynchronously.
815          */
816
817         if (hwnd == GetActiveWindow())
818             WINPOS_ActivateOtherWindow(hwnd);
819
820         /* Revert focus to parent */
821         if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
822             SetFocus( GetParent(hwnd) );
823     }
824     if (!IsWindow( hwnd )) goto END;
825     else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( hwnd, TRUE );
826
827     if (wndPtr->flags & WIN_NEED_SIZE)
828     {
829         /* should happen only in CreateWindowEx() */
830         int wParam = SIZE_RESTORED;
831
832         wndPtr->flags &= ~WIN_NEED_SIZE;
833         if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
834         else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
835         SendMessageA( hwnd, WM_SIZE, wParam,
836                      MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
837                             wndPtr->rectClient.bottom-wndPtr->rectClient.top));
838         SendMessageA( hwnd, WM_MOVE, 0,
839                    MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
840     }
841
842 END:
843     WIN_ReleaseWndPtr(wndPtr);
844     return wasVisible;
845 }