#include "stdafx.h"
#include "apl_gui.h"
#include <mshtml.h>	

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

IMPLEMENT_DYNAMIC(CaplHtmlView, CHtmlView)
BEGIN_MESSAGE_MAP(CaplHtmlView, CHtmlView)
ON_WM_DESTROY()
ON_WM_MOUSEACTIVATE()
END_MESSAGE_MAP()

//////////////////
// Create control in same position as an existing static control with
// the same ID (could be any kind of control, really)
//

CaplHtmlView::CaplHtmlView()
{ 	
	m_bAlwaysUseShellExecute=false;
	m_pIHTMLDocument2=0;
}

CaplHtmlView::~CaplHtmlView()
{
	ReleseInterfaces();
}

bool CaplHtmlView::InitInterfaces()
{
	//if(0!=m_pIHTMLDocument2) ReleseInterfaces(); // На всякий случай
	if(0!=m_pIHTMLDocument2) return true;
	LPDISPATCH pIHtmlDisp = GetHtmlDocument(); 
	if(0==pIHtmlDisp) return false;
	HRESULT hr = pIHtmlDisp->QueryInterface(IID_IHTMLDocument2, (void**)&m_pIHTMLDocument2 );
	if (hr != S_OK )m_pIHTMLDocument2=0;
	pIHtmlDisp->Release();
	return(0!=m_pIHTMLDocument2);
}

void CaplHtmlView::ReleseInterfaces()
{
	if(0!=m_pIHTMLDocument2) { m_pIHTMLDocument2->Release(); m_pIHTMLDocument2=0;}

}

bool CaplHtmlView::SetAlwaysUseShellExecute(bool mode)
{
	bool oldval=m_bAlwaysUseShellExecute;
	m_bAlwaysUseShellExecute=mode;
	return oldval;
}


BOOL CaplHtmlView::CreateFromStatic(UINT nID, CWnd* pParent)
{
	if(0==pParent) return FALSE;

	CWnd *wnd=pParent->GetDlgItem(nID);
	if(0==wnd) return FALSE;
	CRect rc;
	wnd->GetWindowRect(&rc);
	pParent->ScreenToClient(&rc);
	
	// create HTML control (CHtmlView)
	return Create(NULL,					// class name
		NULL,							// title
		(WS_CHILD | WS_VISIBLE ),		// style
		rc,								// rectangle
		pParent,						// parent
		nID,							// control ID
		NULL);							// frame/doc context not used
}

////////////////
// Override to avoid CView stuff that assumes a frame.
//
void CaplHtmlView::OnDestroy()
{
	// This is probably unecessary since ~CHtmlView does it, but
	// safer to mimic CHtmlView::OnDestroy.
	ReleseInterfaces();

	if (m_pBrowserApp) 
	{
		
		#if _MFC_VER < 0x0700
			m_pBrowserApp->Release();
		#else
			m_pBrowserApp.Release();
		#endif

		m_pBrowserApp = NULL;
	}
	CWnd::OnDestroy(); // bypass CView doc/frame stuff
}

////////////////
// Override to avoid CView stuff that assumes a frame.
//
int CaplHtmlView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT msg)
{
	// bypass CView doc/frame stuff
	return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, msg);
}

//////////////////
// Override navigation handler to pass to "app:" links to virtual handler.
// Cancels the navigation in the browser, since app: is a pseudo-protocol.
//
void CaplHtmlView::OnBeforeNavigate2( LPCTSTR		lpszURL,
								  DWORD			/*nFlags*/,
								  LPCTSTR		/*lpszTargetFrameName*/,
								  CByteArray&	/*baPostedData*/,
								  LPCTSTR		/*lpszHeaders*/,
								  BOOL*			pbCancel )
{
	const TCHAR APP_PROTOCOL[] = _T("app:");
	int len = _tcslen(APP_PROTOCOL);
	if (_tcsnicmp(lpszURL, APP_PROTOCOL, len)==0) 
	{
		OnAppCmd(lpszURL + len);
		*pbCancel = TRUE;
	}

	ReleseInterfaces();

	if(m_bAlwaysUseShellExecute)
	{
		aplShellExecute(0,_T("open"),lpszURL,NULL,NULL,SW_SHOW);
		*pbCancel = TRUE;
		return;
	}
}

