// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "../../../core/include/fxcrt/fx_safe_types.h"
#include "../../../core/include/fxcrt/fx_xml.h"
#include "../../include/pdfwindow/PDFWindow.h"
#include "../../include/pdfwindow/PWL_Caret.h"
#include "../../include/pdfwindow/PWL_Edit.h"
#include "../../include/pdfwindow/PWL_EditCtrl.h"
#include "../../include/pdfwindow/PWL_FontMap.h"
#include "../../include/pdfwindow/PWL_ScrollBar.h"
#include "../../include/pdfwindow/PWL_Utils.h"
#include "../../include/pdfwindow/PWL_Wnd.h"

/* ---------------------------- CPWL_Edit ------------------------------ */

CPWL_Edit::CPWL_Edit() : m_pFillerNotify(NULL),
	m_pSpellCheck(NULL),
	m_bFocus(false)
{
	m_pFormFiller = NULL;
}

CPWL_Edit::~CPWL_Edit()
{
	ASSERT(m_bFocus == false);
}

CFX_ByteString CPWL_Edit::GetClassName() const
{
	return PWL_CLASSNAME_EDIT;
}

void CPWL_Edit::OnDestroy()
{
}

void CPWL_Edit::SetText(const FX_WCHAR* csText)
{
	CFX_WideString swText = csText;

	if (HasFlag(PES_RICH))
	{
		CFX_ByteString sValue = CFX_ByteString::FromUnicode(swText);

		if (CXML_Element * pXML = CXML_Element::Parse(sValue.c_str(), sValue.GetLength()))
		{
			int32_t nCount = pXML->CountChildren();
			bool bFirst = true;

			swText.Empty();

			for (int32_t i=0; i<nCount; i++)
			{
				if (CXML_Element * pSubElement = pXML->GetElement(i))
				{
					CFX_ByteString tag=pSubElement->GetTagName();
		   			if (tag.EqualNoCase("p"))
					{
						int nChild = pSubElement->CountChildren();
						CFX_WideString swSection;
						for(int32_t j=0; j<nChild; j++)
						{
							swSection += pSubElement->GetContent(j);
						}

						if (bFirst)bFirst = false;
						else
							swText += FWL_VKEY_Return;
						swText += swSection;
					}
				}
			}

			delete pXML;
		}
	}

	m_pEdit->SetText(swText.c_str());
}

void CPWL_Edit::RePosChildWnd()
{
    if (CPWL_ScrollBar * pVSB = GetVScrollBar()) {
        CPDF_Rect rcWindow = m_rcOldWindow;
        CPDF_Rect rcVScroll = CPDF_Rect(rcWindow.right,
                                        rcWindow.bottom,
                                        rcWindow.right + PWL_SCROLLBAR_WIDTH,
                                        rcWindow.top);
        pVSB->Move(rcVScroll, true, false);
    }

	if (m_pEditCaret && !HasFlag(PES_TEXTOVERFLOW))
		m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect(GetClientRect(),1.0f)); //+1 for caret beside border

	CPWL_EditCtrl::RePosChildWnd();
}

CPDF_Rect CPWL_Edit::GetClientRect() const
{
	CPDF_Rect rcClient = CPWL_Utils::DeflateRect(GetWindowRect(),(FX_FLOAT)(GetBorderWidth()+GetInnerBorderWidth()));

	if (CPWL_ScrollBar * pVSB = GetVScrollBar())
	{
		if (pVSB->IsVisible())
		{
			rcClient.right -= PWL_SCROLLBAR_WIDTH;
		}
	}

	return rcClient;
}

void CPWL_Edit::SetAlignFormatH(PWL_EDIT_ALIGNFORMAT_H nFormat, bool bPaint/* = true*/)
{
	m_pEdit->SetAlignmentH((int32_t)nFormat, bPaint);
}

void CPWL_Edit::SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat, bool bPaint/* = true*/)
{
	m_pEdit->SetAlignmentV((int32_t)nFormat, bPaint);
}

bool	CPWL_Edit::CanSelectAll() const
{
	return  GetSelectWordRange() != m_pEdit->GetWholeWordRange();
}

bool	CPWL_Edit::CanClear() const
{
	return !IsReadOnly() && m_pEdit->IsSelected();
}

bool	CPWL_Edit::CanCopy() const
{
	return 	!HasFlag(PES_PASSWORD) && !HasFlag(PES_NOREAD) && m_pEdit->IsSelected();
}

bool	CPWL_Edit::CanCut() const
{
	return 	CanCopy() && !IsReadOnly();
}

bool	CPWL_Edit::CanPaste() const
{
	if (IsReadOnly()) return false;

	CFX_WideString swClipboard;
	if (IFX_SystemHandler* pSH = GetSystemHandler())
		swClipboard = pSH->GetClipboardText(GetAttachedHWnd());

	return !swClipboard.IsEmpty();
}

void CPWL_Edit::CopyText()
{
	if (!CanCopy()) return;

	CFX_WideString str = m_pEdit->GetSelText();

	if (IFX_SystemHandler* pSH = GetSystemHandler())
		pSH->SetClipboardText(GetAttachedHWnd(), str);
}

