Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Scroll windows and DCs |
| 3 | * |
| 4 | * Copyright David W. Metcalfe, 1993 |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 5 | * Alex Korobka 1995,1996 |
Alexandre Julliard | d471965 | 1995-12-12 18:49:11 +0000 | [diff] [blame] | 6 | * |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 7 | * |
| 8 | */ |
| 9 | |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 10 | #include <stdlib.h> |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 11 | #include "windows.h" |
Alexandre Julliard | d471965 | 1995-12-12 18:49:11 +0000 | [diff] [blame] | 12 | #include "class.h" |
| 13 | #include "win.h" |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 14 | #include "gdi.h" |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 15 | #include "dce.h" |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 16 | #include "region.h" |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 17 | #include "graphics.h" |
Alexandre Julliard | d471965 | 1995-12-12 18:49:11 +0000 | [diff] [blame] | 18 | #include "sysmetrics.h" |
Alexandre Julliard | aca0578 | 1994-10-17 18:12:41 +0000 | [diff] [blame] | 19 | #include "debug.h" |
| 20 | |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 21 | extern HWND32 CARET_GetHwnd(); /* windows/caret.c */ |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 22 | extern void CARET_GetRect(LPRECT32); |
Alexandre Julliard | 1e9ac79 | 1996-06-06 18:38:27 +0000 | [diff] [blame] | 23 | extern void CLIPPING_UpdateGCRegion(DC* ); /* objects/clipping.c */ |
Alexandre Julliard | d471965 | 1995-12-12 18:49:11 +0000 | [diff] [blame] | 24 | |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 25 | /************************************************************************* |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 26 | * ScrollWindow16 (USER.61) |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 27 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 28 | void WINAPI ScrollWindow16(HWND16 hwnd, INT16 dx, INT16 dy, const RECT16 *rect, |
| 29 | const RECT16 *clipRect ) |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 30 | { |
| 31 | RECT32 rect32, clipRect32; |
| 32 | |
| 33 | if (rect) CONV_RECT16TO32( rect, &rect32 ); |
| 34 | if (clipRect) CONV_RECT16TO32( clipRect, &clipRect32 ); |
| 35 | ScrollWindow32( hwnd, dx, dy, rect ? &rect32 : NULL, |
| 36 | clipRect ? &clipRect32 : NULL ); |
| 37 | } |
| 38 | |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 39 | /************************************************************************* |
| 40 | * ScrollWindow32 (USER32.449) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 41 | * |
| 42 | * FIXME: verify clipping region calculations |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 43 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 44 | BOOL32 WINAPI ScrollWindow32( HWND32 hwnd, INT32 dx, INT32 dy, |
| 45 | const RECT32 *rect, const RECT32 *clipRect ) |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 46 | { |
Alexandre Julliard | 2c69f6d | 1996-09-28 18:11:01 +0000 | [diff] [blame] | 47 | HDC32 hdc; |
Alexandre Julliard | bf9130a | 1996-10-13 17:45:47 +0000 | [diff] [blame] | 48 | HRGN32 hrgnUpdate,hrgnClip; |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 49 | RECT32 rc, cliprc; |
| 50 | HWND32 hCaretWnd = CARET_GetHwnd(); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 51 | WND* wndScroll = WIN_FindWndPtr( hwnd ); |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 52 | |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame^] | 53 | TRACE(scroll,"hwnd=%04x, dx=%d, dy=%d, lpRect =%p clipRect=%i,%i,%i,%i\n", |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 54 | hwnd, dx, dy, rect, |
| 55 | clipRect ? clipRect->left : 0, |
| 56 | clipRect ? clipRect->top : 0, |
| 57 | clipRect ? clipRect->right : 0, |
| 58 | clipRect ? clipRect->bottom : 0 ); |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 59 | |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 60 | if ( !wndScroll || !WIN_IsWindowDrawable( wndScroll, TRUE ) ) return TRUE; |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 61 | |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 62 | if ( !rect ) /* do not clip children */ |
Alexandre Julliard | d471965 | 1995-12-12 18:49:11 +0000 | [diff] [blame] | 63 | { |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 64 | GetClientRect32(hwnd, &rc); |
| 65 | hrgnClip = CreateRectRgnIndirect32( &rc ); |
Alexandre Julliard | d471965 | 1995-12-12 18:49:11 +0000 | [diff] [blame] | 66 | |
Alexandre Julliard | 01d6346 | 1997-01-20 19:43:45 +0000 | [diff] [blame] | 67 | if ((hCaretWnd == hwnd) || IsChild32(hwnd,hCaretWnd)) |
Alexandre Julliard | f0cbfa0 | 1997-02-15 14:29:56 +0000 | [diff] [blame] | 68 | HideCaret32(hCaretWnd); |
Alexandre Julliard | 7d654eb | 1996-02-25 11:36:22 +0000 | [diff] [blame] | 69 | else hCaretWnd = 0; |
| 70 | |
Alexandre Julliard | 2c69f6d | 1996-09-28 18:11:01 +0000 | [diff] [blame] | 71 | hdc = GetDCEx32(hwnd, hrgnClip, DCX_CACHE | DCX_CLIPSIBLINGS); |
Alexandre Julliard | 139a4b1 | 1996-11-02 14:24:07 +0000 | [diff] [blame] | 72 | DeleteObject32( hrgnClip ); |
Alexandre Julliard | d471965 | 1995-12-12 18:49:11 +0000 | [diff] [blame] | 73 | } |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 74 | else /* clip children */ |
Alexandre Julliard | d471965 | 1995-12-12 18:49:11 +0000 | [diff] [blame] | 75 | { |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 76 | CopyRect32(&rc, rect); |
Alexandre Julliard | d471965 | 1995-12-12 18:49:11 +0000 | [diff] [blame] | 77 | |
Alexandre Julliard | f0cbfa0 | 1997-02-15 14:29:56 +0000 | [diff] [blame] | 78 | if (hCaretWnd == hwnd) HideCaret32(hCaretWnd); |
Alexandre Julliard | 7d654eb | 1996-02-25 11:36:22 +0000 | [diff] [blame] | 79 | else hCaretWnd = 0; |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 80 | |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 81 | hdc = GetDCEx32( hwnd, 0, DCX_CACHE | DCX_USESTYLE ); |
Alexandre Julliard | d471965 | 1995-12-12 18:49:11 +0000 | [diff] [blame] | 82 | } |
| 83 | |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 84 | if (clipRect == NULL) |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 85 | GetClientRect32(hwnd, &cliprc); |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 86 | else |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 87 | CopyRect32(&cliprc, clipRect); |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 88 | |
Alexandre Julliard | 139a4b1 | 1996-11-02 14:24:07 +0000 | [diff] [blame] | 89 | hrgnUpdate = CreateRectRgn32( 0, 0, 0, 0 ); |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 90 | ScrollDC32( hdc, dx, dy, &rc, &cliprc, hrgnUpdate, NULL ); |
Alexandre Julliard | 2c69f6d | 1996-09-28 18:11:01 +0000 | [diff] [blame] | 91 | ReleaseDC32(hwnd, hdc); |
Alexandre Julliard | d471965 | 1995-12-12 18:49:11 +0000 | [diff] [blame] | 92 | |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 93 | if( !rect ) /* move child windows and update region */ |
| 94 | { |
| 95 | WND* wndPtr; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 96 | |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 97 | if( wndScroll->hrgnUpdate > 1 ) |
Alexandre Julliard | 139a4b1 | 1996-11-02 14:24:07 +0000 | [diff] [blame] | 98 | OffsetRgn32( wndScroll->hrgnUpdate, dx, dy ); |
Alexandre Julliard | d471965 | 1995-12-12 18:49:11 +0000 | [diff] [blame] | 99 | |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 100 | for (wndPtr = wndScroll->child; wndPtr; wndPtr = wndPtr->next) |
Alexandre Julliard | 01d6346 | 1997-01-20 19:43:45 +0000 | [diff] [blame] | 101 | SetWindowPos32(wndPtr->hwndSelf, 0, wndPtr->rectWindow.left + dx, |
| 102 | wndPtr->rectWindow.top + dy, 0,0, SWP_NOZORDER | |
| 103 | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW | |
| 104 | SWP_DEFERERASE ); |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 105 | } |
| 106 | |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 107 | PAINT_RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_ALLCHILDREN | |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame^] | 108 | RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW, RDW_C_USEHRGN ); |
Alexandre Julliard | d471965 | 1995-12-12 18:49:11 +0000 | [diff] [blame] | 109 | |
Alexandre Julliard | 139a4b1 | 1996-11-02 14:24:07 +0000 | [diff] [blame] | 110 | DeleteObject32( hrgnUpdate ); |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 111 | if( hCaretWnd ) |
| 112 | { |
| 113 | POINT32 pt; |
| 114 | GetCaretPos32(&pt); |
| 115 | pt.x += dx; pt.y += dy; |
Alexandre Julliard | 2197901 | 1997-03-05 08:22:35 +0000 | [diff] [blame] | 116 | SetCaretPos32(pt.x, pt.y); |
Alexandre Julliard | f0cbfa0 | 1997-02-15 14:29:56 +0000 | [diff] [blame] | 117 | ShowCaret32(hCaretWnd); |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 118 | } |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 119 | return TRUE; |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | |
| 123 | /************************************************************************* |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 124 | * ScrollDC16 (USER.221) |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 125 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 126 | BOOL16 WINAPI ScrollDC16( HDC16 hdc, INT16 dx, INT16 dy, const RECT16 *rect, |
| 127 | const RECT16 *cliprc, HRGN16 hrgnUpdate, |
| 128 | LPRECT16 rcUpdate ) |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 129 | { |
| 130 | RECT32 rect32, clipRect32, rcUpdate32; |
| 131 | BOOL16 ret; |
| 132 | |
| 133 | if (rect) CONV_RECT16TO32( rect, &rect32 ); |
| 134 | if (cliprc) CONV_RECT16TO32( cliprc, &clipRect32 ); |
| 135 | ret = ScrollDC32( hdc, dx, dy, rect ? &rect32 : NULL, |
| 136 | cliprc ? &clipRect32 : NULL, hrgnUpdate, &rcUpdate32 ); |
| 137 | if (rcUpdate) CONV_RECT32TO16( &rcUpdate32, rcUpdate ); |
| 138 | return ret; |
| 139 | } |
| 140 | |
| 141 | |
| 142 | /************************************************************************* |
| 143 | * ScrollDC32 (USER32.448) |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 144 | * |
Alexandre Julliard | 03468f7 | 1998-02-15 19:40:49 +0000 | [diff] [blame] | 145 | * Both 'rc' and 'prLClip' are in logical units but update info is |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 146 | * returned in device coordinates. |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 147 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 148 | BOOL32 WINAPI ScrollDC32( HDC32 hdc, INT32 dx, INT32 dy, const RECT32 *rc, |
| 149 | const RECT32 *prLClip, HRGN32 hrgnUpdate, |
| 150 | LPRECT32 rcUpdate ) |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 151 | { |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 152 | RECT32 rDClip, rLClip; |
Alexandre Julliard | bf9130a | 1996-10-13 17:45:47 +0000 | [diff] [blame] | 153 | HRGN32 hrgnClip = 0; |
| 154 | HRGN32 hrgnScrollClip = 0; |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 155 | POINT32 src, dest; |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 156 | INT32 ldx, ldy; |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 157 | DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC); |
| 158 | |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame^] | 159 | TRACE(scroll,"%04x %d,%d hrgnUpdate=%04x rcUpdate = %p cliprc = (%d,%d-%d,%d), rc=(%d,%d-%d,%d)\n", |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 160 | (HDC16)hdc, dx, dy, hrgnUpdate, rcUpdate, |
| 161 | prLClip ? prLClip->left : 0, prLClip ? prLClip->top : 0, prLClip ? prLClip->right : 0, prLClip ? prLClip->bottom : 0, |
| 162 | rc ? rc->left : 0, rc ? rc->top : 0, rc ? rc->right : 0, rc ? rc->bottom : 0 ); |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 163 | |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 164 | if ( !dc || !hdc ) return FALSE; |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 165 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 166 | /* |
| 167 | printf(stddeb,"\t[wndOrgX=%i, wndExtX=%i, vportOrgX=%i, vportExtX=%i]\n", |
| 168 | dc->wndOrgX, dc->wndExtX, dc->vportOrgX, dc->vportExtX ); |
| 169 | printf(stddeb,"\t[wndOrgY=%i, wndExtY=%i, vportOrgY=%i, vportExtY=%i]\n", |
| 170 | dc->wndOrgY, dc->wndExtY, dc->vportOrgY, dc->vportExtY ); |
| 171 | */ |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 172 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 173 | /* compute device clipping region */ |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 174 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 175 | if ( rc ) |
| 176 | { |
| 177 | rLClip = *rc; |
| 178 | rDClip.left = XLPTODP(dc, rc->left); rDClip.right = XLPTODP(dc, rc->right); |
| 179 | rDClip.top = YLPTODP(dc, rc->top); rDClip.bottom = YLPTODP(dc, rc->bottom); |
| 180 | } |
| 181 | else /* maybe we should just return FALSE? */ |
| 182 | { |
| 183 | GetClipBox32( hdc, &rDClip ); |
| 184 | rLClip.left = XDPTOLP(dc, rDClip.left); rLClip.right = XDPTOLP(dc, rDClip.right); |
| 185 | rLClip.top = YDPTOLP(dc, rDClip.top); rLClip.bottom = YDPTOLP(dc, rDClip.bottom); |
| 186 | } |
Alexandre Julliard | 1e9ac79 | 1996-06-06 18:38:27 +0000 | [diff] [blame] | 187 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 188 | if (prLClip) |
| 189 | { |
| 190 | RECT32 r; |
| 191 | |
| 192 | r.left = XLPTODP(dc, prLClip->left); r.right = XLPTODP(dc, prLClip->right); |
| 193 | r.top = YLPTODP(dc, prLClip->top); r.bottom = YLPTODP(dc, prLClip->bottom); |
| 194 | IntersectRect32(&rLClip,&rLClip,prLClip); |
| 195 | IntersectRect32(&rDClip,&rDClip,&r); |
| 196 | } |
| 197 | |
| 198 | if( rDClip.left >= rDClip.right || rDClip.top >= rDClip.bottom ) |
Alexandre Julliard | 1e9ac79 | 1996-06-06 18:38:27 +0000 | [diff] [blame] | 199 | return FALSE; |
| 200 | |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 201 | hrgnClip = GetClipRgn16(hdc); |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 202 | hrgnScrollClip = CreateRectRgnIndirect32(&rDClip); |
Alexandre Julliard | 1e9ac79 | 1996-06-06 18:38:27 +0000 | [diff] [blame] | 203 | |
| 204 | if( hrgnClip ) |
| 205 | { |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 206 | /* change device clipping region directly */ |
Alexandre Julliard | 1e9ac79 | 1996-06-06 18:38:27 +0000 | [diff] [blame] | 207 | |
Alexandre Julliard | 139a4b1 | 1996-11-02 14:24:07 +0000 | [diff] [blame] | 208 | CombineRgn32( hrgnScrollClip, hrgnClip, 0, RGN_COPY ); |
Alexandre Julliard | 2197901 | 1997-03-05 08:22:35 +0000 | [diff] [blame] | 209 | SetRectRgn32( hrgnClip, rDClip.left, rDClip.top, |
| 210 | rDClip.right, rDClip.bottom ); |
Alexandre Julliard | 1e9ac79 | 1996-06-06 18:38:27 +0000 | [diff] [blame] | 211 | |
| 212 | CLIPPING_UpdateGCRegion( dc ); |
| 213 | } |
| 214 | else |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 215 | SelectClipRgn32( hdc, hrgnScrollClip ); |
Alexandre Julliard | 1e9ac79 | 1996-06-06 18:38:27 +0000 | [diff] [blame] | 216 | |
| 217 | /* translate coordinates */ |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 218 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 219 | ldx = dx * dc->wndExtX / dc->vportExtX; |
| 220 | ldy = dy * dc->wndExtY / dc->vportExtY; |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 221 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 222 | if (dx > 0) |
| 223 | dest.x = (src.x = rLClip.left) + ldx; |
| 224 | else |
| 225 | src.x = (dest.x = rLClip.left) - ldx; |
| 226 | |
| 227 | if (dy > 0) |
| 228 | dest.y = (src.y = rLClip.top) + ldy; |
| 229 | else |
| 230 | src.y = (dest.y = rLClip.top) - ldy; |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 231 | |
Alexandre Julliard | 1e9ac79 | 1996-06-06 18:38:27 +0000 | [diff] [blame] | 232 | /* copy bits */ |
| 233 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 234 | if( rDClip.right - rDClip.left > dx && |
| 235 | rDClip.bottom - rDClip.top > dy ) |
| 236 | { |
| 237 | ldx = rLClip.right - rLClip.left - ldx; |
| 238 | ldy = rLClip.bottom - rLClip.top - ldy; |
| 239 | |
| 240 | if (!BitBlt32( hdc, dest.x, dest.y, ldx, ldy, |
| 241 | hdc, src.x, src.y, SRCCOPY)) |
| 242 | return FALSE; |
| 243 | } |
| 244 | |
| 245 | /* restore clipping region */ |
| 246 | |
| 247 | if( hrgnClip ) |
| 248 | { |
| 249 | CombineRgn32( hrgnClip, hrgnScrollClip, 0, RGN_COPY ); |
| 250 | CLIPPING_UpdateGCRegion( dc ); |
Alexandre Julliard | 2197901 | 1997-03-05 08:22:35 +0000 | [diff] [blame] | 251 | SetRectRgn32( hrgnScrollClip, rDClip.left, rDClip.top, |
| 252 | rDClip.right, rDClip.bottom ); |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 253 | } |
| 254 | else |
| 255 | SelectClipRgn32( hdc, 0 ); |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 256 | |
Alexandre Julliard | 1e9ac79 | 1996-06-06 18:38:27 +0000 | [diff] [blame] | 257 | /* compute update areas */ |
| 258 | |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 259 | if (hrgnUpdate || rcUpdate) |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 260 | { |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 261 | HRGN32 hrgn = (hrgnUpdate) ? hrgnUpdate : CreateRectRgn32( 0,0,0,0 ); |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 262 | |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 263 | if( dc->w.hVisRgn ) |
| 264 | { |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 265 | CombineRgn32( hrgn, dc->w.hVisRgn, hrgnScrollClip, RGN_AND ); |
| 266 | OffsetRgn32( hrgn, dx, dy ); |
| 267 | CombineRgn32( hrgn, dc->w.hVisRgn, hrgn, RGN_DIFF ); |
| 268 | CombineRgn32( hrgn, hrgn, hrgnScrollClip, RGN_AND ); |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 269 | } |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 270 | else |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 271 | { |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 272 | RECT32 rect; |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 273 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 274 | rect = rDClip; /* vertical band */ |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 275 | if (dx > 0) rect.right = rect.left + dx; |
| 276 | else if (dx < 0) rect.left = rect.right + dx; |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 277 | else SetRectEmpty32( &rect ); |
Alexandre Julliard | 2197901 | 1997-03-05 08:22:35 +0000 | [diff] [blame] | 278 | SetRectRgn32( hrgn, rect.left, rect.top, rect.right, rect.bottom ); |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 279 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 280 | rect = rDClip; /* horizontal band */ |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 281 | if (dy > 0) rect.bottom = rect.top + dy; |
| 282 | else if (dy < 0) rect.top = rect.bottom + dy; |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 283 | else SetRectEmpty32( &rect ); |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 284 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 285 | REGION_UnionRectWithRgn( hrgn, &rect ); |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 286 | } |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 287 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 288 | if (rcUpdate) GetRgnBox32( hrgn, rcUpdate ); |
| 289 | if (!hrgnUpdate) DeleteObject32( hrgn ); |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 290 | } |
| 291 | |
Alexandre Julliard | 139a4b1 | 1996-11-02 14:24:07 +0000 | [diff] [blame] | 292 | DeleteObject32( hrgnScrollClip ); |
Alexandre Julliard | 3ed37e0 | 1994-11-07 18:20:42 +0000 | [diff] [blame] | 293 | return TRUE; |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 294 | } |
| 295 | |
| 296 | |
| 297 | /************************************************************************* |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 298 | * ScrollWindowEx16 (USER.319) |
| 299 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 300 | INT16 WINAPI ScrollWindowEx16( HWND16 hwnd, INT16 dx, INT16 dy, |
| 301 | const RECT16 *rect, const RECT16 *clipRect, |
| 302 | HRGN16 hrgnUpdate, LPRECT16 rcUpdate, |
| 303 | UINT16 flags ) |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 304 | { |
| 305 | RECT32 rect32, clipRect32, rcUpdate32; |
| 306 | BOOL16 ret; |
| 307 | |
| 308 | if (rect) CONV_RECT16TO32( rect, &rect32 ); |
| 309 | if (clipRect) CONV_RECT16TO32( clipRect, &clipRect32 ); |
| 310 | ret = ScrollWindowEx32( hwnd, dx, dy, rect ? &rect32 : NULL, |
| 311 | clipRect ? &clipRect32 : NULL, hrgnUpdate, |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 312 | (rcUpdate) ? &rcUpdate32 : NULL, flags ); |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 313 | if (rcUpdate) CONV_RECT32TO16( &rcUpdate32, rcUpdate ); |
| 314 | return ret; |
| 315 | } |
| 316 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 317 | /************************************************************************* |
| 318 | * SCROLL_FixCaret |
| 319 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 320 | static BOOL32 SCROLL_FixCaret(HWND32 hWnd, LPRECT32 lprc, UINT32 flags) |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 321 | { |
| 322 | HWND32 hCaret = CARET_GetHwnd(); |
| 323 | |
| 324 | if( hCaret ) |
| 325 | { |
| 326 | RECT32 rc; |
| 327 | CARET_GetRect( &rc ); |
| 328 | if( hCaret == hWnd || |
Alexandre Julliard | 01d6346 | 1997-01-20 19:43:45 +0000 | [diff] [blame] | 329 | (flags & SW_SCROLLCHILDREN && IsChild32(hWnd, hCaret)) ) |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 330 | { |
| 331 | POINT32 pt; |
| 332 | |
| 333 | pt.x = rc.left; pt.y = rc.top; |
| 334 | MapWindowPoints32( hCaret, hWnd, (LPPOINT32)&rc, 2 ); |
| 335 | if( IntersectRect32(lprc, lprc, &rc) ) |
| 336 | { |
Alexandre Julliard | f0cbfa0 | 1997-02-15 14:29:56 +0000 | [diff] [blame] | 337 | HideCaret32(0); |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 338 | lprc->left = pt.x; lprc->top = pt.y; |
| 339 | return TRUE; |
| 340 | } |
| 341 | } |
| 342 | } |
| 343 | return FALSE; |
| 344 | } |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 345 | |
| 346 | /************************************************************************* |
| 347 | * ScrollWindowEx32 (USER32.450) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 348 | * |
| 349 | * NOTE: Use this function instead of ScrollWindow32 |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 350 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 351 | INT32 WINAPI ScrollWindowEx32( HWND32 hwnd, INT32 dx, INT32 dy, |
| 352 | const RECT32 *rect, const RECT32 *clipRect, |
| 353 | HRGN32 hrgnUpdate, LPRECT32 rcUpdate, |
| 354 | UINT32 flags ) |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 355 | { |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 356 | INT32 retVal = NULLREGION; |
| 357 | BOOL32 bCaret = FALSE, bOwnRgn = TRUE; |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 358 | RECT32 rc, cliprc; |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 359 | WND* wnd = WIN_FindWndPtr( hwnd ); |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 360 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 361 | if( !wnd || !WIN_IsWindowDrawable( wnd, TRUE )) return ERROR; |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 362 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 363 | if (rect == NULL) GetClientRect32(hwnd, &rc); |
| 364 | else rc = *rect; |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 365 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 366 | if (clipRect) IntersectRect32(&cliprc,&rc,clipRect); |
| 367 | else cliprc = rc; |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 368 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 369 | if (!IsRectEmpty32(&cliprc) && (dx || dy)) |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 370 | { |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 371 | DC* dc; |
| 372 | HDC32 hDC; |
| 373 | BOOL32 bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE)); |
| 374 | HRGN32 hrgnClip = CreateRectRgnIndirect32(&cliprc); |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 375 | |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame^] | 376 | TRACE(scroll,"%04x, %d,%d hrgnUpdate=%04x rcUpdate = %p \ |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 377 | cliprc = (%d,%d-%d,%d), rc=(%d,%d-%d,%d) %04x\n", |
| 378 | (HWND16)hwnd, dx, dy, hrgnUpdate, rcUpdate, |
| 379 | clipRect?clipRect->left:0, clipRect?clipRect->top:0, clipRect?clipRect->right:0, clipRect?clipRect->bottom:0, |
| 380 | rect?rect->left:0, rect?rect->top:0, rect ?rect->right:0, rect ?rect->bottom:0, (UINT16)flags ); |
| 381 | |
| 382 | rc = cliprc; |
| 383 | bCaret = SCROLL_FixCaret(hwnd, &rc, flags); |
| 384 | |
| 385 | if( hrgnUpdate ) bOwnRgn = FALSE; |
| 386 | else if( bUpdate ) hrgnUpdate = CreateRectRgn32( 0, 0, 0, 0 ); |
| 387 | |
| 388 | hDC = GetDCEx32( hwnd, hrgnClip, DCX_CACHE | DCX_USESTYLE | |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 389 | ((flags & SW_SCROLLCHILDREN) ? DCX_NOCLIPCHILDREN : 0) ); |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 390 | if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) ) |
| 391 | { |
| 392 | POINT32 dst, src; |
| 393 | |
| 394 | if( dx > 0 ) dst.x = (src.x = dc->w.DCOrgX + cliprc.left) + dx; |
| 395 | else src.x = (dst.x = dc->w.DCOrgX + cliprc.left) - dx; |
| 396 | |
| 397 | if( dy > 0 ) dst.y = (src.y = dc->w.DCOrgY + cliprc.top) + dy; |
| 398 | else src.y = (dst.y = dc->w.DCOrgY + cliprc.top) - dy; |
| 399 | |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 400 | if( bUpdate ) /* handles non-Wine windows hanging over the scrolled area */ |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 401 | TSXSetGraphicsExposures( display, dc->u.x.gc, True ); |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 402 | |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 403 | TSXSetFunction( display, dc->u.x.gc, GXcopy ); |
| 404 | TSXCopyArea( display, dc->u.x.drawable, dc->u.x.drawable, dc->u.x.gc, |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 405 | src.x, src.y, cliprc.right - cliprc.left - abs(dx), |
| 406 | cliprc.bottom - cliprc.top - abs(dy), dst.x, dst.y ); |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 407 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 408 | if( bUpdate ) |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 409 | TSXSetGraphicsExposures( display, dc->u.x.gc, False ); |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 410 | |
| 411 | if( dc->w.hVisRgn && bUpdate ) |
| 412 | { |
| 413 | CombineRgn32( hrgnUpdate, dc->w.hVisRgn, hrgnClip, RGN_AND ); |
| 414 | OffsetRgn32( hrgnUpdate, dx, dy ); |
| 415 | CombineRgn32( hrgnUpdate, dc->w.hVisRgn, hrgnUpdate, RGN_DIFF ); |
| 416 | CombineRgn32( hrgnUpdate, hrgnUpdate, hrgnClip, RGN_AND ); |
| 417 | |
| 418 | if( rcUpdate ) GetRgnBox32( hrgnUpdate, rcUpdate ); |
| 419 | } |
| 420 | ReleaseDC32(hwnd, hDC); |
| 421 | } |
| 422 | |
| 423 | if( wnd->hrgnUpdate > 1 ) |
| 424 | { |
| 425 | if( rect || clipRect ) |
| 426 | { |
| 427 | if( (CombineRgn32( hrgnClip, hrgnClip, |
| 428 | wnd->hrgnUpdate, RGN_AND ) != NULLREGION) ) |
| 429 | { |
| 430 | CombineRgn32( wnd->hrgnUpdate, wnd->hrgnUpdate, hrgnClip, RGN_DIFF ); |
| 431 | OffsetRgn32( hrgnClip, dx, dy ); |
| 432 | CombineRgn32( wnd->hrgnUpdate, wnd->hrgnUpdate, hrgnClip, RGN_OR ); |
| 433 | } |
| 434 | } |
| 435 | else |
| 436 | OffsetRgn32( wnd->hrgnUpdate, dx, dy ); |
| 437 | } |
| 438 | |
| 439 | if( flags & SW_SCROLLCHILDREN ) |
| 440 | { |
| 441 | RECT32 r; |
| 442 | WND* w; |
| 443 | for( w = wnd->child; w; w = w->next ) |
| 444 | { |
| 445 | CONV_RECT16TO32( &w->rectWindow, &r ); |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 446 | if( !clipRect || IntersectRect32(&r, &r, &cliprc) ) |
Alexandre Julliard | 01d6346 | 1997-01-20 19:43:45 +0000 | [diff] [blame] | 447 | SetWindowPos32(w->hwndSelf, 0, w->rectWindow.left + dx, |
| 448 | w->rectWindow.top + dy, 0,0, SWP_NOZORDER | |
| 449 | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW | |
| 450 | SWP_DEFERERASE ); |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 451 | } |
| 452 | } |
| 453 | |
| 454 | if( flags & (SW_INVALIDATE | SW_ERASE) ) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 455 | PAINT_RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE | |
| 456 | ((flags & SW_ERASE) ? RDW_ERASENOW : 0) | ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0 ), 0 ); |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 457 | |
| 458 | if( bCaret ) |
| 459 | { |
Alexandre Julliard | 2197901 | 1997-03-05 08:22:35 +0000 | [diff] [blame] | 460 | SetCaretPos32( rc.left + dx, rc.top + dy ); |
Alexandre Julliard | f0cbfa0 | 1997-02-15 14:29:56 +0000 | [diff] [blame] | 461 | ShowCaret32(0); |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 462 | } |
| 463 | |
| 464 | if( bOwnRgn && hrgnUpdate ) DeleteObject32( hrgnUpdate ); |
| 465 | DeleteObject32( hrgnClip ); |
| 466 | } |
| 467 | return retVal; |
Alexandre Julliard | e399fc3 | 1993-11-24 17:08:56 +0000 | [diff] [blame] | 468 | } |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 469 | |