BOOL CaplHtmlView::SetEditMode(bool mode)
{
	unsigned short *smode=(unsigned short*)L"On";
	if(mode==false) smode=(unsigned short*)L"Off";

	if(!InitInterfaces()) return FALSE;
	HRESULT hr=m_pIHTMLDocument2->put_designMode((BSTR)smode); 
	if( SUCCEEDED( hr )) return TRUE;
	return FALSE;
}
// ***************************************************************************

BOOL CaplHtmlView::AppendContents(LPCTSTR text)
{
	if(text==0) return FALSE;
	if(text[0]==_T('\0')) return TRUE;

	if(!InitInterfaces()) return FALSE;

	//Get access to the internal document
	IHTMLElement *pElement;
	HRESULT hr = m_pIHTMLDocument2->get_body( &pElement );
	if( SUCCEEDED( hr ) && (pElement !=0))
	{
		//Extract the data
		USES_CONVERSION;
		BSTR bsMainText;
		pElement->get_innerHTML( &bsMainText );
		CString sBody( OLE2T(bsMainText) );
		SysFreeString( bsMainText );

		//Append the new text
		sBody += text;

		TCHAR *buf = NULL;
		if (sBody.GetLength()>0)
		{
			buf = new TCHAR[sBody.GetLength()];
			_strncpy(buf, (LPCTSTR)sBody, sBody.GetLength());
		}

		//Assign the new text
		bsMainText = SysAllocString( T2OLE(buf) );
		pElement->put_innerHTML( bsMainText );
		SysFreeString( bsMainText );
		pElement->Release();
		return TRUE;
	}
	return FALSE;
}
// ***************************************************************************
BOOL CaplHtmlView::SetContents(LPCTSTR text)
{
	if(text==0) return FALSE;
	if(text[0]==_T('\0')) return TRUE;

	if(!InitInterfaces()) return FALSE;

	//Get access to the internal document
	IHTMLElement *pElement;
	HRESULT hr = m_pIHTMLDocument2->get_body( &pElement );
	if( SUCCEEDED( hr )&& (pElement !=0))
	{
		//Extract the data
		USES_CONVERSION;
		BSTR bsMainText;
		//Assign the new text
		bsMainText = SysAllocString( T2OLE((LPTSTR)text) );
		pElement->put_innerHTML( bsMainText );
		SysFreeString( bsMainText );
		pElement->Release();
		return TRUE;
	}
	return FALSE;
}
// ***************************************************************************
BOOL CaplHtmlView::Print()
{
	LPDISPATCH lpDispatch = NULL; 
	LPOLECOMMANDTARGET lpOleCommandTarget = NULL; 

	lpDispatch = GetHtmlDocument(); 
	if( lpDispatch == NULL ) return FALSE;

	HRESULT hr = lpDispatch->QueryInterface(IID_IOleCommandTarget, 
	(void**)&lpOleCommandTarget); 
	
	lpDispatch->Release(); 
	
	if( SUCCEEDED( hr ) && (lpOleCommandTarget !=0))
	{
		// print contents of web browser control 
		lpOleCommandTarget->Exec(NULL, OLECMDID_PRINT, 0, NULL,NULL); 
		lpOleCommandTarget->Release(); 
		return TRUE;
	}
	return FALSE;
}
// ***************************************************************************
BOOL CaplHtmlView::GetContents(CString &buf)
{
	if(!InitInterfaces()) return FALSE;

	//Get access to the internal document
	IHTMLElement *pElement;
	HRESULT hr = m_pIHTMLDocument2->get_body( &pElement );
	if( SUCCEEDED( hr ) && (pElement !=0))
	{
		//Extract the data
		USES_CONVERSION;
		BSTR bsMainText;
		pElement->get_innerHTML( &bsMainText );
		buf=OLE2T(bsMainText);
		SysFreeString( bsMainText );
		pElement->Release();
		return TRUE;
	}
	return FALSE;
}

