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