void CPWL_Edit::PasteText()
{
	if (!CanPaste()) return;

	CFX_WideString swClipboard;
	if (IFX_SystemHandler* pSH = GetSystemHandler())
		swClipboard = pSH->GetClipboardText(GetAttachedHWnd());

	if (m_pFillerNotify)
	{
		bool bRC = true;
		bool bExit = false;
		CFX_WideString strChangeEx;
		int nSelStart = 0;
		int nSelEnd = 0;
		GetSel(nSelStart, nSelEnd);
		m_pFillerNotify->OnBeforeKeyStroke(true, GetAttachedData(), 0 , swClipboard, strChangeEx, nSelStart, nSelEnd, true, bRC, bExit, 0);
		if (!bRC) return;
		if (bExit) return;
	}

	if (swClipboard.GetLength() > 0)
	{
		Clear();
		InsertText(swClipboard.c_str());
	}

	if (m_pFillerNotify)
	{
		bool bExit = false;
		m_pFillerNotify->OnAfterKeyStroke(true, GetAttachedData(), bExit,0);
		if (bExit) return;
	}
}

void CPWL_Edit::CutText()
{
	if (!CanCut()) return;

	CFX_WideString str = m_pEdit->GetSelText();

	if (IFX_SystemHandler* pSH = GetSystemHandler())
		pSH->SetClipboardText(GetAttachedHWnd(), str);

	m_pEdit->Clear();
}

void CPWL_Edit::OnCreated()
{
	CPWL_EditCtrl::OnCreated();

	if (CPWL_ScrollBar * pScroll = GetVScrollBar())
	{
		pScroll->RemoveFlag(PWS_AUTOTRANSPARENT);
		pScroll->SetTransparency(255);
	}

	SetParamByFlag();

	m_rcOldWindow = GetWindowRect();

	m_pEdit->SetOprNotify(this);
	m_pEdit->EnableOprNotify(true);
}

void CPWL_Edit::SetParamByFlag()
{
	if (HasFlag(PES_RIGHT))
	{
		m_pEdit->SetAlignmentH(2, false);
	}
	else if (HasFlag(PES_MIDDLE))
	{
		m_pEdit->SetAlignmentH(1, false);
	}
	else
	{
		m_pEdit->SetAlignmentH(0, false);
	}

	if (HasFlag(PES_BOTTOM))
	{
		m_pEdit->SetAlignmentV(2, false);
	}
	else if (HasFlag(PES_CENTER))
	{
		m_pEdit->SetAlignmentV(1, false);
	}
	else
	{
		m_pEdit->SetAlignmentV(0, false);
	}

	if (HasFlag(PES_PASSWORD))
	{
		m_pEdit->SetPasswordChar('*', false);
	}

	m_pEdit->SetMultiLine(HasFlag(PES_MULTILINE), false);
	m_pEdit->SetAutoReturn(HasFlag(PES_AUTORETURN), false);
	m_pEdit->SetAutoFontSize(HasFlag(PWS_AUTOFONTSIZE), false);
	m_pEdit->SetAutoScroll(HasFlag(PES_AUTOSCROLL), false);
	m_pEdit->EnableUndo(HasFlag(PES_UNDO));

	if (HasFlag(PES_TEXTOVERFLOW))
	{
		SetClipRect(CPDF_Rect(0.0f,0.0f,0.0f,0.0f));
		m_pEdit->SetTextOverflow(true, false);
	}
	else
	{
		if (m_pEditCaret)
		{
			m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect(GetClientRect(),1.0f)); //+1 for caret beside border
		}
	}

	if (HasFlag(PES_SPELLCHECK))
	{
		m_pSpellCheck = GetCreationParam().pSpellCheck;
	}
}

