/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * The contents of this file are subject to the Netscape Public License
 * Version 1.0 (the "NPL"); you may not use this file except in
 * compliance with the NPL.  You may obtain a copy of the NPL at
 * http://www.mozilla.org/NPL/
 *
 * Software distributed under the NPL is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
 * for the specific language governing rights and limitations under the
 * NPL.
 *
 * The Initial Developer of this code under the NPL is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
 * Reserved.
 */

#include "stdafx.h"
#include "mainfrm.h"
#include "urlbar.h"
#include "cxdc.h"
#include "custom.h"
#include "dropmenu.h"
#include "hk_funcs.h"
#include "prefapi.h"
#include "glhist.h"

extern void wfe_Progress(MWContext *pContext, const char *pMessage);

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif


/****************************************************************************
*
*	CONSTANTS
*
****************************************************************************/

// Positions/dimensions for certain widgets (page rep icon, quick file button)

static const int DRAG_ICON_WIDTH = 16;
static const int DRAG_ICON_HEIGHT = 15;

static const int BOOKMARKS_TEXT_LEFT = 10;

BEGIN_MESSAGE_MAP(CURLBar, CURLBarBase) 
    //{{AFX_MSG_MAP(CURLBar)
	ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
	ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut)
	ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
	ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDBLCLK()
    ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_CLOSE()
    ON_WM_LBUTTONDOWN()
    ON_WM_SIZE()
    ON_WM_PAINT()
	ON_WM_SHOWWINDOW()
	ON_WM_ERASEBKGND()
	ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
	ON_COMMAND(ID_EDIT_CUT, OnEditCut)
	ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
	ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
	ON_WM_LBUTTONUP()
	ON_WM_CTLCOLOR()
	ON_WM_PALETTECHANGED()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

#ifndef _AFXDLL
#undef new
#endif
IMPLEMENT_DYNCREATE(CURLBar, CURLBarBase)
#ifndef _AFXDLL
#define new DEBUG_NEW  // MSVC Debugging new...goes to regular new in release mode
#endif

// Buffers to hold all of the bitmaps.  Freed when the last URL bar
//   gets destructed
//
static int numberOfUrlBars = 0;
static CBitmap * pDragURLBitmap = NULL;

/////////////////////////////////////////////////////////////////////////////
// CURLBar dialog

CURLBar::CURLBar(): CURLBarBase(),
    m_cpLBDown(0,0),
	m_DragIconY(0)
{
    m_pBox = NULL;
    m_pIMWContext = NULL;
    m_nTextStatus = TRUE; // == "location" is displayed
    m_bAddToDropList = FALSE;

	m_pFont = NULL;
	m_DragIconX = 0;
	m_pPageProxy = NULL;
	m_hBackgroundBrush = CreateSolidBrush(RGB(192, 192, 192));
	numberOfUrlBars++;
	m_nBoxHeight = 0;
}

void CURLBar::SetContext( LPUNKNOWN pUnk )
{
	if (m_pIMWContext) {
		m_pIMWContext->Release();
		m_pIMWContext = NULL;
	}
	if (pUnk)
	{
		pUnk->QueryInterface( IID_IMWContext, (LPVOID *) &m_pIMWContext );
		m_pPageProxy->SetContext(pUnk);
	}
}

LRESULT CURLBar::WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
{
    if ( ( message == WM_COMMAND ) &&
#ifdef WIN32
        ( LOWORD( wParam ) == IDC_URL_EDIT ) )
            switch ( HIWORD ( wParam ) )
#else
        ( wParam == IDC_URL_EDIT ) )
            switch ( HIWORD ( lParam ) )      
#endif
    {
        case CBN_EDITCHANGE:
            OnEditChange ( );
            break;

        case CBN_SELCHANGE:
            OnSelChange ( );
            Invalidate(FALSE);
            break;

        case CBN_CLOSEUP:
            Invalidate(FALSE);
            break;

    }
    return CURLBarBase::WindowProc ( message, wParam, lParam );
}


void CURLBar::OnLButtonDown(UINT nFlags, CPoint point)
{
	CDialogBar::OnLButtonDown(nFlags, point);

    int load = FALSE;

    if (!m_pIMWContext) 
        return;

	MapWindowPoints(GetParent(), &point, 1);
	GetParent()->SendMessage(WM_LBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));


}

