Release 960314
[wine/multimedia.git] / windows / scroll.c
blob95a88e881773d18b0fce5eb501fe983dc5d8bf81
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"
22 extern HRGN DCE_GetVisRgn(HWND, WORD);
23 extern HWND CARET_GetHwnd();
25 static int RgnType;
28 /* -----------------------------------------------------------------------
29 * SCROLL_TraceChildren
31 * Returns a region invalidated by children, siblings, and/or ansectors
32 * in the window rectangle or client rectangle
34 * dcx can have DCX_WINDOW, DCX_CLIPCHILDREN, DCX_CLIPSIBLINGS set
37 HRGN SCROLL_TraceChildren( HWND hScroll, short dx, short dy, WORD dcx)
39 WND *wndScroll = WIN_FindWndPtr( hScroll );
40 HRGN hRgnWnd;
41 HRGN hUpdateRgn,hCombineRgn;
43 if( !wndScroll || ( !dx && !dy) ) return 0;
45 if( dcx & DCX_WINDOW )
46 hRgnWnd = CreateRectRgnIndirect(&wndScroll->rectWindow);
47 else
49 RECT rect;
51 GetClientRect(hScroll,&rect);
52 hRgnWnd = CreateRectRgnIndirect(&rect);
55 hUpdateRgn = DCE_GetVisRgn( hScroll, dcx );
56 hCombineRgn = CreateRectRgn(0,0,0,0);
58 if( !hUpdateRgn || !hCombineRgn )
60 DeleteObject( hUpdateRgn? hUpdateRgn : hCombineRgn);
61 DeleteObject(hRgnWnd);
62 return 0;
65 OffsetRgn( hUpdateRgn, dx, dy);
66 CombineRgn(hCombineRgn, hRgnWnd, hUpdateRgn, RGN_DIFF);
68 DeleteObject(hRgnWnd);
69 DeleteObject(hUpdateRgn);
71 return hCombineRgn;
75 /* ----------------------------------------------------------------------
76 * SCROLL_ScrollChildren
78 BOOL SCROLL_ScrollChildren( HWND hScroll, short dx, short dy)
80 WND *wndPtr = WIN_FindWndPtr(hScroll);
81 HWND hWnd = wndPtr->hwndChild;
82 HRGN hUpdateRgn;
83 BOOL b = 0;
85 if( !wndPtr || ( !dx && !dy )) return 0;
87 dprintf_scroll(stddeb,"SCROLL_ScrollChildren: hwnd "NPFMT" dx=%i dy=%i\n",hScroll,dx,dy);
89 /* get a region in client rect invalidated by siblings and ansectors */
90 hUpdateRgn = SCROLL_TraceChildren(hScroll, dx , dy, DCX_CLIPSIBLINGS);
92 /* update children coordinates */
93 while( hWnd )
95 wndPtr = WIN_FindWndPtr( hWnd );
97 /* we can check if window intersects with clipRect parameter
98 * and do not move it if not - just a thought. - AK
101 SetWindowPos(hWnd,0,wndPtr->rectWindow.left + dx,
102 wndPtr->rectWindow.top + dy, 0,0, SWP_NOZORDER |
103 SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW |
104 SWP_DEFERERASE );
106 hWnd = wndPtr->hwndNext;
109 /* invalidate uncovered region and paint frames */
110 b = RedrawWindow( hScroll, NULL, hUpdateRgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
111 RDW_ERASENOW | RDW_ALLCHILDREN );
113 DeleteObject( hUpdateRgn);
114 return b;
118 /*************************************************************************
119 * ScrollWindow (USER.61)
121 * FIXME: a bit broken
124 void ScrollWindow(HWND hwnd, short dx, short dy, LPRECT rect, LPRECT clipRect)
126 HDC hdc;
127 HRGN hrgnUpdate,hrgnClip;
128 RECT rc, cliprc;
129 HWND hCaretWnd = CARET_GetHwnd();
131 dprintf_scroll(stddeb,"ScrollWindow: dx=%d, dy=%d, lpRect =%08lx clipRect=%i,%i,%i,%i\n",
132 dx, dy, (LONG)rect, (int)((clipRect)?clipRect->left:0),
133 (int)((clipRect)?clipRect->top:0),
134 (int)((clipRect)?clipRect->right:0),
135 (int)((clipRect)?clipRect->bottom:0));
137 /* if rect is NULL children have to be moved */
138 if ( !rect )
140 GetClientRect(hwnd, &rc);
141 hrgnClip = CreateRectRgnIndirect( &rc );
143 if ((hCaretWnd == hwnd) || IsChild(hwnd,hCaretWnd))
144 HideCaret(hCaretWnd);
145 else hCaretWnd = 0;
147 /* children will be Blt'ed too */
148 hdc = GetDCEx(hwnd, hrgnClip, DCX_CACHE | DCX_CLIPSIBLINGS);
149 DeleteObject(hrgnClip);
151 else
153 GetClientRect(hwnd,&rc);
154 dprintf_scroll(stddeb,"\trect=%i %i %i %i client=%i %i %i %i\n",
155 (int)rect->left,(int)rect->top,(int)rect->right,
156 (int)rect->bottom,(int)rc.left,(int)rc.top,
157 (int)rc.right,(int)rc.bottom);
159 if (hCaretWnd == hwnd) HideCaret(hCaretWnd);
160 else hCaretWnd = 0;
161 CopyRect(&rc, rect);
162 hdc = GetDC(hwnd);
165 if (clipRect == NULL)
166 GetClientRect(hwnd, &cliprc);
167 else
168 CopyRect(&cliprc, clipRect);
170 hrgnUpdate = CreateRectRgn(0, 0, 0, 0);
171 ScrollDC(hdc, dx, dy, &rc, &cliprc, hrgnUpdate, NULL);
172 ReleaseDC(hwnd, hdc);
174 if( !rect )
176 /* FIXME: this doesn't take into account hrgnUpdate */
177 if( !SCROLL_ScrollChildren(hwnd,dx,dy) )
178 InvalidateRgn(hwnd, hrgnUpdate, TRUE);
180 else
182 HRGN hrgnInv = SCROLL_TraceChildren(hwnd,dx,dy,DCX_CLIPCHILDREN |
183 DCX_CLIPSIBLINGS );
184 if( hrgnInv )
186 CombineRgn(hrgnUpdate,hrgnInv,hrgnUpdate,RGN_OR);
187 DeleteObject(hrgnInv);
190 RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW);
193 DeleteObject(hrgnUpdate);
194 if( hCaretWnd ) ShowCaret(hCaretWnd);
198 /*************************************************************************
199 * ScrollDC (USER.221)
201 * FIXME: half-broken
204 BOOL ScrollDC(HDC hdc, short dx, short dy, LPRECT rc, LPRECT cliprc,
205 HRGN hrgnUpdate, LPRECT rcUpdate)
207 HRGN hrgnClip, hrgn1, hrgn2;
208 POINT src, dest;
209 short width, height;
210 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
212 dprintf_scroll(stddeb,"ScrollDC: dx=%d dy=%d, hrgnUpdate="NPFMT" rc=%i %i %i %i\n",
213 dx,dy,hrgnUpdate,(int)((rc)?rc->left:0),
214 (int)((rc)?rc->top:0),
215 (int)((rc)?rc->right:0),
216 (int)((rc)?rc->bottom:0));
218 if (rc == NULL)
219 return FALSE;
221 if (cliprc)
223 hrgnClip = CreateRectRgnIndirect(cliprc);
224 SelectClipRgn(hdc, hrgnClip);
227 if (dx > 0)
229 src.x = XDPTOLP(dc, rc->left);
230 dest.x = XDPTOLP(dc, rc->left + abs(dx));
232 else
234 src.x = XDPTOLP(dc, rc->left + abs(dx));
235 dest.x = XDPTOLP(dc, rc->left);
237 if (dy > 0)
239 src.y = YDPTOLP(dc, rc->top);
240 dest.y = YDPTOLP(dc, rc->top + abs(dy));
242 else
244 src.y = YDPTOLP(dc, rc->top + abs(dy));
245 dest.y = YDPTOLP(dc, rc->top);
248 width = rc->right - rc->left - abs(dx);
249 height = rc->bottom - rc->top - abs(dy);
251 if (!BitBlt(hdc, dest.x, dest.y, width, height, hdc, src.x, src.y,
252 SRCCOPY))
253 return FALSE;
255 if (hrgnUpdate)
257 if (dx > 0)
258 hrgn1 = CreateRectRgn(rc->left, rc->top, rc->left+dx, rc->bottom);
259 else if (dx < 0)
260 hrgn1 = CreateRectRgn(rc->right+dx, rc->top, rc->right,
261 rc->bottom);
262 else
263 hrgn1 = CreateRectRgn(0, 0, 0, 0);
265 if (dy > 0)
266 hrgn2 = CreateRectRgn(rc->left, rc->top, rc->right, rc->top+dy);
267 else if (dy < 0)
268 hrgn2 = CreateRectRgn(rc->left, rc->bottom+dy, rc->right,
269 rc->bottom);
270 else
271 hrgn2 = CreateRectRgn(0, 0, 0, 0);
273 RgnType = CombineRgn(hrgnUpdate, hrgn1, hrgn2, RGN_OR);
274 DeleteObject(hrgn1);
275 DeleteObject(hrgn2);
278 if (rcUpdate) GetRgnBox( hrgnUpdate, rcUpdate );
279 return TRUE;
283 /*************************************************************************
284 * ScrollWindowEx (USER.319)
286 * FIXME: broken
288 * SCROLL_TraceChildren can help
291 int ScrollWindowEx(HWND hwnd, short dx, short dy, LPRECT rect, LPRECT clipRect,
292 HRGN hrgnUpdate, LPRECT rcUpdate, WORD flags)
294 HDC hdc;
295 RECT rc, cliprc;
297 dprintf_scroll(stddeb,"ScrollWindowEx: dx=%d, dy=%d, wFlags=%04x\n",dx, dy, flags);
299 hdc = GetDC(hwnd);
301 if (rect == NULL)
302 GetClientRect(hwnd, &rc);
303 else
304 CopyRect(&rc, rect);
305 if (clipRect == NULL)
306 GetClientRect(hwnd, &cliprc);
307 else
308 CopyRect(&cliprc, clipRect);
310 ScrollDC(hdc, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate);
312 if (flags | SW_INVALIDATE)
314 RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
315 ((flags & SW_ERASE) ? RDW_ERASENOW : 0));
318 ReleaseDC(hwnd, hdc);
319 return RgnType;