1 // Copyright 2017 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 XFA_FDE_CFDE_TEXTEDITENGINE_H_ 8 #define XFA_FDE_CFDE_TEXTEDITENGINE_H_ 9 10 #include <memory> 11 #include <utility> 12 #include <vector> 13 14 #include "core/fxcrt/fx_string.h" 15 #include "core/fxcrt/retain_ptr.h" 16 #include "core/fxge/fx_dib.h" 17 #include "xfa/fgas/layout/cfx_txtbreak.h" 18 19 class CFGAS_GEFont; 20 class TextCharPos; 21 22 struct FDE_TEXTEDITPIECE { 23 FDE_TEXTEDITPIECE(); 24 FDE_TEXTEDITPIECE(const FDE_TEXTEDITPIECE& that); 25 ~FDE_TEXTEDITPIECE(); 26 27 CFX_RectF rtPiece; 28 int32_t nStart = 0; 29 int32_t nCount = 0; 30 int32_t nBidiLevel = 0; 31 uint32_t dwCharStyles = 0; 32 }; 33 34 inline FDE_TEXTEDITPIECE::FDE_TEXTEDITPIECE() = default; 35 inline FDE_TEXTEDITPIECE::FDE_TEXTEDITPIECE(const FDE_TEXTEDITPIECE& that) = 36 default; 37 inline FDE_TEXTEDITPIECE::~FDE_TEXTEDITPIECE() = default; 38 39 class CFDE_TextEditEngine : public CFX_TxtBreak::Engine { 40 public: 41 class Iterator { 42 public: 43 explicit Iterator(const CFDE_TextEditEngine* engine); 44 ~Iterator(); 45 46 void Next(bool bPrev); 47 wchar_t GetChar() const; 48 void SetAt(size_t nIndex); 49 size_t FindNextBreakPos(bool bPrev); 50 bool IsEOF(bool bPrev) const; 51 52 private: 53 UnownedPtr<const CFDE_TextEditEngine> engine_; 54 int32_t current_position_; 55 }; 56 57 class Operation { 58 public: 59 virtual ~Operation() = default; 60 virtual void Redo() const = 0; 61 virtual void Undo() const = 0; 62 }; 63 64 struct TextChange { 65 WideString text; 66 WideString previous_text; 67 size_t selection_start; 68 size_t selection_end; 69 bool cancelled; 70 }; 71 72 class Delegate { 73 public: 74 virtual ~Delegate() = default; 75 virtual void NotifyTextFull() = 0; 76 virtual void OnCaretChanged() = 0; 77 virtual void OnTextWillChange(TextChange* change) = 0; 78 virtual void OnTextChanged() = 0; 79 virtual void OnSelChanged() = 0; 80 virtual bool OnValidate(const WideString& wsText) = 0; 81 virtual void SetScrollOffset(float fScrollOffset) = 0; 82 }; 83 84 enum class RecordOperation { kInsertRecord, kSkipRecord, kSkipNotify }; 85 86 CFDE_TextEditEngine(); 87 ~CFDE_TextEditEngine() override; 88 89 // CFX_TxtBreak::Engine: 90 wchar_t GetChar(size_t idx) const override; 91 size_t GetWidthOfChar(size_t idx) override; 92 SetDelegate(Delegate * delegate)93 void SetDelegate(Delegate* delegate) { delegate_ = delegate; } 94 void Clear(); 95 96 void Insert(size_t idx, 97 const WideString& text, 98 RecordOperation add_operation = RecordOperation::kInsertRecord); 99 WideString Delete( 100 size_t start_idx, 101 size_t length, 102 RecordOperation add_operation = RecordOperation::kInsertRecord); 103 WideString GetText() const; 104 size_t GetLength() const; 105 106 // Non-const so we can force a layout. 107 CFX_RectF GetContentsBoundingBox(); 108 void SetAvailableWidth(size_t width); 109 110 void SetFont(RetainPtr<CFGAS_GEFont> font); 111 RetainPtr<CFGAS_GEFont> GetFont() const; 112 void SetFontSize(float size); GetFontSize()113 float GetFontSize() const { return font_size_; } SetFontColor(FX_ARGB color)114 void SetFontColor(FX_ARGB color) { font_color_ = color; } GetFontColor()115 FX_ARGB GetFontColor() const { return font_color_; } 116 117 void SetAlignment(uint32_t alignment); GetLineSpace()118 float GetLineSpace() const { return line_spacing_; } SetLineSpace(float space)119 void SetLineSpace(float space) { line_spacing_ = space; } SetAliasChar(wchar_t alias)120 void SetAliasChar(wchar_t alias) { password_alias_ = alias; } 121 void SetHasCharacterLimit(bool limit); 122 void SetCharacterLimit(size_t limit); 123 void SetCombText(bool enable); 124 void SetTabWidth(float width); 125 void SetVisibleLineCount(size_t lines); 126 EnableValidation(bool val)127 void EnableValidation(bool val) { validation_enabled_ = val; } EnablePasswordMode(bool val)128 void EnablePasswordMode(bool val) { password_mode_ = val; } 129 void EnableMultiLine(bool val); 130 void EnableLineWrap(bool val); 131 void LimitHorizontalScroll(bool val); 132 void LimitVerticalScroll(bool val); 133 134 bool CanUndo() const; 135 bool CanRedo() const; 136 bool Redo(); 137 bool Undo(); 138 void ClearOperationRecords(); 139 140 // This is not const it can trigger a |Layout|. 141 size_t GetIndexBefore(size_t pos); 142 size_t GetIndexLeft(size_t pos) const; 143 size_t GetIndexRight(size_t pos) const; 144 size_t GetIndexUp(size_t pos) const; 145 size_t GetIndexDown(size_t pos) const; 146 size_t GetIndexAtStartOfLine(size_t pos) const; 147 size_t GetIndexAtEndOfLine(size_t pos) const; 148 149 void SelectAll(); 150 void SetSelection(size_t start_idx, size_t count); 151 void ClearSelection(); HasSelection()152 bool HasSelection() const { return has_selection_; } 153 // Returns <start_idx, count> of the selection. GetSelection()154 std::pair<size_t, size_t> GetSelection() const { 155 return {selection_.start_idx, selection_.count}; 156 } 157 WideString GetSelectedText() const; 158 WideString DeleteSelectedText( 159 RecordOperation add_operation = RecordOperation::kInsertRecord); 160 void ReplaceSelectedText(const WideString& str); 161 162 void Layout(); 163 164 // Non-const so we can force a Layout() if needed. 165 size_t GetIndexForPoint(const CFX_PointF& point); 166 // <start_idx, count> 167 std::pair<size_t, size_t> BoundsForWordAt(size_t idx) const; 168 169 // Returns <bidi level, character rect> 170 std::pair<int32_t, CFX_RectF> GetCharacterInfo(int32_t start_idx); 171 std::vector<CFX_RectF> GetCharacterRectsInRange(int32_t start_idx, 172 int32_t count); 173 GetTextPieces()174 const std::vector<FDE_TEXTEDITPIECE>& GetTextPieces() { 175 // Force a layout if needed. 176 Layout(); 177 return text_piece_info_; 178 } 179 180 std::vector<TextCharPos> GetDisplayPos(const FDE_TEXTEDITPIECE& info); 181 182 void SetMaxEditOperationsForTesting(size_t max); 183 184 private: 185 void SetCombTextWidth(); 186 void AdjustGap(size_t idx, size_t length); 187 void RebuildPieces(); 188 size_t CountCharsExceedingSize(const WideString& str, size_t num_to_check); 189 void AddOperationRecord(std::unique_ptr<Operation> op); 190 IsAlignedRight()191 bool IsAlignedRight() const { 192 return !!(character_alignment_ & CFX_TxtLineAlignment_Left); 193 } 194 IsAlignedCenter()195 bool IsAlignedCenter() const { 196 return !!(character_alignment_ & CFX_TxtLineAlignment_Center); 197 } 198 std::vector<CFX_RectF> GetCharRects(const FDE_TEXTEDITPIECE& piece); 199 200 struct Selection { 201 size_t start_idx; 202 size_t count; 203 }; 204 205 CFX_RectF contents_bounding_box_; 206 UnownedPtr<Delegate> delegate_; 207 std::vector<FDE_TEXTEDITPIECE> text_piece_info_; 208 std::vector<size_t> char_widths_; 209 CFX_TxtBreak text_break_; 210 RetainPtr<CFGAS_GEFont> font_; 211 FX_ARGB font_color_; 212 float font_size_; 213 float line_spacing_; 214 std::vector<WideString::CharType> content_; 215 size_t text_length_; 216 217 // See e.g. https://en.wikipedia.org/wiki/Gap_buffer 218 size_t gap_position_; 219 size_t gap_size_; 220 221 size_t available_width_; 222 size_t character_limit_; 223 size_t visible_line_count_; 224 // Ring buffer of edit operations 225 std::vector<std::unique_ptr<Operation>> operation_buffer_; 226 // Next edit operation to undo. 227 size_t next_operation_index_to_undo_; 228 // Next index to insert an edit operation into. 229 size_t next_operation_index_to_insert_; 230 size_t max_edit_operations_; 231 uint32_t character_alignment_; 232 bool has_character_limit_; 233 bool is_comb_text_; 234 bool is_dirty_; 235 bool validation_enabled_; 236 bool is_multiline_; 237 bool is_linewrap_enabled_; 238 bool limit_horizontal_area_; 239 bool limit_vertical_area_; 240 bool password_mode_; 241 wchar_t password_alias_; 242 bool has_selection_; 243 Selection selection_; 244 }; 245 246 #endif // XFA_FDE_CFDE_TEXTEDITENGINE_H_ 247