/*
 * Scroll windows and DCs
 *
 * Copyright  David W. Metcalfe, 1993
 *	      Alex Korobka       1995,1996
 *
 *
 */

#include <stdlib.h>
#include "wintypes.h"
#include "class.h"
#include "win.h"
#include "gdi.h"
#include "region.h"
#include "sysmetrics.h"
#include "stddebug.h"
/* #define DEBUG_SCROLL */
#include "debug.h"

extern HWND CARET_GetHwnd();			/* windows/caret.c */
extern void CLIPPING_UpdateGCRegion(DC* );	/* objects/clipping.c */

static int RgnType;

/*************************************************************************
 *             ScrollWindow         (USER.61)
 *
 */
void ScrollWindow(HWND hwnd, short dx, short dy, LPRECT16 rect, LPRECT16 clipRect)
{
    HDC  	hdc;
    HRGN 	hrgnUpdate,hrgnClip;
    RECT16 	rc, cliprc;
    HWND 	hCaretWnd = CARET_GetHwnd();
    WND*	wndScroll = WIN_FindWndPtr( hwnd );

    dprintf_scroll(stddeb,"ScrollWindow: hwnd=%04x, dx=%d, dy=%d, lpRect =%08lx clipRect=%i,%i,%i,%i\n", 
	    hwnd, dx, dy, (LONG)rect, (int)((clipRect)?clipRect->left:0),
                                (int)((clipRect)?clipRect->top:0),
                                (int)((clipRect)?clipRect->right:0), 
                                (int)((clipRect)?clipRect->bottom:0));

    if ( !rect ) /* do not clip children */
       {
	  GetClientRect16(hwnd, &rc);
	  hrgnClip = CreateRectRgnIndirect16( &rc );

          if ((hCaretWnd == hwnd) || IsChild(hwnd,hCaretWnd))
              HideCaret(hCaretWnd);
          else hCaretWnd = 0;
 
	  hdc      = GetDCEx(hwnd, hrgnClip, DCX_CACHE | DCX_CLIPSIBLINGS);
          DeleteObject(hrgnClip);
       }
    else	/* clip children */
       {
	  GetClientRect16(hwnd,&rc);
	  CopyRect16(&rc, rect);

          if (hCaretWnd == hwnd) HideCaret(hCaretWnd);
          else hCaretWnd = 0;

	  hdc = GetDC(hwnd);
       }

    if (clipRect == NULL)
	GetClientRect16(hwnd, &cliprc);
    else
	CopyRect16(&cliprc, clipRect);

    hrgnUpdate = CreateRectRgn(0, 0, 0, 0);
    ScrollDC(hdc, dx, dy, &rc, &cliprc, hrgnUpdate, NULL);
    ReleaseDC(hwnd, hdc);

    if( !rect )		/* move child windows and update region */
    { 
      WND*	wndPtr;

      if( wndScroll->hrgnUpdate > 1 )
	OffsetRgn( wndScroll->hrgnUpdate, dx, dy );

      for (wndPtr = wndScroll->child; wndPtr; wndPtr = wndPtr->next)
        SetWindowPos(wndPtr->hwndSelf, 0, wndPtr->rectWindow.left + dx,
                     wndPtr->rectWindow.top  + dy, 0,0, SWP_NOZORDER |
                     SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW |
                     SWP_DEFERERASE );
    }

    /* RDW_ALLCHILDREN is to account for dialog controls */

    RedrawWindow32( hwnd, NULL, hrgnUpdate, RDW_ALLCHILDREN |
					    RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW);

    DeleteObject(hrgnUpdate);
    if( hCaretWnd ) ShowCaret(hCaretWnd);
}


/*************************************************************************
 *             ScrollDC         (USER.221)
 *
 */
