/*
 * 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)
{
    HDC32  	hdc;
    HRGN32 	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 ( !wndScroll || !WIN_IsWindowDrawable( wndScroll, TRUE ) ) return;

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

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

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

	  hdc = GetDC32(hwnd);
       }

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

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

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

      if( wndScroll->hrgnUpdate > 1 )
	OffsetRgn32( 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 );
    }

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

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


/*************************************************************************
 *             ScrollDC         (USER.221)
 *
 */
BOOL ScrollDC(HDC16 hdc, short dx, short dy, LPRECT16 rc, LPRECT16 cliprc,
	      HRGN32 hrgnUpdate, LPRECT16 rcUpdate)
{
    HRGN32 hrgnClip = 0;
    HRGN32 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 */

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

	CLIPPING_UpdateGCRegion( dc );
      }
    else
        SelectClipRgn16( 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)
    {
	HRGN32 hrgn1 = (hrgnUpdate) ? hrgnUpdate : CreateRectRgn32( 0,0,0,0 );

	if( dc->w.hVisRgn )
	{
	  CombineRgn32( hrgn1, dc->w.hVisRgn, 0, RGN_COPY );
	  CombineRgn32( hrgn1, hrgn1, hrgnClip ? hrgnClip : hrgnScrollClip,
                        RGN_AND );
	  OffsetRgn32( hrgn1, dx, dy );
	  CombineRgn32( hrgn1, dc->w.hVisRgn, hrgn1, RGN_DIFF );
	  RgnType = CombineRgn32( 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) DeleteObject32( hrgn1 );
    }

    /* restore clipping region */

    SelectClipRgn32( hdc, hrgnClip ? hrgnScrollClip : 0 );
    DeleteObject32( 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,
		   HRGN32 hrgnUpdate, LPRECT16 rcUpdate, WORD flags)
{
    HDC32 hdc;
    RECT16 rc, cliprc;

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

    hdc = GetDC32(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)
    {
	PAINT_RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
                        ((flags & SW_ERASE) ? RDW_ERASENOW : 0), 0 );
    }

    ReleaseDC32(hwnd, hdc);
    return RgnType;
}