HBRUSH CURLBar::OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
  return CURLBarBase::OnCtlColor(pDC, pWnd, nCtlColor);
}

void CURLBar::OnPaint() 

{
    CURLBarBase::OnPaint ( );

	CClientDC dc(this);

	CRect rcClient;

	GetClientRect(&rcClient);
	
	HPALETTE hPalette = WFE_GetUIPalette(GetParentFrame());
	HPALETTE hOldPalette = ::SelectPalette(dc.m_hDC, hPalette, FALSE);

	// Use our background color
	::FillRect(dc.m_hDC, &rcClient, sysInfo.m_hbrBtnFace);

#ifdef _WIN32
	if ( sysInfo.m_bWin4 )
		m_pBox->SetFont( CFont::FromHandle ( (HFONT) GetStockObject (DEFAULT_GUI_FONT) ) );
	else 
#endif
	if ( !sysInfo.m_bDBCS )
		m_pBox->SetFont ( CFont::FromHandle ( (HFONT) GetStockObject ( ANSI_VAR_FONT ) ) );
	else
	{
		ASSERT(m_pFont != NULL);
		::SendMessage(m_pBox->GetSafeHwnd(), WM_SETFONT, (WPARAM)m_pFont, FALSE);
	}
    m_pBox->UpdateWindow ( );

     if ( !sysInfo.m_bWin4 )
     {
		 // Draw 3D frame around URL box

	    RECT rect;
		m_pBox->GetWindowRect ( &rect );
        rect.right++;
        rect.bottom++;
        rect.left--;
        rect.top--;

		ScreenToClient ( &rect );
		rect.right--;
	    rect.bottom--;

		RECT rcTmp = rect;
		::InflateRect( &rcTmp, -1, -1 );
	
		WFE_DrawHighlight( dc.m_hDC, &rcTmp, 
				   RGB(128, 128, 128), 
				   RGB(0, 0, 0));
		WFE_DrawHighlight( dc.m_hDC, &rect, 
				   RGB(192, 192, 192), 
				   RGB(231, 231, 231) );
	}

	::SelectPalette(dc.m_hDC, hOldPalette, TRUE);

}

void CURLBar::OnShowWindow( BOOL bShow, UINT nStatus )
{
	m_bEraseBackground = bShow;
}

BOOL CURLBar::OnEraseBkgnd( CDC* pDC )
{
	if ( m_bEraseBackground ) {
		m_bEraseBackground = FALSE;
		return (BOOL) Default();
	} else {
		return TRUE;
	}
}


#define TOTAL_SAVED_URLS        15
#define TOTAL_DISPLAYED_URLS    10

int CURLBar::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	int nRtn = CURLBarBase::OnCreate(lpCreateStruct);

    if (nRtn != -1)
	{
		CRect rect(0,0,0,0);

		// Create the proxy container
		m_pProxySurround = new CProxySurroundWnd();
		m_pProxySurround->Create(this);

		// Create the page proxy
		m_pPageProxy = new CPageProxyWindow;
		m_pPageProxy->Create(m_pProxySurround);

		// Create the edit box
		m_pBox = new CEditWnd(this);
		m_pBox->Create(
	        WS_CHILD|WS_VISIBLE|WS_TABSTOP,
			rect, (CWnd *) m_pProxySurround, IDC_URL_EDIT);
		
	}

    return(nRtn);
}

void CURLBar::OnDestroy( )
{
	CWnd::OnDestroy();
}
  

void CURLBar::OnClose()
{
}

void CURLBar::OnPaletteChanged( CWnd* pFocusWnd )
{
	if (pFocusWnd != this) {
		HPALETTE hPalette = WFE_GetUIPalette(GetParentFrame());
		if (WFE_IsGlobalPalette(hPalette)) {
			HDC hDC = ::GetDC(m_hWnd);
			HPALETTE hOldPalette = ::SelectPalette(hDC, hPalette, FALSE);
			::SelectPalette(hDC, hOldPalette, TRUE);
			::ReleaseDC(m_hWnd, hDC);
		}
		Invalidate();
	}
}