BOOL ScrollDC(HDC hdc, short dx, short dy, LPRECT16 rc, LPRECT16 cliprc,
	      HRGN hrgnUpdate, LPRECT16 rcUpdate)
{
    HRGN        hrgnClip 	= 0;
    HRGN 	hrgnScrollClip  = 0;
    RECT16	rectClip;
    POINT16 	src, dest;
    short width, height;
    DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);

    dprintf_scroll(stddeb,"ScrollDC: dx=%d dy=%d, hrgnUpdate=%04x rcUpdate = %p cliprc = %p, rc=%d %d %d %d\n",
                   dx, dy, hrgnUpdate, rcUpdate, cliprc, rc ? rc->left : 0,
                   rc ? rc->top : 0, rc ? rc->right : 0, rc ? rc->bottom : 0 );

    if ( !dc || !hdc ) return FALSE;

    /* set clipping region */

    if ( !rc ) GetClipBox16( hdc, &rectClip );
    else rectClip = *rc;

    if (cliprc)
	IntersectRect16(&rectClip,&rectClip,cliprc);

    if( rectClip.left >= rectClip.right || rectClip.top >= rectClip.bottom )
	return FALSE;
    
    hrgnClip = GetClipRgn(hdc);
    hrgnScrollClip = CreateRectRgnIndirect16(&rectClip);

    if( hrgnClip )
      {
        /* save a copy and change cliprgn directly */

        CombineRgn( hrgnScrollClip, hrgnClip, 0, RGN_COPY );
        SetRectRgn( hrgnClip, rectClip.left, rectClip.top, rectClip.right, rectClip.bottom );

	CLIPPING_UpdateGCRegion( dc );
      }
    else
        SelectClipRgn( hdc, hrgnScrollClip );

    /* translate coordinates */

    if (dx > 0)
    {
	src.x = XDPTOLP(dc, rectClip.left);
	dest.x = XDPTOLP(dc, rectClip.left + abs(dx));
    }
    else
    {
	src.x = XDPTOLP(dc, rectClip.left + abs(dx));
	dest.x = XDPTOLP(dc, rectClip.left);
    }
    if (dy > 0)
    {
	src.y = YDPTOLP(dc, rectClip.top);
	dest.y = YDPTOLP(dc, rectClip.top + abs(dy));
    }
    else
    {
	src.y = YDPTOLP(dc, rectClip.top + abs(dy));
	dest.y = YDPTOLP(dc, rectClip.top);
    }

    width = rectClip.right - rectClip.left - abs(dx);
    height = rectClip.bottom - rectClip.top - abs(dy);

    /* copy bits */

    if (!BitBlt(hdc, dest.x, dest.y, width, height, hdc, src.x, src.y, 
		SRCCOPY))
	return FALSE;

    /* compute update areas */

    if (hrgnUpdate || rcUpdate)
    {
	HRGN   hrgn1 = (hrgnUpdate)?hrgnUpdate:CreateRectRgn( 0,0,0,0 );

	if( dc->w.hVisRgn )
	{
	  CombineRgn( hrgn1, dc->w.hVisRgn, 0, RGN_COPY);
	  CombineRgn( hrgn1, hrgn1, (hrgnClip)?hrgnClip:hrgnScrollClip, RGN_AND);
	  OffsetRgn( hrgn1, dx, dy );
	  CombineRgn( hrgn1, dc->w.hVisRgn, hrgn1, RGN_DIFF);
	  RgnType = CombineRgn( hrgn1, hrgn1, (hrgnClip)?hrgnClip:hrgnScrollClip, RGN_AND);
	}
	else
	{
	  RECT16	rect;

          rect = rectClip;				/* vertical band */
          if (dx > 0) rect.right = rect.left + dx;
          else if (dx < 0) rect.left = rect.right + dx;
          else SetRectEmpty16( &rect );
          SetRectRgn( hrgn1, rect.left, rect.top, rect.right, rect.bottom );

          rect = rectClip;				/* horizontal band */
          if (dy > 0) rect.bottom = rect.top + dy;
          else if (dy < 0) rect.top = rect.bottom + dy;
          else SetRectEmpty16( &rect );

          RgnType = REGION_UnionRectWithRgn( hrgn1, &rect );
	}

	if (rcUpdate) GetRgnBox16( hrgn1, rcUpdate );
	if (!hrgnUpdate) DeleteObject( hrgn1 );
    }

    /* restore clipping region */

    SelectClipRgn( hdc, (hrgnClip)?hrgnScrollClip:0 );
    DeleteObject( hrgnScrollClip );     

    return TRUE;
}


/*************************************************************************
 *             ScrollWindowEx       (USER.319)
 *
 * FIXME: broken, is there a program that actually uses it?
 *
 */

int ScrollWindowEx(HWND hwnd, short dx, short dy, LPRECT16 rect, LPRECT16 clipRect,
		   HRGN hrgnUpdate, LPRECT16 rcUpdate, WORD flags)
{
    HDC hdc;
    RECT16 rc, cliprc;

    dprintf_scroll(stddeb,"ScrollWindowEx: dx=%d, dy=%d, wFlags=%04x\n",dx, dy, flags);

    hdc = GetDC(hwnd);

    if (rect == NULL)
	GetClientRect16(hwnd, &rc);
    else
	CopyRect16(&rc, rect);
    if (clipRect == NULL)
	GetClientRect16(hwnd, &cliprc);
    else
	CopyRect16(&cliprc, clipRect);

    ScrollDC(hdc, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate);

    if (flags | SW_INVALIDATE)
    {
	RedrawWindow32( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
                        ((flags & SW_ERASE) ? RDW_ERASENOW : 0));
    }

    ReleaseDC(hwnd, hdc);
    return RgnType;
}
