blob: e11807786941200aa9819b57e4043485abe9042c [file] [log] [blame] [edit]
// 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 FPDFSDK_PWL_CPWL_EDIT_IMPL_H_
#define FPDFSDK_PWL_CPWL_EDIT_IMPL_H_
#include <deque>
#include <memory>
#include <utility>
#include <vector>
#include "core/fpdfdoc/cpdf_variabletext.h"
#include "core/fpdfdoc/cpvt_wordrange.h"
#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/dib/fx_dib.h"
#define FX_EDIT_ISLATINWORD(u) \
(u == 0x2D || (u <= 0x005A && u >= 0x0041) || \
(u <= 0x007A && u >= 0x0061) || (u <= 0x02AF && u >= 0x00C0))
class CFFL_FormFiller;
class CPWL_EditImpl;
class CPWL_EditImpl_Iterator;
class CPWL_EditImpl_Provider;
class CFX_RenderDevice;
class CPWL_Edit;
class CPWL_EditCtrl;
class IPWL_SystemHandler;
class IFX_Edit_UndoItem;
struct CPWL_EditImpl_LineRect {
CPWL_EditImpl_LineRect(const CPVT_WordRange& wrLine,
const CFX_FloatRect& rcLine)
: m_wrLine(wrLine), m_rcLine(rcLine) {}
CPVT_WordRange m_wrLine;
CFX_FloatRect m_rcLine;
};
class CPWL_EditImpl_Refresh {
public:
CPWL_EditImpl_Refresh();
~CPWL_EditImpl_Refresh();
void BeginRefresh();
void Push(const CPVT_WordRange& linerange, const CFX_FloatRect& rect);
void NoAnalyse();
std::vector<CFX_FloatRect>* GetRefreshRects();
void EndRefresh();
private:
void Add(const CFX_FloatRect& new_rect);
std::vector<CPWL_EditImpl_LineRect> m_NewLineRects;
std::vector<CPWL_EditImpl_LineRect> m_OldLineRects;
std::vector<CFX_FloatRect> m_RefreshRects;
};
class CPWL_EditImpl_Select {
public:
CPWL_EditImpl_Select();
explicit CPWL_EditImpl_Select(const CPVT_WordRange& range);
void Reset();
void Set(const CPVT_WordPlace& begin, const CPVT_WordPlace& end);
void SetEndPos(const CPVT_WordPlace& end);
CPVT_WordRange ConvertToWordRange() const;
bool IsEmpty() const;
CPVT_WordPlace BeginPos;
CPVT_WordPlace EndPos;
};
class CPWL_EditImpl_Undo {
public:
CPWL_EditImpl_Undo();
~CPWL_EditImpl_Undo();
void AddItem(std::unique_ptr<IFX_Edit_UndoItem> pItem);
void Undo();
void Redo();
bool CanUndo() const;
bool CanRedo() const;
private:
void RemoveHeads();
void RemoveTails();
std::deque<std::unique_ptr<IFX_Edit_UndoItem>> m_UndoItemStack;
size_t m_nCurUndoPos;
bool m_bWorking;
};
class IFX_Edit_UndoItem {
public:
virtual ~IFX_Edit_UndoItem() = default;
// Undo/Redo the current undo item and returns the number of additional items
// to be processed in |m_UndoItemStack| to fully undo/redo the action. (An
// example is CFXEU_ReplaceSelection::Undo(), if CFXEU_ReplaceSelection marks
// the end of a replace action, CFXEU_ReplaceSelection::Undo() returns 3
// because 3 more undo items need to be processed to revert the replace
// action: insert text, clear selection and the CFXEU_ReplaceSelection which
// marks the beginning of replace action.) Implementations should return 0 by
// default.
virtual int Undo() = 0;
virtual int Redo() = 0;
};
class CFXEU_InsertWord final : public IFX_Edit_UndoItem {
public:
CFXEU_InsertWord(CPWL_EditImpl* pEdit,
const CPVT_WordPlace& wpOldPlace,
const CPVT_WordPlace& wpNewPlace,
uint16_t word,
int32_t charset);
~CFXEU_InsertWord() override;
// IFX_Edit_UndoItem:
int Redo() override;
int Undo() override;
private:
UnownedPtr<CPWL_EditImpl> m_pEdit;
CPVT_WordPlace m_wpOld;
CPVT_WordPlace m_wpNew;
uint16_t m_Word;
int32_t m_nCharset;
};
class CFXEU_InsertReturn final : public IFX_Edit_UndoItem {
public:
CFXEU_InsertReturn(CPWL_EditImpl* pEdit,
const CPVT_WordPlace& wpOldPlace,
const CPVT_WordPlace& wpNewPlace);
~CFXEU_InsertReturn() override;
// IFX_Edit_UndoItem:
int Redo() override;
int Undo() override;
private:
UnownedPtr<CPWL_EditImpl> m_pEdit;
CPVT_WordPlace m_wpOld;
CPVT_WordPlace m_wpNew;
};
class CFXEU_ReplaceSelection final : public IFX_Edit_UndoItem {
public:
CFXEU_ReplaceSelection(CPWL_EditImpl* pEdit, bool bIsEnd);
~CFXEU_ReplaceSelection() override;
// IFX_Edit_UndoItem:
int Redo() override;
int Undo() override;
private:
bool IsEnd() const { return m_bEnd; }
UnownedPtr<CPWL_EditImpl> m_pEdit;
const bool m_bEnd; // indicate whether this is the end of replace action
};
class CFXEU_Backspace final : public IFX_Edit_UndoItem {
public:
CFXEU_Backspace(CPWL_EditImpl* pEdit,
const CPVT_WordPlace& wpOldPlace,
const CPVT_WordPlace& wpNewPlace,
uint16_t word,
int32_t charset);
~CFXEU_Backspace() override;
// IFX_Edit_UndoItem:
int Redo() override;
int Undo() override;
private:
UnownedPtr<CPWL_EditImpl> m_pEdit;
CPVT_WordPlace m_wpOld;
CPVT_WordPlace m_wpNew;
uint16_t m_Word;
int32_t m_nCharset;
};
class CFXEU_Delete final : public IFX_Edit_UndoItem {
public:
CFXEU_Delete(CPWL_EditImpl* pEdit,
const CPVT_WordPlace& wpOldPlace,
const CPVT_WordPlace& wpNewPlace,
uint16_t word,
int32_t charset,
bool bSecEnd);
~CFXEU_Delete() override;
// IFX_Edit_UndoItem:
int Redo() override;
int Undo() override;
private:
UnownedPtr<CPWL_EditImpl> m_pEdit;
CPVT_WordPlace m_wpOld;
CPVT_WordPlace m_wpNew;
uint16_t m_Word;
int32_t m_nCharset;
bool m_bSecEnd;
};
class CFXEU_Clear final : public IFX_Edit_UndoItem {
public:
CFXEU_Clear(CPWL_EditImpl* pEdit,
const CPVT_WordRange& wrSel,
const WideString& swText);
~CFXEU_Clear() override;
// IFX_Edit_UndoItem:
int Redo() override;
int Undo() override;
private:
UnownedPtr<CPWL_EditImpl> m_pEdit;
CPVT_WordRange m_wrSel;
WideString m_swText;
};
class CFXEU_InsertText final : public IFX_Edit_UndoItem {
public:
CFXEU_InsertText(CPWL_EditImpl* pEdit,
const CPVT_WordPlace& wpOldPlace,
const CPVT_WordPlace& wpNewPlace,
const WideString& swText,
int32_t charset);
~CFXEU_InsertText() override;
// IFX_Edit_UndoItem:
int Redo() override;
int Undo() override;
private:
UnownedPtr<CPWL_EditImpl> m_pEdit;
CPVT_WordPlace m_wpOld;
CPVT_WordPlace m_wpNew;
WideString m_swText;
int32_t m_nCharset;
};
class CPWL_EditImpl {
public:
static void DrawEdit(CFX_RenderDevice* pDevice,
const CFX_Matrix& mtUser2Device,
CPWL_EditImpl* pEdit,
FX_COLORREF crTextFill,
const CFX_FloatRect& rcClip,
const CFX_PointF& ptOffset,
const CPVT_WordRange* pRange,
IPWL_SystemHandler* pSystemHandler,
CFFL_FormFiller* pFFLData);
CPWL_EditImpl();
~CPWL_EditImpl();
void SetFontMap(IPVT_FontMap* pFontMap);
void SetNotify(CPWL_EditCtrl* pNotify);
void SetOperationNotify(CPWL_Edit* pOperationNotify);
// Returns an iterator for the contents. Should not be released.
CPWL_EditImpl_Iterator* GetIterator();
IPVT_FontMap* GetFontMap();
void Initialize();
// Set the bounding box of the text area.
void SetPlateRect(const CFX_FloatRect& rect);
void SetScrollPos(const CFX_PointF& point);
// Set the horizontal text alignment. (nFormat [0:left, 1:middle, 2:right])
void SetAlignmentH(int32_t nFormat, bool bPaint);
// Set the vertical text alignment. (nFormat [0:left, 1:middle, 2:right])
void SetAlignmentV(int32_t nFormat, bool bPaint);
// Set the substitution character for hidden text.
void SetPasswordChar(uint16_t wSubWord, bool bPaint);
// Set the maximum number of words in the text.
void SetLimitChar(int32_t nLimitChar);
void SetCharArray(int32_t nCharArray);
void SetCharSpace(float fCharSpace);
void SetMultiLine(bool bMultiLine, bool bPaint);
void SetAutoReturn(bool bAuto, bool bPaint);
void SetAutoFontSize(bool bAuto, bool bPaint);
void SetAutoScroll(bool bAuto, bool bPaint);
void SetFontSize(float fFontSize);
void SetTextOverflow(bool bAllowed, bool bPaint);
void OnMouseDown(const CFX_PointF& point, bool bShift, bool bCtrl);
void OnMouseMove(const CFX_PointF& point, bool bShift, bool bCtrl);
void OnVK_UP(bool bShift, bool bCtrl);
void OnVK_DOWN(bool bShift, bool bCtrl);
void OnVK_LEFT(bool bShift, bool bCtrl);
void OnVK_RIGHT(bool bShift, bool bCtrl);
void OnVK_HOME(bool bShift, bool bCtrl);
void OnVK_END(bool bShift, bool bCtrl);
void SetText(const WideString& sText);
bool InsertWord(uint16_t word, int32_t charset);
bool InsertReturn();
bool Backspace();
bool Delete();
bool ClearSelection();
bool InsertText(const WideString& sText, int32_t charset);
void ReplaceSelection(const WideString& text);
bool Redo();
bool Undo();
CPVT_WordPlace WordIndexToWordPlace(int32_t index) const;
CPVT_WordPlace SearchWordPlace(const CFX_PointF& point) const;
int32_t GetCaret() const;
CPVT_WordPlace GetCaretWordPlace() const;
WideString GetSelectedText() const;
WideString GetText() const;
float GetFontSize() const;
uint16_t GetPasswordChar() const;
CFX_PointF GetScrollPos() const;
int32_t GetCharArray() const;
CFX_FloatRect GetContentRect() const;
WideString GetRangeText(const CPVT_WordRange& range) const;
float GetCharSpace() const;
void SetSelection(int32_t nStartChar, int32_t nEndChar);
std::pair<int32_t, int32_t> GetSelection() const;
void SelectAll();
void SelectNone();
bool IsSelected() const;
void Paint();
void EnableRefresh(bool bRefresh);
void RefreshWordRange(const CPVT_WordRange& wr);
CPVT_WordRange GetWholeWordRange() const;
CPVT_WordRange GetSelectWordRange() const;
void EnableUndo(bool bUndo);
bool IsTextFull() const;
bool IsTextOverflow() const;
bool CanUndo() const;
bool CanRedo() const;
CPVT_WordRange GetVisibleWordRange() const;
bool Clear();
CPVT_WordPlace DoInsertText(const CPVT_WordPlace& place,
const WideString& sText,
int32_t charset);
int32_t GetCharSetFromUnicode(uint16_t word, int32_t nOldCharset);
int32_t GetTotalLines() const;
ByteString GetPDFWordString(int32_t nFontIndex,
uint16_t Word,
uint16_t SubWord);
void SetSelection(const CPVT_WordPlace& begin, const CPVT_WordPlace& end);
bool Delete(bool bAddUndo, bool bPaint);
bool Clear(bool bAddUndo, bool bPaint);
bool InsertText(const WideString& sText,
int32_t charset,
bool bAddUndo,
bool bPaint);
bool InsertWord(uint16_t word, int32_t charset, bool bAddUndo, bool bPaint);
bool InsertReturn(bool bAddUndo, bool bPaint);
bool Backspace(bool bAddUndo, bool bPaint);
void SetCaret(const CPVT_WordPlace& place);
CFX_PointF VTToEdit(const CFX_PointF& point) const;
private:
void RearrangeAll();
void RearrangePart(const CPVT_WordRange& range);
void ScrollToCaret();
void SetScrollInfo();
void SetScrollPosX(float fx);
void SetScrollPosY(float fy);
void SetScrollLimit();
void SetContentChanged();
void PaintInsertText(const CPVT_WordPlace& wpOld,
const CPVT_WordPlace& wpNew);
CFX_PointF EditToVT(const CFX_PointF& point) const;
CFX_FloatRect VTToEdit(const CFX_FloatRect& rect) const;
void Refresh();
void RefreshPushLineRects(const CPVT_WordRange& wr);
void SetCaretInfo();
void SetCaretOrigin();
void AddEditUndoItem(std::unique_ptr<IFX_Edit_UndoItem> pEditUndoItem);
std::unique_ptr<CPWL_EditImpl_Provider> m_pVTProvider;
std::unique_ptr<CPDF_VariableText> m_pVT; // Must outlive |m_pVTProvider|.
UnownedPtr<CPWL_EditCtrl> m_pNotify;
UnownedPtr<CPWL_Edit> m_pOperationNotify;
CPVT_WordPlace m_wpCaret;
CPVT_WordPlace m_wpOldCaret;
CPWL_EditImpl_Select m_SelState;
CFX_PointF m_ptScrollPos;
CFX_PointF m_ptRefreshScrollPos;
bool m_bEnableScroll;
std::unique_ptr<CPWL_EditImpl_Iterator> m_pIterator;
CPWL_EditImpl_Refresh m_Refresh;
CFX_PointF m_ptCaret;
CPWL_EditImpl_Undo m_Undo;
int32_t m_nAlignment;
bool m_bNotifyFlag;
bool m_bEnableOverflow;
bool m_bEnableRefresh;
CFX_FloatRect m_rcOldContent;
bool m_bEnableUndo;
};
class CPWL_EditImpl_Iterator {
public:
CPWL_EditImpl_Iterator(CPWL_EditImpl* pEdit,
CPDF_VariableText::Iterator* pVTIterator);
~CPWL_EditImpl_Iterator();
bool NextWord();
bool PrevWord();
bool GetWord(CPVT_Word& word) const;
bool GetLine(CPVT_Line& line) const;
void SetAt(int32_t nWordIndex);
void SetAt(const CPVT_WordPlace& place);
const CPVT_WordPlace& GetAt() const;
private:
UnownedPtr<CPWL_EditImpl> m_pEdit;
CPDF_VariableText::Iterator* m_pVTIterator;
};
class CPWL_EditImpl_Provider final : public CPDF_VariableText::Provider {
public:
explicit CPWL_EditImpl_Provider(IPVT_FontMap* pFontMap);
~CPWL_EditImpl_Provider() override;
IPVT_FontMap* GetFontMap() const;
// CPDF_VariableText::Provider:
int GetCharWidth(int32_t nFontIndex, uint16_t word) override;
int32_t GetTypeAscent(int32_t nFontIndex) override;
int32_t GetTypeDescent(int32_t nFontIndex) override;
int32_t GetWordFontIndex(uint16_t word,
int32_t charset,
int32_t nFontIndex) override;
int32_t GetDefaultFontIndex() override;
bool IsLatinWord(uint16_t word) override;
private:
IPVT_FontMap* m_pFontMap;
};
#endif // FPDFSDK_PWL_CPWL_EDIT_IMPL_H_