void CPWL_Edit::GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)
{
	CPWL_Wnd::GetThisAppearanceStream(sAppStream);

	CPDF_Rect rcClient = GetClientRect();
	CFX_ByteTextBuf sLine;

	int32_t nCharArray = m_pEdit->GetCharArray();

	if (nCharArray > 0)
	{
		switch (GetBorderStyle())
		{
		case PBS_SOLID:
			{
				sLine << "q\n" << GetBorderWidth() << " w\n"
					<< CPWL_Utils::GetColorAppStream(GetBorderColor(),false) << " 2 J 0 j\n";

				for (int32_t i=1;i<nCharArray;i++)
				{
					sLine << rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "
						<< rcClient.bottom << " m\n"
						<< rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "
						<< rcClient.top << " l S\n";
				}

				sLine << "Q\n";
			}
			break;
		case PBS_DASH:
			{
				sLine << "q\n" << GetBorderWidth() << " w\n"
					<< CPWL_Utils::GetColorAppStream(GetBorderColor(),false) << " 2 J 0 j\n"
					<< "[" << GetBorderDash().nDash << " "
					<< GetBorderDash().nGap << "] "
					<< GetBorderDash().nPhase << " d\n";

				for (int32_t i=1;i<nCharArray;i++)
				{
					sLine << rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "
						<< rcClient.bottom << " m\n"
						<< rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "
						<< rcClient.top << " l S\n";
				}

				sLine << "Q\n";
			}
			break;
		}
	}

	sAppStream << sLine;

	CFX_ByteTextBuf sText;

	CPDF_Point ptOffset = CPDF_Point(0.0f,0.0f);

	CPVT_WordRange wrWhole = m_pEdit->GetWholeWordRange();
	CPVT_WordRange wrSelect = GetSelectWordRange();
	CPVT_WordRange wrVisible = (HasFlag(PES_TEXTOVERFLOW) ? wrWhole : m_pEdit->GetVisibleWordRange());
	CPVT_WordRange wrSelBefore(wrWhole.BeginPos,wrSelect.BeginPos);
	CPVT_WordRange wrSelAfter(wrSelect.EndPos,wrWhole.EndPos);

	CPVT_WordRange wrTemp = CPWL_Utils::OverlapWordRange(GetSelectWordRange(),wrVisible);
	CFX_ByteString sEditSel = CPWL_Utils::GetEditSelAppStream(m_pEdit, ptOffset,
			&wrTemp);

	if (sEditSel.GetLength() > 0)
		sText << CPWL_Utils::GetColorAppStream(PWL_DEFAULT_SELBACKCOLOR) << sEditSel ;

	wrTemp = CPWL_Utils::OverlapWordRange(wrVisible,wrSelBefore);
	CFX_ByteString sEditBefore = CPWL_Utils::GetEditAppStream(m_pEdit, ptOffset,
			&wrTemp, !HasFlag(PES_CHARARRAY), m_pEdit->GetPasswordChar());

	if (sEditBefore.GetLength() > 0)
		sText << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor()) << sEditBefore << "ET\n";

	wrTemp = CPWL_Utils::OverlapWordRange(wrVisible,wrSelect);
	CFX_ByteString sEditMid = CPWL_Utils::GetEditAppStream(m_pEdit, ptOffset,
			&wrTemp, !HasFlag(PES_CHARARRAY), m_pEdit->GetPasswordChar());

	if (sEditMid.GetLength() > 0)
		sText << "BT\n" << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_GRAY,1)) << sEditMid << "ET\n";

	wrTemp = CPWL_Utils::OverlapWordRange(wrVisible,wrSelAfter);
	CFX_ByteString sEditAfter = CPWL_Utils::GetEditAppStream(m_pEdit, ptOffset,
			&wrTemp, !HasFlag(PES_CHARARRAY), m_pEdit->GetPasswordChar());

	if (sEditAfter.GetLength() > 0)
		sText << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor()) << sEditAfter<< "ET\n";

	if (HasFlag(PES_SPELLCHECK))
	{
		CFX_ByteString sSpellCheck = CPWL_Utils::GetSpellCheckAppStream(m_pEdit, m_pSpellCheck, ptOffset, &wrVisible);
		if (sSpellCheck.GetLength() > 0)
			sText << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_RGB,1,0,0),false) << sSpellCheck;
	}

	if (sText.GetLength() > 0)
	{
		CPDF_Rect rcClient = GetClientRect();
		sAppStream << "q\n/Tx BMC\n";

		if (!HasFlag(PES_TEXTOVERFLOW))
			sAppStream << rcClient.left << " " << rcClient.bottom << " "
				<< rcClient.right - rcClient.left << " " << rcClient.top - rcClient.bottom << " re W n\n";

		sAppStream << sText;

		sAppStream << "EMC\nQ\n";
	}
}

void CPWL_Edit::DrawThisAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
{
	CPWL_Wnd::DrawThisAppearance(pDevice,pUser2Device);

	CPDF_Rect rcClient = GetClientRect();
	CFX_ByteTextBuf sLine;

	int32_t nCharArray = m_pEdit->GetCharArray();
	FX_SAFE_INT32 nCharArraySafe = nCharArray;
	nCharArraySafe -= 1;
	nCharArraySafe *= 2;

	if (nCharArray > 0 && nCharArraySafe.IsValid())
	{
		switch (GetBorderStyle())
		{
		case PBS_SOLID:
			{
				CFX_GraphStateData gsd;
				gsd.m_LineWidth = (FX_FLOAT)GetBorderWidth();

				CFX_PathData path;
				path.SetPointCount(nCharArraySafe.ValueOrDie());

				for (int32_t i=0; i<nCharArray-1; i++)
				{
					path.SetPoint(i*2, rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*(i+1),
						rcClient.bottom, FXPT_MOVETO);
					path.SetPoint(i*2+1, rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*(i+1),
						rcClient.top, FXPT_LINETO);
				}
				if (path.GetPointCount() > 0)
					pDevice->DrawPath(&path, pUser2Device, &gsd,0,
						CPWL_Utils::PWLColorToFXColor(GetBorderColor(),255), FXFILL_ALTERNATE);
			}
			break;
		case PBS_DASH:
			{
				CFX_GraphStateData gsd;
				gsd.m_LineWidth = (FX_FLOAT)GetBorderWidth();

				gsd.SetDashCount(2);
				gsd.m_DashArray[0] = (FX_FLOAT)GetBorderDash().nDash;
				gsd.m_DashArray[1] = (FX_FLOAT)GetBorderDash().nGap;
				gsd.m_DashPhase = (FX_FLOAT)GetBorderDash().nPhase;

				CFX_PathData path;
				path.SetPointCount(nCharArraySafe.ValueOrDie());

				for (int32_t i=0; i<nCharArray-1; i++)
				{
					path.SetPoint(i*2, rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*(i+1),
						rcClient.bottom, FXPT_MOVETO);
					path.SetPoint(i*2+1, rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*(i+1),
						rcClient.top, FXPT_LINETO);
				}
				if (path.GetPointCount() > 0)
					pDevice->DrawPath(&path, pUser2Device, &gsd,0,
						CPWL_Utils::PWLColorToFXColor(GetBorderColor(),255), FXFILL_ALTERNATE);
			}
			break;
		}
	}

	CPDF_Rect rcClip;
	CPVT_WordRange wrRange = m_pEdit->GetVisibleWordRange();
	CPVT_WordRange* pRange = NULL;

	if (!HasFlag(PES_TEXTOVERFLOW))
	{
		rcClip = GetClientRect();
		pRange = &wrRange;
	}
IFX_SystemHandler* pSysHandler = GetSystemHandler();
	IFX_Edit::DrawEdit(pDevice,pUser2Device,m_pEdit,
		CPWL_Utils::PWLColorToFXColor(GetTextColor(), GetTransparency()),
		CPWL_Utils::PWLColorToFXColor(GetTextStrokeColor(), GetTransparency()),
		rcClip,CPDF_Point(0.0f,0.0f),pRange, pSysHandler, m_pFormFiller);

	if (HasFlag(PES_SPELLCHECK))
	{
		CPWL_Utils::DrawEditSpellCheck(pDevice,pUser2Device,m_pEdit,rcClip,
			CPDF_Point(0.0f,0.0f),pRange, GetCreationParam().pSpellCheck);
	}
}

