// 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

#ifndef _PWL_EDIT_H_
#define _PWL_EDIT_H_

class IPWL_Filler_Notify;
class CPWL_Edit;
class IPWL_SpellCheck;

class IPWL_Filler_Notify
{
public:
        virtual ~IPWL_Filler_Notify() { }
	virtual void					QueryWherePopup(void* pPrivateData, FX_FLOAT fPopupMin,FX_FLOAT fPopupMax, 
										FX_INT32 & nRet, FX_FLOAT & fPopupRet) = 0; //nRet: (0:bottom 1:top)
	virtual void					OnBeforeKeyStroke(FX_BOOL bEditOrList, void* pPrivateData, FX_INT32 nKeyCode,
										CFX_WideString & strChange, const CFX_WideString& strChangeEx, 
										int nSelStart, int nSelEnd,
										FX_BOOL bKeyDown, FX_BOOL & bRC, FX_BOOL & bExit, FX_DWORD nFlag) = 0;
	virtual void					OnAfterKeyStroke(FX_BOOL bEditOrList, void* pPrivateData, FX_BOOL & bExit, FX_DWORD nFlag) = 0;
};

class PWL_CLASS CPWL_Edit : public CPWL_EditCtrl, public IFX_Edit_OprNotify
{
public:
	CPWL_Edit();
	virtual ~CPWL_Edit();

public:
	virtual CFX_ByteString			GetClassName() const;
	virtual void					OnDestroy();
	virtual void					OnCreated();
	virtual void					RePosChildWnd();
	virtual CPDF_Rect				GetClientRect() const;

	virtual void					GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream);
	virtual void					DrawThisAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device);

	virtual FX_BOOL					OnLButtonDown(const CPDF_Point & point, FX_DWORD nFlag);
	virtual FX_BOOL					OnLButtonDblClk(const CPDF_Point & point, FX_DWORD nFlag);
	virtual FX_BOOL					OnRButtonUp(const CPDF_Point & point, FX_DWORD nFlag);
	virtual FX_BOOL					OnMouseWheel(short zDelta, const CPDF_Point & point, FX_DWORD nFlag);

	virtual FX_BOOL					OnKeyDown(FX_WORD nChar, FX_DWORD nFlag);
	virtual FX_BOOL					OnChar(FX_WORD nChar, FX_DWORD nFlag);

	virtual CPDF_Rect				GetFocusRect() const;

public:		
	void							SetAlignFormatH(PWL_EDIT_ALIGNFORMAT_H nFormat = PEAH_LEFT, FX_BOOL bPaint = TRUE);	//0:left 1:right 2:middle 
	void							SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat = PEAV_TOP, FX_BOOL bPaint = TRUE);	//0:top 1:bottom 2:center

	void							SetCharArray(FX_INT32 nCharArray);
	void							SetLimitChar(FX_INT32 nLimitChar);

	void							SetHorzScale(FX_INT32 nHorzScale, FX_BOOL bPaint = TRUE);
	void							SetCharSpace(FX_FLOAT fCharSpace, FX_BOOL bPaint = TRUE);

	void							SetLineLeading(FX_FLOAT fLineLeading, FX_BOOL bPaint = TRUE);

	void							EnableSpellCheck(FX_BOOL bEnabled);

	FX_BOOL							CanSelectAll() const;
	FX_BOOL							CanClear() const;
	FX_BOOL							CanCopy() const;
	FX_BOOL							CanCut() const;
	FX_BOOL							CanPaste() const;

	virtual void					CopyText();
	virtual void					PasteText();
	virtual void 					CutText();

	virtual void					SetText(FX_LPCWSTR csText);
	void							ReplaceSel(FX_LPCWSTR csText);

	CFX_ByteString					GetTextAppearanceStream(const CPDF_Point & ptOffset) const;
	CFX_ByteString					GetCaretAppearanceStream(const CPDF_Point & ptOffset) const;	
	CFX_ByteString					GetSelectAppearanceStream(const CPDF_Point & ptOffset) const;

	FX_BOOL							IsTextFull() const;	

	static FX_FLOAT					GetCharArrayAutoFontSize(CPDF_Font* pFont, const CPDF_Rect& rcPlate, FX_INT32 nCharArray);

	void							SetFillerNotify(IPWL_Filler_Notify* pNotify) {m_pFillerNotify = pNotify;}

	void							GeneratePageObjects(CPDF_PageObjects* pPageObjects, 
										const CPDF_Point& ptOffset, CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray);
	void							GeneratePageObjects(CPDF_PageObjects* pPageObjects, 
										const CPDF_Point& ptOffset);

protected:
	virtual void					OnSetFocus();
	virtual void					OnKillFocus();

protected:
	virtual void					OnInsertWord(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace);
	virtual void					OnInsertReturn(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace);
	virtual void					OnBackSpace(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace);
	virtual void					OnDelete(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace);
	virtual void					OnClear(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace);
	virtual void					OnSetText(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace);
	virtual void					OnInsertText(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace);
	virtual void					OnAddUndo(IFX_Edit_UndoItem* pUndoItem);

private:	
	CPVT_WordRange					GetSelectWordRange() const;
	virtual void					ShowVScrollBar(FX_BOOL bShow);
	FX_BOOL							IsVScrollBarVisible() const;
	void							SetParamByFlag();

	FX_FLOAT						GetCharArrayAutoFontSize(FX_INT32 nCharArray);
	CPDF_Point						GetWordRightBottomPoint(const CPVT_WordPlace& wpWord);

	CPVT_WordRange					CombineWordRange(const CPVT_WordRange& wr1, const CPVT_WordRange& wr2);
	CPVT_WordRange					GetLatinWordsRange(const CPDF_Point & point) const;
	CPVT_WordRange					GetLatinWordsRange(const CPVT_WordPlace & place) const;
	CPVT_WordRange					GetArabicWordsRange(const CPVT_WordPlace & place) const;
	CPVT_WordRange					GetSameWordsRange(const CPVT_WordPlace & place, FX_BOOL bLatin, FX_BOOL bArabic) const;

	void							AjustArabicWords(const CPVT_WordRange& wr);
public:
	FX_BOOL							IsProceedtoOnChar(FX_WORD nKeyCode, FX_DWORD nFlag);
private:
	IPWL_Filler_Notify*				m_pFillerNotify;
	IPWL_SpellCheck*				m_pSpellCheck;
	FX_BOOL							m_bFocus;
	CPDF_Rect						m_rcOldWindow;
public:
	void							AttachFFLData(void* pData) {m_pFormFiller = pData;}
private:
	void*							m_pFormFiller;
};

#endif 

