7#include "xfa/fde/cfde_texteditengine.h"
12#include "core/fxcrt/fx_extension.h"
13#include "core/fxcrt/span_util.h"
14#include "core/fxge/text_char_pos.h"
15#include "third_party/base/check.h"
16#include "third_party/base/check_op.h"
17#include "third_party/base/numerics/safe_conversions.h"
18#include "xfa/fde/cfde_textout.h"
19#include "xfa/fde/cfde_wordbreak_data.h"
20#include "xfa/fgas/font/cfgas_gefont.h"
24class InsertOperation
final :
public CFDE_TextEditEngine::
Operation {
26 InsertOperation(CFDE_TextEditEngine* engine,
28 const WideString& added_text)
29 : engine_(engine), start_idx_(start_idx), added_text_(added_text) {}
31 ~InsertOperation()
override =
default;
33 void Redo()
const override {
34 engine_->Insert(start_idx_, added_text_,
35 CFDE_TextEditEngine::RecordOperation::kSkipRecord);
38 void Undo()
const override {
39 engine_->Delete(start_idx_, added_text_.GetLength(),
40 CFDE_TextEditEngine::RecordOperation::kSkipRecord);
46 WideString added_text_;
49class DeleteOperation
final :
public CFDE_TextEditEngine::
Operation {
51 DeleteOperation(CFDE_TextEditEngine* engine,
53 const WideString& removed_text)
54 : engine_(engine), start_idx_(start_idx), removed_text_(removed_text) {}
56 ~DeleteOperation()
override =
default;
58 void Redo()
const override {
59 engine_->Delete(start_idx_, removed_text_.GetLength(),
60 CFDE_TextEditEngine::RecordOperation::kSkipRecord);
63 void Undo()
const override {
64 engine_->Insert(start_idx_, removed_text_,
65 CFDE_TextEditEngine::RecordOperation::kSkipRecord);
71 WideString removed_text_;
74class ReplaceOperation
final :
public CFDE_TextEditEngine::
Operation {
76 ReplaceOperation(CFDE_TextEditEngine* engine,
78 const WideString& removed_text,
79 const WideString& added_text)
80 : insert_op_(engine, start_idx, added_text),
81 delete_op_(engine, start_idx, removed_text) {}
83 ~ReplaceOperation()
override =
default;
85 void Redo()
const override {
90 void Undo()
const override {
96 InsertOperation insert_op_;
97 DeleteOperation delete_op_;
124 content_.resize(gap_size_);
125 operation_buffer_.resize(max_edit_operations_);
127 text_break_.SetFontSize(font_size_);
128 text_break_.SetLineBreakTolerance(2.0f);
129 text_break_.SetTabWidth(36);
137 gap_size_ = kGapSize;
140 content_.resize(gap_size_);
147 max_edit_operations_ = max;
148 operation_buffer_.resize(max);
153void CFDE_TextEditEngine::AdjustGap(size_t idx, size_t length) {
154 static const size_t char_size =
sizeof(WideString::CharType);
157 if (idx < gap_position_) {
158 memmove(content_.data() + idx + gap_size_, content_.data() + idx,
159 (gap_position_ - idx) * char_size);
161 }
else if (idx > gap_position_) {
162 memmove(content_.data() + gap_position_,
163 content_.data() + gap_position_ + gap_size_,
164 (idx - gap_position_) * char_size);
169 if (length >= gap_size_) {
170 size_t new_gap_size = length + kGapSize;
171 content_.resize(text_length_ + new_gap_size);
173 memmove(content_.data() + gap_position_ + new_gap_size,
174 content_.data() + gap_position_ + gap_size_,
175 (text_length_ - gap_position_) * char_size);
177 gap_size_ = new_gap_size;
181size_t CFDE_TextEditEngine::CountCharsExceedingSize(
const WideString& text,
182 size_t num_to_check) {
183 if (!limit_horizontal_area_ && !limit_vertical_area_)
187 text_out->SetLineSpace(line_spacing_);
188 text_out->SetFont(font_);
189 text_out->SetFontSize(font_size_);
195 if (is_linewrap_enabled_) {
197 text_rect.width = available_width_;
199 text_rect
.width = kPageWidthMax;
201 text_out->SetStyles(style);
203 size_t length = text.GetLength();
204 WideStringView temp = text.AsStringView();
206 float vertical_height = line_spacing_ * visible_line_count_;
207 size_t chars_exceeding_size = 0;
209 for (size_t i = 0; i < num_to_check; i++) {
210 text_out->CalcLogicSize(temp, &text_rect);
211 if (limit_horizontal_area_ && text_rect.width <= available_width_)
213 if (limit_vertical_area_ && text_rect
.height <= vertical_height)
216 ++chars_exceeding_size;
219 temp = temp.First(length);
222 return chars_exceeding_size;
225void CFDE_TextEditEngine::
Insert(size_t idx,
226 const WideString& request_text,
228 WideString text = request_text;
232 idx = std::min(idx, text_length_);
235 change.selection_start = idx;
236 change.selection_end = idx;
241 if (delegate_ && (add_operation != RecordOperation::kSkipRecord &&
242 add_operation != RecordOperation::kSkipNotify)) {
243 delegate_->OnTextWillChange(&change);
248 idx = change.selection_start;
251 if (change.selection_end != change.selection_start)
255 idx = std::min(idx, text_length_);
258 size_t length = text.GetLength();
264 bool exceeded_limit =
false;
271 if (has_character_limit_ && text_length_ + length > character_limit_) {
274 character_limit_ = text_length_ + length;
277 CHECK(text_length_ <= character_limit_);
278 length = character_limit_ - text_length_;
279 exceeded_limit =
true;
282 AdjustGap(idx, length);
284 if (validation_enabled_ || limit_horizontal_area_ || limit_vertical_area_) {
286 if (gap_position_ > 0)
287 str += WideStringView(content_.data(), gap_position_);
291 if (text_length_ - gap_position_ > 0) {
292 str += WideStringView(content_.data() + gap_position_ + gap_size_,
293 text_length_ - gap_position_);
296 if (validation_enabled_ && delegate_ && !delegate_->OnValidate(str)) {
303 size_t chars_exceeding = CountCharsExceedingSize(str, length);
304 if (chars_exceeding > 0) {
306 if (chars_exceeding == length) {
308 delegate_->NotifyTextFull();
314 exceeded_limit =
true;
315 length -= chars_exceeding;
321 std::make_unique<InsertOperation>(
this, gap_position_, text));
324 WideString previous_text;
329 fxcrt::spancpy(pdfium::make_span(content_).subspan(gap_position_),
330 text.span().first(length));
331 gap_position_ += length;
333 text_length_ += length;
342 delegate_->NotifyTextFull();
344 delegate_->OnTextChanged();
348void CFDE_TextEditEngine::AddOperationRecord(std::unique_ptr<Operation> op) {
349 size_t last_insert_position = next_operation_index_to_insert_ == 0
350 ? max_edit_operations_ - 1
351 : next_operation_index_to_insert_ - 1;
356 if (next_operation_index_to_undo_ != last_insert_position) {
357 if (next_operation_index_to_undo_ > last_insert_position) {
360 while (last_insert_position != 0) {
361 operation_buffer_[last_insert_position].reset();
362 --last_insert_position;
364 operation_buffer_[0].reset();
368 last_insert_position = max_edit_operations_ - 1;
372 while (next_operation_index_to_undo_ != last_insert_position) {
373 operation_buffer_[last_insert_position].reset();
374 --last_insert_position;
380 ++last_insert_position;
381 if (last_insert_position >= max_edit_operations_)
382 last_insert_position = 0;
384 operation_buffer_[last_insert_position] = std::move(op);
385 next_operation_index_to_insert_ =
386 (last_insert_position + 1) % max_edit_operations_;
387 next_operation_index_to_undo_ = last_insert_position;
391 for (
auto& record : operation_buffer_)
394 next_operation_index_to_undo_ = max_edit_operations_ - 1;
395 next_operation_index_to_insert_ = 0;
405 wchar_t ch = GetChar(pos - 1);
406 if (ch !=
'\r' && ch !=
'\n')
415 if (pos >= text_length_)
419 wchar_t ch = GetChar(pos);
421 while (pos < text_length_ && (ch ==
'\r' || ch ==
'\n')) {
430 size_t line_start = GetIndexAtStartOfLine(pos);
435 size_t dist = pos - line_start;
441 ch = GetChar(line_start);
442 }
while (line_start != 0 && (ch ==
'\r' || ch ==
'\n'));
448 size_t prior_start = GetIndexAtStartOfLine(line_start);
452 if (prior_start + dist > line_start)
453 return GetIndexAtEndOfLine(line_start);
455 return prior_start + dist;
459 size_t line_end = GetIndexAtEndOfLine(pos);
460 if (line_end == text_length_)
466 ch = GetChar(line_end);
467 }
while (line_end < text_length_ && (ch ==
'\r' || ch ==
'\n'));
469 if (line_end == text_length_)
473 size_t dist = pos - GetIndexAtStartOfLine(pos);
477 size_t next_line_end = GetIndexAtEndOfLine(line_end);
478 if (line_end + dist > next_line_end)
479 return next_line_end;
481 return line_end + dist;
488 wchar_t ch = GetChar(pos);
490 if (ch ==
'\r' || ch ==
'\n')
495 ch = GetChar(pos - 1);
496 if (ch ==
'\r' || ch ==
'\n')
506 if (pos >= text_length_)
509 wchar_t ch = GetChar(pos);
511 if (ch ==
'\r' || ch ==
'\n')
518 }
while (pos < text_length_ && (ch !=
'\r' && ch !=
'\n'));
525 limit_horizontal_area_ = val;
530 limit_vertical_area_ = val;
534 return operation_buffer_[next_operation_index_to_undo_] !=
nullptr &&
535 next_operation_index_to_undo_ != next_operation_index_to_insert_;
539 size_t idx = (next_operation_index_to_undo_ + 1) % max_edit_operations_;
540 return idx != next_operation_index_to_insert_ &&
541 operation_buffer_[idx] !=
nullptr;
544bool CFDE_TextEditEngine::
Redo() {
548 next_operation_index_to_undo_ =
549 (next_operation_index_to_undo_ + 1) % max_edit_operations_;
550 operation_buffer_[next_operation_index_to_undo_]->Redo();
554bool CFDE_TextEditEngine::
Undo() {
558 operation_buffer_[next_operation_index_to_undo_]->Undo();
559 next_operation_index_to_undo_ = next_operation_index_to_undo_ == 0
560 ? max_edit_operations_ - 1
561 : next_operation_index_to_undo_ - 1;
576 return contents_bounding_box_;
580 if (width == available_width_)
585 available_width_ = width;
586 if (is_linewrap_enabled_)
587 text_break_.SetLineWidth(width);
595 if (has_character_limit_ == limit)
598 has_character_limit_ = limit;
599 character_limit_ = std::max(character_limit_, text_length_);
607 if (character_limit_ == limit)
612 character_limit_ = std::max(limit, text_length_);
623 font_ = std::move(font);
624 text_break_.SetFont(font_);
633 if (font_size_ == size)
637 text_break_.SetFontSize(font_size_);
642 int32_t old_tab_width = text_break_.GetTabWidth();
643 text_break_.SetTabWidth(width);
644 if (old_tab_width == text_break_.GetTabWidth())
651 if (alignment == character_alignment_)
654 character_alignment_ = alignment;
655 text_break_.SetAlignment(alignment);
660 if (visible_line_count_ == count)
663 visible_line_count_ = std::max(
static_cast<size_t>(1), count);
668 if (is_multiline_ == val)
678 text_break_.SetLayoutStyles(style);
683 if (is_linewrap_enabled_ == val)
686 is_linewrap_enabled_ = val;
687 text_break_.SetLineWidth(is_linewrap_enabled_ ? available_width_
693 if (is_comb_text_ == enable)
696 is_comb_text_ = enable;
705 text_break_.SetLayoutStyles(style);
709void CFDE_TextEditEngine::SetCombTextWidth() {
710 size_t width = available_width_;
711 if (has_character_limit_)
712 width /= character_limit_;
714 text_break_.SetCombWidth(width);
718 if (text_length_ == 0)
721 has_selection_ =
true;
722 selection_.start_idx = 0;
723 selection_.count = text_length_;
727 has_selection_ =
false;
728 selection_.start_idx = 0;
729 selection_.count = 0;
732void CFDE_TextEditEngine::
SetSelection(size_t start_idx, size_t count) {
738 if (start_idx > text_length_)
740 if (start_idx + count > text_length_)
741 count = text_length_ - start_idx;
743 has_selection_ =
true;
744 selection_.start_idx = start_idx;
745 selection_.count = count;
753 if (selection_.start_idx < gap_position_) {
755 if (selection_.start_idx + selection_.count < gap_position_) {
756 text += WideStringView(content_.data() + selection_.start_idx,
762 text += WideStringView(content_.data() + selection_.start_idx,
763 gap_position_ - selection_.start_idx);
765 if (selection_.count - (gap_position_ - selection_.start_idx) > 0) {
767 text += WideStringView(
768 content_.data() + gap_position_ + gap_size_,
769 selection_.count - (gap_position_ - selection_.start_idx));
776 text += WideStringView(content_.data() + gap_size_ + selection_.start_idx,
786 return Delete(selection_.start_idx, selection_.count, add_operation);
789WideString CFDE_TextEditEngine::
Delete(size_t start_idx,
792 if (start_idx >= text_length_)
798 if (delegate_ && (add_operation != RecordOperation::kSkipRecord &&
799 add_operation != RecordOperation::kSkipNotify)) {
801 change.selection_start = start_idx;
802 change.selection_end = start_idx + length;
804 delegate_->OnTextWillChange(&change);
809 start_idx = change.selection_start;
810 length = change.selection_end - change.selection_start;
813 if (start_idx >= text_length_)
817 length = std::min(length, text_length_ - start_idx);
818 AdjustGap(start_idx + length, 0);
821 ret += WideStringView(content_.data() + start_idx, length);
824 AddOperationRecord(std::make_unique<DeleteOperation>(
this, start_idx, ret));
829 gap_position_ = start_idx;
832 text_length_ -= length;
837 if (!change.text.IsEmpty())
838 Insert(start_idx, change.text, RecordOperation::kSkipRecord);
841 delegate_->OnTextChanged();
847 WideString rep = requested_rep;
851 change.selection_start = selection_.start_idx;
852 change.selection_end = selection_.start_idx + selection_.count;
857 delegate_->OnTextWillChange(&change);
862 selection_.start_idx = change.selection_start;
863 selection_.count = change.selection_end - change.selection_start;
866 size_t start_idx = selection_.start_idx;
868 Insert(gap_position_, rep, RecordOperation::kSkipRecord);
871 std::make_unique<ReplaceOperation>(
this, start_idx, txt, rep));
874WideString CFDE_TextEditEngine::
GetText()
const {
876 if (gap_position_ > 0)
877 str += WideStringView(content_.data(), gap_position_);
878 if (text_length_ - gap_position_ > 0) {
879 str += WideStringView(content_.data() + gap_position_ + gap_size_,
880 text_length_ - gap_position_);
889wchar_t CFDE_TextEditEngine::
GetChar(size_t idx)
const {
890 if (idx >= text_length_)
893 return password_alias_;
895 return idx < gap_position_
897 : content_[gap_position_ + gap_size_ + (idx - gap_position_)];
903 return idx < char_widths_.size() ? char_widths_[idx] : 0;
910 auto start_it = text_piece_info_.begin();
911 for (; start_it < text_piece_info_.end(); ++start_it) {
912 if (start_it->rtPiece.top <= point.y &&
913 point.y < start_it->rtPiece.bottom())
918 if (start_it == text_piece_info_.end())
921 auto end_it = start_it;
922 for (; end_it < text_piece_info_.end(); ++end_it) {
925 if (end_it->rtPiece.bottom() <= point.y || point.y < end_it->rtPiece.top)
929 if (end_it == text_piece_info_.end())
932 size_t start_it_idx = start_it->nStart;
933 for (; start_it <= end_it; ++start_it) {
934 bool piece_contains_point_vertically =
935 (point.y >= start_it->rtPiece.top &&
936 point.y < start_it->rtPiece.bottom());
937 if (!piece_contains_point_vertically)
940 std::vector<CFX_RectF> rects = GetCharRects(*start_it);
941 for (size_t i = 0; i < rects.size(); ++i) {
942 bool character_contains_point_horizontally =
943 (point.x >= rects[i].left && point.x < rects[i].right());
944 if (!character_contains_point_horizontally)
950 bool closer_to_left =
951 (point.x - rects[i].left < rects[i].right() - point.x);
952 size_t caret_pos = closer_to_left ? i : i + 1;
953 size_t pos = start_it->nStart + caret_pos;
954 if (pos >= text_length_)
957 wchar_t wch = GetChar(pos);
958 if (wch == L'\n' || wch == L'\r') {
959 if (wch == L'\n' && pos > 0 && GetChar(pos - 1) == L'\r')
972 size_t pos = std::min(
973 static_cast<size_t>(start_it->nStart + start_it->nCount), text_length_);
979 bool is_last_line = (std::next(start_it) == text_piece_info_.end());
980 if (!is_last_line && pos > 0) {
981 wchar_t previous_char = GetChar(pos - 1);
982 if (previous_char == L' ' || previous_char == L'\n' ||
983 previous_char == L'\r') {
991 if (start_it == text_piece_info_.end())
993 if (start_it == end_it)
994 return start_it->nStart;
998 return end_it->nStart;
1001std::vector<CFX_RectF> CFDE_TextEditEngine::GetCharRects(
1003 if (piece.nCount < 1)
1004 return std::vector<CFX_RectF>();
1006 CFGAS_TxtBreak::
Run tr;
1007 tr.pEdtEngine =
this;
1012 tr.dwStyles = text_break_.GetLayoutStyles();
1015 return text_break_.GetCharRects(tr);
1020 if (piece.nCount < 1)
1021 return std::vector<TextCharPos>();
1023 CFGAS_TxtBreak::
Run tr;
1024 tr.pEdtEngine =
this;
1029 tr.dwStyles = text_break_.GetLayoutStyles();
1033 std::vector<TextCharPos> data(text_break_.GetDisplayPos(tr,
nullptr));
1034 text_break_.GetDisplayPos(tr, data.data());
1038void CFDE_TextEditEngine::RebuildPieces() {
1039 text_break_.EndBreak(CFGAS_Char::BreakType::kParagraph);
1040 text_break_.ClearBreakPieces();
1042 char_widths_.clear();
1043 text_piece_info_.clear();
1049 bool initialized_bounding_box =
false;
1051 size_t current_piece_start = 0;
1052 float current_line_start = 0;
1059 password_mode_ ? password_alias_ : iter.GetChar());
1060 if (iter.IsEOF(
false) && CFX_BreakTypeNoneOrPiece(break_status))
1061 break_status = text_break_.EndBreak(CFGAS_Char::BreakType::kParagraph);
1065 int32_t piece_count = text_break_.CountBreakPieces();
1066 for (int32_t i = 0; i < piece_count; ++i) {
1075 pdfium::base::checked_cast<int32_t>(current_piece_start);
1082 text_piece_info_.push_back(txtEdtPiece);
1084 if (initialized_bounding_box) {
1087 contents_bounding_box_
= txtEdtPiece
.rtPiece;
1088 initialized_bounding_box =
true;
1091 current_piece_start += txtEdtPiece
.nCount;
1092 for (int32_t k = 0; k < txtEdtPiece.nCount; ++k)
1093 char_widths_.push_back(piece->GetChar(k)->m_iCharWidth);
1096 current_line_start += line_spacing_;
1097 text_break_.ClearBreakPieces();
1101 bool bounds_smaller = contents_bounding_box_.width < available_width_;
1102 if (IsAlignedRight() && bounds_smaller) {
1103 delta = available_width_ - contents_bounding_box_.width;
1104 }
else if (IsAlignedCenter() && bounds_smaller) {
1105 delta = (available_width_ - contents_bounding_box_.width) / 2.0f;
1109 float offset = delta - contents_bounding_box_
.left;
1110 for (
auto& info : text_piece_info_)
1111 info.rtPiece.Offset(offset, 0.0f);
1116 contents_bounding_box_
.height -= line_spacing_ - font_size_;
1117 text_piece_info_.back().rtPiece.height = font_size_;
1121 int32_t start_idx) {
1122 DCHECK(start_idx >= 0);
1123 DCHECK(
static_cast<size_t>(start_idx) <= text_length_);
1128 auto it = text_piece_info_.begin();
1129 for (; it != text_piece_info_.end(); ++it) {
1130 if (it->nStart <= start_idx && start_idx < it->nStart + it->nCount)
1133 CHECK_NE(it, text_piece_info_.end());
1134 return {it->nBidiLevel, GetCharRects(*it)[start_idx - it->nStart]};
1143 auto it = text_piece_info_.begin();
1144 for (; it != text_piece_info_.end(); ++it) {
1145 if (it->nStart <= start_idx && start_idx < it->nStart + it->nCount)
1148 if (it == text_piece_info_.end())
1149 return std::vector<CFX_RectF>();
1151 int32_t end_idx = start_idx + count - 1;
1152 std::vector<CFX_RectF> rects;
1153 while (it != text_piece_info_.end()) {
1155 if (it->nStart <= end_idx && end_idx < it->nStart + it->nCount) {
1156 std::vector<CFX_RectF> arr = GetCharRects(*it);
1158 piece.Union(arr[end_idx - it->nStart]);
1159 rects.push_back(piece);
1162 rects.push_back(it->rtPiece);
1171 if (idx > text_length_)
1177 size_t start_idx = iter.FindNextBreakPos(
true);
1178 size_t end_idx = iter.FindNextBreakPos(
false);
1179 return {start_idx, end_idx - start_idx + 1};
1188 if (bPrev && current_position_ == -1)
1190 if (!bPrev && current_position_ > -1 &&
1191 static_cast<size_t>(current_position_) == engine_->GetLength()) {
1196 --current_position_;
1198 ++current_position_;
1202 return engine_->GetChar(current_position_);
1206 nIndex = std::min(nIndex, engine_->GetLength());
1207 current_position_ = pdfium::base::checked_cast<int32_t>(nIndex);
1211 return bPrev ? current_position_ == -1
1212 : current_position_ > -1 &&
1213 static_cast<size_t>(current_position_) ==
1214 engine_->GetLength();
1219 return current_position_ > -1 ? current_position_ : 0;
1241 int32_t nFlags = GetBreakFlagsFor(eCurType, eNextType);
1243 if (BreakFlagsChanged(nFlags, ePreType)) {
1252 int32_t nFlags = GetBreakFlagsFor(eNextType, eCurType);
1260 if (BreakFlagsChanged(nFlags, eNextType)) {
1267 eCurType = eNextType;
1270 return current_position_ > -1 ? current_position_ : 0;
WordBreakProperty FX_GetWordBreakProperty(wchar_t wcCodePoint)
bool FX_CheckStateChangeForWordBreak(WordBreakProperty from, WordBreakProperty to)
#define FX_TXTCHARSTYLE_OddBidiLevel
bool CFX_BreakTypeNoneOrPiece(CFGAS_Char::BreakType type)
bool IsEOF(bool bPrev) const
Iterator(const CFDE_TextEditEngine *engine)
void SetAt(size_t nIndex)
size_t FindNextBreakPos(bool bPrev)
void SetAlignment(uint32_t alignment)
void SetCombText(bool enable)
size_t GetIndexAtStartOfLine(size_t pos) const
void Insert(size_t idx, const WideString &text, RecordOperation add_operation=RecordOperation::kInsertRecord)
std::pair< size_t, size_t > BoundsForWordAt(size_t idx) const
void SetAvailableWidth(size_t width)
WideString GetSelectedText() const
WideString GetText() const
size_t GetIndexAtEndOfLine(size_t pos) const
size_t GetIndexLeft(size_t pos) const
size_t GetIndexRight(size_t pos) const
WideString Delete(size_t start_idx, size_t length, RecordOperation add_operation=RecordOperation::kInsertRecord)
~CFDE_TextEditEngine() override
void ClearOperationRecords()
std::pair< int32_t, CFX_RectF > GetCharacterInfo(int32_t start_idx)
void SetVisibleLineCount(size_t lines)
void SetFontSize(float size)
size_t GetIndexDown(size_t pos) const
void LimitHorizontalScroll(bool val)
void EnableLineWrap(bool val)
size_t GetIndexForPoint(const CFX_PointF &point)
void SetSelection(size_t start_idx, size_t count)
void SetFont(RetainPtr< CFGAS_GEFont > font)
void LimitVerticalScroll(bool val)
void SetHasCharacterLimit(bool limit)
std::vector< CFX_RectF > GetCharacterRectsInRange(int32_t start_idx, int32_t count)
int32_t GetWidthOfChar(size_t idx) override
void EnableMultiLine(bool val)
bool CanGenerateCharacterInfo() const
std::vector< TextCharPos > GetDisplayPos(const FDE_TEXTEDITPIECE &info)
void SetCharacterLimit(size_t limit)
RetainPtr< CFGAS_GEFont > GetFont() const
wchar_t GetChar(size_t idx) const override
size_t GetIndexUp(size_t pos) const
void SetTabWidth(float width)
void SetMaxEditOperationsForTesting(size_t max)
void ReplaceSelectedText(const WideString &str)
WideString DeleteSelectedText(RecordOperation add_operation=RecordOperation::kInsertRecord)
CFX_RectF GetContentsBoundingBox()
int32_t GetCharCount() const
int32_t GetStartPos() const
uint32_t GetCharStyles() const
int32_t GetBidiLevel() const
void Offset(float dx, float dy)
constexpr CFX_RectF()=default
CFX_RectF & operator=(const CFX_RectF &other)=default
void Union(const CFX_RectF &rt)
WideString & operator+=(const WideString &str)
WideString & operator=(WideString &&that) noexcept