bool CPWL_Edit::OnLButtonDown(const CPDF_Point & point, FX_DWORD nFlag)
{
	CPWL_Wnd::OnLButtonDown(point,nFlag);

	if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point))
	{
		if (m_bMouseDown)
			InvalidateRect();

		m_bMouseDown = true;
		SetCapture();

		m_pEdit->OnMouseDown(point,IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
	}

	return true;
}

bool	CPWL_Edit::OnLButtonDblClk(const CPDF_Point & point, FX_DWORD nFlag)
{
	CPWL_Wnd::OnLButtonDblClk(point, nFlag);

	if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point))
	{
		m_pEdit->SelectAll();
	}

	return true;
}

#define WM_PWLEDIT_UNDO					0x01
#define WM_PWLEDIT_REDO					0x02
#define WM_PWLEDIT_CUT					0x03
#define WM_PWLEDIT_COPY					0x04
#define WM_PWLEDIT_PASTE				0x05
#define WM_PWLEDIT_DELETE				0x06
#define WM_PWLEDIT_SELECTALL			0x07
#define WM_PWLEDIT_SUGGEST				0x08

bool CPWL_Edit::OnRButtonUp(const CPDF_Point & point, FX_DWORD nFlag)
{
	if (m_bMouseDown) return false;

	CPWL_Wnd::OnRButtonUp(point, nFlag);

	if (!HasFlag(PES_TEXTOVERFLOW) && !ClientHitTest(point)) return true;

	IFX_SystemHandler* pSH = GetSystemHandler();
	if (!pSH) return false;

	SetFocus();

	CPVT_WordRange wrLatin = GetLatinWordsRange(point);
	CFX_WideString swLatin = m_pEdit->GetRangeText(wrLatin);

	FX_HMENU hPopup = pSH->CreatePopupMenu();
	if (!hPopup) return false;

	CFX_ByteStringArray sSuggestWords;
	CPDF_Point ptPopup = point;

	if (!IsReadOnly())
	{
		if (HasFlag(PES_SPELLCHECK) && !swLatin.IsEmpty())
		{
			if (m_pSpellCheck)
			{
				CFX_ByteString sLatin = CFX_ByteString::FromUnicode(swLatin);

				if (!m_pSpellCheck->CheckWord(sLatin))
				{
					m_pSpellCheck->SuggestWords(sLatin,sSuggestWords);

					int32_t nSuggest = sSuggestWords.GetSize();

					for (int32_t nWord=0; nWord<nSuggest; nWord++)
					{
						pSH->AppendMenuItem(hPopup, WM_PWLEDIT_SUGGEST+nWord, sSuggestWords[nWord].UTF8Decode());
					}

					if (nSuggest > 0)
						pSH->AppendMenuItem(hPopup, 0, L"");

					ptPopup = GetWordRightBottomPoint(wrLatin.EndPos);
				}
			}
		}
	}

	IPWL_Provider* pProvider = GetProvider();

	if (HasFlag(PES_UNDO))
	{
		pSH->AppendMenuItem(hPopup, WM_PWLEDIT_UNDO,
			pProvider ? pProvider->LoadPopupMenuString(0) : L"&Undo");
		pSH->AppendMenuItem(hPopup, WM_PWLEDIT_REDO,
			pProvider ? pProvider->LoadPopupMenuString(1) : L"&Redo");
		pSH->AppendMenuItem(hPopup, 0, L"");

		if (!m_pEdit->CanUndo())
			pSH->EnableMenuItem(hPopup, WM_PWLEDIT_UNDO, false);
		if (!m_pEdit->CanRedo())
			pSH->EnableMenuItem(hPopup, WM_PWLEDIT_REDO, false);
	}

	pSH->AppendMenuItem(hPopup, WM_PWLEDIT_CUT,
		pProvider ? pProvider->LoadPopupMenuString(2) : L"Cu&t");
	pSH->AppendMenuItem(hPopup, WM_PWLEDIT_COPY,
		pProvider ? pProvider->LoadPopupMenuString(3) : L"&Copy");
	pSH->AppendMenuItem(hPopup, WM_PWLEDIT_PASTE,
		pProvider ? pProvider->LoadPopupMenuString(4) : L"&Paste");
	pSH->AppendMenuItem(hPopup, WM_PWLEDIT_DELETE,
		pProvider ? pProvider->LoadPopupMenuString(5) : L"&Delete");

	CFX_WideString swText = pSH->GetClipboardText(GetAttachedHWnd());
	if (swText.IsEmpty())
		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_PASTE, false);

	if (!m_pEdit->IsSelected())
	{
		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, false);
		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_COPY, false);
		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_DELETE, false);
	}

	if (IsReadOnly())
	{
		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, false);
		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_DELETE, false);
		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_PASTE, false);
	}

	if (HasFlag(PES_PASSWORD))
	{
		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, false);
		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_COPY, false);
	}

	if (HasFlag(PES_NOREAD))
	{
		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, false);
		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_COPY, false);
	}

	pSH->AppendMenuItem(hPopup, 0, L"");
	pSH->AppendMenuItem(hPopup, WM_PWLEDIT_SELECTALL,
		pProvider ? pProvider->LoadPopupMenuString(6) : L"&Select All");

	if (m_pEdit->GetTotalWords() == 0)
	{
		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_SELECTALL, false);
	}

	int32_t x, y;
	PWLtoWnd(ptPopup, x, y);
	pSH->ClientToScreen(GetAttachedHWnd(), x, y);
	pSH->SetCursor(FXCT_ARROW);
	int32_t nCmd = pSH->TrackPopupMenu(hPopup,
					 x,
					 y,
					 GetAttachedHWnd());


	switch (nCmd)
	{
	case WM_PWLEDIT_UNDO:
		Undo();
		break;
	case WM_PWLEDIT_REDO:
		Redo();
		break;
	case WM_PWLEDIT_CUT:
		CutText();
		break;
	case WM_PWLEDIT_COPY:
		CopyText();
		break;
	case WM_PWLEDIT_PASTE:
		PasteText();
		break;
	case WM_PWLEDIT_DELETE:
		Clear();
		break;
	case WM_PWLEDIT_SELECTALL:
		SelectAll();
		break;
	case WM_PWLEDIT_SUGGEST + 0:
		SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
		ReplaceSel(sSuggestWords[0].UTF8Decode().c_str());
		break;
	case WM_PWLEDIT_SUGGEST + 1:
		SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
		ReplaceSel(sSuggestWords[1].UTF8Decode().c_str());
		break;
	case WM_PWLEDIT_SUGGEST + 2:
		SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
		ReplaceSel(sSuggestWords[2].UTF8Decode().c_str());
		break;
	case WM_PWLEDIT_SUGGEST + 3:
		SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
		ReplaceSel(sSuggestWords[3].UTF8Decode().c_str());
		break;
	case WM_PWLEDIT_SUGGEST + 4:
		SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
		ReplaceSel(sSuggestWords[4].UTF8Decode().c_str());
		break;
	default:
		break;
	}

	pSH->DestroyMenu(hPopup);

	return true;
}

