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_FXEDIT_FXET_EDIT_H_
8 #define FPDFSDK_FXEDIT_FXET_EDIT_H_
9 
10 #include <deque>
11 #include <memory>
12 #include <vector>
13 
14 #include "core/fpdfdoc/cpvt_secprops.h"
15 #include "core/fpdfdoc/cpvt_wordprops.h"
16 #include "fpdfsdk/fxedit/fx_edit.h"
17 
18 class CFFL_FormFiller;
19 class CFX_Edit;
20 class CFX_Edit_Iterator;
21 class CFX_Edit_Provider;
22 class CFX_RenderDevice;
23 class CFX_SystemHandler;
24 class CPDF_PageObjectHolder;
25 class CPDF_TextObject;
26 class CPWL_Edit;
27 class CPWL_EditCtrl;
28 
29 class IFX_Edit_UndoItem;
30 
31 struct CFX_Edit_LineRect {
CFX_Edit_LineRectCFX_Edit_LineRect32   CFX_Edit_LineRect(const CPVT_WordRange& wrLine, const CFX_FloatRect& rcLine)
33       : m_wrLine(wrLine), m_rcLine(rcLine) {}
34 
35   CPVT_WordRange m_wrLine;
36   CFX_FloatRect m_rcLine;
37 };
38 
39 class CFX_Edit_LineRectArray {
40  public:
41   CFX_Edit_LineRectArray();
42   virtual ~CFX_Edit_LineRectArray();
43 
44   void operator=(CFX_Edit_LineRectArray&& rects);
45   void Add(const CPVT_WordRange& wrLine, const CFX_FloatRect& rcLine);
46 
47   int32_t GetSize() const;
48   CFX_Edit_LineRect* GetAt(int32_t nIndex) const;
49 
50  private:
51   std::vector<std::unique_ptr<CFX_Edit_LineRect>> m_LineRects;
52 };
53 
54 class CFX_Edit_RectArray {
55  public:
56   CFX_Edit_RectArray();
57   virtual ~CFX_Edit_RectArray();
58 
59   void Clear();
60   void Add(const CFX_FloatRect& rect);
61 
62   int32_t GetSize() const;
63   CFX_FloatRect* GetAt(int32_t nIndex) const;
64 
65  private:
66   std::vector<std::unique_ptr<CFX_FloatRect>> m_Rects;
67 };
68 
69 class CFX_Edit_Refresh {
70  public:
71   CFX_Edit_Refresh();
72   virtual ~CFX_Edit_Refresh();
73 
74   void BeginRefresh();
75   void Push(const CPVT_WordRange& linerange, const CFX_FloatRect& rect);
76   void NoAnalyse();
77   void AddRefresh(const CFX_FloatRect& rect);
78   const CFX_Edit_RectArray* GetRefreshRects() const;
79   void EndRefresh();
80 
81  private:
82   CFX_Edit_LineRectArray m_NewLineRects;
83   CFX_Edit_LineRectArray m_OldLineRects;
84   CFX_Edit_RectArray m_RefreshRects;
85 };
86 
87 class CFX_Edit_Select {
88  public:
89   CFX_Edit_Select();
90   CFX_Edit_Select(const CPVT_WordPlace& begin, const CPVT_WordPlace& end);
91   explicit CFX_Edit_Select(const CPVT_WordRange& range);
92 
93   void Default();
94   void Set(const CPVT_WordPlace& begin, const CPVT_WordPlace& end);
95   void SetBeginPos(const CPVT_WordPlace& begin);
96   void SetEndPos(const CPVT_WordPlace& end);
97 
98   CPVT_WordRange ConvertToWordRange() const;
99   bool IsExist() const;
100 
101   CPVT_WordPlace BeginPos;
102   CPVT_WordPlace EndPos;
103 };
104 
105 class CFX_Edit_Undo {
106  public:
107   explicit CFX_Edit_Undo(int32_t nBufsize);
108   virtual ~CFX_Edit_Undo();
109 
110   void AddItem(std::unique_ptr<IFX_Edit_UndoItem> pItem);
111   void Undo();
112   void Redo();
113   bool CanUndo() const;
114   bool CanRedo() const;
115   bool IsModified() const;
116   void Reset();
117 
118  private:
119   void RemoveHeads();
120   void RemoveTails();
121 
122   std::deque<std::unique_ptr<IFX_Edit_UndoItem>> m_UndoItemStack;
123   size_t m_nCurUndoPos;
124   size_t m_nBufSize;
125   bool m_bModified;
126   bool m_bVirgin;
127   bool m_bWorking;
128 };
129 
130 class IFX_Edit_UndoItem {
131  public:
~IFX_Edit_UndoItem()132   virtual ~IFX_Edit_UndoItem() {}
133 
134   virtual void Undo() = 0;
135   virtual void Redo() = 0;
136   virtual CFX_WideString GetUndoTitle() const = 0;
137 };
138 
139 class CFX_Edit_UndoItem : public IFX_Edit_UndoItem {
140  public:
141   CFX_Edit_UndoItem();
142   ~CFX_Edit_UndoItem() override;
143 
144   CFX_WideString GetUndoTitle() const override;
145 
146   void SetFirst(bool bFirst);
147   void SetLast(bool bLast);
148   bool IsLast();
149 
150  private:
151   bool m_bFirst;
152   bool m_bLast;
153 };
154 
155 class CFX_Edit_GroupUndoItem : public IFX_Edit_UndoItem {
156  public:
157   explicit CFX_Edit_GroupUndoItem(const CFX_WideString& sTitle);
158   ~CFX_Edit_GroupUndoItem() override;
159 
160   // IFX_Edit_UndoItem
161   void Undo() override;
162   void Redo() override;
163   CFX_WideString GetUndoTitle() const override;
164 
165   void AddUndoItem(std::unique_ptr<CFX_Edit_UndoItem> pUndoItem);
166   void UpdateItems();
167 
168  private:
169   CFX_WideString m_sTitle;
170   std::vector<std::unique_ptr<CFX_Edit_UndoItem>> m_Items;
171 };
172 
173 class CFXEU_InsertWord : public CFX_Edit_UndoItem {
174  public:
175   CFXEU_InsertWord(CFX_Edit* pEdit,
176                    const CPVT_WordPlace& wpOldPlace,
177                    const CPVT_WordPlace& wpNewPlace,
178                    uint16_t word,
179                    int32_t charset,
180                    const CPVT_WordProps* pWordProps);
181   ~CFXEU_InsertWord() override;
182 
183   // CFX_Edit_UndoItem
184   void Redo() override;
185   void Undo() override;
186 
187  private:
188   CFX_Edit* m_pEdit;
189 
190   CPVT_WordPlace m_wpOld;
191   CPVT_WordPlace m_wpNew;
192   uint16_t m_Word;
193   int32_t m_nCharset;
194   CPVT_WordProps m_WordProps;
195 };
196 
197 class CFXEU_InsertReturn : public CFX_Edit_UndoItem {
198  public:
199   CFXEU_InsertReturn(CFX_Edit* pEdit,
200                      const CPVT_WordPlace& wpOldPlace,
201                      const CPVT_WordPlace& wpNewPlace,
202                      const CPVT_SecProps* pSecProps,
203                      const CPVT_WordProps* pWordProps);
204   ~CFXEU_InsertReturn() override;
205 
206   // CFX_Edit_UndoItem
207   void Redo() override;
208   void Undo() override;
209 
210  private:
211   CFX_Edit* m_pEdit;
212 
213   CPVT_WordPlace m_wpOld;
214   CPVT_WordPlace m_wpNew;
215   CPVT_SecProps m_SecProps;
216   CPVT_WordProps m_WordProps;
217 };
218 
219 class CFXEU_Backspace : public CFX_Edit_UndoItem {
220  public:
221   CFXEU_Backspace(CFX_Edit* pEdit,
222                   const CPVT_WordPlace& wpOldPlace,
223                   const CPVT_WordPlace& wpNewPlace,
224                   uint16_t word,
225                   int32_t charset,
226                   const CPVT_SecProps& SecProps,
227                   const CPVT_WordProps& WordProps);
228   ~CFXEU_Backspace() override;
229 
230   // CFX_Edit_UndoItem
231   void Redo() override;
232   void Undo() override;
233 
234  private:
235   CFX_Edit* m_pEdit;
236 
237   CPVT_WordPlace m_wpOld;
238   CPVT_WordPlace m_wpNew;
239   uint16_t m_Word;
240   int32_t m_nCharset;
241   CPVT_SecProps m_SecProps;
242   CPVT_WordProps m_WordProps;
243 };
244 
245 class CFXEU_Delete : public CFX_Edit_UndoItem {
246  public:
247   CFXEU_Delete(CFX_Edit* pEdit,
248                const CPVT_WordPlace& wpOldPlace,
249                const CPVT_WordPlace& wpNewPlace,
250                uint16_t word,
251                int32_t charset,
252                const CPVT_SecProps& SecProps,
253                const CPVT_WordProps& WordProps,
254                bool bSecEnd);
255   ~CFXEU_Delete() override;
256 
257   // CFX_Edit_UndoItem
258   void Redo() override;
259   void Undo() override;
260 
261  private:
262   CFX_Edit* m_pEdit;
263 
264   CPVT_WordPlace m_wpOld;
265   CPVT_WordPlace m_wpNew;
266   uint16_t m_Word;
267   int32_t m_nCharset;
268   CPVT_SecProps m_SecProps;
269   CPVT_WordProps m_WordProps;
270   bool m_bSecEnd;
271 };
272 
273 class CFXEU_Clear : public CFX_Edit_UndoItem {
274  public:
275   CFXEU_Clear(CFX_Edit* pEdit,
276               const CPVT_WordRange& wrSel,
277               const CFX_WideString& swText);
278   ~CFXEU_Clear() override;
279 
280   // CFX_Edit_UndoItem
281   void Redo() override;
282   void Undo() override;
283 
284  private:
285   CFX_Edit* m_pEdit;
286 
287   CPVT_WordRange m_wrSel;
288   CFX_WideString m_swText;
289 };
290 
291 class CFXEU_InsertText : public CFX_Edit_UndoItem {
292  public:
293   CFXEU_InsertText(CFX_Edit* pEdit,
294                    const CPVT_WordPlace& wpOldPlace,
295                    const CPVT_WordPlace& wpNewPlace,
296                    const CFX_WideString& swText,
297                    int32_t charset);
298   ~CFXEU_InsertText() override;
299 
300   // CFX_Edit_UndoItem
301   void Redo() override;
302   void Undo() override;
303 
304  private:
305   CFX_Edit* m_pEdit;
306 
307   CPVT_WordPlace m_wpOld;
308   CPVT_WordPlace m_wpNew;
309   CFX_WideString m_swText;
310   int32_t m_nCharset;
311 };
312 
313 class CFX_Edit {
314  public:
315   static CFX_ByteString GetEditAppearanceStream(CFX_Edit* pEdit,
316                                                 const CFX_PointF& ptOffset,
317                                                 const CPVT_WordRange* pRange,
318                                                 bool bContinuous,
319                                                 uint16_t SubWord);
320   static CFX_ByteString GetSelectAppearanceStream(CFX_Edit* pEdit,
321                                                   const CFX_PointF& ptOffset,
322                                                   const CPVT_WordRange* pRange);
323   static void DrawEdit(CFX_RenderDevice* pDevice,
324                        CFX_Matrix* pUser2Device,
325                        CFX_Edit* pEdit,
326                        FX_COLORREF crTextFill,
327                        const CFX_FloatRect& rcClip,
328                        const CFX_PointF& ptOffset,
329                        const CPVT_WordRange* pRange,
330                        CFX_SystemHandler* pSystemHandler,
331                        CFFL_FormFiller* pFFLData);
332 
333   CFX_Edit();
334   ~CFX_Edit();
335 
336   void SetFontMap(IPVT_FontMap* pFontMap);
337   void SetNotify(CPWL_EditCtrl* pNotify);
338   void SetOprNotify(CPWL_Edit* pOprNotify);
339 
340   // Returns an iterator for the contents. Should not be released.
341   CFX_Edit_Iterator* GetIterator();
342   IPVT_FontMap* GetFontMap();
343   void Initialize();
344 
345   // Set the bounding box of the text area.
346   void SetPlateRect(const CFX_FloatRect& rect);
347   void SetScrollPos(const CFX_PointF& point);
348 
349   // Set the horizontal text alignment. (nFormat [0:left, 1:middle, 2:right])
350   void SetAlignmentH(int32_t nFormat, bool bPaint);
351   // Set the vertical text alignment. (nFormat [0:left, 1:middle, 2:right])
352   void SetAlignmentV(int32_t nFormat, bool bPaint);
353 
354   // Set the substitution character for hidden text.
355   void SetPasswordChar(uint16_t wSubWord, bool bPaint);
356 
357   // Set the maximum number of words in the text.
358   void SetLimitChar(int32_t nLimitChar);
359   void SetCharArray(int32_t nCharArray);
360   void SetCharSpace(FX_FLOAT fCharSpace);
361   void SetMultiLine(bool bMultiLine, bool bPaint);
362   void SetAutoReturn(bool bAuto, bool bPaint);
363   void SetAutoFontSize(bool bAuto, bool bPaint);
364   void SetAutoScroll(bool bAuto, bool bPaint);
365   void SetFontSize(FX_FLOAT fFontSize);
366   void SetTextOverflow(bool bAllowed, bool bPaint);
367   void OnMouseDown(const CFX_PointF& point, bool bShift, bool bCtrl);
368   void OnMouseMove(const CFX_PointF& point, bool bShift, bool bCtrl);
369   void OnVK_UP(bool bShift, bool bCtrl);
370   void OnVK_DOWN(bool bShift, bool bCtrl);
371   void OnVK_LEFT(bool bShift, bool bCtrl);
372   void OnVK_RIGHT(bool bShift, bool bCtrl);
373   void OnVK_HOME(bool bShift, bool bCtrl);
374   void OnVK_END(bool bShift, bool bCtrl);
375   void SetText(const CFX_WideString& sText);
376   bool InsertWord(uint16_t word, int32_t charset);
377   bool InsertReturn();
378   bool Backspace();
379   bool Delete();
380   bool Clear();
381   bool InsertText(const CFX_WideString& sText, int32_t charset);
382   bool Redo();
383   bool Undo();
384   int32_t WordPlaceToWordIndex(const CPVT_WordPlace& place) const;
385   CPVT_WordPlace WordIndexToWordPlace(int32_t index) const;
386   CPVT_WordPlace SearchWordPlace(const CFX_PointF& point) const;
387   int32_t GetCaret() const;
388   CPVT_WordPlace GetCaretWordPlace() const;
389   CFX_WideString GetSelText() const;
390   CFX_WideString GetText() const;
391   FX_FLOAT GetFontSize() const;
392   uint16_t GetPasswordChar() const;
393   CFX_PointF GetScrollPos() const;
394   int32_t GetCharArray() const;
395   CFX_FloatRect GetContentRect() const;
396   CFX_WideString GetRangeText(const CPVT_WordRange& range) const;
397   int32_t GetHorzScale() const;
398   FX_FLOAT GetCharSpace() const;
399   int32_t GetTotalWords() const;
400   void SetSel(int32_t nStartChar, int32_t nEndChar);
401   void GetSel(int32_t& nStartChar, int32_t& nEndChar) const;
402   void SelectAll();
403   void SelectNone();
404   bool IsSelected() const;
405   void Paint();
406   void EnableRefresh(bool bRefresh);
407   void RefreshWordRange(const CPVT_WordRange& wr);
408   void SetCaret(int32_t nPos);
409   CPVT_WordRange GetWholeWordRange() const;
410   CPVT_WordRange GetSelectWordRange() const;
411   void EnableUndo(bool bUndo);
412   void EnableOprNotify(bool bNotify);
413   bool IsTextFull() const;
414   bool IsTextOverflow() const;
415   bool CanUndo() const;
416   bool CanRedo() const;
417   CPVT_WordRange GetVisibleWordRange() const;
418 
419   bool Empty();
420 
421   CPVT_WordPlace DoInsertText(const CPVT_WordPlace& place,
422                               const CFX_WideString& sText,
423                               int32_t charset);
424   int32_t GetCharSetFromUnicode(uint16_t word, int32_t nOldCharset);
425 
426   int32_t GetTotalLines() const;
427 
428  private:
429   friend class CFX_Edit_Iterator;
430   friend class CFXEU_InsertWord;
431   friend class CFXEU_InsertReturn;
432   friend class CFXEU_Backspace;
433   friend class CFXEU_Delete;
434   friend class CFXEU_Clear;
435   friend class CFXEU_InsertText;
436 
437   void SetSel(const CPVT_WordPlace& begin, const CPVT_WordPlace& end);
438 
439   void RearrangeAll();
440   void RearrangePart(const CPVT_WordRange& range);
441   void ScrollToCaret();
442   void SetScrollInfo();
443   void SetScrollPosX(FX_FLOAT fx);
444   void SetScrollPosY(FX_FLOAT fy);
445   void SetScrollLimit();
446   void SetContentChanged();
447 
448   bool InsertWord(uint16_t word,
449                   int32_t charset,
450                   const CPVT_WordProps* pWordProps,
451                   bool bAddUndo,
452                   bool bPaint);
453   bool InsertReturn(const CPVT_SecProps* pSecProps,
454                     const CPVT_WordProps* pWordProps,
455                     bool bAddUndo,
456                     bool bPaint);
457   bool Backspace(bool bAddUndo, bool bPaint);
458   bool Delete(bool bAddUndo, bool bPaint);
459   bool Clear(bool bAddUndo, bool bPaint);
460   bool InsertText(const CFX_WideString& sText,
461                   int32_t charset,
462                   bool bAddUndo,
463                   bool bPaint);
464   void PaintInsertText(const CPVT_WordPlace& wpOld,
465                        const CPVT_WordPlace& wpNew);
466 
467   inline CFX_PointF VTToEdit(const CFX_PointF& point) const;
468   inline CFX_PointF EditToVT(const CFX_PointF& point) const;
469   inline CFX_FloatRect VTToEdit(const CFX_FloatRect& rect) const;
470 
471   void Refresh();
472   void RefreshPushLineRects(const CPVT_WordRange& wr);
473 
474   void SetCaret(const CPVT_WordPlace& place);
475   void SetCaretInfo();
476   void SetCaretOrigin();
477 
478   void AddEditUndoItem(std::unique_ptr<CFX_Edit_UndoItem> pEditUndoItem);
479 
480  private:
481   std::unique_ptr<CPDF_VariableText> m_pVT;
482   CPWL_EditCtrl* m_pNotify;
483   CPWL_Edit* m_pOprNotify;
484   std::unique_ptr<CFX_Edit_Provider> m_pVTProvider;
485   CPVT_WordPlace m_wpCaret;
486   CPVT_WordPlace m_wpOldCaret;
487   CFX_Edit_Select m_SelState;
488   CFX_PointF m_ptScrollPos;
489   CFX_PointF m_ptRefreshScrollPos;
490   bool m_bEnableScroll;
491   std::unique_ptr<CFX_Edit_Iterator> m_pIterator;
492   CFX_Edit_Refresh m_Refresh;
493   CFX_PointF m_ptCaret;
494   CFX_Edit_Undo m_Undo;
495   int32_t m_nAlignment;
496   bool m_bNotifyFlag;
497   bool m_bEnableOverflow;
498   bool m_bEnableRefresh;
499   CFX_FloatRect m_rcOldContent;
500   bool m_bEnableUndo;
501   bool m_bOprNotify;
502   CFX_Edit_GroupUndoItem* m_pGroupUndoItem;
503 };
504 
505 class CFX_Edit_Iterator {
506  public:
507   CFX_Edit_Iterator(CFX_Edit* pEdit, CPDF_VariableText::Iterator* pVTIterator);
508   ~CFX_Edit_Iterator();
509 
510   bool NextWord();
511   bool PrevWord();
512   bool GetWord(CPVT_Word& word) const;
513   bool GetLine(CPVT_Line& line) const;
514   bool GetSection(CPVT_Section& section) const;
515   void SetAt(int32_t nWordIndex);
516   void SetAt(const CPVT_WordPlace& place);
517   const CPVT_WordPlace& GetAt() const;
518 
519  private:
520   CFX_Edit* m_pEdit;
521   CPDF_VariableText::Iterator* m_pVTIterator;
522 };
523 
524 class CFX_Edit_Provider : public CPDF_VariableText::Provider {
525  public:
526   explicit CFX_Edit_Provider(IPVT_FontMap* pFontMap);
527   ~CFX_Edit_Provider() override;
528 
529   IPVT_FontMap* GetFontMap();
530 
531   // CPDF_VariableText::Provider:
532   int32_t GetCharWidth(int32_t nFontIndex, uint16_t word) override;
533   int32_t GetTypeAscent(int32_t nFontIndex) override;
534   int32_t GetTypeDescent(int32_t nFontIndex) override;
535   int32_t GetWordFontIndex(uint16_t word,
536                            int32_t charset,
537                            int32_t nFontIndex) override;
538   int32_t GetDefaultFontIndex() override;
539   bool IsLatinWord(uint16_t word) override;
540 
541  private:
542   IPVT_FontMap* m_pFontMap;
543 };
544 
545 #endif  // FPDFSDK_FXEDIT_FXET_EDIT_H_
546