Release 960225
[wine.git] / windows / scroll.c
blob4aa0fce493bdb4d7e491a3ee111de5b192b0da63
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 HRGN hrgnCombine = CreateRectRgn(0,0,0,0);
188 CombineRgn(hrgnCombine,hrgnInv,hrgnUpdate,RGN_OR);
189 dprintf_scroll(stddeb,"ScrollWindow: hrgnComb="NPFMT" hrgnInv="NPFMT" hrgnUpd="NPFMT"\n",
190 hrgnCombine,hrgnInv,hrgnUpdate);
192 DeleteObject(hrgnUpdate); DeleteObject(hrgnInv);
193 hrgnUpdate = hrgnCombine;
196 RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW);
199 DeleteObject(hrgnUpdate);
200 if( hCaretWnd ) ShowCaret(hCaretWnd);
204 /*************************************************************************
205 * ScrollDC (USER.221)
207 * FIXME: half-broken
210 BOOL ScrollDC(HDC hdc, short dx, short dy, LPRECT rc, LPRECT cliprc,
211 HRGN hrgnUpdate, LPRECT rcUpdate)
213 HRGN hrgnClip, hrgn1, hrgn2;
214 POINT src, dest;
215 short width, height;
216 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
218 dprintf_scroll(stddeb,"ScrollDC: dx=%d dy=%d, hrgnUpdate="NPFMT" rc=%i %i %i %i\n",
219 dx,dy,hrgnUpdate,(int)((rc)?rc->left:0),
220 (int)((rc)?rc->top:0),
221 (int)((rc)?rc->right:0),
222 (int)((rc)?rc->bottom:0));
224 if (rc == NULL)
225 return FALSE;
227 if (cliprc)
229 hrgnClip = CreateRectRgnIndirect(cliprc);
230 SelectClipRgn(hdc, hrgnClip);
233 if (dx > 0)
235 src.x = XDPTOLP(dc, rc->left);
236 dest.x = XDPTOLP(dc, rc->left + abs(dx));
238 else
240 src.x = XDPTOLP(dc, rc->left + abs(dx));
241 dest.x = XDPTOLP(dc, rc->left);
243 if (dy > 0)
245 src.y = YDPTOLP(dc, rc->top);
246 dest.y = YDPTOLP(dc, rc->top + abs(dy));
248 else
250 src.y = YDPTOLP(dc, rc->top + abs(dy));
251 dest.y = YDPTOLP(dc, rc->top);
254 width = rc->right - rc->left - abs(dx);
255 height = rc->bottom - rc->top - abs(dy);
257 if (!BitBlt(hdc, dest.x, dest.y, width, height, hdc, src.x, src.y,
258 SRCCOPY))
259 return FALSE;
261 if (hrgnUpdate)
263 if (dx > 0)
264 hrgn1 = CreateRectRgn(rc->left, rc->top, rc->left+dx, rc->bottom);
265 else if (dx < 0)
266 hrgn1 = CreateRectRgn(rc->right+dx, rc->top, rc->right,
267 rc->bottom);
268 else
269 hrgn1 = CreateRectRgn(0, 0, 0, 0);
271 if (dy > 0)
272 hrgn2 = CreateRectRgn(rc->left, rc->top, rc->right, rc->top+dy);
273 else if (dy < 0)
274 hrgn2 = CreateRectRgn(rc->left, rc->bottom+dy, rc->right,
275 rc->bottom);
276 else
277 hrgn2 = CreateRectRgn(0, 0, 0, 0);
279 RgnType = CombineRgn(hrgnUpdate, hrgn1, hrgn2, RGN_OR);
280 DeleteObject(hrgn1);
281 DeleteObject(hrgn2);
284 if (rcUpdate) GetRgnBox( hrgnUpdate, rcUpdate );
285 return TRUE;
289 /*************************************************************************
290 * ScrollWindowEx (USER.319)
292 * FIXME: broken
294 * SCROLL_TraceChildren can help
297 int ScrollWindowEx(HWND hwnd, short dx, short dy, LPRECT rect, LPRECT clipRect,
298 HRGN hrgnUpdate, LPRECT rcUpdate, WORD flags)
300 HDC hdc;
301 RECT rc, cliprc;
303 dprintf_scroll(stddeb,"ScrollWindowEx: dx=%d, dy=%d, wFlags=%04x\n",dx, dy, flags);
305 hdc = GetDC(hwnd);
307 if (rect == NULL)
308 GetClientRect(hwnd, &rc);
309 else
310 CopyRect(&rc, rect);
311 if (clipRect == NULL)
312 GetClientRect(hwnd, &cliprc);
313 else
314 CopyRect(&cliprc, clipRect);
316 ScrollDC(hdc, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate);
318 if (flags | SW_INVALIDATE)
320 RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
321 ((flags & SW_ERASE) ? RDW_ERASENOW : 0));
324 ReleaseDC(hwnd, hdc);
325 return RgnType;