void CPWL_Edit::OnSetFocus()
{
	SetEditCaret(true);

	if (!IsReadOnly())
	{
		if (IPWL_FocusHandler* pFocusHandler = GetFocusHandler())
			pFocusHandler->OnSetFocus(this);
	}

	m_bFocus = true;
}

void CPWL_Edit::OnKillFocus()
{
	ShowVScrollBar(false);

	m_pEdit->SelectNone();
	SetCaret(false, CPDF_Point(0.0f,0.0f), CPDF_Point(0.0f,0.0f));

	SetCharSet(0);

	if (!IsReadOnly())
	{
		if (IPWL_FocusHandler* pFocusHandler = GetFocusHandler())
			pFocusHandler->OnKillFocus(this);
	}

	m_bFocus = false;
}

void CPWL_Edit::SetHorzScale(int32_t nHorzScale, bool bPaint/* = true*/)
{
	m_pEdit->SetHorzScale(nHorzScale, bPaint);
}

void CPWL_Edit::SetCharSpace(FX_FLOAT fCharSpace, bool bPaint/* = true*/)
{
	m_pEdit->SetCharSpace(fCharSpace, bPaint);
}

void CPWL_Edit::SetLineLeading(FX_FLOAT fLineLeading, bool bPaint/* = true*/)
{
	m_pEdit->SetLineLeading(fLineLeading, bPaint);
}

