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/cfx_renderdevice.h" 17 #include "core/fxge/fx_dib.h" 18 #include "xfa/fgas/layout/cfx_txtbreak.h" 19 20 class CFGAS_GEFont; 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 { 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 class Delegate { 65 public: 66 virtual ~Delegate() = default; 67 virtual void NotifyTextFull() = 0; 68 virtual void OnCaretChanged() = 0; 69 virtual void OnTextChanged(const WideString& prevText) = 0; 70 virtual void OnSelChanged() = 0; 71 virtual bool OnValidate(const WideString& wsText) = 0; 72 virtual void SetScrollOffset(float fScrollOffset) = 0; 73 }; 74 75 enum class RecordOperation { 76 kInsertRecord, 77 kSkipRecord, 78 }; 79 80 CFDE_TextEditEngine(); 81 ~CFDE_TextEditEngine(); 82 SetDelegate(Delegate * delegate)83 void SetDelegate(Delegate* delegate) { delegate_ = delegate; } 84 void Clear(); 85 86 void Insert(size_t idx, 87 const WideString& text, 88 RecordOperation add_operation = RecordOperation::kInsertRecord); 89 WideString Delete( 90 size_t start_idx, 91 size_t length, 92 RecordOperation add_operation = RecordOperation::kInsertRecord); 93 WideString GetText() const; 94 size_t GetLength() const; 95 96 // Non-const so we can force a layout. 97 CFX_RectF GetContentsBoundingBox(); 98 void SetAvailableWidth(size_t width); 99 100 void SetFont(RetainPtr<CFGAS_GEFont> font); 101 RetainPtr<CFGAS_GEFont> GetFont() const; 102 void SetFontSize(float size); GetFontSize()103 float GetFontSize() const { return font_size_; } SetFontColor(FX_ARGB color)104 void SetFontColor(FX_ARGB color) { font_color_ = color; } GetFontColor()105 FX_ARGB GetFontColor() const { return font_color_; } 106 float GetFontAscent() const; 107 108 void SetAlignment(uint32_t alignment); GetLineSpace()109 float GetLineSpace() const { return line_spacing_; } SetLineSpace(float space)110 void SetLineSpace(float space) { line_spacing_ = space; } SetAliasChar(wchar_t alias)111 void SetAliasChar(wchar_t alias) { password_alias_ = alias; } 112 void SetHasCharacterLimit(bool limit); 113 void SetCharacterLimit(size_t limit); 114 void SetCombText(bool enable); 115 void SetTabWidth(float width); 116 void SetVisibleLineCount(size_t lines); 117 EnableValidation(bool val)118 void EnableValidation(bool val) { validation_enabled_ = val; } EnablePasswordMode(bool val)119 void EnablePasswordMode(bool val) { password_mode_ = val; } 120 void EnableMultiLine(bool val); 121 void EnableLineWrap(bool val); 122 void LimitHorizontalScroll(bool val); 123 void LimitVerticalScroll(bool val); 124 125 bool CanUndo() const; 126 bool CanRedo() const; 127 bool Redo(); 128 bool Undo(); 129 void ClearOperationRecords(); 130 131 // This is not const it can trigger a |Layout|. 132 size_t GetIndexBefore(size_t pos); 133 size_t GetIndexLeft(size_t pos) const; 134 size_t GetIndexRight(size_t pos) const; 135 size_t GetIndexUp(size_t pos) const; 136 size_t GetIndexDown(size_t pos) const; 137 size_t GetIndexAtStartOfLine(size_t pos) const; 138 size_t GetIndexAtEndOfLine(size_t pos) const; 139 140 void SelectAll(); 141 void SetSelection(size_t start_idx, size_t count); 142 void ClearSelection(); HasSelection()143 bool HasSelection() const { return has_selection_; } 144 // Returns <start_idx, count> of the selection. GetSelection()145 std::pair<size_t, size_t> GetSelection() const { 146 return {selection_.start_idx, selection_.count}; 147 } 148 WideString GetSelectedText() const; 149 WideString DeleteSelectedText( 150 RecordOperation add_operation = RecordOperation::kInsertRecord); 151 void ReplaceSelectedText(const WideString& str); 152 153 void Layout(); 154 155 wchar_t GetChar(size_t idx) const; 156 // Non-const so we can force a Layout() if needed. 157 size_t GetWidthOfChar(size_t idx); 158 // Non-const so we can force a Layout() if needed. 159 size_t GetIndexForPoint(const CFX_PointF& point); 160 // <start_idx, count> 161 std::pair<size_t, size_t> BoundsForWordAt(size_t idx) const; 162 163 // Returns <bidi level, character rect> 164 std::pair<int32_t, CFX_RectF> GetCharacterInfo(int32_t start_idx); 165 std::vector<CFX_RectF> GetCharacterRectsInRange(int32_t start_idx, 166 int32_t count); 167 GetTextBreak()168 CFX_TxtBreak* GetTextBreak() { return &text_break_; } 169 GetTextPieces()170 const std::vector<FDE_TEXTEDITPIECE>& GetTextPieces() { 171 // Force a layout if needed. 172 Layout(); 173 return text_piece_info_; 174 } 175 176 std::vector<FXTEXT_CHARPOS> GetDisplayPos(const FDE_TEXTEDITPIECE& info); 177 178 void SetMaxEditOperationsForTesting(size_t max); 179 180 private: 181 void SetCombTextWidth(); 182 void AdjustGap(size_t idx, size_t length); 183 void RebuildPieces(); 184 size_t CountCharsExceedingSize(const WideString& str, size_t num_to_check); 185 void AddOperationRecord(std::unique_ptr<Operation> op); 186 IsAlignedRight()187 bool IsAlignedRight() const { 188 return !!(character_alignment_ & CFX_TxtLineAlignment_Left); 189 } 190 IsAlignedCenter()191 bool IsAlignedCenter() const { 192 return !!(character_alignment_ & CFX_TxtLineAlignment_Center); 193 } 194 std::vector<CFX_RectF> GetCharRects(const FDE_TEXTEDITPIECE& piece); 195 196 struct Selection { 197 size_t start_idx; 198 size_t count; 199 }; 200 201 CFX_RectF contents_bounding_box_; 202 UnownedPtr<Delegate> delegate_; 203 std::vector<FDE_TEXTEDITPIECE> text_piece_info_; 204 std::vector<size_t> char_widths_; 205 CFX_TxtBreak text_break_; 206 RetainPtr<CFGAS_GEFont> font_; 207 FX_ARGB font_color_; 208 float font_size_; 209 float line_spacing_; 210 std::vector<WideString::CharType> content_; 211 size_t text_length_; 212 size_t gap_position_; 213 size_t gap_size_; 214 size_t available_width_; 215 size_t character_limit_; 216 size_t visible_line_count_; 217 // Ring buffer of edit operations 218 std::vector<std::unique_ptr<Operation>> operation_buffer_; 219 // Next edit operation to undo. 220 size_t next_operation_index_to_undo_; 221 // Next index to insert an edit operation into. 222 size_t next_operation_index_to_insert_; 223 size_t max_edit_operations_; 224 uint32_t character_alignment_; 225 bool has_character_limit_; 226 bool is_comb_text_; 227 bool is_dirty_; 228 bool validation_enabled_; 229 bool is_multiline_; 230 bool is_linewrap_enabled_; 231 bool limit_horizontal_area_; 232 bool limit_vertical_area_; 233 bool password_mode_; 234 wchar_t password_alias_; 235 bool has_selection_; 236 Selection selection_; 237 }; 238 239 #endif // XFA_FDE_CFDE_TEXTEDITENGINE_H_ 240