CURLBar::~CURLBar()
{
    delete m_pBox;
	if (m_pFont) {
		theApp.ReleaseAppFont(m_pFont);
	}
	delete m_pPageProxy;

	::DeleteObject(m_hBackgroundBrush);
    // decrease reference count
    // if we are the last one delete all of the bitmaps
    if(0 == --numberOfUrlBars) {
		delete pDragURLBitmap;
		pDragURLBitmap = NULL;
    }

}

void CURLBar::DoDataExchange(CDataExchange* pDX)
{
    CURLBarBase::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CURLBar)
    //}}AFX_DATA_MAP
}

/////////////////////////////////////////////////////////////////////////////
// CURLBar message handlers

void CURLBar::OnSize(UINT nType, int cx, int cy)
{
 
    int txtSpacing;
    int boxSpacing;
    CRect rcURLtext, rcIcon, bookmarkRect;
	int x = BOOKMARKS_TEXT_LEFT;
	
	CWnd *pText = GetDlgItem( IDC_URLTEXT );

    if (pText) {
        pText->GetWindowRect(&rcURLtext);
        // figure out how big we need to make the box
        CDC * pDC = m_pBox->GetDC();
        
        TEXTMETRIC tm;

		// creates font for multibyte system running on WinNT and Win16 
		// on Win95, m_pFont should point to DEFAULT_GUI_FONT
		// on single byte NT or win16, it should point to ANSI_VAR_FONT
#ifdef XP_WIN32
		if (sysInfo.m_bWin4 == TRUE)
			m_pBox->SetFont( CFont::FromHandle ( (HFONT) GetStockObject (DEFAULT_GUI_FONT) ) );
		else 
#endif
		if (sysInfo.m_bDBCS == FALSE)
			m_pBox->SetFont ( CFont::FromHandle ( (HFONT) GetStockObject ( ANSI_VAR_FONT ) ) );
		else {
			if (m_pFont == 0) {
				LOGFONT lf;
				XP_MEMSET(&lf,0,sizeof(LOGFONT));
				lf.lfPitchAndFamily = FF_SWISS;
				lf.lfCharSet = IntlGetLfCharset(0);
   				lf.lfHeight = -MulDiv(9,pDC->GetDeviceCaps(LOGPIXELSY), 72);
				strcpy(lf.lfFaceName, IntlGetUIPropFaceName(0));
				lf.lfWeight = 400;
				m_pFont = theApp.CreateAppFont( lf );
			}
			::SendMessage(m_pBox->GetSafeHwnd(), WM_SETFONT, (WPARAM)m_pFont, FALSE);
		}

        pDC->GetTextMetrics(&tm);
        // stay inside of the space we've been given                                   
        m_nBoxHeight = tm.tmHeight; // + tm.tmDescent;
        if(m_nBoxHeight > (cy - 2))
            m_nBoxHeight = cy - 2;
        m_pBox->ReleaseDC(pDC);       
    }

    CURLBarBase::OnSize(nType, cx, cy);

    if( pText && m_pBox ) 
	{
        // position the "Location" text 
		txtSpacing = (cy - rcURLtext.Height()) / 2 ; 

        pText->MoveWindow(x, 
                          txtSpacing, rcURLtext.Width(), rcURLtext.Height());

		x += rcURLtext.Width() + 3;

		m_DragIconX = x;

		// Position the proxy surround wnd
		
		m_pProxySurround->MoveWindow(x-1, 1, ( cx - x - 
                        ( GetSystemMetrics(SM_CXBORDER) * 2)),cy-2);

        boxSpacing = (cy - m_nBoxHeight) / 2 ;
        m_DragIconY = boxSpacing + (m_nBoxHeight - DRAG_ICON_HEIGHT)/2;

		m_pPageProxy->MoveWindow(1, m_DragIconY-1, DRAG_ICON_WIDTH, DRAG_ICON_HEIGHT);
		
		x += DRAG_ICON_WIDTH + 2;

        // position the location edit box
        m_pBox->MoveWindow( DRAG_ICON_WIDTH+3,
                   (cy - m_nBoxHeight) / 2 -1, 
                   ( cx - x - 
                        ( GetSystemMetrics(SM_CXBORDER) * 2)) ,
						m_nBoxHeight); 
	}
      
    m_DragIconY = boxSpacing + (m_nBoxHeight - DRAG_ICON_HEIGHT)/2 + 1;
	
	
}

