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

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



extern HRGN DCE_GetVisRgn(HWND, WORD);
extern HWND CARET_GetHwnd();

static int RgnType;


/* -----------------------------------------------------------------------
 *	       SCROLL_TraceChildren
 * 
 * Returns a region invalidated by children, siblings, and/or ansectors
 * in the window rectangle or client rectangle
 *
 * dcx can have DCX_WINDOW, DCX_CLIPCHILDREN, DCX_CLIPSIBLINGS set
 */

HRGN	SCROLL_TraceChildren( HWND hScroll, short dx, short dy, WORD dcx)
{
 WND	       *wndScroll = WIN_FindWndPtr( hScroll ); 
 HRGN		hRgnWnd;
 HRGN		hUpdateRgn,hCombineRgn;

 if( !wndScroll || ( !dx && !dy) ) return 0;

 if( dcx & DCX_WINDOW )
	 hRgnWnd   = CreateRectRgnIndirect(&wndScroll->rectWindow);
 else
	{
	 RECT rect;

	 GetClientRect(hScroll,&rect);
 	 hRgnWnd   = CreateRectRgnIndirect(&rect);
	}

 hUpdateRgn  = DCE_GetVisRgn( hScroll, dcx );
 hCombineRgn = CreateRectRgn(0,0,0,0);

 if( !hUpdateRgn || !hCombineRgn )
      {
	DeleteObject( hUpdateRgn? hUpdateRgn : hCombineRgn);
	DeleteObject(hRgnWnd);
	return 0;
      }

 OffsetRgn( hUpdateRgn, dx, dy);
 CombineRgn(hCombineRgn, hRgnWnd, hUpdateRgn, RGN_DIFF);
 
 DeleteObject(hRgnWnd);
 DeleteObject(hUpdateRgn);

 return hCombineRgn;
}


/* ----------------------------------------------------------------------
 *	       SCROLL_ScrollChildren
 */
BOOL	SCROLL_ScrollChildren( HWND hScroll, short dx, short dy)
{
 WND           *wndPtr = WIN_FindWndPtr(hScroll);
 HWND		hWnd   = wndPtr->hwndChild;
 HRGN		hUpdateRgn;
 BOOL		b = 0;

 if( !wndPtr || ( !dx && !dy )) return 0;

 dprintf_scroll(stddeb,"SCROLL_ScrollChildren: hwnd "NPFMT" dx=%i dy=%i\n",hScroll,dx,dy);

 /* get a region in client rect invalidated by siblings and ansectors */
 hUpdateRgn = SCROLL_TraceChildren(hScroll, dx , dy, DCX_CLIPSIBLINGS);

 /* update children coordinates */
 while( hWnd )
  {
	wndPtr = WIN_FindWndPtr( hWnd );

	/* we can check if window intersects with clipRect parameter
	 * and do not move it if not - just a thought.     - AK
	 */

	SetWindowPos(hWnd,0,wndPtr->rectWindow.left + dx,
			    wndPtr->rectWindow.top  + dy, 0,0, SWP_NOZORDER |
			    SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW |
			    SWP_DEFERERASE );

	hWnd = wndPtr->hwndNext;
  } 

 /* invalidate uncovered region and paint frames */
 b = RedrawWindow( hScroll, NULL, hUpdateRgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
				              RDW_ERASENOW | RDW_ALLCHILDREN ); 

 DeleteObject( hUpdateRgn);
 return b;
}


/*************************************************************************
 *             ScrollWindow         (USER.61)
 *
 * FIXME: a bit broken
 */

