/*
 * Scroll windows and DCs
 *
 * Copyright 1993  David W. Metcalfe
 * Copyright 1995, 1996 Alex Korobka
 * Copyright 2001 Alexandre Julliard
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "config.h"

#include <stdarg.h>
#include <X11/Xlib.h>

#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"

#include "x11drv.h"
#include "wine/debug.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 %ld 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   (X11DRV.@)
 */
BOOL X11DRV_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;
    INT code = X11DRV_START_EXPOSURES;

    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);
    /* enable X-exposure events */
    if (hrgnUpdate || lprcUpdate)
        ExtEscape( hdc, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, 0, NULL );
    /* 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;
        HRGN ExpRgn = 0;

        /* collect all the exposures */
        code = X11DRV_END_EXPOSURES;
        ExtEscape( hdc, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code,
                sizeof(ExpRgn), (LPSTR)&ExpRgn );
        /* 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);
        /* add the exposures to this */
        if( ExpRgn) {
            if( TRACE_ON( scroll)) dump_region( "Expose region: ", ExpRgn);
            CombineRgn( hrgn, hrgn, ExpRgn, RGN_OR);
            DeleteObject( ExpRgn);
        }
        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;
}
