Ken Thomases : winemac: Implement ScrollDC().

Alexandre Julliard julliard at winehq.org
Tue Feb 5 13:25:25 CST 2013


Module: wine
Branch: master
Commit: 6efd198c521f341e3807c5620f5d3f30088e7386
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6efd198c521f341e3807c5620f5d3f30088e7386

Author: Ken Thomases <ken at codeweavers.com>
Date:   Sun Feb  3 17:20:03 2013 -0600

winemac: Implement ScrollDC().

---

 dlls/winemac.drv/Makefile.in      |    1 +
 dlls/winemac.drv/scroll.c         |  188 +++++++++++++++++++++++++++++++++++++
 dlls/winemac.drv/winemac.drv.spec |    1 +
 3 files changed, 190 insertions(+), 0 deletions(-)

diff --git a/dlls/winemac.drv/Makefile.in b/dlls/winemac.drv/Makefile.in
index 8484db8..c0bdbb7 100644
--- a/dlls/winemac.drv/Makefile.in
+++ b/dlls/winemac.drv/Makefile.in
@@ -8,6 +8,7 @@ C_SRCS = \
 	gdi.c \
 	macdrv_main.c \
 	mouse.c \
+	scroll.c \
 	surface.c \
 	window.c
 
diff --git a/dlls/winemac.drv/scroll.c b/dlls/winemac.drv/scroll.c
new file mode 100644
index 0000000..e8e7537
--- /dev/null
+++ b/dlls/winemac.drv/scroll.c
@@ -0,0 +1,188 @@
+/*
+ * MACDRV window/DC scrolling
+ *
+ * Copyright 1993  David W. Metcalfe
+ * Copyright 1995, 1996 Alex Korobka
+ * Copyright 2001 Alexandre Julliard
+ * Copyright 2011, 2013 Ken Thomases for CodeWeavers Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include "macdrv.h"
+#include "winuser.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(scroll);
+
+
+static void dump_region(const char *p, HRGN hrgn)
+{
+    DWORD i, size;
+    RGNDATA *data = NULL;
+    RECT *rect;
+
+    if (!hrgn)
+    {
+        TRACE("%s null region\n", p);
+        return;
+    }
+    if (!(size = GetRegionData(hrgn, 0, NULL)))
+        return;
+    if (!(data = HeapAlloc(GetProcessHeap(), 0, size))) return;
+    GetRegionData(hrgn, size, data);
+    TRACE("%s %d rects:", p, data->rdh.nCount);
+    for (i = 0, rect = (RECT *)data->Buffer; i<20 && i < data->rdh.nCount; i++, rect++)
+        TRACE(" %s", wine_dbgstr_rect(rect));
+    TRACE("\n");
+    HeapFree(GetProcessHeap(), 0, data);
+}
+
+
+/*************************************************************************
+ *              ScrollDC   (MACDRV.@)
+ */
+BOOL CDECL macdrv_ScrollDC(HDC hdc, INT dx, INT dy, const RECT *lprcScroll,
+                           const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate)
+{
+    RECT rcSrc, rcClip, offset;
+    INT dxdev, dydev, res;
+    HRGN DstRgn, clipRgn, visrgn;
+
+    TRACE("dx,dy %d,%d rcScroll %s rcClip %s hrgnUpdate %p lprcUpdate %p\n",
+          dx, dy, wine_dbgstr_rect(lprcScroll), wine_dbgstr_rect(lprcClip),
+          hrgnUpdate, lprcUpdate);
+
+    /* get the visible region */
+    visrgn = CreateRectRgn(0, 0, 0, 0);
+    GetRandomRgn(hdc, visrgn, SYSRGN);
+    if (!(GetVersion() & 0x80000000))
+    {
+        /* Window NT/2k/XP */
+        POINT org;
+        GetDCOrgEx(hdc, &org);
+        OffsetRgn(visrgn, -org.x, -org.y);
+    }
+
+    /* intersect with the clipping Region if the DC has one */
+    clipRgn = CreateRectRgn(0, 0, 0, 0);
+    if (GetClipRgn(hdc, clipRgn) != 1)
+    {
+        DeleteObject(clipRgn);
+        clipRgn = NULL;
+    }
+    else
+        CombineRgn(visrgn, visrgn, clipRgn, RGN_AND);
+
+    /* only those pixels in the scroll rectangle that remain in the clipping
+     * rect are scrolled. */
+    if (lprcClip)
+        rcClip = *lprcClip;
+    else
+        GetClipBox(hdc, &rcClip);
+    rcSrc = rcClip;
+    OffsetRect(&rcClip, -dx, -dy);
+    IntersectRect(&rcSrc, &rcSrc, &rcClip);
+
+    /* if an scroll rectangle is specified, only the pixels within that
+     * rectangle are scrolled */
+    if (lprcScroll)
+        IntersectRect(&rcSrc, &rcSrc, lprcScroll);
+
+    /* now convert to device coordinates */
+    LPtoDP(hdc, (LPPOINT)&rcSrc, 2);
+    TRACE("source rect: %s\n", wine_dbgstr_rect(&rcSrc));
+
+    /* also dx and dy */
+    SetRect(&offset, 0, 0, dx, dy);
+    LPtoDP(hdc, (LPPOINT)&offset, 2);
+    dxdev = offset.right - offset.left;
+    dydev = offset.bottom - offset.top;
+
+    /* now intersect with the visible region to get the pixels that will
+     * actually scroll */
+    DstRgn = CreateRectRgnIndirect(&rcSrc);
+    res = CombineRgn(DstRgn, DstRgn, visrgn, RGN_AND);
+
+    /* and translate, giving the destination region */
+    OffsetRgn(DstRgn, dxdev, dydev);
+    if (TRACE_ON(scroll)) dump_region("Destination scroll region: ", DstRgn);
+
+    /* if there are any, do it */
+    if (res > NULLREGION)
+    {
+        RECT rect ;
+        /* clip to the destination region, so we can BitBlt with a simple
+         * bounding rectangle */
+        if (clipRgn)
+            ExtSelectClipRgn(hdc, DstRgn, RGN_AND);
+        else
+            SelectClipRgn(hdc, DstRgn);
+        GetRgnBox(DstRgn, &rect);
+        DPtoLP(hdc, (LPPOINT)&rect, 2);
+        TRACE("destination rect: %s\n", wine_dbgstr_rect(&rect));
+
+        BitBlt(hdc, rect.left, rect.top,
+               rect.right - rect.left, rect.bottom - rect.top,
+               hdc, rect.left - dx, rect.top - dy, SRCCOPY);
+    }
+
+    /* compute the update areas.  This is the combined clip rectangle
+     * minus the scrolled region, and intersected with the visible
+     * region. */
+    if (hrgnUpdate || lprcUpdate)
+    {
+        HRGN hrgn = hrgnUpdate;
+
+        /* Intersect clip and scroll rectangles, allowing NULL values */
+        if (lprcScroll)
+            if (lprcClip)
+                IntersectRect(&rcClip, lprcClip, lprcScroll);
+            else
+                rcClip = *lprcScroll;
+        else
+            if (lprcClip)
+                rcClip = *lprcClip;
+            else
+                GetClipBox(hdc, &rcClip);
+
+        /* Convert the combined clip rectangle to device coordinates */
+        LPtoDP(hdc, (LPPOINT)&rcClip, 2);
+        if (hrgn)
+            SetRectRgn(hrgn, rcClip.left, rcClip.top, rcClip.right, rcClip.bottom);
+        else
+            hrgn = CreateRectRgnIndirect(&rcClip);
+        CombineRgn(hrgn, hrgn, visrgn, RGN_AND);
+        CombineRgn(hrgn, hrgn, DstRgn, RGN_DIFF);
+        if (TRACE_ON(scroll)) dump_region("Update region: ", hrgn);
+        if (lprcUpdate)
+        {
+            GetRgnBox(hrgn, lprcUpdate);
+            /* Put the lprcUpdate in logical coordinates */
+            DPtoLP(hdc, (LPPOINT)lprcUpdate, 2);
+            TRACE("returning lprcUpdate %s\n", wine_dbgstr_rect(lprcUpdate));
+        }
+        if (!hrgnUpdate)
+            DeleteObject(hrgn);
+    }
+
+    /* restore original clipping region */
+    SelectClipRgn(hdc, clipRgn);
+    DeleteObject(visrgn);
+    DeleteObject(DstRgn);
+    if (clipRgn) DeleteObject(clipRgn);
+    return TRUE;
+}
diff --git a/dlls/winemac.drv/winemac.drv.spec b/dlls/winemac.drv/winemac.drv.spec
index a0e1ab8..6f780ed 100644
--- a/dlls/winemac.drv/winemac.drv.spec
+++ b/dlls/winemac.drv/winemac.drv.spec
@@ -10,6 +10,7 @@
 @ cdecl EnumDisplayMonitors(long ptr ptr long) macdrv_EnumDisplayMonitors
 @ cdecl GetMonitorInfo(long ptr) macdrv_GetMonitorInfo
 @ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) macdrv_MsgWaitForMultipleObjectsEx
+@ cdecl ScrollDC(long long long ptr ptr long ptr) macdrv_ScrollDC
 @ cdecl SetFocus(long) macdrv_SetFocus
 @ cdecl SetLayeredWindowAttributes(long long long long) macdrv_SetLayeredWindowAttributes
 @ cdecl SetParent(long long long) macdrv_SetParent




More information about the wine-cvs mailing list