1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #ifndef FPDFSDK_PWL_CPWL_EDIT_IMPL_H_ 8 #define FPDFSDK_PWL_CPWL_EDIT_IMPL_H_ 9 10 #include <deque> 11 #include <memory> 12 #include <vector> 13 14 #include "core/fpdfdoc/cpdf_variabletext.h" 15 #include "core/fpdfdoc/cpvt_wordrange.h" 16 #include "core/fxcrt/unowned_ptr.h" 17 #include "core/fxge/fx_dib.h" 18 19 #define FX_EDIT_ISLATINWORD(u) \ 20 (u == 0x2D || (u <= 0x005A && u >= 0x0041) || \ 21 (u <= 0x007A && u >= 0x0061) || (u <= 0x02AF && u >= 0x00C0)) 22 23 class CFFL_FormFiller; 24 class CPWL_EditImpl; 25 class CPWL_EditImpl_Iterator; 26 class CPWL_EditImpl_Provider; 27 class CFX_RenderDevice; 28 class CPWL_Edit; 29 class CPWL_EditCtrl; 30 class IPWL_SystemHandler; 31 class IFX_Edit_UndoItem; 32 33 struct CPWL_EditImpl_LineRect { CPWL_EditImpl_LineRectCPWL_EditImpl_LineRect34 CPWL_EditImpl_LineRect(const CPVT_WordRange& wrLine, 35 const CFX_FloatRect& rcLine) 36 : m_wrLine(wrLine), m_rcLine(rcLine) {} 37 38 CPVT_WordRange m_wrLine; 39 CFX_FloatRect m_rcLine; 40 }; 41 42 class CPWL_EditImpl_Refresh { 43 public: 44 CPWL_EditImpl_Refresh(); 45 ~CPWL_EditImpl_Refresh(); 46 47 void BeginRefresh(); 48 void Push(const CPVT_WordRange& linerange, const CFX_FloatRect& rect); 49 void NoAnalyse(); 50 std::vector<CFX_FloatRect>* GetRefreshRects(); 51 void EndRefresh(); 52 53 private: 54 void Add(const CFX_FloatRect& new_rect); 55 56 std::vector<CPWL_EditImpl_LineRect> m_NewLineRects; 57 std::vector<CPWL_EditImpl_LineRect> m_OldLineRects; 58 std::vector<CFX_FloatRect> m_RefreshRects; 59 }; 60 61 class CPWL_EditImpl_Select { 62 public: 63 CPWL_EditImpl_Select(); 64 explicit CPWL_EditImpl_Select(const CPVT_WordRange& range); 65 66 void Reset(); 67 void Set(const CPVT_WordPlace& begin, const CPVT_WordPlace& end); 68 void SetEndPos(const CPVT_WordPlace& end); 69 70 CPVT_WordRange ConvertToWordRange() const; 71 bool IsEmpty() const; 72 73 CPVT_WordPlace BeginPos; 74 CPVT_WordPlace EndPos; 75 }; 76 77 class CPWL_EditImpl_Undo { 78 public: 79 CPWL_EditImpl_Undo(); 80 ~CPWL_EditImpl_Undo(); 81 82 void AddItem(std::unique_ptr<IFX_Edit_UndoItem> pItem); 83 void Undo(); 84 void Redo(); 85 bool CanUndo() const; 86 bool CanRedo() const; 87 88 private: 89 void RemoveHeads(); 90 void RemoveTails(); 91 92 std::deque<std::unique_ptr<IFX_Edit_UndoItem>> m_UndoItemStack; 93 size_t m_nCurUndoPos; 94 bool m_bWorking; 95 }; 96 97 class IFX_Edit_UndoItem { 98 public: 99 virtual ~IFX_Edit_UndoItem() = default; 100 101 // Undo/Redo the current undo item and returns the number of additional items 102 // to be processed in |m_UndoItemStack| to fully undo/redo the action. (An 103 // example is CFXEU_ReplaceSelection::Undo(), if CFXEU_ReplaceSelection marks 104 // the end of a replace action, CFXEU_ReplaceSelection::Undo() returns 3 105 // because 3 more undo items need to be processed to revert the replace 106 // action: insert text, clear selection and the CFXEU_ReplaceSelection which 107 // marks the beginning of replace action.) Implementations should return 0 by 108 // default. 109 virtual int Undo() = 0; 110 virtual int Redo() = 0; 111 }; 112 113 class CFXEU_InsertWord final : public IFX_Edit_UndoItem { 114 public: 115 CFXEU_InsertWord(CPWL_EditImpl* pEdit, 116 const CPVT_WordPlace& wpOldPlace, 117 const CPVT_WordPlace& wpNewPlace, 118 uint16_t word, 119 int32_t charset); 120 ~CFXEU_InsertWord() override; 121 122 // IFX_Edit_UndoItem: 123 int Redo() override; 124 int Undo() override; 125 126 private: 127 UnownedPtr<CPWL_EditImpl> m_pEdit; 128 129 CPVT_WordPlace m_wpOld; 130 CPVT_WordPlace m_wpNew; 131 uint16_t m_Word; 132 int32_t m_nCharset; 133 }; 134 135 class CFXEU_InsertReturn final : public IFX_Edit_UndoItem { 136 public: 137 CFXEU_InsertReturn(CPWL_EditImpl* pEdit, 138 const CPVT_WordPlace& wpOldPlace, 139 const CPVT_WordPlace& wpNewPlace); 140 ~CFXEU_InsertReturn() override; 141 142 // IFX_Edit_UndoItem: 143 int Redo() override; 144 int Undo() override; 145 146 private: 147 UnownedPtr<CPWL_EditImpl> m_pEdit; 148 149 CPVT_WordPlace m_wpOld; 150 CPVT_WordPlace m_wpNew; 151 }; 152 153 class CFXEU_ReplaceSelection final : public IFX_Edit_UndoItem { 154 public: 155 CFXEU_ReplaceSelection(CPWL_EditImpl* pEdit, bool bIsEnd); 156 ~CFXEU_ReplaceSelection() override; 157 158 // IFX_Edit_UndoItem: 159 int Redo() override; 160 int Undo() override; 161 162 private: IsEnd()163 bool IsEnd() const { return m_bEnd; } 164 165 UnownedPtr<CPWL_EditImpl> m_pEdit; 166 const bool m_bEnd; // indicate whether this is the end of replace action 167 }; 168 169 class CFXEU_Backspace final : public IFX_Edit_UndoItem { 170 public: 171 CFXEU_Backspace(CPWL_EditImpl* pEdit, 172 const CPVT_WordPlace& wpOldPlace, 173 const CPVT_WordPlace& wpNewPlace, 174 uint16_t word, 175 int32_t charset); 176 ~CFXEU_Backspace() override; 177 178 // IFX_Edit_UndoItem: 179 int Redo() override; 180 int Undo() override; 181 182 private: 183 UnownedPtr<CPWL_EditImpl> m_pEdit; 184 185 CPVT_WordPlace m_wpOld; 186 CPVT_WordPlace m_wpNew; 187 uint16_t m_Word; 188 int32_t m_nCharset; 189 }; 190 191 class CFXEU_Delete final : public IFX_Edit_UndoItem { 192 public: 193 CFXEU_Delete(CPWL_EditImpl* pEdit, 194 const CPVT_WordPlace& wpOldPlace, 195 const CPVT_WordPlace& wpNewPlace, 196 uint16_t word, 197 int32_t charset, 198 bool bSecEnd); 199 ~CFXEU_Delete() override; 200 201 // IFX_Edit_UndoItem: 202 int Redo() override; 203 int Undo() override; 204 205 private: 206 UnownedPtr<CPWL_EditImpl> m_pEdit; 207 208 CPVT_WordPlace m_wpOld; 209 CPVT_WordPlace m_wpNew; 210 uint16_t m_Word; 211 int32_t m_nCharset; 212 bool m_bSecEnd; 213 }; 214 215 class CFXEU_Clear final : public IFX_Edit_UndoItem { 216 public: 217 CFXEU_Clear(CPWL_EditImpl* pEdit, 218 const CPVT_WordRange& wrSel, 219 const WideString& swText); 220 ~CFXEU_Clear() override; 221 222 // IFX_Edit_UndoItem: 223 int Redo() override; 224 int Undo() override; 225 226 private: 227 UnownedPtr<CPWL_EditImpl> m_pEdit; 228 229 CPVT_WordRange m_wrSel; 230 WideString m_swText; 231 }; 232 233 class CFXEU_InsertText final : public IFX_Edit_UndoItem { 234 public: 235 CFXEU_InsertText(CPWL_EditImpl* pEdit, 236 const CPVT_WordPlace& wpOldPlace, 237 const CPVT_WordPlace& wpNewPlace, 238 const WideString& swText, 239 int32_t charset); 240 ~CFXEU_InsertText() override; 241 242 // IFX_Edit_UndoItem: 243 int Redo() override; 244 int Undo() override; 245 246 private: 247 UnownedPtr<CPWL_EditImpl> m_pEdit; 248 249 CPVT_WordPlace m_wpOld; 250 CPVT_WordPlace m_wpNew; 251 WideString m_swText; 252 int32_t m_nCharset; 253 }; 254 255 class CPWL_EditImpl { 256 public: 257 static void DrawEdit(CFX_RenderDevice* pDevice, 258 const CFX_Matrix& mtUser2Device, 259 CPWL_EditImpl* pEdit, 260 FX_COLORREF crTextFill, 261 const CFX_FloatRect& rcClip, 262 const CFX_PointF& ptOffset, 263 const CPVT_WordRange* pRange, 264 IPWL_SystemHandler* pSystemHandler, 265 CFFL_FormFiller* pFFLData); 266 267 CPWL_EditImpl(); 268 ~CPWL_EditImpl(); 269 270 void SetFontMap(IPVT_FontMap* pFontMap); 271 void SetNotify(CPWL_EditCtrl* pNotify); 272 void SetOperationNotify(CPWL_Edit* pOperationNotify); 273 274 // Returns an iterator for the contents. Should not be released. 275 CPWL_EditImpl_Iterator* GetIterator(); 276 IPVT_FontMap* GetFontMap(); 277 void Initialize(); 278 279 // Set the bounding box of the text area. 280 void SetPlateRect(const CFX_FloatRect& rect); 281 void SetScrollPos(const CFX_PointF& point); 282 283 // Set the horizontal text alignment. (nFormat [0:left, 1:middle, 2:right]) 284 void SetAlignmentH(int32_t nFormat, bool bPaint); 285 // Set the vertical text alignment. (nFormat [0:left, 1:middle, 2:right]) 286 void SetAlignmentV(int32_t nFormat, bool bPaint); 287 288 // Set the substitution character for hidden text. 289 void SetPasswordChar(uint16_t wSubWord, bool bPaint); 290 291 // Set the maximum number of words in the text. 292 void SetLimitChar(int32_t nLimitChar); 293 void SetCharArray(int32_t nCharArray); 294 void SetCharSpace(float fCharSpace); 295 void SetMultiLine(bool bMultiLine, bool bPaint); 296 void SetAutoReturn(bool bAuto, bool bPaint); 297 void SetAutoFontSize(bool bAuto, bool bPaint); 298 void SetAutoScroll(bool bAuto, bool bPaint); 299 void SetFontSize(float fFontSize); 300 void SetTextOverflow(bool bAllowed, bool bPaint); 301 void OnMouseDown(const CFX_PointF& point, bool bShift, bool bCtrl); 302 void OnMouseMove(const CFX_PointF& point, bool bShift, bool bCtrl); 303 void OnVK_UP(bool bShift, bool bCtrl); 304 void OnVK_DOWN(bool bShift, bool bCtrl); 305 void OnVK_LEFT(bool bShift, bool bCtrl); 306 void OnVK_RIGHT(bool bShift, bool bCtrl); 307 void OnVK_HOME(bool bShift, bool bCtrl); 308 void OnVK_END(bool bShift, bool bCtrl); 309 void SetText(const WideString& sText); 310 bool InsertWord(uint16_t word, int32_t charset); 311 bool InsertReturn(); 312 bool Backspace(); 313 bool Delete(); 314 bool ClearSelection(); 315 bool InsertText(const WideString& sText, int32_t charset); 316 void ReplaceSelection(const WideString& text); 317 bool Redo(); 318 bool Undo(); 319 CPVT_WordPlace WordIndexToWordPlace(int32_t index) const; 320 CPVT_WordPlace SearchWordPlace(const CFX_PointF& point) const; 321 int32_t GetCaret() const; 322 CPVT_WordPlace GetCaretWordPlace() const; 323 WideString GetSelectedText() const; 324 WideString GetText() const; 325 float GetFontSize() const; 326 uint16_t GetPasswordChar() const; 327 CFX_PointF GetScrollPos() const; 328 int32_t GetCharArray() const; 329 CFX_FloatRect GetContentRect() const; 330 WideString GetRangeText(const CPVT_WordRange& range) const; 331 float GetCharSpace() const; 332 void SetSelection(int32_t nStartChar, int32_t nEndChar); 333 void GetSelection(int32_t& nStartChar, int32_t& nEndChar) const; 334 void SelectAll(); 335 void SelectNone(); 336 bool IsSelected() const; 337 void Paint(); 338 void EnableRefresh(bool bRefresh); 339 void RefreshWordRange(const CPVT_WordRange& wr); 340 CPVT_WordRange GetWholeWordRange() const; 341 CPVT_WordRange GetSelectWordRange() const; 342 void EnableUndo(bool bUndo); 343 bool IsTextFull() const; 344 bool IsTextOverflow() const; 345 bool CanUndo() const; 346 bool CanRedo() const; 347 CPVT_WordRange GetVisibleWordRange() const; 348 349 bool Clear(); 350 351 CPVT_WordPlace DoInsertText(const CPVT_WordPlace& place, 352 const WideString& sText, 353 int32_t charset); 354 int32_t GetCharSetFromUnicode(uint16_t word, int32_t nOldCharset); 355 356 int32_t GetTotalLines() const; 357 358 ByteString GetPDFWordString(int32_t nFontIndex, 359 uint16_t Word, 360 uint16_t SubWord); 361 362 void SetSelection(const CPVT_WordPlace& begin, const CPVT_WordPlace& end); 363 364 bool Delete(bool bAddUndo, bool bPaint); 365 bool Clear(bool bAddUndo, bool bPaint); 366 bool InsertText(const WideString& sText, 367 int32_t charset, 368 bool bAddUndo, 369 bool bPaint); 370 bool InsertWord(uint16_t word, int32_t charset, bool bAddUndo, bool bPaint); 371 bool InsertReturn(bool bAddUndo, bool bPaint); 372 bool Backspace(bool bAddUndo, bool bPaint); 373 void SetCaret(const CPVT_WordPlace& place); 374 375 CFX_PointF VTToEdit(const CFX_PointF& point) const; 376 377 private: 378 void RearrangeAll(); 379 void RearrangePart(const CPVT_WordRange& range); 380 void ScrollToCaret(); 381 void SetScrollInfo(); 382 void SetScrollPosX(float fx); 383 void SetScrollPosY(float fy); 384 void SetScrollLimit(); 385 void SetContentChanged(); 386 387 void PaintInsertText(const CPVT_WordPlace& wpOld, 388 const CPVT_WordPlace& wpNew); 389 390 CFX_PointF EditToVT(const CFX_PointF& point) const; 391 CFX_FloatRect VTToEdit(const CFX_FloatRect& rect) const; 392 393 void Refresh(); 394 void RefreshPushLineRects(const CPVT_WordRange& wr); 395 396 void SetCaretInfo(); 397 void SetCaretOrigin(); 398 399 void AddEditUndoItem(std::unique_ptr<IFX_Edit_UndoItem> pEditUndoItem); 400 401 std::unique_ptr<CPWL_EditImpl_Provider> m_pVTProvider; 402 std::unique_ptr<CPDF_VariableText> m_pVT; // Must outlive |m_pVTProvider|. 403 UnownedPtr<CPWL_EditCtrl> m_pNotify; 404 UnownedPtr<CPWL_Edit> m_pOperationNotify; 405 CPVT_WordPlace m_wpCaret; 406 CPVT_WordPlace m_wpOldCaret; 407 CPWL_EditImpl_Select m_SelState; 408 CFX_PointF m_ptScrollPos; 409 CFX_PointF m_ptRefreshScrollPos; 410 bool m_bEnableScroll; 411 std::unique_ptr<CPWL_EditImpl_Iterator> m_pIterator; 412 CPWL_EditImpl_Refresh m_Refresh; 413 CFX_PointF m_ptCaret; 414 CPWL_EditImpl_Undo m_Undo; 415 int32_t m_nAlignment; 416 bool m_bNotifyFlag; 417 bool m_bEnableOverflow; 418 bool m_bEnableRefresh; 419 CFX_FloatRect m_rcOldContent; 420 bool m_bEnableUndo; 421 }; 422 423 class CPWL_EditImpl_Iterator { 424 public: 425 CPWL_EditImpl_Iterator(CPWL_EditImpl* pEdit, 426 CPDF_VariableText::Iterator* pVTIterator); 427 ~CPWL_EditImpl_Iterator(); 428 429 bool NextWord(); 430 bool PrevWord(); 431 bool GetWord(CPVT_Word& word) const; 432 bool GetLine(CPVT_Line& line) const; 433 void SetAt(int32_t nWordIndex); 434 void SetAt(const CPVT_WordPlace& place); 435 const CPVT_WordPlace& GetAt() const; 436 437 private: 438 UnownedPtr<CPWL_EditImpl> m_pEdit; 439 CPDF_VariableText::Iterator* m_pVTIterator; 440 }; 441 442 class CPWL_EditImpl_Provider final : public CPDF_VariableText::Provider { 443 public: 444 explicit CPWL_EditImpl_Provider(IPVT_FontMap* pFontMap); 445 ~CPWL_EditImpl_Provider() override; 446 447 IPVT_FontMap* GetFontMap() const; 448 449 // CPDF_VariableText::Provider: 450 uint32_t GetCharWidth(int32_t nFontIndex, uint16_t word) override; 451 int32_t GetTypeAscent(int32_t nFontIndex) override; 452 int32_t GetTypeDescent(int32_t nFontIndex) override; 453 int32_t GetWordFontIndex(uint16_t word, 454 int32_t charset, 455 int32_t nFontIndex) override; 456 int32_t GetDefaultFontIndex() override; 457 bool IsLatinWord(uint16_t word) override; 458 459 private: 460 IPVT_FontMap* m_pFontMap; 461 }; 462 463 #endif // FPDFSDK_PWL_CPWL_EDIT_IMPL_H_ 464