CFX_ByteString CPWL_Edit::GetSelectAppearanceStream(const CPDF_Point & ptOffset) const
{
	CPVT_WordRange wr = GetSelectWordRange();
	return CPWL_Utils::GetEditSelAppStream(m_pEdit,ptOffset,&wr);
}

CPVT_WordRange CPWL_Edit::GetSelectWordRange() const
{
	if (m_pEdit->IsSelected())
	{
		int32_t nStart = -1;
		int32_t nEnd = -1;

		m_pEdit->GetSel(nStart, nEnd);

		CPVT_WordPlace wpStart = m_pEdit->WordIndexToWordPlace(nStart);
		CPVT_WordPlace wpEnd = m_pEdit->WordIndexToWordPlace(nEnd);

		return CPVT_WordRange(wpStart,wpEnd);
	}

	return CPVT_WordRange();
}

CFX_ByteString CPWL_Edit::GetTextAppearanceStream(const CPDF_Point & ptOffset) const
{
	CFX_ByteTextBuf sRet;
	CFX_ByteString sEdit = CPWL_Utils::GetEditAppStream(m_pEdit,ptOffset);

	if (sEdit.GetLength() > 0)
	{
		sRet << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor()) << sEdit << "ET\n";
	}

	return sRet.GetByteString();
}

CFX_ByteString CPWL_Edit::GetCaretAppearanceStream(const CPDF_Point & ptOffset) const
{
	if (m_pEditCaret)
		return m_pEditCaret->GetCaretAppearanceStream(ptOffset);

	return CFX_ByteString();
}

CPDF_Point CPWL_Edit::GetWordRightBottomPoint(const CPVT_WordPlace& wpWord)
{
	CPDF_Point pt(0.0f, 0.0f);

	if (IFX_Edit_Iterator * pIterator = m_pEdit->GetIterator())
	{
		CPVT_WordPlace wpOld = pIterator->GetAt();
		pIterator->SetAt(wpWord);
		CPVT_Word word;
		if (pIterator->GetWord(word))
		{
			pt = CPDF_Point(word.ptWord.x + word.fWidth, word.ptWord.y + word.fDescent);
		}

		pIterator->SetAt(wpOld);
	}

	return pt;
}

bool	CPWL_Edit::IsTextFull() const
{
	return m_pEdit->IsTextFull();
}

FX_FLOAT CPWL_Edit::GetCharArrayAutoFontSize(CPDF_Font* pFont, const CPDF_Rect& rcPlate, int32_t nCharArray)
{
	if (pFont && !pFont->IsStandardFont())
	{
		FX_RECT rcBBox;
		pFont->GetFontBBox(rcBBox);

		CPDF_Rect rcCell = rcPlate;
		FX_FLOAT xdiv = rcCell.Width() / nCharArray * 1000.0f / rcBBox.Width();
		FX_FLOAT ydiv = - rcCell.Height() * 1000.0f / rcBBox.Height();

		return xdiv < ydiv ? xdiv : ydiv;
	}

	return 0.0f;
}

void CPWL_Edit::SetCharArray(int32_t nCharArray)
{
	if (HasFlag(PES_CHARARRAY) && nCharArray > 0)
	{
		m_pEdit->SetCharArray(nCharArray);
		m_pEdit->SetTextOverflow(true);

		if (HasFlag(PWS_AUTOFONTSIZE))
		{
			if (IFX_Edit_FontMap* pFontMap = GetFontMap())
			{
				FX_FLOAT fFontSize = GetCharArrayAutoFontSize(pFontMap->GetPDFFont(0), GetClientRect(), nCharArray);
				if (fFontSize > 0.0f)
				{
					m_pEdit->SetAutoFontSize(false);
					m_pEdit->SetFontSize(fFontSize);
				}
			}
		}
	}
}

void CPWL_Edit::SetLimitChar(int32_t nLimitChar)
{
	m_pEdit->SetLimitChar(nLimitChar);
}

void CPWL_Edit::ReplaceSel(const FX_WCHAR* csText)
{
	m_pEdit->Clear();
	m_pEdit->InsertText(csText);
}

CPDF_Rect CPWL_Edit::GetFocusRect() const
{
	return CPDF_Rect();
}

void CPWL_Edit::ShowVScrollBar(bool bShow)
{
	if (CPWL_ScrollBar * pScroll = GetVScrollBar())
	{
		if (bShow)
		{
			if (!pScroll->IsVisible())
			{
				pScroll->SetVisible(true);
				CPDF_Rect rcWindow = GetWindowRect();
				m_rcOldWindow = rcWindow;
				rcWindow.right += PWL_SCROLLBAR_WIDTH;
				Move(rcWindow, true, true);
			}
		}
		else
		{
			if (pScroll->IsVisible())
			{
				pScroll->SetVisible(false);
				Move(m_rcOldWindow, true, true);
			}
		}
	}
}

bool	CPWL_Edit::IsVScrollBarVisible() const
{
	if (CPWL_ScrollBar * pScroll = GetVScrollBar())
	{
		return pScroll->IsVisible();
	}

	return false;
}

