Release 960728
[wine/multimedia.git] / windows / scroll.c
blobd00330b3b1937b915abe2ad30acefd89b821ef0c
1 /*
2 * Scroll windows and DCs
4 * Copyright David W. Metcalfe, 1993
5 * Alex Korobka 1995
8 */
10 #include <stdlib.h>
11 #include "wintypes.h"
12 #include "class.h"
13 #include "win.h"
14 #include "gdi.h"
15 #include "sysmetrics.h"
16 #include "stddebug.h"
17 /* #define DEBUG_SCROLL */
18 #include "debug.h"
20 extern HRGN DCE_GetVisRgn(HWND, WORD); /* windows/dce.c */
21 extern HWND CARET_GetHwnd(); /* windows/caret.c */
22 extern void CLIPPING_UpdateGCRegion(DC* ); /* objects/clipping.c */
24 static int RgnType;
27 /* -----------------------------------------------------------------------
28 * SCROLL_TraceChildren
30 * Returns a region invalidated by children, siblings, and/or ansectors
31 * in the window rectangle or client rectangle
33 * dcx can have DCX_WINDOW, DCX_CLIPCHILDREN, DCX_CLIPSIBLINGS set
36 HRGN SCROLL_TraceChildren( WND* wndScroll, short dx, short dy, WORD dcx)
38 HRGN hRgnWnd;
39 HRGN hUpdateRgn,hCombineRgn;
41 if( !wndScroll || ( !dx && !dy) ) return 0;
43 if( dcx & DCX_WINDOW )
44 hRgnWnd = CreateRectRgnIndirect16(&wndScroll->rectWindow);
45 else
47 RECT32 rect = { 0, 0, wndScroll->rectClient.right - wndScroll->rectClient.left,
48 wndScroll->rectClient.bottom - wndScroll->rectClient.top };
50 hRgnWnd = CreateRectRgnIndirect32(&rect);
53 hUpdateRgn = DCE_GetVisRgn( wndScroll->hwndSelf, dcx );
54 hCombineRgn = CreateRectRgn(0,0,0,0);
56 if( !hUpdateRgn || !hCombineRgn )
58 DeleteObject( hUpdateRgn? hUpdateRgn : hCombineRgn);
59 DeleteObject(hRgnWnd);
60 return 0;
63 OffsetRgn( hUpdateRgn, dx, dy);
64 CombineRgn(hCombineRgn, hRgnWnd, hUpdateRgn, RGN_DIFF);
66 DeleteObject(hRgnWnd);
67 DeleteObject(hUpdateRgn);
69 return hCombineRgn;
73 /* ----------------------------------------------------------------------
74 * SCROLL_ScrollChildren
76 BOOL SCROLL_ScrollChildren( WND* wndScroll, short dx, short dy)
78 WND *wndPtr = NULL;
79 HRGN hUpdateRgn;
80 BOOL b = 0;
82 if( !wndScroll || ( !dx && !dy )) return 0;
84 dprintf_scroll(stddeb,"SCROLL_ScrollChildren: hwnd %04x dx=%i dy=%i\n",wndScroll->hwndSelf,dx,dy);
86 /* get a region in client rect invalidated by siblings and ansectors */
87 hUpdateRgn = SCROLL_TraceChildren(wndScroll, dx , dy, DCX_CLIPSIBLINGS);
89 /* update children coordinates */
90 for (wndPtr = wndScroll->child; wndPtr; wndPtr = wndPtr->next)
92 /* we can check if window intersects with clipRect parameter
93 * and do not move it if not - just a thought. - AK
95 SetWindowPos(wndPtr->hwndSelf, 0, wndPtr->rectWindow.left + dx,
96 wndPtr->rectWindow.top + dy, 0,0, SWP_NOZORDER |
97 SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW |
98 SWP_DEFERERASE );
101 /* invalidate uncovered region and paint frames */
102 b = RedrawWindow32( wndScroll->hwndSelf, NULL, hUpdateRgn,
103 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN );
105 DeleteObject( hUpdateRgn);
106 return b;
110 /*************************************************************************
111 * ScrollWindow (USER.61)
114 void ScrollWindow(HWND hwnd, short dx, short dy, LPRECT16 rect, LPRECT16 clipRect)
116 HDC hdc;
117 HRGN hrgnUpdate,hrgnClip;
118 RECT16 rc, cliprc;
119 HWND hCaretWnd = CARET_GetHwnd();
120 WND* wndScroll = WIN_FindWndPtr( hwnd );
122 dprintf_scroll(stddeb,"ScrollWindow: dx=%d, dy=%d, lpRect =%08lx clipRect=%i,%i,%i,%i\n",
123 dx, dy, (LONG)rect, (int)((clipRect)?clipRect->left:0),
124 (int)((clipRect)?clipRect->top:0),
125 (int)((clipRect)?clipRect->right:0),
126 (int)((clipRect)?clipRect->bottom:0));
128 /* if rect is NULL children have to be moved */
129 if ( !rect )
131 GetClientRect16(hwnd, &rc);
132 hrgnClip = CreateRectRgnIndirect16( &rc );
134 if ((hCaretWnd == hwnd) || IsChild(hwnd,hCaretWnd))
135 HideCaret(hCaretWnd);
136 else hCaretWnd = 0;
138 /* children will be Blt'ed too */
139 hdc = GetDCEx(hwnd, hrgnClip, DCX_CACHE | DCX_CLIPSIBLINGS);
140 DeleteObject(hrgnClip);
142 else
144 GetClientRect16(hwnd,&rc);
145 dprintf_scroll(stddeb,"\trect=%i %i %i %i client=%i %i %i %i\n",
146 (int)rect->left,(int)rect->top,(int)rect->right,
147 (int)rect->bottom,(int)rc.left,(int)rc.top,
148 (int)rc.right,(int)rc.bottom);
150 if (hCaretWnd == hwnd) HideCaret(hCaretWnd);
151 else hCaretWnd = 0;
152 CopyRect16(&rc, rect);
153 hdc = GetDC(hwnd);
156 if (clipRect == NULL)
157 GetClientRect16(hwnd, &cliprc);
158 else
159 CopyRect16(&cliprc, clipRect);
161 /* move window update region (if any) */
163 if( wndScroll->hrgnUpdate > 1 )
164 OffsetRgn( wndScroll->hrgnUpdate, dx, dy );
166 hrgnUpdate = CreateRectRgn(0, 0, 0, 0);
167 ScrollDC(hdc, dx, dy, &rc, &cliprc, hrgnUpdate, NULL);
168 ReleaseDC(hwnd, hdc);
170 if( !rect )
172 /* FIXME: this doesn't take into account hrgnUpdate */
174 if( !SCROLL_ScrollChildren( wndScroll, dx,dy) )
175 InvalidateRgn(hwnd, hrgnUpdate, TRUE);
177 else
179 HRGN hrgnInv = SCROLL_TraceChildren( wndScroll ,dx,dy,DCX_CLIPCHILDREN |
180 DCX_CLIPSIBLINGS );
181 if( hrgnInv )
183 CombineRgn(hrgnUpdate,hrgnInv,hrgnUpdate,RGN_OR);
184 DeleteObject(hrgnInv);
187 RedrawWindow32( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW);
190 DeleteObject(hrgnUpdate);
191 if( hCaretWnd ) ShowCaret(hCaretWnd);
195 /*************************************************************************
196 * ScrollDC (USER.221)
199 BOOL ScrollDC(HDC hdc, short dx, short dy, LPRECT16 rc, LPRECT16 cliprc,
200 HRGN hrgnUpdate, LPRECT16 rcUpdate)
202 HRGN hrgnClip = 0;
203 HRGN hrgnScrollClip = 0;
204 RECT16 rectClip;
205 POINT16 src, dest;
206 short width, height;
207 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
209 dprintf_scroll(stddeb,"ScrollDC: dx=%d dy=%d, hrgnUpdate=%04x rcUpdate = %p cliprc = %p, rc=%d %d %d %d\n",
210 dx, dy, hrgnUpdate, rcUpdate, cliprc, rc ? rc->left : 0,
211 rc ? rc->top : 0, rc ? rc->right : 0, rc ? rc->bottom : 0 );
213 if (rc == NULL || !hdc || !dc)
214 return FALSE;
216 /* set clipping region */
218 if (cliprc)
219 IntersectRect16(&rectClip,rc,cliprc);
220 else
221 rectClip = *rc;
223 if( rectClip.left >= rectClip.right || rectClip.top >= rectClip.bottom )
224 return FALSE;
226 hrgnClip = GetClipRgn(hdc);
227 hrgnScrollClip = CreateRectRgnIndirect16(&rectClip);
229 if( hrgnClip )
231 /* call UpdateGCRegion directly to avoid
232 * one more temporary region
235 CombineRgn( hrgnScrollClip, hrgnClip, 0, RGN_COPY );
236 SetRectRgn( hrgnClip, rectClip.left, rectClip.top, rectClip.right, rectClip.bottom );
238 CLIPPING_UpdateGCRegion( dc );
240 else
241 SelectClipRgn( hdc, hrgnScrollClip );
243 /* translate coordinates */
245 if (dx > 0)
247 src.x = XDPTOLP(dc, rc->left);
248 dest.x = XDPTOLP(dc, rc->left + abs(dx));
250 else
252 src.x = XDPTOLP(dc, rc->left + abs(dx));
253 dest.x = XDPTOLP(dc, rc->left);
255 if (dy > 0)
257 src.y = YDPTOLP(dc, rc->top);
258 dest.y = YDPTOLP(dc, rc->top + abs(dy));
260 else
262 src.y = YDPTOLP(dc, rc->top + abs(dy));
263 dest.y = YDPTOLP(dc, rc->top);
266 width = rc->right - rc->left - abs(dx);
267 height = rc->bottom - rc->top - abs(dy);
269 /* copy bits */
271 if (!BitBlt(hdc, dest.x, dest.y, width, height, hdc, src.x, src.y,
272 SRCCOPY))
273 return FALSE;
275 /* compute update areas */
277 if (hrgnUpdate)
279 HRGN hrgn1,hrgn2;
281 if (dx > 0)
282 hrgn1 = CreateRectRgn(rc->left, rc->top, rc->left+dx, rc->bottom);
283 else if (dx < 0)
284 hrgn1 = CreateRectRgn(rc->right+dx, rc->top, rc->right,
285 rc->bottom);
286 else
287 hrgn1 = CreateRectRgn(0, 0, 0, 0);
289 if (dy > 0)
290 hrgn2 = CreateRectRgn(rc->left, rc->top, rc->right, rc->top+dy);
291 else if (dy < 0)
292 hrgn2 = CreateRectRgn(rc->left, rc->bottom+dy, rc->right,
293 rc->bottom);
294 else
295 hrgn2 = CreateRectRgn(0, 0, 0, 0);
297 RgnType = CombineRgn(hrgnUpdate, hrgn1, hrgn2, RGN_OR);
298 DeleteObject(hrgn1);
299 DeleteObject(hrgn2);
300 if (rcUpdate) GetRgnBox16( hrgnUpdate, rcUpdate );
302 else if (rcUpdate)
304 RECT16 rx,ry;
306 rx = ry = *rc;
307 if( dx > 0 ) rx.right = rc->left+dx;
308 else if (dx < 0) rx.left = rc->right+dx;
309 else SetRectEmpty16( &rx );
311 if( dy > 0 ) ry.bottom = rc->top+dy;
312 else if (dy < 0) ry.top = rc->bottom+dy;
313 else SetRectEmpty16( &ry );
315 UnionRect16( rcUpdate, &rx, &ry );
318 /* restore clipping region */
320 SelectClipRgn( hdc, (hrgnClip)?hrgnScrollClip:0 );
321 DeleteObject( hrgnScrollClip );
323 return TRUE;
327 /*************************************************************************
328 * ScrollWindowEx (USER.319)
330 * FIXME: broken
332 * SCROLL_TraceChildren can help
335 int ScrollWindowEx(HWND hwnd, short dx, short dy, LPRECT16 rect, LPRECT16 clipRect,
336 HRGN hrgnUpdate, LPRECT16 rcUpdate, WORD flags)
338 HDC hdc;
339 RECT16 rc, cliprc;
341 dprintf_scroll(stddeb,"ScrollWindowEx: dx=%d, dy=%d, wFlags=%04x\n",dx, dy, flags);
343 hdc = GetDC(hwnd);
345 if (rect == NULL)
346 GetClientRect16(hwnd, &rc);
347 else
348 CopyRect16(&rc, rect);
349 if (clipRect == NULL)
350 GetClientRect16(hwnd, &cliprc);
351 else
352 CopyRect16(&cliprc, clipRect);
354 ScrollDC(hdc, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate);
356 if (flags | SW_INVALIDATE)
358 RedrawWindow32( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
359 ((flags & SW_ERASE) ? RDW_ERASENOW : 0));
362 ReleaseDC(hwnd, hdc);
363 return RgnType;