// ***************************************************************************
//DESCRIPTION:
//		This is called by OnBeforeNavigate2() when a link starting with
//		"app:" is requested. 
//PARAMS:
//		lpszWhere	String identifing the action to perform.
//CREATED:
//		10-3-2001, 8:05:08 PM by john@mctainsh.com
// ***************************************************************************
void CaplHtmlView::OnAppCmd(LPCTSTR lpszWhere)
{
	if( _tcscmp( _T("Minimise"), lpszWhere )==0 && AfxGetMainWnd()!=0) 
	{
		AfxGetMainWnd()->ShowWindow( SW_MINIMIZE );
	}	
	else if( _tcscmp( _T("Beep"), lpszWhere )==0 ) 
	{
		MessageBeep( MB_ICONASTERISK );
	}
	else
	{
		MessageBox( lpszWhere, _T("Unexpected Command"), MB_ICONQUESTION  );
	}
}
//********************************************************************************
// Редактирование
//********************************************************************************
bool CaplHtmlView::ExecCommand(DWORD command, VARIANT *vin, VARIANT *vout)
{
	if (0==m_pBrowserApp) return false;
	IOleCommandTarget* pCmdTarg;
	m_pBrowserApp->QueryInterface(IID_IOleCommandTarget, (void**)&pCmdTarg);
	if (NULL==pCmdTarg)  return false;
	HRESULT hr = pCmdTarg->Exec(&CGID_MSHTML, command, MSOCMDEXECOPT_DODEFAULT, vin, vout);
	pCmdTarg->Release();
	if(S_OK==hr) return true;
	return false;
}

void CaplHtmlView::SetSelectionBold() {ExecCommand(IDM_BOLD);}
void CaplHtmlView::SetSelectionItalic() {ExecCommand(IDM_ITALIC);}
void CaplHtmlView::SetSelectionUnderlined() {ExecCommand(IDM_UNDERLINE);}
void CaplHtmlView::SetSelectionStrikeouted() {ExecCommand(IDM_STRIKETHROUGH);}

void CaplHtmlView::SetParagraphLeft() {ExecCommand(IDM_JUSTIFYLEFT);}
void CaplHtmlView::SetParagraphCenter() {ExecCommand(IDM_JUSTIFYCENTER);}
void CaplHtmlView::SetParagraphRight() {ExecCommand(IDM_JUSTIFYRIGHT);}
void CaplHtmlView::SetParagraphWidth() {ExecCommand(IDM_JUSTIFYFULL);}
void CaplHtmlView::SetOrderList() {ExecCommand(IDM_ORDERLIST);}
void CaplHtmlView::SetUnOrderList() {ExecCommand(IDM_UNORDERLIST);}


BOOL CaplHtmlView::queryCommandValue(BSTR command)
{
	if(0==command)  return FALSE;
	if(!InitInterfaces()) return FALSE;

	COleVariant olevar;
	VARIANT *v=LPVARIANT(olevar);

	HRESULT hr2 = m_pIHTMLDocument2->queryCommandValue(command,v);
	if(S_OK!=hr2) return FALSE;
	if(v->vt==VT_BOOL && 0!=v->bVal) return TRUE;
	return FALSE;
}


BOOL CaplHtmlView::IsSelectionBold() {return queryCommandValue(L"Bold");}
BOOL CaplHtmlView::IsSelectionItalic() {return queryCommandValue(L"Italic");}
BOOL CaplHtmlView::IsSelectionUnderline() {return queryCommandValue(L"Underline");}
BOOL CaplHtmlView::IsSelectionStrikeouted() {return queryCommandValue(L"StrikeThrough");}
BOOL CaplHtmlView::IsParagraphLeft() {return queryCommandValue(L"JustifyLeft");}
BOOL CaplHtmlView::IsParagraphCenter() {return queryCommandValue(L"JustifyCenter");}
BOOL CaplHtmlView::IsParagraphRight() {return queryCommandValue(L"JustifyRight");}
BOOL CaplHtmlView::IsParagraphWidth() {return queryCommandValue(L"JustifyFull");}
BOOL CaplHtmlView::IsOrderList() {return queryCommandValue(L"insertOrderedList");}
BOOL CaplHtmlView::IsUnOrderList() {return queryCommandValue(L"insertUnorderedList");}


