2 * Scroll windows and DCs
4 * Copyright David W. Metcalfe, 1993
5 * Alex Korobka 1995,1996
10 #define NO_TRANSITION_TYPES /* This file is Win32-clean */
19 #include "sysmetrics.h"
23 extern HWND32
CARET_GetHwnd(); /* windows/caret.c */
24 extern void CARET_GetRect(LPRECT32
);
25 extern void CLIPPING_UpdateGCRegion(DC
* ); /* objects/clipping.c */
27 /*************************************************************************
28 * ScrollWindow16 (USER.61)
30 void ScrollWindow16( HWND16 hwnd
, INT16 dx
, INT16 dy
, const RECT16
*rect
,
31 const RECT16
*clipRect
)
33 RECT32 rect32
, clipRect32
;
35 if (rect
) CONV_RECT16TO32( rect
, &rect32
);
36 if (clipRect
) CONV_RECT16TO32( clipRect
, &clipRect32
);
37 ScrollWindow32( hwnd
, dx
, dy
, rect
? &rect32
: NULL
,
38 clipRect
? &clipRect32
: NULL
);
41 /*************************************************************************
42 * ScrollWindow32 (USER32.449)
44 BOOL32
ScrollWindow32( HWND32 hwnd
, INT32 dx
, INT32 dy
, const RECT32
*rect
,
45 const RECT32
*clipRect
)
48 HRGN32 hrgnUpdate
,hrgnClip
;
50 HWND32 hCaretWnd
= CARET_GetHwnd();
51 WND
* wndScroll
= WIN_FindWndPtr( hwnd
);
53 dprintf_scroll(stddeb
,"ScrollWindow: hwnd=%04x, dx=%d, dy=%d, lpRect =%p clipRect=%i,%i,%i,%i\n",
55 clipRect
? clipRect
->left
: 0,
56 clipRect
? clipRect
->top
: 0,
57 clipRect
? clipRect
->right
: 0,
58 clipRect
? clipRect
->bottom
: 0 );
60 if ( !wndScroll
|| !WIN_IsWindowDrawable( wndScroll
, TRUE
) ) return TRUE
;
62 if ( !rect
) /* do not clip children */
64 GetClientRect32(hwnd
, &rc
);
65 hrgnClip
= CreateRectRgnIndirect32( &rc
);
67 if ((hCaretWnd
== hwnd
) || IsChild32(hwnd
,hCaretWnd
))
68 HideCaret32(hCaretWnd
);
71 hdc
= GetDCEx32(hwnd
, hrgnClip
, DCX_CACHE
| DCX_CLIPSIBLINGS
);
72 DeleteObject32( hrgnClip
);
74 else /* clip children */
76 CopyRect32(&rc
, rect
);
78 if (hCaretWnd
== hwnd
) HideCaret32(hCaretWnd
);
81 hdc
= GetDCEx32( hwnd
, 0, DCX_CACHE
| DCX_USESTYLE
);
85 GetClientRect32(hwnd
, &cliprc
);
87 CopyRect32(&cliprc
, clipRect
);
89 hrgnUpdate
= CreateRectRgn32( 0, 0, 0, 0 );
90 ScrollDC32( hdc
, dx
, dy
, &rc
, &cliprc
, hrgnUpdate
, NULL
);
91 ReleaseDC32(hwnd
, hdc
);
93 if( !rect
) /* move child windows and update region */
97 if( wndScroll
->hrgnUpdate
> 1 )
98 OffsetRgn32( wndScroll
->hrgnUpdate
, dx
, dy
);
100 for (wndPtr
= wndScroll
->child
; wndPtr
; wndPtr
= wndPtr
->next
)
101 SetWindowPos32(wndPtr
->hwndSelf
, 0, wndPtr
->rectWindow
.left
+ dx
,
102 wndPtr
->rectWindow
.top
+ dy
, 0,0, SWP_NOZORDER
|
103 SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOREDRAW
|
107 PAINT_RedrawWindow( hwnd
, NULL
, hrgnUpdate
, RDW_ALLCHILDREN
|
108 RDW_INVALIDATE
| RDW_ERASE
| RDW_ERASENOW
, RDW_C_USEHRGN
);
110 DeleteObject32( hrgnUpdate
);
115 pt
.x
+= dx
; pt
.y
+= dy
;
116 SetCaretPos(pt
.x
, pt
.y
);
117 ShowCaret32(hCaretWnd
);
123 /*************************************************************************
124 * ScrollDC16 (USER.221)
126 BOOL16
ScrollDC16( HDC16 hdc
, INT16 dx
, INT16 dy
, const RECT16
*rect
,
127 const RECT16
*cliprc
, HRGN16 hrgnUpdate
, LPRECT16 rcUpdate
)
129 RECT32 rect32
, clipRect32
, rcUpdate32
;
132 if (rect
) CONV_RECT16TO32( rect
, &rect32
);
133 if (cliprc
) CONV_RECT16TO32( cliprc
, &clipRect32
);
134 ret
= ScrollDC32( hdc
, dx
, dy
, rect
? &rect32
: NULL
,
135 cliprc
? &clipRect32
: NULL
, hrgnUpdate
, &rcUpdate32
);
136 if (rcUpdate
) CONV_RECT32TO16( &rcUpdate32
, rcUpdate
);
141 /*************************************************************************
142 * ScrollDC32 (USER32.448)
144 * Both 'rc' and 'rLClip' are in logical units but update info is
145 * returned in device coordinates.
147 BOOL32
ScrollDC32( HDC32 hdc
, INT32 dx
, INT32 dy
, const RECT32
*rc
,
148 const RECT32
*prLClip
, HRGN32 hrgnUpdate
, LPRECT32 rcUpdate
)
150 RECT32 rDClip
, rLClip
;
152 HRGN32 hrgnScrollClip
= 0;
155 DC
*dc
= (DC
*)GDI_GetObjPtr(hdc
, DC_MAGIC
);
157 dprintf_scroll(stddeb
,"ScrollDC: %04x %d,%d hrgnUpdate=%04x rcUpdate = %p cliprc = (%d,%d-%d,%d), rc=(%d,%d-%d,%d)\n",
158 (HDC16
)hdc
, dx
, dy
, hrgnUpdate
, rcUpdate
,
159 prLClip
? prLClip
->left
: 0, prLClip
? prLClip
->top
: 0, prLClip
? prLClip
->right
: 0, prLClip
? prLClip
->bottom
: 0,
160 rc
? rc
->left
: 0, rc
? rc
->top
: 0, rc
? rc
->right
: 0, rc
? rc
->bottom
: 0 );
162 if ( !dc
|| !hdc
) return FALSE
;
165 printf(stddeb,"\t[wndOrgX=%i, wndExtX=%i, vportOrgX=%i, vportExtX=%i]\n",
166 dc->wndOrgX, dc->wndExtX, dc->vportOrgX, dc->vportExtX );
167 printf(stddeb,"\t[wndOrgY=%i, wndExtY=%i, vportOrgY=%i, vportExtY=%i]\n",
168 dc->wndOrgY, dc->wndExtY, dc->vportOrgY, dc->vportExtY );
171 /* compute device clipping region */
176 rDClip
.left
= XLPTODP(dc
, rc
->left
); rDClip
.right
= XLPTODP(dc
, rc
->right
);
177 rDClip
.top
= YLPTODP(dc
, rc
->top
); rDClip
.bottom
= YLPTODP(dc
, rc
->bottom
);
179 else /* maybe we should just return FALSE? */
181 GetClipBox32( hdc
, &rDClip
);
182 rLClip
.left
= XDPTOLP(dc
, rDClip
.left
); rLClip
.right
= XDPTOLP(dc
, rDClip
.right
);
183 rLClip
.top
= YDPTOLP(dc
, rDClip
.top
); rLClip
.bottom
= YDPTOLP(dc
, rDClip
.bottom
);
190 r
.left
= XLPTODP(dc
, prLClip
->left
); r
.right
= XLPTODP(dc
, prLClip
->right
);
191 r
.top
= YLPTODP(dc
, prLClip
->top
); r
.bottom
= YLPTODP(dc
, prLClip
->bottom
);
192 IntersectRect32(&rLClip
,&rLClip
,prLClip
);
193 IntersectRect32(&rDClip
,&rDClip
,&r
);
196 if( rDClip
.left
>= rDClip
.right
|| rDClip
.top
>= rDClip
.bottom
)
199 hrgnClip
= GetClipRgn16(hdc
);
200 hrgnScrollClip
= CreateRectRgnIndirect32(&rDClip
);
204 /* change device clipping region directly */
206 CombineRgn32( hrgnScrollClip
, hrgnClip
, 0, RGN_COPY
);
207 SetRectRgn( hrgnClip
, rDClip
.left
, rDClip
.top
,
208 rDClip
.right
, rDClip
.bottom
);
210 CLIPPING_UpdateGCRegion( dc
);
213 SelectClipRgn32( hdc
, hrgnScrollClip
);
215 /* translate coordinates */
217 ldx
= dx
* dc
->wndExtX
/ dc
->vportExtX
;
218 ldy
= dy
* dc
->wndExtY
/ dc
->vportExtY
;
221 dest
.x
= (src
.x
= rLClip
.left
) + ldx
;
223 src
.x
= (dest
.x
= rLClip
.left
) - ldx
;
226 dest
.y
= (src
.y
= rLClip
.top
) + ldy
;
228 src
.y
= (dest
.y
= rLClip
.top
) - ldy
;
232 if( rDClip
.right
- rDClip
.left
> dx
&&
233 rDClip
.bottom
- rDClip
.top
> dy
)
235 ldx
= rLClip
.right
- rLClip
.left
- ldx
;
236 ldy
= rLClip
.bottom
- rLClip
.top
- ldy
;
238 if (!BitBlt32( hdc
, dest
.x
, dest
.y
, ldx
, ldy
,
239 hdc
, src
.x
, src
.y
, SRCCOPY
))
243 /* restore clipping region */
247 CombineRgn32( hrgnClip
, hrgnScrollClip
, 0, RGN_COPY
);
248 CLIPPING_UpdateGCRegion( dc
);
249 SetRectRgn( hrgnScrollClip
, rDClip
.left
, rDClip
.top
,
250 rDClip
.right
, rDClip
.bottom
);
253 SelectClipRgn32( hdc
, 0 );
255 /* compute update areas */
257 if (hrgnUpdate
|| rcUpdate
)
259 HRGN32 hrgn
= (hrgnUpdate
) ? hrgnUpdate
: CreateRectRgn32( 0,0,0,0 );
263 CombineRgn32( hrgn
, dc
->w
.hVisRgn
, hrgnScrollClip
, RGN_AND
);
264 OffsetRgn32( hrgn
, dx
, dy
);
265 CombineRgn32( hrgn
, dc
->w
.hVisRgn
, hrgn
, RGN_DIFF
);
266 CombineRgn32( hrgn
, hrgn
, hrgnScrollClip
, RGN_AND
);
272 rect
= rDClip
; /* vertical band */
273 if (dx
> 0) rect
.right
= rect
.left
+ dx
;
274 else if (dx
< 0) rect
.left
= rect
.right
+ dx
;
275 else SetRectEmpty32( &rect
);
276 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
278 rect
= rDClip
; /* horizontal band */
279 if (dy
> 0) rect
.bottom
= rect
.top
+ dy
;
280 else if (dy
< 0) rect
.top
= rect
.bottom
+ dy
;
281 else SetRectEmpty32( &rect
);
283 REGION_UnionRectWithRgn( hrgn
, &rect
);
286 if (rcUpdate
) GetRgnBox32( hrgn
, rcUpdate
);
287 if (!hrgnUpdate
) DeleteObject32( hrgn
);
290 DeleteObject32( hrgnScrollClip
);
295 /*************************************************************************
296 * ScrollWindowEx16 (USER.319)
298 INT16
ScrollWindowEx16( HWND16 hwnd
, INT16 dx
, INT16 dy
, const RECT16
*rect
,
299 const RECT16
*clipRect
, HRGN16 hrgnUpdate
,
300 LPRECT16 rcUpdate
, UINT16 flags
)
302 RECT32 rect32
, clipRect32
, rcUpdate32
;
305 if (rect
) CONV_RECT16TO32( rect
, &rect32
);
306 if (clipRect
) CONV_RECT16TO32( clipRect
, &clipRect32
);
307 ret
= ScrollWindowEx32( hwnd
, dx
, dy
, rect
? &rect32
: NULL
,
308 clipRect
? &clipRect32
: NULL
, hrgnUpdate
,
309 (rcUpdate
) ? &rcUpdate32
: NULL
, flags
);
310 if (rcUpdate
) CONV_RECT32TO16( &rcUpdate32
, rcUpdate
);
314 /*************************************************************************
317 BOOL32
SCROLL_FixCaret(HWND32 hWnd
, LPRECT32 lprc
, UINT32 flags
)
319 HWND32 hCaret
= CARET_GetHwnd();
324 CARET_GetRect( &rc
);
325 if( hCaret
== hWnd
||
326 (flags
& SW_SCROLLCHILDREN
&& IsChild32(hWnd
, hCaret
)) )
330 pt
.x
= rc
.left
; pt
.y
= rc
.top
;
331 MapWindowPoints32( hCaret
, hWnd
, (LPPOINT32
)&rc
, 2 );
332 if( IntersectRect32(lprc
, lprc
, &rc
) )
335 lprc
->left
= pt
.x
; lprc
->top
= pt
.y
;
343 /*************************************************************************
344 * ScrollWindowEx32 (USER32.450)
346 INT32
ScrollWindowEx32( HWND32 hwnd
, INT32 dx
, INT32 dy
, const RECT32
*rect
,
347 const RECT32
*clipRect
, HRGN32 hrgnUpdate
,
348 LPRECT32 rcUpdate
, UINT32 flags
)
350 INT32 retVal
= NULLREGION
;
351 BOOL32 bCaret
= FALSE
, bOwnRgn
= TRUE
;
353 WND
* wnd
= WIN_FindWndPtr( hwnd
);
355 if( !wnd
|| !WIN_IsWindowDrawable( wnd
, TRUE
)) return ERROR
;
357 if (rect
== NULL
) GetClientRect32(hwnd
, &rc
);
360 if (clipRect
) IntersectRect32(&cliprc
,&rc
,clipRect
);
363 if (!IsRectEmpty32(&cliprc
) && (dx
|| dy
))
367 BOOL32 bUpdate
= (rcUpdate
|| hrgnUpdate
|| flags
& (SW_INVALIDATE
| SW_ERASE
));
368 HRGN32 hrgnClip
= CreateRectRgnIndirect32(&cliprc
);
370 dprintf_scroll(stddeb
,"ScrollWindowEx: %04x, %d,%d hrgnUpdate=%04x rcUpdate = %p \
371 cliprc = (%d,%d-%d,%d), rc=(%d,%d-%d,%d) %04x\n",
372 (HWND16
)hwnd
, dx
, dy
, hrgnUpdate
, rcUpdate
,
373 clipRect
?clipRect
->left
:0, clipRect
?clipRect
->top
:0, clipRect
?clipRect
->right
:0, clipRect
?clipRect
->bottom
:0,
374 rect
?rect
->left
:0, rect
?rect
->top
:0, rect
?rect
->right
:0, rect
?rect
->bottom
:0, (UINT16
)flags
);
377 bCaret
= SCROLL_FixCaret(hwnd
, &rc
, flags
);
379 if( hrgnUpdate
) bOwnRgn
= FALSE
;
380 else if( bUpdate
) hrgnUpdate
= CreateRectRgn32( 0, 0, 0, 0 );
382 hDC
= GetDCEx32( hwnd
, hrgnClip
, DCX_CACHE
| DCX_USESTYLE
|
383 (flags
& SW_SCROLLCHILDREN
) ? DCX_NOCLIPCHILDREN
: 0 );
384 if( (dc
= (DC
*)GDI_GetObjPtr(hDC
, DC_MAGIC
)) )
388 if( dx
> 0 ) dst
.x
= (src
.x
= dc
->w
.DCOrgX
+ cliprc
.left
) + dx
;
389 else src
.x
= (dst
.x
= dc
->w
.DCOrgX
+ cliprc
.left
) - dx
;
391 if( dy
> 0 ) dst
.y
= (src
.y
= dc
->w
.DCOrgY
+ cliprc
.top
) + dy
;
392 else src
.y
= (dst
.y
= dc
->w
.DCOrgY
+ cliprc
.top
) - dy
;
395 XSetGraphicsExposures( display
, dc
->u
.x
.gc
, True
);
396 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
397 XCopyArea( display
, dc
->u
.x
.drawable
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
398 src
.x
, src
.y
, cliprc
.right
- cliprc
.left
- abs(dx
),
399 cliprc
.bottom
- cliprc
.top
- abs(dy
), dst
.x
, dst
.y
);
401 XSetGraphicsExposures( display
, dc
->u
.x
.gc
, False
);
403 if( dc
->w
.hVisRgn
&& bUpdate
)
405 CombineRgn32( hrgnUpdate
, dc
->w
.hVisRgn
, hrgnClip
, RGN_AND
);
406 OffsetRgn32( hrgnUpdate
, dx
, dy
);
407 CombineRgn32( hrgnUpdate
, dc
->w
.hVisRgn
, hrgnUpdate
, RGN_DIFF
);
408 CombineRgn32( hrgnUpdate
, hrgnUpdate
, hrgnClip
, RGN_AND
);
410 if( rcUpdate
) GetRgnBox32( hrgnUpdate
, rcUpdate
);
412 ReleaseDC32(hwnd
, hDC
);
415 if( wnd
->hrgnUpdate
> 1 )
417 if( rect
|| clipRect
)
419 if( (CombineRgn32( hrgnClip
, hrgnClip
,
420 wnd
->hrgnUpdate
, RGN_AND
) != NULLREGION
) )
422 CombineRgn32( wnd
->hrgnUpdate
, wnd
->hrgnUpdate
, hrgnClip
, RGN_DIFF
);
423 OffsetRgn32( hrgnClip
, dx
, dy
);
424 CombineRgn32( wnd
->hrgnUpdate
, wnd
->hrgnUpdate
, hrgnClip
, RGN_OR
);
428 OffsetRgn32( wnd
->hrgnUpdate
, dx
, dy
);
431 if( flags
& SW_SCROLLCHILDREN
)
435 for( w
= wnd
->child
; w
; w
= w
->next
)
437 CONV_RECT16TO32( &w
->rectWindow
, &r
);
438 if( IntersectRect32(&r
, &r
, &cliprc
) )
439 SetWindowPos32(w
->hwndSelf
, 0, w
->rectWindow
.left
+ dx
,
440 w
->rectWindow
.top
+ dy
, 0,0, SWP_NOZORDER
|
441 SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOREDRAW
|
446 if( flags
& (SW_INVALIDATE
| SW_ERASE
) )
447 PAINT_RedrawWindow( hwnd
, NULL
, hrgnUpdate
, RDW_INVALIDATE
| RDW_ERASE
|
448 ((flags
& SW_ERASE
) ? RDW_ERASENOW
: 0), 0 );
452 SetCaretPos( rc
.left
+ dx
, rc
.top
+ dy
);
456 if( bOwnRgn
&& hrgnUpdate
) DeleteObject32( hrgnUpdate
);
457 DeleteObject32( hrgnClip
);