//////////////////////////////////////////////////////////////////////////////
// The user has hit return in the URL box.  download the current selection and
// give the focus back to the frame
void CURLBar::ProcessEnterKey() 
{
    char *new_text = NULL;
    char    text[1000];
    URL_Struct * URL_s;

    if (!m_pIMWContext) return;

    m_pBox->GetWindowText(text, 1000);

    if (text[0])
    {
        MWContext *context = m_pIMWContext->GetContext();
        int32 id;

        if (context)
        {
            id = XP_CONTEXTID(context);
        }
        else
        {
            id = 0;
        }

        if (HK_CallHook(HK_LOCATION, NULL, id, text, &new_text))
        {
            // Nothing, new_text is already set.
        }
        else
        {
            new_text = NULL;
        }
    }

    if (new_text)
    {
        URL_s = NET_CreateURLStruct(new_text, NET_DONT_RELOAD);
        XP_FREE(new_text);
    }
    else
    {
        URL_s = NET_CreateURLStruct(text, NET_DONT_RELOAD);
    }

	//	Load up.
	m_pIMWContext->GetUrl(URL_s, FO_CACHE_AND_PRESENT);
}


//////////////////////////////////////////////////////////////////////////////////////
// Set the current url bar to the given string and make sure that the text label
//   says "Location:".  We are probably setting it more frequently than we
//   need to because of the location / netsite history
void CURLBar::UpdateFields( const char * msg )
{       
    CWnd *pText = GetDlgItem( IDC_URLTEXT );

    // strip random backend crap out of the url
    msg = LM_StripWysiwygURLPrefix(msg);

    CString cs(msg);
    m_pBox->SetWindowText(cs); 
    UpdateWindow();
    //m_pBox->SetEditSel(cs.GetLength()-1,cs.GetLength());
    m_pBox->Clear();
    
	// If this was a netsite server change the string
	History_entry*	pEntry = SHIST_GetCurrent(&m_pIMWContext->GetContext()->hist);

	if (pEntry && pEntry->is_netsite)
		pText->SetWindowText(szLoadString(IDS_NETSITE));
	else
		pText->SetWindowText(szLoadString(IDS_LOCATION));

    m_nTextStatus = TRUE;
}

void CURLBar::OnEditCopy()
{
    m_pBox->Copy();
    OnEditChange();
}

void CURLBar::OnUpdateEditCopy(CCmdUI* pCmdUI)	{
	int iStartSel, iEndSel;
	m_pBox->GetSel(iStartSel, iEndSel);

	if(iStartSel != iEndSel)	{
		pCmdUI->Enable(TRUE);
	}
	else	{
		pCmdUI->Enable(FALSE);
	}
}

void CURLBar::OnEditCut()
{
    m_pBox->Cut();
    OnEditChange();
}

void CURLBar::OnUpdateEditCut(CCmdUI* pCmdUI)	{
	int iStartSel, iEndSel;
	m_pBox->GetSel(iStartSel, iEndSel);

	if(iStartSel != iEndSel)	{
		pCmdUI->Enable(TRUE);
	}
	else	{
		pCmdUI->Enable(FALSE);
	}
}

void CURLBar::OnEditPaste()
{

	m_pBox->Paste();
    OnEditChange();
}

void CURLBar::OnUpdateEditPaste(CCmdUI* pCmdUI)	{
	pCmdUI->Enable(::IsClipboardFormatAvailable(CF_TEXT));
}

void CURLBar::OnEditUndo()
{
    m_pBox->Undo();
    OnEditChange();
}

void CURLBar::OnUpdateEditUndo(CCmdUI* pCmdUI)	{
	pCmdUI->Enable(m_pBox->CanUndo());
}

void CURLBar::OnSelChange()
{
}

///////////////////////////////////////////////////////////////////////////////////////
// The user has modified the text in the edit field.  make sure it is now labeled as
//   "Go to:" rather than "Location:"
void CURLBar::OnEditChange()
{
	CWnd *pText = GetDlgItem( IDC_URLTEXT );

    if( pText && m_nTextStatus )
    {
        pText->SetWindowText(szLoadString(IDS_GOTO));
        m_nTextStatus = FALSE;
    }
}