void CPWL_Edit::EnableSpellCheck(bool bEnabled)
{
	if (bEnabled)
		AddFlag(PES_SPELLCHECK);
	else
		RemoveFlag(PES_SPELLCHECK);
}

bool CPWL_Edit::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag)
{
	if (m_bMouseDown) return true;

	if (nChar == FWL_VKEY_Delete)
	{
		if (m_pFillerNotify)
		{
			bool bRC = true;
			bool bExit = false;
			CFX_WideString strChange;
			CFX_WideString strChangeEx;

			int nSelStart = 0;
			int nSelEnd = 0;
			GetSel(nSelStart, nSelEnd);

			if (nSelStart == nSelEnd)
				nSelEnd = nSelStart + 1;
			m_pFillerNotify->OnBeforeKeyStroke(true, GetAttachedData(), FWL_VKEY_Delete, strChange, strChangeEx, nSelStart, nSelEnd, true, bRC, bExit, nFlag);
			if (!bRC) return false;
			if (bExit) return false;
		}
	}

	bool bRet = CPWL_EditCtrl::OnKeyDown(nChar,  nFlag);

	if (nChar == FWL_VKEY_Delete)
	{
		if (m_pFillerNotify)
		{
			bool bExit = false;
			m_pFillerNotify->OnAfterKeyStroke(true, GetAttachedData(), bExit,nFlag);
			if (bExit) return false;
		}
	}

	//In case of implementation swallow the OnKeyDown event.
	if(IsProceedtoOnChar(nChar, nFlag))
			return true;

	return bRet;
}

/**
*In case of implementation swallow the OnKeyDown event.
*If the event is swallowed, implementation may do other unexpected things, which is not the control means to do.
*/
bool CPWL_Edit::IsProceedtoOnChar(FX_WORD nKeyCode, FX_DWORD nFlag)
{

	bool bCtrl = IsCTRLpressed(nFlag);
	bool bAlt = IsALTpressed(nFlag);
	if(bCtrl && !bAlt)
	{
	//hot keys for edit control.
		switch(nKeyCode)
		{
		case 'C':
		case 'V':
		case 'X':
		case 'A':
		case 'Z':
			return true;
		default:
			break;
		}
	}
	//control characters.
	switch(nKeyCode)
	{
	case FWL_VKEY_Escape:
	case FWL_VKEY_Back:
	case FWL_VKEY_Return:
	case FWL_VKEY_Space:
		return true;
	default:
		break;
	}
	return false;

}

bool CPWL_Edit::OnChar(FX_WORD nChar, FX_DWORD nFlag)
{
	if (m_bMouseDown) return true;

	bool bRC = true;
	bool bExit = false;

	bool bCtrl = IsCTRLpressed(nFlag);
	if (!bCtrl)
	{
		if (m_pFillerNotify)
		{
			CFX_WideString swChange;
			int32_t nKeyCode;

			int nSelStart = 0;
			int nSelEnd = 0;
			GetSel(nSelStart, nSelEnd);

			switch (nChar)
			{
			case FWL_VKEY_Back:
				nKeyCode = nChar;
				if (nSelStart == nSelEnd)
					nSelStart = nSelEnd - 1;
				break;
			case FWL_VKEY_Return:
				nKeyCode = nChar;
				break;
			default:
				nKeyCode = 0;
				swChange += nChar;
				break;
			}

			CFX_WideString strChangeEx;
			m_pFillerNotify->OnBeforeKeyStroke(true, GetAttachedData(), nKeyCode, swChange, strChangeEx, nSelStart, nSelEnd, true, bRC, bExit, nFlag);
		}
	}

	if (!bRC) return true;
	if (bExit) return false;

	if (IFX_Edit_FontMap * pFontMap = GetFontMap())
	{
		int32_t nOldCharSet = GetCharSet();
		int32_t nNewCharSet = pFontMap->CharSetFromUnicode(nChar, DEFAULT_CHARSET);
		if(nOldCharSet != nNewCharSet)
		{
			SetCharSet(nNewCharSet);
		}
	}
	bool bRet = CPWL_EditCtrl::OnChar(nChar,nFlag);

	if (!bCtrl)
	{
		if (m_pFillerNotify)
		{
			m_pFillerNotify->OnAfterKeyStroke(true, GetAttachedData(), bExit,nFlag);
			if (bExit) return false;
		}
	}

	return bRet;
}

bool	CPWL_Edit::OnMouseWheel(short zDelta, const CPDF_Point & point, FX_DWORD nFlag)
{
	if (HasFlag(PES_MULTILINE))
	{
		CPDF_Point ptScroll = GetScrollPos();

		if (zDelta > 0)
		{
			ptScroll.y += GetFontSize();
		}
		else
		{
			ptScroll.y -= GetFontSize();
		}
		SetScrollPos(ptScroll);

		return true;
	}

	return false;
}

void CPWL_Edit::OnInsertReturn(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
{
	if (HasFlag(PES_SPELLCHECK))
	{
		m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));
	}

	if (m_pEditNotify)
	{
		m_pEditNotify->OnInsertReturn(place, oldplace);
	}
}

void CPWL_Edit::OnBackSpace(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
{
	if (HasFlag(PES_SPELLCHECK))
	{
		m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));
	}

	if (m_pEditNotify)
	{
		m_pEditNotify->OnBackSpace(place, oldplace);
	}
}