void ScrollWindow(HWND hwnd, short dx, short dy, LPRECT rect, LPRECT clipRect)
{
    HDC  hdc;
    HRGN hrgnUpdate,hrgnClip;
    RECT rc, cliprc;
    HWND hCaretWnd = CARET_GetHwnd();

    dprintf_scroll(stddeb,"ScrollWindow: dx=%d, dy=%d, lpRect =%08lx clipRect=%i,%i,%i,%i\n", 
	    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 is NULL children have to be moved */
    if ( !rect )
       {
	GetClientRect(hwnd, &rc);
	  hrgnClip = CreateRectRgnIndirect( &rc );

          if ((hCaretWnd == hwnd) || IsChild(hwnd,hCaretWnd))
              HideCaret(hCaretWnd);
          else hCaretWnd = 0;
 
	  /* children will be Blt'ed too */
	  hdc      = GetDCEx(hwnd, hrgnClip, DCX_CACHE | DCX_CLIPSIBLINGS);
          DeleteObject(hrgnClip);
       }
    else
       {
	  GetClientRect(hwnd,&rc);
	  dprintf_scroll(stddeb,"\trect=%i %i %i %i client=%i %i %i %i\n",
			 (int)rect->left,(int)rect->top,(int)rect->right,
			 (int)rect->bottom,(int)rc.left,(int)rc.top,
			 (int)rc.right,(int)rc.bottom);

          if (hCaretWnd == hwnd) HideCaret(hCaretWnd);
          else hCaretWnd = 0;
          CopyRect(&rc, rect);
	  hdc = GetDC(hwnd);
       }

    if (clipRect == NULL)
	GetClientRect(hwnd, &cliprc);
    else
	CopyRect(&cliprc, clipRect);

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

    if( !rect )
      {
         /* FIXME: this doesn't take into account hrgnUpdate */
         if( !SCROLL_ScrollChildren(hwnd,dx,dy) )
	     InvalidateRgn(hwnd, hrgnUpdate, TRUE);
      }
    else
      {
        HRGN hrgnInv = SCROLL_TraceChildren(hwnd,dx,dy,DCX_CLIPCHILDREN |
						       DCX_CLIPSIBLINGS );
        if( hrgnInv )
        {
	    CombineRgn(hrgnUpdate,hrgnInv,hrgnUpdate,RGN_OR);
            DeleteObject(hrgnInv);
        }

        RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW);
      }

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


/*************************************************************************
 *             ScrollDC         (USER.221)
 *
 * FIXME: half-broken
 */

BOOL ScrollDC(HDC hdc, short dx, short dy, LPRECT rc, LPRECT cliprc,
	      HRGN hrgnUpdate, LPRECT rcUpdate)
{
    HRGN hrgnClip, hrgn1, hrgn2;
    POINT src, dest;
    short width, height;
    DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);

    dprintf_scroll(stddeb,"ScrollDC: dx=%d dy=%d, hrgnUpdate="NPFMT" rc=%i %i %i %i\n",
                                     dx,dy,hrgnUpdate,(int)((rc)?rc->left:0),
				                      (int)((rc)?rc->top:0),
				                      (int)((rc)?rc->right:0),
				                      (int)((rc)?rc->bottom:0)); 

    if (rc == NULL)
	return FALSE;

    if (cliprc)
    {
	hrgnClip = CreateRectRgnIndirect(cliprc);
	SelectClipRgn(hdc, hrgnClip);
    }

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

    width = rc->right - rc->left - abs(dx);
    height = rc->bottom - rc->top - abs(dy);

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

    if (hrgnUpdate)
    {
	if (dx > 0)
	    hrgn1 = CreateRectRgn(rc->left, rc->top, rc->left+dx, rc->bottom);
	else if (dx < 0)
	    hrgn1 = CreateRectRgn(rc->right+dx, rc->top, rc->right, 
				  rc->bottom);
	else
	    hrgn1 = CreateRectRgn(0, 0, 0, 0);

	if (dy > 0)
	    hrgn2 = CreateRectRgn(rc->left, rc->top, rc->right, rc->top+dy);
	else if (dy < 0)
	    hrgn2 = CreateRectRgn(rc->left, rc->bottom+dy, rc->right, 
				  rc->bottom);
	else
	    hrgn2 = CreateRectRgn(0, 0, 0, 0);

	RgnType = CombineRgn(hrgnUpdate, hrgn1, hrgn2, RGN_OR);
	DeleteObject(hrgn1);
	DeleteObject(hrgn2);
    }

    if (rcUpdate) GetRgnBox( hrgnUpdate, rcUpdate );
    return TRUE;
}


/*************************************************************************
 *             ScrollWindowEx       (USER.319)
 *
 * FIXME: broken
 *
 * SCROLL_TraceChildren can help
 */

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

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

    hdc = GetDC(hwnd);

    if (rect == NULL)
	GetClientRect(hwnd, &rc);
    else
	CopyRect(&rc, rect);
    if (clipRect == NULL)
	GetClientRect(hwnd, &cliprc);
    else
	CopyRect(&cliprc, clipRect);

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

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

    ReleaseDC(hwnd, hdc);
    return RgnType;
}