void CURLBar::OnMouseMove(UINT nFlags, CPoint point) 
{
	CURLBarBase::OnMouseMove(nFlags, point);
    // Display previous status
    wfe_Progress( m_pIMWContext->GetContext(), "" );

  	MapWindowPoints(GetParent(), &point, 1);
	GetParent()->SendMessage(WM_MOUSEMOVE, nFlags, MAKELPARAM(point.x, point.y));

}

void CURLBar::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	CURLBarBase::OnLButtonDblClk(nFlags, point);

}


void CURLBar::OnLButtonUp(UINT nFlags, CPoint point) 
{
	MapWindowPoints(GetParent(), &point, 1);
	GetParent()->SendMessage(WM_LBUTTONUP, nFlags, MAKELPARAM(point.x, point.y));

}

CEditWnd::~CEditWnd()
{
    if (m_idTimer)
        KillTimer(m_idTimer);
    if (m_pComplete)
        free(m_pComplete);
}


BEGIN_MESSAGE_MAP(CEditWnd,CGenericEdit)
    ON_WM_TIMER()
END_MESSAGE_MAP()


LRESULT CEditWnd::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    LRESULT result = CEdit::DefWindowProc(message,wParam,lParam);
    if (message == WM_CHAR)
    {
        switch (wParam)
        {
            case VK_BACK:
                break;
            default:
                UrlCompletion();
                break;
        }
    }
    return result;
}

#define URL_AUTO_CHECK_DELAY    25
#define URL_TIMER 10

BOOL CEditWnd::PreTranslateMessage ( MSG * msg )
{
   if ( msg->message == WM_KEYDOWN)
   {
	  CURLBar* pBar = (CURLBar*)m_pBar;
	  LPMWCONTEXT pCX = pBar->GetContext();
      
	  switch(msg->wParam)
      {
         case VK_RETURN:
			 // Kill any urlcompletion still on the timer
			 m_bRestart = TRUE;
			 if (m_idTimer)
			 {
				KillTimer(m_idTimer);
				m_idTimer = 0;
			 }
                  
             if (pCX) 
             {
                CString url;
                char *new_url = NULL;
                char *url_str;
                GetWindowText ( url );

				// Call the location_hook to process and possibly change the
				// text just entered.
        
				if ((url)&&(*url))
				{
					MWContext *context = (MWContext *)pCX;
					int32 id;

					if (context)
					{
						id = XP_CONTEXTID(context);
					}
					else
					{
						id = 0;
					}

					const char *c_url = (const char *)url;
					url_str = (char *)c_url;
					if (HK_CallHook(HK_LOCATION, NULL, id, url_str, &new_url))
					{
						// Nothing, new_url is already set.
					}
					else
					{
						new_url = NULL;
					}
				}
			
				if (new_url)
				{
					if ( strlen ( new_url ) )
					{
						pCX->NormalGetUrl(new_url);
					}
					XP_FREE(new_url);
				}
				else
				{
					if ( strlen ( url ) )
					{
						pCX->NormalGetUrl(url);
					}
				}
			 }
			 break;
		 case VK_DOWN:
            {
               int nStart, nEnd;
               CString csOriginal, csPartial;
               GetWindowText(csOriginal);
               GetSel(nStart,nEnd);
               if (nEnd>=nStart)
               {
                  csPartial = csOriginal.Left(nStart);
                  char * pszResult = NULL;
                  switch (urlMatch(csPartial,&pszResult,FALSE, m_Scroll = TRUE))
                  {
                     case stillSearching:
                        if (!m_idTimer)
                        {
                           m_idTimer = SetTimer(URL_TIMER, URL_AUTO_CHECK_DELAY, NULL);
                           m_bRestart = FALSE;
                        }
                        break;
                  }
                  DrawCompletion(csPartial,pszResult);
               }
            }
			return TRUE;
		default:
            m_Scroll = FALSE;
            break;
      }
	}
   return CEdit::PreTranslateMessage ( msg );
}

