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