void CPWL_Edit::OnDelete(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
{
	if (HasFlag(PES_SPELLCHECK))
	{
		m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));
	}

	if (m_pEditNotify)
	{
		m_pEditNotify->OnDelete(place, oldplace);
	}
}

void CPWL_Edit::OnClear(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
{
	if (HasFlag(PES_SPELLCHECK))
	{
		m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));
	}

	if (m_pEditNotify)
	{
		m_pEditNotify->OnClear(place, oldplace);
	}
}

void CPWL_Edit::OnInsertWord(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
{
	if (HasFlag(PES_SPELLCHECK))
	{
		m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));
	}

	if (m_pEditNotify)
	{
		m_pEditNotify->OnInsertWord(place, oldplace);
	}
}

void CPWL_Edit::OnSetText(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
{
}

void CPWL_Edit::OnInsertText(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
{
	if (HasFlag(PES_SPELLCHECK))
	{
		m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));
	}

	if (m_pEditNotify)
	{
		m_pEditNotify->OnInsertText(place, oldplace);
	}
}

void CPWL_Edit::OnAddUndo(IFX_Edit_UndoItem* pUndoItem)
{
	if (m_pEditNotify)
	{
		m_pEditNotify->OnAddUndo(this);
	}
}

CPVT_WordRange CPWL_Edit::CombineWordRange(const CPVT_WordRange& wr1, const CPVT_WordRange& wr2)
{
	CPVT_WordRange wrRet;

	if (wr1.BeginPos.WordCmp(wr2.BeginPos) < 0)
	{
		wrRet.BeginPos = wr1.BeginPos;
	}
	else
	{
		wrRet.BeginPos = wr2.BeginPos;
	}

	if (wr1.EndPos.WordCmp(wr2.EndPos) < 0)
	{
		wrRet.EndPos = wr2.EndPos;
	}
	else
	{
		wrRet.EndPos = wr1.EndPos;
	}

	return wrRet;
}

CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CPDF_Point& point) const
{
	return GetSameWordsRange(m_pEdit->SearchWordPlace(point), true, false);
}

CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CPVT_WordPlace & place) const
{
	return GetSameWordsRange(place, true, false);
}

CPVT_WordRange CPWL_Edit::GetArabicWordsRange(const CPVT_WordPlace & place) const
{
	return GetSameWordsRange(place, false, true);
}

#define PWL_ISARABICWORD(word) ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC))

CPVT_WordRange CPWL_Edit::GetSameWordsRange(const CPVT_WordPlace & place, bool bLatin, bool bArabic) const
{
	CPVT_WordRange range;

	if (IFX_Edit_Iterator* pIterator = m_pEdit->GetIterator())
	{
		CPVT_Word wordinfo;
		CPVT_WordPlace wpStart(place),wpEnd(place);
		pIterator->SetAt(place);

		if (bLatin)
		{
			while (pIterator->NextWord())
			{
				if (pIterator->GetWord(wordinfo) && FX_EDIT_ISLATINWORD(wordinfo.Word))
				{
					wpEnd = pIterator->GetAt();
					continue;
				}
				else
					break;
			};
		}
		else if (bArabic)
		{
			while (pIterator->NextWord())
			{
				if (pIterator->GetWord(wordinfo) && PWL_ISARABICWORD(wordinfo.Word))
				{
					wpEnd = pIterator->GetAt();
					continue;
				}
				else
					break;
			};
		}

		pIterator->SetAt(place);

		if (bLatin)
		{
			do
			{
				if (pIterator->GetWord(wordinfo) && FX_EDIT_ISLATINWORD(wordinfo.Word))
				{
					continue;
				}
				else
				{
					wpStart = pIterator->GetAt();
					break;
				}
			}
			while (pIterator->PrevWord());
		}
		else if (bArabic)
		{
			do
			{
				if (pIterator->GetWord(wordinfo) && PWL_ISARABICWORD(wordinfo.Word))
				{
					continue;
				}
				else
				{
					wpStart = pIterator->GetAt();
					break;
				}
			}
			while (pIterator->PrevWord());
		}

		range.Set(wpStart,wpEnd);
	}

	return range;
}

void CPWL_Edit::AjustArabicWords(const CPVT_WordRange& wr)
{
}

void CPWL_Edit::GeneratePageObjects(CPDF_PageObjects* pPageObjects,
										const CPDF_Point& ptOffset, CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray)
{
	IFX_Edit::GeneratePageObjects(pPageObjects, m_pEdit, ptOffset, NULL, CPWL_Utils::PWLColorToFXColor(GetTextColor(),GetTransparency()), ObjArray);
}

void CPWL_Edit::GeneratePageObjects(CPDF_PageObjects* pPageObjects,
									const CPDF_Point& ptOffset)
{
	CFX_ArrayTemplate<CPDF_TextObject*> ObjArray;
	IFX_Edit::GeneratePageObjects(pPageObjects, m_pEdit, ptOffset, NULL, CPWL_Utils::PWLColorToFXColor(GetTextColor(),GetTransparency()), ObjArray);
}