void CEditWnd::UrlCompletion()
{
    CString cs;
	Bool cursorAtEnd, textSelected;
	int nStart, nEnd;
    GetWindowText(cs);
	GetSel(nStart,nEnd);
    char * pszResult = NULL;


	textSelected = (nEnd - nStart) ? TRUE : FALSE;
	cursorAtEnd = (!textSelected && ( nEnd == cs.GetLength() ));

	if(textSelected || cursorAtEnd)
	{
		switch (urlMatch(cs,&pszResult,m_bRestart, m_Scroll = FALSE))
		{
			case dontCallOnIdle:
			case notFoundDone:
			case foundDone:
				m_bRestart = TRUE;
				if (m_idTimer)
				{
					KillTimer(m_idTimer);
					m_idTimer = 0;
				}
				break;
			case stillSearching:
				m_bRestart = FALSE;
				if (!m_idTimer)
				{
					m_idTimer = SetTimer(URL_TIMER, URL_AUTO_CHECK_DELAY, NULL);
					break;
				}
				break;
		}
    
		DrawCompletion(cs, pszResult);
	}
}

void CEditWnd::DrawCompletion(CString & cs, char * pszResult)
{
    if (pszResult)
    {
        if (m_pComplete)
        {
            free(m_pComplete);
            m_pComplete = NULL;
        }
        m_pComplete = strdup(pszResult);
        UINT iPre = cs.GetLength();
        CString csNew;
        csNew = cs;
        if (iPre >= 0 && iPre <= strlen(pszResult))
            csNew += CString(&pszResult[iPre]);
        SetWindowText(csNew);
        SetSel((int)iPre,-1);
		free(pszResult);
		pszResult = NULL;
    }
}

void CEditWnd::OnTimer( UINT  nIDEvent )
{
   if (nIDEvent == m_idTimer)
   {
      int nStart, nEnd;
      CString csOriginal, csPartial;
      GetWindowText(csOriginal);
      GetSel(nStart,nEnd);
      if ( (nEnd>=nStart) && m_Scroll )
         csPartial = csOriginal.Left(nStart);
      else
         csPartial = csOriginal;
      char * pszResult = NULL;
      switch (urlMatch(csPartial,&pszResult,m_bRestart, m_Scroll))
      {
         case dontCallOnIdle:
	         m_bRestart = FALSE;
             if (m_idTimer)
             {
                 KillTimer(m_idTimer);
                 m_idTimer = 0;
             }
             break;
         case notFoundDone:
         case foundDone:
             m_bRestart = TRUE;
             if (m_idTimer)
             {
                 KillTimer(m_idTimer);
                 m_idTimer = 0;
             }
             break;
      }
      DrawCompletion(csPartial, pszResult);
    }
}


// CProxySurroundWnd

BEGIN_MESSAGE_MAP(CProxySurroundWnd, CWnd) 
    //{{AFX_MSG_MAP(CProxySurroundWnd)
	ON_WM_PAINT()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

BOOL CProxySurroundWnd::Create(CWnd *pParent)
{
	CRect rect(0, 0, 10, 10); // will size/position it later

	BOOL bRtn = CWnd::CreateEx( NULL, 
                                NULL, 
                                NULL, 
                                WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE | WS_BORDER, 
                                0, 0, 10, 10,
                        		pParent ? pParent->m_hWnd : NULL, 0 );
	return bRtn;
}

void CProxySurroundWnd::OnPaint() 
{
    CWnd::OnPaint ( );

	CClientDC dc(this);

	CRect rcClient;

	GetClientRect(&rcClient);
	
	// Use window background color
	HBRUSH br = ::CreateSolidBrush(::GetSysColor(COLOR_WINDOW));
	::FillRect(dc.m_hDC,&rcClient,br);
	::DeleteObject(br);

}

///////////////////////////////////////////////////////////////////////////////////////////
//								Class CPageProxyWindow
///////////////////////////////////////////////////////////////////////////////////////////

#define IDT_PROXYFOCUS 16420
#define PROXYFOCUS_DELAY_MS 10

CPageProxyWindow::CPageProxyWindow(void)
{
	m_bDraggingURL = FALSE;
	m_bDragIconHit = FALSE;
	m_bDragStatusHint = FALSE;
	m_pIMWContext = NULL;
}

CPageProxyWindow::~CPageProxyWindow(void)
{


}
void CPageProxyWindow::SetContext( LPUNKNOWN pUnk )
{
	if (m_pIMWContext) {
		m_pIMWContext->Release();
		m_pIMWContext = NULL;
	}
	if (pUnk)
		pUnk->QueryInterface( IID_IMWContext, (LPVOID *) &m_pIMWContext );
}