//**************************************************************************************
void CaplHtmlView::SetSelectionColor()
{
	COLORREF curcolor=RGB(0,0,0);
	COleVariant olevar;
	VARIANT *v=LPVARIANT(olevar);
	if(ExecCommand(IDM_FORECOLOR,0,v)) curcolor=(COLORREF)olevar.lVal;

	CColorDialog dlg(curcolor);
	
	if( dlg.DoModal() != IDOK ) return;
	COLORREF color= dlg.GetColor();

	CString htmlColor;
	htmlColor.Format(_T("#%02x%02x%02x"),GetRValue(color), GetGValue(color), GetBValue(color));
	olevar=htmlColor;
	ExecCommand(IDM_FORECOLOR,LPVARIANT(olevar),0);
}

//**************************************************************************************
void CaplHtmlView::SetFontSize(int fontsize)
{
	if(fontsize<=0) return;
	COleVariant olevar((long)fontsize);
	ExecCommand(IDM_FONTSIZE,LPVARIANT(olevar),0);
}

int CaplHtmlView::GetSelectionFontSize()
{
	COleVariant olevar;
	ExecCommand(IDM_FONTSIZE,0,LPVARIANT(olevar));
	VARIANT *v=LPVARIANT(olevar);

	if(VT_I4!=v->vt) return 0;
	int i=v->lVal;
	return i;

}

void CaplHtmlView::SetFontName(LPCTSTR fontname)
{
	if(0==fontname) return;
	if(_T('\0')==fontname[0]) return;
	COleVariant olevar(fontname);
	VARIANT *v=LPVARIANT(olevar);
	ExecCommand(IDM_FONTNAME,v,0);
}


bool  CaplHtmlView::GetSelectionFontName(CString &font_name)
{
	font_name=_T("");
	COleVariant olevar;
	ExecCommand(IDM_FONTNAME,0,LPVARIANT(olevar));
	VARIANT *v=LPVARIANT(olevar);
	if(VT_BSTR!=v->vt) return false;
	font_name=v->bstrVal;
	return true;
}


void CaplHtmlView::Cut()
{
	ExecWB(OLECMDID_CUT, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL); 
}
void CaplHtmlView::Copy()
{
	 ExecWB(OLECMDID_COPY, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL); 
}
void CaplHtmlView::Paste()
{
	ExecWB(OLECMDID_PASTE, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL); 
}


BOOL  CaplHtmlView::CanCopy()
{
	OLECMDF olecmdf = QueryStatusWB (OLECMDID_COPY);
	if(olecmdf & OLECMDF_ENABLED) return TRUE;
	return FALSE;
}

BOOL  CaplHtmlView::CanPaste()
{
	OLECMDF olecmdf = QueryStatusWB (OLECMDID_PASTE);
	if(olecmdf & OLECMDF_ENABLED) return TRUE;
	return FALSE;
}



BOOL CaplHtmlView::PreTranslateMessage(MSG* pMsg)
{
	// TODO: Add your specialized code here and/or call the base class
	if(pMsg->message== WM_LBUTTONDOWN)
	{
		// Это чтобы родитель мог обновить состояние кнопок
		CWnd* parent = GetParent();
		if(parent)
		{
			m_nmh.code = EN_SELCHANGE;    // Message type defined by control.
			m_nmh.idFrom = GetDlgCtrlID();
			m_nmh.hwndFrom = m_hWnd;
			parent->PostMessage(WM_NOTIFY, m_nmh.idFrom, (LPARAM)&m_nmh);
		}
	}
	return CHtmlView::PreTranslateMessage(pMsg);
}
