2 * Scroll windows and DCs
4 * Copyright David W. Metcalfe, 1993
5 * Alex Korobka 1995,1996
18 #include "sysmetrics.h"
21 /*************************************************************************
22 * ScrollWindow16 (USER.61)
24 void WINAPI
ScrollWindow16(HWND16 hwnd
, INT16 dx
, INT16 dy
, const RECT16
*rect
,
25 const RECT16
*clipRect
)
27 RECT32 rect32
, clipRect32
;
29 if (rect
) CONV_RECT16TO32( rect
, &rect32
);
30 if (clipRect
) CONV_RECT16TO32( clipRect
, &clipRect32
);
31 ScrollWindow32( hwnd
, dx
, dy
, rect
? &rect32
: NULL
,
32 clipRect
? &clipRect32
: NULL
);
35 /*************************************************************************
36 * ScrollWindow32 (USER32.450)
38 * FIXME: verify clipping region calculations
40 BOOL32 WINAPI
ScrollWindow32( HWND32 hwnd
, INT32 dx
, INT32 dy
,
41 const RECT32
*rect
, const RECT32
*clipRect
)
44 HRGN32 hrgnUpdate
,hrgnClip
;
46 HWND32 hCaretWnd
= CARET_GetHwnd();
47 WND
* wndScroll
= WIN_FindWndPtr( hwnd
);
49 TRACE(scroll
,"hwnd=%04x, dx=%d, dy=%d, lpRect =%p clipRect=%i,%i,%i,%i\n",
51 clipRect
? clipRect
->left
: 0,
52 clipRect
? clipRect
->top
: 0,
53 clipRect
? clipRect
->right
: 0,
54 clipRect
? clipRect
->bottom
: 0 );
56 if ( !wndScroll
|| !WIN_IsWindowDrawable( wndScroll
, TRUE
) ) return TRUE
;
58 if ( !rect
) /* do not clip children */
60 GetClientRect32(hwnd
, &rc
);
61 hrgnClip
= CreateRectRgnIndirect32( &rc
);
63 if ((hCaretWnd
== hwnd
) || IsChild32(hwnd
,hCaretWnd
))
64 HideCaret32(hCaretWnd
);
67 hdc
= GetDCEx32(hwnd
, hrgnClip
, DCX_CACHE
| DCX_CLIPSIBLINGS
);
68 DeleteObject32( hrgnClip
);
70 else /* clip children */
72 CopyRect32(&rc
, rect
);
74 if (hCaretWnd
== hwnd
) HideCaret32(hCaretWnd
);
77 hdc
= GetDCEx32( hwnd
, 0, DCX_CACHE
| DCX_USESTYLE
);
81 GetClientRect32(hwnd
, &cliprc
);
83 CopyRect32(&cliprc
, clipRect
);
85 hrgnUpdate
= CreateRectRgn32( 0, 0, 0, 0 );
86 ScrollDC32( hdc
, dx
, dy
, &rc
, &cliprc
, hrgnUpdate
, NULL
);
87 ReleaseDC32(hwnd
, hdc
);
89 if( !rect
) /* move child windows and update region */
93 if( wndScroll
->hrgnUpdate
> 1 )
94 OffsetRgn32( wndScroll
->hrgnUpdate
, dx
, dy
);
96 for (wndPtr
= wndScroll
->child
; wndPtr
; wndPtr
= wndPtr
->next
)
97 SetWindowPos32(wndPtr
->hwndSelf
, 0, wndPtr
->rectWindow
.left
+ dx
,
98 wndPtr
->rectWindow
.top
+ dy
, 0,0, SWP_NOZORDER
|
99 SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOREDRAW
|
103 PAINT_RedrawWindow( hwnd
, NULL
, hrgnUpdate
, RDW_ALLCHILDREN
|
104 RDW_INVALIDATE
| RDW_ERASE
| RDW_ERASENOW
, RDW_C_USEHRGN
);
106 DeleteObject32( hrgnUpdate
);
111 pt
.x
+= dx
; pt
.y
+= dy
;
112 SetCaretPos32(pt
.x
, pt
.y
);
113 ShowCaret32(hCaretWnd
);
119 /*************************************************************************
120 * ScrollDC16 (USER.221)
122 BOOL16 WINAPI
ScrollDC16( HDC16 hdc
, INT16 dx
, INT16 dy
, const RECT16
*rect
,
123 const RECT16
*cliprc
, HRGN16 hrgnUpdate
,
126 RECT32 rect32
, clipRect32
, rcUpdate32
;
129 if (rect
) CONV_RECT16TO32( rect
, &rect32
);
130 if (cliprc
) CONV_RECT16TO32( cliprc
, &clipRect32
);
131 ret
= ScrollDC32( hdc
, dx
, dy
, rect
? &rect32
: NULL
,
132 cliprc
? &clipRect32
: NULL
, hrgnUpdate
, &rcUpdate32
);
133 if (rcUpdate
) CONV_RECT32TO16( &rcUpdate32
, rcUpdate
);
138 /*************************************************************************
139 * ScrollDC32 (USER32.449)
141 * Both 'rc' and 'prLClip' are in logical units but update info is
142 * returned in device coordinates.
144 BOOL32 WINAPI
ScrollDC32( HDC32 hdc
, INT32 dx
, INT32 dy
, const RECT32
*rc
,
145 const RECT32
*prLClip
, HRGN32 hrgnUpdate
,
151 DC
*dc
= (DC
*)GDI_GetObjPtr(hdc
, DC_MAGIC
);
153 TRACE(scroll
,"%04x %d,%d hrgnUpdate=%04x rcUpdate = %p cliprc = (%d,%d-%d,%d), rc=(%d,%d-%d,%d)\n",
154 (HDC16
)hdc
, dx
, dy
, hrgnUpdate
, rcUpdate
,
155 prLClip
? prLClip
->left
: 0, prLClip
? prLClip
->top
: 0, prLClip
? prLClip
->right
: 0, prLClip
? prLClip
->bottom
: 0,
156 rc
? rc
->left
: 0, rc
? rc
->top
: 0, rc
? rc
->right
: 0, rc
? rc
->bottom
: 0 );
158 if ( !dc
|| !hdc
) return FALSE
;
161 TRACE(scroll,"\t[wndOrgX=%i, wndExtX=%i, vportOrgX=%i, vportExtX=%i]\n",
162 dc->wndOrgX, dc->wndExtX, dc->vportOrgX, dc->vportExtX );
163 TRACE(scroll,"\t[wndOrgY=%i, wndExtY=%i, vportOrgY=%i, vportExtY=%i]\n",
164 dc->wndOrgY, dc->wndExtY, dc->vportOrgY, dc->vportExtY );
167 /* compute device clipping region */
171 else /* maybe we should just return FALSE? */
172 GetClipBox32( hdc
, &rClip
);
175 IntersectRect32(&rClip
,&rClip
,prLClip
);
177 if( rClip
.left
>= rClip
.right
|| rClip
.top
>= rClip
.bottom
)
179 GDI_HEAP_UNLOCK( hdc
);
184 IntersectVisRect( hdc
, rClip
.left
, rClip
.top
,
185 rClip
.right
, rClip
.bottom
);
188 /* translate coordinates */
190 ldx
= dx
* dc
->wndExtX
/ dc
->vportExtX
;
191 ldy
= dy
* dc
->wndExtY
/ dc
->vportExtY
;
194 dest
.x
= (src
.x
= rClip
.left
) + ldx
;
196 src
.x
= (dest
.x
= rClip
.left
) - ldx
;
199 dest
.y
= (src
.y
= rClip
.top
) + ldy
;
201 src
.y
= (dest
.y
= rClip
.top
) - ldy
;
205 if( rClip
.right
- rClip
.left
> ldx
&&
206 rClip
.bottom
- rClip
.top
> ldy
)
208 ldx
= rClip
.right
- rClip
.left
- ldx
;
209 ldy
= rClip
.bottom
- rClip
.top
- ldy
;
211 if (!BitBlt32( hdc
, dest
.x
, dest
.y
, ldx
, ldy
,
212 hdc
, src
.x
, src
.y
, SRCCOPY
))
214 GDI_HEAP_UNLOCK( hdc
);
219 /* restore clipping region */
221 RestoreVisRgn( hdc
);
224 /* compute update areas */
226 if ( (hrgnUpdate
|| rcUpdate
) && dc
->w
.hVisRgn
)
228 HRGN32 hrgn
= (hrgnUpdate
) ? hrgnUpdate
: CreateRectRgn32( 0,0,0,0 );
231 LPtoDP32( hdc
, (LPPOINT32
)&rClip
, 2 );
232 OffsetRect32( &rClip
, dc
->w
.DCOrgX
, dc
->w
.DCOrgY
);
233 hrgnClip
= CreateRectRgnIndirect32( &rClip
);
235 CombineRgn32( hrgn
, dc
->w
.hVisRgn
, hrgnClip
, RGN_AND
);
236 OffsetRgn32( hrgn
, dx
, dy
);
237 CombineRgn32( hrgn
, dc
->w
.hVisRgn
, hrgn
, RGN_DIFF
);
238 CombineRgn32( hrgn
, hrgn
, hrgnClip
, RGN_AND
);
239 OffsetRgn32( hrgn
, -dc
->w
.DCOrgX
, -dc
->w
.DCOrgY
);
241 if( rcUpdate
) GetRgnBox32( hrgnUpdate
, rcUpdate
);
243 if (!hrgnUpdate
) DeleteObject32( hrgn
);
244 DeleteObject32( hrgnClip
);
247 GDI_HEAP_UNLOCK( hdc
);
252 /*************************************************************************
253 * ScrollWindowEx16 (USER.319)
255 INT16 WINAPI
ScrollWindowEx16( HWND16 hwnd
, INT16 dx
, INT16 dy
,
256 const RECT16
*rect
, const RECT16
*clipRect
,
257 HRGN16 hrgnUpdate
, LPRECT16 rcUpdate
,
260 RECT32 rect32
, clipRect32
, rcUpdate32
;
263 if (rect
) CONV_RECT16TO32( rect
, &rect32
);
264 if (clipRect
) CONV_RECT16TO32( clipRect
, &clipRect32
);
265 ret
= ScrollWindowEx32( hwnd
, dx
, dy
, rect
? &rect32
: NULL
,
266 clipRect
? &clipRect32
: NULL
, hrgnUpdate
,
267 (rcUpdate
) ? &rcUpdate32
: NULL
, flags
);
268 if (rcUpdate
) CONV_RECT32TO16( &rcUpdate32
, rcUpdate
);
272 /*************************************************************************
275 static BOOL32
SCROLL_FixCaret(HWND32 hWnd
, LPRECT32 lprc
, UINT32 flags
)
277 HWND32 hCaret
= CARET_GetHwnd();
282 CARET_GetRect( &rc
);
283 if( hCaret
== hWnd
||
284 (flags
& SW_SCROLLCHILDREN
&& IsChild32(hWnd
, hCaret
)) )
288 pt
.x
= rc
.left
; pt
.y
= rc
.top
;
289 MapWindowPoints32( hCaret
, hWnd
, (LPPOINT32
)&rc
, 2 );
290 if( IntersectRect32(lprc
, lprc
, &rc
) )
293 lprc
->left
= pt
.x
; lprc
->top
= pt
.y
;
301 /*************************************************************************
302 * ScrollWindowEx32 (USER32.451)
304 * NOTE: Use this function instead of ScrollWindow32
306 INT32 WINAPI
ScrollWindowEx32( HWND32 hwnd
, INT32 dx
, INT32 dy
,
307 const RECT32
*rect
, const RECT32
*clipRect
,
308 HRGN32 hrgnUpdate
, LPRECT32 rcUpdate
,
311 INT32 retVal
= NULLREGION
;
312 BOOL32 bCaret
= FALSE
, bOwnRgn
= TRUE
;
314 WND
* wnd
= WIN_FindWndPtr( hwnd
);
316 if( !wnd
|| !WIN_IsWindowDrawable( wnd
, TRUE
)) return ERROR
;
318 if (rect
== NULL
) GetClientRect32(hwnd
, &rc
);
321 if (clipRect
) IntersectRect32(&cliprc
,&rc
,clipRect
);
324 if (!IsRectEmpty32(&cliprc
) && (dx
|| dy
))
328 BOOL32 bUpdate
= (rcUpdate
|| hrgnUpdate
|| flags
& (SW_INVALIDATE
| SW_ERASE
));
329 HRGN32 hrgnClip
= CreateRectRgnIndirect32(&cliprc
);
331 TRACE(scroll
,"%04x, %d,%d hrgnUpdate=%04x rcUpdate = %p \
332 cliprc = (%d,%d-%d,%d), rc=(%d,%d-%d,%d) %04x\n",
333 (HWND16
)hwnd
, dx
, dy
, hrgnUpdate
, rcUpdate
,
334 clipRect
?clipRect
->left
:0, clipRect
?clipRect
->top
:0, clipRect
?clipRect
->right
:0, clipRect
?clipRect
->bottom
:0,
335 rect
?rect
->left
:0, rect
?rect
->top
:0, rect
?rect
->right
:0, rect
?rect
->bottom
:0, (UINT16
)flags
);
338 bCaret
= SCROLL_FixCaret(hwnd
, &rc
, flags
);
340 if( hrgnUpdate
) bOwnRgn
= FALSE
;
341 else if( bUpdate
) hrgnUpdate
= CreateRectRgn32( 0, 0, 0, 0 );
343 hDC
= GetDCEx32( hwnd
, hrgnClip
, DCX_CACHE
| DCX_USESTYLE
|
344 ((flags
& SW_SCROLLCHILDREN
) ? DCX_NOCLIPCHILDREN
: 0) );
345 if( (dc
= (DC
*)GDI_GetObjPtr(hDC
, DC_MAGIC
)) )
347 wnd
->pDriver
->pScrollWindow(wnd
,dc
,dx
,dy
,&cliprc
,bUpdate
);
349 if( dc
->w
.hVisRgn
&& bUpdate
)
351 OffsetRgn32( hrgnClip
, dc
->w
.DCOrgX
, dc
->w
.DCOrgY
);
352 CombineRgn32( hrgnUpdate
, dc
->w
.hVisRgn
, hrgnClip
, RGN_AND
);
353 OffsetRgn32( hrgnUpdate
, dx
, dy
);
354 CombineRgn32( hrgnUpdate
, dc
->w
.hVisRgn
, hrgnUpdate
, RGN_DIFF
);
355 CombineRgn32( hrgnUpdate
, hrgnUpdate
, hrgnClip
, RGN_AND
);
356 OffsetRgn32( hrgnUpdate
, -dc
->w
.DCOrgX
, -dc
->w
.DCOrgY
);
358 if( rcUpdate
) GetRgnBox32( hrgnUpdate
, rcUpdate
);
360 ReleaseDC32(hwnd
, hDC
);
361 GDI_HEAP_UNLOCK( hDC
);
364 if( wnd
->hrgnUpdate
> 1 )
366 if( rect
|| clipRect
)
368 if( (CombineRgn32( hrgnClip
, hrgnClip
,
369 wnd
->hrgnUpdate
, RGN_AND
) != NULLREGION
) )
371 CombineRgn32( wnd
->hrgnUpdate
, wnd
->hrgnUpdate
, hrgnClip
, RGN_DIFF
);
372 OffsetRgn32( hrgnClip
, dx
, dy
);
373 CombineRgn32( wnd
->hrgnUpdate
, wnd
->hrgnUpdate
, hrgnClip
, RGN_OR
);
377 OffsetRgn32( wnd
->hrgnUpdate
, dx
, dy
);
380 if( flags
& SW_SCROLLCHILDREN
)
384 for( w
= wnd
->child
; w
; w
= w
->next
)
386 CONV_RECT16TO32( &w
->rectWindow
, &r
);
387 if( !clipRect
|| IntersectRect32(&r
, &r
, &cliprc
) )
388 SetWindowPos32(w
->hwndSelf
, 0, w
->rectWindow
.left
+ dx
,
389 w
->rectWindow
.top
+ dy
, 0,0, SWP_NOZORDER
|
390 SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOREDRAW
|
395 if( flags
& (SW_INVALIDATE
| SW_ERASE
) )
396 PAINT_RedrawWindow( hwnd
, NULL
, hrgnUpdate
, RDW_INVALIDATE
| RDW_ERASE
|
397 ((flags
& SW_ERASE
) ? RDW_ERASENOW
: 0) | ((flags
& SW_SCROLLCHILDREN
) ? RDW_ALLCHILDREN
: 0 ), 0 );
401 SetCaretPos32( rc
.left
+ dx
, rc
.top
+ dy
);
405 if( bOwnRgn
&& hrgnUpdate
) DeleteObject32( hrgnUpdate
);
406 DeleteObject32( hrgnClip
);