BOOL CPageProxyWindow::Create(CWnd *pParent)
{
	CRect rect(0, 0, 10, 10); // will size/position it later

	BOOL bRtn = CWnd::CreateEx( NULL, 
                                AfxRegisterWndClass( CS_SAVEBITS, theApp.LoadCursor( IDC_HANDOPEN ), 
                                                     (HBRUSH)(COLOR_BTNFACE+1) ), 
                                NULL, 
                                WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, 
                                0, 0, 10, 10,
                        		pParent ? pParent->m_hWnd : NULL, 0 );
	if(bRtn)
	{
		CString tipStr;

		tipStr.LoadString(IDS_DRAGURLTIP);

		
		m_ToolTip.Create(this, TTS_ALWAYSTIP);


		m_ToolTip.AddTool(this, (const char*) tipStr );

		m_ToolTip.Activate(TRUE);
		m_ToolTip.SetDelayTime(200);
	
	}

	return bRtn;
}

///////////////////////////////////////////////////////////////////////////////////////////
//								CPageProxyWindow Messages
///////////////////////////////////////////////////////////////////////////////////////////

int CPageProxyWindow::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{

    return(0);
}

BEGIN_MESSAGE_MAP(CPageProxyWindow, CWnd) 
    //{{AFX_MSG_MAP(CPageProxyWindow)
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDBLCLK()
    ON_WM_LBUTTONDOWN()
	ON_WM_PAINT()
	ON_WM_SHOWWINDOW()
	ON_WM_ERASEBKGND()
	ON_WM_LBUTTONUP()
	ON_WM_TIMER()
    ON_WM_MOUSEACTIVATE()

	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CPageProxyWindow::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	CWnd::OnLButtonDblClk(nFlags, point);

    if ( m_pIMWContext && !m_pIMWContext->GetContext()->waitingMode && 
         !m_bDraggingURL && !m_bDragIconHit)  {
		WINCX(m_pIMWContext->GetContext())->CopyCurrentURL();
    }
}


void CPageProxyWindow::OnLButtonUp(UINT nFlags, CPoint point) 
{
	ReleaseCapture();
    m_bDragIconHit = FALSE;
	MSG msg = *(GetCurrentMessage());
	m_ToolTip.RelayEvent(&msg);

	SetCursor(theApp.LoadCursor(IDC_HANDOPEN));

}

int CPageProxyWindow::OnMouseActivate( CWnd *, UINT, UINT )
{
    //
    // Prevent the frame window from activating.  Allows for easier drag/drop from proxy
    // to a different top-level window in that the browser frame retains it's z-position.
    //
    return MA_NOACTIVATE;
}

void CPageProxyWindow::OnMouseMove(UINT nFlags, CPoint point) 
{
	CWnd::OnMouseMove(nFlags, point);

	SetCursor(theApp.LoadCursor(IDC_HANDOPEN));

	if ( m_pIMWContext && !m_pIMWContext->GetContext()->waitingMode && !m_bDraggingURL ) {
        if ( m_bDragIconHit &&
             ((abs(point.x - m_cpLBDown.x) > 3)
             || (abs(point.y - m_cpLBDown.y) > 3)) ) {
            // We moved enough to start dragging
            m_bDraggingURL = TRUE;
            // DragNDrop baby!
			m_bDragStatusHint = FALSE;
			RedrawWindow();
			ReleaseCapture();
            WINCX(m_pIMWContext->GetContext())->DragCurrentURL();
            // Done -- clear flags
            m_bDraggingURL = FALSE;
            m_bDragIconHit = FALSE;

            // Return focus to frame??
            // Not such a good idea; Drag/drop ops should maintain z-order.
            // GetTopLevelFrame()->SetFocus();
       } else if( (point.x >= 0) && 
                   (point.x <=  DRAG_ICON_WIDTH) &&
                   (point.y >= 0) && 
                   (point.y <=  DRAG_ICON_HEIGHT) ) {
            // Mouse is over the icon and button is up
            // TODO: Simulate ToolTip here (IDS_DRAG_THIS_URL_TIP)
            // For now -- display on StatusBar
            if ( !m_bDragStatusHint ) {
                m_pIMWContext->Progress(m_pIMWContext->GetContext(), szLoadString(ID_DRAG_THIS_URL));
                m_bDragStatusHint = TRUE;
				m_hFocusTimer = SetTimer(IDT_PROXYFOCUS, PROXYFOCUS_DELAY_MS, NULL);
				RedrawWindow();
	            }
       } else if (m_bDragStatusHint) {
            // Restore message to previous contents
          #if 0
            m_pIMWContext->Progress(m_pIMWContext->GetContext(), "");
          #else
            // Display previous status
            wfe_Progress( m_pIMWContext->GetContext(), "" );
          #endif
            m_bDragStatusHint = FALSE;
			RedrawWindow();

        }
    }

	m_ToolTip.Activate(TRUE);
	MSG msg = *(GetCurrentMessage());
	m_ToolTip.RelayEvent(&msg);
}

