2 * Scroll windows and DCs
4 * Copyright David W. Metcalfe, 1993
5 * Alex Korobka 1995,1996
16 #include "sysmetrics.h"
18 /* #define DEBUG_SCROLL */
21 extern HWND
CARET_GetHwnd(); /* windows/caret.c */
22 extern void CLIPPING_UpdateGCRegion(DC
* ); /* objects/clipping.c */
26 /*************************************************************************
27 * ScrollWindow (USER.61)
30 void ScrollWindow(HWND hwnd
, short dx
, short dy
, LPRECT16 rect
, LPRECT16 clipRect
)
33 HRGN hrgnUpdate
,hrgnClip
;
35 HWND hCaretWnd
= CARET_GetHwnd();
36 WND
* wndScroll
= WIN_FindWndPtr( hwnd
);
38 dprintf_scroll(stddeb
,"ScrollWindow: hwnd=%04x, dx=%d, dy=%d, lpRect =%08lx clipRect=%i,%i,%i,%i\n",
39 hwnd
, dx
, dy
, (LONG
)rect
, (int)((clipRect
)?clipRect
->left
:0),
40 (int)((clipRect
)?clipRect
->top
:0),
41 (int)((clipRect
)?clipRect
->right
:0),
42 (int)((clipRect
)?clipRect
->bottom
:0));
44 if ( !wndScroll
|| !WIN_IsWindowDrawable( wndScroll
, TRUE
) ) return;
46 if ( !rect
) /* do not clip children */
48 GetClientRect16(hwnd
, &rc
);
49 hrgnClip
= CreateRectRgnIndirect16( &rc
);
51 if ((hCaretWnd
== hwnd
) || IsChild(hwnd
,hCaretWnd
))
55 hdc
= GetDCEx(hwnd
, hrgnClip
, DCX_CACHE
| DCX_CLIPSIBLINGS
);
56 DeleteObject(hrgnClip
);
58 else /* clip children */
60 GetClientRect16(hwnd
,&rc
);
61 CopyRect16(&rc
, rect
);
63 if (hCaretWnd
== hwnd
) HideCaret(hCaretWnd
);
70 GetClientRect16(hwnd
, &cliprc
);
72 CopyRect16(&cliprc
, clipRect
);
74 hrgnUpdate
= CreateRectRgn(0, 0, 0, 0);
75 ScrollDC(hdc
, dx
, dy
, &rc
, &cliprc
, hrgnUpdate
, NULL
);
78 if( !rect
) /* move child windows and update region */
82 if( wndScroll
->hrgnUpdate
> 1 )
83 OffsetRgn( wndScroll
->hrgnUpdate
, dx
, dy
);
85 for (wndPtr
= wndScroll
->child
; wndPtr
; wndPtr
= wndPtr
->next
)
86 SetWindowPos(wndPtr
->hwndSelf
, 0, wndPtr
->rectWindow
.left
+ dx
,
87 wndPtr
->rectWindow
.top
+ dy
, 0,0, SWP_NOZORDER
|
88 SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOREDRAW
|
92 PAINT_RedrawWindow( hwnd
, NULL
, hrgnUpdate
, RDW_ALLCHILDREN
|
93 RDW_INVALIDATE
| RDW_ERASE
| RDW_ERASENOW
, RDW_C_USEHRGN
);
95 DeleteObject(hrgnUpdate
);
96 if( hCaretWnd
) ShowCaret(hCaretWnd
);
100 /*************************************************************************
101 * ScrollDC (USER.221)
104 BOOL
ScrollDC(HDC hdc
, short dx
, short dy
, LPRECT16 rc
, LPRECT16 cliprc
,
105 HRGN hrgnUpdate
, LPRECT16 rcUpdate
)
108 HRGN hrgnScrollClip
= 0;
112 DC
*dc
= (DC
*)GDI_GetObjPtr(hdc
, DC_MAGIC
);
114 dprintf_scroll(stddeb
,"ScrollDC: dx=%d dy=%d, hrgnUpdate=%04x rcUpdate = %p cliprc = %p, rc=%d %d %d %d\n",
115 dx
, dy
, hrgnUpdate
, rcUpdate
, cliprc
, rc
? rc
->left
: 0,
116 rc
? rc
->top
: 0, rc
? rc
->right
: 0, rc
? rc
->bottom
: 0 );
118 if ( !dc
|| !hdc
) return FALSE
;
120 /* set clipping region */
122 if ( !rc
) GetClipBox16( hdc
, &rectClip
);
126 IntersectRect16(&rectClip
,&rectClip
,cliprc
);
128 if( rectClip
.left
>= rectClip
.right
|| rectClip
.top
>= rectClip
.bottom
)
131 hrgnClip
= GetClipRgn(hdc
);
132 hrgnScrollClip
= CreateRectRgnIndirect16(&rectClip
);
136 /* save a copy and change cliprgn directly */
138 CombineRgn( hrgnScrollClip
, hrgnClip
, 0, RGN_COPY
);
139 SetRectRgn( hrgnClip
, rectClip
.left
, rectClip
.top
, rectClip
.right
, rectClip
.bottom
);
141 CLIPPING_UpdateGCRegion( dc
);
144 SelectClipRgn( hdc
, hrgnScrollClip
);
146 /* translate coordinates */
150 src
.x
= XDPTOLP(dc
, rectClip
.left
);
151 dest
.x
= XDPTOLP(dc
, rectClip
.left
+ abs(dx
));
155 src
.x
= XDPTOLP(dc
, rectClip
.left
+ abs(dx
));
156 dest
.x
= XDPTOLP(dc
, rectClip
.left
);
160 src
.y
= YDPTOLP(dc
, rectClip
.top
);
161 dest
.y
= YDPTOLP(dc
, rectClip
.top
+ abs(dy
));
165 src
.y
= YDPTOLP(dc
, rectClip
.top
+ abs(dy
));
166 dest
.y
= YDPTOLP(dc
, rectClip
.top
);
169 width
= rectClip
.right
- rectClip
.left
- abs(dx
);
170 height
= rectClip
.bottom
- rectClip
.top
- abs(dy
);
174 if (!BitBlt(hdc
, dest
.x
, dest
.y
, width
, height
, hdc
, src
.x
, src
.y
,
178 /* compute update areas */
180 if (hrgnUpdate
|| rcUpdate
)
182 HRGN hrgn1
= (hrgnUpdate
)?hrgnUpdate
:CreateRectRgn( 0,0,0,0 );
186 CombineRgn( hrgn1
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
187 CombineRgn( hrgn1
, hrgn1
, (hrgnClip
)?hrgnClip
:hrgnScrollClip
, RGN_AND
);
188 OffsetRgn( hrgn1
, dx
, dy
);
189 CombineRgn( hrgn1
, dc
->w
.hVisRgn
, hrgn1
, RGN_DIFF
);
190 RgnType
= CombineRgn( hrgn1
, hrgn1
, (hrgnClip
)?hrgnClip
:hrgnScrollClip
, RGN_AND
);
196 rect
= rectClip
; /* vertical band */
197 if (dx
> 0) rect
.right
= rect
.left
+ dx
;
198 else if (dx
< 0) rect
.left
= rect
.right
+ dx
;
199 else SetRectEmpty16( &rect
);
200 SetRectRgn( hrgn1
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
202 rect
= rectClip
; /* horizontal band */
203 if (dy
> 0) rect
.bottom
= rect
.top
+ dy
;
204 else if (dy
< 0) rect
.top
= rect
.bottom
+ dy
;
205 else SetRectEmpty16( &rect
);
207 RgnType
= REGION_UnionRectWithRgn( hrgn1
, &rect
);
210 if (rcUpdate
) GetRgnBox16( hrgn1
, rcUpdate
);
211 if (!hrgnUpdate
) DeleteObject( hrgn1
);
214 /* restore clipping region */
216 SelectClipRgn( hdc
, (hrgnClip
)?hrgnScrollClip
:0 );
217 DeleteObject( hrgnScrollClip
);
223 /*************************************************************************
224 * ScrollWindowEx (USER.319)
226 * FIXME: broken, is there a program that actually uses it?
230 int ScrollWindowEx(HWND hwnd
, short dx
, short dy
, LPRECT16 rect
, LPRECT16 clipRect
,
231 HRGN hrgnUpdate
, LPRECT16 rcUpdate
, WORD flags
)
236 dprintf_scroll(stddeb
,"ScrollWindowEx: dx=%d, dy=%d, wFlags=%04x\n",dx
, dy
, flags
);
241 GetClientRect16(hwnd
, &rc
);
243 CopyRect16(&rc
, rect
);
244 if (clipRect
== NULL
)
245 GetClientRect16(hwnd
, &cliprc
);
247 CopyRect16(&cliprc
, clipRect
);
249 ScrollDC(hdc
, dx
, dy
, &rc
, &cliprc
, hrgnUpdate
, rcUpdate
);
251 if (flags
| SW_INVALIDATE
)
253 PAINT_RedrawWindow( hwnd
, NULL
, hrgnUpdate
, RDW_INVALIDATE
| RDW_ERASE
|
254 ((flags
& SW_ERASE
) ? RDW_ERASENOW
: 0), 0 );
257 ReleaseDC(hwnd
, hdc
);