blob: f92adf16fd5043e0350f5db26d5dab2cb23811b6 [file] [log] [blame]
Alexandre Julliarde399fc31993-11-24 17:08:56 +00001/*
2 * Scroll windows and DCs
3 *
4 * Copyright David W. Metcalfe, 1993
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +00005 * Alex Korobka 1995,1996
Alexandre Julliardd4719651995-12-12 18:49:11 +00006 *
Alexandre Julliarde399fc31993-11-24 17:08:56 +00007 *
8 */
9
Alexandre Julliarde399fc31993-11-24 17:08:56 +000010#include <stdlib.h>
Alexandre Julliardd4719651995-12-12 18:49:11 +000011#include "wintypes.h"
12#include "class.h"
13#include "win.h"
Alexandre Julliarde399fc31993-11-24 17:08:56 +000014#include "gdi.h"
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +000015#include "region.h"
Alexandre Julliardd4719651995-12-12 18:49:11 +000016#include "sysmetrics.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000017#include "stddebug.h"
Alexandre Julliard234bc241994-12-10 13:02:28 +000018/* #define DEBUG_SCROLL */
Alexandre Julliardaca05781994-10-17 18:12:41 +000019#include "debug.h"
20
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000021extern HWND CARET_GetHwnd(); /* windows/caret.c */
22extern void CLIPPING_UpdateGCRegion(DC* ); /* objects/clipping.c */
Alexandre Julliardd4719651995-12-12 18:49:11 +000023
Alexandre Julliarde399fc31993-11-24 17:08:56 +000024static int RgnType;
25
Alexandre Julliarde399fc31993-11-24 17:08:56 +000026/*************************************************************************
27 * ScrollWindow (USER.61)
Alexandre Julliardd4719651995-12-12 18:49:11 +000028 *
Alexandre Julliarde399fc31993-11-24 17:08:56 +000029 */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000030void ScrollWindow(HWND hwnd, short dx, short dy, LPRECT16 rect, LPRECT16 clipRect)
Alexandre Julliarde399fc31993-11-24 17:08:56 +000031{
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000032 HDC32 hdc;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +000033 HRGN hrgnUpdate,hrgnClip;
34 RECT16 rc, cliprc;
35 HWND hCaretWnd = CARET_GetHwnd();
36 WND* wndScroll = WIN_FindWndPtr( hwnd );
Alexandre Julliarde399fc31993-11-24 17:08:56 +000037
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +000038 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),
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +000040 (int)((clipRect)?clipRect->top:0),
41 (int)((clipRect)?clipRect->right:0),
42 (int)((clipRect)?clipRect->bottom:0));
Alexandre Julliarde399fc31993-11-24 17:08:56 +000043
Alexandre Julliard1e37a181996-08-18 16:21:52 +000044 if ( !wndScroll || !WIN_IsWindowDrawable( wndScroll, TRUE ) ) return;
45
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +000046 if ( !rect ) /* do not clip children */
Alexandre Julliardd4719651995-12-12 18:49:11 +000047 {
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000048 GetClientRect16(hwnd, &rc);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000049 hrgnClip = CreateRectRgnIndirect16( &rc );
Alexandre Julliardd4719651995-12-12 18:49:11 +000050
Alexandre Julliard7d654eb1996-02-25 11:36:22 +000051 if ((hCaretWnd == hwnd) || IsChild(hwnd,hCaretWnd))
52 HideCaret(hCaretWnd);
53 else hCaretWnd = 0;
54
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000055 hdc = GetDCEx32(hwnd, hrgnClip, DCX_CACHE | DCX_CLIPSIBLINGS);
Alexandre Julliardd4719651995-12-12 18:49:11 +000056 DeleteObject(hrgnClip);
57 }
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +000058 else /* clip children */
Alexandre Julliardd4719651995-12-12 18:49:11 +000059 {
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000060 GetClientRect16(hwnd,&rc);
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +000061 CopyRect16(&rc, rect);
Alexandre Julliardd4719651995-12-12 18:49:11 +000062
Alexandre Julliard7d654eb1996-02-25 11:36:22 +000063 if (hCaretWnd == hwnd) HideCaret(hCaretWnd);
64 else hCaretWnd = 0;
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +000065
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000066 hdc = GetDC32(hwnd);
Alexandre Julliardd4719651995-12-12 18:49:11 +000067 }
68
Alexandre Julliarde399fc31993-11-24 17:08:56 +000069 if (clipRect == NULL)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000070 GetClientRect16(hwnd, &cliprc);
Alexandre Julliarde399fc31993-11-24 17:08:56 +000071 else
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000072 CopyRect16(&cliprc, clipRect);
Alexandre Julliarde399fc31993-11-24 17:08:56 +000073
74 hrgnUpdate = CreateRectRgn(0, 0, 0, 0);
75 ScrollDC(hdc, dx, dy, &rc, &cliprc, hrgnUpdate, NULL);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000076 ReleaseDC32(hwnd, hdc);
Alexandre Julliardd4719651995-12-12 18:49:11 +000077
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +000078 if( !rect ) /* move child windows and update region */
79 {
80 WND* wndPtr;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +000081
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +000082 if( wndScroll->hrgnUpdate > 1 )
83 OffsetRgn( wndScroll->hrgnUpdate, dx, dy );
Alexandre Julliardd4719651995-12-12 18:49:11 +000084
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +000085 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 |
89 SWP_DEFERERASE );
90 }
91
Alexandre Julliard1e37a181996-08-18 16:21:52 +000092 PAINT_RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_ALLCHILDREN |
93 RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW, RDW_C_USEHRGN );
Alexandre Julliardd4719651995-12-12 18:49:11 +000094
95 DeleteObject(hrgnUpdate);
Alexandre Julliard7d654eb1996-02-25 11:36:22 +000096 if( hCaretWnd ) ShowCaret(hCaretWnd);
Alexandre Julliarde399fc31993-11-24 17:08:56 +000097}
98
99
100/*************************************************************************
101 * ScrollDC (USER.221)
Alexandre Julliardd4719651995-12-12 18:49:11 +0000102 *
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000103 */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000104BOOL ScrollDC(HDC hdc, short dx, short dy, LPRECT16 rc, LPRECT16 cliprc,
105 HRGN hrgnUpdate, LPRECT16 rcUpdate)
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000106{
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000107 HRGN hrgnClip = 0;
108 HRGN hrgnScrollClip = 0;
109 RECT16 rectClip;
110 POINT16 src, dest;
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000111 short width, height;
112 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
113
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000114 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 );
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000117
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000118 if ( !dc || !hdc ) return FALSE;
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000119
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000120 /* set clipping region */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000121
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000122 if ( !rc ) GetClipBox16( hdc, &rectClip );
123 else rectClip = *rc;
124
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000125 if (cliprc)
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000126 IntersectRect16(&rectClip,&rectClip,cliprc);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000127
128 if( rectClip.left >= rectClip.right || rectClip.top >= rectClip.bottom )
129 return FALSE;
130
131 hrgnClip = GetClipRgn(hdc);
132 hrgnScrollClip = CreateRectRgnIndirect16(&rectClip);
133
134 if( hrgnClip )
135 {
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000136 /* save a copy and change cliprgn directly */
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000137
138 CombineRgn( hrgnScrollClip, hrgnClip, 0, RGN_COPY );
139 SetRectRgn( hrgnClip, rectClip.left, rectClip.top, rectClip.right, rectClip.bottom );
140
141 CLIPPING_UpdateGCRegion( dc );
142 }
143 else
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000144 SelectClipRgn( hdc, hrgnScrollClip );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000145
146 /* translate coordinates */
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000147
148 if (dx > 0)
149 {
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000150 src.x = XDPTOLP(dc, rectClip.left);
151 dest.x = XDPTOLP(dc, rectClip.left + abs(dx));
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000152 }
153 else
154 {
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000155 src.x = XDPTOLP(dc, rectClip.left + abs(dx));
156 dest.x = XDPTOLP(dc, rectClip.left);
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000157 }
158 if (dy > 0)
159 {
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000160 src.y = YDPTOLP(dc, rectClip.top);
161 dest.y = YDPTOLP(dc, rectClip.top + abs(dy));
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000162 }
163 else
164 {
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000165 src.y = YDPTOLP(dc, rectClip.top + abs(dy));
166 dest.y = YDPTOLP(dc, rectClip.top);
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000167 }
168
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000169 width = rectClip.right - rectClip.left - abs(dx);
170 height = rectClip.bottom - rectClip.top - abs(dy);
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000171
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000172 /* copy bits */
173
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000174 if (!BitBlt(hdc, dest.x, dest.y, width, height, hdc, src.x, src.y,
175 SRCCOPY))
Alexandre Julliard3ed37e01994-11-07 18:20:42 +0000176 return FALSE;
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000177
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000178 /* compute update areas */
179
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000180 if (hrgnUpdate || rcUpdate)
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000181 {
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000182 HRGN hrgn1 = (hrgnUpdate)?hrgnUpdate:CreateRectRgn( 0,0,0,0 );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000183
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000184 if( dc->w.hVisRgn )
185 {
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);
191 }
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000192 else
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000193 {
194 RECT16 rect;
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000195
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000196 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 );
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000201
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000202 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 );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000206
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000207 RgnType = REGION_UnionRectWithRgn( hrgn1, &rect );
208 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000209
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000210 if (rcUpdate) GetRgnBox16( hrgn1, rcUpdate );
211 if (!hrgnUpdate) DeleteObject( hrgn1 );
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000212 }
213
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000214 /* restore clipping region */
215
216 SelectClipRgn( hdc, (hrgnClip)?hrgnScrollClip:0 );
217 DeleteObject( hrgnScrollClip );
218
Alexandre Julliard3ed37e01994-11-07 18:20:42 +0000219 return TRUE;
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000220}
221
222
223/*************************************************************************
224 * ScrollWindowEx (USER.319)
Alexandre Julliardd4719651995-12-12 18:49:11 +0000225 *
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000226 * FIXME: broken, is there a program that actually uses it?
Alexandre Julliardd4719651995-12-12 18:49:11 +0000227 *
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000228 */
229
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000230int ScrollWindowEx(HWND hwnd, short dx, short dy, LPRECT16 rect, LPRECT16 clipRect,
231 HRGN hrgnUpdate, LPRECT16 rcUpdate, WORD flags)
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000232{
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000233 HDC32 hdc;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000234 RECT16 rc, cliprc;
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000235
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000236 dprintf_scroll(stddeb,"ScrollWindowEx: dx=%d, dy=%d, wFlags=%04x\n",dx, dy, flags);
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000237
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000238 hdc = GetDC32(hwnd);
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000239
240 if (rect == NULL)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000241 GetClientRect16(hwnd, &rc);
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000242 else
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000243 CopyRect16(&rc, rect);
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000244 if (clipRect == NULL)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000245 GetClientRect16(hwnd, &cliprc);
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000246 else
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000247 CopyRect16(&cliprc, clipRect);
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000248
249 ScrollDC(hdc, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate);
250
251 if (flags | SW_INVALIDATE)
252 {
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000253 PAINT_RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
254 ((flags & SW_ERASE) ? RDW_ERASENOW : 0), 0 );
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000255 }
256
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000257 ReleaseDC32(hwnd, hdc);
Alexandre Julliarde399fc31993-11-24 17:08:56 +0000258 return RgnType;
259}