Release 960521
[wine.git] / windows / scroll.c
blob55690939d9e016053f2efba2da4641c482573734
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 = CreateRectRgnIndirect16(&wndScroll->rectWindow);
47 else
49 RECT32 rect;
51 GetClientRect32(hScroll,&rect);
52 hRgnWnd = CreateRectRgnIndirect32(&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 HRGN hUpdateRgn;
82 BOOL b = 0;
84 if( !wndPtr || ( !dx && !dy )) return 0;
86 dprintf_scroll(stddeb,"SCROLL_ScrollChildren: hwnd %04x dx=%i dy=%i\n",hScroll,dx,dy);
88 /* get a region in client rect invalidated by siblings and ansectors */
89 hUpdateRgn = SCROLL_TraceChildren(hScroll, dx , dy, DCX_CLIPSIBLINGS);
91 /* update children coordinates */
92 for (wndPtr = wndPtr->child; wndPtr; wndPtr = wndPtr->next)
94 /* we can check if window intersects with clipRect parameter
95 * and do not move it if not - just a thought. - AK
97 SetWindowPos(wndPtr->hwndSelf, 0, wndPtr->rectWindow.left + dx,
98 wndPtr->rectWindow.top + dy, 0,0, SWP_NOZORDER |
99 SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW |
100 SWP_DEFERERASE );
103 /* invalidate uncovered region and paint frames */
104 b = RedrawWindow32( hScroll, NULL, hUpdateRgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
105 RDW_ERASENOW | RDW_ALLCHILDREN );
107 DeleteObject( hUpdateRgn);
108 return b;
112 /*************************************************************************
113 * ScrollWindow (USER.61)
115 * FIXME: a bit broken
118 void ScrollWindow(HWND hwnd, short dx, short dy, LPRECT16 rect, LPRECT16 clipRect)
120 HDC hdc;
121 HRGN hrgnUpdate,hrgnClip;
122 RECT16 rc, cliprc;
123 HWND hCaretWnd = CARET_GetHwnd();
125 dprintf_scroll(stddeb,"ScrollWindow: dx=%d, dy=%d, lpRect =%08lx clipRect=%i,%i,%i,%i\n",
126 dx, dy, (LONG)rect, (int)((clipRect)?clipRect->left:0),
127 (int)((clipRect)?clipRect->top:0),
128 (int)((clipRect)?clipRect->right:0),
129 (int)((clipRect)?clipRect->bottom:0));
131 /* if rect is NULL children have to be moved */
132 if ( !rect )
134 GetClientRect16(hwnd, &rc);
135 hrgnClip = CreateRectRgnIndirect16( &rc );
137 if ((hCaretWnd == hwnd) || IsChild(hwnd,hCaretWnd))
138 HideCaret(hCaretWnd);
139 else hCaretWnd = 0;
141 /* children will be Blt'ed too */
142 hdc = GetDCEx(hwnd, hrgnClip, DCX_CACHE | DCX_CLIPSIBLINGS);
143 DeleteObject(hrgnClip);
145 else
147 GetClientRect16(hwnd,&rc);
148 dprintf_scroll(stddeb,"\trect=%i %i %i %i client=%i %i %i %i\n",
149 (int)rect->left,(int)rect->top,(int)rect->right,
150 (int)rect->bottom,(int)rc.left,(int)rc.top,
151 (int)rc.right,(int)rc.bottom);
153 if (hCaretWnd == hwnd) HideCaret(hCaretWnd);
154 else hCaretWnd = 0;
155 CopyRect16(&rc, rect);
156 hdc = GetDC(hwnd);
159 if (clipRect == NULL)
160 GetClientRect16(hwnd, &cliprc);
161 else
162 CopyRect16(&cliprc, clipRect);
164 hrgnUpdate = CreateRectRgn(0, 0, 0, 0);
165 ScrollDC(hdc, dx, dy, &rc, &cliprc, hrgnUpdate, NULL);
166 ReleaseDC(hwnd, hdc);
168 if( !rect )
170 /* FIXME: this doesn't take into account hrgnUpdate */
171 if( !SCROLL_ScrollChildren(hwnd,dx,dy) )
172 InvalidateRgn(hwnd, hrgnUpdate, TRUE);
174 else
176 HRGN hrgnInv = SCROLL_TraceChildren(hwnd,dx,dy,DCX_CLIPCHILDREN |
177 DCX_CLIPSIBLINGS );
178 if( hrgnInv )
180 CombineRgn(hrgnUpdate,hrgnInv,hrgnUpdate,RGN_OR);
181 DeleteObject(hrgnInv);
184 RedrawWindow32( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW);
187 DeleteObject(hrgnUpdate);
188 if( hCaretWnd ) ShowCaret(hCaretWnd);
192 /*************************************************************************
193 * ScrollDC (USER.221)
195 * FIXME: half-broken
198 BOOL ScrollDC(HDC hdc, short dx, short dy, LPRECT16 rc, LPRECT16 cliprc,
199 HRGN hrgnUpdate, LPRECT16 rcUpdate)
201 HRGN hrgnClip;
202 POINT16 src, dest;
203 short width, height;
204 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
206 dprintf_scroll(stddeb,"ScrollDC: dx=%d dy=%d, hrgnUpdate=%04x rcUpdate = %p cliprc = %p, rc=%d %d %d %d\n",
207 dx, dy, hrgnUpdate, rcUpdate, cliprc, rc ? rc->left : 0,
208 rc ? rc->top : 0, rc ? rc->right : 0, rc ? rc->bottom : 0 );
210 if (rc == NULL)
211 return FALSE;
213 if (!dc)
215 fprintf(stdnimp,"ScrollDC: Invalid HDC\n");
216 return FALSE;
219 if (cliprc)
221 hrgnClip = CreateRectRgnIndirect16(cliprc);
222 SelectClipRgn(hdc, hrgnClip);
225 if (dx > 0)
227 src.x = XDPTOLP(dc, rc->left);
228 dest.x = XDPTOLP(dc, rc->left + abs(dx));
230 else
232 src.x = XDPTOLP(dc, rc->left + abs(dx));
233 dest.x = XDPTOLP(dc, rc->left);
235 if (dy > 0)
237 src.y = YDPTOLP(dc, rc->top);
238 dest.y = YDPTOLP(dc, rc->top + abs(dy));
240 else
242 src.y = YDPTOLP(dc, rc->top + abs(dy));
243 dest.y = YDPTOLP(dc, rc->top);
246 width = rc->right - rc->left - abs(dx);
247 height = rc->bottom - rc->top - abs(dy);
249 if (!BitBlt(hdc, dest.x, dest.y, width, height, hdc, src.x, src.y,
250 SRCCOPY))
251 return FALSE;
253 if (hrgnUpdate)
255 HRGN hrgn1,hrgn2;
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);
276 if (rcUpdate) GetRgnBox16( hrgnUpdate, rcUpdate );
278 else if (rcUpdate)
280 RECT16 rx,ry;
282 rx = ry = *rc;
283 if( dx > 0 ) rx.right = rc->left+dx;
284 else if (dx < 0) rx.left = rc->right+dx;
285 else SetRectEmpty16( &rx );
287 if( dy > 0 ) ry.bottom = rc->top+dy;
288 else if (dy < 0) ry.top = rc->bottom+dy;
289 else SetRectEmpty16( &ry );
291 UnionRect16( rcUpdate, &rx, &ry );
294 return TRUE;
298 /*************************************************************************
299 * ScrollWindowEx (USER.319)
301 * FIXME: broken
303 * SCROLL_TraceChildren can help
306 int ScrollWindowEx(HWND hwnd, short dx, short dy, LPRECT16 rect, LPRECT16 clipRect,
307 HRGN hrgnUpdate, LPRECT16 rcUpdate, WORD flags)
309 HDC hdc;
310 RECT16 rc, cliprc;
312 dprintf_scroll(stddeb,"ScrollWindowEx: dx=%d, dy=%d, wFlags=%04x\n",dx, dy, flags);
314 hdc = GetDC(hwnd);
316 if (rect == NULL)
317 GetClientRect16(hwnd, &rc);
318 else
319 CopyRect16(&rc, rect);
320 if (clipRect == NULL)
321 GetClientRect16(hwnd, &cliprc);
322 else
323 CopyRect16(&cliprc, clipRect);
325 ScrollDC(hdc, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate);
327 if (flags | SW_INVALIDATE)
329 RedrawWindow32( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
330 ((flags & SW_ERASE) ? RDW_ERASENOW : 0));
333 ReleaseDC(hwnd, hdc);
334 return RgnType;