void CPageProxyWindow::OnLButtonDown(UINT nFlags, CPoint point)
{
	CWnd::OnLButtonDown(nFlags, point);

    int load = FALSE;

    if (!m_pIMWContext) 
        return;

	m_cpLBDown = point;
    
    //CLM: Check if clicking in the Drag icon:
    if (!m_pIMWContext->GetContext()->waitingMode && (point.x >= 0) && 
        (point.x <=  DRAG_ICON_WIDTH) &&
        (point.y >= 0) && 
        (point.y <=  DRAG_ICON_HEIGHT)) {
        m_bDragIconHit = TRUE;
		SetCursor(theApp.LoadCursor(IDC_LINK_COPY));

		SetCapture();
    }

	MSG msg = *(GetCurrentMessage());
	m_ToolTip.RelayEvent(&msg);


}

void CPageProxyWindow::OnPaint() 
{
    CWnd::OnPaint ( );

	CClientDC dc(this);

	CRect rcClient;

	GetClientRect(&rcClient);
	
	// Use window background color
	HBRUSH br = ::CreateSolidBrush(::GetSysColor(COLOR_WINDOW));
	::FillRect(dc.m_hDC,&rcClient,br);
	::DeleteObject(br);

    CDC SrcDC;
	SrcDC.CreateCompatibleDC(&dc);


    // Draw the bitmap for dragging this URL

    // Create the bitmaps if we haven't already
    if(pDragURLBitmap == NULL) {
        pDragURLBitmap = new CBitmap;

        if(pDragURLBitmap) {
			pDragURLBitmap->LoadBitmap( IDB_DRAG_URL );
        }
    }

    if(pDragURLBitmap) {
		CPoint bitmapStart(m_bDragStatusHint ? DRAG_ICON_WIDTH : 0 , 0);

        CBitmap *pOldBitmap = SrcDC.SelectObject(pDragURLBitmap);
		::FEU_TransBlt( &SrcDC, &dc,
						bitmapStart, 
						CPoint(0, 0),
						DRAG_ICON_WIDTH, DRAG_ICON_HEIGHT,WFE_GetUIPalette(GetParentFrame()));

        SrcDC.SelectObject( pOldBitmap );
    }


	SrcDC.DeleteDC();


}

void CPageProxyWindow::OnShowWindow( BOOL bShow, UINT nStatus )
{
	m_bEraseBackground = bShow;
}

BOOL CPageProxyWindow::OnEraseBkgnd( CDC* pDC )
{
	if ( m_bEraseBackground ) {
		m_bEraseBackground = FALSE;
		return (BOOL) Default();
	} else {
		return TRUE;
	}
}

void CPageProxyWindow::OnTimer( UINT  nIDEvent )
{
	if(nIDEvent == IDT_PROXYFOCUS)
	{
		POINT point;

		KillTimer(IDT_PROXYFOCUS);
		m_hFocusTimer = 0;
		GetCursorPos(&point);

		CRect rcClient;
		GetWindowRect(&rcClient);

		if (!rcClient.PtInRect(point))
		{
			m_bDragStatusHint = FALSE;
			RedrawWindow();
		
		}
		else
			m_hFocusTimer = SetTimer(IDT_PROXYFOCUS, PROXYFOCUS_DELAY_MS, NULL);

	}


}
