2 * Scroll windows and DCs
4 * Copyright David W. Metcalfe, 1993
5 * Alex Korobka 1995,1996
14 #include "wine/winuser16.h"
21 #include "debugtools.h"
23 DEFAULT_DEBUG_CHANNEL(scroll
)
25 /*************************************************************************
26 * ScrollWindow16 (USER.61)
28 void WINAPI
ScrollWindow16(HWND16 hwnd
, INT16 dx
, INT16 dy
, const RECT16
*rect
,
29 const RECT16
*clipRect
)
31 RECT rect32
, clipRect32
;
33 if (rect
) CONV_RECT16TO32( rect
, &rect32
);
34 if (clipRect
) CONV_RECT16TO32( clipRect
, &clipRect32
);
35 ScrollWindow( hwnd
, dx
, dy
, rect
? &rect32
: NULL
,
36 clipRect
? &clipRect32
: NULL
);
39 /*************************************************************************
40 * ScrollWindow (USER32.450)
43 BOOL WINAPI
ScrollWindow( HWND hwnd
, INT dx
, INT dy
,
44 const RECT
*rect
, const RECT
*clipRect
)
47 (ERROR
!= ScrollWindowEx( hwnd
, dx
, dy
, rect
, clipRect
, 0, NULL
,
48 (rect
? 0 : SW_SCROLLCHILDREN
) |
52 /*************************************************************************
53 * ScrollDC16 (USER.221)
55 BOOL16 WINAPI
ScrollDC16( HDC16 hdc
, INT16 dx
, INT16 dy
, const RECT16
*rect
,
56 const RECT16
*cliprc
, HRGN16 hrgnUpdate
,
59 RECT rect32
, clipRect32
, rcUpdate32
;
62 if (rect
) CONV_RECT16TO32( rect
, &rect32
);
63 if (cliprc
) CONV_RECT16TO32( cliprc
, &clipRect32
);
64 ret
= ScrollDC( hdc
, dx
, dy
, rect
? &rect32
: NULL
,
65 cliprc
? &clipRect32
: NULL
, hrgnUpdate
, &rcUpdate32
);
66 if (rcUpdate
) CONV_RECT32TO16( &rcUpdate32
, rcUpdate
);
71 /*************************************************************************
72 * ScrollDC (USER32.449)
74 * Only the hrgnUpdate is return in device coordinate.
75 * rcUpdate must be returned in logical coordinate to comply with win API.
78 BOOL WINAPI
ScrollDC( HDC hdc
, INT dx
, INT dy
, const RECT
*rc
,
79 const RECT
*prLClip
, HRGN hrgnUpdate
,
82 RECT rect
, rClip
, rSrc
;
84 DC
*dc
= (DC
*)GDI_GetObjPtr(hdc
, DC_MAGIC
);
86 TRACE("%04x %d,%d hrgnUpdate=%04x rcUpdate = %p cliprc = (%d,%d-%d,%d), rc=(%d,%d-%d,%d)\n",
87 (HDC16
)hdc
, dx
, dy
, hrgnUpdate
, rcUpdate
,
88 prLClip
? prLClip
->left
: 0, prLClip
? prLClip
->top
: 0, prLClip
? prLClip
->right
: 0, prLClip
? prLClip
->bottom
: 0,
89 rc
? rc
->left
: 0, rc
? rc
->top
: 0, rc
? rc
->right
: 0, rc
? rc
->bottom
: 0 );
91 if ( !dc
|| !hdc
) return FALSE
;
94 TRACE(scroll,"\t[wndOrgX=%i, wndExtX=%i, vportOrgX=%i, vportExtX=%i]\n",
95 dc->wndOrgX, dc->wndExtX, dc->vportOrgX, dc->vportExtX );
96 TRACE(scroll,"\t[wndOrgY=%i, wndExtY=%i, vportOrgY=%i, vportExtY=%i]\n",
97 dc->wndOrgY, dc->wndExtY, dc->vportOrgY, dc->vportExtY );
100 /* compute device clipping region */
104 else /* maybe we should just return FALSE? */
105 GetClipBox( hdc
, &rect
);
108 IntersectRect( &rClip
,&rect
,prLClip
);
113 OffsetRect( &rSrc
, -dx
, -dy
);
114 IntersectRect( &rSrc
, &rSrc
, &rect
);
118 if (!IsRectEmpty(&rSrc
))
120 dest
.x
= (src
.x
= rSrc
.left
) + dx
;
121 dest
.y
= (src
.y
= rSrc
.top
) + dy
;
125 if (!BitBlt( hdc
, dest
.x
, dest
.y
,
126 rSrc
.right
- rSrc
.left
, rSrc
.bottom
- rSrc
.top
,
127 hdc
, src
.x
, src
.y
, SRCCOPY
))
129 GDI_HEAP_UNLOCK( hdc
);
134 /* compute update areas */
136 if (hrgnUpdate
|| rcUpdate
)
139 (hrgnUpdate
) ? hrgnUpdate
: CreateRectRgn( 0,0,0,0 );
142 dx
= XLPTODP ( dc
, rect
.left
+ dx
) - XLPTODP ( dc
, rect
.left
);
143 dy
= YLPTODP ( dc
, rect
.top
+ dy
) - YLPTODP ( dc
, rect
.top
);
144 LPtoDP( hdc
, (LPPOINT
)&rect
, 2 );
145 LPtoDP( hdc
, (LPPOINT
)&rClip
, 2 );
146 hrgn2
= CreateRectRgnIndirect( &rect
);
147 OffsetRgn( hrgn2
, dc
->w
.DCOrgX
, dc
->w
.DCOrgY
);
148 CombineRgn( hrgn2
, hrgn2
, dc
->w
.hVisRgn
, RGN_AND
);
149 OffsetRgn( hrgn2
, -dc
->w
.DCOrgX
, -dc
->w
.DCOrgY
);
150 SetRectRgn( hrgn
, rClip
.left
, rClip
.top
,
151 rClip
.right
, rClip
.bottom
);
152 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_AND
);
153 OffsetRgn( hrgn2
, dx
, dy
);
154 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_DIFF
);
158 GetRgnBox( hrgn
, rcUpdate
);
160 /* Put the rcUpdate in logical coordinate */
161 DPtoLP( hdc
, (LPPOINT
)rcUpdate
, 2 );
163 if (!hrgnUpdate
) DeleteObject( hrgn
);
164 DeleteObject( hrgn2
);
170 if (hrgnUpdate
) SetRectRgn(hrgnUpdate
, 0, 0, 0, 0);
171 if (rcUpdate
) SetRectEmpty(rcUpdate
);
174 GDI_HEAP_UNLOCK( hdc
);
179 /*************************************************************************
180 * ScrollWindowEx16 (USER.319)
182 INT16 WINAPI
ScrollWindowEx16( HWND16 hwnd
, INT16 dx
, INT16 dy
,
183 const RECT16
*rect
, const RECT16
*clipRect
,
184 HRGN16 hrgnUpdate
, LPRECT16 rcUpdate
,
187 RECT rect32
, clipRect32
, rcUpdate32
;
190 if (rect
) CONV_RECT16TO32( rect
, &rect32
);
191 if (clipRect
) CONV_RECT16TO32( clipRect
, &clipRect32
);
192 ret
= ScrollWindowEx( hwnd
, dx
, dy
, rect
? &rect32
: NULL
,
193 clipRect
? &clipRect32
: NULL
, hrgnUpdate
,
194 (rcUpdate
) ? &rcUpdate32
: NULL
, flags
);
195 if (rcUpdate
) CONV_RECT32TO16( &rcUpdate32
, rcUpdate
);
199 /*************************************************************************
202 static BOOL
SCROLL_FixCaret(HWND hWnd
, LPRECT lprc
, UINT flags
)
204 HWND hCaret
= CARET_GetHwnd();
209 CARET_GetRect( &rc
);
210 if( hCaret
== hWnd
||
211 (flags
& SW_SCROLLCHILDREN
&& IsChild(hWnd
, hCaret
)) )
215 pt
.x
= rc
.left
; pt
.y
= rc
.top
;
216 MapWindowPoints( hCaret
, hWnd
, (LPPOINT
)&rc
, 2 );
217 if( IntersectRect(lprc
, lprc
, &rc
) )
220 lprc
->left
= pt
.x
; lprc
->top
= pt
.y
;
228 /*************************************************************************
229 * ScrollWindowEx (USER32.451)
231 * NOTE: Use this function instead of ScrollWindow32
233 INT WINAPI
ScrollWindowEx( HWND hwnd
, INT dx
, INT dy
,
234 const RECT
*rect
, const RECT
*clipRect
,
235 HRGN hrgnUpdate
, LPRECT rcUpdate
,
238 INT retVal
= NULLREGION
;
239 BOOL bCaret
= FALSE
, bOwnRgn
= TRUE
;
241 WND
* wnd
= WIN_FindWndPtr( hwnd
);
243 if( !wnd
|| !WIN_IsWindowDrawable( wnd
, TRUE
))
249 GetClientRect(hwnd
, &rc
);
250 if (rect
) IntersectRect(&rc
, &rc
, rect
);
252 if (clipRect
) IntersectRect(&cliprc
,&rc
,clipRect
);
255 if (!IsRectEmpty(&cliprc
) && (dx
|| dy
))
259 BOOL bUpdate
= (rcUpdate
|| hrgnUpdate
|| flags
& (SW_INVALIDATE
| SW_ERASE
));
260 HRGN hrgnClip
= CreateRectRgnIndirect(&cliprc
);
261 HRGN hrgnTemp
= CreateRectRgnIndirect(&rc
);
264 TRACE("%04x, %d,%d hrgnUpdate=%04x rcUpdate = %p \
265 cliprc = (%d,%d-%d,%d), rc=(%d,%d-%d,%d) %04x\n",
266 (HWND16
)hwnd
, dx
, dy
, hrgnUpdate
, rcUpdate
,
267 clipRect
?clipRect
->left
:0, clipRect
?clipRect
->top
:0, clipRect
?clipRect
->right
:0, clipRect
?clipRect
->bottom
:0,
268 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
, (UINT16
)flags
);
271 bCaret
= SCROLL_FixCaret(hwnd
, &caretrc
, flags
);
273 if( hrgnUpdate
) bOwnRgn
= FALSE
;
274 else if( bUpdate
) hrgnUpdate
= CreateRectRgn( 0, 0, 0, 0 );
276 hDC
= GetDCEx( hwnd
, hrgnClip
, DCX_CACHE
| DCX_USESTYLE
|
277 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
|
278 ((flags
& SW_SCROLLCHILDREN
) ? DCX_NOCLIPCHILDREN
: 0) );
279 if( (dc
= (DC
*)GDI_GetObjPtr(hDC
, DC_MAGIC
)) )
282 wnd
->pDriver
->pSurfaceCopy(wnd
,hDC
,dx
,dy
,&rc
,bUpdate
);
286 OffsetRgn( hrgnTemp
, dc
->w
.DCOrgX
, dc
->w
.DCOrgY
);
287 CombineRgn( hrgnTemp
, hrgnTemp
, dc
->w
.hVisRgn
,
289 OffsetRgn( hrgnTemp
, -dc
->w
.DCOrgX
, -dc
->w
.DCOrgY
);
290 CombineRgn( hrgnUpdate
, hrgnTemp
, hrgnClip
,
292 OffsetRgn( hrgnTemp
, dx
, dy
);
294 CombineRgn( hrgnUpdate
, hrgnUpdate
, hrgnTemp
,
297 if( rcUpdate
) GetRgnBox( hrgnUpdate
, rcUpdate
);
300 ReleaseDC(hwnd
, hDC
);
301 GDI_HEAP_UNLOCK( hDC
);
304 if( wnd
->hrgnUpdate
> 1 )
306 /* Takes into account the fact that some damages may have
307 occured during the scroll. */
308 CombineRgn( hrgnTemp
, wnd
->hrgnUpdate
, 0, RGN_COPY
);
309 OffsetRgn( hrgnTemp
, dx
, dy
);
310 CombineRgn( hrgnTemp
, hrgnTemp
, hrgnClip
, RGN_AND
);
311 CombineRgn( wnd
->hrgnUpdate
, wnd
->hrgnUpdate
, hrgnTemp
, RGN_OR
);
314 if( flags
& SW_SCROLLCHILDREN
)
318 for( w
=WIN_LockWndPtr(wnd
->child
); w
; WIN_UpdateWndPtr(&w
, w
->next
))
320 CONV_RECT16TO32( &w
->rectWindow
, &r
);
321 if( !rect
|| IntersectRect(&r
, &r
, &rc
) )
322 SetWindowPos(w
->hwndSelf
, 0, w
->rectWindow
.left
+ dx
,
323 w
->rectWindow
.top
+ dy
, 0,0, SWP_NOZORDER
|
324 SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOREDRAW
|
329 if( flags
& (SW_INVALIDATE
| SW_ERASE
) )
330 PAINT_RedrawWindow( hwnd
, NULL
, hrgnUpdate
, RDW_INVALIDATE
| RDW_ERASE
|
331 ((flags
& SW_ERASE
) ? RDW_ERASENOW
: 0) | ((flags
& SW_SCROLLCHILDREN
) ? RDW_ALLCHILDREN
: 0 ), 0 );
335 SetCaretPos( caretrc
.left
+ dx
, caretrc
.top
+ dy
);
339 if( bOwnRgn
&& hrgnUpdate
) DeleteObject( hrgnUpdate
);
340 DeleteObject( hrgnClip
);
341 DeleteObject( hrgnTemp
);
344 WIN_ReleaseWndPtr(wnd
);